4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2017 Toomas Soome <tsoome@me.com>
32 #include <sys/types.h>
40 #include <sys/multiboot.h>
44 direct_or_multi_t bam_direct
= BAM_DIRECT_NOT_SET
;
45 hv_t bam_is_hv
= BAM_HV_UNKNOWN
;
46 findroot_t bam_is_findroot
= BAM_FINDROOT_UNKNOWN
;
49 get_findroot_cap(const char *osroot
)
53 char buf
[BAM_MAXLINE
];
58 const char *fcn
= "get_findroot_cap()";
60 (void) snprintf(path
, sizeof (path
), "%s/%s",
61 osroot
, "boot/grub/capability");
63 if (stat(path
, &sb
) == -1) {
64 bam_is_findroot
= BAM_FINDROOT_ABSENT
;
65 BAM_DPRINTF(("%s: findroot capability absent\n", fcn
));
69 fp
= fopen(path
, "r");
71 INJECT_ERROR1("GET_CAP_FINDROOT_FOPEN", fp
= NULL
);
73 bam_error(_("failed to open file: %s: %s\n"), path
,
79 while (s_fgets(buf
, sizeof (buf
), fp
) != NULL
) {
80 if (strcmp(buf
, "findroot") == 0) {
81 BAM_DPRINTF(("%s: findroot capability present\n", fcn
));
82 bam_is_findroot
= BAM_FINDROOT_PRESENT
;
84 if (strcmp(buf
, "dboot") == 0) {
85 BAM_DPRINTF(("%s: dboot capability present\n", fcn
));
92 if (bam_is_findroot
== BAM_FINDROOT_UNKNOWN
) {
93 bam_is_findroot
= BAM_FINDROOT_ABSENT
;
94 BAM_DPRINTF(("%s: findroot capability absent\n", fcn
));
99 INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret
= 1);
101 bam_error(_("failed to close file: %s: %s\n"),
102 path
, strerror(error
));
107 get_boot_cap(const char *osroot
)
109 char fname
[PATH_MAX
];
115 multiboot_header_t
*mbh
;
118 const char *fcn
= "get_boot_cap()";
121 /* there is no non dboot sparc new-boot */
122 bam_direct
= BAM_DIRECT_DBOOT
;
123 BAM_DPRINTF(("%s: is sparc - always DBOOT\n", fcn
));
124 return (BAM_SUCCESS
);
128 * The install media can support both 64 and 32 bit boot
129 * by using boot archive as ramdisk image. However, to save
130 * the memory, the ramdisk may only have either 32 or 64
131 * bit kernel files. To avoid error message about missing unix,
132 * we should try both variants here and only complain if neither
133 * is found. Since the 64-bit systems are more common, we start
137 (void) snprintf(fname
, PATH_MAX
, "%s/%s", osroot
,
138 "platform/i86pc/kernel/amd64/unix");
139 fd
= open(fname
, O_RDONLY
);
142 (void) snprintf(fname
, PATH_MAX
, "%s/%s", osroot
,
143 "platform/i86pc/kernel/unix");
144 fd
= open(fname
, O_RDONLY
);
147 INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd
= -1);
149 bam_error(_("failed to open file: %s: %s\n"), fname
,
155 * Verify that this is a sane unix at least 8192 bytes in length
157 if (fstat(fd
, &sb
) == -1 || sb
.st_size
< 8192) {
159 bam_error(_("invalid or corrupted binary: %s\n"), fname
);
166 image
= mmap(NULL
, 8192, PROT_READ
, MAP_SHARED
, fd
, 0);
168 INJECT_ERROR1("GET_CAP_MMAP", image
= MAP_FAILED
);
169 if (image
== MAP_FAILED
) {
170 bam_error(_("failed to mmap file: %s: %s\n"), fname
,
175 ident
= (uchar_t
*)image
;
176 if (ident
[EI_MAG0
] != ELFMAG0
|| ident
[EI_MAG1
] != ELFMAG1
||
177 ident
[EI_MAG2
] != ELFMAG2
|| ident
[EI_MAG3
] != ELFMAG3
) {
178 bam_error(_("%s is not an ELF file.\n"), fname
);
181 if (ident
[EI_CLASS
] != class) {
182 bam_error(_("%s is wrong ELF class 0x%x\n"), fname
,
188 * The GRUB multiboot header must be 32-bit aligned and completely
189 * contained in the 1st 8K of the file. If the unix binary has
190 * a multiboot header, then it is a 'dboot' kernel. Otherwise,
191 * this kernel must be booted via multiboot -- we call this a
192 * 'multiboot' kernel.
194 bam_direct
= BAM_DIRECT_MULTIBOOT
;
195 for (m
= 0; m
< 8192 - sizeof (multiboot_header_t
); m
+= 4) {
196 mbh
= (void *)(image
+ m
);
197 if (mbh
->magic
== MB_HEADER_MAGIC
) {
198 BAM_DPRINTF(("%s: is DBOOT unix\n", fcn
));
199 bam_direct
= BAM_DIRECT_DBOOT
;
203 (void) munmap(image
, 8192);
206 INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct
= BAM_DIRECT_MULTIBOOT
);
207 if (bam_direct
== BAM_DIRECT_DBOOT
) {
208 if (bam_is_hv
== BAM_HV_PRESENT
) {
209 BAM_DPRINTF(("%s: is xVM system\n", fcn
));
211 BAM_DPRINTF(("%s: is *NOT* xVM system\n", fcn
));
214 BAM_DPRINTF(("%s: is MULTIBOOT unix\n", fcn
));
217 /* Not a fatal error if this fails */
218 get_findroot_cap(osroot
);
220 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn
));
221 return (BAM_SUCCESS
);
224 #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE"
227 * Return true if root has been bfu'ed. bfu will blow away
228 * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
229 * assume the system has not been bfu'ed.
232 is_bfu_system(const char *root
)
234 static int is_bfu
= -1;
237 const char *fcn
= "is_bfu_system()";
240 BAM_DPRINTF(("%s: already done bfu test. bfu is %s present\n",
241 fcn
, is_bfu
? "" : "NOT"));
245 (void) snprintf(path
, sizeof (path
), "%s/%s", root
, INST_RELEASE
);
246 if (stat(path
, &sb
) != 0) {
248 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn
));
251 BAM_DPRINTF(("%s: returning FAILURE\n", fcn
));
256 #define MENU_URL(root) (is_bfu_system(root) ? \
257 "http://illumos.org/msg/SUNOS-8000-CF" : \
258 "http://illumos.org/msg/SUNOS-8000-AK")
261 * Simply allocate a new line and copy in cmd + sep + arg
264 update_line(line_t
*linep
)
267 const char *fcn
= "update_line()";
269 BAM_DPRINTF(("%s: line before update: %s\n", fcn
, linep
->line
));
271 size
= strlen(linep
->cmd
) + strlen(linep
->sep
) + strlen(linep
->arg
) + 1;
272 linep
->line
= s_calloc(1, size
);
273 (void) snprintf(linep
->line
, size
, "%s%s%s", linep
->cmd
, linep
->sep
,
275 BAM_DPRINTF(("%s: line after update: %s\n", fcn
, linep
->line
));
279 skip_wspace(char *ptr
)
281 const char *fcn
= "skip_wspace()";
283 INJECT_ERROR1("SKIP_WSPACE", ptr
= NULL
);
285 BAM_DPRINTF(("%s: NULL ptr\n", fcn
));
289 BAM_DPRINTF(("%s: ptr on entry: %s\n", fcn
, ptr
));
290 for (; *ptr
!= '\0'; ptr
++) {
291 if ((*ptr
!= ' ') && (*ptr
!= '\t') &&
296 ptr
= (*ptr
== '\0' ? NULL
: ptr
);
298 BAM_DPRINTF(("%s: ptr on exit: %s\n", fcn
, ptr
? ptr
: "NULL"));
304 rskip_bspace(char *bound
, char *ptr
)
306 const char *fcn
= "rskip_bspace()";
309 assert(bound
<= ptr
);
310 assert(*bound
!= ' ' && *bound
!= '\t' && *bound
!= '\n');
312 BAM_DPRINTF(("%s: ptr on entry: %s\n", fcn
, ptr
));
313 for (; ptr
> bound
; ptr
--) {
314 if (*ptr
== ' ' || *ptr
== '\t' || *ptr
== '\n')
318 BAM_DPRINTF(("%s: ptr on exit: %s\n", fcn
, ptr
));
323 * The parse_kernel_line function examines a menu.lst kernel line. For
324 * multiboot, this is:
326 * kernel <multiboot path> <flags1> <kernel path> <flags2>
328 * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot
330 * <kernel path> may be missing, or may be any full or relative path to unix.
331 * We check for it by looking for a word ending in "/unix". If it ends
332 * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in
333 * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise,
334 * it's a custom kernel, and we skip it.
336 * <flags*> are anything that doesn't fit either of the above - these will be
339 * For direct boot, the defaults are
341 * kernel$ <kernel path> <flags>
343 * <kernel path> is one of:
344 * /platform/i86pc/kernel/$ISADIR/unix
345 * /boot/platform/i86pc/kernel/$ISADIR/unix
346 * /platform/i86pc/kernel/unix
347 * /platform/i86pc/kernel/amd64/unix
348 * /boot/platform/i86pc/kernel/unix
349 * /boot/platform/i86pc/kernel/amd64/unix
351 * If <kernel path> is any of the last four, the command may also be "kernel".
353 * <flags> is anything that isn't <kernel path>.
355 * This function is only called to convert a multiboot entry to a dboot entry
357 * For safety, we do one more check: if the kernel path starts with /boot,
358 * we verify that the new kernel exists before changing it. This is mainly
359 * done for bfu, as it may cause the failsafe archives to be a different
360 * boot architecture from the newly bfu'ed system.
363 cvt_kernel_line(line_t
*line
, const char *osroot
, entry_t
*entry
)
365 char path
[PATH_MAX
], path_64
[PATH_MAX
];
366 char linebuf
[PATH_MAX
];
367 char new_arg
[PATH_MAX
];
368 struct stat sb
, sb_64
;
373 const char *fcn
= "cvt_kernel_line()";
375 BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn
, line
->line
, osroot
));
378 * We only convert multiboot to dboot and nothing else.
380 if (!(entry
->flags
& BAM_ENTRY_MULTIBOOT
)) {
381 BAM_DPRINTF(("%s: not MULTIBOOT, not converting\n", fcn
));
382 return (BAM_SUCCESS
);
385 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
387 * We're attempting to change failsafe to dboot.
388 * In the bfu case, we may not have a dboot failsafe
389 * kernel i.e. a "unix" under the "/boot" hierarchy.
390 * If so, just emit a message in verbose mode and
393 BAM_DPRINTF(("%s: trying to convert failsafe to DBOOT\n", fcn
));
394 (void) snprintf(path
, PATH_MAX
, "%s%s", osroot
,
395 DIRECT_BOOT_FAILSAFE_32
);
396 (void) snprintf(path_64
, PATH_MAX
, "%s%s", osroot
,
397 DIRECT_BOOT_FAILSAFE_64
);
398 if (stat(path
, &sb
) != 0 && stat(path_64
, &sb_64
) != 0) {
400 bam_error(_("bootadm -m upgrade run, but the "
401 "failsafe archives have not been\nupdated. "
402 "Not updating line %d\n"), line
->lineNum
);
404 BAM_DPRINTF(("%s: no FAILSAFE unix, not converting\n",
406 return (BAM_SUCCESS
);
411 * Make sure we have the correct cmd
415 line
->cmd
= s_strdup(menu_cmds
[KERNEL_DOLLAR_CMD
]);
416 BAM_DPRINTF(("%s: converted kernel cmd to %s\n", fcn
, line
->cmd
));
418 assert(sizeof (linebuf
) > strlen(line
->arg
) + 32);
419 (void) strlcpy(linebuf
, line
->arg
, sizeof (linebuf
));
421 old_ptr
= strpbrk(linebuf
, " \t\n");
422 old_ptr
= skip_wspace(old_ptr
);
423 if (old_ptr
== NULL
) {
425 * only multiboot and nothing else
426 * i.e. flags1 = unix = flags2 = NULL
428 flags1_ptr
= unix_ptr
= flags2_ptr
= NULL
;
429 BAM_DPRINTF(("%s: NULL flags1, unix, flags2\n", fcn
))
435 * old_ptr is either at "flags1" or "unix"
437 if ((unix_ptr
= strstr(old_ptr
, "/unix")) != NULL
) {
442 BAM_DPRINTF(("%s: unix present\n", fcn
));
444 /* See if there's a flags2 past unix */
445 flags2_ptr
= unix_ptr
+ strlen("/unix");
446 flags2_ptr
= skip_wspace(flags2_ptr
);
448 BAM_DPRINTF(("%s: flags2 present: %s\n", fcn
,
451 BAM_DPRINTF(("%s: flags2 absent\n", fcn
));
454 /* see if there is a flags1 before unix */
455 unix_ptr
= rskip_bspace(old_ptr
, unix_ptr
);
457 if (unix_ptr
== old_ptr
) {
459 BAM_DPRINTF(("%s: flags1 absent\n", fcn
));
461 flags1_ptr
= old_ptr
;
464 BAM_DPRINTF(("%s: flags1 present: %s\n", fcn
,
469 /* There is no unix, there is only a bunch of flags */
470 flags1_ptr
= old_ptr
;
471 unix_ptr
= flags2_ptr
= NULL
;
472 BAM_DPRINTF(("%s: flags1 present: %s, unix, flags2 absent\n",
477 * With dboot, unix is fixed and is at the beginning. We need to
478 * migrate flags1 and flags2
481 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
482 (void) snprintf(new_arg
, sizeof (new_arg
), "%s",
483 DIRECT_BOOT_FAILSAFE_KERNEL
);
485 (void) snprintf(new_arg
, sizeof (new_arg
), "%s",
488 BAM_DPRINTF(("%s: converted unix: %s\n", fcn
, new_arg
));
490 if (flags1_ptr
!= NULL
) {
491 (void) strlcat(new_arg
, " ", sizeof (new_arg
));
492 (void) strlcat(new_arg
, flags1_ptr
, sizeof (new_arg
));
495 if (flags2_ptr
!= NULL
) {
496 (void) strlcat(new_arg
, " ", sizeof (new_arg
));
497 (void) strlcat(new_arg
, flags2_ptr
, sizeof (new_arg
));
500 BAM_DPRINTF(("%s: converted unix with flags : %s\n", fcn
, new_arg
));
503 line
->arg
= s_strdup(new_arg
);
505 BAM_DPRINTF(("%s: converted line is: %s\n", fcn
, line
->line
));
506 return (BAM_SUCCESS
);
510 * Similar to above, except this time we're looking at a module line,
511 * which is quite a bit simpler.
513 * Under multiboot, the archive line is:
515 * module /platform/i86pc/boot_archive
517 * Under directboot, the archive line is:
519 * module$ /platform/i86pc/$ISADIR/boot_archive
521 * which may be specified exactly as either of:
523 * module /platform/i86pc/boot_archive
524 * module /platform/i86pc/amd64/boot_archive
526 * Under multiboot, the failsafe is:
528 * module /boot/x86.miniroot-safe
530 * Under dboot, the failsafe is:
532 * module$ /boot/$ISADIR/x86.miniroot-safe
534 * which may be specified exactly as either of:
536 * module /boot/x86.miniroot-safe
537 * module /boot/amd64/x86.miniroot-safe
540 cvt_module_line(line_t
*line
, entry_t
*entry
)
542 const char *fcn
= "cvt_module_line()";
544 BAM_DPRINTF(("%s: entered. arg: %s\n", fcn
, line
->line
));
547 * We only convert multiboot to dboot and nothing else
549 if (!(entry
->flags
& BAM_ENTRY_MULTIBOOT
)) {
550 BAM_DPRINTF(("%s: not MULTIBOOT, not converting\n", fcn
));
551 return (BAM_SUCCESS
);
554 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
555 if (strcmp(line
->arg
, FAILSAFE_ARCHIVE
) == 0) {
556 BAM_DPRINTF(("%s: failsafe module line needs no "
557 "conversion: %s\n", fcn
, line
->arg
));
558 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn
));
559 return (BAM_SUCCESS
);
561 } else if (strcmp(line
->arg
, MULTIBOOT_ARCHIVE
) != 0) {
562 bam_error(_("module command on line %d not recognized.\n"),
564 BAM_DPRINTF(("%s: returning FAILURE\n", fcn
));
570 line
->cmd
= s_strdup(menu_cmds
[MODULE_DOLLAR_CMD
]);
572 line
->arg
= s_strdup(entry
->flags
& BAM_ENTRY_FAILSAFE
?
573 FAILSAFE_ARCHIVE
: DIRECT_BOOT_ARCHIVE
);
576 BAM_DPRINTF(("%s: converted module line is: %s\n", fcn
, line
->line
));
577 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn
));
578 return (BAM_SUCCESS
);
582 bam_warn_hand_entries(menu_t
*mp
, char *osroot
)
589 const char *fcn
= "bam_warn_hand_entries()";
593 * No warning needed, we are automatically converting
596 BAM_DPRINTF(("%s: force specified, no warnings about hand "
602 hand_max
= BAM_ENTRY_NUM
;
603 hand_list
= s_calloc(1, hand_max
);
605 for (entry
= mp
->entries
; entry
; entry
= entry
->next
) {
606 if (entry
->flags
& (BAM_ENTRY_BOOTADM
|BAM_ENTRY_LU
))
608 BAM_DPRINTF(("%s: found hand entry #: %d\n", fcn
,
610 if (++hand_num
> hand_max
) {
612 hand_list
= s_realloc(hand_list
,
613 hand_max
* sizeof (int));
615 hand_list
[hand_num
- 1] = entry
->entryNum
;
618 bam_error(_("bootadm(1M) will only upgrade GRUB menu entries added "
619 "by \nbootadm(1M) or lu(1M). The following entries on %s will "
620 "not be upgraded.\nFor details on manually updating entries, "
621 "see %s\n"), osroot
, MENU_URL(osroot
));
622 bam_print_stderr("Entry Number%s: ", (hand_num
> 1) ?
624 for (i
= 0; i
< hand_num
; i
++) {
625 bam_print_stderr("%d ", hand_list
[i
]);
627 bam_print_stderr("\n");
640 const char *fcn
= "find_matching_entry()";
643 assert(root_opt
== 0 || root_opt
== 1);
645 (void) snprintf(opt
, sizeof (opt
), "%d", root_opt
);
646 BAM_DPRINTF(("%s: entered. args: %s %s %s\n", fcn
, grubsign
,
649 for (entry
= estart
; entry
; entry
= entry
->next
) {
651 if (!(entry
->flags
& (BAM_ENTRY_BOOTADM
|BAM_ENTRY_LU
)) &&
653 BAM_DPRINTF(("%s: skipping hand entry #: %d\n",
654 fcn
, entry
->entryNum
));
658 if (entry
->flags
& BAM_ENTRY_ROOT
) {
659 for (line
= entry
->start
; line
; line
= line
->next
) {
660 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
661 if (line
== entry
->end
) {
662 BAM_DPRINTF(("%s: entry has "
666 BAM_DPRINTF(("%s: skipping "
667 "NULL line\n", fcn
));
671 if (strcmp(line
->cmd
, menu_cmds
[ROOT_CMD
])
672 == 0 && strcmp(line
->arg
, grubroot
) == 0) {
673 BAM_DPRINTF(("%s: found matching root "
674 "line: %s,%s\n", fcn
,
675 line
->line
, grubsign
));
678 if (line
== entry
->end
) {
679 BAM_DPRINTF(("%s: entry has ended\n",
684 } else if (entry
->flags
& BAM_ENTRY_FINDROOT
) {
685 for (line
= entry
->start
; line
; line
= line
->next
) {
686 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
687 if (line
== entry
->end
) {
688 BAM_DPRINTF(("%s: entry has "
692 BAM_DPRINTF(("%s: skipping "
693 "NULL line\n", fcn
));
697 if (strcmp(line
->cmd
, menu_cmds
[FINDROOT_CMD
])
698 == 0 && strcmp(line
->arg
, grubsign
) == 0) {
699 BAM_DPRINTF(("%s: found matching "
700 "findroot line: %s,%s\n", fcn
,
701 line
->line
, grubsign
));
704 if (line
== entry
->end
) {
705 BAM_DPRINTF(("%s: entry has ended\n",
710 } else if (root_opt
) {
711 /* Neither root nor findroot */
712 BAM_DPRINTF(("%s: no root or findroot and root is "
713 "opt: %d\n", fcn
, entry
->entryNum
));
718 BAM_DPRINTF(("%s: no matching entry found\n", fcn
));
723 * The following is a set of routines that attempt to convert the
724 * menu entries for the supplied osroot into a format compatible
725 * with the GRUB installation on osroot.
727 * Each of these conversion routines make no assumptions about
728 * the current state of the menu entry, it does its best to
729 * convert the menu entry to the new state. In the process
730 * we may either upgrade or downgrade.
732 * We don't make any heroic efforts at conversion. It is better
733 * to be conservative and bail out at the first sign of error. We will
734 * in such cases, point the user at the knowledge-base article
735 * so that they can upgrade manually.
738 bam_add_findroot(menu_t
*mp
, char *grubsign
, char *grubroot
, int root_opt
)
744 char linebuf
[PATH_MAX
];
745 const char *fcn
= "bam_add_findroot()";
749 bam_print(_("converting entries to findroot...\n"));
751 entry
= find_matching_entry(mp
->entries
, grubsign
, grubroot
, root_opt
);
752 while (entry
!= NULL
) {
753 if (entry
->flags
& BAM_ENTRY_FINDROOT
) {
754 /* already converted */
755 BAM_DPRINTF(("%s: entry %d already converted to "
756 "findroot\n", fcn
, entry
->entryNum
));
757 entry
= find_matching_entry(entry
->next
, grubsign
,
761 for (line
= entry
->start
; line
; line
= line
->next
) {
762 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
763 if (line
== entry
->end
) {
764 BAM_DPRINTF(("%s: entry has ended\n",
768 BAM_DPRINTF(("%s: skipping NULL line\n",
773 if (strcmp(line
->cmd
, menu_cmds
[TITLE_CMD
]) == 0) {
774 newlp
= s_calloc(1, sizeof (line_t
));
775 newlp
->cmd
= s_strdup(menu_cmds
[FINDROOT_CMD
]);
776 newlp
->sep
= s_strdup(" ");
777 newlp
->arg
= s_strdup(grubsign
);
778 (void) snprintf(linebuf
, sizeof (linebuf
),
779 "%s%s%s", newlp
->cmd
, newlp
->sep
,
781 newlp
->line
= s_strdup(linebuf
);
782 bam_add_line(mp
, entry
, line
, newlp
);
784 entry
->flags
&= ~BAM_ENTRY_ROOT
;
785 entry
->flags
|= BAM_ENTRY_FINDROOT
;
786 BAM_DPRINTF(("%s: added findroot line: %s\n",
790 if (strcmp(line
->cmd
, menu_cmds
[ROOT_CMD
]) == 0) {
791 BAM_DPRINTF(("%s: freeing root line: %s\n",
793 unlink_line(mp
, line
);
796 if (line
== entry
->end
) {
797 BAM_DPRINTF(("%s: entry has ended\n", fcn
));
801 entry
= find_matching_entry(entry
->next
, grubsign
, grubroot
,
806 BAM_DPRINTF(("%s: updated numbering\n", fcn
));
807 update_numbering(mp
);
810 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn
));
811 return (BAM_SUCCESS
);
815 bam_add_hv(menu_t
*mp
, char *grubsign
, char *grubroot
, int root_opt
)
818 const char *fcn
= "bam_add_hv()";
820 bam_print(_("adding xVM entries...\n"));
822 entry
= find_matching_entry(mp
->entries
, grubsign
, grubroot
, root_opt
);
823 while (entry
!= NULL
) {
824 if (entry
->flags
& BAM_ENTRY_HV
) {
825 BAM_DPRINTF(("%s: entry %d already converted to "
826 "xvm HV\n", fcn
, entry
->entryNum
));
827 return (BAM_SUCCESS
);
829 entry
= find_matching_entry(entry
->next
, grubsign
, grubroot
,
833 (void) add_boot_entry(mp
, NEW_HV_ENTRY
, grubsign
, XEN_MENU
,
834 XEN_KERNEL_MODULE_LINE
, DIRECT_BOOT_ARCHIVE
, NULL
);
836 BAM_DPRINTF(("%s: added xVM HV entry via add_boot_entry()\n", fcn
));
838 update_numbering(mp
);
840 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn
));
842 return (BAM_SUCCESS
);
857 const char *fcn
= "bam_add_dboot()";
859 bam_print(_("converting entries to dboot...\n"));
861 entry
= find_matching_entry(mp
->entries
, grubsign
, grubroot
, root_opt
);
862 while (entry
!= NULL
) {
863 for (line
= entry
->start
; line
; line
= line
->next
) {
864 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
865 if (line
== entry
->end
) {
866 BAM_DPRINTF(("%s: entry has ended\n",
870 BAM_DPRINTF(("%s: skipping NULL line\n",
877 * If we have a kernel$ command, assume it
878 * is dboot already. If it is not a dboot
879 * entry, something funny is going on and
880 * we will leave it alone
882 if (strcmp(line
->cmd
, menu_cmds
[KERNEL_CMD
]) == 0) {
883 ret
= cvt_kernel_line(line
, osroot
, entry
);
884 INJECT_ERROR1("ADD_DBOOT_KERN_ERR",
886 INJECT_ERROR1("ADD_DBOOT_KERN_MSG",
888 if (ret
== BAM_ERROR
) {
889 BAM_DPRINTF(("%s: cvt_kernel_line() "
892 } else if (ret
== BAM_MSG
) {
894 BAM_DPRINTF(("%s: BAM_MSG returned "
895 "from cvt_kernel_line()\n", fcn
));
898 if (strcmp(line
->cmd
, menu_cmds
[MODULE_CMD
]) == 0) {
899 ret
= cvt_module_line(line
, entry
);
900 INJECT_ERROR1("ADD_DBOOT_MOD_ERR",
902 INJECT_ERROR1("ADD_DBOOT_MOD_MSG",
904 if (ret
== BAM_ERROR
) {
905 BAM_DPRINTF(("%s: cvt_module_line() "
908 } else if (ret
== BAM_MSG
) {
909 BAM_DPRINTF(("%s: BAM_MSG returned "
910 "from cvt_module_line()\n", fcn
));
915 if (line
== entry
->end
) {
916 BAM_DPRINTF(("%s: entry has ended\n", fcn
));
920 entry
= find_matching_entry(entry
->next
, grubsign
, grubroot
,
924 ret
= msg
? BAM_MSG
: BAM_SUCCESS
;
925 BAM_DPRINTF(("%s: returning ret = %d\n", fcn
, ret
));
931 upgrade_menu(menu_t
*mp
, char *osroot
, char *menu_root
)
939 const char *fcn
= "upgrade_menu()";
944 BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn
, osroot
, menu_root
));
947 * We only support upgrades. Xen may not be present
948 * on smaller metaclusters so we don't check for that.
950 if (bam_is_findroot
!= BAM_FINDROOT_PRESENT
||
951 bam_direct
!= BAM_DIRECT_DBOOT
) {
952 bam_error(_("automated downgrade of GRUB menu to older "
953 "version not supported.\n"));
958 * First get the GRUB signature
960 osdev
= get_special(osroot
);
961 INJECT_ERROR1("UPGRADE_OSDEV", osdev
= NULL
);
963 bam_error(_("cant find special file for mount-point %s\n"),
968 grubsign
= get_grubsign(osroot
, osdev
);
969 INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign
= NULL
);
970 if (grubsign
== NULL
) {
972 bam_error(_("cannot find GRUB signature for %s\n"), osroot
);
976 /* not fatal if we can't get grubroot */
977 grubroot
= get_grubroot(osroot
, osdev
, menu_root
);
978 INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot
= NULL
);
982 ret1
= bam_add_findroot(mp
, grubsign
,
983 grubroot
, root_optional(osroot
, menu_root
));
984 INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1
= BAM_ERROR
);
985 if (ret1
== BAM_ERROR
)
988 if (bam_is_hv
== BAM_HV_PRESENT
) {
989 ret2
= bam_add_hv(mp
, grubsign
, grubroot
,
990 root_optional(osroot
, menu_root
));
991 INJECT_ERROR1("UPGRADE_ADD_HV", ret2
= BAM_ERROR
);
992 if (ret2
== BAM_ERROR
)
997 ret3
= bam_add_dboot(mp
, osroot
, grubsign
,
998 grubroot
, root_optional(osroot
, menu_root
));
999 INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3
= BAM_ERROR
);
1000 if (ret3
== BAM_ERROR
)
1003 if (ret1
== BAM_MSG
|| ret2
== BAM_MSG
|| ret3
== BAM_MSG
) {
1004 bam_error(_("one or more GRUB menu entries were not "
1005 "automatically upgraded\nFor details on manually "
1006 "updating entries, see %s\n"), MENU_URL(osroot
));
1008 bam_warn_hand_entries(mp
, osroot
);
1013 BAM_DPRINTF(("%s: returning ret = %d\n", fcn
, BAM_WRITE
));
1018 bam_error(_("error upgrading GRUB menu entries on %s. Aborting.\n"
1019 "For details on manually updating entries, see %s\n"), osroot
,