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.
31 #include <sys/types.h>
39 #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 assert(is_grub(osroot
));
62 (void) snprintf(path
, sizeof (path
), "%s/%s",
63 osroot
, "boot/grub/capability");
65 if (stat(path
, &sb
) == -1) {
66 bam_is_findroot
= BAM_FINDROOT_ABSENT
;
67 BAM_DPRINTF((D_FINDROOT_ABSENT
, fcn
));
71 fp
= fopen(path
, "r");
73 INJECT_ERROR1("GET_CAP_FINDROOT_FOPEN", fp
= NULL
);
75 bam_error(OPEN_FAIL
, path
, strerror(error
));
80 while (s_fgets(buf
, sizeof (buf
), fp
) != NULL
) {
81 if (strcmp(buf
, "findroot") == 0) {
82 BAM_DPRINTF((D_FINDROOT_PRESENT
, fcn
));
83 bam_is_findroot
= BAM_FINDROOT_PRESENT
;
85 if (strcmp(buf
, "dboot") == 0) {
86 BAM_DPRINTF((D_DBOOT_PRESENT
, fcn
));
93 if (bam_is_findroot
== BAM_FINDROOT_UNKNOWN
) {
94 bam_is_findroot
= BAM_FINDROOT_ABSENT
;
95 BAM_DPRINTF((D_FINDROOT_ABSENT
, fcn
));
100 INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret
= 1);
102 bam_error(CLOSE_FAIL
, path
, strerror(error
));
107 get_boot_cap(const char *osroot
)
109 char fname
[PATH_MAX
];
114 multiboot_header_t
*mbh
;
117 const char *fcn
= "get_boot_cap()";
120 /* there is no non dboot sparc new-boot */
121 bam_direct
= BAM_DIRECT_DBOOT
;
122 BAM_DPRINTF((D_IS_SPARC_DBOOT
, fcn
));
123 return (BAM_SUCCESS
);
126 if (!is_grub(osroot
)) {
127 bam_error(NOT_GRUB_ROOT
, osroot
);
131 (void) snprintf(fname
, PATH_MAX
, "%s/%s", osroot
,
132 "platform/i86pc/kernel/unix");
133 fd
= open(fname
, O_RDONLY
);
135 INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd
= -1);
137 bam_error(OPEN_FAIL
, fname
, strerror(error
));
142 * Verify that this is a sane unix at least 8192 bytes in length
144 if (fstat(fd
, &sb
) == -1 || sb
.st_size
< 8192) {
146 bam_error(INVALID_BINARY
, fname
);
153 image
= mmap(NULL
, 8192, PROT_READ
, MAP_SHARED
, fd
, 0);
155 INJECT_ERROR1("GET_CAP_MMAP", image
= MAP_FAILED
);
156 if (image
== MAP_FAILED
) {
157 bam_error(MMAP_FAIL
, fname
, strerror(error
));
161 ident
= (uchar_t
*)image
;
162 if (ident
[EI_MAG0
] != ELFMAG0
|| ident
[EI_MAG1
] != ELFMAG1
||
163 ident
[EI_MAG2
] != ELFMAG2
|| ident
[EI_MAG3
] != ELFMAG3
) {
164 bam_error(NOT_ELF_FILE
, fname
);
167 if (ident
[EI_CLASS
] != ELFCLASS32
) {
168 bam_error(WRONG_ELF_CLASS
, fname
, ident
[EI_CLASS
]);
173 * The GRUB multiboot header must be 32-bit aligned and completely
174 * contained in the 1st 8K of the file. If the unix binary has
175 * a multiboot header, then it is a 'dboot' kernel. Otherwise,
176 * this kernel must be booted via multiboot -- we call this a
177 * 'multiboot' kernel.
179 bam_direct
= BAM_DIRECT_MULTIBOOT
;
180 for (m
= 0; m
< 8192 - sizeof (multiboot_header_t
); m
+= 4) {
181 mbh
= (void *)(image
+ m
);
182 if (mbh
->magic
== MB_HEADER_MAGIC
) {
183 BAM_DPRINTF((D_IS_DBOOT
, fcn
));
184 bam_direct
= BAM_DIRECT_DBOOT
;
188 (void) munmap(image
, 8192);
191 INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct
= BAM_DIRECT_MULTIBOOT
);
192 if (bam_direct
== BAM_DIRECT_DBOOT
) {
193 if (bam_is_hv
== BAM_HV_PRESENT
) {
194 BAM_DPRINTF((D_IS_XVM
, fcn
));
196 BAM_DPRINTF((D_IS_NOT_XVM
, fcn
));
199 BAM_DPRINTF((D_IS_MULTIBOOT
, fcn
));
202 /* Not a fatal error if this fails */
203 get_findroot_cap(osroot
);
205 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
206 return (BAM_SUCCESS
);
209 #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE"
212 * Return true if root has been bfu'ed. bfu will blow away
213 * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
214 * assume the system has not been bfu'ed.
217 is_bfu_system(const char *root
)
219 static int is_bfu
= -1;
222 const char *fcn
= "is_bfu_system()";
225 BAM_DPRINTF((D_ALREADY_BFU_TEST
, fcn
, is_bfu
? "" : "NOT"));
229 (void) snprintf(path
, sizeof (path
), "%s/%s", root
, INST_RELEASE
);
230 if (stat(path
, &sb
) != 0) {
232 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
235 BAM_DPRINTF((D_RETURN_FAILURE
, fcn
));
240 #define MENU_URL(root) (is_bfu_system(root) ? \
241 "http://illumos.org/msg/SUNOS-8000-CF" : \
242 "http://illumos.org/msg/SUNOS-8000-AK")
245 * Simply allocate a new line and copy in cmd + sep + arg
248 update_line(line_t
*linep
)
251 const char *fcn
= "update_line()";
253 BAM_DPRINTF((D_UPDATE_LINE_BEFORE
, fcn
, linep
->line
));
255 size
= strlen(linep
->cmd
) + strlen(linep
->sep
) + strlen(linep
->arg
) + 1;
256 linep
->line
= s_calloc(1, size
);
257 (void) snprintf(linep
->line
, size
, "%s%s%s", linep
->cmd
, linep
->sep
,
259 BAM_DPRINTF((D_UPDATE_LINE_AFTER
, fcn
, linep
->line
));
263 skip_wspace(char *ptr
)
265 const char *fcn
= "skip_wspace()";
267 INJECT_ERROR1("SKIP_WSPACE", ptr
= NULL
);
269 BAM_DPRINTF((D_SKIP_WSPACE_PTR_NULL
, fcn
));
273 BAM_DPRINTF((D_SKIP_WSPACE_ENTRY_PTR
, fcn
, ptr
));
274 for (; *ptr
!= '\0'; ptr
++) {
275 if ((*ptr
!= ' ') && (*ptr
!= '\t') &&
280 ptr
= (*ptr
== '\0' ? NULL
: ptr
);
282 BAM_DPRINTF((D_SKIP_WSPACE_EXIT_PTR
, fcn
, ptr
? ptr
: "NULL"));
288 rskip_bspace(char *bound
, char *ptr
)
290 const char *fcn
= "rskip_bspace()";
293 assert(bound
<= ptr
);
294 assert(*bound
!= ' ' && *bound
!= '\t' && *bound
!= '\n');
296 BAM_DPRINTF((D_RSKIP_BSPACE_ENTRY
, fcn
, ptr
));
297 for (; ptr
> bound
; ptr
--) {
298 if (*ptr
== ' ' || *ptr
== '\t' || *ptr
== '\n')
302 BAM_DPRINTF((D_RSKIP_BSPACE_EXIT
, fcn
, ptr
));
307 * The parse_kernel_line function examines a menu.lst kernel line. For
308 * multiboot, this is:
310 * kernel <multiboot path> <flags1> <kernel path> <flags2>
312 * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot
314 * <kernel path> may be missing, or may be any full or relative path to unix.
315 * We check for it by looking for a word ending in "/unix". If it ends
316 * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in
317 * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise,
318 * it's a custom kernel, and we skip it.
320 * <flags*> are anything that doesn't fit either of the above - these will be
323 * For direct boot, the defaults are
325 * kernel$ <kernel path> <flags>
327 * <kernel path> is one of:
328 * /platform/i86pc/kernel/$ISADIR/unix
329 * /boot/platform/i86pc/kernel/$ISADIR/unix
330 * /platform/i86pc/kernel/unix
331 * /platform/i86pc/kernel/amd64/unix
332 * /boot/platform/i86pc/kernel/unix
333 * /boot/platform/i86pc/kernel/amd64/unix
335 * If <kernel path> is any of the last four, the command may also be "kernel".
337 * <flags> is anything that isn't <kernel path>.
339 * This function is only called to convert a multiboot entry to a dboot entry
341 * For safety, we do one more check: if the kernel path starts with /boot,
342 * we verify that the new kernel exists before changing it. This is mainly
343 * done for bfu, as it may cause the failsafe archives to be a different
344 * boot architecture from the newly bfu'ed system.
347 cvt_kernel_line(line_t
*line
, const char *osroot
, entry_t
*entry
)
349 char path
[PATH_MAX
], path_64
[PATH_MAX
];
350 char linebuf
[PATH_MAX
];
351 char new_arg
[PATH_MAX
];
352 struct stat sb
, sb_64
;
357 const char *fcn
= "cvt_kernel_line()";
359 BAM_DPRINTF((D_FUNC_ENTRY2
, fcn
, line
->line
, osroot
));
362 * We only convert multiboot to dboot and nothing else.
364 if (!(entry
->flags
& BAM_ENTRY_MULTIBOOT
)) {
365 BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT
, fcn
));
366 return (BAM_SUCCESS
);
369 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
371 * We're attempting to change failsafe to dboot.
372 * In the bfu case, we may not have a dboot failsafe
373 * kernel i.e. a "unix" under the "/boot" hierarchy.
374 * If so, just emit a message in verbose mode and
377 BAM_DPRINTF((D_TRYING_FAILSAFE_CVT_TO_DBOOT
, fcn
));
378 (void) snprintf(path
, PATH_MAX
, "%s%s", osroot
,
379 DIRECT_BOOT_FAILSAFE_32
);
380 (void) snprintf(path_64
, PATH_MAX
, "%s%s", osroot
,
381 DIRECT_BOOT_FAILSAFE_64
);
382 if (stat(path
, &sb
) != 0 && stat(path_64
, &sb_64
) != 0) {
384 bam_error(FAILSAFE_MISSING
, line
->lineNum
);
386 BAM_DPRINTF((D_NO_FAILSAFE_UNIX_CONVERT
, fcn
));
387 return (BAM_SUCCESS
);
392 * Make sure we have the correct cmd
396 line
->cmd
= s_strdup(menu_cmds
[KERNEL_DOLLAR_CMD
]);
397 BAM_DPRINTF((D_CVT_CMD_KERN_DOLLAR
, fcn
, line
->cmd
));
399 assert(sizeof (linebuf
) > strlen(line
->arg
) + 32);
400 (void) strlcpy(linebuf
, line
->arg
, sizeof (linebuf
));
402 old_ptr
= strpbrk(linebuf
, " \t\n");
403 old_ptr
= skip_wspace(old_ptr
);
404 if (old_ptr
== NULL
) {
406 * only multiboot and nothing else
407 * i.e. flags1 = unix = flags2 = NULL
409 flags1_ptr
= unix_ptr
= flags2_ptr
= NULL
;
410 BAM_DPRINTF((D_FLAGS1_UNIX_FLAGS2_NULL
, fcn
))
416 * old_ptr is either at "flags1" or "unix"
418 if (unix_ptr
= strstr(old_ptr
, "/unix")) {
423 BAM_DPRINTF((D_UNIX_PRESENT
, fcn
));
425 /* See if there's a flags2 past unix */
426 flags2_ptr
= unix_ptr
+ strlen("/unix");
427 flags2_ptr
= skip_wspace(flags2_ptr
);
429 BAM_DPRINTF((D_FLAGS2_PRESENT
, fcn
, flags2_ptr
));
431 BAM_DPRINTF((D_FLAGS2_ABSENT
, fcn
));
434 /* see if there is a flags1 before unix */
435 unix_ptr
= rskip_bspace(old_ptr
, unix_ptr
);
437 if (unix_ptr
== old_ptr
) {
439 BAM_DPRINTF((D_FLAGS1_ABSENT
, fcn
));
441 flags1_ptr
= old_ptr
;
444 BAM_DPRINTF((D_FLAGS1_PRESENT
, fcn
, flags1_ptr
));
448 /* There is no unix, there is only a bunch of flags */
449 flags1_ptr
= old_ptr
;
450 unix_ptr
= flags2_ptr
= NULL
;
451 BAM_DPRINTF((D_FLAGS1_ONLY
, fcn
, flags1_ptr
));
455 * With dboot, unix is fixed and is at the beginning. We need to
456 * migrate flags1 and flags2
459 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
460 (void) snprintf(new_arg
, sizeof (new_arg
), "%s",
461 DIRECT_BOOT_FAILSAFE_KERNEL
);
463 (void) snprintf(new_arg
, sizeof (new_arg
), "%s",
466 BAM_DPRINTF((D_CVTED_UNIX
, fcn
, new_arg
));
468 if (flags1_ptr
!= NULL
) {
469 (void) strlcat(new_arg
, " ", sizeof (new_arg
));
470 (void) strlcat(new_arg
, flags1_ptr
, sizeof (new_arg
));
473 if (flags2_ptr
!= NULL
) {
474 (void) strlcat(new_arg
, " ", sizeof (new_arg
));
475 (void) strlcat(new_arg
, flags2_ptr
, sizeof (new_arg
));
478 BAM_DPRINTF((D_CVTED_UNIX_AND_FLAGS
, fcn
, new_arg
));
481 line
->arg
= s_strdup(new_arg
);
483 BAM_DPRINTF((D_CVTED_KERNEL_LINE
, fcn
, line
->line
));
484 return (BAM_SUCCESS
);
488 * Similar to above, except this time we're looking at a module line,
489 * which is quite a bit simpler.
491 * Under multiboot, the archive line is:
493 * module /platform/i86pc/boot_archive
495 * Under directboot, the archive line is:
497 * module$ /platform/i86pc/$ISADIR/boot_archive
499 * which may be specified exactly as either of:
501 * module /platform/i86pc/boot_archive
502 * module /platform/i86pc/amd64/boot_archive
504 * Under multiboot, the failsafe is:
506 * module /boot/x86.miniroot-safe
508 * Under dboot, the failsafe is:
510 * module$ /boot/$ISADIR/x86.miniroot-safe
512 * which may be specified exactly as either of:
514 * module /boot/x86.miniroot-safe
515 * module /boot/amd64/x86.miniroot-safe
518 cvt_module_line(line_t
*line
, entry_t
*entry
)
520 const char *fcn
= "cvt_module_line()";
522 BAM_DPRINTF((D_FUNC_ENTRY1
, fcn
, line
->line
));
525 * We only convert multiboot to dboot and nothing else
527 if (!(entry
->flags
& BAM_ENTRY_MULTIBOOT
)) {
528 BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT
, fcn
));
529 return (BAM_SUCCESS
);
532 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
533 if (strcmp(line
->arg
, FAILSAFE_ARCHIVE
) == 0) {
534 BAM_DPRINTF((D_FAILSAFE_NO_CVT_NEEDED
, fcn
, line
->arg
));
535 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
536 return (BAM_SUCCESS
);
538 } else if (strcmp(line
->arg
, MULTIBOOT_ARCHIVE
) != 0) {
539 bam_error(UNKNOWN_MODULE_LINE
, line
->lineNum
);
540 BAM_DPRINTF((D_RETURN_FAILURE
, fcn
));
546 line
->cmd
= s_strdup(menu_cmds
[MODULE_DOLLAR_CMD
]);
548 line
->arg
= s_strdup(entry
->flags
& BAM_ENTRY_FAILSAFE
?
549 FAILSAFE_ARCHIVE
: DIRECT_BOOT_ARCHIVE
);
552 BAM_DPRINTF((D_CVTED_MODULE
, fcn
, line
->line
));
553 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
554 return (BAM_SUCCESS
);
558 bam_warn_hand_entries(menu_t
*mp
, char *osroot
)
565 const char *fcn
= "bam_warn_hand_entries()";
569 * No warning needed, we are automatically converting
572 BAM_DPRINTF((D_FORCE_HAND_CVT
, fcn
));
577 hand_max
= BAM_ENTRY_NUM
;
578 hand_list
= s_calloc(1, hand_max
);
580 for (entry
= mp
->entries
; entry
; entry
= entry
->next
) {
581 if (entry
->flags
& (BAM_ENTRY_BOOTADM
|BAM_ENTRY_LU
))
583 BAM_DPRINTF((D_FOUND_HAND
, fcn
, entry
->entryNum
));
584 if (++hand_num
> hand_max
) {
586 hand_list
= s_realloc(hand_list
,
587 hand_max
* sizeof (int));
589 hand_list
[hand_num
- 1] = entry
->entryNum
;
592 bam_error(HAND_ADDED_ENTRIES
, osroot
, MENU_URL(osroot
));
593 bam_print_stderr("Entry Number%s: ", (hand_num
> 1) ?
595 for (i
= 0; i
< hand_num
; i
++) {
596 bam_print_stderr("%d ", hand_list
[i
]);
598 bam_print_stderr("\n");
611 const char *fcn
= "find_matching_entry()";
614 assert(root_opt
== 0 || root_opt
== 1);
616 (void) snprintf(opt
, sizeof (opt
), "%d", root_opt
);
617 BAM_DPRINTF((D_FUNC_ENTRY3
, fcn
, grubsign
, grubroot
, opt
));
619 for (entry
= estart
; entry
; entry
= entry
->next
) {
621 if (!(entry
->flags
& (BAM_ENTRY_BOOTADM
|BAM_ENTRY_LU
)) &&
623 BAM_DPRINTF((D_SKIP_ENTRY
, fcn
, entry
->entryNum
));
627 if (entry
->flags
& BAM_ENTRY_ROOT
) {
628 for (line
= entry
->start
; line
; line
= line
->next
) {
629 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
630 if (line
== entry
->end
) {
631 BAM_DPRINTF((D_ENTRY_END
, fcn
));
634 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
638 if (strcmp(line
->cmd
, menu_cmds
[ROOT_CMD
])
639 == 0 && strcmp(line
->arg
, grubroot
) == 0) {
640 BAM_DPRINTF((D_ROOT_MATCH
, fcn
,
641 line
->line
, grubsign
));
644 if (line
== entry
->end
) {
645 BAM_DPRINTF((D_ENTRY_END
, fcn
));
649 } else if (entry
->flags
& BAM_ENTRY_FINDROOT
) {
650 for (line
= entry
->start
; line
; line
= line
->next
) {
651 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
652 if (line
== entry
->end
) {
653 BAM_DPRINTF((D_ENTRY_END
, fcn
));
656 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
660 if (strcmp(line
->cmd
, menu_cmds
[FINDROOT_CMD
])
661 == 0 && strcmp(line
->arg
, grubsign
) == 0) {
662 BAM_DPRINTF((D_FINDROOT_MATCH
, fcn
,
663 line
->line
, grubsign
));
666 if (line
== entry
->end
) {
667 BAM_DPRINTF((D_ENTRY_END
, fcn
));
671 } else if (root_opt
) {
672 /* Neither root nor findroot */
673 BAM_DPRINTF((D_NO_ROOT_FINDROOT
, fcn
, entry
->entryNum
));
678 BAM_DPRINTF((D_NO_MATCH
, fcn
));
683 * The following is a set of routines that attempt to convert the
684 * menu entries for the supplied osroot into a format compatible
685 * with the GRUB installation on osroot.
687 * Each of these conversion routines make no assumptions about
688 * the current state of the menu entry, it does its best to
689 * convert the menu entry to the new state. In the process
690 * we may either upgrade or downgrade.
692 * We don't make any heroic efforts at conversion. It is better
693 * to be conservative and bail out at the first sign of error. We will
694 * in such cases, point the user at the knowledge-base article
695 * so that they can upgrade manually.
698 bam_add_findroot(menu_t
*mp
, char *grubsign
, char *grubroot
, int root_opt
)
704 char linebuf
[PATH_MAX
];
705 const char *fcn
= "bam_add_findroot()";
709 bam_print(CVT_FINDROOT
);
712 for (; entry
= find_matching_entry(entry
, grubsign
, grubroot
, root_opt
);
713 entry
= entry
->next
) {
714 if (entry
->flags
& BAM_ENTRY_FINDROOT
) {
715 /* already converted */
716 BAM_DPRINTF((D_ALREADY_FINDROOT
, fcn
, entry
->entryNum
));
719 for (line
= entry
->start
; line
; line
= line
->next
) {
720 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
721 if (line
== entry
->end
) {
722 BAM_DPRINTF((D_ENTRY_END
, fcn
));
725 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
729 if (strcmp(line
->cmd
, menu_cmds
[TITLE_CMD
]) == 0) {
730 newlp
= s_calloc(1, sizeof (line_t
));
731 newlp
->cmd
= s_strdup(menu_cmds
[FINDROOT_CMD
]);
732 newlp
->sep
= s_strdup(" ");
733 newlp
->arg
= s_strdup(grubsign
);
734 (void) snprintf(linebuf
, sizeof (linebuf
),
735 "%s%s%s", newlp
->cmd
, newlp
->sep
,
737 newlp
->line
= s_strdup(linebuf
);
738 bam_add_line(mp
, entry
, line
, newlp
);
740 entry
->flags
&= ~BAM_ENTRY_ROOT
;
741 entry
->flags
|= BAM_ENTRY_FINDROOT
;
742 BAM_DPRINTF((D_ADDED_FINDROOT
, fcn
,
746 if (strcmp(line
->cmd
, menu_cmds
[ROOT_CMD
]) == 0) {
747 BAM_DPRINTF((D_FREEING_ROOT
, fcn
, line
->line
));
748 unlink_line(mp
, line
);
751 if (line
== entry
->end
) {
752 BAM_DPRINTF((D_ENTRY_END
, fcn
));
759 BAM_DPRINTF((D_UPDATED_NUMBERING
, fcn
));
760 update_numbering(mp
);
763 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
764 return (BAM_SUCCESS
);
768 bam_add_hv(menu_t
*mp
, char *grubsign
, char *grubroot
, int root_opt
)
771 const char *fcn
= "bam_add_hv()";
776 for (; entry
= find_matching_entry(entry
, grubsign
, grubroot
, root_opt
);
777 entry
= entry
->next
) {
778 if (entry
->flags
& BAM_ENTRY_HV
) {
779 BAM_DPRINTF((D_ALREADY_HV
, fcn
, entry
->entryNum
));
780 return (BAM_SUCCESS
);
784 (void) add_boot_entry(mp
, NEW_HV_ENTRY
, grubsign
, XEN_MENU
,
785 XEN_KERNEL_MODULE_LINE
, DIRECT_BOOT_ARCHIVE
, NULL
);
787 BAM_DPRINTF((D_ADDED_XVM_ENTRY
, fcn
));
789 update_numbering(mp
);
791 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
793 return (BAM_SUCCESS
);
808 const char *fcn
= "bam_add_dboot()";
810 bam_print(CVT_DBOOT
);
813 for (; entry
= find_matching_entry(entry
, grubsign
, grubroot
, root_opt
);
814 entry
= entry
->next
) {
815 for (line
= entry
->start
; line
; line
= line
->next
) {
816 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
817 if (line
== entry
->end
) {
818 BAM_DPRINTF((D_ENTRY_END
, fcn
));
821 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
827 * If we have a kernel$ command, assume it
828 * is dboot already. If it is not a dboot
829 * entry, something funny is going on and
830 * we will leave it alone
832 if (strcmp(line
->cmd
, menu_cmds
[KERNEL_CMD
]) == 0) {
833 ret
= cvt_kernel_line(line
, osroot
, entry
);
834 INJECT_ERROR1("ADD_DBOOT_KERN_ERR",
836 INJECT_ERROR1("ADD_DBOOT_KERN_MSG",
838 if (ret
== BAM_ERROR
) {
839 BAM_DPRINTF((D_CVT_KERNEL_FAIL
, fcn
));
841 } else if (ret
== BAM_MSG
) {
843 BAM_DPRINTF((D_CVT_KERNEL_MSG
, fcn
));
846 if (strcmp(line
->cmd
, menu_cmds
[MODULE_CMD
]) == 0) {
847 ret
= cvt_module_line(line
, entry
);
848 INJECT_ERROR1("ADD_DBOOT_MOD_ERR",
850 INJECT_ERROR1("ADD_DBOOT_MOD_MSG",
852 if (ret
== BAM_ERROR
) {
853 BAM_DPRINTF((D_CVT_MODULE_FAIL
, fcn
));
855 } else if (ret
== BAM_MSG
) {
856 BAM_DPRINTF((D_CVT_MODULE_MSG
, fcn
));
861 if (line
== entry
->end
) {
862 BAM_DPRINTF((D_ENTRY_END
, fcn
));
868 ret
= msg
? BAM_MSG
: BAM_SUCCESS
;
869 BAM_DPRINTF((D_RETURN_RET
, fcn
, ret
));
875 upgrade_menu(menu_t
*mp
, char *osroot
, char *menu_root
)
883 const char *fcn
= "upgrade_menu()";
888 BAM_DPRINTF((D_FUNC_ENTRY2
, fcn
, osroot
, menu_root
));
891 * We only support upgrades. Xen may not be present
892 * on smaller metaclusters so we don't check for that.
894 if (bam_is_findroot
!= BAM_FINDROOT_PRESENT
||
895 bam_direct
!= BAM_DIRECT_DBOOT
) {
896 bam_error(DOWNGRADE_NOTSUP
, osroot
);
901 * First get the GRUB signature
903 osdev
= get_special(osroot
);
904 INJECT_ERROR1("UPGRADE_OSDEV", osdev
= NULL
);
906 bam_error(CANT_FIND_SPECIAL
, osroot
);
910 grubsign
= get_grubsign(osroot
, osdev
);
911 INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign
= NULL
);
912 if (grubsign
== NULL
) {
914 bam_error(CANT_FIND_GRUBSIGN
, osroot
);
918 /* not fatal if we can't get grubroot */
919 grubroot
= get_grubroot(osroot
, osdev
, menu_root
);
920 INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot
= NULL
);
924 ret1
= bam_add_findroot(mp
, grubsign
,
925 grubroot
, root_optional(osroot
, menu_root
));
926 INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1
= BAM_ERROR
);
927 if (ret1
== BAM_ERROR
)
930 if (bam_is_hv
== BAM_HV_PRESENT
) {
931 ret2
= bam_add_hv(mp
, grubsign
, grubroot
,
932 root_optional(osroot
, menu_root
));
933 INJECT_ERROR1("UPGRADE_ADD_HV", ret2
= BAM_ERROR
);
934 if (ret2
== BAM_ERROR
)
939 ret3
= bam_add_dboot(mp
, osroot
, grubsign
,
940 grubroot
, root_optional(osroot
, menu_root
));
941 INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3
= BAM_ERROR
);
942 if (ret3
== BAM_ERROR
)
945 if (ret1
== BAM_MSG
|| ret2
== BAM_MSG
|| ret3
== BAM_MSG
) {
946 bam_error(CVT_TODO
, MENU_URL(osroot
));
948 bam_warn_hand_entries(mp
, osroot
);
953 BAM_DPRINTF((D_RETURN_RET
, fcn
, BAM_WRITE
));
958 bam_error(CVT_ABORT
, osroot
, MENU_URL(osroot
));