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 /* 223446Smrj * Copyright 2007 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; 47*5084Sjohnlev hv_t bam_is_hv = BAM_HV_UNKNOWN; 483446Smrj 493446Smrj error_t 503446Smrj dboot_or_multiboot(const char *root) 513446Smrj { 523446Smrj char fname[PATH_MAX]; 533446Smrj char *image; 543446Smrj uchar_t *ident; 553446Smrj int fd, m; 563446Smrj multiboot_header_t *mbh; 57*5084Sjohnlev struct stat sb; 583446Smrj 593446Smrj (void) snprintf(fname, PATH_MAX, "%s/%s", root, 603446Smrj "platform/i86pc/kernel/unix"); 613446Smrj fd = open(fname, O_RDONLY); 623446Smrj if (fd < 0) { 633446Smrj bam_error(OPEN_FAIL, fname, strerror(errno)); 643446Smrj return (BAM_ERROR); 653446Smrj } 663446Smrj 673446Smrj /* 683446Smrj * mmap the first 8K 693446Smrj */ 703446Smrj image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0); 713446Smrj if (image == MAP_FAILED) { 723446Smrj bam_error(MMAP_FAIL, fname, strerror(errno)); 733446Smrj return (BAM_ERROR); 743446Smrj } 753446Smrj 763446Smrj ident = (uchar_t *)image; 773446Smrj if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || 783446Smrj ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) { 793446Smrj bam_error(NOT_ELF_FILE, fname); 803446Smrj return (BAM_ERROR); 813446Smrj } 823446Smrj if (ident[EI_CLASS] != ELFCLASS32) { 833446Smrj bam_error(WRONG_ELF_CLASS, fname, ident[EI_CLASS]); 843446Smrj return (BAM_ERROR); 853446Smrj } 863446Smrj 873446Smrj /* 883446Smrj * The GRUB multiboot header must be 32-bit aligned and completely 893446Smrj * contained in the 1st 8K of the file. If the unix binary has 903446Smrj * a multiboot header, then it is a 'dboot' kernel. Otherwise, 913446Smrj * this kernel must be booted via multiboot -- we call this a 923446Smrj * 'multiboot' kernel. 933446Smrj */ 943446Smrj bam_direct = BAM_DIRECT_MULTIBOOT; 953446Smrj for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) { 963446Smrj mbh = (void *)(image + m); 973446Smrj if (mbh->magic == MB_HEADER_MAGIC) { 983446Smrj bam_direct = BAM_DIRECT_DBOOT; 993446Smrj break; 1003446Smrj } 1013446Smrj } 1023446Smrj (void) munmap(image, 8192); 1033446Smrj (void) close(fd); 104*5084Sjohnlev 105*5084Sjohnlev if (bam_direct == BAM_DIRECT_DBOOT) { 106*5084Sjohnlev (void) snprintf(fname, PATH_MAX, "%s/%s", root, XEN_32); 107*5084Sjohnlev if (stat(fname, &sb) == 0) { 108*5084Sjohnlev bam_is_hv = BAM_HV_PRESENT; 109*5084Sjohnlev } else { 110*5084Sjohnlev bam_is_hv = BAM_HV_NO; 111*5084Sjohnlev } 112*5084Sjohnlev } 113*5084Sjohnlev 1143446Smrj return (BAM_SUCCESS); 1153446Smrj } 1163446Smrj 1173446Smrj #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE" 1183446Smrj 1193446Smrj /* 1203446Smrj * Return true if root has been bfu'ed. bfu will blow away 1213446Smrj * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can 1223446Smrj * assume the system has not been bfu'ed. 1233446Smrj */ 1243446Smrj static int 1253446Smrj is_bfu_system(const char *root) 1263446Smrj { 1273446Smrj static int is_bfu = -1; 1283446Smrj char path[PATH_MAX]; 1293446Smrj struct stat sb; 1303446Smrj 1313446Smrj if (is_bfu != -1) 1323446Smrj return (is_bfu); 1333446Smrj 1343446Smrj (void) snprintf(path, sizeof (path), "%s/%s", root, INST_RELEASE); 1353446Smrj if (stat(path, &sb) != 0) { 1363446Smrj is_bfu = 1; 1373446Smrj } else { 1383446Smrj is_bfu = 0; 1393446Smrj } 1403446Smrj return (is_bfu); 1413446Smrj } 1423446Smrj 1433446Smrj #define MENU_URL(root) (is_bfu_system(root) ? \ 1443446Smrj "http://www.sun.com/msg/SUNOS-8000-CF" : \ 1453446Smrj "http://www.sun.com/msg/SUNOS-8000-AK") 1463446Smrj 1473446Smrj /* 1483446Smrj * Simply allocate a new line and copy in cmd + sep + arg 1493446Smrj */ 1503446Smrj void 1513446Smrj update_line(line_t *linep) 1523446Smrj { 1533446Smrj size_t size; 1543446Smrj 1553446Smrj free(linep->line); 1563446Smrj size = strlen(linep->cmd) + strlen(linep->sep) + strlen(linep->arg) + 1; 1573446Smrj linep->line = s_calloc(1, size); 1583446Smrj (void) snprintf(linep->line, size, "%s%s%s", linep->cmd, linep->sep, 1593446Smrj linep->arg); 1603446Smrj } 1613446Smrj 1623446Smrj /* 1633446Smrj * The parse_kernel_line function examines a menu.lst kernel line. For 1643446Smrj * multiboot, this is: 1653446Smrj * 1663446Smrj * kernel <multiboot path> <flags1> <kernel path> <flags2> 1673446Smrj * 1683446Smrj * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot 1693446Smrj * 1703446Smrj * <kernel path> may be missing, or may be any full or relative path to unix. 1713446Smrj * We check for it by looking for a word ending in "/unix". If it ends 1723446Smrj * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in 1733446Smrj * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise, 1743446Smrj * it's a custom kernel, and we skip it. 1753446Smrj * 1763446Smrj * <flags*> are anything that doesn't fit either of the above - these will be 1773446Smrj * copied over. 1783446Smrj * 1793446Smrj * For direct boot, the defaults are 1803446Smrj * 1813446Smrj * kernel$ <kernel path> <flags> 1823446Smrj * 1833446Smrj * <kernel path> is one of: 1843446Smrj * /platform/i86pc/kernel/$ISADIR/unix 1853446Smrj * /platform/i86pc/kernel/unix 1863446Smrj * /platform/i86pc/kernel/amd64/unix 1873446Smrj * /boot/platform/i86pc/kernel/unix 1883446Smrj * 1893446Smrj * If <kernel path> is any of the last three, the command may also be "kernel". 1903446Smrj * 1913446Smrj * <flags> is anything that isn't <kernel path>. 1923446Smrj * 1933446Smrj * This function is only called if it applies to our target boot environment. 1943446Smrj * If we can't make any sense of the kernel line, an error is printed and 1953446Smrj * BAM_ERROR is returned. 1963446Smrj * 1973446Smrj * The desired install type is given in the global variable bam_direct. 1983446Smrj * If the kernel line is of a different install type, we change it to the 1993446Smrj * preferred type. If the kernel line is already of the correct install 2003446Smrj * type, we do nothing. Either way, BAM_SUCCESS is returned. 2013446Smrj * 2023446Smrj * For safety, we do one more check: if the kernel path starts with /boot, 2033446Smrj * we verify that the new kernel exists before changing it. This is mainly 2043446Smrj * done for bfu, as it may cause the failsafe archives to be a different 2053446Smrj * boot architecture from the newly bfu'ed system. 2063446Smrj */ 2073446Smrj static error_t 2083446Smrj parse_kernel_line(line_t *linep, const char *root, uint8_t *flags) 2093446Smrj { 2103446Smrj char path[PATH_MAX]; 2113446Smrj int len, left, total_len; 2123446Smrj struct stat sb; 2133446Smrj char *new_ptr, *new_arg, *old_ptr; 2143446Smrj menu_cmd_t which; 2153446Smrj 2163446Smrj /* Used when changing a multiboot line to dboot */ 2173446Smrj char *unix_ptr, *flags1_ptr, *flags2_ptr; 2183446Smrj 2193446Smrj /* 2203446Smrj * Note that BAM_ENTRY_DBOOT refers to the entry we're looking at, not 2213446Smrj * necessarily the system type. 2223446Smrj */ 2233446Smrj if (strncmp(linep->arg, DIRECT_BOOT_32, 2243446Smrj sizeof (DIRECT_BOOT_32) - 1) == 0) { 2253446Smrj *flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_32BIT; 2263446Smrj } else if ((strncmp(linep->arg, DIRECT_BOOT_KERNEL, 2273446Smrj sizeof (DIRECT_BOOT_KERNEL) - 1) == 0) || 2283446Smrj (strncmp(linep->arg, DIRECT_BOOT_64, 2293446Smrj sizeof (DIRECT_BOOT_64) - 1) == 0) || 2303446Smrj (strncmp(linep->arg, DIRECT_BOOT_FAILSAFE_KERNEL, 2313446Smrj sizeof (DIRECT_BOOT_FAILSAFE_KERNEL) - 1) == 0)) { 2323446Smrj *flags |= BAM_ENTRY_DBOOT; 2333446Smrj } else if ((strncmp(linep->arg, MULTI_BOOT, 2343446Smrj sizeof (MULTI_BOOT) - 1) == 0) || 2353446Smrj (strncmp(linep->arg, MULTI_BOOT_FAILSAFE, 2363446Smrj sizeof (MULTI_BOOT_FAILSAFE) - 1) == 0)) { 2373446Smrj *flags &= ~BAM_ENTRY_DBOOT; 2383446Smrj } else { 2393446Smrj bam_error(NO_KERNEL_MATCH, linep->lineNum, MENU_URL(root)); 2403446Smrj return (BAM_ERROR); 2413446Smrj } 2423446Smrj 2433446Smrj if (((*flags & BAM_ENTRY_DBOOT) && (bam_direct == BAM_DIRECT_DBOOT)) || 2443446Smrj (((*flags & BAM_ENTRY_DBOOT) == 0) && 2453446Smrj (bam_direct == BAM_DIRECT_MULTIBOOT))) { 2463446Smrj 2473446Smrj /* No action needed */ 2483446Smrj return (BAM_SUCCESS); 2493446Smrj } 2503446Smrj 2513446Smrj if (*flags & BAM_ENTRY_MINIROOT) { 2523446Smrj /* 2533446Smrj * We're changing boot architectures - make sure 2543446Smrj * the multiboot failsafe still exists. 2553446Smrj */ 2563446Smrj (void) snprintf(path, PATH_MAX, "%s%s", root, 2573446Smrj (*flags & BAM_ENTRY_DBOOT) ? MULTI_BOOT_FAILSAFE : 2583446Smrj DIRECT_BOOT_FAILSAFE_KERNEL); 2593446Smrj if (stat(path, &sb) != 0) { 2603446Smrj if (bam_verbose) { 2613446Smrj bam_error(FAILSAFE_MISSING, linep->lineNum); 2623446Smrj } 2633446Smrj return (BAM_SUCCESS); 2643446Smrj } 2653446Smrj } 2663446Smrj 2673446Smrj /* 2683446Smrj * Make sure we have the correct cmd - either kernel or kernel$ 2693446Smrj * The failsafe entry should always be KERNEL_CMD. 2703446Smrj */ 2713446Smrj which = ((bam_direct == BAM_DIRECT_MULTIBOOT) || 2723446Smrj (*flags & BAM_ENTRY_MINIROOT)) ? KERNEL_CMD : KERNEL_DOLLAR_CMD; 2733446Smrj free(linep->cmd); 2743446Smrj len = strlen(menu_cmds[which]) + 1; 2753446Smrj linep->cmd = s_calloc(1, len); 2763446Smrj (void) strncpy(linep->cmd, menu_cmds[which], len); 2773446Smrj 2783446Smrj /* 2793446Smrj * Since all arguments are copied, the new arg string should be close 2803446Smrj * in size to the old one. Just add 32 to cover the difference in 2813446Smrj * the boot path. 2823446Smrj */ 2833446Smrj total_len = strlen(linep->arg) + 32; 2843446Smrj new_arg = s_calloc(1, total_len); 2853446Smrj old_ptr = strchr(linep->arg, ' '); 2863446Smrj if (old_ptr != NULL) 2873446Smrj old_ptr++; 2883446Smrj 2893446Smrj /* 2903446Smrj * Transitioning from dboot to multiboot is pretty simple. We 2913446Smrj * copy in multiboot and any args. 2923446Smrj */ 2933446Smrj if (bam_direct == BAM_DIRECT_MULTIBOOT) { 2943446Smrj if (old_ptr == NULL) { 2953446Smrj (void) snprintf(new_arg, total_len, "%s", 2963446Smrj (*flags & BAM_ENTRY_MINIROOT) ? 2973446Smrj MULTI_BOOT_FAILSAFE : MULTI_BOOT); 2983446Smrj } else { 2993446Smrj (void) snprintf(new_arg, total_len, "%s %s", 3003446Smrj (*flags & BAM_ENTRY_MINIROOT) ? 3013446Smrj MULTI_BOOT_FAILSAFE : MULTI_BOOT, old_ptr); 3023446Smrj } 3033446Smrj goto done; 3043446Smrj } 3053446Smrj 3063446Smrj /* 3073446Smrj * Transitioning from multiboot to directboot is a bit more 3083446Smrj * complicated, since we may have two sets of arguments to 3093446Smrj * copy and a unix path to parse. 3103446Smrj * 3113446Smrj * First, figure out if there's a unix path. 3123446Smrj */ 3133446Smrj if ((old_ptr != NULL) && 3143446Smrj ((unix_ptr = strstr(old_ptr, "/unix")) != NULL)) { 3153446Smrj /* See if there's anything past unix */ 3163446Smrj flags2_ptr = unix_ptr + sizeof ("/unix"); 3173446Smrj if (*flags2_ptr == '\0') { 3183446Smrj flags2_ptr = NULL; 3193446Smrj } 3203446Smrj 3213446Smrj while ((unix_ptr > old_ptr) && (*unix_ptr != ' ')) 3223446Smrj unix_ptr--; 3233446Smrj 3243446Smrj if (unix_ptr == old_ptr) { 3253446Smrj flags1_ptr = NULL; 3263446Smrj } else { 3273446Smrj flags1_ptr = old_ptr; 3283446Smrj } 3293446Smrj 3303446Smrj if (strstr(unix_ptr, "kernel/unix") != NULL) { 3313446Smrj *flags |= BAM_ENTRY_32BIT; 3323446Smrj } else if ((strstr(unix_ptr, "kernel/amd64/unix") == NULL) && 3333446Smrj (!bam_force)) { 3343446Smrj /* 3353446Smrj * If the above strstr returns NULL, but bam_force is 3363446Smrj * set, we'll be upgrading an Install kernel. The 3373446Smrj * result probably won't be what was intended, but we'll 3383446Smrj * try it anyways. 3393446Smrj */ 3403446Smrj return (BAM_SKIP); 3413446Smrj } 3423446Smrj } else if (old_ptr != NULL) { 3433446Smrj flags1_ptr = old_ptr; 3443446Smrj unix_ptr = flags1_ptr + strlen(old_ptr); 3453446Smrj flags2_ptr = NULL; 3463446Smrj } else { 3473446Smrj unix_ptr = flags1_ptr = flags2_ptr = NULL; 3483446Smrj } 3493446Smrj 3503446Smrj if (*flags & BAM_ENTRY_MINIROOT) { 3513446Smrj (void) snprintf(new_arg, total_len, "%s", 3523446Smrj DIRECT_BOOT_FAILSAFE_KERNEL); 3533446Smrj } else if (*flags & BAM_ENTRY_32BIT) { 3543446Smrj (void) snprintf(new_arg, total_len, "%s", DIRECT_BOOT_32); 3553446Smrj } else { 3563446Smrj (void) snprintf(new_arg, total_len, "%s", DIRECT_BOOT_KERNEL); 3573446Smrj } 3583446Smrj 3593446Smrj /* 3603446Smrj * We now want to copy flags1_ptr through unix_ptr, and 3613446Smrj * flags2_ptr through the end of the string 3623446Smrj */ 3633446Smrj if (flags1_ptr != NULL) { 3643446Smrj len = strlcat(new_arg, " ", total_len); 3653446Smrj left = total_len - len; 3663446Smrj new_ptr = new_arg + len; 3673446Smrj 3683446Smrj if ((unix_ptr - flags1_ptr) < left) 3693446Smrj left = (unix_ptr - flags1_ptr) + 1; 3703446Smrj (void) strlcpy(new_ptr, flags1_ptr, left); 3713446Smrj } 3723446Smrj if (flags2_ptr != NULL) { 3733446Smrj (void) strlcat(new_arg, " ", total_len); 3743446Smrj (void) strlcat(new_arg, flags2_ptr, total_len); 3753446Smrj } 3763446Smrj 3773446Smrj done: 3783446Smrj free(linep->arg); 3793446Smrj linep->arg = new_arg; 3803446Smrj update_line(linep); 3813446Smrj return (BAM_SUCCESS); 3823446Smrj } 3833446Smrj 3843446Smrj /* 3853446Smrj * Similar to above, except this time we're looking at a module line, 3863446Smrj * which is quite a bit simpler. 3873446Smrj * 3883446Smrj * Under multiboot, the archive line is: 3893446Smrj * 3903446Smrj * module /platform/i86pc/boot_archive 3913446Smrj * 3923446Smrj * Under directboot, the archive line is: 3933446Smrj * 3943446Smrj * module$ /platform/i86pc/$ISADIR/boot_archive 3953446Smrj * 3963446Smrj * which may be specified exactly as either of: 3973446Smrj * 3983446Smrj * module /platform/i86pc/boot_archive 3993446Smrj * module /platform/i86pc/amd64/boot_archive 4003446Smrj * 4013446Smrj * For either dboot or multiboot, the failsafe is: 4023446Smrj * 4033446Smrj * module /boot/x86.miniroot-safe 4043446Smrj */ 4053446Smrj static error_t 4063446Smrj parse_module_line(line_t *linep, const char *root, uint8_t flags) 4073446Smrj { 4083446Smrj int len; 4093446Smrj menu_cmd_t which; 4103446Smrj char *new; 4113446Smrj 4123446Smrj /* 4133446Smrj * If necessary, BAM_ENTRY_MINIROOT was already set in flags 4143446Smrj * in upgrade_menu(). We re-check BAM_ENTRY_DBOOT here in here 4153446Smrj * in case the kernel and module lines differ. 4163446Smrj */ 4173446Smrj if ((strcmp(linep->arg, DIRECT_BOOT_ARCHIVE) == 0) || 4183446Smrj (strcmp(linep->arg, DIRECT_BOOT_ARCHIVE_64) == 0)) { 4193446Smrj flags |= BAM_ENTRY_DBOOT; 4203446Smrj } else if ((strcmp(linep->arg, MULTI_BOOT_ARCHIVE) == 0) || 4213446Smrj (strcmp(linep->arg, MINIROOT) == 0)) { 4223446Smrj flags &= ~BAM_ENTRY_DBOOT; 4233446Smrj } else { 4243446Smrj bam_error(NO_MODULE_MATCH, linep->lineNum, MENU_URL(root)); 4253446Smrj return (BAM_ERROR); 4263446Smrj } 4273446Smrj 4283446Smrj if (((flags & BAM_ENTRY_DBOOT) && (bam_direct == BAM_DIRECT_DBOOT)) || 4293446Smrj (((flags & BAM_ENTRY_DBOOT) == 0) && 4303446Smrj (bam_direct == BAM_DIRECT_MULTIBOOT)) || 4313446Smrj ((flags & BAM_ENTRY_MINIROOT) && 4323446Smrj (strcmp(linep->cmd, menu_cmds[MODULE_CMD]) == 0))) { 4333446Smrj 4343446Smrj /* No action needed */ 4353446Smrj return (BAM_SUCCESS); 4363446Smrj } 4373446Smrj 4383446Smrj /* 4393446Smrj * Make sure we have the correct cmd - either module or module$ 4403446Smrj * The failsafe entry should always be MODULE_CMD. 4413446Smrj */ 4423446Smrj which = ((bam_direct == BAM_DIRECT_MULTIBOOT) || 4433446Smrj (flags & BAM_ENTRY_MINIROOT)) ? MODULE_CMD : MODULE_DOLLAR_CMD; 4443446Smrj free(linep->cmd); 4453446Smrj len = strlen(menu_cmds[which]) + 1; 4463446Smrj linep->cmd = s_calloc(1, len); 4473446Smrj (void) strncpy(linep->cmd, menu_cmds[which], len); 4483446Smrj 4493446Smrj if (flags & BAM_ENTRY_MINIROOT) { 4503446Smrj new = MINIROOT; 4513446Smrj } else if ((bam_direct == BAM_DIRECT_DBOOT) && 4523446Smrj ((flags & BAM_ENTRY_32BIT) == 0)) { 4533446Smrj new = DIRECT_BOOT_ARCHIVE; 4543446Smrj } else { 4553446Smrj new = MULTI_BOOT_ARCHIVE; 4563446Smrj } 4573446Smrj 4583446Smrj free(linep->arg); 4593446Smrj len = strlen(new) + 1; 4603446Smrj linep->arg = s_calloc(1, len); 4613446Smrj (void) strncpy(linep->arg, new, len); 4623446Smrj update_line(linep); 4633446Smrj 4643446Smrj return (BAM_SUCCESS); 4653446Smrj } 4663446Smrj 4673446Smrj /*ARGSUSED*/ 4683446Smrj error_t 4693446Smrj upgrade_menu(menu_t *mp, char *root, char *opt) 4703446Smrj { 4713446Smrj entry_t *cur_entry; 4723446Smrj line_t *cur_line; 473*5084Sjohnlev int i, skipit, num_entries, found_hv; 4743446Smrj int *hand_entries = NULL; 4753446Smrj boolean_t found_kernel = B_FALSE; 4763446Smrj error_t rv; 4773446Smrj char *rootdev, *grubdisk = NULL; 4783446Smrj 479*5084Sjohnlev skipit = num_entries = found_hv = 0; 480*5084Sjohnlev 4813446Smrj rootdev = get_special(root); 4823446Smrj if (rootdev) { 4833446Smrj grubdisk = os_to_grubdisk(rootdev, strlen(root) == 1); 4843446Smrj free(rootdev); 4853446Smrj rootdev = NULL; 4863446Smrj } 4873446Smrj 4883446Smrj /* Loop through all OS entries in the menu.lst file */ 4893446Smrj for (cur_entry = mp->entries; cur_entry != NULL; 4903446Smrj cur_entry = cur_entry->next, skipit = 0) { 4913446Smrj 4923446Smrj if ((cur_entry->flags & BAM_ENTRY_CHAINLOADER) || 4933446Smrj ((cur_entry->flags & BAM_ENTRY_MINIROOT) && !bam_force)) 4943446Smrj continue; 4953446Smrj 4963446Smrj /* 4973446Smrj * We only change entries added by bootadm and live upgrade, 4983446Smrj * and warn on the rest, unless the -f flag was passed. 4993446Smrj */ 5003446Smrj if ((!(cur_entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))) && 5013446Smrj !bam_force) { 5023446Smrj if (num_entries == 0) { 5033446Smrj hand_entries = s_calloc(1, sizeof (int)); 5043446Smrj } else { 5053446Smrj hand_entries = s_realloc(hand_entries, 5063446Smrj (num_entries + 1) * sizeof (int)); 5073446Smrj } 5083446Smrj hand_entries[num_entries++] = cur_entry->entryNum; 5093446Smrj continue; 5103446Smrj } 5113446Smrj 512*5084Sjohnlev if (cur_entry->flags & BAM_ENTRY_HV) { 513*5084Sjohnlev found_hv = 1; 514*5084Sjohnlev continue; 515*5084Sjohnlev } 516*5084Sjohnlev 5173446Smrj /* 5183446Smrj * We make two loops through the lines. First, we check if 5193446Smrj * there is a root entry, and if so, whether we should be 5203446Smrj * checking this entry. 5213446Smrj */ 5223446Smrj if ((grubdisk != NULL) && (cur_entry->flags & BAM_ENTRY_ROOT)) { 5233446Smrj for (cur_line = cur_entry->start; cur_line != NULL; 5243446Smrj cur_line = cur_line->next) { 5253446Smrj if ((cur_line->cmd == NULL) || 5263446Smrj (cur_line->arg == NULL)) 5273446Smrj continue; 5283446Smrj 5293446Smrj if (strcmp(cur_line->cmd, 5303446Smrj menu_cmds[ROOT_CMD]) == 0) { 5313446Smrj if (strcmp(cur_line->arg, 5323446Smrj grubdisk) != 0) { 5333446Smrj /* A different slice */ 5343446Smrj skipit = 1; 5353446Smrj } 5363446Smrj break; 5373446Smrj } 5383446Smrj if (cur_line == cur_entry->end) 5393446Smrj break; 5403446Smrj } 5413446Smrj } 5423446Smrj if (skipit) 5433446Smrj continue; 5443446Smrj 5453446Smrj for (cur_line = cur_entry->start; cur_line != NULL; 5463446Smrj cur_line = cur_line->next) { 5473446Smrj 5483446Smrj /* 5493446Smrj * We only compare for the length of KERNEL_CMD, 5503446Smrj * so that KERNEL_DOLLAR_CMD will also match. 5513446Smrj */ 5523446Smrj if (strncmp(cur_line->cmd, menu_cmds[KERNEL_CMD], 5533446Smrj strlen(menu_cmds[KERNEL_CMD])) == 0) { 5543446Smrj rv = parse_kernel_line(cur_line, root, 5553446Smrj &(cur_entry->flags)); 5563446Smrj if (rv == BAM_SKIP) { 5573446Smrj break; 5583446Smrj } else if (rv != BAM_SUCCESS) { 5593446Smrj return (rv); 5603446Smrj } 5613446Smrj found_kernel = B_TRUE; 5623446Smrj } else if (strncmp(cur_line->cmd, 5633446Smrj menu_cmds[MODULE_CMD], 5643446Smrj strlen(menu_cmds[MODULE_CMD])) == 0) { 5653446Smrj rv = parse_module_line(cur_line, root, 5663446Smrj cur_entry->flags); 5673446Smrj if (rv != BAM_SUCCESS) { 5683446Smrj return (rv); 5693446Smrj } 5703446Smrj } 5713446Smrj if (cur_line == cur_entry->end) 5723446Smrj break; 5733446Smrj } 5743446Smrj } 5753446Smrj 5763446Smrj /* 577*5084Sjohnlev * If we're upgrading to a virtualized kernel and there are no 578*5084Sjohnlev * hv entries in menu.lst, we need to add one. 579*5084Sjohnlev */ 580*5084Sjohnlev if ((bam_is_hv == BAM_HV_PRESENT) && (found_hv == 0)) { 581*5084Sjohnlev (void) add_boot_entry(mp, NEW_HV_ENTRY, grubdisk, 582*5084Sjohnlev XEN_MENU, KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE); 583*5084Sjohnlev } 584*5084Sjohnlev 585*5084Sjohnlev /* 5863446Smrj * We only want to output one error, to avoid confusing a user. We 5873446Smrj * rank "No kernels changed" as a higher priority than "will not 5883446Smrj * update hand-added entries", since the former implies the latter. 5893446Smrj */ 5903446Smrj if (found_kernel == B_FALSE) { 5913446Smrj bam_error(NO_KERNELS_FOUND, MENU_URL(root)); 5923446Smrj return (BAM_ERROR); 5933446Smrj } else if (num_entries > 0) { 5943446Smrj bam_error(HAND_ADDED_ENTRY, MENU_URL(root)); 5953446Smrj bam_print_stderr("Entry Number%s: ", (num_entries > 1) ? 5963446Smrj "s" : ""); 5973446Smrj for (i = 0; i < num_entries; i++) { 5983446Smrj bam_print_stderr("%d ", hand_entries[i]); 5993446Smrj } 6003446Smrj bam_print_stderr("\n"); 6013446Smrj } 6023446Smrj return (BAM_WRITE); 6033446Smrj } 604