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.
24719db50fSToomas 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
get_findroot_cap(const char * osroot)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;
65c262cbbcSToomas 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) {
73c262cbbcSToomas Soome bam_error(_("failed to open file: %s: %s\n"), path,
74c262cbbcSToomas 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) {
81c262cbbcSToomas Soome BAM_DPRINTF(("%s: findroot capability present\n", fcn));
82eb2bd662Svikram bam_is_findroot = BAM_FINDROOT_PRESENT;
83eb2bd662Svikram }
84eb2bd662Svikram if (strcmp(buf, "dboot") == 0) {
85c262cbbcSToomas 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;
94c262cbbcSToomas Soome BAM_DPRINTF(("%s: findroot capability absent\n", fcn));
95eb2bd662Svikram }
963bbf88b3SToomas Soome
97eb2bd662Svikram ret = fclose(fp);
98eb2bd662Svikram error = errno;
99eb2bd662Svikram INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret = 1);
100eb2bd662Svikram if (ret != 0) {
101c262cbbcSToomas Soome bam_error(_("failed to close file: %s: %s\n"),
102c262cbbcSToomas Soome path, strerror(error));
103eb2bd662Svikram }
104eb2bd662Svikram }
105ae115bc7Smrj
106ae115bc7Smrj error_t
get_boot_cap(const char * osroot)107eb2bd662Svikram get_boot_cap(const char *osroot)
108ae115bc7Smrj {
109eb2bd662Svikram char fname[PATH_MAX];
110eb2bd662Svikram char *image;
111eb2bd662Svikram uchar_t *ident;
112719db50fSToomas Soome uchar_t class;
113eb2bd662Svikram int fd;
114eb2bd662Svikram int m;
115ae115bc7Smrj multiboot_header_t *mbh;
116eb2bd662Svikram 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;
123c262cbbcSToomas Soome BAM_DPRINTF(("%s: is sparc - always DBOOT\n", fcn));
124986fd29aSsetje return (BAM_SUCCESS);
125986fd29aSsetje }
126986fd29aSsetje
127719db50fSToomas Soome /*
128719db50fSToomas Soome * The install media can support both 64 and 32 bit boot
129719db50fSToomas Soome * by using boot archive as ramdisk image. However, to save
130719db50fSToomas Soome * the memory, the ramdisk may only have either 32 or 64
131719db50fSToomas Soome * bit kernel files. To avoid error message about missing unix,
132719db50fSToomas Soome * we should try both variants here and only complain if neither
133719db50fSToomas Soome * is found. Since the 64-bit systems are more common, we start
134719db50fSToomas Soome * from amd64.
135719db50fSToomas Soome */
136719db50fSToomas Soome class = ELFCLASS64;
137eb2bd662Svikram (void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
138719db50fSToomas Soome "platform/i86pc/kernel/amd64/unix");
139ae115bc7Smrj fd = open(fname, O_RDONLY);
140719db50fSToomas Soome if (fd < 0) {
141719db50fSToomas Soome class = ELFCLASS32;
142719db50fSToomas Soome (void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
143719db50fSToomas Soome "platform/i86pc/kernel/unix");
144719db50fSToomas Soome fd = open(fname, O_RDONLY);
145719db50fSToomas Soome }
146eb2bd662Svikram error = errno;
147eb2bd662Svikram INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd = -1);
148ae115bc7Smrj if (fd < 0) {
149c262cbbcSToomas Soome bam_error(_("failed to open file: %s: %s\n"), fname,
150c262cbbcSToomas 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);
159c262cbbcSToomas 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) {
170c262cbbcSToomas Soome bam_error(_("failed to mmap file: %s: %s\n"), fname,
171c262cbbcSToomas 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) {
178c262cbbcSToomas Soome bam_error(_("%s is not an ELF file.\n"), fname);
179ae115bc7Smrj return (BAM_ERROR);
180ae115bc7Smrj }
181719db50fSToomas Soome if (ident[EI_CLASS] != class) {
182c262cbbcSToomas Soome bam_error(_("%s is wrong ELF class 0x%x\n"), fname,
183c262cbbcSToomas 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) {
198c262cbbcSToomas 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) {
209c262cbbcSToomas Soome BAM_DPRINTF(("%s: is xVM system\n", fcn));
210843e1988Sjohnlev } else {
211c262cbbcSToomas Soome BAM_DPRINTF(("%s: is *NOT* xVM system\n", fcn));
212843e1988Sjohnlev }
213eb2bd662Svikram } else {
214c262cbbcSToomas 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
220c262cbbcSToomas 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
is_bfu_system(const char * root)232ae115bc7Smrj is_bfu_system(const char *root)
233ae115bc7Smrj {
234eb2bd662Svikram static int is_bfu = -1;
235eb2bd662Svikram char path[PATH_MAX];
236eb2bd662Svikram struct stat sb;
237eb2bd662Svikram const char *fcn = "is_bfu_system()";
238ae115bc7Smrj
239eb2bd662Svikram if (is_bfu != -1) {
240c262cbbcSToomas Soome BAM_DPRINTF(("%s: already done bfu test. bfu is %s present\n",
241c262cbbcSToomas 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;
248c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
249ae115bc7Smrj } else {
250ae115bc7Smrj is_bfu = 0;
251c262cbbcSToomas 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
update_line(line_t * linep)264ae115bc7Smrj update_line(line_t *linep)
265ae115bc7Smrj {
266eb2bd662Svikram size_t size;
267eb2bd662Svikram const char *fcn = "update_line()";
268ae115bc7Smrj
269c262cbbcSToomas 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);
275c262cbbcSToomas Soome BAM_DPRINTF(("%s: line after update: %s\n", fcn, linep->line));
276eb2bd662Svikram }
277eb2bd662Svikram
278eb2bd662Svikram static char *
skip_wspace(char * ptr)279eb2bd662Svikram skip_wspace(char *ptr)
280eb2bd662Svikram {
281eb2bd662Svikram const char *fcn = "skip_wspace()";
282eb2bd662Svikram
283eb2bd662Svikram INJECT_ERROR1("SKIP_WSPACE", ptr = NULL);
284eb2bd662Svikram if (ptr == NULL) {
285c262cbbcSToomas Soome BAM_DPRINTF(("%s: NULL ptr\n", fcn));
286eb2bd662Svikram return (NULL);
287eb2bd662Svikram }
288eb2bd662Svikram
289c262cbbcSToomas 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
298c262cbbcSToomas Soome BAM_DPRINTF(("%s: ptr on exit: %s\n", fcn, ptr ? ptr : "NULL"));
299eb2bd662Svikram
300eb2bd662Svikram return (ptr);
301eb2bd662Svikram }
302eb2bd662Svikram
303eb2bd662Svikram static char *
rskip_bspace(char * bound,char * ptr)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
312c262cbbcSToomas 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
318c262cbbcSToomas 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
cvt_kernel_line(line_t * line,const char * osroot,entry_t * entry)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()";
374eb2bd662Svikram
375c262cbbcSToomas 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)) {
381c262cbbcSToomas 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 */
393c262cbbcSToomas 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) {
400c262cbbcSToomas Soome bam_error(_("bootadm -m upgrade run, but the "
401c262cbbcSToomas Soome "failsafe archives have not been\nupdated. "
402c262cbbcSToomas Soome "Not updating line %d\n"), line->lineNum);
403ae115bc7Smrj }
404c262cbbcSToomas Soome BAM_DPRINTF(("%s: no FAILSAFE unix, not converting\n",
405c262cbbcSToomas 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
414bbcc54bdSEnrico Perla - Sun Microsystems free(line->cmd);
415bbcc54bdSEnrico Perla - Sun Microsystems line->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
416c262cbbcSToomas 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);
423eb2bd662Svikram 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;
429c262cbbcSToomas 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 */
4373bbf88b3SToomas Soome if ((unix_ptr = strstr(old_ptr, "/unix")) != NULL) {
438eb2bd662Svikram
439eb2bd662Svikram /*
440eb2bd662Svikram * There is a unix.
441eb2bd662Svikram */
442c262cbbcSToomas 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) {
448c262cbbcSToomas Soome BAM_DPRINTF(("%s: flags2 present: %s\n", fcn,
449c262cbbcSToomas Soome flags2_ptr));
450eb2bd662Svikram } else {
451c262cbbcSToomas 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;
459c262cbbcSToomas Soome BAM_DPRINTF(("%s: flags1 absent\n", fcn));
460ae115bc7Smrj } else {
461ae115bc7Smrj flags1_ptr = old_ptr;
462eb2bd662Svikram *unix_ptr = '\0';
463eb2bd662Svikram unix_ptr++;
464c262cbbcSToomas Soome BAM_DPRINTF(("%s: flags1 present: %s\n", fcn,
465c262cbbcSToomas Soome flags1_ptr));
466ae115bc7Smrj }
467ae115bc7Smrj
468eb2bd662Svikram } else {
469eb2bd662Svikram /* There is no unix, there is only a bunch of flags */
470ae115bc7Smrj flags1_ptr = old_ptr;
471eb2bd662Svikram unix_ptr = flags2_ptr = NULL;
472c262cbbcSToomas Soome BAM_DPRINTF(("%s: flags1 present: %s, unix, flags2 absent\n",
473c262cbbcSToomas Soome fcn, flags1_ptr));
474ae115bc7Smrj }
475ae115bc7Smrj
476eb2bd662Svikram /*
477eb2bd662Svikram * With dboot, unix is fixed and is at the beginning. We need to
478eb2bd662Svikram * migrate flags1 and flags2
479eb2bd662Svikram */
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 }
488c262cbbcSToomas 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
500c262cbbcSToomas 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);
505c262cbbcSToomas 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
cvt_module_line(line_t * line,entry_t * entry)540eb2bd662Svikram cvt_module_line(line_t *line, entry_t *entry)
541ae115bc7Smrj {
542eb2bd662Svikram const char *fcn = "cvt_module_line()";
543eb2bd662Svikram
544c262cbbcSToomas 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)) {
550c262cbbcSToomas Soome BAM_DPRINTF(("%s: not MULTIBOOT, not converting\n", fcn));
551eb2bd662Svikram return (BAM_SUCCESS);
552ae115bc7Smrj }
553ae115bc7Smrj
554eb2bd662Svikram if (entry->flags & BAM_ENTRY_FAILSAFE) {
555eb2bd662Svikram if (strcmp(line->arg, FAILSAFE_ARCHIVE) == 0) {
556c262cbbcSToomas Soome BAM_DPRINTF(("%s: failsafe module line needs no "
557c262cbbcSToomas Soome "conversion: %s\n", fcn, line->arg));
558c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
559eb2bd662Svikram return (BAM_SUCCESS);
560eb2bd662Svikram }
561eb2bd662Svikram } else if (strcmp(line->arg, MULTIBOOT_ARCHIVE) != 0) {
562c262cbbcSToomas Soome bam_error(_("module command on line %d not recognized.\n"),
563c262cbbcSToomas Soome line->lineNum);
564c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning FAILURE\n", fcn));
565eb2bd662Svikram return (BAM_MSG);
566ae115bc7Smrj }
567ae115bc7Smrj
568bbcc54bdSEnrico Perla - Sun Microsystems free(line->cmd);
569bbcc54bdSEnrico Perla - Sun Microsystems free(line->arg);
570bbcc54bdSEnrico Perla - Sun Microsystems 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);
574ae115bc7Smrj
575eb2bd662Svikram update_line(line);
576c262cbbcSToomas Soome BAM_DPRINTF(("%s: converted module line is: %s\n", fcn, line->line));
577c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
578ae115bc7Smrj return (BAM_SUCCESS);
579ae115bc7Smrj }
580ae115bc7Smrj
581eb2bd662Svikram static void
bam_warn_hand_entries(menu_t * mp,char * osroot)582eb2bd662Svikram bam_warn_hand_entries(menu_t *mp, char *osroot)
583ae115bc7Smrj {
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 */
596c262cbbcSToomas Soome BAM_DPRINTF(("%s: force specified, no warnings about hand "
597c262cbbcSToomas Soome "entries\n", fcn));
598eb2bd662Svikram return;
599eb2bd662Svikram }
600ae115bc7Smrj
601eb2bd662Svikram hand_num = 0;
602eb2bd662Svikram hand_max = BAM_ENTRY_NUM;
603eb2bd662Svikram hand_list = s_calloc(1, hand_max);
604843e1988Sjohnlev
605eb2bd662Svikram for (entry = mp->entries; entry; entry = entry->next) {
606eb2bd662Svikram if (entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))
607eb2bd662Svikram continue;
608c262cbbcSToomas Soome BAM_DPRINTF(("%s: found hand entry #: %d\n", fcn,
609c262cbbcSToomas 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;
616ae115bc7Smrj }
617ae115bc7Smrj
618*bbf21555SRichard Lowe bam_error(_("bootadm(8) will only upgrade GRUB menu entries added "
619*bbf21555SRichard Lowe "by \nbootadm(8) or lu(8). The following entries on %s will "
620c262cbbcSToomas Soome "not be upgraded.\nFor details on manually updating entries, "
621c262cbbcSToomas 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 }
629ae115bc7Smrj
630eb2bd662Svikram static entry_t *
find_matching_entry(entry_t * estart,char * grubsign,char * grubroot,int root_opt)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()";
641ae115bc7Smrj
642eb2bd662Svikram assert(grubsign);
643eb2bd662Svikram assert(root_opt == 0 || root_opt == 1);
644eb2bd662Svikram
645eb2bd662Svikram (void) snprintf(opt, sizeof (opt), "%d", root_opt);
646c262cbbcSToomas Soome BAM_DPRINTF(("%s: entered. args: %s %s %s\n", fcn, grubsign,
647c262cbbcSToomas Soome grubroot, opt));
648ae115bc7Smrj
649eb2bd662Svikram for (entry = estart; entry; entry = entry->next) {
650963390b4Svikram
651eb2bd662Svikram if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) &&
652eb2bd662Svikram !bam_force) {
653c262cbbcSToomas Soome BAM_DPRINTF(("%s: skipping hand entry #: %d\n",
654c262cbbcSToomas Soome fcn, entry->entryNum));
655843e1988Sjohnlev continue;
656843e1988Sjohnlev }
657843e1988Sjohnlev
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) {
662c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has "
663c262cbbcSToomas Soome "ended\n", fcn));
664eb2bd662Svikram break;
665eb2bd662Svikram } else {
666c262cbbcSToomas Soome BAM_DPRINTF(("%s: skipping "
667c262cbbcSToomas Soome "NULL line\n", fcn));
668eb2bd662Svikram continue;
669ae115bc7Smrj }
670eb2bd662Svikram }
671eb2bd662Svikram if (strcmp(line->cmd, menu_cmds[ROOT_CMD])
672eb2bd662Svikram == 0 && strcmp(line->arg, grubroot) == 0) {
673c262cbbcSToomas Soome BAM_DPRINTF(("%s: found matching root "
674c262cbbcSToomas Soome "line: %s,%s\n", fcn,
675eb2bd662Svikram line->line, grubsign));
676eb2bd662Svikram return (entry);
677eb2bd662Svikram }
678eb2bd662Svikram if (line == entry->end) {
679c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has ended\n",
680c262cbbcSToomas Soome fcn));
681ae115bc7Smrj break;
682ae115bc7Smrj }
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) {
688c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has "
689c262cbbcSToomas Soome "ended\n", fcn));
690eb2bd662Svikram break;
691eb2bd662Svikram } else {
692c262cbbcSToomas Soome BAM_DPRINTF(("%s: skipping "
693c262cbbcSToomas 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) {
699c262cbbcSToomas Soome BAM_DPRINTF(("%s: found matching "
700c262cbbcSToomas Soome "findroot line: %s,%s\n", fcn,
701eb2bd662Svikram line->line, grubsign));
702eb2bd662Svikram return (entry);
703eb2bd662Svikram }
704eb2bd662Svikram if (line == entry->end) {
705c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has ended\n",
706c262cbbcSToomas Soome fcn));
707ae115bc7Smrj break;
708eb2bd662Svikram }
709ae115bc7Smrj }
710eb2bd662Svikram } else if (root_opt) {
711eb2bd662Svikram /* Neither root nor findroot */
712c262cbbcSToomas Soome BAM_DPRINTF(("%s: no root or findroot and root is "
713c262cbbcSToomas Soome "opt: %d\n", fcn, entry->entryNum));
714eb2bd662Svikram return (entry);
715ae115bc7Smrj }
716eb2bd662Svikram }
717eb2bd662Svikram
718c262cbbcSToomas 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
bam_add_findroot(menu_t * mp,char * grubsign,char * grubroot,int root_opt)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
749c262cbbcSToomas Soome bam_print(_("converting entries to findroot...\n"));
750eb2bd662Svikram
7513bbf88b3SToomas Soome entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
7523bbf88b3SToomas Soome while (entry != NULL) {
753eb2bd662Svikram if (entry->flags & BAM_ENTRY_FINDROOT) {
754eb2bd662Svikram /* already converted */
755c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry %d already converted to "
756c262cbbcSToomas Soome "findroot\n", fcn, entry->entryNum));
7573bbf88b3SToomas Soome entry = find_matching_entry(entry->next, grubsign,
7583bbf88b3SToomas Soome grubroot, root_opt);
759ae115bc7Smrj continue;
760eb2bd662Svikram }
761eb2bd662Svikram for (line = entry->start; line; line = line->next) {
762eb2bd662Svikram if (line->cmd == NULL || line->arg == NULL) {
763eb2bd662Svikram if (line == entry->end) {
764c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has ended\n",
765c262cbbcSToomas Soome fcn));
766eb2bd662Svikram break;
767eb2bd662Svikram } else {
768c262cbbcSToomas Soome BAM_DPRINTF(("%s: skipping NULL line\n",
769c262cbbcSToomas 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;
786c262cbbcSToomas Soome BAM_DPRINTF(("%s: added findroot line: %s\n",
787c262cbbcSToomas Soome fcn, newlp->line));
788eb2bd662Svikram line = newlp;
789eb2bd662Svikram }
790eb2bd662Svikram if (strcmp(line->cmd, menu_cmds[ROOT_CMD]) == 0) {
791c262cbbcSToomas Soome BAM_DPRINTF(("%s: freeing root line: %s\n",
792c262cbbcSToomas Soome fcn, line->line));
793eb2bd662Svikram unlink_line(mp, line);
794eb2bd662Svikram line_free(line);
795eb2bd662Svikram }
796eb2bd662Svikram if (line == entry->end) {
797c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has ended\n", fcn));
798eb2bd662Svikram break;
799eb2bd662Svikram }
800eb2bd662Svikram }
8013bbf88b3SToomas Soome entry = find_matching_entry(entry->next, grubsign, grubroot,
8023bbf88b3SToomas Soome root_opt);
803eb2bd662Svikram }
804eb2bd662Svikram
805eb2bd662Svikram if (update_num) {
806c262cbbcSToomas Soome BAM_DPRINTF(("%s: updated numbering\n", fcn));
807eb2bd662Svikram update_numbering(mp);
808eb2bd662Svikram }
809eb2bd662Svikram
810c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
811eb2bd662Svikram return (BAM_SUCCESS);
812eb2bd662Svikram }
813ae115bc7Smrj
814eb2bd662Svikram static error_t
bam_add_hv(menu_t * mp,char * grubsign,char * grubroot,int root_opt)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
820c262cbbcSToomas Soome bam_print(_("adding xVM entries...\n"));
821eb2bd662Svikram
8223bbf88b3SToomas Soome entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
8233bbf88b3SToomas Soome while (entry != NULL) {
824eb2bd662Svikram if (entry->flags & BAM_ENTRY_HV) {
825c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry %d already converted to "
826c262cbbcSToomas Soome "xvm HV\n", fcn, entry->entryNum));
827eb2bd662Svikram return (BAM_SUCCESS);
828eb2bd662Svikram }
8293bbf88b3SToomas Soome entry = find_matching_entry(entry->next, grubsign, grubroot,
8303bbf88b3SToomas 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
836c262cbbcSToomas Soome BAM_DPRINTF(("%s: added xVM HV entry via add_boot_entry()\n", fcn));
837eb2bd662Svikram
838eb2bd662Svikram update_numbering(mp);
839eb2bd662Svikram
840c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
841eb2bd662Svikram
842eb2bd662Svikram return (BAM_SUCCESS);
843eb2bd662Svikram }
844eb2bd662Svikram
845eb2bd662Svikram static error_t
bam_add_dboot(menu_t * mp,char * osroot,char * grubsign,char * grubroot,int root_opt)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
859c262cbbcSToomas Soome bam_print(_("converting entries to dboot...\n"));
860eb2bd662Svikram
8613bbf88b3SToomas Soome entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
8623bbf88b3SToomas 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) {
866c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has ended\n",
867c262cbbcSToomas Soome fcn));
868eb2bd662Svikram break;
869eb2bd662Svikram } else {
870c262cbbcSToomas Soome BAM_DPRINTF(("%s: skipping NULL line\n",
871c262cbbcSToomas Soome fcn));
872eb2bd662Svikram continue;
873eb2bd662Svikram }
874eb2bd662Svikram }
875ae115bc7Smrj
876ae115bc7Smrj /*
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
881ae115bc7Smrj */
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) {
889c262cbbcSToomas Soome BAM_DPRINTF(("%s: cvt_kernel_line() "
890c262cbbcSToomas Soome "failed\n", fcn));
891eb2bd662Svikram return (ret);
892eb2bd662Svikram } else if (ret == BAM_MSG) {
893eb2bd662Svikram msg = 1;
894c262cbbcSToomas Soome BAM_DPRINTF(("%s: BAM_MSG returned "
895c262cbbcSToomas Soome "from cvt_kernel_line()\n", fcn));
896ae115bc7Smrj }
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) {
905c262cbbcSToomas Soome BAM_DPRINTF(("%s: cvt_module_line() "
906c262cbbcSToomas Soome "failed\n", fcn));
907eb2bd662Svikram return (ret);
908eb2bd662Svikram } else if (ret == BAM_MSG) {
909c262cbbcSToomas Soome BAM_DPRINTF(("%s: BAM_MSG returned "
910c262cbbcSToomas Soome "from cvt_module_line()\n", fcn));
911eb2bd662Svikram msg = 1;
912ae115bc7Smrj }
913ae115bc7Smrj }
914eb2bd662Svikram
915eb2bd662Svikram if (line == entry->end) {
916c262cbbcSToomas Soome BAM_DPRINTF(("%s: entry has ended\n", fcn));
917ae115bc7Smrj break;
918eb2bd662Svikram }
919ae115bc7Smrj }
9203bbf88b3SToomas Soome entry = find_matching_entry(entry->next, grubsign, grubroot,
9213bbf88b3SToomas Soome root_opt);
922ae115bc7Smrj }
923ae115bc7Smrj
924eb2bd662Svikram ret = msg ? BAM_MSG : BAM_SUCCESS;
925c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning ret = %d\n", fcn, ret));
926eb2bd662Svikram return (ret);
927eb2bd662Svikram }
928eb2bd662Svikram
929eb2bd662Svikram /*ARGSUSED*/
930eb2bd662Svikram error_t
upgrade_menu(menu_t * mp,char * osroot,char * menu_root)931eb2bd662Svikram upgrade_menu(menu_t *mp, char *osroot, char *menu_root)
932eb2bd662Svikram {
933eb2bd662Svikram char *osdev;
934eb2bd662Svikram char *grubsign;
935eb2bd662Svikram char *grubroot;
936eb2bd662Svikram int ret1;
937eb2bd662Svikram int ret2;
938eb2bd662Svikram int ret3;
939eb2bd662Svikram const char *fcn = "upgrade_menu()";
940eb2bd662Svikram
941eb2bd662Svikram assert(osroot);
942eb2bd662Svikram assert(menu_root);
943eb2bd662Svikram
944c262cbbcSToomas Soome BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn, osroot, menu_root));
945eb2bd662Svikram
946843e1988Sjohnlev /*
947eb2bd662Svikram * We only support upgrades. Xen may not be present
948eb2bd662Svikram * on smaller metaclusters so we don't check for that.
949843e1988Sjohnlev */
950eb2bd662Svikram if (bam_is_findroot != BAM_FINDROOT_PRESENT ||
951eb2bd662Svikram bam_direct != BAM_DIRECT_DBOOT) {
952c262cbbcSToomas Soome bam_error(_("automated downgrade of GRUB menu to older "
953c262cbbcSToomas Soome "version not supported.\n"));
954eb2bd662Svikram return (BAM_ERROR);
955843e1988Sjohnlev }
956843e1988Sjohnlev
957ae115bc7Smrj /*
958eb2bd662Svikram * First get the GRUB signature
959ae115bc7Smrj */
960eb2bd662Svikram osdev = get_special(osroot);
961eb2bd662Svikram INJECT_ERROR1("UPGRADE_OSDEV", osdev = NULL);
962eb2bd662Svikram if (osdev == NULL) {
963c262cbbcSToomas Soome bam_error(_("cant find special file for mount-point %s\n"),
964c262cbbcSToomas Soome osroot);
965eb2bd662Svikram return (BAM_ERROR);
966eb2bd662Svikram }
967eb2bd662Svikram
968eb2bd662Svikram grubsign = get_grubsign(osroot, osdev);
969eb2bd662Svikram INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign = NULL);
970eb2bd662Svikram if (grubsign == NULL) {
971eb2bd662Svikram free(osdev);
972c262cbbcSToomas Soome bam_error(_("cannot find GRUB signature for %s\n"), osroot);
973ae115bc7Smrj return (BAM_ERROR);
974ae115bc7Smrj }
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) {
9893028dfd6SFrank Van Der Linden ret2 = bam_add_hv(mp, grubsign, grubroot,
9903028dfd6SFrank Van Der Linden root_optional(osroot, menu_root));
9913028dfd6SFrank Van Der Linden INJECT_ERROR1("UPGRADE_ADD_HV", ret2 = BAM_ERROR);
9923028dfd6SFrank Van Der Linden if (ret2 == BAM_ERROR)
9933028dfd6SFrank Van Der Linden 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) {
1004c262cbbcSToomas Soome bam_error(_("one or more GRUB menu entries were not "
1005c262cbbcSToomas Soome "automatically upgraded\nFor details on manually "
1006c262cbbcSToomas Soome "updating entries, see %s\n"), MENU_URL(osroot));
1007eb2bd662Svikram } else {
1008eb2bd662Svikram bam_warn_hand_entries(mp, osroot);
1009eb2bd662Svikram }
1010eb2bd662Svikram
1011eb2bd662Svikram free(grubsign);
1012eb2bd662Svikram
1013c262cbbcSToomas Soome BAM_DPRINTF(("%s: returning ret = %d\n", fcn, BAM_WRITE));
1014ae115bc7Smrj return (BAM_WRITE);
1015eb2bd662Svikram
1016eb2bd662Svikram abort:
1017eb2bd662Svikram free(grubsign);
1018c262cbbcSToomas Soome bam_error(_("error upgrading GRUB menu entries on %s. Aborting.\n"
1019c262cbbcSToomas Soome "For details on manually updating entries, see %s\n"), osroot,
1020c262cbbcSToomas Soome MENU_URL(osroot));
1021eb2bd662Svikram return (BAM_ERROR);
1022ae115bc7Smrj }
1023