xref: /titanic_44/usr/src/cmd/boot/bootadm/bootadm_upgrade.c (revision ddabfda27c1b77b7ab79bb8925e2637322024168)
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