Home | History | Annotate | Download | only in bootadm
      1   3446      mrj /*
      2   3446      mrj  * CDDL HEADER START
      3   3446      mrj  *
      4   3446      mrj  * The contents of this file are subject to the terms of the
      5   3446      mrj  * Common Development and Distribution License (the "License").
      6   3446      mrj  * You may not use this file except in compliance with the License.
      7   3446      mrj  *
      8   3446      mrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9   3446      mrj  * or http://www.opensolaris.org/os/licensing.
     10   3446      mrj  * See the License for the specific language governing permissions
     11   3446      mrj  * and limitations under the License.
     12   3446      mrj  *
     13   3446      mrj  * When distributing Covered Code, include this CDDL HEADER in each
     14   3446      mrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15   3446      mrj  * If applicable, add the following below this CDDL HEADER, with the
     16   3446      mrj  * fields enclosed by brackets "[]" replaced with your own identifying
     17   3446      mrj  * information: Portions Copyright [yyyy] [name of copyright owner]
     18   3446      mrj  *
     19   3446      mrj  * CDDL HEADER END
     20   3446      mrj  */
     21   3446      mrj /*
     22  10405    Frank  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23   3446      mrj  * Use is subject to license terms.
     24   3446      mrj  */
     25   3446      mrj 
     26   3446      mrj #include <stdio.h>
     27   3446      mrj #include <errno.h>
     28   3446      mrj #include <stdlib.h>
     29   3446      mrj #include <string.h>
     30   3446      mrj #include <unistd.h>
     31   3446      mrj #include <sys/types.h>
     32   3446      mrj #include <sys/stat.h>
     33   3446      mrj #include <limits.h>
     34   3446      mrj #include <fcntl.h>
     35   3446      mrj #include <strings.h>
     36   3446      mrj 
     37   3446      mrj #include <sys/mman.h>
     38   3446      mrj #include <sys/elf.h>
     39   3446      mrj #include <sys/multiboot.h>
     40   3446      mrj 
     41   3446      mrj #include "message.h"
     42   3446      mrj #include "bootadm.h"
     43   3446      mrj 
     44   3446      mrj direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET;
     45   5084  johnlev hv_t bam_is_hv = BAM_HV_UNKNOWN;
     46   6448   vikram findroot_t bam_is_findroot = BAM_FINDROOT_UNKNOWN;
     47   6448   vikram 
     48   6448   vikram static void
     49   6448   vikram get_findroot_cap(const char *osroot)
     50   6448   vikram {
     51   6448   vikram 	FILE		*fp;
     52   6448   vikram 	char		path[PATH_MAX];
     53   6448   vikram 	char		buf[BAM_MAXLINE];
     54   6448   vikram 	struct stat	sb;
     55   6448   vikram 	int		dboot;
     56   6448   vikram 	int		error;
     57   6448   vikram 	int		ret;
     58   6448   vikram 	const char	*fcn = "get_findroot_cap()";
     59   6448   vikram 
     60   6448   vikram 	assert(is_grub(osroot));
     61   6448   vikram 
     62   6448   vikram 	(void) snprintf(path, sizeof (path), "%s/%s",
     63   6448   vikram 	    osroot, "boot/grub/capability");
     64   6448   vikram 
     65   6448   vikram 	if (stat(path, &sb) == -1) {
     66   6448   vikram 		bam_is_findroot = BAM_FINDROOT_ABSENT;
     67   6448   vikram 		BAM_DPRINTF((D_FINDROOT_ABSENT, fcn));
     68   6448   vikram 		return;
     69   6448   vikram 	}
     70   6448   vikram 
     71   6448   vikram 	fp = fopen(path, "r");
     72   6448   vikram 	error = errno;
     73   6448   vikram 	INJECT_ERROR1("GET_CAP_FINDROOT_FOPEN", fp = NULL);
     74   6448   vikram 	if (fp == NULL) {
     75   6448   vikram 		bam_error(OPEN_FAIL, path, strerror(error));
     76   6448   vikram 		return;
     77   6448   vikram 	}
     78   6448   vikram 
     79  10405    Frank 	dboot = 0;
     80   6448   vikram 	while (s_fgets(buf, sizeof (buf), fp) != NULL) {
     81   6448   vikram 		if (strcmp(buf, "findroot") == 0) {
     82   6448   vikram 			BAM_DPRINTF((D_FINDROOT_PRESENT, fcn));
     83   6448   vikram 			bam_is_findroot = BAM_FINDROOT_PRESENT;
     84   6448   vikram 		}
     85   6448   vikram 		if (strcmp(buf, "dboot") == 0) {
     86   6448   vikram 			BAM_DPRINTF((D_DBOOT_PRESENT, fcn));
     87   6448   vikram 			dboot = 1;
     88   6448   vikram 		}
     89   6448   vikram 	}
     90   6448   vikram 
     91   6448   vikram 	assert(dboot);
     92   6448   vikram 
     93   6448   vikram 	if (bam_is_findroot == BAM_FINDROOT_UNKNOWN) {
     94   6448   vikram 		bam_is_findroot = BAM_FINDROOT_ABSENT;
     95   6448   vikram 		BAM_DPRINTF((D_FINDROOT_ABSENT, fcn));
     96   6448   vikram 	}
     97   6448   vikram out:
     98   6448   vikram 	ret = fclose(fp);
     99   6448   vikram 	error = errno;
    100   6448   vikram 	INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret = 1);
    101   6448   vikram 	if (ret != 0) {
    102   6448   vikram 		bam_error(CLOSE_FAIL, path, strerror(error));
    103   6448   vikram 	}
    104   6448   vikram }
    105   3446      mrj 
    106   3446      mrj error_t
    107   6448   vikram get_boot_cap(const char *osroot)
    108   3446      mrj {
    109   6448   vikram 	char		fname[PATH_MAX];
    110   6448   vikram 	char		*image;
    111   6448   vikram 	uchar_t		*ident;
    112   6448   vikram 	int		fd;
    113   6448   vikram 	int		m;
    114   3446      mrj 	multiboot_header_t *mbh;
    115   6448   vikram 	struct stat	sb;
    116   6448   vikram 	int		error;
    117   6448   vikram 	const char	*fcn = "get_boot_cap()";
    118   5648    setje 
    119   6448   vikram 	if (is_sparc()) {
    120   5648    setje 		/* there is no non dboot sparc new-boot */
    121   5648    setje 		bam_direct = BAM_DIRECT_DBOOT;
    122   6448   vikram 		BAM_DPRINTF((D_IS_SPARC_DBOOT, fcn));
    123   5648    setje 		return (BAM_SUCCESS);
    124   5648    setje 	}
    125   3446      mrj 
    126   6448   vikram 	if (!is_grub(osroot)) {
    127   6448   vikram 		bam_error(NOT_GRUB_ROOT, osroot);
    128   6448   vikram 		return (BAM_ERROR);
    129   6448   vikram 	}
    130   6448   vikram 
    131   6448   vikram 	(void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
    132   3446      mrj 	    "platform/i86pc/kernel/unix");
    133   3446      mrj 	fd = open(fname, O_RDONLY);
    134   6448   vikram 	error = errno;
    135   6448   vikram 	INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd = -1);
    136   3446      mrj 	if (fd < 0) {
    137   6448   vikram 		bam_error(OPEN_FAIL, fname, strerror(error));
    138   6448   vikram 		return (BAM_ERROR);
    139   6448   vikram 	}
    140   6448   vikram 
    141   6448   vikram 	/*
    142   6448   vikram 	 * Verify that this is a sane unix at least 8192 bytes in length
    143   6448   vikram 	 */
    144   6448   vikram 	if (fstat(fd, &sb) == -1 || sb.st_size < 8192) {
    145   6448   vikram 		(void) close(fd);
    146   6448   vikram 		bam_error(INVALID_BINARY, fname);
    147   3446      mrj 		return (BAM_ERROR);
    148   3446      mrj 	}
    149   3446      mrj 
    150   3446      mrj 	/*
    151   3446      mrj 	 * mmap the first 8K
    152   3446      mrj 	 */
    153   3446      mrj 	image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0);
    154   6448   vikram 	error = errno;
    155   6448   vikram 	INJECT_ERROR1("GET_CAP_MMAP", image = MAP_FAILED);
    156   3446      mrj 	if (image == MAP_FAILED) {
    157   6448   vikram 		bam_error(MMAP_FAIL, fname, strerror(error));
    158   3446      mrj 		return (BAM_ERROR);
    159   3446      mrj 	}
    160   3446      mrj 
    161   3446      mrj 	ident = (uchar_t *)image;
    162   3446      mrj 	if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
    163   3446      mrj 	    ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
    164   3446      mrj 		bam_error(NOT_ELF_FILE, fname);
    165   3446      mrj 		return (BAM_ERROR);
    166   3446      mrj 	}
    167   3446      mrj 	if (ident[EI_CLASS] != ELFCLASS32) {
    168   3446      mrj 		bam_error(WRONG_ELF_CLASS, fname, ident[EI_CLASS]);
    169   3446      mrj 		return (BAM_ERROR);
    170   3446      mrj 	}
    171   3446      mrj 
    172   3446      mrj 	/*
    173   3446      mrj 	 * The GRUB multiboot header must be 32-bit aligned and completely
    174   3446      mrj 	 * contained in the 1st 8K of the file.  If the unix binary has
    175   3446      mrj 	 * a multiboot header, then it is a 'dboot' kernel.  Otherwise,
    176   3446      mrj 	 * this kernel must be booted via multiboot -- we call this a
    177   3446      mrj 	 * 'multiboot' kernel.
    178   3446      mrj 	 */
    179   3446      mrj 	bam_direct = BAM_DIRECT_MULTIBOOT;
    180   3446      mrj 	for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) {
    181   3446      mrj 		mbh = (void *)(image + m);
    182   3446      mrj 		if (mbh->magic == MB_HEADER_MAGIC) {
    183   6448   vikram 			BAM_DPRINTF((D_IS_DBOOT, fcn));
    184   3446      mrj 			bam_direct = BAM_DIRECT_DBOOT;
    185   3446      mrj 			break;
    186   3446      mrj 		}
    187   3446      mrj 	}
    188   3446      mrj 	(void) munmap(image, 8192);
    189   3446      mrj 	(void) close(fd);
    190   5084  johnlev 
    191   6448   vikram 	INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct = BAM_DIRECT_MULTIBOOT);
    192   5084  johnlev 	if (bam_direct == BAM_DIRECT_DBOOT) {
    193  10405    Frank 		if (bam_is_hv == BAM_HV_PRESENT) {
    194   6448   vikram 			BAM_DPRINTF((D_IS_XVM, fcn));
    195   5084  johnlev 		} else {
    196   6448   vikram 			BAM_DPRINTF((D_IS_NOT_XVM, fcn));
    197   5084  johnlev 		}
    198   6448   vikram 	} else {
    199   6448   vikram 		BAM_DPRINTF((D_IS_MULTIBOOT, fcn));
    200   5084  johnlev 	}
    201   5084  johnlev 
    202   6448   vikram 	/* Not a fatal error if this fails */
    203   6448   vikram 	get_findroot_cap(osroot);
    204   6448   vikram 
    205   6448   vikram 	BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
    206   3446      mrj 	return (BAM_SUCCESS);
    207   3446      mrj }
    208   3446      mrj 
    209   3446      mrj #define	INST_RELEASE	"var/sadm/system/admin/INST_RELEASE"
    210   3446      mrj 
    211   3446      mrj /*
    212   3446      mrj  * Return true if root has been bfu'ed.  bfu will blow away
    213   3446      mrj  * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
    214   3446      mrj  * assume the system has not been bfu'ed.
    215   3446      mrj  */
    216   3446      mrj static int
    217   3446      mrj is_bfu_system(const char *root)
    218   3446      mrj {
    219   6448   vikram 	static int		is_bfu = -1;
    220   6448   vikram 	char			path[PATH_MAX];
    221   6448   vikram 	struct stat		sb;
    222   6448   vikram 	const char		*fcn = "is_bfu_system()";
    223   3446      mrj 
    224   6448   vikram 	if (is_bfu != -1) {
    225   6448   vikram 		BAM_DPRINTF((D_ALREADY_BFU_TEST, fcn, is_bfu ? "" : "NOT"));
    226   3446      mrj 		return (is_bfu);
    227   6448   vikram 	}
    228   3446      mrj 
    229   3446      mrj 	(void) snprintf(path, sizeof (path), "%s/%s", root, INST_RELEASE);
    230   3446      mrj 	if (stat(path, &sb) != 0) {
    231   3446      mrj 		is_bfu = 1;
    232   6448   vikram 		BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
    233   3446      mrj 	} else {
    234   3446      mrj 		is_bfu = 0;
    235   6448   vikram 		BAM_DPRINTF((D_RETURN_FAILURE, fcn));
    236   3446      mrj 	}
    237   3446      mrj 	return (is_bfu);
    238   3446      mrj }
    239   3446      mrj 
    240   3446      mrj #define	MENU_URL(root)	(is_bfu_system(root) ?		\
    241   3446      mrj 	"http://www.sun.com/msg/SUNOS-8000-CF" :	\
    242   3446      mrj 	"http://www.sun.com/msg/SUNOS-8000-AK")
    243   3446      mrj 
    244   3446      mrj /*
    245   3446      mrj  * Simply allocate a new line and copy in cmd + sep + arg
    246   3446      mrj  */
    247   3446      mrj void
    248   3446      mrj update_line(line_t *linep)
    249   3446      mrj {
    250   6448   vikram 	size_t		size;
    251   6448   vikram 	const char	*fcn = "update_line()";
    252   3446      mrj 
    253   6448   vikram 	BAM_DPRINTF((D_UPDATE_LINE_BEFORE, fcn, linep->line));
    254   3446      mrj 	free(linep->line);
    255   3446      mrj 	size = strlen(linep->cmd) + strlen(linep->sep) + strlen(linep->arg) + 1;
    256   3446      mrj 	linep->line = s_calloc(1, size);
    257   3446      mrj 	(void) snprintf(linep->line, size, "%s%s%s", linep->cmd, linep->sep,
    258   3446      mrj 	    linep->arg);
    259   6448   vikram 	BAM_DPRINTF((D_UPDATE_LINE_AFTER, fcn, linep->line));
    260   6448   vikram }
    261   6448   vikram 
    262   6448   vikram static char *
    263   6448   vikram skip_wspace(char *ptr)
    264   6448   vikram {
    265   6448   vikram 	const char		*fcn = "skip_wspace()";
    266   6448   vikram 
    267   6448   vikram 	INJECT_ERROR1("SKIP_WSPACE", ptr = NULL);
    268   6448   vikram 	if (ptr == NULL) {
    269   6448   vikram 		BAM_DPRINTF((D_SKIP_WSPACE_PTR_NULL, fcn));
    270   6448   vikram 		return (NULL);
    271   6448   vikram 	}
    272   6448   vikram 
    273   6448   vikram 	BAM_DPRINTF((D_SKIP_WSPACE_ENTRY_PTR, fcn, ptr));
    274   6448   vikram 	for (; *ptr != '\0'; ptr++) {
    275   6448   vikram 		if ((*ptr != ' ') && (*ptr != '\t') &&
    276   6448   vikram 		    (*ptr != '\n'))
    277   6448   vikram 			break;
    278   6448   vikram 	}
    279   6448   vikram 
    280   6448   vikram 	ptr = (*ptr == '\0' ? NULL : ptr);
    281   6448   vikram 
    282   6448   vikram 	BAM_DPRINTF((D_SKIP_WSPACE_EXIT_PTR, fcn, ptr ? ptr : "NULL"));
    283   6448   vikram 
    284   6448   vikram 	return (ptr);
    285   6448   vikram }
    286   6448   vikram 
    287   6448   vikram static char *
    288   6448   vikram rskip_bspace(char *bound, char *ptr)
    289   6448   vikram {
    290   6448   vikram 	const char		*fcn = "rskip_bspace()";
    291   6448   vikram 	assert(bound);
    292   6448   vikram 	assert(ptr);
    293   6448   vikram 	assert(bound <= ptr);
    294   6448   vikram 	assert(*bound != ' ' && *bound != '\t' && *bound != '\n');
    295   6448   vikram 
    296   6448   vikram 	BAM_DPRINTF((D_RSKIP_BSPACE_ENTRY, fcn, ptr));
    297   6448   vikram 	for (; ptr > bound; ptr--) {
    298   6448   vikram 		if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
    299   6448   vikram 			break;
    300   6448   vikram 	}
    301   6448   vikram 
    302   6448   vikram 	BAM_DPRINTF((D_RSKIP_BSPACE_EXIT, fcn, ptr));
    303   6448   vikram 	return (ptr);
    304   3446      mrj }
    305   3446      mrj 
    306   3446      mrj /*
    307   3446      mrj  * The parse_kernel_line function examines a menu.lst kernel line.  For
    308   3446      mrj  * multiboot, this is:
    309   3446      mrj  *
    310   3446      mrj  * kernel <multiboot path> <flags1> <kernel path> <flags2>
    311   3446      mrj  *
    312   3446      mrj  * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot
    313   3446      mrj  *
    314   3446      mrj  * <kernel path> may be missing, or may be any full or relative path to unix.
    315   3446      mrj  *	We check for it by looking for a word ending in "/unix".  If it ends
    316   3446      mrj  *	in "kernel/unix", we upgrade it to a 32-bit entry.  If it ends in
    317   3446      mrj  *	"kernel/amd64/unix", we upgrade it to the default entry.  Otherwise,
    318   3446      mrj  *	it's a custom kernel, and we skip it.
    319   3446      mrj  *
    320   3446      mrj  * <flags*> are anything that doesn't fit either of the above - these will be
    321   3446      mrj  *	copied over.
    322   3446      mrj  *
    323   3446      mrj  * For direct boot, the defaults are
    324   3446      mrj  *
    325   3446      mrj  * kernel$ <kernel path> <flags>
    326   3446      mrj  *
    327   3446      mrj  * <kernel path> is one of:
    328   3446      mrj  *	/platform/i86pc/kernel/$ISADIR/unix
    329   8104   Enrico  *	/boot/platform/i86pc/kernel/$ISADIR/unix
    330   3446      mrj  *	/platform/i86pc/kernel/unix
    331   3446      mrj  *	/platform/i86pc/kernel/amd64/unix
    332   3446      mrj  *	/boot/platform/i86pc/kernel/unix
    333   8104   Enrico  *	/boot/platform/i86pc/kernel/amd64/unix
    334   3446      mrj  *
    335   8104   Enrico  * If <kernel path> is any of the last four, the command may also be "kernel".
    336   3446      mrj  *
    337   3446      mrj  * <flags> is anything that isn't <kernel path>.
    338   3446      mrj  *
    339   6448   vikram  * This function is only called to convert a multiboot entry to a dboot entry
    340   3446      mrj  *
    341   3446      mrj  * For safety, we do one more check: if the kernel path starts with /boot,
    342   3446      mrj  * we verify that the new kernel exists before changing it.  This is mainly
    343   3446      mrj  * done for bfu, as it may cause the failsafe archives to be a different
    344   3446      mrj  * boot architecture from the newly bfu'ed system.
    345   3446      mrj  */
    346   3446      mrj static error_t
    347   6448   vikram cvt_kernel_line(line_t *line, const char *osroot, entry_t *entry)
    348   3446      mrj {
    349   8104   Enrico 	char		path[PATH_MAX], path_64[PATH_MAX];
    350   6448   vikram 	char		linebuf[PATH_MAX];
    351   6448   vikram 	char		new_arg[PATH_MAX];
    352   8104   Enrico 	struct stat	sb, sb_64;
    353   6448   vikram 	char		*old_ptr;
    354   6448   vikram 	char		*unix_ptr;
    355   6448   vikram 	char		*flags1_ptr;
    356   6448   vikram 	char		*flags2_ptr;
    357   6448   vikram 	const char	*fcn = "cvt_kernel_line()";
    358   3446      mrj 
    359   6448   vikram 	BAM_DPRINTF((D_FUNC_ENTRY2, fcn, line->line, osroot));
    360   3446      mrj 
    361   3446      mrj 	/*
    362   6448   vikram 	 * We only convert multiboot to dboot and nothing else.
    363   3446      mrj 	 */
    364   6448   vikram 	if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) {
    365   6448   vikram 		BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT, fcn));
    366   3446      mrj 		return (BAM_SUCCESS);
    367   3446      mrj 	}
    368   3446      mrj 
    369   6448   vikram 	if (entry->flags & BAM_ENTRY_FAILSAFE) {
    370   3446      mrj 		/*
    371   6448   vikram 		 * We're attempting to change failsafe to dboot.
    372   6448   vikram 		 * In the bfu case, we may not have a dboot failsafe
    373   6448   vikram 		 * kernel i.e. a "unix" under the "/boot" hierarchy.
    374   6448   vikram 		 * If so, just emit a message in verbose mode and
    375   6448   vikram 		 * return success.
    376   3446      mrj 		 */
    377   6448   vikram 		BAM_DPRINTF((D_TRYING_FAILSAFE_CVT_TO_DBOOT, fcn));
    378   6448   vikram 		(void) snprintf(path, PATH_MAX, "%s%s", osroot,
    379   8104   Enrico 		    DIRECT_BOOT_FAILSAFE_32);
    380   8104   Enrico 		(void) snprintf(path_64, PATH_MAX, "%s%s", osroot,
    381   8104   Enrico 		    DIRECT_BOOT_FAILSAFE_64);
    382   8104   Enrico 		if (stat(path, &sb) != 0 && stat(path_64, &sb_64) != 0) {
    383   3446      mrj 			if (bam_verbose) {
    384   6448   vikram 				bam_error(FAILSAFE_MISSING, line->lineNum);
    385   3446      mrj 			}
    386   6448   vikram 			BAM_DPRINTF((D_NO_FAILSAFE_UNIX_CONVERT, fcn));
    387   3446      mrj 			return (BAM_SUCCESS);
    388   3446      mrj 		}
    389   3446      mrj 	}
    390   3446      mrj 
    391   3446      mrj 	/*
    392   8104   Enrico 	 * Make sure we have the correct cmd
    393   3446      mrj 	 */
    394   8104   Enrico 
    395   8104   Enrico 	free(line->cmd);
    396   8104   Enrico 	line->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
    397   8104   Enrico 	BAM_DPRINTF((D_CVT_CMD_KERN_DOLLAR, fcn, line->cmd));
    398   3446      mrj 
    399   6448   vikram 	assert(sizeof (linebuf) > strlen(line->arg) + 32);
    400   6448   vikram 	(void) strlcpy(linebuf, line->arg, sizeof (linebuf));
    401   3446      mrj 
    402   6448   vikram 	old_ptr = strpbrk(linebuf, " \t\n");
    403   6448   vikram 	old_ptr = skip_wspace(old_ptr);
    404   6448   vikram 	if (old_ptr == NULL) {
    405   6448   vikram 		/*
    406   6448   vikram 		 * only multiboot and nothing else
    407   6448   vikram 		 * i.e. flags1 = unix = flags2 = NULL
    408   6448   vikram 		 */
    409   6448   vikram 		flags1_ptr = unix_ptr = flags2_ptr = NULL;
    410   6448   vikram 		BAM_DPRINTF((D_FLAGS1_UNIX_FLAGS2_NULL, fcn))
    411   6448   vikram 		goto create;
    412   3446      mrj 	}
    413   3446      mrj 
    414   3446      mrj 	/*
    415   3446      mrj 	 *
    416   6448   vikram 	 * old_ptr is either at "flags1" or "unix"
    417   3446      mrj 	 */
    418   6448   vikram 	if (unix_ptr = strstr(old_ptr, "/unix")) {
    419   6448   vikram 
    420   6448   vikram 		/*
    421   6448   vikram 		 * There is a  unix.
    422   6448   vikram 		 */
    423   6448   vikram 		BAM_DPRINTF((D_UNIX_PRESENT, fcn));
    424   6448   vikram 
    425   6448   vikram 		/* See if there's a flags2 past unix */
    426   6448   vikram 		flags2_ptr = unix_ptr + strlen("/unix");
    427   6448   vikram 		flags2_ptr = skip_wspace(flags2_ptr);
    428   6448   vikram 		if (flags2_ptr) {
    429   6448   vikram 			BAM_DPRINTF((D_FLAGS2_PRESENT, fcn, flags2_ptr));
    430   6448   vikram 		} else {
    431   6448   vikram 			BAM_DPRINTF((D_FLAGS2_ABSENT, fcn));
    432   3446      mrj 		}
    433   3446      mrj 
    434   6448   vikram 		/* see if there is a flags1 before unix */
    435   6448   vikram 		unix_ptr = rskip_bspace(old_ptr, unix_ptr);
    436   3446      mrj 
    437   3446      mrj 		if (unix_ptr == old_ptr) {
    438   3446      mrj 			flags1_ptr = NULL;
    439   6448   vikram 			BAM_DPRINTF((D_FLAGS1_ABSENT, fcn));
    440   3446      mrj 		} else {
    441   3446      mrj 			flags1_ptr = old_ptr;
    442   6448   vikram 			*unix_ptr = '\0';
    443   6448   vikram 			unix_ptr++;
    444   6448   vikram 			BAM_DPRINTF((D_FLAGS1_PRESENT, fcn, flags1_ptr));
    445   3446      mrj 		}
    446   3446      mrj 
    447   6448   vikram 	} else  {
    448   6448   vikram 		/* There is no unix, there is only a bunch of flags */
    449   3446      mrj 		flags1_ptr = old_ptr;
    450   6448   vikram 		unix_ptr = flags2_ptr = NULL;
    451   6448   vikram 		BAM_DPRINTF((D_FLAGS1_ONLY, fcn, flags1_ptr));
    452   3446      mrj 	}
    453   3446      mrj 
    454   3446      mrj 	/*
    455   6448   vikram 	 * With dboot, unix is fixed and is at the beginning. We need to
    456   6448   vikram 	 * migrate flags1 and flags2
    457   3446      mrj 	 */
    458   6448   vikram create:
    459   6448   vikram 	if (entry->flags & BAM_ENTRY_FAILSAFE) {
    460   6448   vikram 		(void) snprintf(new_arg, sizeof (new_arg), "%s",
    461   6448   vikram 		    DIRECT_BOOT_FAILSAFE_KERNEL);
    462   6448   vikram 	} else {
    463   6448   vikram 		(void) snprintf(new_arg, sizeof (new_arg), "%s",
    464   6448   vikram 		    DIRECT_BOOT_KERNEL);
    465   6448   vikram 	}
    466   6448   vikram 	BAM_DPRINTF((D_CVTED_UNIX, fcn, new_arg));
    467   6448   vikram 
    468   3446      mrj 	if (flags1_ptr != NULL) {
    469   6448   vikram 		(void) strlcat(new_arg, " ", sizeof (new_arg));
    470   6448   vikram 		(void) strlcat(new_arg, flags1_ptr, sizeof (new_arg));
    471   3446      mrj 	}
    472   3446      mrj 
    473   6448   vikram 	if (flags2_ptr != NULL) {
    474   6448   vikram 		(void) strlcat(new_arg, " ", sizeof (new_arg));
    475   6448   vikram 		(void) strlcat(new_arg, flags2_ptr, sizeof (new_arg));
    476   6448   vikram 	}
    477   6448   vikram 
    478   6448   vikram 	BAM_DPRINTF((D_CVTED_UNIX_AND_FLAGS, fcn, new_arg));
    479   6448   vikram 
    480   6448   vikram 	free(line->arg);
    481   6448   vikram 	line->arg = s_strdup(new_arg);
    482   6448   vikram 	update_line(line);
    483   6448   vikram 	BAM_DPRINTF((D_CVTED_KERNEL_LINE, fcn, line->line));
    484   3446      mrj 	return (BAM_SUCCESS);
    485   3446      mrj }
    486   3446      mrj 
    487   3446      mrj /*
    488   3446      mrj  * Similar to above, except this time we're looking at a module line,
    489   3446      mrj  * which is quite a bit simpler.
    490   3446      mrj  *
    491   3446      mrj  * Under multiboot, the archive line is:
    492   3446      mrj  *
    493   3446      mrj  * module /platform/i86pc/boot_archive
    494   3446      mrj  *
    495   3446      mrj  * Under directboot, the archive line is:
    496   3446      mrj  *
    497   3446      mrj  * module$ /platform/i86pc/$ISADIR/boot_archive
    498   3446      mrj  *
    499   3446      mrj  * which may be specified exactly as either of:
    500   3446      mrj  *
    501   3446      mrj  * module /platform/i86pc/boot_archive
    502   3446      mrj  * module /platform/i86pc/amd64/boot_archive
    503   3446      mrj  *
    504   8104   Enrico  * Under multiboot, the failsafe is:
    505   3446      mrj  *
    506   3446      mrj  * module /boot/x86.miniroot-safe
    507   8104   Enrico  *
    508   8104   Enrico  * Under dboot, the failsafe is:
    509   8104   Enrico  *
    510   8104   Enrico  * module$ /boot/$ISADIR/x86.miniroot-safe
    511   8104   Enrico  *
    512   8104   Enrico  * which may be specified exactly as either of:
    513   8104   Enrico  *
    514   8104   Enrico  * module /boot/x86.miniroot-safe
    515   8104   Enrico  * module /boot/amd64/x86.miniroot-safe
    516   3446      mrj  */
    517   3446      mrj static error_t
    518   6448   vikram cvt_module_line(line_t *line, entry_t *entry)
    519   3446      mrj {
    520   6448   vikram 	const char		*fcn = "cvt_module_line()";
    521   6448   vikram 
    522   6448   vikram 	BAM_DPRINTF((D_FUNC_ENTRY1, fcn, line->line));
    523   3446      mrj 
    524   3446      mrj 	/*
    525   6448   vikram 	 * We only convert multiboot to dboot and nothing else
    526   3446      mrj 	 */
    527   6448   vikram 	if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) {
    528   6448   vikram 		BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT, fcn));
    529   3446      mrj 		return (BAM_SUCCESS);
    530   3446      mrj 	}
    531   3446      mrj 
    532   6448   vikram 	if (entry->flags & BAM_ENTRY_FAILSAFE) {
    533   6448   vikram 		if (strcmp(line->arg, FAILSAFE_ARCHIVE) == 0) {
    534   6448   vikram 			BAM_DPRINTF((D_FAILSAFE_NO_CVT_NEEDED, fcn, line->arg));
    535   6448   vikram 			BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
    536   6448   vikram 			return (BAM_SUCCESS);
    537   6448   vikram 		}
    538   6448   vikram 	} else if (strcmp(line->arg, MULTIBOOT_ARCHIVE) != 0) {
    539   6448   vikram 		bam_error(UNKNOWN_MODULE_LINE, line->lineNum);
    540   6448   vikram 		BAM_DPRINTF((D_RETURN_FAILURE, fcn));
    541   6448   vikram 		return (BAM_MSG);
    542   3446      mrj 	}
    543   3446      mrj 
    544   8104   Enrico 	free(line->cmd);
    545   8104   Enrico 	free(line->arg);
    546   8104   Enrico 	line->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]);
    547   8104   Enrico 
    548   8104   Enrico 	line->arg = s_strdup(entry->flags & BAM_ENTRY_FAILSAFE ?
    549   8104   Enrico 	    FAILSAFE_ARCHIVE : DIRECT_BOOT_ARCHIVE);
    550   6448   vikram 
    551   6448   vikram 	update_line(line);
    552   6448   vikram 	BAM_DPRINTF((D_CVTED_MODULE, fcn, line->line));
    553   6448   vikram 	BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
    554   6448   vikram 	return (BAM_SUCCESS);
    555   6448   vikram }
    556   6448   vikram 
    557   6448   vikram static void
    558   6448   vikram bam_warn_hand_entries(menu_t *mp, char *osroot)
    559   6448   vikram {
    560   6448   vikram 	int		hand_num;
    561   6448   vikram 	int		hand_max;
    562   6448   vikram 	int		*hand_list;
    563   6448   vikram 	int		i;
    564   6448   vikram 	entry_t		*entry;
    565   6448   vikram 	const char	*fcn = "bam_warn_hand_entries()";
    566   6448   vikram 
    567   6448   vikram 	if (bam_force) {
    568   6448   vikram 		/*
    569   6448   vikram 		 * No warning needed, we are automatically converting
    570   6448   vikram 		 * the "hand" entries
    571   6448   vikram 		 */
    572   6448   vikram 		BAM_DPRINTF((D_FORCE_HAND_CVT,  fcn));
    573   6448   vikram 		return;
    574   6448   vikram 	}
    575   6448   vikram 
    576   6448   vikram 	hand_num = 0;
    577   6448   vikram 	hand_max = BAM_ENTRY_NUM;
    578   6448   vikram 	hand_list = s_calloc(1, hand_max);
    579   6448   vikram 
    580   6448   vikram 	for (entry = mp->entries; entry; entry = entry->next) {
    581   6448   vikram 		if (entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))
    582   6448   vikram 			continue;
    583   6448   vikram 		BAM_DPRINTF((D_FOUND_HAND, fcn, entry->entryNum));
    584   6448   vikram 		if (++hand_num > hand_max) {
    585   6448   vikram 			hand_max *= 2;
    586   6448   vikram 			hand_list = s_realloc(hand_list,
    587   6448   vikram 			    hand_max * sizeof (int));
    588   6448   vikram 		}
    589   6448   vikram 		hand_list[hand_num - 1] = entry->entryNum;
    590   6448   vikram 	}
    591   6448   vikram 
    592   6448   vikram 	bam_error(HAND_ADDED_ENTRIES, osroot, MENU_URL(osroot));
    593   6448   vikram 	bam_print_stderr("Entry Number%s: ", (hand_num > 1) ?
    594   6448   vikram 	    "s" : "");
    595   6448   vikram 	for (i = 0; i < hand_num; i++) {
    596   6448   vikram 		bam_print_stderr("%d ", hand_list[i]);
    597   6448   vikram 	}
    598   6448   vikram 	bam_print_stderr("\n");
    599   6448   vikram }
    600   6448   vikram 
    601   6448   vikram static entry_t *
    602   6448   vikram find_matching_entry(
    603   6448   vikram 	entry_t *estart,
    604   6448   vikram 	char *grubsign,
    605   6448   vikram 	char *grubroot,
    606   6448   vikram 	int root_opt)
    607   6448   vikram {
    608   6448   vikram 	entry_t		*entry;
    609   6448   vikram 	line_t		*line;
    610   6448   vikram 	char		opt[10];
    611   6448   vikram 	const char	*fcn = "find_matching_entry()";
    612   6448   vikram 
    613   6448   vikram 	assert(grubsign);
    614   6448   vikram 	assert(root_opt == 0 || root_opt == 1);
    615   6448   vikram 
    616   6448   vikram 	(void) snprintf(opt, sizeof (opt), "%d", root_opt);
    617   6448   vikram 	BAM_DPRINTF((D_FUNC_ENTRY3, fcn, grubsign, grubroot, opt));
    618   6448   vikram 
    619   6448   vikram 	for (entry = estart; entry; entry = entry->next) {
    620   6694   vikram 
    621   6448   vikram 		if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) &&
    622   6448   vikram 		    !bam_force) {
    623   6448   vikram 			BAM_DPRINTF((D_SKIP_ENTRY, fcn, entry->entryNum));
    624   6448   vikram 			continue;
    625   6448   vikram 		}
    626   6448   vikram 
    627   6448   vikram 		if (entry->flags & BAM_ENTRY_ROOT) {
    628   6448   vikram 			for (line = entry->start; line; line = line->next) {
    629   6448   vikram 				if (line->cmd == NULL || line->arg == NULL) {
    630   6448   vikram 					if (line == entry->end) {
    631   6448   vikram 						BAM_DPRINTF((D_ENTRY_END, fcn));
    632   6448   vikram 						break;
    633   6448   vikram 					} else {
    634   6448   vikram 						BAM_DPRINTF((D_SKIP_NULL, fcn));
    635   6448   vikram 						continue;
    636   6448   vikram 					}
    637   6448   vikram 				}
    638   6448   vikram 				if (strcmp(line->cmd, menu_cmds[ROOT_CMD])
    639   6448   vikram 				    == 0 && strcmp(line->arg, grubroot) == 0) {
    640   6448   vikram 					BAM_DPRINTF((D_ROOT_MATCH, fcn,
    641   6448   vikram 					    line->line, grubsign));
    642   6448   vikram 					return (entry);
    643   6448   vikram 				}
    644   6448   vikram 				if (line == entry->end) {
    645   6448   vikram 					BAM_DPRINTF((D_ENTRY_END, fcn));
    646   6448   vikram 					break;
    647   6448   vikram 				}
    648   6448   vikram 			}
    649   6448   vikram 		} else if (entry->flags & BAM_ENTRY_FINDROOT) {
    650   6448   vikram 			for (line = entry->start; line; line = line->next) {
    651   6448   vikram 				if (line->cmd == NULL || line->arg == NULL) {
    652   6448   vikram 					if (line == entry->end) {
    653   6448   vikram 						BAM_DPRINTF((D_ENTRY_END, fcn));
    654   6448   vikram 						break;
    655   6448   vikram 					} else {
    656   6448   vikram 						BAM_DPRINTF((D_SKIP_NULL, fcn));
    657   6448   vikram 						continue;
    658   6448   vikram 					}
    659   6448   vikram 				}
    660   6448   vikram 				if (strcmp(line->cmd, menu_cmds[FINDROOT_CMD])
    661   6448   vikram 				    == 0 && strcmp(line->arg, grubsign) == 0) {
    662   6448   vikram 					BAM_DPRINTF((D_FINDROOT_MATCH, fcn,
    663   6448   vikram 					    line->line, grubsign));
    664   6448   vikram 					return (entry);
    665   6448   vikram 				}
    666   6448   vikram 				if (line == entry->end) {
    667   6448   vikram 					BAM_DPRINTF((D_ENTRY_END, fcn));
    668   6448   vikram 					break;
    669   6448   vikram 				}
    670   6448   vikram 			}
    671   6448   vikram 		} else if (root_opt) {
    672   6448   vikram 			/* Neither root nor findroot */
    673   6448   vikram 			BAM_DPRINTF((D_NO_ROOT_FINDROOT, fcn, entry->entryNum));
    674   6448   vikram 			return (entry);
    675   6448   vikram 		}
    676   6448   vikram 	}
    677   6448   vikram 
    678   6448   vikram 	BAM_DPRINTF((D_NO_MATCH, fcn));
    679   6448   vikram 	return (NULL);
    680   6448   vikram }
    681   6448   vikram 
    682   6448   vikram /*
    683   6448   vikram  * The following is a set of routines that attempt to convert the
    684   6448   vikram  * menu entries for the supplied osroot into a format compatible
    685   6448   vikram  * with the GRUB installation on osroot.
    686   6448   vikram  *
    687   6448   vikram  * Each of these conversion routines make no assumptions about
    688   6448   vikram  * the current state of the menu entry, it does its best to
    689   6448   vikram  * convert the menu entry to the new state. In the process
    690   6448   vikram  * we may either upgrade or downgrade.
    691   6448   vikram  *
    692   6448   vikram  * We don't make any heroic efforts at conversion. It is better
    693   6448   vikram  * to be conservative and bail out at the first sign of error. We will
    694   6448   vikram  * in such cases, point the user at the knowledge-base article
    695   6448   vikram  * so that they can upgrade manually.
    696   6448   vikram  */
    697   6448   vikram static error_t
    698   6448   vikram bam_add_findroot(menu_t *mp, char *grubsign, char *grubroot, int root_opt)
    699   6448   vikram {
    700   6448   vikram 	entry_t		*entry;
    701   6448   vikram 	line_t		*line;
    702   6448   vikram 	line_t		*newlp;
    703   6448   vikram 	int		update_num;
    704   6448   vikram 	char		linebuf[PATH_MAX];
    705   6448   vikram 	const char	*fcn = "bam_add_findroot()";
    706   6448   vikram 
    707   6448   vikram 	update_num = 0;
    708   6448   vikram 
    709   6448   vikram 	bam_print(CVT_FINDROOT);
    710   6448   vikram 
    711   6448   vikram 	entry = mp->entries;
    712   6448   vikram 	for (; entry = find_matching_entry(entry, grubsign, grubroot, root_opt);
    713   6448   vikram 	    entry = entry->next) {
    714   6448   vikram 		if (entry->flags & BAM_ENTRY_FINDROOT) {
    715   6448   vikram 			/* already converted */
    716   6448   vikram 			BAM_DPRINTF((D_ALREADY_FINDROOT, fcn, entry->entryNum));
    717   6448   vikram 			continue;
    718   6448   vikram 		}
    719   6448   vikram 		for (line = entry->start; line; line = line->next) {
    720   6448   vikram 			if (line->cmd == NULL || line->arg == NULL) {
    721   6448   vikram 				if (line == entry->end) {
    722   6448   vikram 					BAM_DPRINTF((D_ENTRY_END, fcn));
    723   6448   vikram 					break;
    724   6448   vikram 				} else {
    725   6448   vikram 					BAM_DPRINTF((D_SKIP_NULL, fcn));
    726   6448   vikram 					continue;
    727   6448   vikram 				}
    728   6448   vikram 			}
    729   6448   vikram 			if (strcmp(line->cmd, menu_cmds[TITLE_CMD]) == 0) {
    730   6448   vikram 				newlp = s_calloc(1, sizeof (line_t));
    731   6448   vikram 				newlp->cmd = s_strdup(menu_cmds[FINDROOT_CMD]);
    732   6448   vikram 				newlp->sep = s_strdup(" ");
    733   6448   vikram 				newlp->arg = s_strdup(grubsign);
    734   6448   vikram 				(void) snprintf(linebuf, sizeof (linebuf),
    735   6448   vikram 				    "%s%s%s", newlp->cmd, newlp->sep,
    736   6448   vikram 				    newlp->arg);
    737   6448   vikram 				newlp->line = s_strdup(linebuf);
    738   6448   vikram 				bam_add_line(mp, entry, line, newlp);
    739   6448   vikram 				update_num = 1;
    740   6448   vikram 				entry->flags &= ~BAM_ENTRY_ROOT;
    741   6448   vikram 				entry->flags |= BAM_ENTRY_FINDROOT;
    742   6448   vikram 				BAM_DPRINTF((D_ADDED_FINDROOT, fcn,
    743   6448   vikram 				    newlp->line));
    744   6448   vikram 				line = newlp;
    745   6448   vikram 			}
    746   6448   vikram 			if (strcmp(line->cmd, menu_cmds[ROOT_CMD]) == 0) {
    747   6448   vikram 				BAM_DPRINTF((D_FREEING_ROOT, fcn, line->line));
    748   6448   vikram 				unlink_line(mp, line);
    749   6448   vikram 				line_free(line);
    750   6448   vikram 			}
    751   6448   vikram 			if (line == entry->end) {
    752   6448   vikram 				BAM_DPRINTF((D_ENTRY_END, fcn));
    753   6448   vikram 				break;
    754   6448   vikram 			}
    755   6448   vikram 		}
    756   6448   vikram 	}
    757   6448   vikram 
    758   6448   vikram 	if (update_num) {
    759   6448   vikram 		BAM_DPRINTF((D_UPDATED_NUMBERING, fcn));
    760   6448   vikram 		update_numbering(mp);
    761   6448   vikram 	}
    762   6448   vikram 
    763   6448   vikram 	BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
    764   6448   vikram 	return (BAM_SUCCESS);
    765   6448   vikram }
    766   6448   vikram 
    767   6448   vikram static error_t
    768   6448   vikram bam_add_hv(menu_t *mp, char *grubsign, char *grubroot, int root_opt)
    769   6448   vikram {
    770   6448   vikram 	entry_t		*entry;
    771   6448   vikram 	const char	*fcn = "bam_add_hv()";
    772   6448   vikram 
    773   6448   vikram 	bam_print(CVT_HV);
    774   6448   vikram 
    775   6448   vikram 	entry = mp->entries;
    776   6448   vikram 	for (; entry = find_matching_entry(entry, grubsign, grubroot, root_opt);
    777   6448   vikram 	    entry = entry->next) {
    778   6448   vikram 		if (entry->flags & BAM_ENTRY_HV) {
    779   6448   vikram 			BAM_DPRINTF((D_ALREADY_HV, fcn, entry->entryNum));
    780   6448   vikram 			return (BAM_SUCCESS);
    781   6448   vikram 		}
    782   6448   vikram 	}
    783   6448   vikram 
    784   6448   vikram 	(void) add_boot_entry(mp, NEW_HV_ENTRY, grubsign, XEN_MENU,
    785  10499  William 	    XEN_KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE, NULL);
    786   6448   vikram 
    787   6448   vikram 	BAM_DPRINTF((D_ADDED_XVM_ENTRY, fcn));
    788   6448   vikram 
    789   6448   vikram 	update_numbering(mp);
    790   6448   vikram 
    791   6448   vikram 	BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
    792   3446      mrj 
    793   3446      mrj 	return (BAM_SUCCESS);
    794   3446      mrj }
    795   3446      mrj 
    796   6448   vikram static error_t
    797   6448   vikram bam_add_dboot(
    798   6448   vikram 	menu_t *mp,
    799   6448   vikram 	char *osroot,
    800   6448   vikram 	char *grubsign,
    801   6448   vikram 	char *grubroot,
    802   6448   vikram 	int root_opt)
    803   3446      mrj {
    804   6448   vikram 	int		msg = 0;
    805   6448   vikram 	entry_t		*entry;
    806   6448   vikram 	line_t		*line;
    807   6448   vikram 	error_t		ret;
    808   6448   vikram 	const char 	*fcn = "bam_add_dboot()";
    809   5084  johnlev 
    810   6448   vikram 	bam_print(CVT_DBOOT);
    811   3446      mrj 
    812   6448   vikram 	entry = mp->entries;
    813   6448   vikram 	for (; entry = find_matching_entry(entry, grubsign, grubroot, root_opt);
    814   6448   vikram 	    entry = entry->next) {
    815   6448   vikram 		for (line = entry->start; line; line = line->next) {
    816   6448   vikram 			if (line->cmd == NULL || line->arg == NULL) {
    817   6448   vikram 				if (line == entry->end) {
    818   6448   vikram 					BAM_DPRINTF((D_ENTRY_END, fcn));
    819   6448   vikram 					break;
    820   6448   vikram 				} else {
    821   6448   vikram 					BAM_DPRINTF((D_SKIP_NULL, fcn));
    822   6448   vikram 					continue;
    823   6448   vikram 				}
    824   3446      mrj 			}
    825   3446      mrj 
    826   3446      mrj 			/*
    827   6448   vikram 			 * If we have a kernel$ command, assume it
    828   6448   vikram 			 * is dboot already.  If it is not a dboot
    829   6448   vikram 			 * entry, something funny is going on and
    830   6448   vikram 			 * we will leave it alone
    831   3446      mrj 			 */
    832   6448   vikram 			if (strcmp(line->cmd, menu_cmds[KERNEL_CMD]) == 0) {
    833   6448   vikram 				ret = cvt_kernel_line(line, osroot, entry);
    834   6448   vikram 				INJECT_ERROR1("ADD_DBOOT_KERN_ERR",
    835   6448   vikram 				    ret = BAM_ERROR);
    836   6448   vikram 				INJECT_ERROR1("ADD_DBOOT_KERN_MSG",
    837   6448   vikram 				    ret = BAM_MSG);
    838   6448   vikram 				if (ret == BAM_ERROR) {
    839   6448   vikram 					BAM_DPRINTF((D_CVT_KERNEL_FAIL, fcn));
    840   6448   vikram 					return (ret);
    841   6448   vikram 				} else if (ret == BAM_MSG) {
    842   6448   vikram 					msg = 1;
    843   6448   vikram 					BAM_DPRINTF((D_CVT_KERNEL_MSG, fcn));
    844   3446      mrj 				}
    845   3446      mrj 			}
    846   6448   vikram 			if (strcmp(line->cmd, menu_cmds[MODULE_CMD]) == 0) {
    847   6448   vikram 				ret = cvt_module_line(line, entry);
    848   6448   vikram 				INJECT_ERROR1("ADD_DBOOT_MOD_ERR",
    849   6448   vikram 				    ret = BAM_ERROR);
    850   6448   vikram 				INJECT_ERROR1("ADD_DBOOT_MOD_MSG",
    851   6448   vikram 				    ret = BAM_MSG);
    852   6448   vikram 				if (ret == BAM_ERROR) {
    853   6448   vikram 					BAM_DPRINTF((D_CVT_MODULE_FAIL, fcn));
    854   6448   vikram 					return (ret);
    855   6448   vikram 				} else if (ret == BAM_MSG) {
    856   6448   vikram 					BAM_DPRINTF((D_CVT_MODULE_MSG, fcn));
    857   6448   vikram 					msg = 1;
    858   6448   vikram 				}
    859   6448   vikram 			}
    860   6448   vikram 
    861   6448   vikram 			if (line == entry->end) {
    862   6448   vikram 				BAM_DPRINTF((D_ENTRY_END, fcn));
    863   3446      mrj 				break;
    864   6448   vikram 			}
    865   3446      mrj 		}
    866   3446      mrj 	}
    867   3446      mrj 
    868   6448   vikram 	ret = msg ? BAM_MSG : BAM_SUCCESS;
    869   6448   vikram 	BAM_DPRINTF((D_RETURN_RET, fcn, ret));
    870   6448   vikram 	return (ret);
    871   6448   vikram }
    872   6448   vikram 
    873   6448   vikram /*ARGSUSED*/
    874   6448   vikram error_t
    875   6448   vikram upgrade_menu(menu_t *mp, char *osroot, char *menu_root)
    876   6448   vikram {
    877   6448   vikram 	char		*osdev;
    878   6448   vikram 	char		*grubsign;
    879   6448   vikram 	char		*grubroot;
    880   6448   vikram 	int		ret1;
    881   6448   vikram 	int		ret2;
    882   6448   vikram 	int		ret3;
    883   6448   vikram 	const char	*fcn = "upgrade_menu()";
    884   6448   vikram 
    885   6448   vikram 	assert(osroot);
    886   6448   vikram 	assert(menu_root);
    887   6448   vikram 
    888   6448   vikram 	BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, menu_root));
    889   6448   vikram 
    890   3446      mrj 	/*
    891   6448   vikram 	 * We only support upgrades. Xen may not be present
    892   6448   vikram 	 * on smaller metaclusters so we don't check for that.
    893   5084  johnlev 	 */
    894   6448   vikram 	if (bam_is_findroot != BAM_FINDROOT_PRESENT ||
    895   6448   vikram 	    bam_direct != BAM_DIRECT_DBOOT) {
    896   6448   vikram 		bam_error(DOWNGRADE_NOTSUP, osroot);
    897   6448   vikram 		return (BAM_ERROR);
    898   5084  johnlev 	}
    899   5084  johnlev 
    900   5084  johnlev 	/*
    901   6448   vikram 	 * First get the GRUB signature
    902   3446      mrj 	 */
    903   6448   vikram 	osdev = get_special(osroot);
    904   6448   vikram 	INJECT_ERROR1("UPGRADE_OSDEV", osdev = NULL);
    905   6448   vikram 	if (osdev == NULL) {
    906   6448   vikram 		bam_error(CANT_FIND_SPECIAL, osroot);
    907   3446      mrj 		return (BAM_ERROR);
    908   3446      mrj 	}
    909   6448   vikram 
    910   6448   vikram 	grubsign = get_grubsign(osroot, osdev);
    911   6448   vikram 	INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign = NULL);
    912   6448   vikram 	if (grubsign == NULL) {
    913   6448   vikram 		free(osdev);
    914   6448   vikram 		bam_error(CANT_FIND_GRUBSIGN, osroot);
    915   6448   vikram 		return (BAM_ERROR);
    916   6448   vikram 	}
    917   6448   vikram 
    918   6448   vikram 	/* not fatal if we can't get grubroot */
    919   6448   vikram 	grubroot = get_grubroot(osroot, osdev, menu_root);
    920   6448   vikram 	INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot = NULL);
    921   6448   vikram 
    922   6448   vikram 	free(osdev);
    923   6448   vikram 
    924   6448   vikram 	ret1 = bam_add_findroot(mp, grubsign,
    925   6448   vikram 	    grubroot, root_optional(osroot, menu_root));
    926   6448   vikram 	INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1 = BAM_ERROR);
    927   6448   vikram 	if (ret1 == BAM_ERROR)
    928   6448   vikram 		goto abort;
    929   6448   vikram 
    930  10405    Frank 	if (bam_is_hv == BAM_HV_PRESENT) {
    931  10405    Frank 		ret2 = bam_add_hv(mp, grubsign, grubroot,
    932  10405    Frank 		    root_optional(osroot, menu_root));
    933  10405    Frank 		INJECT_ERROR1("UPGRADE_ADD_HV", ret2 = BAM_ERROR);
    934  10405    Frank 		if (ret2 == BAM_ERROR)
    935  10405    Frank 			goto abort;
    936  10405    Frank 	} else
    937  10405    Frank 		ret2 = BAM_SUCCESS;
    938   6448   vikram 
    939   6448   vikram 	ret3 = bam_add_dboot(mp, osroot, grubsign,
    940   6448   vikram 	    grubroot, root_optional(osroot, menu_root));
    941   6448   vikram 	INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3 = BAM_ERROR);
    942   6448   vikram 	if (ret3 == BAM_ERROR)
    943   6448   vikram 		goto abort;
    944   6448   vikram 
    945   6448   vikram 	if (ret1 == BAM_MSG || ret2 == BAM_MSG || ret3 == BAM_MSG) {
    946   6448   vikram 		bam_error(CVT_TODO, MENU_URL(osroot));
    947   6448   vikram 	} else {
    948   6448   vikram 		bam_warn_hand_entries(mp, osroot);
    949   6448   vikram 	}
    950   6448   vikram 
    951   6448   vikram 	free(grubsign);
    952   6448   vikram 
    953   6448   vikram 	BAM_DPRINTF((D_RETURN_RET, fcn, BAM_WRITE));
    954   3446      mrj 	return (BAM_WRITE);
    955   6448   vikram 
    956   6448   vikram abort:
    957   6448   vikram 	free(grubsign);
    958   6448   vikram 	bam_error(CVT_ABORT, osroot, MENU_URL(osroot));
    959   6448   vikram 	return (BAM_ERROR);
    960   3446      mrj }
    961