bootadm_hyper.c revision 772d6a58e8b646d197debb720cdea7723d5892d8
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * Append the string pointed to by "str" to the string pointed to by "orig" 2N/A * adding the delimeter "delim" in between. 2N/A * Return a pointer to the new string or NULL, if we were passed a bad string. 2N/A * Return a pointer to a copy of the path so a caller can 2N/A * always rely upon being able to free() a returned pointer. 2N/A * Replace the substring "old_str" in a path with the substring "new_str" 2N/A * Return a pointer to the modified string. 2N/A * Return a pointer to a copy of the path so a caller can always rely 2N/A * upon being able to free() a returned pointer. 2N/A * Allocate space for duplicate of path with name changes and 2N/A * NULL terminating byte 2N/A * Set "token" to be the the string starting from the pointer "str" delimited 2N/A * by any character in the string "delim" or the end of the string, but IGNORE 2N/A * any characters between single or double quotes. 2N/A * Return a pointer to the next non-whitespace character after the delimiter 2N/A * or NULL if we hit the end of the string. Also return NULL upon failure to 2N/A * find any characters from the delimeter string or upon failure to allocate 2N/A * memory for the new token string. 2N/A /* no matching quote found in string */ 2N/A /* look for a character from the delimiter string */ 2N/A /* found a delimiter, so create a token string */ 2N/A /* if we hit the end of the string, the token is the whole string */ 2N/A * Convert a metal "console" device name to an equivalent one suitable for 2N/A * use with the hypervisor. 2N/A * Default to "vga" if we can't parse the console device. 2N/A * If rate is a NULL pointer, erase any existing serial configuration 2N/A * for this serial port. 2N/A * Convert "metal" serial port parameters to values compatible with the 2N/A * Return 0 on success, otherwise -1. 2N/A * Check if it's specified as the default rate; if so it defaults to 2N/A * "auto" and we need not set it for they hypervisor. 2N/A if (
sscanf(
metal_serial,
"%u,%u,%c,%u,%c", &
baud, &
bits, &
parity, &
stop,
2N/A /* validate serial port parameters */ 2N/A /* validate baud rate */ 2N/A * The hypervisor has no way to specify a handshake method, so it gets 2N/A * quietly dropped in the conversion. 2N/A * Convert "name=value" metal options to values suitable for use with the 2N/A * Our main concerns are the console device and serial port settings. 2N/A * -1: Unparseable line 2N/A * (n > 0): A property unimportant to us 2N/A * Convert "name=value" properties for use with a bare metal kernel 2N/A * Our main concerns are the console setting and serial port modes. 2N/A * -1: Unparseable line 2N/A * (n > 0): A property unimportant to us 2N/A#
define SER_LEN 15 /* strlen("115200,8,n,1,-") + 1 */ 2N/A * If there's no "=" in the token, it's likely a standalone 2N/A * hypervisor token we don't care about (e.g. "noreboot" or 2N/A * "nosmp") so we ignore it. 2N/A * Note that we use strncmp against the values because the 2N/A * hypervisor allows setting console parameters for both the 2N/A * console and debugger via the format: 2N/A * console=cons_dev,debug_dev 2N/A * and we only care about "cons_dev." 2N/A * This also allows us to extract "comN" from hypervisor constructs 2N/A * like "com1H" or "com2L," concepts unsupported on bare metal kernels. 2N/A * Default the console device to "text" if it was "vga" or was 2N/A /* ignore the "console=hypervisor" option */ 2N/A /* serial port parameter conversion */ 2N/A * Check if it's "auto" - if so, use the default setting 2N/A * of "9600,8,n,1,-". 2N/A * We can't just assume the serial port will default to 2N/A * "9600,8,n,1" as there could be a directive in bootenv.rc 2N/A * that would set it to some other value and we want the serial 2N/A * parameters to be the same as that used by the hypervisor. 2N/A * Extract the "B,PS" setting from the com line; ignore 2N/A * other settings like io_base or IRQ. 2N/A /* validate serial port parameters */ 2N/A /* validate baud rate */ 2N/A * As the hypervisor has no way to denote handshaking 2N/A * in its serial port settings, emit a metal serial 2N/A * port configuration with none as well. 2N/A * Parse a hardware kernel's "kernel$" specifier into parameters we can then 2N/A * use to construct an appropriate "module$" line that can be used to specify 2N/A * how to boot the hypervisor's dom0. 2N/A * -1: error parsing kernel path 2N/A * 1: kernel already a hypervisor kernel 2N/A * If the metal kernel specified contains the name of the hypervisor, 2N/A * we're probably trying to convert an entry already setup to run the 2N/A * hypervisor, so error out now. 2N/A /* if the path was the last item on the line, that's OK. */ 2N/A /* if the next token is "-B" process boot options */ 2N/A * Parse a hypervisor's "kernel$" line into parameters that can be used to 2N/A * help build an appropriate "kernel$" line for booting a bare metal kernel. 2N/A * Return 0 on success, non-zero on failure. 2N/A * If the hypervisor kernel specified lives in the metal kernel 2N/A * directory, we're probably trying to convert an entry already setup 2N/A * to run on bare metal, so error out now. 2N/A /* check for kernel options */ 2N/A * Parse a hypervisor's "module$" line into parameters that can be used to 2N/A * help build an appropriate "kernel$" line for booting a bare metal kernel. 2N/A * If multiple pathnames exist on the module$ line, we just want 2N/A /* if the path was the last item on the line, that's OK. */ 2N/A /* check for "-B" option */ 2N/A /* check for kernel options */ 2N/A /* if we couldn't open the bootenv.rc file, ignore the issue. */ 2N/A /* we're only interested in parsing "setprop" directives. */ 2N/A /* eat initial "setprop" */ 2N/A /* get property name */ 2N/A /* get console property value */ 2N/A /* check if it's a serial port setting */ 2N/A /* nope, so check the next line */ 2N/A /* get serial port setting */ 2N/A const char *
fcn =
"cvt_to_hyper()";
2N/A * First just check to verify osroot is a sane directory. 2N/A * While the effect is purely cosmetic, if osroot is "/" don't 2N/A * bother prepending it to any paths as they are constructed to 2N/A * begin with "/" anyway. 2N/A * Found the GRUB signature on the target partitions, so now get the 2N/A * default GRUB boot entry number from the menu.lst file 2N/A /* look for the first line of the matching boot entry */ 2N/A /* couldn't find it, so error out */ 2N/A * We found the proper menu entry, so first we need to process the 2N/A * bootenv.rc file to look for boot options the hypervisor might need 2N/A * passed as kernel start options such as the console device and serial 2N/A * If there's no bootenv.rc, it's not an issue. 2N/A * Now process the entry itself. 2N/A * Process important lines from menu.lst boot entry. 2N/A * If findroot, module or kern_path are NULL, the boot entry is 2N/A /* assemble new kernel and module arguments from parsed values */ 2N/A * Change the kernel directory from the metal version to that needed for 2N/A * the hypervisor. Convert either "direct boot" path to the default 2N/A * We need to allocate space for the kernel path (twice) plus an 2N/A * intervening space, possibly the ZFS boot string, and NULL, 2N/A /* shut off warning messages from the entry line parser */ 2N/A * Now try to delete the current default entry from the menu and add 2N/A * the new hypervisor entry with the parameters we've setup. 2N/A * If we successfully created the new entry, set the default boot 2N/A * entry to that entry and let the caller know the new menu should 2N/A const char *
fcn =
"cvt_to_metal()";
2N/A * First just check to verify osroot is a sane directory. 2N/A * Found the GRUB signature on the target partitions, so now get the 2N/A * default GRUB boot entry number from the menu.lst file 2N/A /* look for the first line of the matching boot entry */ 2N/A /* couldn't find it, so error out */ 2N/A * Now process the entry itself. 2N/A * Process important lines from menu.lst boot entry. 2N/A * If findroot, module or kern_path are NULL, the boot entry is 2N/A * Assemble new kernel and module arguments from parsed values. 2N/A * First, change the kernel directory from the hypervisor version to 2N/A * that needed for a metal kernel. 2N/A /* allocate initial space for the kernel path */ 2N/A * Process the bootenv.rc file to look for boot options that would be 2N/A * the same as what the hypervisor had manually set, as we need not set 2N/A * If there's no bootenv.rc, it's not an issue. 2N/A * Don't emit a console setting if it's the same as what would be 2N/A * set by bootenv.rc. 2N/A * We have to do some strange processing here because the hypervisor's 2N/A * serial ports default to "9600,8,n,1,-" if "comX=auto" is specified, 2N/A * or to "auto" if nothing is specified. 2N/A * This could result in a serial mode setting string being added when 2N/A * it would otherwise not be needed, but it's better to play it safe. 2N/A * Pass the serial configuration as the delimiter to 2N/A * append_str() as it will be inserted between the current 2N/A * string and the string we're appending, in this case the 2N/A * closing single quote. 2N/A * Pass the serial configuration as the delimiter to 2N/A * append_str() as it will be inserted between the current 2N/A * string and the string we're appending, in this case the 2N/A * closing single quote. 2N/A /* shut off warning messages from the entry line parser */ 2N/A * Now try to delete the current default entry from the menu and add 2N/A * the new hypervisor entry with the parameters we've setup. 2N/A * If we successfully created the new entry, set the default boot 2N/A * entry to that entry and let the caller know the new menu should