diff options
| author | Keith M Wesolowski <wesolows@foobazco.org> | 2013-02-20 23:46:02 +0000 |
|---|---|---|
| committer | Keith M Wesolowski <wesolows@foobazco.org> | 2013-03-05 00:43:42 +0000 |
| commit | df8e9ae2b126b7dc626ed694e6b79e0e941149e4 (patch) | |
| tree | 976c62ef466965137d5bd08cf84d292e789b440f /usr/src | |
| parent | 402014fd6398e9ae37720d84cc57bb9608969209 (diff) | |
| download | illumos-joyent-df8e9ae2b126b7dc626ed694e6b79e0e941149e4.tar.gz | |
OS-1910 want grub support for cross-menu OS console variable
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/Makefile.solaris | 54 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/asm.S | 3 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/builtins.c | 468 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/common.c | 3 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/cpu.h | 7 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/expand.c | 463 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/expand.h | 31 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/shared.h | 4 | ||||
| -rw-r--r-- | usr/src/grub/grub-0.97/stage2/stage2.c | 10 |
9 files changed, 604 insertions, 439 deletions
diff --git a/usr/src/grub/grub-0.97/stage2/Makefile.solaris b/usr/src/grub/grub-0.97/stage2/Makefile.solaris index 94b168f43d..bb737888cd 100644 --- a/usr/src/grub/grub-0.97/stage2/Makefile.solaris +++ b/usr/src/grub/grub-0.97/stage2/Makefile.solaris @@ -65,6 +65,7 @@ LIBGRUB_OBJS = libgrub_a-boot.o \ libgrub_a-cmdline.o \ libgrub_a-common.o \ libgrub_a-disk_io.o \ + libgrub_a-expand.o \ libgrub_a-fsys_ext2fs.o \ libgrub_a-fsys_fat.o \ libgrub_a-fsys_ffs.o \ @@ -155,6 +156,7 @@ DISKLESS_OBJS = diskless_exec-bios.o \ diskless_exec-common.o \ diskless_exec-console.o \ diskless_exec-disk_io.o \ + diskless_exec-expand.o \ diskless_exec-fsys_ext2fs.o \ diskless_exec-fsys_fat.o \ diskless_exec-fsys_ffs.o \ @@ -198,8 +200,8 @@ $(DISKLESS_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE2_CFLAGS) \ E2FS_STAGE1_5_DATA = e2fs_stage1_5 E2FS_STAGE1_5_EXEC = e2fs_stage1_5.exec -E2FS_STAGE1_5_ASMOBJS = e2fs_stage1_5_exec-asm.o \ - e2fs_stage1_5_exec-start.o +E2FS_STAGE1_5_ASMOBJS = e2fs_stage1_5_exec-start.o \ + e2fs_stage1_5_exec-asm.o E2FS_STAGE1_5_OBJS = e2fs_stage1_5_exec-bios.o \ e2fs_stage1_5_exec-char_io.o \ @@ -222,8 +224,8 @@ $(E2FS_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ FAT_STAGE1_5_DATA = fat_stage1_5 FAT_STAGE1_5_EXEC = fat_stage1_5.exec -FAT_STAGE1_5_ASMOBJS = fat_stage1_5_exec-asm.o \ - fat_stage1_5_exec-start.o +FAT_STAGE1_5_ASMOBJS = fat_stage1_5_exec-start.o \ + fat_stage1_5_exec-asm.o FAT_STAGE1_5_OBJS = fat_stage1_5_exec-bios.o \ fat_stage1_5_exec-char_io.o \ @@ -246,8 +248,8 @@ $(FAT_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ FFS_STAGE1_5_DATA = ffs_stage1_5 FFS_STAGE1_5_EXEC = ffs_stage1_5.exec -FFS_STAGE1_5_ASMOBJS = ffs_stage1_5_exec-asm.o \ - ffs_stage1_5_exec-start.o +FFS_STAGE1_5_ASMOBJS = ffs_stage1_5_exec-start.o \ + ffs_stage1_5_exec-asm.o FFS_STAGE1_5_OBJS = ffs_stage1_5_exec-bios.o \ ffs_stage1_5_exec-char_io.o \ @@ -270,8 +272,8 @@ $(FFS_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ ISO9660_STAGE1_5_DATA = iso9660_stage1_5 ISO9660_STAGE1_5_EXEC = iso9660_stage1_5.exec -ISO9660_STAGE1_5_ASMOBJS = iso9660_stage1_5_exec-asm.o \ - iso9660_stage1_5_exec-start_eltorito.o +ISO9660_STAGE1_5_ASMOBJS = iso9660_stage1_5_exec-start_eltorito.o \ + iso9660_stage1_5_exec-asm.o ISO9660_STAGE1_5_OBJS = iso9660_stage1_5_exec-bios.o \ iso9660_stage1_5_exec-char_io.o \ @@ -295,8 +297,8 @@ $(ISO9660_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ JFS_STAGE1_5_DATA = jfs_stage1_5 JFS_STAGE1_5_EXEC = jfs_stage1_5.exec -JFS_STAGE1_5_ASMOBJS = jfs_stage1_5_exec-asm.o \ - jfs_stage1_5_exec-start.o +JFS_STAGE1_5_ASMOBJS = jfs_stage1_5_exec-start.o \ + jfs_stage1_5_exec-asm.o JFS_STAGE1_5_OBJS = jfs_stage1_5_exec-bios.o \ jfs_stage1_5_exec-char_io.o \ @@ -319,8 +321,8 @@ $(JFS_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ MINIX_STAGE1_5_DATA = minix_stage1_5 MINIX_STAGE1_5_EXEC = minix_stage1_5.exec -MINIX_STAGE1_5_ASMOBJS = minix_stage1_5_exec-asm.o \ - minix_stage1_5_exec-start.o +MINIX_STAGE1_5_ASMOBJS = minix_stage1_5_exec-start.o \ + minix_stage1_5_exec-asm.o MINIX_STAGE1_5_OBJS = minix_stage1_5_exec-bios.o \ minix_stage1_5_exec-char_io.o \ @@ -367,6 +369,7 @@ PRE_STAGE2_OBJS = pre_stage2_exec-bios.o \ pre_stage2_exec-common.o \ pre_stage2_exec-console.o \ pre_stage2_exec-disk_io.o \ + pre_stage2_exec-expand.o \ pre_stage2_exec-fsys_ext2fs.o \ pre_stage2_exec-fsys_fat.o \ pre_stage2_exec-fsys_ffs.o \ @@ -423,8 +426,8 @@ $(PXELOADER_ASMOBJS) := CCASFLAGS = $(BASE_CCASFLAGS) $(STAGE2_CFLAGS) REISERFS_STAGE1_5_DATA = reiserfs_stage1_5 REISERFS_STAGE1_5_EXEC = reiserfs_stage1_5.exec -REISERFS_STAGE1_5_ASMOBJS = reiserfs_stage1_5_exec-asm.o \ - reiserfs_stage1_5_exec-start.o +REISERFS_STAGE1_5_ASMOBJS = reiserfs_stage1_5_exec-start.o \ + reiserfs_stage1_5_exec-asm.o REISERFS_STAGE1_5_OBJS = reiserfs_stage1_5_exec-bios.o \ reiserfs_stage1_5_exec-char_io.o \ @@ -478,8 +481,8 @@ $(START_ELTORITO_ASMOBJS) := CCASFLAGS = $(BASE_CCASFLAGS) $(STAGE2_CFLAGS) UFS2_STAGE1_5_DATA = ufs2_stage1_5 UFS2_STAGE1_5_EXEC = ufs2_stage1_5.exec -UFS2_STAGE1_5_ASMOBJS = ufs2_stage1_5_exec-asm.o \ - ufs2_stage1_5_exec-start.o +UFS2_STAGE1_5_ASMOBJS = ufs2_stage1_5_exec-start.o \ + ufs2_stage1_5_exec-asm.o UFS2_STAGE1_5_OBJS = ufs2_stage1_5_exec-bios.o \ ufs2_stage1_5_exec-char_io.o \ @@ -502,8 +505,8 @@ $(UFS2_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ UFS_STAGE1_5_DATA = ufs_stage1_5 UFS_STAGE1_5_EXEC = ufs_stage1_5.exec -UFS_STAGE1_5_ASMOBJS = ufs_stage1_5_exec-asm.o \ - ufs_stage1_5_exec-start.o +UFS_STAGE1_5_ASMOBJS = ufs_stage1_5_exec-start.o \ + ufs_stage1_5_exec-asm.o UFS_STAGE1_5_OBJS = ufs_stage1_5_exec-bios.o \ ufs_stage1_5_exec-char_io.o \ @@ -526,8 +529,8 @@ $(UFS_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ ZFS_STAGE1_5_DATA = zfs_stage1_5 ZFS_STAGE1_5_EXEC = zfs_stage1_5.exec -ZFS_STAGE1_5_ASMOBJS = zfs_stage1_5_exec-asm.o \ - zfs_stage1_5_exec-start.o +ZFS_STAGE1_5_ASMOBJS = zfs_stage1_5_exec-start.o \ + zfs_stage1_5_exec-asm.o ZFS_STAGE1_5_OBJS = zfs_stage1_5_exec-bios.o \ zfs_stage1_5_exec-char_io.o \ @@ -554,8 +557,8 @@ $(ZFS_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ VSTAFS_STAGE1_5_DATA = vstafs_stage1_5 VSTAFS_STAGE1_5_EXEC = vstafs_stage1_5.exec -VSTAFS_STAGE1_5_ASMOBJS = vstafs_stage1_5_exec-asm.o \ - vstafs_stage1_5_exec-start.o +VSTAFS_STAGE1_5_ASMOBJS = vstafs_stage1_5_exec-start.o \ + vstafs_stage1_5_exec-asm.o VSTAFS_STAGE1_5_OBJS = vstafs_stage1_5_exec-bios.o \ vstafs_stage1_5_exec-char_io.o \ @@ -578,8 +581,8 @@ $(VSTAFS_STAGE1_5_OBJS) := CFLAGS = $(BASE_CFLAGS) $(STAGE1_5_CFLAGS) \ XFS_STAGE1_5_DATA = xfs_stage1_5 XFS_STAGE1_5_EXEC = xfs_stage1_5.exec -XFS_STAGE1_5_ASMOBJS = xfs_stage1_5_exec-asm.o \ - xfs_stage1_5_exec-start.o +XFS_STAGE1_5_ASMOBJS = xfs_stage1_5_exec-start.o \ + xfs_stage1_5_exec-asm.o XFS_STAGE1_5_OBJS = xfs_stage1_5_exec-bios.o \ xfs_stage1_5_exec-char_io.o \ @@ -607,7 +610,8 @@ SRC_DIR = $(ROOT_SRC)/stage2 SRC_ZFSINC_DIR = $(SRC_DIR)/zfs-include SRC_FILES = Makefile.am Makefile.in apic.h apm.S asm.S bios.c boot.c \ builtins.c char_io.c cmdline.c common.c console.c defs.h \ - dir.h disk_inode.h disk_inode_ffs.h disk_io.c fat.h \ + dir.h disk_inode.h disk_inode_ffs.h disk_io.c expand.c \ + expand.h fat.h \ filesys.h freebsd.h fs.h fsys_ext2fs.c fsys_fat.c \ fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \ zfs_sha256.c zfs_lzjb.c zfs_lz4.c zfs_fletcher.c fsys_zfs.c \ diff --git a/usr/src/grub/grub-0.97/stage2/asm.S b/usr/src/grub/grub-0.97/stage2/asm.S index 3e9986c0df..5d6faf7010 100644 --- a/usr/src/grub/grub-0.97/stage2/asm.S +++ b/usr/src/grub/grub-0.97/stage2/asm.S @@ -2664,8 +2664,8 @@ ENTRY(get_target_operating_mode) movw $0xec00, %ax movw $0x03, %bx int $0x15 -/* XXX still need to pass back return */ + setc %al movw %ax, %cx DATA32 call EXT_C(real_to_prot) @@ -2673,6 +2673,7 @@ ENTRY(get_target_operating_mode) xorl %eax, %eax movw %cx, %ax + movl %eax, 0x1c(%esp) popa ret diff --git a/usr/src/grub/grub-0.97/stage2/builtins.c b/usr/src/grub/grub-0.97/stage2/builtins.c index e1022da156..5294ded9c7 100644 --- a/usr/src/grub/grub-0.97/stage2/builtins.c +++ b/usr/src/grub/grub-0.97/stage2/builtins.c @@ -49,6 +49,7 @@ #endif #include <cpu.h> +#include <expand.h> /* The type of kernel loaded. */ kernel_t kernel_type; @@ -86,7 +87,7 @@ static int configfile_func (char *arg, int flags); static void solaris_config_file (void); #endif -static unsigned int min_mem64 = 0; +unsigned int min_mem64 = 0; #if defined(__sun) && !defined(GRUB_UTIL) extern void __enable_execute_stack (void *); @@ -2791,117 +2792,6 @@ static struct builtin builtin_ioprobe = }; -/* - * To boot from a ZFS root filesystem, the kernel$ or module$ commands - * must include "-B $ZFS-BOOTFS" to expand to the zfs-bootfs, bootpath, - * and diskdevid boot property values for passing to the kernel: - * - * e.g. - * kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS,console=ttya - * - * $ZFS-BOOTFS is expanded to - * - * zfs-bootfs=<rootpool-name/zfs-rootfilesystem-object-num>, - * bootpath=<device phys path>, - * diskdevid=<device id> - * - * if both bootpath and diskdevid can be found. - * e.g - * zfs-bootfs=rpool/85, - * bootpath="/pci@0,0/pci1022,7450@a/pci17c2,10@4/sd@0,0:a", - * diskdevid="id1,sd@SSEAGATE_ST336607LC______3JA0LNHE0000741326W6/a" - */ -static int -expand_dollar_bootfs(char *in, char *out) -{ - char *token, *tmpout = out; - int outlen, blen; - int postcomma = 0; - - /* no op if this is not zfs */ - if (is_zfs_mount == 0) - return (0); - - if (current_bootpath[0] == '\0' && current_devid[0] == '\0') { - errnum = ERR_NO_BOOTPATH; - return (1); - } - - outlen = strlen(in); - blen = current_bootfs_obj == 0 ? strlen(current_rootpool) : - strlen(current_rootpool) + 11; - - out[0] = '\0'; - while (token = strstr(in, "$ZFS-BOOTFS")) { - - if ((outlen += blen) >= MAX_CMDLINE) { - errnum = ERR_WONT_FIT; - return (1); - } - - token[0] = '\0'; - grub_sprintf(tmpout, "%s", in); - token[0] = '$'; - in = token + 11; /* skip over $ZFS-BOOTFS */ - tmpout = out + strlen(out); - - /* Note: %u only fits 32 bit integer; */ - if (current_bootfs_obj > 0) - grub_sprintf(tmpout, "zfs-bootfs=%s/%u", - current_rootpool, current_bootfs_obj); - else - grub_sprintf(tmpout, "zfs-bootfs=%s", - current_rootpool); - tmpout = out + strlen(out); - } - - /* - * Check to see if 'zfs-bootfs' was explicitly specified on the command - * line so that we can insert the 'bootpath' property. - */ - if ((tmpout == out) && (token = strstr(in, "zfs-bootfs")) != NULL) { - token[0] = '\0'; - grub_strcpy(tmpout, in); - token[0] = 'z'; - in = token; - - tmpout = out + strlen(out); - postcomma = 1; - } - - /* - * Set the 'bootpath' property if a ZFS dataset was specified, either - * through '$ZFS-BOOTFS' or an explicit 'zfs-bootfs' setting. - */ - if (tmpout != out) { - if (current_bootpath[0] != '\0') { - if ((outlen += 12 + strlen(current_bootpath)) - >= MAX_CMDLINE) { - errnum = ERR_WONT_FIT; - return (1); - } - grub_sprintf(tmpout, - postcomma ? "bootpath=\"%s\"," : ",bootpath=\"%s\"", - current_bootpath); - tmpout = out + strlen(out); - } - - if (current_devid[0] != '\0') { - if ((outlen += 13 + strlen(current_devid)) - >= MAX_CMDLINE) { - errnum = ERR_WONT_FIT; - return (1); - } - grub_sprintf(tmpout, - postcomma ? "diskdevid=\"%s\"," : ",diskdevid=\"%s\"", - current_devid); - } - } - - strncat(out, in, MAX_CMDLINE); - return (0); -} - /* kernel */ static int kernel_func (char *arg, int flags) @@ -3007,289 +2897,17 @@ static struct builtin builtin_min_mem64 = "even on 64-bit capable hardware." }; -int -check_min_mem64() -{ - if (min_mem64 == 0) - return (1); - - if ((mbi.mem_upper / 10240) * 11 >= min_mem64) - return (1); - - return (0); -} - -static int detect_target_operating_mode(); - -int -amd64_config_cpu(void) -{ - struct amd64_cpuid_regs __vcr, *vcr = &__vcr; - uint32_t maxeax; - uint32_t max_maxeax = 0x100; - char vendor[13]; - int isamd64 = 0; - uint32_t stdfeatures = 0, xtdfeatures = 0; - uint64_t efer; - - /* - * This check may seem silly, but if the C preprocesor symbol __amd64 - * is #defined during compilation, something that may outwardly seem - * like a good idea, uts/common/sys/isa_defs.h will #define _LP64, - * which will cause uts/common/sys/int_types.h to typedef uint64_t as - * an unsigned long - which is only 4 bytes in size when using a 32-bit - * compiler. - * - * If that happens, all the page table translation routines will fail - * horribly, so check the size of uint64_t just to insure some degree - * of sanity in future operations. - */ - /*LINTED [sizeof result is invarient]*/ - if (sizeof (uint64_t) != 8) - prom_panic("grub compiled improperly, unable to boot " - "64-bit AMD64 executables"); - - /* - * If the CPU doesn't support the CPUID instruction, it's definitely - * not an AMD64. - */ - if (amd64_cpuid_supported() == 0) - return (0); - - amd64_cpuid_insn(0, vcr); - - maxeax = vcr->r_eax; - { - /*LINTED [vendor string from cpuid data]*/ - uint32_t *iptr = (uint32_t *)vendor; - - *iptr++ = vcr->r_ebx; - *iptr++ = vcr->r_edx; - *iptr++ = vcr->r_ecx; - - vendor[12] = '\0'; - } - - if (maxeax > max_maxeax) { - grub_printf("cpu: warning, maxeax was 0x%x -> 0x%x\n", - maxeax, max_maxeax); - maxeax = max_maxeax; - } - - if (maxeax < 1) - return (0); /* no additional functions, not an AMD64 */ - else { - uint_t family, model, step; - - amd64_cpuid_insn(1, vcr); - - /* - * All AMD64/IA32e processors technically SHOULD report - * themselves as being in family 0xf, but for some reason - * Simics doesn't, and this may change in the future, so - * don't error out if it's not true. - */ - if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf) - family += BITX(vcr->r_eax, 27, 20); - - if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf) - model += BITX(vcr->r_eax, 19, 16) << 4; - step = BITX(vcr->r_eax, 3, 0); - - grub_printf("cpu: '%s' family %d model %d step %d\n", - vendor, family, model, step); - stdfeatures = vcr->r_edx; - } - - amd64_cpuid_insn(0x80000000, vcr); - - if (vcr->r_eax & 0x80000000) { - uint32_t xmaxeax = vcr->r_eax; - const uint32_t max_xmaxeax = 0x80000100; - - if (xmaxeax > max_xmaxeax) { - grub_printf("amd64: warning, xmaxeax was " - "0x%x -> 0x%x\n", xmaxeax, max_xmaxeax); - xmaxeax = max_xmaxeax; - } - - if (xmaxeax >= 0x80000001) { - amd64_cpuid_insn(0x80000001, vcr); - xtdfeatures = vcr->r_edx; - } - } - - if (BITX(xtdfeatures, 29, 29)) /* long mode */ - isamd64++; - else - grub_printf("amd64: CPU does NOT support long mode\n"); - - if (!BITX(stdfeatures, 0, 0)) { - grub_printf("amd64: CPU does NOT support FPU\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 4, 4)) { - grub_printf("amd64: CPU does NOT support TSC\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 5, 5)) { - grub_printf("amd64: CPU does NOT support MSRs\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 6, 6)) { - grub_printf("amd64: CPU does NOT support PAE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 8, 8)) { - grub_printf("amd64: CPU does NOT support CX8\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 13, 13)) { - grub_printf("amd64: CPU does NOT support PGE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 19, 19)) { - grub_printf("amd64: CPU does NOT support CLFSH\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 23, 23)) { - grub_printf("amd64: CPU does NOT support MMX\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 24, 24)) { - grub_printf("amd64: CPU does NOT support FXSR\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 25, 25)) { - grub_printf("amd64: CPU does NOT support SSE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 26, 26)) { - grub_printf("amd64: CPU does NOT support SSE2\n"); - isamd64--; - } - - if (isamd64 < 1) { - grub_printf("amd64: CPU does not support amd64 executables.\n"); - return (0); - } - - amd64_rdmsr(MSR_AMD_EFER, &efer); - if (efer & AMD_EFER_SCE) - grub_printf("amd64: EFER_SCE (syscall/sysret) already " - "enabled\n"); - if (efer & AMD_EFER_NXE) - grub_printf("amd64: EFER_NXE (no-exec prot) already enabled\n"); - if (efer & AMD_EFER_LME) - grub_printf("amd64: EFER_LME (long mode) already enabled\n"); - - return (detect_target_operating_mode()); -} - -static int -detect_target_operating_mode() -{ - int ret, ah; - - ah = get_target_operating_mode(); - - ah = ah >> 8; - - /* XXX still need to pass back the return from the call */ - ret = 0; - - if (ah == 0x86 && (ret & CB) != 0) { - grub_printf("[BIOS 'Detect Target Operating Mode' " - "callback unsupported on this platform]\n"); - return (1); /* unsupported, ignore */ - } - - if (ah == 0x0 && (ret & CB) == 0) { - grub_printf("[BIOS accepted mixed-mode target setting!]\n"); - return (1); /* told the bios what we're up to */ - } - - if (ah == 0 && ret & CB) { - grub_printf("fatal: BIOS reports this machine CANNOT run in " - "mixed 32/64-bit mode!\n"); - return (0); - } - - grub_printf("warning: BIOS Detect Target Operating Mode callback " - "confused.\n %%ax >> 8 = 0x%x, carry = %d\n", ah, - ret & CB ? 1 : 0); - - return (1); -} - - -int -isamd64() -{ - static int ret = -1; - - if (ret == -1) - ret = amd64_config_cpu(); - - return (ret); -} - -static void -expand_arch (char *arg, char *newarg) -{ - char *index; - - newarg[0] = '\0'; - - while ((index = strstr(arg, "$ISADIR")) != NULL) { - - index[0] = '\0'; - strncat(newarg, arg, MAX_CMDLINE); - index[0] = '$'; - - if (isamd64() && check_min_mem64()) - strncat(newarg, "amd64", MAX_CMDLINE); - - arg = index + 7; - } - - strncat(newarg, arg, MAX_CMDLINE); - return; -} - -/* kernel$ */ static int kernel_dollar_func (char *arg, int flags) { char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ grub_printf("loading '%s' ...\n", arg); - expand_arch(arg, newarg); - - if (kernel_func(newarg, flags)) - return (1); + expand_string(arg, newarg, MAX_CMDLINE); - mb_cmdline = (char *)MB_CMDLINE_BUF; - if (expand_dollar_bootfs(newarg, mb_cmdline)) { - grub_printf("cannot expand $ZFS-BOOTFS for dataset %s\n", - current_bootfs); - return (1); - } + grub_printf("loading '%s' ...\n", newarg); - grub_printf("'%s' is loaded\n", mb_cmdline); - mb_cmdline += grub_strlen(mb_cmdline) + 1; - - return (0); + return (kernel_func(newarg, flags)); } static struct builtin builtin_kernel_dollar = @@ -3298,7 +2916,8 @@ static struct builtin builtin_kernel_dollar = kernel_dollar_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "kernel$ [--no-mem-option] [--type=TYPE] FILE [ARG ...]", - " Just like kernel, but with $ISADIR expansion." + " Just like kernel, but with variable expansion, including the legacy" + " (and nonconforming) variables $ISADIR and $ZFS-BOOTFS." }; @@ -3521,26 +3140,14 @@ static struct builtin builtin_module = static int module_dollar_func (char *arg, int flags) { - char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ - char *cmdline_sav; + char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ + char *cmdline_sav; - grub_printf("loading '%s' ...\n", arg); - expand_arch(arg, newarg); - - cmdline_sav = (char *)mb_cmdline; - if (module_func(newarg, flags)) - return (1); + grub_printf("loading '%s' ...\n", arg); + expand_string(arg, newarg, MAX_CMDLINE); + grub_printf("loading '%s' ...\n", newarg); - if (expand_dollar_bootfs(newarg, cmdline_sav)) { - grub_printf("cannot expand $ZFS-BOOTFS for dataset %s\n", - current_bootfs); - return (1); - } - - grub_printf("'%s' is loaded\n", (char *)cmdline_sav); - mb_cmdline += grub_strlen(cmdline_sav) + 1; - - return (0); + return (module_func(newarg, flags)); } static struct builtin builtin_module_dollar = @@ -5818,6 +5425,54 @@ static struct builtin builtin_vbeprobe = "Probe VBE information. If the mode number MODE is specified, show only" " the information about only the mode." }; + +static int +variable_func(char *arg, int flags) +{ + char name[EV_NAMELEN]; + char *val; + int err; + + if (*arg == '\0') { + dump_variables(); + return (0); + } + + if ((val = grub_strchr(arg, ' ')) != NULL) { + if (val - arg >= sizeof (name)) { + errnum = ERR_WONT_FIT; + return (1); + } + (void) grub_memcpy(name, arg, (val - arg)); + name[val - arg] = '\0'; + val = skip_to(0, arg); + } else { + if (grub_strlen(arg) >= sizeof (name)) { + errnum = ERR_WONT_FIT; + return (1); + } + (void) grub_strcpy(name, arg); + } + + if ((err = set_variable(name, val)) != 0) { + errnum = err; + return (1); + } + + return (0); +} + +static struct builtin builtin_variable = +{ + "variable", + variable_func, + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, + "variable NAME [VALUE]", + "Set the variable NAME to VALUE, or to the empty string if no value is" + " given. NAME must contain no spaces. There is no quoting mechanism" + " and nested variable references are not allowed. Variable values may" + " be substituted into the kernel$ and module$ commands using ${NAME}." +}; /* The table of builtin commands. Sorted in dictionary order. */ @@ -5925,6 +5580,7 @@ struct builtin *builtin_table[] = &builtin_title, &builtin_unhide, &builtin_uppermem, + &builtin_variable, &builtin_vbeprobe, &builtin_verbose, 0 diff --git a/usr/src/grub/grub-0.97/stage2/common.c b/usr/src/grub/grub-0.97/stage2/common.c index b4bb696641..3ca5340206 100644 --- a/usr/src/grub/grub-0.97/stage2/common.c +++ b/usr/src/grub/grub-0.97/stage2/common.c @@ -99,7 +99,8 @@ char *err_list[] = [ERR_NEWER_VERSION] = "Newer on-disk pool version", [ERR_NOTXPM] = "Image not in XPM graphics format", [ERR_TOOMANYCOLORS] = "Image cannot use more than 14 colors", - [ERR_CORRUPTXPM] = "File contains corrupt XPM image data" + [ERR_CORRUPTXPM] = "File contains corrupt XPM image data", + [ERR_NOVAR] = "Unknown variable reference", }; diff --git a/usr/src/grub/grub-0.97/stage2/cpu.h b/usr/src/grub/grub-0.97/stage2/cpu.h index 34180727d9..ad2948978f 100644 --- a/usr/src/grub/grub-0.97/stage2/cpu.h +++ b/usr/src/grub/grub-0.97/stage2/cpu.h @@ -30,6 +30,8 @@ extern "C" { #endif +#include <shared.h> + typedef unsigned int uint_t; typedef unsigned long ulong_t; @@ -37,11 +39,6 @@ typedef unsigned long ulong_t; #include <controlregs.h> -#define CB 0x0001 - -extern void amd64_flush_tlb(void); -extern void amd64_flush_tlbentry(caddr_t); - extern ulong_t amd64_get_cr2(void); extern ulong_t amd64_get_cr0(void); extern ulong_t amd64_get_cr3(void); diff --git a/usr/src/grub/grub-0.97/stage2/expand.c b/usr/src/grub/grub-0.97/stage2/expand.c new file mode 100644 index 0000000000..6a83d0b1b6 --- /dev/null +++ b/usr/src/grub/grub-0.97/stage2/expand.c @@ -0,0 +1,463 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. + * Copyright (c) 2013 Joyent, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <expand.h> +#include <shared.h> + +#ifdef SUPPORT_NETBOOT +#include <grub.h> +#endif + +#include <cpu.h> + +#define EVF_DEFINED 0x01 +#define EVF_VALUESET 0x02 + +typedef struct variable { + char v_name[EV_NAMELEN]; + unsigned int v_flags; + char v_value[220]; /* 256 - EV_NAMELEN - sizeof (fields) */ +} variable_t; + +static variable_t expvars[32]; +static const unsigned int nexpvars = 32; + +int +set_variable(const char *name, const char *value) +{ + unsigned int i; + unsigned int avail = nexpvars; + + if (strlen(name) >= sizeof (expvars[0].v_name)) + return (ERR_WONT_FIT); + + if (value != NULL && strlen(value) >= sizeof (expvars[0].v_value)) + return (ERR_WONT_FIT); + + for (i = 0; i < nexpvars; i++) { + if (expvars[i].v_flags & EVF_DEFINED) { + if (grub_strcmp(expvars[i].v_name, name) == 0) + break; + } else if (i < avail) { + avail = i; + } + } + + if (i == nexpvars) { + if (avail == nexpvars) + return (ERR_WONT_FIT); + + i = avail; + (void) grub_strcpy(expvars[i].v_name, name); + expvars[i].v_flags = EVF_DEFINED; + } + + if (value != NULL) { + (void) grub_strcpy(expvars[i].v_value, value); + expvars[i].v_flags |= EVF_VALUESET; + } else { + expvars[i].v_flags &= ~EVF_VALUESET; + } + + return (0); +} + +const char * +get_variable(const char *name) +{ + unsigned int i; + + for (i = 0; i < nexpvars; i++) { + if (!(expvars[i].v_flags & EVF_DEFINED)) + continue; + if (grub_strcmp(expvars[i].v_name, name) == 0) { + if (expvars[i].v_flags & EVF_VALUESET) + return (expvars[i].v_value); + return (""); + } + } + + return (NULL); +} + +static int +detect_target_operating_mode(void) +{ + int ret, ah; + + /* + * This function returns 16 bits. The upper 8 are the value of %ah + * after calling int 15/ec00. The lower 8 bits are zero if the BIOS + * call left CF clear, nonzero otherwise. + */ + ret = get_target_operating_mode(); + ah = ret & 0xff; + ret >>= 8; + + if (ah == 0x86 && ret != 0) { + grub_printf("[BIOS 'Detect Target Operating Mode' " + "callback unsupported on this platform]\n"); + return (1); /* unsupported, ignore */ + } + + if (ah == 0 && ret == 0) { + grub_printf("[BIOS accepted mixed-mode target setting!]\n"); + return (1); /* told the bios what we're up to */ + } + + if (ah == 0 && ret != 0) { + grub_printf("fatal: BIOS reports this machine CANNOT run in " + "mixed 32/64-bit mode!\n"); + return (0); + } + + grub_printf("warning: BIOS Detect Target Operating Mode callback " + "confused.\n %%ax >> 8 = 0x%x, carry = %d\n", ah, ret); + + return (1); +} + +static int +amd64_config_cpu(void) +{ + struct amd64_cpuid_regs __vcr, *vcr = &__vcr; + uint32_t maxeax; + uint32_t max_maxeax = 0x100; + char vendor[13]; + int isamd64 = 0; + uint32_t stdfeatures = 0, xtdfeatures = 0; + uint64_t efer; + + /* + * This check may seem silly, but if the C preprocesor symbol __amd64 + * is #defined during compilation, something that may outwardly seem + * like a good idea, uts/common/sys/isa_defs.h will #define _LP64, + * which will cause uts/common/sys/int_types.h to typedef uint64_t as + * an unsigned long - which is only 4 bytes in size when using a 32-bit + * compiler. + * + * If that happens, all the page table translation routines will fail + * horribly, so check the size of uint64_t just to insure some degree + * of sanity in future operations. + */ + /*LINTED [sizeof result is invarient]*/ + if (sizeof (uint64_t) != 8) + prom_panic("grub compiled improperly, unable to boot " + "64-bit AMD64 executables"); + + /* + * If the CPU doesn't support the CPUID instruction, it's definitely + * not an AMD64. + */ + if (amd64_cpuid_supported() == 0) + return (0); + + amd64_cpuid_insn(0, vcr); + + maxeax = vcr->r_eax; + { + /*LINTED [vendor string from cpuid data]*/ + uint32_t *iptr = (uint32_t *)vendor; + + *iptr++ = vcr->r_ebx; + *iptr++ = vcr->r_edx; + *iptr++ = vcr->r_ecx; + + vendor[12] = '\0'; + } + + if (maxeax > max_maxeax) { + grub_printf("cpu: warning, maxeax was 0x%x -> 0x%x\n", + maxeax, max_maxeax); + maxeax = max_maxeax; + } + + if (maxeax < 1) + return (0); /* no additional functions, not an AMD64 */ + else { + uint_t family, model, step; + + amd64_cpuid_insn(1, vcr); + + /* + * All AMD64/IA32e processors technically SHOULD report + * themselves as being in family 0xf, but for some reason + * Simics doesn't, and this may change in the future, so + * don't error out if it's not true. + */ + if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf) + family += BITX(vcr->r_eax, 27, 20); + + if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf) + model += BITX(vcr->r_eax, 19, 16) << 4; + step = BITX(vcr->r_eax, 3, 0); + + grub_printf("cpu: '%s' family %d model %d step %d\n", + vendor, family, model, step); + stdfeatures = vcr->r_edx; + } + + amd64_cpuid_insn(0x80000000, vcr); + + if (vcr->r_eax & 0x80000000) { + uint32_t xmaxeax = vcr->r_eax; + const uint32_t max_xmaxeax = 0x80000100; + + if (xmaxeax > max_xmaxeax) { + grub_printf("amd64: warning, xmaxeax was " + "0x%x -> 0x%x\n", xmaxeax, max_xmaxeax); + xmaxeax = max_xmaxeax; + } + + if (xmaxeax >= 0x80000001) { + amd64_cpuid_insn(0x80000001, vcr); + xtdfeatures = vcr->r_edx; + } + } + + if (BITX(xtdfeatures, 29, 29)) /* long mode */ + isamd64++; + else + grub_printf("amd64: CPU does NOT support long mode\n"); + + if (!BITX(stdfeatures, 0, 0)) { + grub_printf("amd64: CPU does NOT support FPU\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 4, 4)) { + grub_printf("amd64: CPU does NOT support TSC\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 5, 5)) { + grub_printf("amd64: CPU does NOT support MSRs\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 6, 6)) { + grub_printf("amd64: CPU does NOT support PAE\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 8, 8)) { + grub_printf("amd64: CPU does NOT support CX8\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 13, 13)) { + grub_printf("amd64: CPU does NOT support PGE\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 19, 19)) { + grub_printf("amd64: CPU does NOT support CLFSH\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 23, 23)) { + grub_printf("amd64: CPU does NOT support MMX\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 24, 24)) { + grub_printf("amd64: CPU does NOT support FXSR\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 25, 25)) { + grub_printf("amd64: CPU does NOT support SSE\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 26, 26)) { + grub_printf("amd64: CPU does NOT support SSE2\n"); + isamd64--; + } + + if (isamd64 < 1) { + grub_printf("amd64: CPU does not support amd64 executables.\n"); + return (0); + } + + amd64_rdmsr(MSR_AMD_EFER, &efer); + if (efer & AMD_EFER_SCE) + grub_printf("amd64: EFER_SCE (syscall/sysret) already " + "enabled\n"); + if (efer & AMD_EFER_NXE) + grub_printf("amd64: EFER_NXE (no-exec prot) already enabled\n"); + if (efer & AMD_EFER_LME) + grub_printf("amd64: EFER_LME (long mode) already enabled\n"); + + return (detect_target_operating_mode()); +} + +static int +isamd64() +{ + static int ret = -1; + + if (ret == -1) + ret = amd64_config_cpu(); + + return (ret); +} + +static int +check_min_mem64(void) +{ + if (min_mem64 == 0) + return (1); + + if ((mbi.mem_upper / 10240) * 11 >= min_mem64) + return (1); + + return (0); +} + +/* + * Given the nul-terminated input string s, expand all variable references + * within that string into the buffer pointed to by d, which must be of length + * not less than len bytes. + * + * We also expand the special case tokens "$ISADIR" and "$ZFS-BOOTFS" here. + * + * If the string will not fit, returns ERR_WONT_FIT. + * If a nonexistent variable is referenced, returns ERR_NOVAR. + * Otherwise, returns 0. The resulting string is nul-terminated. On error, + * the contents of the destination buffer are undefined. + */ +int +expand_string(const char *s, char *d, unsigned int len) +{ + unsigned int i; + int vlen; + const char *p; + char *q; + const char *start; + char name[EV_NAMELEN]; + const char *val; + + for (p = s, q = d; *p != '\0' && q < d + len; ) { + /* Special case: $ISADIR */ + if (grub_strncmp(p, "$ISADIR", 7) == 0) { + if (isamd64() && check_min_mem64()) { + if (q + 5 >= d + len) + return (ERR_WONT_FIT); + (void) grub_memcpy(q, "amd64", 5); + q += 5; /* amd64 */ + } + p += 7; /* $ISADIR */ + continue; + } + /* Special case: $ZFS-BOOTFS */ + if (grub_strncmp(p, "$ZFS-BOOTFS", 11) == 0 && + is_zfs_mount != 0) { + if (current_bootpath[0] == '\0' && + current_devid[0] == '\0') { + return (ERR_NO_BOOTPATH); + } + + /* zfs-bootfs=%s/%u */ + vlen = (current_bootfs_obj > 0) ? 10 : 0; + vlen += 11; + vlen += strlen(current_rootpool); + + /* ,bootpath=\"%s\" */ + if (current_bootpath[0] != '\0') + vlen += 12 + strlen(current_bootpath); + + /* ,diskdevid=\"%s\" */ + if (current_devid[0] != '\0') + vlen += 13 + strlen(current_devid); + + if (q + vlen >= d + len) + return (ERR_WONT_FIT); + + if (current_bootfs_obj > 0) { + q += grub_sprintf(q, "zfs-bootfs=%s/%u", + current_rootpool, current_bootfs_obj); + } else { + q += grub_sprintf(q, "zfs-bootfs=%s", + current_rootpool); + } + if (current_bootpath[0] != '\0') { + q += grub_sprintf(q, ",bootpath=\"%s\"", + current_bootpath); + } + if (current_devid[0] != '\0') { + q += grub_sprintf(q, ",diskdevid=\"%s\"", + current_devid); + } + + p += 11; /* $ZFS-BOOTFS */ + continue; + } + if (*p == '$' && *(p + 1) == '{') { + start = p + 2; + for (p = start; *p != '\0' && *p != '}' && + p - start < sizeof (name); p++) { + name[p - start] = *p; + } + /* + * Unterminated reference. Copy verbatim. + */ + if (p - start == sizeof (name) || *p != '}') { + p = start; + *q++ = '$'; + *q++ = '{'; + } + + val = get_variable(name); + if (val == NULL) + return (ERR_NOVAR); + + if ((vlen = grub_strlen(val)) >= q + len - d) + return (ERR_WONT_FIT); + + (void) grub_memcpy(q, val, vlen); + q += vlen; + p++; + } else { + *q++ = *p++; + } + } + + if (q >= d + len) + return (ERR_WONT_FIT); + + *q = '\0'; + + return (0); +} + +void +dump_variables(void) +{ + unsigned int i; + + for (i = 0; i < nexpvars; i++) { + if (!(expvars[i].v_flags & EVF_DEFINED)) + continue; + (void) grub_printf("[%u] '%s' => '%s'\n", i, expvars[i].v_name, + (expvars[i].v_flags & EVF_VALUESET) ? + expvars[i].v_value : ""); + } +} diff --git a/usr/src/grub/grub-0.97/stage2/expand.h b/usr/src/grub/grub-0.97/stage2/expand.h new file mode 100644 index 0000000000..ed8344e8af --- /dev/null +++ b/usr/src/grub/grub-0.97/stage2/expand.h @@ -0,0 +1,31 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (c) 2013 Joyent, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GRUB_EXPAND_H +#define _GRUB_EXPAND_H + +#define EV_NAMELEN 32 + +extern void init_variables(void); +extern int set_variable(const char *, const char *); +extern const char *get_variable(const char *); +extern int expand_string(const char *, char *, unsigned int); +extern void dump_variables(void); + +#endif diff --git a/usr/src/grub/grub-0.97/stage2/shared.h b/usr/src/grub/grub-0.97/stage2/shared.h index 205715b021..cb41978ce3 100644 --- a/usr/src/grub/grub-0.97/stage2/shared.h +++ b/usr/src/grub/grub-0.97/stage2/shared.h @@ -579,7 +579,7 @@ typedef enum ERR_NOTXPM, ERR_TOOMANYCOLORS, ERR_CORRUPTXPM, - + ERR_NOVAR, MAX_ERR_NUM } grub_error_t; @@ -639,6 +639,8 @@ extern int fallback_entryno; extern int default_entry; extern int current_entryno; +extern unsigned int min_mem64; + /* The constants for password types. */ typedef enum { diff --git a/usr/src/grub/grub-0.97/stage2/stage2.c b/usr/src/grub/grub-0.97/stage2/stage2.c index 25ef4df1e7..292ac308df 100644 --- a/usr/src/grub/grub-0.97/stage2/stage2.c +++ b/usr/src/grub/grub-0.97/stage2/stage2.c @@ -19,6 +19,7 @@ #include <shared.h> #include <term.h> +#include <expand.h> #define MENU_ROWS 7 @@ -239,6 +240,7 @@ run_menu (char *menu_entries, char *config_entries, int num_entries, int c, time1, time2 = -1, first_entry = 0; char *cur_entry = 0; struct term_entry *prev_term = NULL; + const char *console = NULL; /* * Main loop for menu UI. @@ -334,6 +336,14 @@ restart: selected line, or escape to go back to the main menu."); } + /* The selected OS console is special; if it's in use, tell the user. */ + console = get_variable("os_console"); + if (console != NULL) { + printf("\n\n Selected OS console device is '%s'." + "\n Use 'variable' command to change OS console device.", + console); + } + if (current_term->flags & TERM_DUMB) grub_printf ("\n\nThe selected entry is %d ", entryno); else |
