diff options
author | rscott <none@none> | 2007-04-23 16:09:20 -0700 |
---|---|---|
committer | rscott <none@none> | 2007-04-23 16:09:20 -0700 |
commit | adb91f4744062c28f7f3d0e8bf4704d2a8127b89 (patch) | |
tree | 4853e760b963902720f3ccfe57e2f43958d119cc | |
parent | c40d7343efa60b18ad1ceb316eb337caeea79046 (diff) | |
download | illumos-joyent-adb91f4744062c28f7f3d0e8bf4704d2a8127b89.tar.gz |
6520287 Serial console redirection ignores ttyX-mode with direct boot
6528202 bfu breaks the failsafe boot after snv_57 (dboot changes)
-rw-r--r-- | usr/src/cmd/eeprom/i386/benv.c | 67 | ||||
-rw-r--r-- | usr/src/tools/scripts/bfu.sh | 66 | ||||
-rw-r--r-- | usr/src/uts/i86pc/Makefile.rules | 2 | ||||
-rw-r--r-- | usr/src/uts/i86pc/boot/boot_console.c | 262 | ||||
-rw-r--r-- | usr/src/uts/i86pc/dboot/dboot_elfload.c | 2 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/fakebop.c | 11 | ||||
-rw-r--r-- | usr/src/uts/i86pc/unix/Makefile | 1 | ||||
-rw-r--r-- | usr/src/uts/intel/sys/bootconf.h | 2 |
8 files changed, 331 insertions, 82 deletions
diff --git a/usr/src/cmd/eeprom/i386/benv.c b/usr/src/cmd/eeprom/i386/benv.c index 6cdd09bb9a..cc2e01abe7 100644 --- a/usr/src/cmd/eeprom/i386/benv.c +++ b/usr/src/cmd/eeprom/i386/benv.c @@ -415,21 +415,24 @@ get_bootadm_value(char *name, const int quiet) /* * If quiet is 1, print nothing if there is no value. If quiet is 0, print - * a message. + * a message. Return 1 if the value is printed, 0 otherwise. */ -static void +static int print_bootadm_value(char *name, const int quiet) { + int rv = 0; char *value = get_bootadm_value(name, quiet); if ((value != NULL) && (value[0] != '\0')) { (void) printf("%s=%s\n", name, value); + rv = 1; } else if (quiet == 0) { (void) printf("%s: data not available.\n", name); } if (value != NULL) free(value); + return (rv); } static void @@ -437,10 +440,23 @@ print_var(char *name, eplist_t *list) { benv_ent_t *p; - if ((strcmp(name, "boot-file") == 0) || - (strcmp(name, "boot-args") == 0) || - (strcmp(name, "console") == 0)) { - print_bootadm_value(name, 0); + /* + * The console property is kept in both menu.lst and bootenv.rc. The + * menu.lst value takes precedence. + */ + if (strcmp(name, "console") == 0) { + if (print_bootadm_value(name, 1) == 0) { + if ((p = get_var(name, list)) != NULL) { + (void) printf("%s=%s\n", name, p->val ? + p->val : ""); + } else { + (void) printf("%s: data not available.\n", + name); + } + } + } else if ((strcmp(name, "boot-file") == 0) || + (strcmp(name, "boot-args") == 0)) { + (void) print_bootadm_value(name, 0); } else if ((p = get_var(name, list)) == NULL) (void) printf("%s: data not available.\n", name); else @@ -452,22 +468,30 @@ print_vars(eplist_t *list) { eplist_t *e; benv_ent_t *p; + int console_printed = 0; + + /* + * The console property is kept both in menu.lst and bootenv.rc. + * The menu.lst value takes precedence, so try printing that one + * first. + */ + console_printed = print_bootadm_value("console", 1); for (e = list->next; e != list; e = e->next) { p = (benv_ent_t *)e->item; if (p->name != NULL) { - if ((strcmp(p->name, "boot-file") == 0) || - (strcmp(p->name, "boot-args") == 0) || - (strcmp(p->name, "console") == 0)) { + if (((strcmp(p->name, "console") == 0) && + (console_printed == 1)) || + ((strcmp(p->name, "boot-file") == 0) || + (strcmp(p->name, "boot-args") == 0))) { /* handle these separately */ continue; } (void) printf("%s=%s\n", p->name, p->val ? p->val : ""); } } - print_bootadm_value("boot-file", 1); - print_bootadm_value("boot-args", 1); - print_bootadm_value("console", 1); + (void) print_bootadm_value("boot-file", 1); + (void) print_bootadm_value("boot-args", 1); } /* @@ -504,7 +528,7 @@ set_bootadm_var(char *name, char *value) if (verbose) { (void) printf("old:"); - print_bootadm_value(name, 0); + (void) print_bootadm_value(name, 0); } /* @@ -561,7 +585,7 @@ set_bootadm_var(char *name, char *value) if (verbose) { (void) printf("new:"); - print_bootadm_value(name, 0); + (void) print_bootadm_value(name, 0); } } @@ -569,14 +593,25 @@ static void set_var(char *name, char *val, eplist_t *list) { benv_ent_t *p; + int old_verbose; if ((strcmp(name, "boot-file") == 0) || - (strcmp(name, "boot-args") == 0) || - (strcmp(name, "console") == 0)) { + (strcmp(name, "boot-args") == 0)) { set_bootadm_var(name, val); return; } + /* + * The console property is kept in two places: menu.lst and bootenv.rc. + * Update them both. We clear verbose to prevent duplicate messages. + */ + if (strcmp(name, "console") == 0) { + old_verbose = verbose; + verbose = 0; + set_bootadm_var(name, val); + verbose = old_verbose; + } + if (verbose) { (void) printf("old:"); print_var(name, list); diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index 3ab3378455..3887a7e754 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -1887,6 +1887,21 @@ EOF smf_fix_i86pc_profile } +# +# The directboot putback moved the console property from +# /boot/solaris/bootenv.rc to /boot/grub/menu.lst. It should be kept in both. +# +cleanup_eeprom_console() +{ + bootenvrc="$root/boot/solaris/bootenv.rc" + menu_console=`eeprom console 2>/dev/null | \ + grep -v 'data not available' | cut -d= -f2-` + bootenv_console=`grep '^setprop[ ]\{1,\}console\>' $bootenvrc` + if [ -n "$menu_console" ] && [ -z "$bootenv_console" ]; then + echo "setprop console '$menu_console'" >> $bootenvrc + fi +} + EXTRACT_LOG=/tmp/bfu-extract-log.$$ rm -f $EXTRACT_LOG @@ -2027,12 +2042,6 @@ if [ $diskless = no ]; then [[ -f $root/etc/system ]] || \ fail "$root/etc/system not found; nonglobal zone target not allowed" - if [ -f $root/boot/platform/i86pc/kernel/unix ]; then - failsafe_type=directboot - elif [ -f $root/boot/multiboot ]; then - failsafe_type=multiboot - fi - # Make sure we extract the sun4u-us3 libc_psr.so.1 if [ -d $root/platform/sun4u -a \ ! -d $root/platform/sun4u-us3 ] @@ -2477,6 +2486,9 @@ if [ $multi_or_direct = yes ]; then [ -x /$cmd ] && cp /$cmd /tmp/bfubin fi done + if [ $archive_type = directboot ] && [ $root_is_directboot = yes ]; then + cleanup_eeprom_console + fi fi multiboot_cmds=" @@ -2643,6 +2655,40 @@ if [ $multi_or_direct = yes ]; then done fi +# +# For directboot archives, /boot/platform/i86pc/kernel/unix will be +# overwritten, which could cause a mis-match with the failsafe +# miniroot. Extract unix from the miniroot and save it off for now. +# +if [ $archive_type = directboot ] && [ $diskless = no ]; then + if gunzip -c "$root/boot/x86.miniroot-safe" \ + >/tmp/bfubin/miniroot-unzipped; then + lofifile=/tmp/bfubin/miniroot-unzipped + else + # Shouldn't happen? See if someone already unzipped it. + lofifile="$root/boot/x86.miniroot-safe" + fi + lofidev=`lofiadm -a $lofifile 2>/dev/null` + if [ -n "$lofidev" ]; then + mkdir /tmp/bfubin/mnt + mount -r $lofidev /tmp/bfubin/mnt + + unix=/tmp/bfubin/mnt/boot/platform/i86pc/kernel/unix + if [ -f $unix ]; then + cp $unix /tmp/bfubin/unix + failsafe_type=directboot + elif [ -f /tmp/bfubin/mnt/platform/i86pc/multiboot ] + then + failsafe_type=multiboot + fi + + umount /tmp/bfubin/mnt + rmdir /tmp/bfubin/mnt + lofiadm -d $lofidev + fi + rm -f /tmp/bfubin/miniroot-unzipped +fi + create_datalink_conf() { # /etc/datalink.conf needs to be populated. @@ -4565,7 +4611,7 @@ update_bootenv() fi if [ $bootenvrc_updated = 1 ]; then - egrep -v '^setprop[ ]+(console|boot-file|boot-args|input-device)[ ]' $bootenvrc > ${bootenvrc}.new + egrep -v '^setprop[ ]+(boot-file|boot-args)[ ]' $bootenvrc > ${bootenvrc}.new [ -s ${bootenvrc}.new ] && mv ${bootenvrc}.new $bootenvrc fi } @@ -4674,6 +4720,9 @@ install_failsafe() # if [ $failsafe_type = multiboot ]; then rm -f $rootprefix/boot/platform/i86pc/kernel/unix + elif [ $failsafe_type = directboot ]; then + cp /tmp/bfubin/unix \ + $rootprefix/boot/platform/i86pc/kernel/unix fi else echo "Updating failsafe archives" @@ -4841,6 +4890,9 @@ EOF fi elif [ $failsafe_type = multiboot ]; then rm -f $rootprefix/boot/platform/i86pc/kernel/unix + elif [ $failsafe_type = directboot ]; then + cp /tmp/bfubin/unix \ + $rootprefix/boot/platform/i86pc/kernel/unix fi build_boot_archive else diff --git a/usr/src/uts/i86pc/Makefile.rules b/usr/src/uts/i86pc/Makefile.rules index dcfee40f65..be06be43ac 100644 --- a/usr/src/uts/i86pc/Makefile.rules +++ b/usr/src/uts/i86pc/Makefile.rules @@ -152,7 +152,7 @@ DBOOT_LINTFLAGS_i86pc = $(LINTFLAGS_i386_32) $(LINTTAGS_i386_32) DBOOT_LINTFLAGS = $(DBOOT_LINTFLAGS_$(PLATFORM)) $(C99LMODE) $(CPPFLAGS) \ $(DBOOT_DEFS) DBOOT_LOCAL_LINTFLAGS = -c -dirout=$(DBOOT_LINTS_DIR) -I$(SRC)/common \ - $(DBOOT_LINTFLAGS) + $(DBOOT_LINTFLAGS) $(DBOOT_LINTTAGS) $(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86pc/boot/%.c $(i386_CC) $(CERRWARN) -O $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< diff --git a/usr/src/uts/i86pc/boot/boot_console.c b/usr/src/uts/i86pc/boot/boot_console.c index 71134377ec..b9f0745cc9 100644 --- a/usr/src/uts/i86pc/boot/boot_console.c +++ b/usr/src/uts/i86pc/boot/boot_console.c @@ -29,13 +29,13 @@ #include <sys/systm.h> #include <sys/archsystm.h> #include <sys/boot_console.h> +#include <sys/ctype.h> #include "boot_serial.h" #include "boot_vga.h" #if defined(_BOOT) -#include "../dboot/dboot_xboot.h" -#include <util/string.h> +#include <dboot/dboot_xboot.h> #else #include <sys/bootconf.h> static char *usbser_buf; @@ -52,6 +52,9 @@ static void serial_adjust_prop(void); static char *boot_line = NULL; +/* Set if the console or mode are expressed in the boot line */ +static int console_set, console_mode_set; + /* Clear the screen and initialize VIDEO, XPOS and YPOS. */ static void clear_screen(void) @@ -171,6 +174,117 @@ serial_init(void) #endif } +/* Advance str pointer past white space */ +#define EAT_WHITE_SPACE(str) { \ + while ((*str != '\0') && ISSPACE(*str)) \ + str++; \ +} + +/* + * boot_line is set when we call here. Search it for the argument name, + * and if found, return a pointer to it. + */ +static char * +find_boot_line_prop(const char *name) +{ + char *ptr; + char end_char; + size_t len; + + if (boot_line == NULL) + return (NULL); + + len = strlen(name); + + /* + * We have two nested loops here: the outer loop discards all options + * except -B, and the inner loop parses the -B options looking for + * the one we're interested in. + */ + for (ptr = boot_line; *ptr != '\0'; ptr++) { + EAT_WHITE_SPACE(ptr); + + if (*ptr == '-') { + ptr++; + while ((*ptr != '\0') && (*ptr != 'B') && + !ISSPACE(*ptr)) + ptr++; + if (*ptr == '\0') + return (NULL); + else if (*ptr != 'B') + continue; + } else { + while ((*ptr != '\0') && !ISSPACE(*ptr)) + ptr++; + if (*ptr == '\0') + return (NULL); + continue; + } + + do { + ptr++; + EAT_WHITE_SPACE(ptr); + + if ((strncmp(ptr, name, len) == 0) && + (ptr[len] == '=')) { + ptr += len + 1; + if ((*ptr == '\'') || (*ptr == '"')) + return (ptr + 1); + else + return (ptr); + } + + /* + * We have a property, and it's not the one we're + * interested in. Skip the property name. A name + * can end with '=', a comma, or white space. + */ + while ((*ptr != '\0') && (*ptr != '=') && + (*ptr != ',') && (!ISSPACE(*ptr))) + ptr++; + + /* + * We only want to go through the rest of the inner + * loop if we have a comma. If we have a property + * name without a value, either continue or break. + */ + if (*ptr == '\0') + return (NULL); + else if (*ptr == ',') + continue; + else if (ISSPACE(*ptr)) + break; + ptr++; + + /* + * Is the property quoted? + */ + if ((*ptr == '\'') || (*ptr == '"')) { + end_char = *ptr; + } else { + /* + * Not quoted, so the string ends at a comma + * or at white space. Deal with white space + * later. + */ + end_char = ','; + } + + /* + * Now, we can ignore any characters until we find + * end_char. + */ + for (; (*ptr != '\0') && (*ptr != end_char); ptr++) { + if ((end_char == ',') && ISSPACE(*ptr)) + break; + } + if (*ptr && (*ptr != ',')) + ptr++; + } while (*ptr == ','); + } + return (NULL); +} + #define MATCHES(p, pat) \ (strncmp(p, pat, strlen(pat)) == 0 ? (p += strlen(pat), 1) : 0) @@ -187,17 +301,11 @@ serial_init(void) static char * get_mode_value(char *name) { - char *p; - /* * when specified on boot line it looks like "name" "=".... */ if (boot_line != NULL) { - p = strstr(boot_line, name); - if (p == NULL) - return (NULL); - SKIP(p, '='); - return (p); + return (find_boot_line_prop(name)); } #if defined(_BOOT) @@ -210,9 +318,9 @@ get_mode_value(char *name) static char propval[20]; propval[0] = 0; - if (bootops == NULL || BOP_GETPROPLEN(bootops, name) == 0) + if (do_bsys_getproplen(NULL, name) <= 0) return (NULL); - (void) BOP_GETPROP(bootops, name, propval); + (void) do_bsys_getprop(NULL, name, propval); return (propval); } #endif @@ -237,6 +345,8 @@ serial_adjust_prop(void) propval = get_mode_value(propname); if (propval == NULL) propval = "9600,8,n,1,-"; + else + console_mode_set = 1; /* property is of the form: "9600,8,n,1,-" */ p = propval; @@ -334,18 +444,57 @@ serial_adjust_prop(void) outb(port + MCR, mcr | OUT2); } +/* + * A structure to map console names to values. + */ +typedef struct { + char *name; + int value; +} console_value_t; + +console_value_t console_devices[] = { + { "ttya", CONS_TTYA }, + { "ttyb", CONS_TTYB }, + { "text", CONS_SCREEN_TEXT }, +#if !defined(_BOOT) + { "usb-serial", CONS_USBSER }, +#endif + { "", CONS_INVALID } +}; + void bcons_init(char *bootstr) { + console_value_t *consolep; + size_t len, cons_len; + char *cons_str; + boot_line = bootstr; console = CONS_INVALID; - if (strstr(bootstr, "console=ttya") != 0) - console = CONS_TTYA; - else if (strstr(bootstr, "console=ttyb") != 0) - console = CONS_TTYB; - else if (strstr(bootstr, "console=text") != 0) - console = CONS_SCREEN_TEXT; + cons_str = find_boot_line_prop("console"); + if (cons_str == NULL) + cons_str = find_boot_line_prop("output-device"); + + /* + * Go through the console_devices array trying to match the string + * we were given. The string on the command line must end with + * a comma or white space. + */ + if (cons_str != NULL) { + cons_len = strlen(cons_str); + consolep = console_devices; + for (; consolep->name[0] != '\0'; consolep++) { + len = strlen(consolep->name); + if ((len <= cons_len) && ((cons_str[len] == '\0') || + (cons_str[len] == ',') || (cons_str[len] == '\'') || + (cons_str[len] == '"') || ISSPACE(cons_str[len])) && + (strncmp(cons_str, consolep->name, len) == 0)) { + console = consolep->value; + break; + } + } + } /* * If no console device specified, default to text. @@ -353,6 +502,8 @@ bcons_init(char *bootstr) */ if (console == CONS_INVALID) console = CONS_SCREEN_TEXT; + else + console_set = 1; switch (console) { case CONS_TTYA: @@ -360,6 +511,14 @@ bcons_init(char *bootstr) serial_init(); break; +#if !defined(_BOOT) + case CONS_USBSER: + /* + * We can't do anything with the usb serial + * until we have memory management. + */ + break; +#endif case CONS_SCREEN_TEXT: default: #if defined(_BOOT) @@ -383,49 +542,50 @@ bcons_init2(char *inputdev, char *outputdev, char *consoledev) { #if !defined(_BOOT) int cons = CONS_INVALID; + char *devnames[] = { consoledev, outputdev, inputdev, NULL }; + console_value_t *consolep; + int i; - if (consoledev) { - if (strstr(consoledev, "ttya") != 0) - cons = CONS_TTYA; - else if (strstr(consoledev, "ttyb") != 0) - cons = CONS_TTYB; - else if (strstr(consoledev, "usb-serial") != 0) - cons = CONS_USBSER; - } - - if (cons == CONS_INVALID && inputdev) { - if (strstr(inputdev, "ttya") != 0) - cons = CONS_TTYA; - else if (strstr(inputdev, "ttyb") != 0) - cons = CONS_TTYB; - else if (strstr(inputdev, "usb-serial") != 0) - cons = CONS_USBSER; - } + if (console != CONS_USBSER) { + if (console_set) { + /* + * If the console was set on the command line, + * but the ttyX-mode was not, we only need to + * check bootenv.rc for that setting. + */ + if ((!console_mode_set) && + (console == CONS_TTYA || console == CONS_TTYB)) + serial_init(); + return; + } - if (cons == CONS_INVALID && outputdev) { - if (strstr(outputdev, "ttya") != 0) - cons = CONS_TTYA; - else if (strstr(outputdev, "ttyb") != 0) - cons = CONS_TTYB; - else if (strstr(outputdev, "usb-serial") != 0) - cons = CONS_USBSER; - } + for (i = 0; devnames[i] != NULL; i++) { + consolep = console_devices; + for (; consolep->name[0] != '\0'; consolep++) { + if (strcmp(devnames[i], consolep->name) == 0) { + cons = consolep->value; + } + } + if (cons != CONS_INVALID) + break; + } - if (cons == CONS_INVALID) - return; - if (cons == console) - return; + if (cons == CONS_INVALID) + return; + if (cons == console) + return; - console = cons; - if (cons == CONS_TTYA || cons == CONS_TTYB) { - serial_init(); - return; + console = cons; + if (cons == CONS_TTYA || cons == CONS_TTYB) { + serial_init(); + return; + } } /* * USB serial -- we just collect data into a buffer */ - if (cons == CONS_USBSER) { + if (console == CONS_USBSER) { extern void *usbser_init(size_t); usbser_buf = usbser_cur = usbser_init(MMU_PAGESIZE); } diff --git a/usr/src/uts/i86pc/dboot/dboot_elfload.c b/usr/src/uts/i86pc/dboot/dboot_elfload.c index 5260d2d405..436dde8917 100644 --- a/usr/src/uts/i86pc/dboot/dboot_elfload.c +++ b/usr/src/uts/i86pc/dboot/dboot_elfload.c @@ -153,7 +153,7 @@ dboot_elfload64(uintptr_t file_image) src = (uintptr_t)PGETBYTES(phdr->p_offset); dst = ktext_phys + phdr->p_paddr - FOUR_MEG; if (prom_debug) - dboot_printf("copying %lu bytes from ELF offset 0x%lx " + dboot_printf("copying %ld bytes from ELF offset 0x%lx " "to physaddr 0x%lx (va=0x%lx)\n", (ulong_t)phdr->p_filesz, (ulong_t)phdr->p_offset, (ulong_t)dst, (ulong_t)phdr->p_vaddr); diff --git a/usr/src/uts/i86pc/os/fakebop.c b/usr/src/uts/i86pc/os/fakebop.c index bf4f1b9ae9..0fb6f65086 100644 --- a/usr/src/uts/i86pc/os/fakebop.c +++ b/usr/src/uts/i86pc/os/fakebop.c @@ -364,7 +364,7 @@ bsetpropsi(char *name, int value) * to find the size of the buffer to allocate */ /*ARGSUSED*/ -static int +int do_bsys_getproplen(bootops_t *bop, char *name) { bootprop_t *b; @@ -381,7 +381,7 @@ do_bsys_getproplen(bootops_t *bop, char *name) * get the value associated with this name */ /*ARGSUSED*/ -static int +int do_bsys_getprop(bootops_t *bop, char *name, void *value) { bootprop_t *b; @@ -587,11 +587,10 @@ boot_prop_finish(void) continue; /* - * If console was explicitly set on the command line it will - * override a setting in bootenv.rc + * If a property was explicitly set on the command line + * it will override a setting in bootenv.rc */ - if (strcmp(name, "console") == 0 && - do_bsys_getproplen(NULL, "console") > 0) + if (do_bsys_getproplen(NULL, name) > 0) continue; bsetprop(name, n_len, value, v_len + 1); diff --git a/usr/src/uts/i86pc/unix/Makefile b/usr/src/uts/i86pc/unix/Makefile index 8bef129839..4244e5a2e3 100644 --- a/usr/src/uts/i86pc/unix/Makefile +++ b/usr/src/uts/i86pc/unix/Makefile @@ -75,6 +75,7 @@ DBOOT_O = $(OBJS_DIR)/$(DBOOT).o DBOOT_S = $(DBOOT_O:%.o=%.s) DBOOT_LINTS = $(DBOOT_OBJS:%.o=$(DBOOT_OBJS_DIR)/%.ln) DBOOT_LINT = $(i386_LINT) +DBOOT_LINTTAGS = -erroff=E_STATIC_UNUSED # # Include common rules. diff --git a/usr/src/uts/intel/sys/bootconf.h b/usr/src/uts/intel/sys/bootconf.h index d500d3aa4f..4da7f8c3cb 100644 --- a/usr/src/uts/intel/sys/bootconf.h +++ b/usr/src/uts/intel/sys/bootconf.h @@ -240,6 +240,8 @@ extern void boot_prop_finish(void); */ extern paddr_t do_bop_phys_alloc(uint64_t, uint64_t); +extern int do_bsys_getproplen(bootops_t *, char *); +extern int do_bsys_getprop(bootops_t *, char *, void *); #endif /* _KERNEL && !_BOOT */ |