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