From c7c0ceafd167e558cd8cb8195b8bd63cbc817b27 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Thu, 23 Jul 2015 18:46:09 +0300 Subject: [PATCH] =?utf8?q?6085=20export=20libbe=20installboot=20function?= =?utf8?q?=206086=20add=20install=20bootblock=20option=20for=20bootadm=20R?= =?utf8?q?eviewed=20by:=20Igor=20Kozhukhov=20=20Revi?= =?utf8?q?ewed=20by:=20Adam=20=C5=A0tevko=20=20Revi?= =?utf8?q?ewed=20by:=20Josef=20Sipek=20=20Approved?= =?utf8?q?=20by:=20Robert=20Mustacchi=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- usr/src/cmd/boot/bootadm/bootadm.c | 297 ++++++++++++++++++++++++++++++++- usr/src/lib/libbe/common/be_activate.c | 153 ++++++++++++++--- usr/src/lib/libbe/common/libbe.h | 13 ++ usr/src/lib/libbe/common/mapfile-vers | 1 + usr/src/man/man1m/bootadm.1m | 114 +++++++++++-- 5 files changed, 544 insertions(+), 34 deletions(-) diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c index dfafc5f87f..2d3a3ff8d2 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.c +++ b/usr/src/cmd/boot/bootadm/bootadm.c @@ -83,6 +83,7 @@ #include #include #include +#include #include "message.h" #include "bootadm.h" @@ -96,7 +97,8 @@ /* Primary subcmds */ typedef enum { BAM_MENU = 3, - BAM_ARCHIVE + BAM_ARCHIVE, + BAM_INSTALL } subcmd_t; typedef enum { @@ -233,12 +235,14 @@ static int bam_purge = 0; static char *bam_subcmd; static char *bam_opt; static char **bam_argv; +static char *bam_pool; static int bam_argc; static int bam_check; static int bam_saved_check; static int bam_smf_check; static int bam_lock_fd = -1; static int bam_zfs; +static int bam_mbr; static char rootbuf[PATH_MAX] = "/"; static int bam_update_all; static int bam_alt_platform; @@ -249,6 +253,7 @@ static char *bam_home_env = NULL; static void parse_args_internal(int, char *[]); static void parse_args(int, char *argv[]); static error_t bam_menu(char *, char *, int, char *[]); +static error_t bam_install(char *, char *); static error_t bam_archive(char *, char *); static void bam_lock(void); @@ -269,6 +274,7 @@ static error_t delete_all_entries(menu_t *, char *, char *); static error_t update_entry(menu_t *mp, char *menu_root, char *opt); static error_t update_temp(menu_t *mp, char *dummy, char *opt); +static error_t install_bootloader(void); static error_t update_archive(char *, char *); static error_t list_archive(char *, char *); static error_t update_all(char *, char *); @@ -318,6 +324,12 @@ static subcmd_defn_t arch_subcmds[] = { NULL, 0, NULL, 0 /* must be last */ }; +/* Install related sub commands */ +static subcmd_defn_t inst_subcmds[] = { + "install_bootloader", OPT_ABSENT, install_bootloader, 0, /* PUB */ + NULL, 0, NULL, 0 /* must be last */ +}; + enum dircache_copy_opt { FILE32 = 0, FILE64, @@ -446,6 +458,13 @@ usage(void) "\t%s update-archive [-vn] [-R altroot [-p platform]]\n", prog); (void) fprintf(stderr, "\t%s list-archive [-R altroot [-p platform]]\n", prog); +#if defined(_OPB) + (void) fprintf(stderr, + "\t%s install-bootloader [-fv] [-R altroot] [-P pool]\n", prog); +#else + (void) fprintf(stderr, + "\t%s install-bootloader [-Mfv] [-R altroot] [-P pool]\n", prog); +#endif #if !defined(_OPB) /* x86 only */ (void) fprintf(stderr, "\t%s set-menu [-R altroot] key=value\n", prog); @@ -540,6 +559,9 @@ main(int argc, char *argv[]) case BAM_ARCHIVE: ret = bam_archive(bam_subcmd, bam_opt); break; + case BAM_INSTALL: + ret = bam_install(bam_subcmd, bam_opt); + break; default: usage(); bam_exit(1); @@ -559,6 +581,7 @@ main(int argc, char *argv[]) * set-menu -- -m set_option * list-menu -- -m list_entry * update-menu -- -m update_entry + * install-bootloader -- -i install_bootloader */ static struct cmd_map { char *bam_cmdname; @@ -570,6 +593,7 @@ static struct cmd_map { { "set-menu", BAM_MENU, "set_option"}, { "list-menu", BAM_MENU, "list_entry"}, { "update-menu", BAM_MENU, "update_entry"}, + { "install-bootloader", BAM_INSTALL, "install_bootloader"}, { NULL, 0, NULL} }; @@ -611,6 +635,7 @@ parse_args(int argc, char *argv[]) * -a update -- update-archive * -a list -- list-archive * -a update-all -- (reboot to sync all mnted OS archive) + * -i install_bootloader -- install-bootloader * -m update_entry -- update-menu * -m list_entry -- list-menu * -m update_temp -- (reboot -- [boot-args]) @@ -630,12 +655,17 @@ parse_args_internal(int argc, char *argv[]) int c, error; extern char *optarg; extern int optind, opterr; +#if defined(_OPB) + const char *optstring = "a:d:fi:m:no:veFCR:p:P:XZ"; +#else + const char *optstring = "a:d:fi:m:no:veFCMR:p:P:XZ"; +#endif /* Suppress error message from getopt */ opterr = 0; error = 0; - while ((c = getopt(argc, argv, "a:d:fm:no:veFCR:p:XZ")) != -1) { + while ((c = getopt(argc, argv, optstring)) != -1) { switch (c) { case 'a': if (bam_cmd) { @@ -658,6 +688,14 @@ parse_args_internal(int argc, char *argv[]) case 'F': bam_purge = 1; break; + case 'i': + if (bam_cmd) { + error = 1; + bam_error(MULT_CMDS, c); + } + bam_cmd = BAM_INSTALL; + bam_subcmd = optarg; + break; case 'm': if (bam_cmd) { error = 1; @@ -666,6 +704,11 @@ parse_args_internal(int argc, char *argv[]) bam_cmd = BAM_MENU; bam_subcmd = optarg; break; +#if !defined(_OPB) + case 'M': + bam_mbr = 1; + break; +#endif case 'n': bam_check = 1; /* @@ -693,6 +736,13 @@ parse_args_internal(int argc, char *argv[]) case 'C': bam_smf_check = 1; break; + case 'P': + if (bam_pool != NULL) { + error = 1; + bam_error(DUP_OPT, c); + } + bam_pool = optarg; + break; case 'R': if (bam_root) { error = 1; @@ -772,6 +822,14 @@ parse_args_internal(int argc, char *argv[]) } /* + * mbr and pool are options for install_bootloader + */ + if (bam_cmd != BAM_INSTALL && (bam_mbr || bam_pool != NULL)) { + usage(); + bam_exit(0); + } + + /* * -n implies verbose mode */ if (bam_check) @@ -981,6 +1039,241 @@ list_setting(menu_t *mp, char *which, char *setting) } static error_t +install_bootloader(void) +{ + nvlist_t *nvl; + uint16_t flags = 0; + int found = 0; + struct extmnttab mnt; + struct stat statbuf = {0}; + be_node_list_t *be_nodes, *node; + FILE *fp; + char *root_ds = NULL; + int ret; + + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { + bam_error(_("out of memory\n")); + return (BAM_ERROR); + } + + /* + * if bam_alt_root is set, the stage files are used from alt root. + * if pool is set, the target devices are pool devices, stage files + * are read from pool bootfs unless alt root is set. + * + * use arguments as targets, stage files are from alt or current root + * if no arguments and no pool, install on current boot pool. + */ + + if (bam_alt_root) { + if (stat(bam_root, &statbuf) != 0) { + bam_error(STAT_FAIL, bam_root, strerror(errno)); + ret = BAM_ERROR; + goto done; + } + if ((fp = fopen(MNTTAB, "r")) == NULL) { + bam_error(OPEN_FAIL, MNTTAB, strerror(errno)); + ret = BAM_ERROR; + goto done; + } + resetmnttab(fp); + while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) { + if (mnt.mnt_major == major(statbuf.st_dev) && + mnt.mnt_minor == minor(statbuf.st_dev)) { + found = 1; + root_ds = strdup(mnt.mnt_special); + break; + } + } + (void) fclose(fp); + + if (found == 0) { + bam_error(NOT_IN_MNTTAB, bam_root); + ret = BAM_ERROR; + goto done; + } + if (root_ds == NULL) { + bam_error(_("out of memory\n")); + ret = BAM_ERROR; + goto done; + } + + if (be_list(NULL, &be_nodes) != BE_SUCCESS) { + bam_error(_("No BE's found\n")); + ret = BAM_ERROR; + goto done; + } + for (node = be_nodes; node != NULL; node = node->be_next_node) + if (strcmp(root_ds, node->be_root_ds) == 0) + break; + + if (node == NULL) + bam_error(_("BE (%s) does not exist\n"), root_ds); + + free(root_ds); + root_ds = NULL; + if (node == NULL) { + be_free_list(be_nodes); + ret = BAM_ERROR; + goto done; + } + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_NAME, + node->be_node_name); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_ROOT, + node->be_root_ds); + be_free_list(be_nodes); + if (ret) { + ret = BAM_ERROR; + goto done; + } + } + + if (bam_force) + flags |= BE_INSTALLBOOT_FLAG_FORCE; + if (bam_mbr) + flags |= BE_INSTALLBOOT_FLAG_MBR; + if (bam_verbose) + flags |= BE_INSTALLBOOT_FLAG_VERBOSE; + + if (nvlist_add_uint16(nvl, BE_ATTR_INSTALL_FLAGS, flags) != 0) { + bam_error(_("out of memory\n")); + goto done; + } + + /* + * if altroot was set, we got be name and be root, only need + * to set pool name as target. + * if no altroot, need to find be name and root from pool. + */ + if (bam_pool != NULL) { + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_POOL, bam_pool); + if (ret) { + ret = BAM_ERROR; + goto done; + } + if (found) { + ret = be_installboot(nvl); + if (ret) + ret = BAM_ERROR; + goto done; + } + } + + if (be_list(NULL, &be_nodes) != BE_SUCCESS) { + bam_error(_("No BE's found\n")); + ret = BAM_ERROR; + goto done; + } + + if (bam_pool != NULL) { + /* + * find active be_node in bam_pool + */ + for (node = be_nodes; node != NULL; node = node->be_next_node) { + if (strcmp(bam_pool, node->be_rpool) != 0) + continue; + if (node->be_active_on_boot) + break; + } + if (node == NULL) { + bam_error(_("No active BE in %s\n"), bam_pool); + be_free_list(be_nodes); + ret = BAM_ERROR; + goto done; + } + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_NAME, + node->be_node_name); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_ROOT, + node->be_root_ds); + be_free_list(be_nodes); + if (ret) { + ret = BAM_ERROR; + goto done; + } + ret = be_installboot(nvl); + if (ret) + ret = BAM_ERROR; + goto done; + } + + /* + * get dataset for "/" and fill up the args. + */ + if ((fp = fopen(MNTTAB, "r")) == NULL) { + bam_error(OPEN_FAIL, MNTTAB, strerror(errno)); + ret = BAM_ERROR; + be_free_list(be_nodes); + goto done; + } + resetmnttab(fp); + found = 0; + while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) { + if (strcmp(mnt.mnt_mountp, "/") == 0) { + found = 1; + root_ds = strdup(mnt.mnt_special); + break; + } + } + (void) fclose(fp); + + if (found == 0) { + bam_error(NOT_IN_MNTTAB, "/"); + ret = BAM_ERROR; + be_free_list(be_nodes); + goto done; + } + if (root_ds == NULL) { + bam_error(_("out of memory\n")); + ret = BAM_ERROR; + be_free_list(be_nodes); + goto done; + } + + for (node = be_nodes; node != NULL; node = node->be_next_node) { + if (strcmp(root_ds, node->be_root_ds) == 0) + break; + } + + if (node == NULL) { + bam_error(_("No such BE: %s\n"), root_ds); + free(root_ds); + be_free_list(be_nodes); + ret = BAM_ERROR; + goto done; + } + free(root_ds); + + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_NAME, node->be_node_name); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_ROOT, node->be_root_ds); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_POOL, node->be_rpool); + be_free_list(be_nodes); + + if (ret) + ret = BAM_ERROR; + else + ret = be_installboot(nvl) ? BAM_ERROR : 0; +done: + nvlist_free(nvl); + + return (ret); +} + +static error_t +bam_install(char *subcmd, char *opt) +{ + error_t (*f)(void); + + /* + * Check arguments + */ + if (check_subcmd_and_options(subcmd, opt, inst_subcmds, &f) == + BAM_ERROR) + return (BAM_ERROR); + + return (f()); +} + +static error_t bam_menu(char *subcmd, char *opt, int largc, char *largv[]) { error_t ret; diff --git a/usr/src/lib/libbe/common/be_activate.c b/usr/src/lib/libbe/common/be_activate.c index 985a585094..6eda8eebba 100644 --- a/usr/src/lib/libbe/common/be_activate.c +++ b/usr/src/lib/libbe/common/be_activate.c @@ -55,8 +55,8 @@ static int set_bootfs(char *boot_rpool, char *be_root_ds); static int set_canmount(be_node_list_t *, char *); static boolean_t be_do_install_mbr(char *, nvlist_t *); static int be_do_installboot_helper(zpool_handle_t *, nvlist_t *, char *, - char *); -static int be_do_installboot(be_transaction_data_t *); + char *, uint16_t); +static int be_do_installboot(be_transaction_data_t *, uint16_t); static int be_get_grub_vers(be_transaction_data_t *, char **, char **); static int get_ver_from_capfile(char *, char **); static int be_promote_zone_ds(char *, char *); @@ -119,6 +119,82 @@ be_activate(nvlist_t *be_attrs) return (ret); } +/* + * Function: be_installboot + * Description: Calls be_do_installboot to install/update bootloader on + * pool passed in through be_attrs. The primary consumer is + * bootadm command to avoid duplication of the code. + * Parameters: + * be_attrs - pointer to nvlist_t of attributes being passed in. + * The following attribute values are used: + * + * BE_ATTR_ORIG_BE_NAME *required + * BE_ATTR_ORIG_BE_POOL *required + * BE_ATTR_ORIG_BE_ROOT *required + * BE_ATTR_INSTALL_FLAGS optional + * + * Return: + * BE_SUCCESS - Success + * be_errno_t - Failure + * Scope: + * Public + */ +int +be_installboot(nvlist_t *be_attrs) +{ + int ret = BE_SUCCESS; + uint16_t flags = 0; + uint16_t verbose; + be_transaction_data_t bt = { 0 }; + + /* Get flags */ + if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, + BE_ATTR_INSTALL_FLAGS, DATA_TYPE_UINT16, &flags, NULL) != 0) { + be_print_err(gettext("be_installboot: failed to lookup " + "BE_ATTR_INSTALL_FLAGS attribute\n")); + return (BE_ERR_INVAL); + } + + /* Set verbose early, so we get all messages */ + verbose = flags & BE_INSTALLBOOT_FLAG_VERBOSE; + if (verbose == BE_INSTALLBOOT_FLAG_VERBOSE) + libbe_print_errors(B_TRUE); + + ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, + &bt.obe_name); + if (ret != 0) { + be_print_err(gettext("be_installboot: failed to " + "lookup BE_ATTR_ORIG_BE_NAME attribute\n")); + return (BE_ERR_INVAL); + } + + ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_POOL, + &bt.obe_zpool); + if (ret != 0) { + be_print_err(gettext("be_installboot: failed to " + "lookup BE_ATTR_ORIG_BE_POOL attribute\n")); + return (BE_ERR_INVAL); + } + + ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_ROOT, + &bt.obe_root_ds); + if (ret != 0) { + be_print_err(gettext("be_installboot: failed to " + "lookup BE_ATTR_ORIG_BE_ROOT attribute\n")); + return (BE_ERR_INVAL); + } + + /* Initialize libzfs handle */ + if (!be_zfs_init()) + return (BE_ERR_INIT); + + ret = be_do_installboot(&bt, flags); + + be_zfs_fini(); + + return (ret); +} + /* ******************************************************************** */ /* Semi Private Functions */ /* ******************************************************************** */ @@ -175,7 +251,8 @@ _be_activate(char *be_name) cb.obe_root_ds = strdup(root_ds); if (getzoneid() == GLOBAL_ZONEID) { - if ((ret = be_do_installboot(&cb)) != BE_SUCCESS) + ret = be_do_installboot(&cb, BE_INSTALLBOOT_FLAG_NULL); + if (ret != BE_SUCCESS) return (ret); if (!be_has_menu_entry(root_ds, cb.obe_zpool, &entry)) { @@ -794,14 +871,16 @@ be_do_install_mbr(char *diskname, nvlist_t *child) static int be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1, - char *stage2) + char *stage2, uint16_t flags) { char install_cmd[MAXPATHLEN]; char be_run_cmd_errbuf[BUFSIZ]; + char be_run_cmd_outbuf[BUFSIZ]; char diskname[MAXPATHLEN]; char *vname; char *path, *dsk_ptr; char *flag = ""; + int ret; if (nvlist_lookup_string(child, ZPOOL_CONFIG_PATH, &path) != 0) { be_print_err(gettext("be_do_installboot: " @@ -836,31 +915,60 @@ be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1, } if (be_is_isa("i386")) { - if (be_do_install_mbr(diskname, child)) - flag = "-m -f"; + uint16_t force = flags & BE_INSTALLBOOT_FLAG_FORCE; + uint16_t mbr = flags & BE_INSTALLBOOT_FLAG_MBR; + + if (force == BE_INSTALLBOOT_FLAG_FORCE) { + if (mbr == BE_INSTALLBOOT_FLAG_MBR || + be_do_install_mbr(diskname, child)) + flag = "-F -m -f"; + else + flag = "-F"; + } else { + if (mbr == BE_INSTALLBOOT_FLAG_MBR || + be_do_install_mbr(diskname, child)) + flag = "-m -f"; + } + (void) snprintf(install_cmd, sizeof (install_cmd), "%s %s %s %s %s", BE_INSTALL_GRUB, flag, stage1, stage2, diskname); } else { - flag = "-F zfs"; + if ((flags & BE_INSTALLBOOT_FLAG_FORCE) == + BE_INSTALLBOOT_FLAG_FORCE) + flag = "-f -F zfs"; + else + flag = "-F zfs"; + (void) snprintf(install_cmd, sizeof (install_cmd), "%s %s %s %s", BE_INSTALL_BOOT, flag, stage2, diskname); } - if (be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ, NULL, 0) - != BE_SUCCESS) { + *be_run_cmd_outbuf = '\0'; + *be_run_cmd_errbuf = '\0'; + + ret = be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ, + be_run_cmd_outbuf, BUFSIZ); + + if (ret != BE_SUCCESS) { be_print_err(gettext("be_do_installboot: install " "failed for device %s.\n"), vname); - /* Assume localized cmd err output. */ - be_print_err(gettext(" Command: \"%s\"\n"), - install_cmd); + ret = BE_ERR_BOOTFILE_INST; + } + + be_print_err(gettext(" Command: \"%s\"\n"), install_cmd); + if (be_run_cmd_outbuf[0] != 0) { + be_print_err(gettext(" Output:\n")); + be_print_err("%s", be_run_cmd_outbuf); + } + + if (be_run_cmd_errbuf[0] != 0) { + be_print_err(gettext(" Errors:\n")); be_print_err("%s", be_run_cmd_errbuf); - free(vname); - return (BE_ERR_BOOTFILE_INST); } free(vname); - return (BE_SUCCESS); + return (ret); } /* @@ -1069,6 +1177,7 @@ be_is_install_needed(be_transaction_data_t *bt, boolean_t *update) * * Parameters: * bt - The transaction data for the BE we're activating. + * flags - flags for bootloader install * Return: * BE_SUCCESS - Success * be_errno_t - Failure @@ -1077,7 +1186,7 @@ be_is_install_needed(be_transaction_data_t *bt, boolean_t *update) * Private */ static int -be_do_installboot(be_transaction_data_t *bt) +be_do_installboot(be_transaction_data_t *bt, uint16_t flags) { zpool_handle_t *zphp = NULL; zfs_handle_t *zhp = NULL; @@ -1096,9 +1205,11 @@ be_do_installboot(be_transaction_data_t *bt) * version implementation like grub. Embedded versioning is * checked by actual installer. */ - ret = be_is_install_needed(bt, &update); - if (ret != BE_SUCCESS || update == B_FALSE) - return (ret); + if ((flags & BE_INSTALLBOOT_FLAG_FORCE) != BE_INSTALLBOOT_FLAG_FORCE) { + ret = be_is_install_needed(bt, &update); + if (ret != BE_SUCCESS || update == B_FALSE) + return (ret); + } if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) { @@ -1205,7 +1316,7 @@ be_do_installboot(be_transaction_data_t *bt) for (i = 0; i < nchildren; i++) { ret = be_do_installboot_helper(zphp, nvchild[i], - stage1, stage2); + stage1, stage2, flags); if (ret != BE_SUCCESS) goto done; } @@ -1213,7 +1324,7 @@ be_do_installboot(be_transaction_data_t *bt) free(vname); ret = be_do_installboot_helper(zphp, child[c], stage1, - stage2); + stage2, flags); if (ret != BE_SUCCESS) goto done; } diff --git a/usr/src/lib/libbe/common/libbe.h b/usr/src/lib/libbe/common/libbe.h index c5662893a2..994bc881ac 100644 --- a/usr/src/lib/libbe/common/libbe.h +++ b/usr/src/lib/libbe/common/libbe.h @@ -42,6 +42,7 @@ extern "C" { #define BE_ATTR_ORIG_BE_NAME "orig_be_name" #define BE_ATTR_ORIG_BE_POOL "orig_be_pool" +#define BE_ATTR_ORIG_BE_ROOT "orig_be_root" #define BE_ATTR_SNAP_NAME "snap_name" #define BE_ATTR_NEW_BE_NAME "new_be_name" @@ -59,6 +60,7 @@ extern "C" { #define BE_ATTR_MOUNT_FLAGS "mount_flags" #define BE_ATTR_UNMOUNT_FLAGS "unmount_flags" #define BE_ATTR_DESTROY_FLAGS "destroy_flags" +#define BE_ATTR_INSTALL_FLAGS "install_flags" #define BE_ATTR_ROOT_DS "root_ds" #define BE_ATTR_UUID_STR "uuid_str" @@ -205,6 +207,12 @@ typedef struct be_node_list { #define BE_DESTROY_FLAG_SNAPSHOTS 0x00000001 #define BE_DESTROY_FLAG_FORCE_UNMOUNT 0x00000002 +/* Flags for installboot */ +#define BE_INSTALLBOOT_FLAG_NULL 0x00000000 +#define BE_INSTALLBOOT_FLAG_MBR 0x00000001 +#define BE_INSTALLBOOT_FLAG_FORCE 0x00000002 +#define BE_INSTALLBOOT_FLAG_VERBOSE 0x00000004 + /* sort rules for be_sort() */ typedef enum { BE_SORT_UNSPECIFIED = -1, @@ -244,6 +252,11 @@ char *be_err_to_str(int); int be_sort(be_node_list_t **, int); /* + * Installboot support + */ +int be_installboot(nvlist_t *); + +/* * Library functions */ void libbe_print_errors(boolean_t); diff --git a/usr/src/lib/libbe/common/mapfile-vers b/usr/src/lib/libbe/common/mapfile-vers index 0e57583dab..0602bd7de3 100644 --- a/usr/src/lib/libbe/common/mapfile-vers +++ b/usr/src/lib/libbe/common/mapfile-vers @@ -49,6 +49,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { be_err_to_str; be_free_list; be_init; + be_installboot; be_list; be_mount; be_rename; diff --git a/usr/src/man/man1m/bootadm.1m b/usr/src/man/man1m/bootadm.1m index db51b33f58..a227e23232 100644 --- a/usr/src/man/man1m/bootadm.1m +++ b/usr/src/man/man1m/bootadm.1m @@ -3,7 +3,8 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH BOOTADM 1M "Apr 25, 2008" +.\" Copyright (c) 2015 Toomas Soome +.TH BOOTADM 1M "Jul 26, 2015" .SH NAME bootadm \- manage bootability of GRUB-enabled operating system .SH SYNOPSIS @@ -19,6 +20,11 @@ bootadm \- manage bootability of GRUB-enabled operating system .LP .nf +\fB/sbin/bootadm\fR install-bootloader [\fB-Mfv\fR] [\fB-R\fR \fIaltroot\fR] [\fB-P\fR \fIpool\fR] +.fi + +.LP +.nf x86 only .fi @@ -33,7 +39,6 @@ bootadm \- manage bootability of GRUB-enabled operating system .fi .SH DESCRIPTION -.sp .LP The \fBbootadm\fR command manages the boot archive and, with x86 boot environments, the GRUB (GRand Unified Bootloader) menu. The @@ -43,6 +48,18 @@ as a preventative measure or as part of a recovery procedure. The default boot entry in the GRUB menu. .sp .LP +The \fBinstall-bootloader\fR subcommand installs the system boot loader on a +ZFS pool. If ZFS pool was not specified with the \fB-P\fR option, then the boot +loader is installed on the ZFS pool that the system booted from. If the +system did not boot from a ZFS pool (for example, it booted an installer via PXE +or CD-ROM) then the \fB-P\fR option is required. +.sp +This subcommand can be used to install, update, and repair the boot loader on a +ZFS pool intended for booting. When disks in the ZFS pool used for booting the +system have been replaced, one should run \fBbootadm install-bootloader\fR to +ensure that all disks in that pool have the system boot loader installed. +.sp +.LP The \fBlist-menu\fR subcommand displays the location of the GRUB menu and the current GRUB menu entries. While the typical location of the GRUB menu is \fB/boot/grub/menu.lst\fR, depending on the install method used the active GRUB @@ -59,7 +76,6 @@ The \fBbootadm\fR command determines dynamically the options supported by the image to be managed, so that \fBbootadm\fR invoked on one platform can be used to manage diskless clients of a different platform type. .SH SUBCOMMANDS -.sp .LP The \fBbootadm\fR command has the following subcommands: .sp @@ -87,6 +103,40 @@ both SPARC and x86 platforms. .sp .ne 2 .na +\fB\fBinstall-bootloader\fR\fR +.ad +.sp .6 +.RS 4n +Applies platform specific method to install the system boot loader to the disks +that are part of the selected ZFS pool (either specified with \fB-P\fR or +the default). +.sp +On SPARC, the boot loader is installed in the boot area of the disk partition +used by the ZFS pool. +.sp +On x86, disks are formatted using either \fBMBR Partitioning\fR (Master Boot +Record) or using \fBGPT Partitioning\fR (GUID Partition Tables). The first +sector on the disk that is used by the \fBBIOS\fR to find a boot loader +is referred to as the \fBMBR\fR (Master Boot Record) and is always used +regardless of the partition scheme. +.sp +On x86, disks in a ZFS pool may be a combination of either type of partitioning +scheme. If an entire disk was added to a ZFS pool (e.g. c0t0d0), then it was +formatted with \fBGPT\fR partitioning and the fact is recorded. The +\fBinstall-bootloader\fR subcommand will always update the system boot loader on +the disks. However, unless the entire disk was given a ZFS pool or the \fB-M\fR +option is specified, the \fBMBR\fR of the disk will not updated, as the system +cannot guarantee that the \fBMBR\fR belongs to it. If, for example, the system +was being dual booted, a different initial boot loader may be installed there. +.sp +When \fBGRUB\fR is being used as the system boot loader (currently on x86), to +reinstall the boot loader on some or all of the disks, the \fB-f\fR option must +be passed to the \fBinstall-bootloader\fR subcommand. +.RE + +.sp +.ne 2 +.na \fB\fBset-menu\fR\fR .ad .sp .6 @@ -109,17 +159,17 @@ title of each entry. Applies to x86 platforms only. .RE .SH OPTIONS -.sp .LP The \fBbootadm\fR command has the following options: .sp .ne 2 .na -\fB\fB-v\fR\fR +\fB\fB-f\fR\fR .ad .sp .6 .RS 4n -In an \fBupdate-archive\fR operation, stale files are displayed on stderr. +In an \fBinstall-bootloader\fR operation, override boot loader versioning +constraints. .RE .sp @@ -150,11 +200,55 @@ than the server. Platform must be one of \fBi86pc\fR, \fBsun4u\fR, or .sp .ne 2 .na +\fB\fB-v\fR\fR +.ad +.sp .6 +.RS 4n +In an \fBupdate-archive\fR operation, stale files are displayed on stderr. +.sp +In an \fBinstall-bootloader\fR operation, display any output from tasks +performed. +.RE + +.sp +.ne 2 +.na +\fB\fB-M\fR\fR +.ad +.sp .6 +.RS 4n +On x86 systems, in an \fBinstall-bootloader\fR operation, additionally installs +the system boot loader to the \fBMBR\fR (master boot record). For more +information, see the discussion of \fBinstall-bootloader\fR in the +\fBSUBCOMMANDS\fR section. +.sp +This option is not supported on non-x86 systems, and it is an error to specify +it. +.RE + +.sp +.ne 2 +.na +\fB-P\fR\ \fIpool\fR +.ad +.sp .6 +.RS 4n +In an \fBinstall-bootloader\fR operation, the boot loader is installed on +the disks in the ZFS pool \fIpool\fR. If the \fB-P\fR option is not specified, +then the boot loader is installed on the ZFS pool that the system booted from. +If the system did not boot from a ZFS pool then the \fB-P\fR option is required. +.RE + +.sp +.ne 2 +.na \fB\fB-R\fR\ \fIaltroot\fR\fR .ad .sp .6 .RS 4n -Operation is applied to an alternate root path. +Operation is applied to an alternate root path. In an \fBinstall-bootloader\fR +operation, the boot loader is still installed on the specified pool; however, +the boot loader itself will come from the alternate root. .LP Note - .sp @@ -307,7 +401,6 @@ mounted. To access the GRUB menu, mount the device and access the GRUB menu at \fB\fI\fR/boot/grub/menu.lst\fR. .SH EXIT STATUS -.sp .LP The following exit values are returned: .sp @@ -331,7 +424,6 @@ The command exited due to an error. .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -347,9 +439,9 @@ Interface Stability Committed .TE .SH SEE ALSO -.sp .LP -\fBboot\fR(1M), \fBinstallgrub\fR(1M), \fBattributes\fR(5) +\fBboot\fR(1M), \fBbeadm\fR(1M), \fBinstallgrub\fR(1M), \fBinstallboot\fR(1M), +\fBattributes\fR(5) .sp .LP Consult the GRUB home page, under: -- 2.11.4.GIT