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