13446Smrj /* 23446Smrj * CDDL HEADER START 33446Smrj * 43446Smrj * The contents of this file are subject to the terms of the 53446Smrj * Common Development and Distribution License (the "License"). 63446Smrj * You may not use this file except in compliance with the License. 73446Smrj * 83446Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93446Smrj * or http://www.opensolaris.org/os/licensing. 103446Smrj * See the License for the specific language governing permissions 113446Smrj * and limitations under the License. 123446Smrj * 133446Smrj * When distributing Covered Code, include this CDDL HEADER in each 143446Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153446Smrj * If applicable, add the following below this CDDL HEADER, with the 163446Smrj * fields enclosed by brackets "[]" replaced with your own identifying 173446Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 183446Smrj * 193446Smrj * CDDL HEADER END 203446Smrj */ 213446Smrj /* 22*6448Svikram * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233446Smrj * Use is subject to license terms. 243446Smrj */ 253446Smrj 263446Smrj #pragma ident "%Z%%M% %I% %E% SMI" 273446Smrj 283446Smrj #include <stdio.h> 293446Smrj #include <errno.h> 303446Smrj #include <stdlib.h> 313446Smrj #include <string.h> 323446Smrj #include <unistd.h> 333446Smrj #include <sys/types.h> 343446Smrj #include <sys/stat.h> 353446Smrj #include <limits.h> 363446Smrj #include <fcntl.h> 373446Smrj #include <strings.h> 383446Smrj 393446Smrj #include <sys/mman.h> 403446Smrj #include <sys/elf.h> 413446Smrj #include <sys/multiboot.h> 423446Smrj 433446Smrj #include "message.h" 443446Smrj #include "bootadm.h" 453446Smrj 463446Smrj direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET; 475084Sjohnlev hv_t bam_is_hv = BAM_HV_UNKNOWN; 48*6448Svikram findroot_t bam_is_findroot = BAM_FINDROOT_UNKNOWN; 49*6448Svikram 50*6448Svikram static void 51*6448Svikram get_findroot_cap(const char *osroot) 52*6448Svikram { 53*6448Svikram FILE *fp; 54*6448Svikram char path[PATH_MAX]; 55*6448Svikram char buf[BAM_MAXLINE]; 56*6448Svikram struct stat sb; 57*6448Svikram int dboot; 58*6448Svikram int xVM; 59*6448Svikram int error; 60*6448Svikram int ret; 61*6448Svikram const char *fcn = "get_findroot_cap()"; 62*6448Svikram 63*6448Svikram assert(is_grub(osroot)); 64*6448Svikram 65*6448Svikram (void) snprintf(path, sizeof (path), "%s/%s", 66*6448Svikram osroot, "boot/grub/capability"); 67*6448Svikram 68*6448Svikram if (stat(path, &sb) == -1) { 69*6448Svikram bam_is_findroot = BAM_FINDROOT_ABSENT; 70*6448Svikram BAM_DPRINTF((D_FINDROOT_ABSENT, fcn)); 71*6448Svikram return; 72*6448Svikram } 73*6448Svikram 74*6448Svikram fp = fopen(path, "r"); 75*6448Svikram error = errno; 76*6448Svikram INJECT_ERROR1("GET_CAP_FINDROOT_FOPEN", fp = NULL); 77*6448Svikram if (fp == NULL) { 78*6448Svikram bam_error(OPEN_FAIL, path, strerror(error)); 79*6448Svikram return; 80*6448Svikram } 81*6448Svikram 82*6448Svikram dboot = xVM = 0; 83*6448Svikram while (s_fgets(buf, sizeof (buf), fp) != NULL) { 84*6448Svikram if (strcmp(buf, "findroot") == 0) { 85*6448Svikram BAM_DPRINTF((D_FINDROOT_PRESENT, fcn)); 86*6448Svikram bam_is_findroot = BAM_FINDROOT_PRESENT; 87*6448Svikram } 88*6448Svikram if (strcmp(buf, "dboot") == 0) { 89*6448Svikram BAM_DPRINTF((D_DBOOT_PRESENT, fcn)); 90*6448Svikram dboot = 1; 91*6448Svikram } 92*6448Svikram if (strcmp(buf, "xVM") == 0) { 93*6448Svikram BAM_DPRINTF((D_XVM_PRESENT, fcn)); 94*6448Svikram xVM = 1; 95*6448Svikram } 96*6448Svikram } 97*6448Svikram 98*6448Svikram assert(dboot); 99*6448Svikram assert(xVM); 100*6448Svikram 101*6448Svikram if (bam_is_findroot == BAM_FINDROOT_UNKNOWN) { 102*6448Svikram bam_is_findroot = BAM_FINDROOT_ABSENT; 103*6448Svikram BAM_DPRINTF((D_FINDROOT_ABSENT, fcn)); 104*6448Svikram } 105*6448Svikram out: 106*6448Svikram ret = fclose(fp); 107*6448Svikram error = errno; 108*6448Svikram INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret = 1); 109*6448Svikram if (ret != 0) { 110*6448Svikram bam_error(CLOSE_FAIL, path, strerror(error)); 111*6448Svikram } 112*6448Svikram } 1133446Smrj 1143446Smrj error_t 115*6448Svikram get_boot_cap(const char *osroot) 1163446Smrj { 117*6448Svikram char fname[PATH_MAX]; 118*6448Svikram char *image; 119*6448Svikram uchar_t *ident; 120*6448Svikram int fd; 121*6448Svikram int m; 1223446Smrj multiboot_header_t *mbh; 123*6448Svikram struct stat sb; 124*6448Svikram int error; 125*6448Svikram const char *fcn = "get_boot_cap()"; 1263446Smrj 127*6448Svikram if (is_sparc()) { 1285648Ssetje /* there is no non dboot sparc new-boot */ 1295648Ssetje bam_direct = BAM_DIRECT_DBOOT; 130*6448Svikram BAM_DPRINTF((D_IS_SPARC_DBOOT, fcn)); 1315648Ssetje return (BAM_SUCCESS); 1325648Ssetje } 1335648Ssetje 134*6448Svikram if (!is_grub(osroot)) { 135*6448Svikram bam_error(NOT_GRUB_ROOT, osroot); 136*6448Svikram return (BAM_ERROR); 137*6448Svikram } 138*6448Svikram 139*6448Svikram (void) snprintf(fname, PATH_MAX, "%s/%s", osroot, 1403446Smrj "platform/i86pc/kernel/unix"); 1413446Smrj fd = open(fname, O_RDONLY); 142*6448Svikram error = errno; 143*6448Svikram INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd = -1); 1443446Smrj if (fd < 0) { 145*6448Svikram bam_error(OPEN_FAIL, fname, strerror(error)); 146*6448Svikram return (BAM_ERROR); 147*6448Svikram } 148*6448Svikram 149*6448Svikram /* 150*6448Svikram * Verify that this is a sane unix at least 8192 bytes in length 151*6448Svikram */ 152*6448Svikram if (fstat(fd, &sb) == -1 || sb.st_size < 8192) { 153*6448Svikram (void) close(fd); 154*6448Svikram bam_error(INVALID_BINARY, fname); 1553446Smrj return (BAM_ERROR); 1563446Smrj } 1573446Smrj 1583446Smrj /* 1593446Smrj * mmap the first 8K 1603446Smrj */ 1613446Smrj image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0); 162*6448Svikram error = errno; 163*6448Svikram INJECT_ERROR1("GET_CAP_MMAP", image = MAP_FAILED); 1643446Smrj if (image == MAP_FAILED) { 165*6448Svikram bam_error(MMAP_FAIL, fname, strerror(error)); 1663446Smrj return (BAM_ERROR); 1673446Smrj } 1683446Smrj 1693446Smrj ident = (uchar_t *)image; 1703446Smrj if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || 1713446Smrj ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) { 1723446Smrj bam_error(NOT_ELF_FILE, fname); 1733446Smrj return (BAM_ERROR); 1743446Smrj } 1753446Smrj if (ident[EI_CLASS] != ELFCLASS32) { 1763446Smrj bam_error(WRONG_ELF_CLASS, fname, ident[EI_CLASS]); 1773446Smrj return (BAM_ERROR); 1783446Smrj } 1793446Smrj 1803446Smrj /* 1813446Smrj * The GRUB multiboot header must be 32-bit aligned and completely 1823446Smrj * contained in the 1st 8K of the file. If the unix binary has 1833446Smrj * a multiboot header, then it is a 'dboot' kernel. Otherwise, 1843446Smrj * this kernel must be booted via multiboot -- we call this a 1853446Smrj * 'multiboot' kernel. 1863446Smrj */ 1873446Smrj bam_direct = BAM_DIRECT_MULTIBOOT; 1883446Smrj for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) { 1893446Smrj mbh = (void *)(image + m); 1903446Smrj if (mbh->magic == MB_HEADER_MAGIC) { 191*6448Svikram BAM_DPRINTF((D_IS_DBOOT, fcn)); 1923446Smrj bam_direct = BAM_DIRECT_DBOOT; 1933446Smrj break; 1943446Smrj } 1953446Smrj } 1963446Smrj (void) munmap(image, 8192); 1973446Smrj (void) close(fd); 1985084Sjohnlev 199*6448Svikram INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct = BAM_DIRECT_MULTIBOOT); 2005084Sjohnlev if (bam_direct == BAM_DIRECT_DBOOT) { 201*6448Svikram (void) snprintf(fname, PATH_MAX, "%s/%s", osroot, XEN_32); 2025084Sjohnlev if (stat(fname, &sb) == 0) { 2035084Sjohnlev bam_is_hv = BAM_HV_PRESENT; 204*6448Svikram BAM_DPRINTF((D_IS_XVM, fcn)); 2055084Sjohnlev } else { 2065084Sjohnlev bam_is_hv = BAM_HV_NO; 207*6448Svikram BAM_DPRINTF((D_IS_NOT_XVM, fcn)); 2085084Sjohnlev } 209*6448Svikram } else { 210*6448Svikram BAM_DPRINTF((D_IS_MULTIBOOT, fcn)); 2115084Sjohnlev } 2125084Sjohnlev 213*6448Svikram /* Not a fatal error if this fails */ 214*6448Svikram get_findroot_cap(osroot); 215*6448Svikram 216*6448Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 2173446Smrj return (BAM_SUCCESS); 2183446Smrj } 2193446Smrj 2203446Smrj #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE" 2213446Smrj 2223446Smrj /* 2233446Smrj * Return true if root has been bfu'ed. bfu will blow away 2243446Smrj * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can 2253446Smrj * assume the system has not been bfu'ed. 2263446Smrj */ 2273446Smrj static int 2283446Smrj is_bfu_system(const char *root) 2293446Smrj { 230*6448Svikram static int is_bfu = -1; 231*6448Svikram char path[PATH_MAX]; 232*6448Svikram struct stat sb; 233*6448Svikram const char *fcn = "is_bfu_system()"; 2343446Smrj 235*6448Svikram if (is_bfu != -1) { 236*6448Svikram BAM_DPRINTF((D_ALREADY_BFU_TEST, fcn, is_bfu ? "" : "NOT")); 2373446Smrj return (is_bfu); 238*6448Svikram } 2393446Smrj 2403446Smrj (void) snprintf(path, sizeof (path), "%s/%s", root, INST_RELEASE); 2413446Smrj if (stat(path, &sb) != 0) { 2423446Smrj is_bfu = 1; 243*6448Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 2443446Smrj } else { 2453446Smrj is_bfu = 0; 246*6448Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 2473446Smrj } 2483446Smrj return (is_bfu); 2493446Smrj } 2503446Smrj 2513446Smrj #define MENU_URL(root) (is_bfu_system(root) ? \ 2523446Smrj "http://www.sun.com/msg/SUNOS-8000-CF" : \ 2533446Smrj "http://www.sun.com/msg/SUNOS-8000-AK") 2543446Smrj 2553446Smrj /* 2563446Smrj * Simply allocate a new line and copy in cmd + sep + arg 2573446Smrj */ 2583446Smrj void 2593446Smrj update_line(line_t *linep) 2603446Smrj { 261*6448Svikram size_t size; 262*6448Svikram const char *fcn = "update_line()"; 2633446Smrj 264*6448Svikram BAM_DPRINTF((D_UPDATE_LINE_BEFORE, fcn, linep->line)); 2653446Smrj free(linep->line); 2663446Smrj size = strlen(linep->cmd) + strlen(linep->sep) + strlen(linep->arg) + 1; 2673446Smrj linep->line = s_calloc(1, size); 2683446Smrj (void) snprintf(linep->line, size, "%s%s%s", linep->cmd, linep->sep, 2693446Smrj linep->arg); 270*6448Svikram BAM_DPRINTF((D_UPDATE_LINE_AFTER, fcn, linep->line)); 271*6448Svikram } 272*6448Svikram 273*6448Svikram static char * 274*6448Svikram skip_wspace(char *ptr) 275*6448Svikram { 276*6448Svikram const char *fcn = "skip_wspace()"; 277*6448Svikram 278*6448Svikram INJECT_ERROR1("SKIP_WSPACE", ptr = NULL); 279*6448Svikram if (ptr == NULL) { 280*6448Svikram BAM_DPRINTF((D_SKIP_WSPACE_PTR_NULL, fcn)); 281*6448Svikram return (NULL); 282*6448Svikram } 283*6448Svikram 284*6448Svikram BAM_DPRINTF((D_SKIP_WSPACE_ENTRY_PTR, fcn, ptr)); 285*6448Svikram for (; *ptr != '\0'; ptr++) { 286*6448Svikram if ((*ptr != ' ') && (*ptr != '\t') && 287*6448Svikram (*ptr != '\n')) 288*6448Svikram break; 289*6448Svikram } 290*6448Svikram 291*6448Svikram ptr = (*ptr == '\0' ? NULL : ptr); 292*6448Svikram 293*6448Svikram BAM_DPRINTF((D_SKIP_WSPACE_EXIT_PTR, fcn, ptr ? ptr : "NULL")); 294*6448Svikram 295*6448Svikram return (ptr); 296*6448Svikram } 297*6448Svikram 298*6448Svikram static char * 299*6448Svikram rskip_bspace(char *bound, char *ptr) 300*6448Svikram { 301*6448Svikram const char *fcn = "rskip_bspace()"; 302*6448Svikram assert(bound); 303*6448Svikram assert(ptr); 304*6448Svikram assert(bound <= ptr); 305*6448Svikram assert(*bound != ' ' && *bound != '\t' && *bound != '\n'); 306*6448Svikram 307*6448Svikram BAM_DPRINTF((D_RSKIP_BSPACE_ENTRY, fcn, ptr)); 308*6448Svikram for (; ptr > bound; ptr--) { 309*6448Svikram if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') 310*6448Svikram break; 311*6448Svikram } 312*6448Svikram 313*6448Svikram BAM_DPRINTF((D_RSKIP_BSPACE_EXIT, fcn, ptr)); 314*6448Svikram return (ptr); 3153446Smrj } 3163446Smrj 3173446Smrj /* 3183446Smrj * The parse_kernel_line function examines a menu.lst kernel line. For 3193446Smrj * multiboot, this is: 3203446Smrj * 3213446Smrj * kernel <multiboot path> <flags1> <kernel path> <flags2> 3223446Smrj * 3233446Smrj * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot 3243446Smrj * 3253446Smrj * <kernel path> may be missing, or may be any full or relative path to unix. 3263446Smrj * We check for it by looking for a word ending in "/unix". If it ends 3273446Smrj * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in 3283446Smrj * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise, 3293446Smrj * it's a custom kernel, and we skip it. 3303446Smrj * 3313446Smrj * <flags*> are anything that doesn't fit either of the above - these will be 3323446Smrj * copied over. 3333446Smrj * 3343446Smrj * For direct boot, the defaults are 3353446Smrj * 3363446Smrj * kernel$ <kernel path> <flags> 3373446Smrj * 3383446Smrj * <kernel path> is one of: 3393446Smrj * /platform/i86pc/kernel/$ISADIR/unix 3403446Smrj * /platform/i86pc/kernel/unix 3413446Smrj * /platform/i86pc/kernel/amd64/unix 3423446Smrj * /boot/platform/i86pc/kernel/unix 3433446Smrj * 3443446Smrj * If <kernel path> is any of the last three, the command may also be "kernel". 3453446Smrj * 3463446Smrj * <flags> is anything that isn't <kernel path>. 3473446Smrj * 348*6448Svikram * This function is only called to convert a multiboot entry to a dboot entry 3493446Smrj * 3503446Smrj * For safety, we do one more check: if the kernel path starts with /boot, 3513446Smrj * we verify that the new kernel exists before changing it. This is mainly 3523446Smrj * done for bfu, as it may cause the failsafe archives to be a different 3533446Smrj * boot architecture from the newly bfu'ed system. 3543446Smrj */ 3553446Smrj static error_t 356*6448Svikram cvt_kernel_line(line_t *line, const char *osroot, entry_t *entry) 3573446Smrj { 358*6448Svikram char path[PATH_MAX]; 359*6448Svikram char linebuf[PATH_MAX]; 360*6448Svikram char new_arg[PATH_MAX]; 361*6448Svikram struct stat sb; 362*6448Svikram char *old_ptr; 363*6448Svikram char *unix_ptr; 364*6448Svikram char *flags1_ptr; 365*6448Svikram char *flags2_ptr; 366*6448Svikram const char *fcn = "cvt_kernel_line()"; 3673446Smrj 368*6448Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, line->line, osroot)); 3693446Smrj 3703446Smrj /* 371*6448Svikram * We only convert multiboot to dboot and nothing else. 3723446Smrj */ 373*6448Svikram if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) { 374*6448Svikram BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT, fcn)); 3753446Smrj return (BAM_SUCCESS); 3763446Smrj } 3773446Smrj 378*6448Svikram if (entry->flags & BAM_ENTRY_FAILSAFE) { 3793446Smrj /* 380*6448Svikram * We're attempting to change failsafe to dboot. 381*6448Svikram * In the bfu case, we may not have a dboot failsafe 382*6448Svikram * kernel i.e. a "unix" under the "/boot" hierarchy. 383*6448Svikram * If so, just emit a message in verbose mode and 384*6448Svikram * return success. 3853446Smrj */ 386*6448Svikram BAM_DPRINTF((D_TRYING_FAILSAFE_CVT_TO_DBOOT, fcn)); 387*6448Svikram (void) snprintf(path, PATH_MAX, "%s%s", osroot, 3883446Smrj DIRECT_BOOT_FAILSAFE_KERNEL); 3893446Smrj if (stat(path, &sb) != 0) { 3903446Smrj if (bam_verbose) { 391*6448Svikram bam_error(FAILSAFE_MISSING, line->lineNum); 3923446Smrj } 393*6448Svikram BAM_DPRINTF((D_NO_FAILSAFE_UNIX_CONVERT, fcn)); 3943446Smrj return (BAM_SUCCESS); 3953446Smrj } 3963446Smrj } 3973446Smrj 3983446Smrj /* 3993446Smrj * Make sure we have the correct cmd - either kernel or kernel$ 400*6448Svikram * The failsafe entry should always be kernel. 4013446Smrj */ 402*6448Svikram if (!(entry->flags & BAM_ENTRY_FAILSAFE)) { 403*6448Svikram free(line->cmd); 404*6448Svikram line->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]); 405*6448Svikram BAM_DPRINTF((D_CVT_CMD_KERN_DOLLAR, fcn, line->cmd)); 406*6448Svikram } 407*6448Svikram 408*6448Svikram assert(sizeof (linebuf) > strlen(line->arg) + 32); 409*6448Svikram (void) strlcpy(linebuf, line->arg, sizeof (linebuf)); 4103446Smrj 411*6448Svikram old_ptr = strpbrk(linebuf, " \t\n"); 412*6448Svikram old_ptr = skip_wspace(old_ptr); 413*6448Svikram if (old_ptr == NULL) { 414*6448Svikram /* 415*6448Svikram * only multiboot and nothing else 416*6448Svikram * i.e. flags1 = unix = flags2 = NULL 417*6448Svikram */ 418*6448Svikram flags1_ptr = unix_ptr = flags2_ptr = NULL; 419*6448Svikram BAM_DPRINTF((D_FLAGS1_UNIX_FLAGS2_NULL, fcn)) 420*6448Svikram goto create; 4213446Smrj } 4223446Smrj 4233446Smrj /* 4243446Smrj * 425*6448Svikram * old_ptr is either at "flags1" or "unix" 4263446Smrj */ 427*6448Svikram if (unix_ptr = strstr(old_ptr, "/unix")) { 428*6448Svikram 429*6448Svikram /* 430*6448Svikram * There is a unix. 431*6448Svikram */ 432*6448Svikram BAM_DPRINTF((D_UNIX_PRESENT, fcn)); 433*6448Svikram 434*6448Svikram /* See if there's a flags2 past unix */ 435*6448Svikram flags2_ptr = unix_ptr + strlen("/unix"); 436*6448Svikram flags2_ptr = skip_wspace(flags2_ptr); 437*6448Svikram if (flags2_ptr) { 438*6448Svikram BAM_DPRINTF((D_FLAGS2_PRESENT, fcn, flags2_ptr)); 439*6448Svikram } else { 440*6448Svikram BAM_DPRINTF((D_FLAGS2_ABSENT, fcn)); 4413446Smrj } 4423446Smrj 443*6448Svikram /* see if there is a flags1 before unix */ 444*6448Svikram unix_ptr = rskip_bspace(old_ptr, unix_ptr); 4453446Smrj 4463446Smrj if (unix_ptr == old_ptr) { 4473446Smrj flags1_ptr = NULL; 448*6448Svikram BAM_DPRINTF((D_FLAGS1_ABSENT, fcn)); 4493446Smrj } else { 4503446Smrj flags1_ptr = old_ptr; 451*6448Svikram *unix_ptr = '\0'; 452*6448Svikram unix_ptr++; 453*6448Svikram BAM_DPRINTF((D_FLAGS1_PRESENT, fcn, flags1_ptr)); 4543446Smrj } 4553446Smrj 456*6448Svikram } else { 457*6448Svikram /* There is no unix, there is only a bunch of flags */ 4583446Smrj flags1_ptr = old_ptr; 459*6448Svikram unix_ptr = flags2_ptr = NULL; 460*6448Svikram BAM_DPRINTF((D_FLAGS1_ONLY, fcn, flags1_ptr)); 4613446Smrj } 4623446Smrj 4633446Smrj /* 464*6448Svikram * With dboot, unix is fixed and is at the beginning. We need to 465*6448Svikram * migrate flags1 and flags2 4663446Smrj */ 467*6448Svikram create: 468*6448Svikram if (entry->flags & BAM_ENTRY_FAILSAFE) { 469*6448Svikram (void) snprintf(new_arg, sizeof (new_arg), "%s", 470*6448Svikram DIRECT_BOOT_FAILSAFE_KERNEL); 471*6448Svikram } else { 472*6448Svikram (void) snprintf(new_arg, sizeof (new_arg), "%s", 473*6448Svikram DIRECT_BOOT_KERNEL); 474*6448Svikram } 475*6448Svikram BAM_DPRINTF((D_CVTED_UNIX, fcn, new_arg)); 4763446Smrj 477*6448Svikram if (flags1_ptr != NULL) { 478*6448Svikram (void) strlcat(new_arg, " ", sizeof (new_arg)); 479*6448Svikram (void) strlcat(new_arg, flags1_ptr, sizeof (new_arg)); 4803446Smrj } 4813446Smrj 482*6448Svikram if (flags2_ptr != NULL) { 483*6448Svikram (void) strlcat(new_arg, " ", sizeof (new_arg)); 484*6448Svikram (void) strlcat(new_arg, flags2_ptr, sizeof (new_arg)); 485*6448Svikram } 486*6448Svikram 487*6448Svikram BAM_DPRINTF((D_CVTED_UNIX_AND_FLAGS, fcn, new_arg)); 488*6448Svikram 489*6448Svikram free(line->arg); 490*6448Svikram line->arg = s_strdup(new_arg); 491*6448Svikram update_line(line); 492*6448Svikram BAM_DPRINTF((D_CVTED_KERNEL_LINE, fcn, line->line)); 4933446Smrj return (BAM_SUCCESS); 4943446Smrj } 4953446Smrj 4963446Smrj /* 4973446Smrj * Similar to above, except this time we're looking at a module line, 4983446Smrj * which is quite a bit simpler. 4993446Smrj * 5003446Smrj * Under multiboot, the archive line is: 5013446Smrj * 5023446Smrj * module /platform/i86pc/boot_archive 5033446Smrj * 5043446Smrj * Under directboot, the archive line is: 5053446Smrj * 5063446Smrj * module$ /platform/i86pc/$ISADIR/boot_archive 5073446Smrj * 5083446Smrj * which may be specified exactly as either of: 5093446Smrj * 5103446Smrj * module /platform/i86pc/boot_archive 5113446Smrj * module /platform/i86pc/amd64/boot_archive 5123446Smrj * 5133446Smrj * For either dboot or multiboot, the failsafe is: 5143446Smrj * 5153446Smrj * module /boot/x86.miniroot-safe 5163446Smrj */ 5173446Smrj static error_t 518*6448Svikram cvt_module_line(line_t *line, entry_t *entry) 5193446Smrj { 520*6448Svikram const char *fcn = "cvt_module_line()"; 521*6448Svikram 522*6448Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, line->line)); 5233446Smrj 5243446Smrj /* 525*6448Svikram * We only convert multiboot to dboot and nothing else 5263446Smrj */ 527*6448Svikram if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) { 528*6448Svikram BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT, fcn)); 5293446Smrj return (BAM_SUCCESS); 5303446Smrj } 5313446Smrj 532*6448Svikram if (entry->flags & BAM_ENTRY_FAILSAFE) { 533*6448Svikram if (strcmp(line->arg, FAILSAFE_ARCHIVE) == 0) { 534*6448Svikram BAM_DPRINTF((D_FAILSAFE_NO_CVT_NEEDED, fcn, line->arg)); 535*6448Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 536*6448Svikram return (BAM_SUCCESS); 537*6448Svikram } 538*6448Svikram } else if (strcmp(line->arg, MULTIBOOT_ARCHIVE) != 0) { 539*6448Svikram bam_error(UNKNOWN_MODULE_LINE, line->lineNum); 540*6448Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 541*6448Svikram return (BAM_MSG); 542*6448Svikram } 543*6448Svikram 544*6448Svikram if (entry->flags & BAM_ENTRY_FAILSAFE) { 545*6448Svikram free(line->cmd); 546*6448Svikram free(line->arg); 547*6448Svikram line->cmd = s_strdup(menu_cmds[MODULE_CMD]); 548*6448Svikram line->arg = s_strdup(FAILSAFE_ARCHIVE); 549*6448Svikram } else { 550*6448Svikram free(line->cmd); 551*6448Svikram free(line->arg); 552*6448Svikram line->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]); 553*6448Svikram line->arg = s_strdup(DIRECT_BOOT_ARCHIVE); 554*6448Svikram } 555*6448Svikram 556*6448Svikram update_line(line); 557*6448Svikram BAM_DPRINTF((D_CVTED_MODULE, fcn, line->line)); 558*6448Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 559*6448Svikram return (BAM_SUCCESS); 560*6448Svikram } 561*6448Svikram 562*6448Svikram static void 563*6448Svikram bam_warn_hand_entries(menu_t *mp, char *osroot) 564*6448Svikram { 565*6448Svikram int hand_num; 566*6448Svikram int hand_max; 567*6448Svikram int *hand_list; 568*6448Svikram int i; 569*6448Svikram entry_t *entry; 570*6448Svikram const char *fcn = "bam_warn_hand_entries()"; 571*6448Svikram 572*6448Svikram if (bam_force) { 573*6448Svikram /* 574*6448Svikram * No warning needed, we are automatically converting 575*6448Svikram * the "hand" entries 576*6448Svikram */ 577*6448Svikram BAM_DPRINTF((D_FORCE_HAND_CVT, fcn)); 578*6448Svikram return; 579*6448Svikram } 580*6448Svikram 581*6448Svikram hand_num = 0; 582*6448Svikram hand_max = BAM_ENTRY_NUM; 583*6448Svikram hand_list = s_calloc(1, hand_max); 584*6448Svikram 585*6448Svikram for (entry = mp->entries; entry; entry = entry->next) { 586*6448Svikram if (entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) 587*6448Svikram continue; 588*6448Svikram BAM_DPRINTF((D_FOUND_HAND, fcn, entry->entryNum)); 589*6448Svikram if (++hand_num > hand_max) { 590*6448Svikram hand_max *= 2; 591*6448Svikram hand_list = s_realloc(hand_list, 592*6448Svikram hand_max * sizeof (int)); 593*6448Svikram } 594*6448Svikram hand_list[hand_num - 1] = entry->entryNum; 595*6448Svikram } 596*6448Svikram 597*6448Svikram bam_error(HAND_ADDED_ENTRIES, osroot, MENU_URL(osroot)); 598*6448Svikram bam_print_stderr("Entry Number%s: ", (hand_num > 1) ? 599*6448Svikram "s" : ""); 600*6448Svikram for (i = 0; i < hand_num; i++) { 601*6448Svikram bam_print_stderr("%d ", hand_list[i]); 602*6448Svikram } 603*6448Svikram bam_print_stderr("\n"); 604*6448Svikram } 6053446Smrj 606*6448Svikram static entry_t * 607*6448Svikram find_matching_entry( 608*6448Svikram entry_t *estart, 609*6448Svikram char *grubsign, 610*6448Svikram char *grubroot, 611*6448Svikram int root_opt) 612*6448Svikram { 613*6448Svikram entry_t *entry; 614*6448Svikram line_t *line; 615*6448Svikram char opt[10]; 616*6448Svikram const char *fcn = "find_matching_entry()"; 617*6448Svikram 618*6448Svikram assert(grubsign); 619*6448Svikram assert(root_opt == 0 || root_opt == 1); 620*6448Svikram 621*6448Svikram (void) snprintf(opt, sizeof (opt), "%d", root_opt); 622*6448Svikram BAM_DPRINTF((D_FUNC_ENTRY3, fcn, grubsign, grubroot, opt)); 623*6448Svikram 624*6448Svikram for (entry = estart; entry; entry = entry->next) { 625*6448Svikram #if 0 626*6448Svikram if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) && 627*6448Svikram !bam_force) { 628*6448Svikram #endif 629*6448Svikram if (!(entry->flags & BAM_ENTRY_BOOTADM) && !bam_force) { 630*6448Svikram BAM_DPRINTF((D_SKIP_ENTRY, fcn, entry->entryNum)); 631*6448Svikram continue; 632*6448Svikram } 633*6448Svikram 634*6448Svikram if (entry->flags & BAM_ENTRY_ROOT) { 635*6448Svikram for (line = entry->start; line; line = line->next) { 636*6448Svikram if (line->cmd == NULL || line->arg == NULL) { 637*6448Svikram if (line == entry->end) { 638*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 639*6448Svikram break; 640*6448Svikram } else { 641*6448Svikram BAM_DPRINTF((D_SKIP_NULL, fcn)); 642*6448Svikram continue; 643*6448Svikram } 644*6448Svikram } 645*6448Svikram if (strcmp(line->cmd, menu_cmds[ROOT_CMD]) 646*6448Svikram == 0 && strcmp(line->arg, grubroot) == 0) { 647*6448Svikram BAM_DPRINTF((D_ROOT_MATCH, fcn, 648*6448Svikram line->line, grubsign)); 649*6448Svikram return (entry); 650*6448Svikram } 651*6448Svikram if (line == entry->end) { 652*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 653*6448Svikram break; 654*6448Svikram } 655*6448Svikram } 656*6448Svikram } else if (entry->flags & BAM_ENTRY_FINDROOT) { 657*6448Svikram for (line = entry->start; line; line = line->next) { 658*6448Svikram if (line->cmd == NULL || line->arg == NULL) { 659*6448Svikram if (line == entry->end) { 660*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 661*6448Svikram break; 662*6448Svikram } else { 663*6448Svikram BAM_DPRINTF((D_SKIP_NULL, fcn)); 664*6448Svikram continue; 665*6448Svikram } 666*6448Svikram } 667*6448Svikram if (strcmp(line->cmd, menu_cmds[FINDROOT_CMD]) 668*6448Svikram == 0 && strcmp(line->arg, grubsign) == 0) { 669*6448Svikram BAM_DPRINTF((D_FINDROOT_MATCH, fcn, 670*6448Svikram line->line, grubsign)); 671*6448Svikram return (entry); 672*6448Svikram } 673*6448Svikram if (line == entry->end) { 674*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 675*6448Svikram break; 676*6448Svikram } 677*6448Svikram } 678*6448Svikram } else if (root_opt) { 679*6448Svikram /* Neither root nor findroot */ 680*6448Svikram BAM_DPRINTF((D_NO_ROOT_FINDROOT, fcn, entry->entryNum)); 681*6448Svikram return (entry); 682*6448Svikram } 6833446Smrj } 6843446Smrj 685*6448Svikram BAM_DPRINTF((D_NO_MATCH, fcn)); 686*6448Svikram return (NULL); 687*6448Svikram } 688*6448Svikram 689*6448Svikram /* 690*6448Svikram * The following is a set of routines that attempt to convert the 691*6448Svikram * menu entries for the supplied osroot into a format compatible 692*6448Svikram * with the GRUB installation on osroot. 693*6448Svikram * 694*6448Svikram * Each of these conversion routines make no assumptions about 695*6448Svikram * the current state of the menu entry, it does its best to 696*6448Svikram * convert the menu entry to the new state. In the process 697*6448Svikram * we may either upgrade or downgrade. 698*6448Svikram * 699*6448Svikram * We don't make any heroic efforts at conversion. It is better 700*6448Svikram * to be conservative and bail out at the first sign of error. We will 701*6448Svikram * in such cases, point the user at the knowledge-base article 702*6448Svikram * so that they can upgrade manually. 703*6448Svikram */ 704*6448Svikram static error_t 705*6448Svikram bam_add_findroot(menu_t *mp, char *grubsign, char *grubroot, int root_opt) 706*6448Svikram { 707*6448Svikram entry_t *entry; 708*6448Svikram line_t *line; 709*6448Svikram line_t *newlp; 710*6448Svikram int update_num; 711*6448Svikram char linebuf[PATH_MAX]; 712*6448Svikram const char *fcn = "bam_add_findroot()"; 713*6448Svikram 714*6448Svikram update_num = 0; 715*6448Svikram 716*6448Svikram bam_print(CVT_FINDROOT); 717*6448Svikram 718*6448Svikram entry = mp->entries; 719*6448Svikram for (; entry = find_matching_entry(entry, grubsign, grubroot, root_opt); 720*6448Svikram entry = entry->next) { 721*6448Svikram if (entry->flags & BAM_ENTRY_FINDROOT) { 722*6448Svikram /* already converted */ 723*6448Svikram BAM_DPRINTF((D_ALREADY_FINDROOT, fcn, entry->entryNum)); 724*6448Svikram continue; 725*6448Svikram } 726*6448Svikram for (line = entry->start; line; line = line->next) { 727*6448Svikram if (line->cmd == NULL || line->arg == NULL) { 728*6448Svikram if (line == entry->end) { 729*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 730*6448Svikram break; 731*6448Svikram } else { 732*6448Svikram BAM_DPRINTF((D_SKIP_NULL, fcn)); 733*6448Svikram continue; 734*6448Svikram } 735*6448Svikram } 736*6448Svikram if (strcmp(line->cmd, menu_cmds[TITLE_CMD]) == 0) { 737*6448Svikram newlp = s_calloc(1, sizeof (line_t)); 738*6448Svikram newlp->cmd = s_strdup(menu_cmds[FINDROOT_CMD]); 739*6448Svikram newlp->sep = s_strdup(" "); 740*6448Svikram newlp->arg = s_strdup(grubsign); 741*6448Svikram (void) snprintf(linebuf, sizeof (linebuf), 742*6448Svikram "%s%s%s", newlp->cmd, newlp->sep, 743*6448Svikram newlp->arg); 744*6448Svikram newlp->line = s_strdup(linebuf); 745*6448Svikram bam_add_line(mp, entry, line, newlp); 746*6448Svikram update_num = 1; 747*6448Svikram entry->flags &= ~BAM_ENTRY_ROOT; 748*6448Svikram entry->flags |= BAM_ENTRY_FINDROOT; 749*6448Svikram BAM_DPRINTF((D_ADDED_FINDROOT, fcn, 750*6448Svikram newlp->line)); 751*6448Svikram line = newlp; 752*6448Svikram } 753*6448Svikram if (strcmp(line->cmd, menu_cmds[ROOT_CMD]) == 0) { 754*6448Svikram BAM_DPRINTF((D_FREEING_ROOT, fcn, line->line)); 755*6448Svikram unlink_line(mp, line); 756*6448Svikram line_free(line); 757*6448Svikram } 758*6448Svikram if (line == entry->end) { 759*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 760*6448Svikram break; 761*6448Svikram } 762*6448Svikram } 763*6448Svikram } 764*6448Svikram 765*6448Svikram if (update_num) { 766*6448Svikram BAM_DPRINTF((D_UPDATED_NUMBERING, fcn)); 767*6448Svikram update_numbering(mp); 768*6448Svikram } 769*6448Svikram 770*6448Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 771*6448Svikram return (BAM_SUCCESS); 772*6448Svikram } 773*6448Svikram 774*6448Svikram static error_t 775*6448Svikram bam_add_hv(menu_t *mp, char *grubsign, char *grubroot, int root_opt) 776*6448Svikram { 777*6448Svikram entry_t *entry; 778*6448Svikram const char *fcn = "bam_add_hv()"; 779*6448Svikram 780*6448Svikram bam_print(CVT_HV); 781*6448Svikram 782*6448Svikram entry = mp->entries; 783*6448Svikram for (; entry = find_matching_entry(entry, grubsign, grubroot, root_opt); 784*6448Svikram entry = entry->next) { 785*6448Svikram if (entry->flags & BAM_ENTRY_HV) { 786*6448Svikram BAM_DPRINTF((D_ALREADY_HV, fcn, entry->entryNum)); 787*6448Svikram return (BAM_SUCCESS); 788*6448Svikram } 789*6448Svikram } 790*6448Svikram 791*6448Svikram (void) add_boot_entry(mp, NEW_HV_ENTRY, grubsign, XEN_MENU, 792*6448Svikram XEN_KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE); 793*6448Svikram 794*6448Svikram BAM_DPRINTF((D_ADDED_XVM_ENTRY, fcn)); 795*6448Svikram 796*6448Svikram update_numbering(mp); 797*6448Svikram 798*6448Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 7993446Smrj 8003446Smrj return (BAM_SUCCESS); 8013446Smrj } 8023446Smrj 803*6448Svikram static error_t 804*6448Svikram bam_add_dboot( 805*6448Svikram menu_t *mp, 806*6448Svikram char *osroot, 807*6448Svikram char *grubsign, 808*6448Svikram char *grubroot, 809*6448Svikram int root_opt) 810*6448Svikram { 811*6448Svikram int msg = 0; 812*6448Svikram entry_t *entry; 813*6448Svikram line_t *line; 814*6448Svikram error_t ret; 815*6448Svikram const char *fcn = "bam_add_dboot()"; 816*6448Svikram 817*6448Svikram bam_print(CVT_DBOOT); 818*6448Svikram 819*6448Svikram entry = mp->entries; 820*6448Svikram for (; entry = find_matching_entry(entry, grubsign, grubroot, root_opt); 821*6448Svikram entry = entry->next) { 822*6448Svikram for (line = entry->start; line; line = line->next) { 823*6448Svikram if (line->cmd == NULL || line->arg == NULL) { 824*6448Svikram if (line == entry->end) { 825*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 826*6448Svikram break; 827*6448Svikram } else { 828*6448Svikram BAM_DPRINTF((D_SKIP_NULL, fcn)); 829*6448Svikram continue; 830*6448Svikram } 831*6448Svikram } 832*6448Svikram 833*6448Svikram /* 834*6448Svikram * If we have a kernel$ command, assume it 835*6448Svikram * is dboot already. If it is not a dboot 836*6448Svikram * entry, something funny is going on and 837*6448Svikram * we will leave it alone 838*6448Svikram */ 839*6448Svikram if (strcmp(line->cmd, menu_cmds[KERNEL_CMD]) == 0) { 840*6448Svikram ret = cvt_kernel_line(line, osroot, entry); 841*6448Svikram INJECT_ERROR1("ADD_DBOOT_KERN_ERR", 842*6448Svikram ret = BAM_ERROR); 843*6448Svikram INJECT_ERROR1("ADD_DBOOT_KERN_MSG", 844*6448Svikram ret = BAM_MSG); 845*6448Svikram if (ret == BAM_ERROR) { 846*6448Svikram BAM_DPRINTF((D_CVT_KERNEL_FAIL, fcn)); 847*6448Svikram return (ret); 848*6448Svikram } else if (ret == BAM_MSG) { 849*6448Svikram msg = 1; 850*6448Svikram BAM_DPRINTF((D_CVT_KERNEL_MSG, fcn)); 851*6448Svikram } 852*6448Svikram } 853*6448Svikram if (strcmp(line->cmd, menu_cmds[MODULE_CMD]) == 0) { 854*6448Svikram ret = cvt_module_line(line, entry); 855*6448Svikram INJECT_ERROR1("ADD_DBOOT_MOD_ERR", 856*6448Svikram ret = BAM_ERROR); 857*6448Svikram INJECT_ERROR1("ADD_DBOOT_MOD_MSG", 858*6448Svikram ret = BAM_MSG); 859*6448Svikram if (ret == BAM_ERROR) { 860*6448Svikram BAM_DPRINTF((D_CVT_MODULE_FAIL, fcn)); 861*6448Svikram return (ret); 862*6448Svikram } else if (ret == BAM_MSG) { 863*6448Svikram BAM_DPRINTF((D_CVT_MODULE_MSG, fcn)); 864*6448Svikram msg = 1; 865*6448Svikram } 866*6448Svikram } 867*6448Svikram 868*6448Svikram if (line == entry->end) { 869*6448Svikram BAM_DPRINTF((D_ENTRY_END, fcn)); 870*6448Svikram break; 871*6448Svikram } 872*6448Svikram } 873*6448Svikram } 874*6448Svikram 875*6448Svikram ret = msg ? BAM_MSG : BAM_SUCCESS; 876*6448Svikram BAM_DPRINTF((D_RETURN_RET, fcn, ret)); 877*6448Svikram return (ret); 878*6448Svikram } 879*6448Svikram 8803446Smrj /*ARGSUSED*/ 8813446Smrj error_t 882*6448Svikram upgrade_menu(menu_t *mp, char *osroot, char *menu_root) 8833446Smrj { 884*6448Svikram char *osdev; 885*6448Svikram char *grubsign; 886*6448Svikram char *grubroot; 887*6448Svikram int ret1; 888*6448Svikram int ret2; 889*6448Svikram int ret3; 890*6448Svikram const char *fcn = "upgrade_menu()"; 8915084Sjohnlev 892*6448Svikram assert(osroot); 893*6448Svikram assert(menu_root); 8943446Smrj 895*6448Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, menu_root)); 8963446Smrj 897*6448Svikram /* 898*6448Svikram * We only support upgrades. Xen may not be present 899*6448Svikram * on smaller metaclusters so we don't check for that. 900*6448Svikram */ 901*6448Svikram if (bam_is_findroot != BAM_FINDROOT_PRESENT || 902*6448Svikram bam_direct != BAM_DIRECT_DBOOT) { 903*6448Svikram bam_error(DOWNGRADE_NOTSUP, osroot); 904*6448Svikram return (BAM_ERROR); 9053446Smrj } 9063446Smrj 9073446Smrj /* 908*6448Svikram * First get the GRUB signature 9095084Sjohnlev */ 910*6448Svikram osdev = get_special(osroot); 911*6448Svikram INJECT_ERROR1("UPGRADE_OSDEV", osdev = NULL); 912*6448Svikram if (osdev == NULL) { 913*6448Svikram bam_error(CANT_FIND_SPECIAL, osroot); 914*6448Svikram return (BAM_ERROR); 915*6448Svikram } 916*6448Svikram 917*6448Svikram grubsign = get_grubsign(osroot, osdev); 918*6448Svikram INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign = NULL); 919*6448Svikram if (grubsign == NULL) { 920*6448Svikram free(osdev); 921*6448Svikram bam_error(CANT_FIND_GRUBSIGN, osroot); 922*6448Svikram return (BAM_ERROR); 9235084Sjohnlev } 9245084Sjohnlev 925*6448Svikram /* not fatal if we can't get grubroot */ 926*6448Svikram grubroot = get_grubroot(osroot, osdev, menu_root); 927*6448Svikram INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot = NULL); 928*6448Svikram 929*6448Svikram free(osdev); 930*6448Svikram 931*6448Svikram ret1 = bam_add_findroot(mp, grubsign, 932*6448Svikram grubroot, root_optional(osroot, menu_root)); 933*6448Svikram INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1 = BAM_ERROR); 934*6448Svikram if (ret1 == BAM_ERROR) 935*6448Svikram goto abort; 936*6448Svikram 937*6448Svikram ret2 = bam_add_hv(mp, grubsign, grubroot, 938*6448Svikram root_optional(osroot, menu_root)); 939*6448Svikram INJECT_ERROR1("UPGRADE_ADD_HV", ret2 = BAM_ERROR); 940*6448Svikram if (ret2 == BAM_ERROR) 941*6448Svikram goto abort; 942*6448Svikram 943*6448Svikram ret3 = bam_add_dboot(mp, osroot, grubsign, 944*6448Svikram grubroot, root_optional(osroot, menu_root)); 945*6448Svikram INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3 = BAM_ERROR); 946*6448Svikram if (ret3 == BAM_ERROR) 947*6448Svikram goto abort; 948*6448Svikram 949*6448Svikram if (ret1 == BAM_MSG || ret2 == BAM_MSG || ret3 == BAM_MSG) { 950*6448Svikram bam_error(CVT_TODO, MENU_URL(osroot)); 951*6448Svikram } else { 952*6448Svikram bam_warn_hand_entries(mp, osroot); 9533446Smrj } 954*6448Svikram 955*6448Svikram free(grubsign); 956*6448Svikram 957*6448Svikram BAM_DPRINTF((D_RETURN_RET, fcn, BAM_WRITE)); 9583446Smrj return (BAM_WRITE); 959*6448Svikram 960*6448Svikram abort: 961*6448Svikram free(grubsign); 962*6448Svikram bam_error(CVT_ABORT, osroot, MENU_URL(osroot)); 963*6448Svikram return (BAM_ERROR); 9643446Smrj } 965