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 2015 Toomas Soome <tsoome@me.com>
32 #include <sys/types.h>
40 #include <sys/multiboot.h>
45 direct_or_multi_t bam_direct
= BAM_DIRECT_NOT_SET
;
46 hv_t bam_is_hv
= BAM_HV_UNKNOWN
;
47 findroot_t bam_is_findroot
= BAM_FINDROOT_UNKNOWN
;
50 get_findroot_cap(const char *osroot
)
54 char buf
[BAM_MAXLINE
];
59 const char *fcn
= "get_findroot_cap()";
61 (void) snprintf(path
, sizeof (path
), "%s/%s",
62 osroot
, "boot/grub/capability");
64 if (stat(path
, &sb
) == -1) {
65 bam_is_findroot
= BAM_FINDROOT_ABSENT
;
66 BAM_DPRINTF((D_FINDROOT_ABSENT
, fcn
));
70 fp
= fopen(path
, "r");
72 INJECT_ERROR1("GET_CAP_FINDROOT_FOPEN", fp
= NULL
);
74 bam_error(OPEN_FAIL
, path
, strerror(error
));
79 while (s_fgets(buf
, sizeof (buf
), fp
) != NULL
) {
80 if (strcmp(buf
, "findroot") == 0) {
81 BAM_DPRINTF((D_FINDROOT_PRESENT
, fcn
));
82 bam_is_findroot
= BAM_FINDROOT_PRESENT
;
84 if (strcmp(buf
, "dboot") == 0) {
85 BAM_DPRINTF((D_DBOOT_PRESENT
, fcn
));
92 if (bam_is_findroot
== BAM_FINDROOT_UNKNOWN
) {
93 bam_is_findroot
= BAM_FINDROOT_ABSENT
;
94 BAM_DPRINTF((D_FINDROOT_ABSENT
, fcn
));
99 INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret
= 1);
101 bam_error(CLOSE_FAIL
, path
, strerror(error
));
106 get_boot_cap(const char *osroot
)
108 char fname
[PATH_MAX
];
113 multiboot_header_t
*mbh
;
116 const char *fcn
= "get_boot_cap()";
119 /* there is no non dboot sparc new-boot */
120 bam_direct
= BAM_DIRECT_DBOOT
;
121 BAM_DPRINTF((D_IS_SPARC_DBOOT
, fcn
));
122 return (BAM_SUCCESS
);
125 (void) snprintf(fname
, PATH_MAX
, "%s/%s", osroot
,
126 "platform/i86pc/kernel/unix");
127 fd
= open(fname
, O_RDONLY
);
129 INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd
= -1);
131 bam_error(OPEN_FAIL
, fname
, strerror(error
));
136 * Verify that this is a sane unix at least 8192 bytes in length
138 if (fstat(fd
, &sb
) == -1 || sb
.st_size
< 8192) {
140 bam_error(INVALID_BINARY
, fname
);
147 image
= mmap(NULL
, 8192, PROT_READ
, MAP_SHARED
, fd
, 0);
149 INJECT_ERROR1("GET_CAP_MMAP", image
= MAP_FAILED
);
150 if (image
== MAP_FAILED
) {
151 bam_error(MMAP_FAIL
, fname
, strerror(error
));
155 ident
= (uchar_t
*)image
;
156 if (ident
[EI_MAG0
] != ELFMAG0
|| ident
[EI_MAG1
] != ELFMAG1
||
157 ident
[EI_MAG2
] != ELFMAG2
|| ident
[EI_MAG3
] != ELFMAG3
) {
158 bam_error(NOT_ELF_FILE
, fname
);
161 if (ident
[EI_CLASS
] != ELFCLASS32
) {
162 bam_error(WRONG_ELF_CLASS
, fname
, ident
[EI_CLASS
]);
167 * The GRUB multiboot header must be 32-bit aligned and completely
168 * contained in the 1st 8K of the file. If the unix binary has
169 * a multiboot header, then it is a 'dboot' kernel. Otherwise,
170 * this kernel must be booted via multiboot -- we call this a
171 * 'multiboot' kernel.
173 bam_direct
= BAM_DIRECT_MULTIBOOT
;
174 for (m
= 0; m
< 8192 - sizeof (multiboot_header_t
); m
+= 4) {
175 mbh
= (void *)(image
+ m
);
176 if (mbh
->magic
== MB_HEADER_MAGIC
) {
177 BAM_DPRINTF((D_IS_DBOOT
, fcn
));
178 bam_direct
= BAM_DIRECT_DBOOT
;
182 (void) munmap(image
, 8192);
185 INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct
= BAM_DIRECT_MULTIBOOT
);
186 if (bam_direct
== BAM_DIRECT_DBOOT
) {
187 if (bam_is_hv
== BAM_HV_PRESENT
) {
188 BAM_DPRINTF((D_IS_XVM
, fcn
));
190 BAM_DPRINTF((D_IS_NOT_XVM
, fcn
));
193 BAM_DPRINTF((D_IS_MULTIBOOT
, fcn
));
196 /* Not a fatal error if this fails */
197 get_findroot_cap(osroot
);
199 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
200 return (BAM_SUCCESS
);
203 #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE"
206 * Return true if root has been bfu'ed. bfu will blow away
207 * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
208 * assume the system has not been bfu'ed.
211 is_bfu_system(const char *root
)
213 static int is_bfu
= -1;
216 const char *fcn
= "is_bfu_system()";
219 BAM_DPRINTF((D_ALREADY_BFU_TEST
, fcn
, is_bfu
? "" : "NOT"));
223 (void) snprintf(path
, sizeof (path
), "%s/%s", root
, INST_RELEASE
);
224 if (stat(path
, &sb
) != 0) {
226 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
229 BAM_DPRINTF((D_RETURN_FAILURE
, fcn
));
234 #define MENU_URL(root) (is_bfu_system(root) ? \
235 "http://illumos.org/msg/SUNOS-8000-CF" : \
236 "http://illumos.org/msg/SUNOS-8000-AK")
239 * Simply allocate a new line and copy in cmd + sep + arg
242 update_line(line_t
*linep
)
245 const char *fcn
= "update_line()";
247 BAM_DPRINTF((D_UPDATE_LINE_BEFORE
, fcn
, linep
->line
));
249 size
= strlen(linep
->cmd
) + strlen(linep
->sep
) + strlen(linep
->arg
) + 1;
250 linep
->line
= s_calloc(1, size
);
251 (void) snprintf(linep
->line
, size
, "%s%s%s", linep
->cmd
, linep
->sep
,
253 BAM_DPRINTF((D_UPDATE_LINE_AFTER
, fcn
, linep
->line
));
257 skip_wspace(char *ptr
)
259 const char *fcn
= "skip_wspace()";
261 INJECT_ERROR1("SKIP_WSPACE", ptr
= NULL
);
263 BAM_DPRINTF((D_SKIP_WSPACE_PTR_NULL
, fcn
));
267 BAM_DPRINTF((D_SKIP_WSPACE_ENTRY_PTR
, fcn
, ptr
));
268 for (; *ptr
!= '\0'; ptr
++) {
269 if ((*ptr
!= ' ') && (*ptr
!= '\t') &&
274 ptr
= (*ptr
== '\0' ? NULL
: ptr
);
276 BAM_DPRINTF((D_SKIP_WSPACE_EXIT_PTR
, fcn
, ptr
? ptr
: "NULL"));
282 rskip_bspace(char *bound
, char *ptr
)
284 const char *fcn
= "rskip_bspace()";
287 assert(bound
<= ptr
);
288 assert(*bound
!= ' ' && *bound
!= '\t' && *bound
!= '\n');
290 BAM_DPRINTF((D_RSKIP_BSPACE_ENTRY
, fcn
, ptr
));
291 for (; ptr
> bound
; ptr
--) {
292 if (*ptr
== ' ' || *ptr
== '\t' || *ptr
== '\n')
296 BAM_DPRINTF((D_RSKIP_BSPACE_EXIT
, fcn
, ptr
));
301 * The parse_kernel_line function examines a menu.lst kernel line. For
302 * multiboot, this is:
304 * kernel <multiboot path> <flags1> <kernel path> <flags2>
306 * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot
308 * <kernel path> may be missing, or may be any full or relative path to unix.
309 * We check for it by looking for a word ending in "/unix". If it ends
310 * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in
311 * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise,
312 * it's a custom kernel, and we skip it.
314 * <flags*> are anything that doesn't fit either of the above - these will be
317 * For direct boot, the defaults are
319 * kernel$ <kernel path> <flags>
321 * <kernel path> is one of:
322 * /platform/i86pc/kernel/$ISADIR/unix
323 * /boot/platform/i86pc/kernel/$ISADIR/unix
324 * /platform/i86pc/kernel/unix
325 * /platform/i86pc/kernel/amd64/unix
326 * /boot/platform/i86pc/kernel/unix
327 * /boot/platform/i86pc/kernel/amd64/unix
329 * If <kernel path> is any of the last four, the command may also be "kernel".
331 * <flags> is anything that isn't <kernel path>.
333 * This function is only called to convert a multiboot entry to a dboot entry
335 * For safety, we do one more check: if the kernel path starts with /boot,
336 * we verify that the new kernel exists before changing it. This is mainly
337 * done for bfu, as it may cause the failsafe archives to be a different
338 * boot architecture from the newly bfu'ed system.
341 cvt_kernel_line(line_t
*line
, const char *osroot
, entry_t
*entry
)
343 char path
[PATH_MAX
], path_64
[PATH_MAX
];
344 char linebuf
[PATH_MAX
];
345 char new_arg
[PATH_MAX
];
346 struct stat sb
, sb_64
;
351 const char *fcn
= "cvt_kernel_line()";
353 BAM_DPRINTF((D_FUNC_ENTRY2
, fcn
, line
->line
, osroot
));
356 * We only convert multiboot to dboot and nothing else.
358 if (!(entry
->flags
& BAM_ENTRY_MULTIBOOT
)) {
359 BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT
, fcn
));
360 return (BAM_SUCCESS
);
363 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
365 * We're attempting to change failsafe to dboot.
366 * In the bfu case, we may not have a dboot failsafe
367 * kernel i.e. a "unix" under the "/boot" hierarchy.
368 * If so, just emit a message in verbose mode and
371 BAM_DPRINTF((D_TRYING_FAILSAFE_CVT_TO_DBOOT
, fcn
));
372 (void) snprintf(path
, PATH_MAX
, "%s%s", osroot
,
373 DIRECT_BOOT_FAILSAFE_32
);
374 (void) snprintf(path_64
, PATH_MAX
, "%s%s", osroot
,
375 DIRECT_BOOT_FAILSAFE_64
);
376 if (stat(path
, &sb
) != 0 && stat(path_64
, &sb_64
) != 0) {
378 bam_error(FAILSAFE_MISSING
, line
->lineNum
);
380 BAM_DPRINTF((D_NO_FAILSAFE_UNIX_CONVERT
, fcn
));
381 return (BAM_SUCCESS
);
386 * Make sure we have the correct cmd
390 line
->cmd
= s_strdup(menu_cmds
[KERNEL_DOLLAR_CMD
]);
391 BAM_DPRINTF((D_CVT_CMD_KERN_DOLLAR
, fcn
, line
->cmd
));
393 assert(sizeof (linebuf
) > strlen(line
->arg
) + 32);
394 (void) strlcpy(linebuf
, line
->arg
, sizeof (linebuf
));
396 old_ptr
= strpbrk(linebuf
, " \t\n");
397 old_ptr
= skip_wspace(old_ptr
);
398 if (old_ptr
== NULL
) {
400 * only multiboot and nothing else
401 * i.e. flags1 = unix = flags2 = NULL
403 flags1_ptr
= unix_ptr
= flags2_ptr
= NULL
;
404 BAM_DPRINTF((D_FLAGS1_UNIX_FLAGS2_NULL
, fcn
))
410 * old_ptr is either at "flags1" or "unix"
412 if ((unix_ptr
= strstr(old_ptr
, "/unix")) != NULL
) {
417 BAM_DPRINTF((D_UNIX_PRESENT
, fcn
));
419 /* See if there's a flags2 past unix */
420 flags2_ptr
= unix_ptr
+ strlen("/unix");
421 flags2_ptr
= skip_wspace(flags2_ptr
);
423 BAM_DPRINTF((D_FLAGS2_PRESENT
, fcn
, flags2_ptr
));
425 BAM_DPRINTF((D_FLAGS2_ABSENT
, fcn
));
428 /* see if there is a flags1 before unix */
429 unix_ptr
= rskip_bspace(old_ptr
, unix_ptr
);
431 if (unix_ptr
== old_ptr
) {
433 BAM_DPRINTF((D_FLAGS1_ABSENT
, fcn
));
435 flags1_ptr
= old_ptr
;
438 BAM_DPRINTF((D_FLAGS1_PRESENT
, fcn
, flags1_ptr
));
442 /* There is no unix, there is only a bunch of flags */
443 flags1_ptr
= old_ptr
;
444 unix_ptr
= flags2_ptr
= NULL
;
445 BAM_DPRINTF((D_FLAGS1_ONLY
, fcn
, flags1_ptr
));
449 * With dboot, unix is fixed and is at the beginning. We need to
450 * migrate flags1 and flags2
453 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
454 (void) snprintf(new_arg
, sizeof (new_arg
), "%s",
455 DIRECT_BOOT_FAILSAFE_KERNEL
);
457 (void) snprintf(new_arg
, sizeof (new_arg
), "%s",
460 BAM_DPRINTF((D_CVTED_UNIX
, fcn
, new_arg
));
462 if (flags1_ptr
!= NULL
) {
463 (void) strlcat(new_arg
, " ", sizeof (new_arg
));
464 (void) strlcat(new_arg
, flags1_ptr
, sizeof (new_arg
));
467 if (flags2_ptr
!= NULL
) {
468 (void) strlcat(new_arg
, " ", sizeof (new_arg
));
469 (void) strlcat(new_arg
, flags2_ptr
, sizeof (new_arg
));
472 BAM_DPRINTF((D_CVTED_UNIX_AND_FLAGS
, fcn
, new_arg
));
475 line
->arg
= s_strdup(new_arg
);
477 BAM_DPRINTF((D_CVTED_KERNEL_LINE
, fcn
, line
->line
));
478 return (BAM_SUCCESS
);
482 * Similar to above, except this time we're looking at a module line,
483 * which is quite a bit simpler.
485 * Under multiboot, the archive line is:
487 * module /platform/i86pc/boot_archive
489 * Under directboot, the archive line is:
491 * module$ /platform/i86pc/$ISADIR/boot_archive
493 * which may be specified exactly as either of:
495 * module /platform/i86pc/boot_archive
496 * module /platform/i86pc/amd64/boot_archive
498 * Under multiboot, the failsafe is:
500 * module /boot/x86.miniroot-safe
502 * Under dboot, the failsafe is:
504 * module$ /boot/$ISADIR/x86.miniroot-safe
506 * which may be specified exactly as either of:
508 * module /boot/x86.miniroot-safe
509 * module /boot/amd64/x86.miniroot-safe
512 cvt_module_line(line_t
*line
, entry_t
*entry
)
514 const char *fcn
= "cvt_module_line()";
516 BAM_DPRINTF((D_FUNC_ENTRY1
, fcn
, line
->line
));
519 * We only convert multiboot to dboot and nothing else
521 if (!(entry
->flags
& BAM_ENTRY_MULTIBOOT
)) {
522 BAM_DPRINTF((D_NOT_MULTIBOOT_CONVERT
, fcn
));
523 return (BAM_SUCCESS
);
526 if (entry
->flags
& BAM_ENTRY_FAILSAFE
) {
527 if (strcmp(line
->arg
, FAILSAFE_ARCHIVE
) == 0) {
528 BAM_DPRINTF((D_FAILSAFE_NO_CVT_NEEDED
, fcn
, line
->arg
));
529 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
530 return (BAM_SUCCESS
);
532 } else if (strcmp(line
->arg
, MULTIBOOT_ARCHIVE
) != 0) {
533 bam_error(UNKNOWN_MODULE_LINE
, line
->lineNum
);
534 BAM_DPRINTF((D_RETURN_FAILURE
, fcn
));
540 line
->cmd
= s_strdup(menu_cmds
[MODULE_DOLLAR_CMD
]);
542 line
->arg
= s_strdup(entry
->flags
& BAM_ENTRY_FAILSAFE
?
543 FAILSAFE_ARCHIVE
: DIRECT_BOOT_ARCHIVE
);
546 BAM_DPRINTF((D_CVTED_MODULE
, fcn
, line
->line
));
547 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
548 return (BAM_SUCCESS
);
552 bam_warn_hand_entries(menu_t
*mp
, char *osroot
)
559 const char *fcn
= "bam_warn_hand_entries()";
563 * No warning needed, we are automatically converting
566 BAM_DPRINTF((D_FORCE_HAND_CVT
, fcn
));
571 hand_max
= BAM_ENTRY_NUM
;
572 hand_list
= s_calloc(1, hand_max
);
574 for (entry
= mp
->entries
; entry
; entry
= entry
->next
) {
575 if (entry
->flags
& (BAM_ENTRY_BOOTADM
|BAM_ENTRY_LU
))
577 BAM_DPRINTF((D_FOUND_HAND
, fcn
, entry
->entryNum
));
578 if (++hand_num
> hand_max
) {
580 hand_list
= s_realloc(hand_list
,
581 hand_max
* sizeof (int));
583 hand_list
[hand_num
- 1] = entry
->entryNum
;
586 bam_error(HAND_ADDED_ENTRIES
, osroot
, MENU_URL(osroot
));
587 bam_print_stderr("Entry Number%s: ", (hand_num
> 1) ?
589 for (i
= 0; i
< hand_num
; i
++) {
590 bam_print_stderr("%d ", hand_list
[i
]);
592 bam_print_stderr("\n");
605 const char *fcn
= "find_matching_entry()";
608 assert(root_opt
== 0 || root_opt
== 1);
610 (void) snprintf(opt
, sizeof (opt
), "%d", root_opt
);
611 BAM_DPRINTF((D_FUNC_ENTRY3
, fcn
, grubsign
, grubroot
, opt
));
613 for (entry
= estart
; entry
; entry
= entry
->next
) {
615 if (!(entry
->flags
& (BAM_ENTRY_BOOTADM
|BAM_ENTRY_LU
)) &&
617 BAM_DPRINTF((D_SKIP_ENTRY
, fcn
, entry
->entryNum
));
621 if (entry
->flags
& BAM_ENTRY_ROOT
) {
622 for (line
= entry
->start
; line
; line
= line
->next
) {
623 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
624 if (line
== entry
->end
) {
625 BAM_DPRINTF((D_ENTRY_END
, fcn
));
628 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
632 if (strcmp(line
->cmd
, menu_cmds
[ROOT_CMD
])
633 == 0 && strcmp(line
->arg
, grubroot
) == 0) {
634 BAM_DPRINTF((D_ROOT_MATCH
, fcn
,
635 line
->line
, grubsign
));
638 if (line
== entry
->end
) {
639 BAM_DPRINTF((D_ENTRY_END
, fcn
));
643 } else if (entry
->flags
& BAM_ENTRY_FINDROOT
) {
644 for (line
= entry
->start
; line
; line
= line
->next
) {
645 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
646 if (line
== entry
->end
) {
647 BAM_DPRINTF((D_ENTRY_END
, fcn
));
650 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
654 if (strcmp(line
->cmd
, menu_cmds
[FINDROOT_CMD
])
655 == 0 && strcmp(line
->arg
, grubsign
) == 0) {
656 BAM_DPRINTF((D_FINDROOT_MATCH
, fcn
,
657 line
->line
, grubsign
));
660 if (line
== entry
->end
) {
661 BAM_DPRINTF((D_ENTRY_END
, fcn
));
665 } else if (root_opt
) {
666 /* Neither root nor findroot */
667 BAM_DPRINTF((D_NO_ROOT_FINDROOT
, fcn
, entry
->entryNum
));
672 BAM_DPRINTF((D_NO_MATCH
, fcn
));
677 * The following is a set of routines that attempt to convert the
678 * menu entries for the supplied osroot into a format compatible
679 * with the GRUB installation on osroot.
681 * Each of these conversion routines make no assumptions about
682 * the current state of the menu entry, it does its best to
683 * convert the menu entry to the new state. In the process
684 * we may either upgrade or downgrade.
686 * We don't make any heroic efforts at conversion. It is better
687 * to be conservative and bail out at the first sign of error. We will
688 * in such cases, point the user at the knowledge-base article
689 * so that they can upgrade manually.
692 bam_add_findroot(menu_t
*mp
, char *grubsign
, char *grubroot
, int root_opt
)
698 char linebuf
[PATH_MAX
];
699 const char *fcn
= "bam_add_findroot()";
703 bam_print(CVT_FINDROOT
);
705 entry
= find_matching_entry(mp
->entries
, grubsign
, grubroot
, root_opt
);
706 while (entry
!= NULL
) {
707 if (entry
->flags
& BAM_ENTRY_FINDROOT
) {
708 /* already converted */
709 BAM_DPRINTF((D_ALREADY_FINDROOT
, fcn
, entry
->entryNum
));
710 entry
= find_matching_entry(entry
->next
, grubsign
,
714 for (line
= entry
->start
; line
; line
= line
->next
) {
715 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
716 if (line
== entry
->end
) {
717 BAM_DPRINTF((D_ENTRY_END
, fcn
));
720 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
724 if (strcmp(line
->cmd
, menu_cmds
[TITLE_CMD
]) == 0) {
725 newlp
= s_calloc(1, sizeof (line_t
));
726 newlp
->cmd
= s_strdup(menu_cmds
[FINDROOT_CMD
]);
727 newlp
->sep
= s_strdup(" ");
728 newlp
->arg
= s_strdup(grubsign
);
729 (void) snprintf(linebuf
, sizeof (linebuf
),
730 "%s%s%s", newlp
->cmd
, newlp
->sep
,
732 newlp
->line
= s_strdup(linebuf
);
733 bam_add_line(mp
, entry
, line
, newlp
);
735 entry
->flags
&= ~BAM_ENTRY_ROOT
;
736 entry
->flags
|= BAM_ENTRY_FINDROOT
;
737 BAM_DPRINTF((D_ADDED_FINDROOT
, fcn
,
741 if (strcmp(line
->cmd
, menu_cmds
[ROOT_CMD
]) == 0) {
742 BAM_DPRINTF((D_FREEING_ROOT
, fcn
, line
->line
));
743 unlink_line(mp
, line
);
746 if (line
== entry
->end
) {
747 BAM_DPRINTF((D_ENTRY_END
, fcn
));
751 entry
= find_matching_entry(entry
->next
, grubsign
, grubroot
,
756 BAM_DPRINTF((D_UPDATED_NUMBERING
, fcn
));
757 update_numbering(mp
);
760 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
761 return (BAM_SUCCESS
);
765 bam_add_hv(menu_t
*mp
, char *grubsign
, char *grubroot
, int root_opt
)
768 const char *fcn
= "bam_add_hv()";
772 entry
= find_matching_entry(mp
->entries
, grubsign
, grubroot
, root_opt
);
773 while (entry
!= NULL
) {
774 if (entry
->flags
& BAM_ENTRY_HV
) {
775 BAM_DPRINTF((D_ALREADY_HV
, fcn
, entry
->entryNum
));
776 return (BAM_SUCCESS
);
778 entry
= find_matching_entry(entry
->next
, grubsign
, grubroot
,
782 (void) add_boot_entry(mp
, NEW_HV_ENTRY
, grubsign
, XEN_MENU
,
783 XEN_KERNEL_MODULE_LINE
, DIRECT_BOOT_ARCHIVE
, NULL
);
785 BAM_DPRINTF((D_ADDED_XVM_ENTRY
, fcn
));
787 update_numbering(mp
);
789 BAM_DPRINTF((D_RETURN_SUCCESS
, fcn
));
791 return (BAM_SUCCESS
);
806 const char *fcn
= "bam_add_dboot()";
808 bam_print(CVT_DBOOT
);
810 entry
= find_matching_entry(mp
->entries
, grubsign
, grubroot
, root_opt
);
811 while (entry
!= NULL
) {
812 for (line
= entry
->start
; line
; line
= line
->next
) {
813 if (line
->cmd
== NULL
|| line
->arg
== NULL
) {
814 if (line
== entry
->end
) {
815 BAM_DPRINTF((D_ENTRY_END
, fcn
));
818 BAM_DPRINTF((D_SKIP_NULL
, fcn
));
824 * If we have a kernel$ command, assume it
825 * is dboot already. If it is not a dboot
826 * entry, something funny is going on and
827 * we will leave it alone
829 if (strcmp(line
->cmd
, menu_cmds
[KERNEL_CMD
]) == 0) {
830 ret
= cvt_kernel_line(line
, osroot
, entry
);
831 INJECT_ERROR1("ADD_DBOOT_KERN_ERR",
833 INJECT_ERROR1("ADD_DBOOT_KERN_MSG",
835 if (ret
== BAM_ERROR
) {
836 BAM_DPRINTF((D_CVT_KERNEL_FAIL
, fcn
));
838 } else if (ret
== BAM_MSG
) {
840 BAM_DPRINTF((D_CVT_KERNEL_MSG
, fcn
));
843 if (strcmp(line
->cmd
, menu_cmds
[MODULE_CMD
]) == 0) {
844 ret
= cvt_module_line(line
, entry
);
845 INJECT_ERROR1("ADD_DBOOT_MOD_ERR",
847 INJECT_ERROR1("ADD_DBOOT_MOD_MSG",
849 if (ret
== BAM_ERROR
) {
850 BAM_DPRINTF((D_CVT_MODULE_FAIL
, fcn
));
852 } else if (ret
== BAM_MSG
) {
853 BAM_DPRINTF((D_CVT_MODULE_MSG
, fcn
));
858 if (line
== entry
->end
) {
859 BAM_DPRINTF((D_ENTRY_END
, fcn
));
863 entry
= find_matching_entry(entry
->next
, grubsign
, grubroot
,
867 ret
= msg
? BAM_MSG
: BAM_SUCCESS
;
868 BAM_DPRINTF((D_RETURN_RET
, fcn
, ret
));
874 upgrade_menu(menu_t
*mp
, char *osroot
, char *menu_root
)
882 const char *fcn
= "upgrade_menu()";
887 BAM_DPRINTF((D_FUNC_ENTRY2
, fcn
, osroot
, menu_root
));
890 * We only support upgrades. Xen may not be present
891 * on smaller metaclusters so we don't check for that.
893 if (bam_is_findroot
!= BAM_FINDROOT_PRESENT
||
894 bam_direct
!= BAM_DIRECT_DBOOT
) {
895 bam_error(DOWNGRADE_NOTSUP
);
900 * First get the GRUB signature
902 osdev
= get_special(osroot
);
903 INJECT_ERROR1("UPGRADE_OSDEV", osdev
= NULL
);
905 bam_error(CANT_FIND_SPECIAL
, osroot
);
909 grubsign
= get_grubsign(osroot
, osdev
);
910 INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign
= NULL
);
911 if (grubsign
== NULL
) {
913 bam_error(CANT_FIND_GRUBSIGN
, osroot
);
917 /* not fatal if we can't get grubroot */
918 grubroot
= get_grubroot(osroot
, osdev
, menu_root
);
919 INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot
= NULL
);
923 ret1
= bam_add_findroot(mp
, grubsign
,
924 grubroot
, root_optional(osroot
, menu_root
));
925 INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1
= BAM_ERROR
);
926 if (ret1
== BAM_ERROR
)
929 if (bam_is_hv
== BAM_HV_PRESENT
) {
930 ret2
= bam_add_hv(mp
, grubsign
, grubroot
,
931 root_optional(osroot
, menu_root
));
932 INJECT_ERROR1("UPGRADE_ADD_HV", ret2
= BAM_ERROR
);
933 if (ret2
== BAM_ERROR
)
938 ret3
= bam_add_dboot(mp
, osroot
, grubsign
,
939 grubroot
, root_optional(osroot
, menu_root
));
940 INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3
= BAM_ERROR
);
941 if (ret3
== BAM_ERROR
)
944 if (ret1
== BAM_MSG
|| ret2
== BAM_MSG
|| ret3
== BAM_MSG
) {
945 bam_error(CVT_TODO
, MENU_URL(osroot
));
947 bam_warn_hand_entries(mp
, osroot
);
952 BAM_DPRINTF((D_RETURN_RET
, fcn
, BAM_WRITE
));
957 bam_error(CVT_ABORT
, osroot
, MENU_URL(osroot
));