Mercurial > illumos > illumos-gate
changeset 10989:47a08e52035f
6896046 bootadm -m enable_hypervisor should modify current entry
author | William Kucharski <William.Kucharski@Sun.COM> |
---|---|
date | Fri, 06 Nov 2009 14:09:44 -0700 |
parents | 9d2e6b32f3a9 |
children | 05e8539af38e |
files | usr/src/cmd/boot/bootadm/bootadm.c usr/src/cmd/boot/bootadm/bootadm.h usr/src/cmd/boot/bootadm/bootadm_hyper.c |
diffstat | 3 files changed, 228 insertions(+), 176 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/boot/bootadm/bootadm.c Fri Nov 06 12:06:40 2009 -0800 +++ b/usr/src/cmd/boot/bootadm/bootadm.c Fri Nov 06 14:09:44 2009 -0700 @@ -4206,6 +4206,7 @@ static line_t *prev = NULL; static entry_t *curr_ent = NULL; static int in_liveupgrade = 0; + static int is_libbe_ent = 0; line_t *lp; char *cmd, *sep, *arg; @@ -4236,6 +4237,8 @@ in_liveupgrade = 1; } else if (strstr(arg, BAM_LU_FTR) != NULL) { in_liveupgrade = 0; + } else if (strstr(arg, BAM_LIBBE_FTR) != NULL) { + is_libbe_ent = 1; } } else if (*str == '\0') { /* blank line */ cmd = sep = arg = NULL; @@ -4353,7 +4356,12 @@ mp->old_rc_default = lp; } else if (lp->flags == BAM_ENTRY || (lp->flags == BAM_COMMENT && - strcmp(lp->arg, BAM_BOOTADM_FTR) == 0)) { + ((strcmp(lp->arg, BAM_BOOTADM_FTR) == 0) || is_libbe_ent))) { + if (is_libbe_ent) { + curr_ent->flags |= BAM_ENTRY_LIBBE; + is_libbe_ent = 0; + } + boot_entry_addline(curr_ent, lp); } append_line(mp, lp); @@ -4754,9 +4762,17 @@ ent = mp->entries; while (ent) { lp = ent->start; - /* check entry number and make sure it's a bootadm entry */ - if (lp->flags != BAM_COMMENT || - strcmp(lp->arg, BAM_BOOTADM_HDR) != 0 || + + /* + * Check entry number and make sure it's a modifiable entry. + * + * Guidelines: + * + We can modify a bootadm-created entry + * + We can modify a libbe-created entry + */ + if ((lp->flags != BAM_COMMENT && + (((ent->flags & BAM_ENTRY_LIBBE) == 0) && + strcmp(lp->arg, BAM_BOOTADM_HDR) != 0)) || (entryNum != ALL_ENTRIES && lp->entryNum != entryNum)) { ent = ent->next; continue;
--- a/usr/src/cmd/boot/bootadm/bootadm.h Fri Nov 06 12:06:40 2009 -0800 +++ b/usr/src/cmd/boot/bootadm/bootadm.h Fri Nov 06 14:09:44 2009 -0700 @@ -86,6 +86,8 @@ #define BAM_ENTRY_UPGFSKERNEL 0x800 /* Upgrade failsafe kernel entry */ #define BAM_ENTRY_UPGFSMODULE 0x1000 /* Upgrade failsafe module entry */ +#define BAM_ENTRY_LIBBE 0x2000 /* entry created by libbe */ + typedef struct { line_t *start; line_t *end; @@ -203,6 +205,11 @@ #define BAM_OLDDEF "BOOTADM SAVED DEFAULT: " #define BAM_OLD_RC_DEF "BOOTADM RC SAVED DEFAULT: " +/* + * menu.lst comment created by libbe + */ +#define BAM_LIBBE_FTR "============ End of LIBBE entry =============" + /* Title used for failsafe entries */ #define FAILSAFE_TITLE "Solaris failsafe"
--- a/usr/src/cmd/boot/bootadm/bootadm_hyper.c Fri Nov 06 12:06:40 2009 -0800 +++ b/usr/src/cmd/boot/bootadm/bootadm_hyper.c Fri Nov 06 14:09:44 2009 -0700 @@ -50,8 +50,10 @@ #define WHITESPC(x) (x) static char *serial_config[2] = { NULL, NULL }; +static char *console_dev = NULL; -static char *console_dev = NULL; +static char *bootenv_rc_serial[2] = { NULL, NULL }; +static char *bootenv_rc_console = NULL; static unsigned zfs_boot = 0; @@ -212,6 +214,9 @@ { char **rp = &serial_config[com - 1]; + if ((com < 1) || (com > 2)) + return (-1); + /* * If rate is a NULL pointer, erase any existing serial configuration * for this serial port. @@ -305,88 +310,6 @@ } /* - * Convert bootenv.rc boot property strings of the form: - * - * setprop property value - * - * into boot option lines suitable for use with the hypervisor. - * - * Our main concerns are the console device and serial port settings. - * - * Return values: - * - * -1: Unparseable line - * 0: Success - * (n > 0): A property unimportant to us - */ -static int -cvt_bootprop(char *propstr) -{ - char *parsestr, *port, *token; - - int retval = 0; - - /* get initial "setprop" */ - if ((parsestr = get_token(&token, propstr, " \t")) == NULL) { - if (token != NULL) - free(token); - - return (-1); - } - - if (strcmp(token, "setprop")) { - free(token); - return (1); - } - - free(token); - - /* get property name */ - if ((parsestr = get_token(&token, parsestr, " \t")) == NULL) { - if (token != NULL) - free(token); - - return (-2); - } - - if (strcmp(token, "console") == 0) { - free(token); - - /* get console property value */ - parsestr = get_token(&token, parsestr, " \t"); - if (token == NULL) - return (-3); - - console_metal_to_hyper(token); - free(token); - return (0); - } - - /* check if it's a serial port setting */ - if ((strcmp(token, "ttya-mode") == 0) || - (strcmp(token, "ttyb-mode") == 0)) { - port = token; - } else { - free(token); - return (3); - } - - /* get serial port setting */ - parsestr = get_token(&token, parsestr, " \t"); - - if (token == NULL) { - free(port); - return (-1); - } - - retval = serial_metal_to_hyper(port, token); - - free(port); - free(token); - return (retval); -} - -/* * Convert "name=value" metal options to values suitable for use with the * hypervisor. * @@ -447,7 +370,7 @@ static int cvt_hyper_option(char *optstr) { -#define SER_LEN 27 /* strlen("ttyb-mode='115200,8,n,1,-'") */ +#define SER_LEN 15 /* strlen("115200,8,n,1,-") + 1 */ char ser[SER_LEN]; char *value; @@ -496,11 +419,11 @@ return (0); if (strncmp(value, "com1", 4) == 0) - console_dev = "console=ttya"; + console_dev = "ttya"; else if (strncmp(value, "com2", 4) == 0) - console_dev = "console=ttyb"; + console_dev = "ttyb"; else - console_dev = "console=text"; + console_dev = "text"; } /* serial port parameter conversion */ @@ -519,55 +442,50 @@ * parameters to be the same as that used by the hypervisor. */ if (strcmp(value, "auto") == 0) { - (void) snprintf(ser, SER_LEN, - "tty%c-mode='9600,8,n,1,-'", '`' + com); + (void) snprintf(ser, SER_LEN, "9600,8,n,1,-"); + } else { + /* + * Extract the "B,PS" setting from the com line; ignore + * other settings like io_base or IRQ. + */ + if (sscanf(value, "%u,%c%c%c", &baud, &bits, &parity, + &stop) != 4) + return (-1); - if (set_serial_rate(com, ser) != 0) + /* validate serial port parameters */ + if (((stop != '0') && (stop != '1')) || + ((bits < '5') && (bits > '8')) || + ((parity != 'n') && (parity != 'e') && + (parity != 'o'))) return (-1); - return (0); - } - - /* - * Extract the "B,PS" setting from the com line; ignore other - * settings like io_base or IRQ. - */ - if (sscanf(value, "%u,%c%c%c", &baud, &bits, &parity, - &stop) != 4) - return (-1); - - /* validate serial port parameters */ - if (((stop != '0') && (stop != '1')) || - ((bits < '5') && (bits > '8')) || - ((parity != 'n') && (parity != 'e') && (parity != 'o'))) - return (-1); + /* validate baud rate */ + switch (baud) { + case 150: + case 300: + case 600: + case 1200: + case 2400: + case 4800: + case 19200: + case 38400: + case 57600: + case 115200: + break; - /* validate baud rate */ - switch (baud) { - case 150: - case 300: - case 600: - case 1200: - case 2400: - case 4800: - case 19200: - case 38400: - case 57600: - case 115200: - break; + default: + return (-1); + } - default: - return (-1); + /* + * As the hypervisor has no way to denote handshaking + * in its serial port settings, emit a metal serial + * port configuration with none as well. + */ + (void) snprintf(ser, SER_LEN, "%u,%c,%c,%c,-", baud, + bits, parity, stop); } - /* - * As the hypervisor has no way to denote handshaking in its - * serial port settings, emit a metal serial port configuration - * with none as well. - */ - (void) snprintf(ser, SER_LEN, "tty%c-mode='%u,%c,%c,%c,-'", - '`' + com, baud, bits, parity, stop); - if (set_serial_rate(com, ser) != 0) return (-1); @@ -756,11 +674,75 @@ } while (s_fgets(line, LINEBUF_SZ, fp) != NULL) { + char *parsestr, *token; + int port = 0; + /* we're only interested in parsing "setprop" directives. */ if (strncmp(line, "setprop", 7) != NULL) continue; - (void) cvt_bootprop(line); + /* eat initial "setprop" */ + if ((parsestr = get_token(&token, line, " \t")) == NULL) { + if (token != NULL) + free(token); + + continue; + } + + if (strcmp(token, "setprop") != 0) { + free(token); + continue; + } + + free(token); + + /* get property name */ + if ((parsestr = get_token(&token, parsestr, " \t")) == NULL) { + if (token != NULL) + free(token); + + continue; + } + + if (strcmp(token, "console") == 0) { + free(token); + + /* get console property value */ + parsestr = get_token(&token, parsestr, " \t"); + if (token == NULL) + continue; + + if (bootenv_rc_console != NULL) + free(bootenv_rc_console); + + bootenv_rc_console = s_strdup(token); + continue; + } + + /* check if it's a serial port setting */ + if (strcmp(token, "ttya-mode") == 0) { + free(token); + port = 0; + } else if (strcmp(token, "ttyb-mode") == 0) { + free(token); + port = 1; + } else { + /* nope, so check the next line */ + free(token); + continue; + } + + /* get serial port setting */ + parsestr = get_token(&token, parsestr, " \t"); + + if (token == NULL) + continue; + + if (bootenv_rc_serial[port] != NULL) + free(bootenv_rc_serial[port]); + + bootenv_rc_serial[port] = s_strdup(token); + free(token); } (void) fclose(fp); @@ -788,7 +770,7 @@ char *kern_path = NULL; char *kern_bargs = NULL; - int curdef; + int curdef, newdef; int kp_allocated = 0; int ret = BAM_ERROR; @@ -841,6 +823,15 @@ */ parse_bootenvrc(osroot); + if (bootenv_rc_console != NULL) + console_metal_to_hyper(bootenv_rc_console); + + if (bootenv_rc_serial[0] != NULL) + (void) serial_metal_to_hyper("ttya-mode", bootenv_rc_serial[0]); + + if (bootenv_rc_serial[1] != NULL) + (void) serial_metal_to_hyper("ttyb-mode", bootenv_rc_serial[1]); + /* * Now process the entry itself. */ @@ -877,7 +868,8 @@ } /* - * If findroot, module or kern_path are NULL, boot entry was malformed + * If findroot, module or kern_path are NULL, the boot entry is + * malformed. */ if (findroot == NULL) { bam_error(FINDROOT_NOT_FOUND, curdef); @@ -976,25 +968,25 @@ BAM_DPRINTF((D_CVT_CMD_KERN_DOLLAR, fcn, kernel)); BAM_DPRINTF((D_CVT_CMD_MOD_DOLLAR, fcn, mod_kernel)); + if ((newdef = add_boot_entry(mp, title, findroot, kernel, mod_kernel, + module, bootfs)) == BAM_ERROR) + return (newdef); + /* * Now try to delete the current default entry from the menu and add * the new hypervisor entry with the parameters we've setup. */ - if (delete_boot_entry(mp, curdef, DBE_QUIET) != BAM_SUCCESS) + if (delete_boot_entry(mp, curdef, DBE_QUIET) == BAM_SUCCESS) + newdef--; + else bam_print(NEW_BOOT_ENTRY, title); - curdef = add_boot_entry(mp, title, findroot, kernel, mod_kernel, - module, bootfs); - /* * If we successfully created the new entry, set the default boot * entry to that entry and let the caller know the new menu should * be written out. */ - if (curdef != BAM_ERROR) - return (set_global(mp, menu_cmds[DEFAULT_CMD], curdef)); - - return (BAM_ERROR); + return (set_global(mp, menu_cmds[DEFAULT_CMD], newdef)); abort: if (ret != BAM_NOCHANGE) @@ -1026,7 +1018,7 @@ char *barchive_path = DIRECT_BOOT_ARCHIVE; char *kern_path = NULL; - int curdef; + int curdef, newdef; int emit_bflag = 1; int ret = BAM_ERROR; @@ -1098,7 +1090,8 @@ } /* - * If findroot, module or kern_path are NULL, boot entry was malformed + * If findroot, module or kern_path are NULL, the boot entry is + * malformed. */ if (findroot == NULL) { bam_error(FINDROOT_NOT_FOUND, curdef); @@ -1146,32 +1139,46 @@ emit_bflag = 0; } - if (console_dev != NULL) { + /* + * Process the bootenv.rc file to look for boot options that would be + * the same as what the hypervisor had manually set, as we need not set + * those explicitly. + * + * If there's no bootenv.rc, it's not an issue. + */ + parse_bootenvrc(osroot); + + /* + * Don't emit a console setting if it's the same as what would be + * set by bootenv.rc. + */ + if ((console_dev != NULL) && (bootenv_rc_console == NULL || + (strcmp(console_dev, bootenv_rc_console) != 0))) { if (emit_bflag) { newstr = append_str(kernel, BFLAG, " "); free(kernel); - kernel = append_str(newstr, console_dev, " "); + kernel = append_str(newstr, "console=", " "); free(newstr); + newstr = append_str(kernel, console_dev, ""); + free(kernel); + kernel = newstr; emit_bflag = 0; } else { - newstr = append_str(kernel, console_dev, ","); + newstr = append_str(kernel, "console=", ","); free(kernel); - kernel = newstr; + kernel = append_str(newstr, console_dev, ""); + free(newstr); } } /* - * We have to do some strange processing here because the - * hypervisor's serial ports default to "9600,8,n,1,-" if - * "comX=auto" is specified, or to "auto" if nothing is - * specified. + * We have to do some strange processing here because the hypervisor's + * serial ports default to "9600,8,n,1,-" if "comX=auto" is specified, + * or to "auto" if nothing is specified. * - * Since there could be entries in the bootenv.rc file that - * set the serial port to some other setting, when converting - * a hypervisor entry to a metal entry we must force the - * serial ports to their defaults. + * This could result in a serial mode setting string being added when + * it would otherwise not be needed, but it's better to play it safe. */ - if (emit_bflag) { newstr = append_str(kernel, BFLAG, " "); free(kernel); @@ -1180,19 +1187,37 @@ emit_bflag = 0; } - if (serial_config[0] != NULL) - newstr = append_str(kernel, serial_config[0], delim); - else - newstr = append_str(kernel, "ttya-mode='9600,8,n,1,-'", delim); + if ((serial_config[0] != NULL) && (bootenv_rc_serial[0] == NULL || + (strcmp(serial_config[0], bootenv_rc_serial[0]) != 0))) { + newstr = append_str(kernel, "ttya-mode='", delim); + free(kernel); - free(kernel); + /* + * Pass the serial configuration as the delimiter to + * append_str() as it will be inserted between the current + * string and the string we're appending, in this case the + * closing single quote. + */ + kernel = append_str(newstr, "'", serial_config[0]); + free(newstr); + delim = ","; + } - if (serial_config[1] != NULL) - kernel = append_str(newstr, serial_config[1], ","); - else - kernel = append_str(newstr, "ttyb-mode='9600,8,n,1,-'", ","); + if ((serial_config[1] != NULL) && (bootenv_rc_serial[1] == NULL || + (strcmp(serial_config[1], bootenv_rc_serial[1]) != 0))) { + newstr = append_str(kernel, "ttyb-mode='", delim); + free(kernel); - free(newstr); + /* + * Pass the serial configuration as the delimiter to + * append_str() as it will be inserted between the current + * string and the string we're appending, in this case the + * closing single quote. + */ + kernel = append_str(newstr, "'", serial_config[1]); + free(newstr); + delim = ","; + } /* shut off warning messages from the entry line parser */ if (ent->flags & BAM_ENTRY_BOOTADM) @@ -1201,25 +1226,29 @@ BAM_DPRINTF((D_CVT_CMD_KERN_DOLLAR, fcn, kernel)); BAM_DPRINTF((D_CVT_CMD_MOD_DOLLAR, fcn, module)); + if ((newdef = add_boot_entry(mp, title, findroot, kernel, NULL, + barchive_path, bootfs)) == BAM_ERROR) { + free(kernel); + return (newdef); + } + /* * Now try to delete the current default entry from the menu and add * the new hypervisor entry with the parameters we've setup. */ - if (delete_boot_entry(mp, curdef, DBE_QUIET) != BAM_SUCCESS) + if (delete_boot_entry(mp, curdef, DBE_QUIET) == BAM_SUCCESS) + newdef--; + else bam_print(NEW_BOOT_ENTRY, title); - curdef = add_boot_entry(mp, title, findroot, kernel, NULL, - barchive_path, bootfs); + free(kernel); /* * If we successfully created the new entry, set the default boot * entry to that entry and let the caller know the new menu should * be written out. */ - if (curdef != BAM_ERROR) - return (set_global(mp, menu_cmds[DEFAULT_CMD], curdef)); - - return (BAM_ERROR); + return (set_global(mp, menu_cmds[DEFAULT_CMD], newdef)); abort: if (ret != BAM_NOCHANGE)