272
273 static int is_amd64(void);
274 static char *get_machine(void);
275 static void append_to_flist(filelist_t *, char *);
276 static int ufs_add_to_sign_list(char *sign);
277 static error_t synchronize_BE_menu(void);
278
279 #if !defined(_OBP)
280 static void ucode_install();
281 #endif
282
283 /* Menu related sub commands */
284 static subcmd_defn_t menu_subcmds[] = {
285 "set_option", OPT_ABSENT, set_option, 0, /* PUB */
286 "list_entry", OPT_OPTIONAL, list_entry, 1, /* PUB */
287 "delete_all_entries", OPT_ABSENT, delete_all_entries, 0, /* PVT */
288 "update_entry", OPT_REQ, update_entry, 0, /* menu */
289 "update_temp", OPT_OPTIONAL, update_temp, 0, /* reboot */
290 "upgrade", OPT_ABSENT, upgrade_menu, 0, /* menu */
291 "list_setting", OPT_OPTIONAL, list_setting, 1, /* menu */
292 "disable_hypervisor", OPT_ABSENT, cvt_to_metal, 0, /* menu */
293 "enable_hypervisor", OPT_ABSENT, cvt_to_hyper, 0, /* menu */
294 NULL, 0, NULL, 0 /* must be last */
295 };
296
297 /* Archive related sub commands */
298 static subcmd_defn_t arch_subcmds[] = {
299 "update", OPT_ABSENT, update_archive, 0, /* PUB */
300 "update_all", OPT_ABSENT, update_all, 0, /* PVT */
301 "list", OPT_OPTIONAL, list_archive, 1, /* PUB */
302 NULL, 0, NULL, 0 /* must be last */
303 };
304
305 /* Install related sub commands */
306 static subcmd_defn_t inst_subcmds[] = {
307 "install_bootloader", OPT_ABSENT, install_bootloader, 0, /* PUB */
308 NULL, 0, NULL, 0 /* must be last */
309 };
310
311 enum dircache_copy_opt {
312 FILE32 = 0,
313 FILE64,
535 if (is_grub(bam_alt_root ? bam_root : "/")) {
536 ret = bam_menu(bam_subcmd, bam_opt,
537 bam_argc, bam_argv);
538 } else {
539 ret = bam_loader_menu(bam_subcmd, bam_opt,
540 bam_argc, bam_argv);
541 }
542 break;
543 case BAM_ARCHIVE:
544 ret = bam_archive(bam_subcmd, bam_opt);
545 break;
546 case BAM_INSTALL:
547 ret = bam_install(bam_subcmd, bam_opt);
548 break;
549 default:
550 usage();
551 bam_exit(1);
552 }
553
554 if (ret != BAM_SUCCESS)
555 bam_exit((ret == BAM_NOCHANGE) ? 2 : 1);
556
557 bam_unlock();
558 return (0);
559 }
560
561 /*
562 * Equivalence of public and internal commands:
563 * update-archive -- -a update
564 * list-archive -- -a list
565 * set-menu -- -m set_option
566 * list-menu -- -m list_entry
567 * update-menu -- -m update_entry
568 * install-bootloader -- -i install_bootloader
569 */
570 static struct cmd_map {
571 char *bam_cmdname;
572 int bam_cmd;
573 char *bam_subcmd;
574 } cmd_map[] = {
575 { "update-archive", BAM_ARCHIVE, "update"},
607 bam_exit(1);
608 }
609 argc--;
610 argv++;
611 }
612
613 parse_args_internal(argc, argv);
614 }
615
616 /*
617 * A combination of public and private commands are parsed here.
618 * The internal syntax and the corresponding functionality are:
619 * -a update -- update-archive
620 * -a list -- list-archive
621 * -a update-all -- (reboot to sync all mnted OS archive)
622 * -i install_bootloader -- install-bootloader
623 * -m update_entry -- update-menu
624 * -m list_entry -- list-menu
625 * -m update_temp -- (reboot -- [boot-args])
626 * -m delete_all_entries -- (called from install)
627 * -m enable_hypervisor [args] -- cvt_to_hyper
628 * -m disable_hypervisor -- cvt_to_metal
629 * -m list_setting [entry] [value] -- list_setting
630 *
631 * A set of private flags is there too:
632 * -F -- purge the cache directories and rebuild them
633 * -e -- use the (faster) archive update approach (used by
634 * reboot)
635 */
636 static void
637 parse_args_internal(int argc, char *argv[])
638 {
639 int c, error;
640 extern char *optarg;
641 extern int optind, opterr;
642 #if defined(_OBP)
643 const char *optstring = "a:d:fi:m:no:veFCR:p:P:XZ";
644 #else
645 const char *optstring = "a:d:fi:m:no:veFCMR:p:P:XZ";
646 #endif
647
648 /* Suppress error message from getopt */
745 optarg, strerror(errno));
746 break;
747 }
748 bam_alt_root = 1;
749 bam_root = rootbuf;
750 bam_rootlen = strlen(rootbuf);
751 break;
752 case 'p':
753 bam_alt_platform = 1;
754 bam_platform = optarg;
755 if ((strcmp(bam_platform, "i86pc") != 0) &&
756 (strcmp(bam_platform, "sun4u") != 0) &&
757 (strcmp(bam_platform, "sun4v") != 0)) {
758 error = 1;
759 bam_error(_("invalid platform %s - must be "
760 "one of sun4u, sun4v or i86pc\n"),
761 bam_platform);
762 }
763 break;
764 case 'X':
765 bam_is_hv = BAM_HV_PRESENT;
766 break;
767 case 'Z':
768 bam_zfs = 1;
769 break;
770 case 'e':
771 bam_extend = 1;
772 break;
773 case '?':
774 error = 1;
775 bam_error(_("invalid option or missing option "
776 "argument: -%c\n"), optopt);
777 break;
778 default :
779 error = 1;
780 bam_error(_("invalid option or missing option "
781 "argument: -%c\n"), c);
782 break;
783 }
784 }
785
851 usage();
852 return (BAM_ERROR);
853 } else if (bam_argc > 1 || bam_argv[1] != NULL) {
854 bam_error(_("invalid trailing arguments\n"));
855 usage();
856 return (BAM_ERROR);
857 }
858 } else if (strcmp(subcmd, "update_all") == 0) {
859 /*
860 * The only option we accept for the "update_all"
861 * subcmd is "fastboot".
862 */
863 if (bam_argc > 1 || (bam_argc == 1 &&
864 strcmp(bam_argv[0], "fastboot") != 0)) {
865 bam_error(_("invalid trailing arguments\n"));
866 usage();
867 return (BAM_ERROR);
868 }
869 if (bam_argc == 1)
870 sync_menu = 0;
871 } else if (((strcmp(subcmd, "enable_hypervisor") != 0) &&
872 (strcmp(subcmd, "list_setting") != 0)) && (bam_argc || bam_argv)) {
873 /*
874 * Of the remaining subcommands, only "enable_hypervisor" and
875 * "list_setting" take trailing arguments.
876 */
877 bam_error(_("invalid trailing arguments\n"));
878 usage();
879 return (BAM_ERROR);
880 }
881
882 if (bam_root == NULL) {
883 bam_root = rootbuf;
884 bam_rootlen = 1;
885 }
886
887 /* verify that subcmd is valid */
888 for (i = 0; table[i].subcmd != NULL; i++) {
889 if (strcmp(table[i].subcmd, subcmd) == 0)
890 break;
891 }
892
893 if (table[i].subcmd == NULL) {
894 bam_error(_("invalid sub-command specified: %s\n"), subcmd);
895 return (BAM_ERROR);
1414 */
1415 if (strcmp(subcmd, "list_entry") == 0)
1416 bam_print(_("the location for the active GRUB menu is: %s\n"),
1417 menu_path);
1418
1419 if ((menu = menu_read(menu_path)) == NULL) {
1420 bam_error(_("cannot find GRUB menu file: %s\n"), menu_path);
1421 free(special);
1422
1423 return (BAM_ERROR);
1424 }
1425
1426 /*
1427 * We already checked the following case in
1428 * check_subcmd_and_suboptions() above. Complete the
1429 * final step now.
1430 */
1431 if (strcmp(subcmd, "set_option") == 0) {
1432 assert(largc == 1 && largv[0] && largv[1] == NULL);
1433 opt = largv[0];
1434 } else if ((strcmp(subcmd, "enable_hypervisor") != 0) &&
1435 (strcmp(subcmd, "list_setting") != 0)) {
1436 assert(largc == 0 && largv == NULL);
1437 }
1438
1439 ret = get_boot_cap(bam_root);
1440 if (ret != BAM_SUCCESS) {
1441 BAM_DPRINTF(("%s: Failed to get boot capability\n", fcn));
1442 goto out;
1443 }
1444
1445 /*
1446 * Once the sub-cmd handler has run
1447 * only the line field is guaranteed to have valid values
1448 */
1449 if (strcmp(subcmd, "update_entry") == 0) {
1450 ret = f(menu, menu_root, osdev);
1451 } else if (strcmp(subcmd, "upgrade") == 0) {
1452 ret = f(menu, bam_root, menu_root);
1453 } else if (strcmp(subcmd, "list_entry") == 0) {
1454 ret = f(menu, menu_path, opt);
1455 } else if (strcmp(subcmd, "list_setting") == 0) {
1456 ret = f(menu, ((largc > 0) ? largv[0] : ""),
1457 ((largc > 1) ? largv[1] : ""));
1458 } else if (strcmp(subcmd, "disable_hypervisor") == 0) {
1459 if (is_sparc()) {
1460 bam_error(_("%s operation unsupported on SPARC "
1461 "machines\n"), subcmd);
1462 ret = BAM_ERROR;
1463 } else {
1464 ret = f(menu, bam_root, NULL);
1465 }
1466 } else if (strcmp(subcmd, "enable_hypervisor") == 0) {
1467 if (is_sparc()) {
1468 bam_error(_("%s operation unsupported on SPARC "
1469 "machines\n"), subcmd);
1470 ret = BAM_ERROR;
1471 } else {
1472 char *extra_args = NULL;
1473
1474 /*
1475 * Compress all arguments passed in the largv[] array
1476 * into one string that can then be appended to the
1477 * end of the kernel$ string the routine to enable the
1478 * hypervisor will build.
1479 *
1480 * This allows the caller to supply arbitrary unparsed
1481 * arguments, such as dom0 memory settings or APIC
1482 * options.
1483 *
1484 * This concatenation will be done without ANY syntax
1485 * checking whatsoever, so it's the responsibility of
1486 * the caller to make sure the arguments are valid and
1487 * do not duplicate arguments the conversion routines
1488 * may create.
1489 */
1490 if (largc > 0) {
1491 int extra_len, i;
1492
1493 for (extra_len = 0, i = 0; i < largc; i++)
1494 extra_len += strlen(largv[i]);
1495
1496 /*
1497 * Allocate space for argument strings,
1498 * intervening spaces and terminating NULL.
1499 */
1500 extra_args = alloca(extra_len + largc);
1501
1502 (void) strcpy(extra_args, largv[0]);
1503
1504 for (i = 1; i < largc; i++) {
1505 (void) strcat(extra_args, " ");
1506 (void) strcat(extra_args, largv[i]);
1507 }
1508 }
1509
1510 ret = f(menu, bam_root, extra_args);
1511 }
1512 } else
1513 ret = f(menu, NULL, opt);
1514
1515 if (ret == BAM_WRITE) {
1516 BAM_DPRINTF(("%s: writing menu to clean-menu-root: <%s>\n",
1517 fcn, clean_menu_root));
1518 ret = menu_write(clean_menu_root, menu);
1519 }
1520
1521 out:
1522 INJECT_ERROR1("POOL_SET", pool = "/pooldata");
1523 assert((is_zfs(menu_root)) ^ (pool == NULL));
1524 if (pool) {
1525 (void) umount_top_dataset(pool, zmnted, zmntpt);
1526 free(special);
1527 }
1528 menu_free(menu);
1529 return (ret);
1530 }
1531
4612 } else if (strncmp(arg, DIRECT_BOOT_FAILSAFE_32,
4613 sizeof (DIRECT_BOOT_FAILSAFE_32) - 1) == 0) {
4614 BAM_DPRINTF(("%s: setting DBOOT|DBOOT_FAILSAFE|DBOOT_32 "
4615 "flag: %s\n", fcn, arg));
4616 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_FAILSAFE
4617 | BAM_ENTRY_32BIT;
4618 } else if (strncmp(arg, DIRECT_BOOT_FAILSAFE_64,
4619 sizeof (DIRECT_BOOT_FAILSAFE_64) - 1) == 0) {
4620 BAM_DPRINTF(("%s: setting DBOOT|DBOOT_FAILSAFE|DBOOT_64 "
4621 "flag: %s\n", fcn, arg));
4622 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_FAILSAFE
4623 | BAM_ENTRY_64BIT;
4624 } else if (strncmp(arg, MULTI_BOOT, sizeof (MULTI_BOOT) - 1) == 0) {
4625 BAM_DPRINTF(("%s: setting MULTIBOOT flag: %s\n", fcn, arg));
4626 entry->flags |= BAM_ENTRY_MULTIBOOT;
4627 } else if (strncmp(arg, MULTI_BOOT_FAILSAFE,
4628 sizeof (MULTI_BOOT_FAILSAFE) - 1) == 0) {
4629 BAM_DPRINTF(("%s: setting MULTIBOOT|MULTIBOOT_FAILSAFE "
4630 "flag: %s\n", fcn, arg));
4631 entry->flags |= BAM_ENTRY_MULTIBOOT | BAM_ENTRY_FAILSAFE;
4632 } else if (strstr(arg, XEN_KERNEL_SUBSTR)) {
4633 BAM_DPRINTF(("%s: setting XEN HV flag: %s\n", fcn, arg));
4634 entry->flags |= BAM_ENTRY_HV;
4635 } else if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))) {
4636 BAM_DPRINTF(("%s: is HAND kernel flag: %s\n", fcn, arg));
4637 return (BAM_ERROR);
4638 } else if (strncmp(arg, KERNEL_PREFIX, strlen(KERNEL_PREFIX)) == 0 &&
4639 strstr(arg, UNIX_SPACE)) {
4640 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_32BIT;
4641 } else if (strncmp(arg, KERNEL_PREFIX, strlen(KERNEL_PREFIX)) == 0 &&
4642 strstr(arg, AMD_UNIX_SPACE)) {
4643 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_64BIT;
4644 } else {
4645 BAM_DPRINTF(("%s: is UNKNOWN kernel entry: %s\n", fcn, arg));
4646 bam_error(_("kernel command on line %d not recognized.\n"),
4647 linenum);
4648 return (BAM_ERROR);
4649 }
4650
4651 return (BAM_SUCCESS);
4652 }
4653
4654 static error_t
4655 module_parser(entry_t *entry, char *cmd, char *arg, int linenum)
4656 {
4657 const char *fcn = "module_parser()";
4658
4659 assert(entry);
4660 assert(cmd);
4661 assert(arg);
4662
4663 if (strcmp(cmd, menu_cmds[MODULE_CMD]) != 0 &&
4664 strcmp(cmd, menu_cmds[MODULE_DOLLAR_CMD]) != 0) {
4665 BAM_DPRINTF(("%s: not module cmd: %s\n", fcn, cmd));
4666 return (BAM_ERROR);
4667 }
4668
4669 if (strcmp(arg, DIRECT_BOOT_ARCHIVE) == 0 ||
4670 strcmp(arg, DIRECT_BOOT_ARCHIVE_32) == 0 ||
4671 strcmp(arg, DIRECT_BOOT_ARCHIVE_64) == 0 ||
4672 strcmp(arg, MULTIBOOT_ARCHIVE) == 0 ||
4673 strcmp(arg, FAILSAFE_ARCHIVE) == 0 ||
4674 strcmp(arg, FAILSAFE_ARCHIVE_32) == 0 ||
4675 strcmp(arg, FAILSAFE_ARCHIVE_64) == 0 ||
4676 strcmp(arg, XEN_KERNEL_MODULE_LINE) == 0 ||
4677 strcmp(arg, XEN_KERNEL_MODULE_LINE_ZFS) == 0) {
4678 BAM_DPRINTF(("%s: bootadm or LU module cmd: %s\n", fcn, arg));
4679 return (BAM_SUCCESS);
4680 } else if (!(entry->flags & BAM_ENTRY_BOOTADM) &&
4681 !(entry->flags & BAM_ENTRY_LU)) {
4682 /* don't emit warning for hand entries */
4683 BAM_DPRINTF(("%s: is HAND module: %s\n", fcn, arg));
4684 return (BAM_ERROR);
4685 } else {
4686 BAM_DPRINTF(("%s: is UNKNOWN module: %s\n", fcn, arg));
4687 bam_error(_("module command on line %d not recognized.\n"),
4688 linenum);
4689 return (BAM_ERROR);
4690 }
4691 }
4692
4693 /*
4694 * A line in menu.lst looks like
4695 * [ ]*<cmd>[ \t=]*<arg>*
4696 */
4697 static void
8236 if (lp == NULL || lp->next == NULL) {
8237 continue;
8238 }
8239
8240 if (kernel &&
8241 (!check_cmd(lp->cmd, KERNEL_CMD, lp->arg, kernel))) {
8242 if (!(ent->flags & BAM_ENTRY_FAILSAFE) ||
8243 !(ent->flags & BAM_ENTRY_DBOOT) ||
8244 strcmp(kernel, DIRECT_BOOT_FAILSAFE_LINE) != 0)
8245 continue;
8246
8247 ent->flags |= BAM_ENTRY_UPGFSKERNEL;
8248
8249 }
8250 BAM_DPRINTF(("%s: kernel match: %s, %s\n", fcn,
8251 kernel, lp->arg));
8252
8253 /*
8254 * Check for matching module entry (failsafe or normal).
8255 * If it fails to match, we go around the loop again.
8256 * For xpv entries, there are two module lines, so we
8257 * do the check twice.
8258 */
8259 lp = lp->next; /* advance to module line */
8260 if (check_cmd(lp->cmd, MODULE_CMD, lp->arg, module) ||
8261 (((lp = lp->next) != NULL) &&
8262 check_cmd(lp->cmd, MODULE_CMD, lp->arg, module))) {
8263 /* match found */
8264 BAM_DPRINTF(("%s: module match: %s, %s\n", fcn,
8265 module, lp->arg));
8266 break;
8267 }
8268
8269 if (strcmp(module, FAILSAFE_ARCHIVE) == 0 &&
8270 (strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_32) == 0 ||
8271 strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_64) == 0)) {
8272 ent->flags |= BAM_ENTRY_UPGFSMODULE;
8273 break;
8274 }
8275
8276 }
8277
8278 if (ent && entry_num) {
8279 *entry_num = i;
8280 }
8281
8282 if (ent) {
8571 grubroot = get_grubroot(osroot, osdev, menu_root);
8572 INJECT_ERROR1("GET_GRUBROOT_FAIL", grubroot = NULL);
8573 if (grubroot) {
8574 BAM_DPRINTF(("%s: get_grubroot success. osroot=%s, osdev=%s, "
8575 "menu_root=%s\n", fcn, osroot, osdev, menu_root));
8576 } else {
8577 BAM_DPRINTF(("%s: get_grubroot failed. osroot=%s, osdev=%s, "
8578 "menu_root=%s\n", fcn, osroot, osdev, menu_root));
8579 }
8580
8581 /* add the entry for normal Solaris */
8582 INJECT_ERROR1("UPDATE_ENTRY_MULTIBOOT",
8583 bam_direct = BAM_DIRECT_MULTIBOOT);
8584 if (bam_direct == BAM_DIRECT_DBOOT) {
8585 entry = update_boot_entry(mp, title, grubsign, grubroot,
8586 (bam_zfs ? DIRECT_BOOT_KERNEL_ZFS : DIRECT_BOOT_KERNEL),
8587 NULL, DIRECT_BOOT_ARCHIVE,
8588 root_optional(osroot, menu_root));
8589 BAM_DPRINTF(("%s: updated boot entry bam_zfs=%d, "
8590 "grubsign = %s\n", fcn, bam_zfs, grubsign));
8591 if ((entry != BAM_ERROR) && (bam_is_hv == BAM_HV_PRESENT)) {
8592 (void) update_boot_entry(mp, NEW_HV_ENTRY, grubsign,
8593 grubroot, XEN_MENU, bam_zfs ?
8594 XEN_KERNEL_MODULE_LINE_ZFS : XEN_KERNEL_MODULE_LINE,
8595 DIRECT_BOOT_ARCHIVE,
8596 root_optional(osroot, menu_root));
8597 BAM_DPRINTF(("%s: updated HV entry bam_zfs=%d, "
8598 "grubsign = %s\n", fcn, bam_zfs, grubsign));
8599 }
8600 } else {
8601 entry = update_boot_entry(mp, title, grubsign, grubroot,
8602 MULTI_BOOT, NULL, MULTIBOOT_ARCHIVE,
8603 root_optional(osroot, menu_root));
8604
8605 BAM_DPRINTF(("%s: updated MULTIBOOT entry grubsign = %s\n",
8606 fcn, grubsign));
8607 }
8608
8609 /*
8610 * Add the entry for failsafe archive. On a bfu'd system, the
8611 * failsafe may be different than the installed kernel.
8612 */
8613 (void) snprintf(failsafe, sizeof (failsafe), "%s%s",
8614 osroot, FAILSAFE_ARCHIVE_32);
8615 (void) snprintf(failsafe_64, sizeof (failsafe_64), "%s%s",
8616 osroot, FAILSAFE_ARCHIVE_64);
8617
8618 /*
8619 * Check if at least one of the two archives exists
8620 * Using $ISADIR as the default line, we have an entry which works
8621 * for both the cases.
8622 */
8623
8624 if (stat(failsafe, &sbuf) == 0 || stat(failsafe_64, &sbuf) == 0) {
|
272
273 static int is_amd64(void);
274 static char *get_machine(void);
275 static void append_to_flist(filelist_t *, char *);
276 static int ufs_add_to_sign_list(char *sign);
277 static error_t synchronize_BE_menu(void);
278
279 #if !defined(_OBP)
280 static void ucode_install();
281 #endif
282
283 /* Menu related sub commands */
284 static subcmd_defn_t menu_subcmds[] = {
285 "set_option", OPT_ABSENT, set_option, 0, /* PUB */
286 "list_entry", OPT_OPTIONAL, list_entry, 1, /* PUB */
287 "delete_all_entries", OPT_ABSENT, delete_all_entries, 0, /* PVT */
288 "update_entry", OPT_REQ, update_entry, 0, /* menu */
289 "update_temp", OPT_OPTIONAL, update_temp, 0, /* reboot */
290 "upgrade", OPT_ABSENT, upgrade_menu, 0, /* menu */
291 "list_setting", OPT_OPTIONAL, list_setting, 1, /* menu */
292 NULL, 0, NULL, 0 /* must be last */
293 };
294
295 /* Archive related sub commands */
296 static subcmd_defn_t arch_subcmds[] = {
297 "update", OPT_ABSENT, update_archive, 0, /* PUB */
298 "update_all", OPT_ABSENT, update_all, 0, /* PVT */
299 "list", OPT_OPTIONAL, list_archive, 1, /* PUB */
300 NULL, 0, NULL, 0 /* must be last */
301 };
302
303 /* Install related sub commands */
304 static subcmd_defn_t inst_subcmds[] = {
305 "install_bootloader", OPT_ABSENT, install_bootloader, 0, /* PUB */
306 NULL, 0, NULL, 0 /* must be last */
307 };
308
309 enum dircache_copy_opt {
310 FILE32 = 0,
311 FILE64,
533 if (is_grub(bam_alt_root ? bam_root : "/")) {
534 ret = bam_menu(bam_subcmd, bam_opt,
535 bam_argc, bam_argv);
536 } else {
537 ret = bam_loader_menu(bam_subcmd, bam_opt,
538 bam_argc, bam_argv);
539 }
540 break;
541 case BAM_ARCHIVE:
542 ret = bam_archive(bam_subcmd, bam_opt);
543 break;
544 case BAM_INSTALL:
545 ret = bam_install(bam_subcmd, bam_opt);
546 break;
547 default:
548 usage();
549 bam_exit(1);
550 }
551
552 if (ret != BAM_SUCCESS)
553 bam_exit(1);
554
555 bam_unlock();
556 return (0);
557 }
558
559 /*
560 * Equivalence of public and internal commands:
561 * update-archive -- -a update
562 * list-archive -- -a list
563 * set-menu -- -m set_option
564 * list-menu -- -m list_entry
565 * update-menu -- -m update_entry
566 * install-bootloader -- -i install_bootloader
567 */
568 static struct cmd_map {
569 char *bam_cmdname;
570 int bam_cmd;
571 char *bam_subcmd;
572 } cmd_map[] = {
573 { "update-archive", BAM_ARCHIVE, "update"},
605 bam_exit(1);
606 }
607 argc--;
608 argv++;
609 }
610
611 parse_args_internal(argc, argv);
612 }
613
614 /*
615 * A combination of public and private commands are parsed here.
616 * The internal syntax and the corresponding functionality are:
617 * -a update -- update-archive
618 * -a list -- list-archive
619 * -a update-all -- (reboot to sync all mnted OS archive)
620 * -i install_bootloader -- install-bootloader
621 * -m update_entry -- update-menu
622 * -m list_entry -- list-menu
623 * -m update_temp -- (reboot -- [boot-args])
624 * -m delete_all_entries -- (called from install)
625 * -m list_setting [entry] [value] -- list_setting
626 *
627 * A set of private flags is there too:
628 * -F -- purge the cache directories and rebuild them
629 * -e -- use the (faster) archive update approach (used by
630 * reboot)
631 */
632 static void
633 parse_args_internal(int argc, char *argv[])
634 {
635 int c, error;
636 extern char *optarg;
637 extern int optind, opterr;
638 #if defined(_OBP)
639 const char *optstring = "a:d:fi:m:no:veFCR:p:P:XZ";
640 #else
641 const char *optstring = "a:d:fi:m:no:veFCMR:p:P:XZ";
642 #endif
643
644 /* Suppress error message from getopt */
741 optarg, strerror(errno));
742 break;
743 }
744 bam_alt_root = 1;
745 bam_root = rootbuf;
746 bam_rootlen = strlen(rootbuf);
747 break;
748 case 'p':
749 bam_alt_platform = 1;
750 bam_platform = optarg;
751 if ((strcmp(bam_platform, "i86pc") != 0) &&
752 (strcmp(bam_platform, "sun4u") != 0) &&
753 (strcmp(bam_platform, "sun4v") != 0)) {
754 error = 1;
755 bam_error(_("invalid platform %s - must be "
756 "one of sun4u, sun4v or i86pc\n"),
757 bam_platform);
758 }
759 break;
760 case 'X':
761 /* obsolete */
762 break;
763 case 'Z':
764 bam_zfs = 1;
765 break;
766 case 'e':
767 bam_extend = 1;
768 break;
769 case '?':
770 error = 1;
771 bam_error(_("invalid option or missing option "
772 "argument: -%c\n"), optopt);
773 break;
774 default :
775 error = 1;
776 bam_error(_("invalid option or missing option "
777 "argument: -%c\n"), c);
778 break;
779 }
780 }
781
847 usage();
848 return (BAM_ERROR);
849 } else if (bam_argc > 1 || bam_argv[1] != NULL) {
850 bam_error(_("invalid trailing arguments\n"));
851 usage();
852 return (BAM_ERROR);
853 }
854 } else if (strcmp(subcmd, "update_all") == 0) {
855 /*
856 * The only option we accept for the "update_all"
857 * subcmd is "fastboot".
858 */
859 if (bam_argc > 1 || (bam_argc == 1 &&
860 strcmp(bam_argv[0], "fastboot") != 0)) {
861 bam_error(_("invalid trailing arguments\n"));
862 usage();
863 return (BAM_ERROR);
864 }
865 if (bam_argc == 1)
866 sync_menu = 0;
867 } else if (strcmp(subcmd, "list_setting") != 0 &&
868 (bam_argc || bam_argv)) {
869 /*
870 * Of the remaining subcommands, only "list_setting" takes
871 * trailing arguments.
872 */
873 bam_error(_("invalid trailing arguments\n"));
874 usage();
875 return (BAM_ERROR);
876 }
877
878 if (bam_root == NULL) {
879 bam_root = rootbuf;
880 bam_rootlen = 1;
881 }
882
883 /* verify that subcmd is valid */
884 for (i = 0; table[i].subcmd != NULL; i++) {
885 if (strcmp(table[i].subcmd, subcmd) == 0)
886 break;
887 }
888
889 if (table[i].subcmd == NULL) {
890 bam_error(_("invalid sub-command specified: %s\n"), subcmd);
891 return (BAM_ERROR);
1410 */
1411 if (strcmp(subcmd, "list_entry") == 0)
1412 bam_print(_("the location for the active GRUB menu is: %s\n"),
1413 menu_path);
1414
1415 if ((menu = menu_read(menu_path)) == NULL) {
1416 bam_error(_("cannot find GRUB menu file: %s\n"), menu_path);
1417 free(special);
1418
1419 return (BAM_ERROR);
1420 }
1421
1422 /*
1423 * We already checked the following case in
1424 * check_subcmd_and_suboptions() above. Complete the
1425 * final step now.
1426 */
1427 if (strcmp(subcmd, "set_option") == 0) {
1428 assert(largc == 1 && largv[0] && largv[1] == NULL);
1429 opt = largv[0];
1430 } else if (strcmp(subcmd, "list_setting") != 0) {
1431 assert(largc == 0 && largv == NULL);
1432 }
1433
1434 ret = get_boot_cap(bam_root);
1435 if (ret != BAM_SUCCESS) {
1436 BAM_DPRINTF(("%s: Failed to get boot capability\n", fcn));
1437 goto out;
1438 }
1439
1440 /*
1441 * Once the sub-cmd handler has run
1442 * only the line field is guaranteed to have valid values
1443 */
1444 if (strcmp(subcmd, "update_entry") == 0) {
1445 ret = f(menu, menu_root, osdev);
1446 } else if (strcmp(subcmd, "upgrade") == 0) {
1447 ret = f(menu, bam_root, menu_root);
1448 } else if (strcmp(subcmd, "list_entry") == 0) {
1449 ret = f(menu, menu_path, opt);
1450 } else if (strcmp(subcmd, "list_setting") == 0) {
1451 ret = f(menu, ((largc > 0) ? largv[0] : ""),
1452 ((largc > 1) ? largv[1] : ""));
1453 } else
1454 ret = f(menu, NULL, opt);
1455
1456 if (ret == BAM_WRITE) {
1457 BAM_DPRINTF(("%s: writing menu to clean-menu-root: <%s>\n",
1458 fcn, clean_menu_root));
1459 ret = menu_write(clean_menu_root, menu);
1460 }
1461
1462 out:
1463 INJECT_ERROR1("POOL_SET", pool = "/pooldata");
1464 assert((is_zfs(menu_root)) ^ (pool == NULL));
1465 if (pool) {
1466 (void) umount_top_dataset(pool, zmnted, zmntpt);
1467 free(special);
1468 }
1469 menu_free(menu);
1470 return (ret);
1471 }
1472
4553 } else if (strncmp(arg, DIRECT_BOOT_FAILSAFE_32,
4554 sizeof (DIRECT_BOOT_FAILSAFE_32) - 1) == 0) {
4555 BAM_DPRINTF(("%s: setting DBOOT|DBOOT_FAILSAFE|DBOOT_32 "
4556 "flag: %s\n", fcn, arg));
4557 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_FAILSAFE
4558 | BAM_ENTRY_32BIT;
4559 } else if (strncmp(arg, DIRECT_BOOT_FAILSAFE_64,
4560 sizeof (DIRECT_BOOT_FAILSAFE_64) - 1) == 0) {
4561 BAM_DPRINTF(("%s: setting DBOOT|DBOOT_FAILSAFE|DBOOT_64 "
4562 "flag: %s\n", fcn, arg));
4563 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_FAILSAFE
4564 | BAM_ENTRY_64BIT;
4565 } else if (strncmp(arg, MULTI_BOOT, sizeof (MULTI_BOOT) - 1) == 0) {
4566 BAM_DPRINTF(("%s: setting MULTIBOOT flag: %s\n", fcn, arg));
4567 entry->flags |= BAM_ENTRY_MULTIBOOT;
4568 } else if (strncmp(arg, MULTI_BOOT_FAILSAFE,
4569 sizeof (MULTI_BOOT_FAILSAFE) - 1) == 0) {
4570 BAM_DPRINTF(("%s: setting MULTIBOOT|MULTIBOOT_FAILSAFE "
4571 "flag: %s\n", fcn, arg));
4572 entry->flags |= BAM_ENTRY_MULTIBOOT | BAM_ENTRY_FAILSAFE;
4573 } else if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))) {
4574 BAM_DPRINTF(("%s: is HAND kernel flag: %s\n", fcn, arg));
4575 return (BAM_ERROR);
4576 } else if (strncmp(arg, KERNEL_PREFIX, strlen(KERNEL_PREFIX)) == 0 &&
4577 strstr(arg, UNIX_SPACE)) {
4578 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_32BIT;
4579 } else if (strncmp(arg, KERNEL_PREFIX, strlen(KERNEL_PREFIX)) == 0 &&
4580 strstr(arg, AMD_UNIX_SPACE)) {
4581 entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_64BIT;
4582 } else {
4583 BAM_DPRINTF(("%s: is UNKNOWN kernel entry: %s\n", fcn, arg));
4584 bam_error(_("kernel command on line %d not recognized.\n"),
4585 linenum);
4586 return (BAM_ERROR);
4587 }
4588
4589 return (BAM_SUCCESS);
4590 }
4591
4592 static error_t
4593 module_parser(entry_t *entry, char *cmd, char *arg, int linenum)
4594 {
4595 const char *fcn = "module_parser()";
4596
4597 assert(entry);
4598 assert(cmd);
4599 assert(arg);
4600
4601 if (strcmp(cmd, menu_cmds[MODULE_CMD]) != 0 &&
4602 strcmp(cmd, menu_cmds[MODULE_DOLLAR_CMD]) != 0) {
4603 BAM_DPRINTF(("%s: not module cmd: %s\n", fcn, cmd));
4604 return (BAM_ERROR);
4605 }
4606
4607 if (strcmp(arg, DIRECT_BOOT_ARCHIVE) == 0 ||
4608 strcmp(arg, DIRECT_BOOT_ARCHIVE_32) == 0 ||
4609 strcmp(arg, DIRECT_BOOT_ARCHIVE_64) == 0 ||
4610 strcmp(arg, MULTIBOOT_ARCHIVE) == 0 ||
4611 strcmp(arg, FAILSAFE_ARCHIVE) == 0 ||
4612 strcmp(arg, FAILSAFE_ARCHIVE_32) == 0 ||
4613 strcmp(arg, FAILSAFE_ARCHIVE_64) == 0) {
4614 BAM_DPRINTF(("%s: bootadm or LU module cmd: %s\n", fcn, arg));
4615 return (BAM_SUCCESS);
4616 } else if (!(entry->flags & BAM_ENTRY_BOOTADM) &&
4617 !(entry->flags & BAM_ENTRY_LU)) {
4618 /* don't emit warning for hand entries */
4619 BAM_DPRINTF(("%s: is HAND module: %s\n", fcn, arg));
4620 return (BAM_ERROR);
4621 } else {
4622 BAM_DPRINTF(("%s: is UNKNOWN module: %s\n", fcn, arg));
4623 bam_error(_("module command on line %d not recognized.\n"),
4624 linenum);
4625 return (BAM_ERROR);
4626 }
4627 }
4628
4629 /*
4630 * A line in menu.lst looks like
4631 * [ ]*<cmd>[ \t=]*<arg>*
4632 */
4633 static void
8172 if (lp == NULL || lp->next == NULL) {
8173 continue;
8174 }
8175
8176 if (kernel &&
8177 (!check_cmd(lp->cmd, KERNEL_CMD, lp->arg, kernel))) {
8178 if (!(ent->flags & BAM_ENTRY_FAILSAFE) ||
8179 !(ent->flags & BAM_ENTRY_DBOOT) ||
8180 strcmp(kernel, DIRECT_BOOT_FAILSAFE_LINE) != 0)
8181 continue;
8182
8183 ent->flags |= BAM_ENTRY_UPGFSKERNEL;
8184
8185 }
8186 BAM_DPRINTF(("%s: kernel match: %s, %s\n", fcn,
8187 kernel, lp->arg));
8188
8189 /*
8190 * Check for matching module entry (failsafe or normal).
8191 * If it fails to match, we go around the loop again.
8192 */
8193 lp = lp->next; /* advance to module line */
8194 if (check_cmd(lp->cmd, MODULE_CMD, lp->arg, module)) {
8195 /* match found */
8196 BAM_DPRINTF(("%s: module match: %s, %s\n", fcn,
8197 module, lp->arg));
8198 break;
8199 }
8200
8201 if (strcmp(module, FAILSAFE_ARCHIVE) == 0 &&
8202 (strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_32) == 0 ||
8203 strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_64) == 0)) {
8204 ent->flags |= BAM_ENTRY_UPGFSMODULE;
8205 break;
8206 }
8207
8208 }
8209
8210 if (ent && entry_num) {
8211 *entry_num = i;
8212 }
8213
8214 if (ent) {
8503 grubroot = get_grubroot(osroot, osdev, menu_root);
8504 INJECT_ERROR1("GET_GRUBROOT_FAIL", grubroot = NULL);
8505 if (grubroot) {
8506 BAM_DPRINTF(("%s: get_grubroot success. osroot=%s, osdev=%s, "
8507 "menu_root=%s\n", fcn, osroot, osdev, menu_root));
8508 } else {
8509 BAM_DPRINTF(("%s: get_grubroot failed. osroot=%s, osdev=%s, "
8510 "menu_root=%s\n", fcn, osroot, osdev, menu_root));
8511 }
8512
8513 /* add the entry for normal Solaris */
8514 INJECT_ERROR1("UPDATE_ENTRY_MULTIBOOT",
8515 bam_direct = BAM_DIRECT_MULTIBOOT);
8516 if (bam_direct == BAM_DIRECT_DBOOT) {
8517 entry = update_boot_entry(mp, title, grubsign, grubroot,
8518 (bam_zfs ? DIRECT_BOOT_KERNEL_ZFS : DIRECT_BOOT_KERNEL),
8519 NULL, DIRECT_BOOT_ARCHIVE,
8520 root_optional(osroot, menu_root));
8521 BAM_DPRINTF(("%s: updated boot entry bam_zfs=%d, "
8522 "grubsign = %s\n", fcn, bam_zfs, grubsign));
8523 } else {
8524 entry = update_boot_entry(mp, title, grubsign, grubroot,
8525 MULTI_BOOT, NULL, MULTIBOOT_ARCHIVE,
8526 root_optional(osroot, menu_root));
8527 BAM_DPRINTF(("%s: updated MULTIBOOT entry grubsign = %s\n",
8528 fcn, grubsign));
8529 }
8530
8531 /*
8532 * Add the entry for failsafe archive. On a bfu'd system, the
8533 * failsafe may be different than the installed kernel.
8534 */
8535 (void) snprintf(failsafe, sizeof (failsafe), "%s%s",
8536 osroot, FAILSAFE_ARCHIVE_32);
8537 (void) snprintf(failsafe_64, sizeof (failsafe_64), "%s%s",
8538 osroot, FAILSAFE_ARCHIVE_64);
8539
8540 /*
8541 * Check if at least one of the two archives exists
8542 * Using $ISADIR as the default line, we have an entry which works
8543 * for both the cases.
8544 */
8545
8546 if (stat(failsafe, &sbuf) == 0 || stat(failsafe_64, &sbuf) == 0) {
|