Index: sys/boot/forth/menu.rc =================================================================== --- sys/boot/forth/menu.rc +++ sys/boot/forth/menu.rc @@ -65,6 +65,11 @@ set mainmenu_keycode[6]=111 set mainansi_caption[6]="Configure Boot ^[1mO^[mptions..." +set mainmenu_caption[7]="Select Boot [E]nvironment..." +set mainmenu_command[7]="3 goto_menu" +set mainmenu_keycode[7]=101 +set mainansi_caption[7]="Select Boot ^[1mE^[37mnvironment..." + \ \ BOOT OPTIONS MENU \ @@ -116,6 +121,53 @@ set optionsansi_caption[6]="^[1mV^[merbose..... ^[34;1mOff^[m" set optionstoggled_ansi[6]="^[1mV^[merbose..... ^[32;7mOn^[m" +\ +\ BOOT ENVIRONMENT MENU +\ + +set menuset_name3="bootenv" + +set bootenvmenu_caption[1]="Back to Main Menu [Backspace]" +set bootenvmenu_command[1]="1 goto_menu" +set bootenvmenu_keycode[1]=8 +set bootenvansi_caption[1]="Back to Main Menu ^[1m[Backspace]^[37m" + +set bootenvmenu_caption[2]="Choice: " +set bootenvmenu_command[2]="true" +set bootenvmenu_keycode[2]=27 +set bootenvansi_caption[2]="^[1m${bootenvmenu_caption[2]}^[37m" + +set bemenu_current="Choice: " +set beansi_current="^[1m${bemenu_current}^[37m" +: init_bootenv ( -- ) + s" set menu_caption[2]=${bemenu_current}${vfs.root.mountfrom}" evaluate + s" set ansi_caption[2]=${beansi_current}${vfs.root.mountfrom}" evaluate +; + +set bootenvmenu_init="init_bootenv" +unset bootenvmenu_caption[2] +unset bootenvansi_caption[2] + +: set_bootenv ( N -- N TRUE ) + dup s" set vfs.root.mountfrom=${bootenv_root[E]}" 38 +c! evaluate + s" set currdev=${vfs.root.mountfrom}:" evaluate + s" read-conf /boot/defaults/loader.conf" evaluate + s" read-conf /boot/loader.conf" evaluate + s" unload" evaluate + init_bootenv + menu-redraw + TRUE +; + +set bootenvmenu_caption[3]="[A]ctive: ${vfs.root.mountfrom}" +set bootenvansi_caption[3]="^[1mA^[37mctive: ${vfs.root.mountfrom}" +set bootenvmenu_keycode[3]=97 +set bootenvmenu_command[3]="set_bootenv" +set bootenv_root[3]="${zfs_be_active}" + +set bootenvmenu_options=4 +set bootenvmenu_optionstext="Boot Environments:" + \ Enable automatic booting (add ``autoboot_delay=N'' to loader.conf(5) to \ customize the timeout; default is 10-seconds) \ Index: sys/boot/i386/loader/main.c =================================================================== --- sys/boot/i386/loader/main.c +++ sys/boot/i386/loader/main.c @@ -69,6 +69,7 @@ static void isa_outb(int port, int value); void exit(int code); #ifdef LOADER_ZFS_SUPPORT +static void list_zfs_bootenv(char *currdev); static void i386_zfs_probe(void); #endif @@ -299,12 +300,41 @@ new_currdev.d_unit = 0; } +#ifdef LOADER_ZFS_SUPPORT + list_zfs_bootenv(zfs_fmtdev(&new_currdev)); +#endif + env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), i386_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, env_nounset); } +#ifdef LOADER_ZFS_SUPPORT +static void +list_zfs_bootenv(char *currdev) +{ + char *beroot; + + /* Remove the trailing : */ + currdev[strlen(currdev) - 1] = '\0'; + setenv("zfs_be_active", currdev, 1); + /* Do not overwrite if already set */ + setenv("vfs.root.mountfrom", currdev, 0); + /* Forward past zfs: */ + currdev = strchr(currdev, ':'); + currdev++; + /* Remove the last element (current bootenv) */ + beroot = strrchr(currdev, '/'); + beroot[0] = '\0'; + + beroot = currdev; + + if (beroot && beroot[0] != '\0') + zfs_bootenv(beroot); +} +#endif + COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int @@ -360,6 +390,27 @@ } return (CMD_OK); } + +COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments", + command_reloadbe); + +static int +command_reloadbe(int argc, char *argv[]) +{ + int err; + + if (argc != 2) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } + + err = zfs_bootenv(argv[1]); + if (err != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } + return (CMD_OK); +} #endif /* ISA bus access functions for PnP. */ Index: sys/boot/zfs/libzfs.h =================================================================== --- sys/boot/zfs/libzfs.h +++ sys/boot/zfs/libzfs.h @@ -62,6 +62,8 @@ char *zfs_fmtdev(void *vdev); int zfs_probe_dev(const char *devname, uint64_t *pool_guid); int zfs_list(const char *name); +int zfs_bootenv(const char *name); +int zfs_set_env(const char *name); extern struct devsw zfs_dev; extern struct fs_ops zfs_fsops; Index: sys/boot/zfs/zfs.c =================================================================== --- sys/boot/zfs/zfs.c +++ sys/boot/zfs/zfs.c @@ -80,6 +80,8 @@ zap_leaf_phys_t *f_zap_leaf; /* zap leaf buffer */ }; +static int zfs_env_index = 0; + /* * Open a file. */ @@ -694,3 +696,93 @@ rv = zfs_list_dataset(spa, objid); return (rv); } + +int +zfs_bootenv(const char *name) +{ + static char poolname[ZFS_MAXNAMELEN]; + uint64_t objid; + spa_t *spa; + const char *dsname; + char *index_str; + int len; + int rv; + + setenv("zfs_beroot", name, 1); + + zfs_env_index = 4; + len = strlen(name); + dsname = strchr(name, '/'); + if (dsname != NULL) { + len = dsname - name; + dsname++; + } else + dsname = ""; + memcpy(poolname, name, len); + poolname[len] = '\0'; + + spa = spa_find_by_name(poolname); + if (!spa) + return (ENXIO); + rv = zfs_lookup_dataset(spa, dsname, &objid); + if (rv != 0) + return (rv); + rv = zfs_callback_dataset(spa, objid, zfs_set_env); + if (rv != 0) + return (rv); + index_str = malloc(20); + snprintf(index_str, 20, "%d", zfs_env_index - 1); + rv = setenv("bootenv_count", index_str, 1); + return (rv); +} + +int +zfs_set_env(const char *name) +{ + char *envname = NULL, *envval = NULL, *beroot; + int rv, i; + + beroot = getenv("zfs_beroot"); + if (beroot == NULL) + return (1); + + envname = malloc(32); + envval = malloc(256); + /* Don't overflow the menu, shuffle entries down to show the newest */ + if (zfs_env_index == 9) { + for (i = 4; i < 8; i++) { + snprintf(envname, 32, "bootenvmenu_caption[%d]", i); + snprintf(envval, 32, "bootenvmenu_caption[%d]", i + 1); + setenv(envname, getenv(envval), 1); + + snprintf(envname, 32, "bootenvansi_caption[%d]", i); + snprintf(envval, 32, "bootenvansi_caption[%d]", i + 1); + setenv(envname, getenv(envval), 1); + + snprintf(envname, 32, "bootenv_root[%d]", i); + snprintf(envval, 32, "bootenv_root[%d]", i + 1); + setenv(envname, getenv(envval), 1); + } + zfs_env_index = 8; + } + + snprintf(envname, 32, "bootenvmenu_caption[%d]", zfs_env_index); + snprintf(envval, 256, "%s", name); + rv = setenv(envname, envval, 1); + + snprintf(envname, 32, "bootenvansi_caption[%d]", zfs_env_index); + rv = setenv(envname, envval, 1); + + snprintf(envname, 32, "bootenvmenu_command[%d]", zfs_env_index); + rv = setenv(envname, "set_bootenv", 1); + + snprintf(envname, 32, "bootenv_root[%d]", zfs_env_index); + snprintf(envval, 256, "zfs:%s/%s", beroot, name); + rv = setenv(envname, envval, 1); + + if (zfs_env_index <= 8) + zfs_env_index++; + free(envname); + free(envval); + return (rv); +} \ No newline at end of file Index: sys/boot/zfs/zfsimpl.c =================================================================== --- sys/boot/zfs/zfsimpl.c +++ sys/boot/zfs/zfsimpl.c @@ -1473,7 +1473,7 @@ * the directory contents. */ static int -mzap_list(const dnode_phys_t *dnode) +mzap_list(const dnode_phys_t *dnode, int (*callback)(const char *)) { const mzap_phys_t *mz; const mzap_ent_phys_t *mze; @@ -1492,7 +1492,7 @@ mze = &mz->mz_chunk[i]; if (mze->mze_name[0]) //printf("%-32s 0x%jx\n", mze->mze_name, (uintmax_t)mze->mze_value); - printf("%s\n", mze->mze_name); + callback(mze->mze_name); } return (0); @@ -1503,7 +1503,7 @@ * the directory header. */ static int -fzap_list(const spa_t *spa, const dnode_phys_t *dnode) +fzap_list(const spa_t *spa, const dnode_phys_t *dnode, int (*callback)(const char *)) { int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT; zap_phys_t zh = *(zap_phys_t *) zap_scratch; @@ -1566,13 +1566,19 @@ value = fzap_leaf_value(&zl, zc); //printf("%s 0x%jx\n", name, (uintmax_t)value); - printf("%s\n", name); + callback((const char *)name); } } return (0); } +static int zfs_printf(const char *name) +{ + printf("%s\n", name); + return (0); +} + /* * List a zap directory. */ @@ -1587,9 +1593,9 @@ zap_type = *(uint64_t *) zap_scratch; if (zap_type == ZBT_MICRO) - return mzap_list(dnode); + return mzap_list(dnode, zfs_printf); else - return fzap_list(spa, dnode); + return fzap_list(spa, dnode, zfs_printf); } static int @@ -1858,6 +1864,43 @@ return (zap_list(spa, &child_dir_zap) != 0); } + +int +zfs_callback_dataset(const spa_t *spa, uint64_t objnum, int (*callback)(const char *name)) +{ + uint64_t dir_obj, child_dir_zapobj, zap_type; + dnode_phys_t child_dir_zap, dir, dataset; + dsl_dataset_phys_t *ds; + dsl_dir_phys_t *dd; + + if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) { + printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum); + return (EIO); + } + ds = (dsl_dataset_phys_t *) &dataset.dn_bonus; + dir_obj = ds->ds_dir_obj; + + if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir)) { + printf("ZFS: can't find dirobj %ju\n", (uintmax_t)dir_obj); + return (EIO); + } + dd = (dsl_dir_phys_t *)&dir.dn_bonus; + + child_dir_zapobj = dd->dd_child_dir_zapobj; + if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_zap) != 0) { + printf("ZFS: can't find child zap %ju\n", (uintmax_t)dir_obj); + return (EIO); + } + + if (dnode_read(spa, &child_dir_zap, 0, zap_scratch, child_dir_zap.dn_datablkszsec * 512)) + return (EIO); + + zap_type = *(uint64_t *) zap_scratch; + if (zap_type == ZBT_MICRO) + return mzap_list(&child_dir_zap, callback); + else + return fzap_list(spa, &child_dir_zap, callback); +} #endif /* Index: usr.sbin/bsdinstall/partedit/gpart_ops.c =================================================================== --- usr.sbin/bsdinstall/partedit/gpart_ops.c +++ usr.sbin/bsdinstall/partedit/gpart_ops.c @@ -206,12 +206,11 @@ } } -int -gpart_partition(const char *lg_name, const char *scheme) +const char * +choose_part_type(const char *def_scheme) { int cancel, choice; - struct gctl_req *r; - const char *errstr; + const char *scheme = NULL; DIALOG_LISTITEM items[] = { {"APM", "Apple Partition Map", @@ -228,16 +227,16 @@ "Bootable on Sun SPARC systems", 0 }, }; -schememenu: +parttypemenu: if (scheme == NULL) { - dialog_vars.default_item = __DECONST(char *, default_scheme()); + dialog_vars.default_item = __DECONST(char *, def_scheme); cancel = dlg_menu("Partition Scheme", "Select a partition scheme for this volume:", 0, 0, 0, sizeof(items) / sizeof(items[0]), items, &choice, NULL); dialog_vars.default_item = NULL; if (cancel) - return (-1); + return NULL; if (!is_scheme_bootable(items[choice].name)) { char message[512]; @@ -248,12 +247,42 @@ cancel = dialog_yesno("Warning", message, 0, 0); dialog_vars.defaultno = FALSE; if (cancel) /* cancel */ - goto schememenu; + goto parttypemenu; } scheme = items[choice].name; } + return scheme; +} + +int +gpart_partition(const char *lg_name, const char *scheme) +{ + int cancel; + struct gctl_req *r; + const char *errstr; + +schememenu: + if (scheme == NULL) { + scheme = choose_part_type(default_scheme()); + + if (scheme == NULL) + return (-1); + + if (!is_scheme_bootable(scheme)) { + char message[512]; + sprintf(message, "This partition scheme (%s) is not " + "bootable on this platform. Are you sure you want " + "to proceed?", scheme); + dialog_vars.defaultno = TRUE; + cancel = dialog_yesno("Warning", message, 0, 0); + dialog_vars.defaultno = FALSE; + if (cancel) /* cancel */ + goto schememenu; + } + } + r = gctl_get_handle(); gctl_ro_param(r, "class", -1, "PART"); gctl_ro_param(r, "arg0", -1, lg_name); @@ -322,6 +351,26 @@ gctl_free(r); } +void +gpart_set_root(const char *lg_name, const char *attribute) +{ + struct gctl_req *r; + const char *errstr; + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, lg_name); + gctl_ro_param(r, "flags", -1, "C"); + gctl_ro_param(r, "verb", -1, "set"); + gctl_ro_param(r, "attrib", -1, attribute); + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Error", "Error setting parameter on disk:", + errstr); + gctl_free(r); +} + static void gpart_bootcode(struct ggeom *gp) { Index: usr.sbin/bsdinstall/partedit/part_wizard.c =================================================================== --- usr.sbin/bsdinstall/partedit/part_wizard.c +++ usr.sbin/bsdinstall/partedit/part_wizard.c @@ -257,8 +257,8 @@ goto query; gpart_destroy(gpart); - gpart_partition(disk, default_scheme()); - scheme = default_scheme(); + scheme = choose_part_type(default_scheme()); + gpart_partition(disk, scheme); } if (scheme == NULL || choice == 0) { @@ -272,8 +272,8 @@ gpart_destroy(gpart); } - gpart_partition(disk, default_scheme()); - scheme = default_scheme(); + scheme = choose_part_type(default_scheme()); + gpart_partition(disk, scheme); } if (strcmp(scheme, "PC98") == 0 || strcmp(scheme, "MBR") == 0) { Index: usr.sbin/bsdinstall/partedit/partedit.h =================================================================== --- usr.sbin/bsdinstall/partedit/partedit.h +++ usr.sbin/bsdinstall/partedit/partedit.h @@ -72,6 +72,8 @@ int gpart_partition(const char *lg_name, const char *scheme); void set_default_part_metadata(const char *name, const char *scheme, const char *type, const char *mountpoint, const char *newfs); +void gpart_set_root(const char *lg_name, const char *attribute); +const char *choose_part_type(const char *def_scheme); /* machine-dependent bootability checks */ const char *default_scheme(void); Index: usr.sbin/bsdinstall/partedit/partedit.c =================================================================== --- usr.sbin/bsdinstall/partedit/partedit.c +++ usr.sbin/bsdinstall/partedit/partedit.c @@ -44,6 +44,7 @@ static int sade_mode = 0; static int apply_changes(struct gmesh *mesh); +static void apply_workaround(struct gmesh *mesh); static struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems); static void add_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items, int *nitems); @@ -189,6 +190,7 @@ if (op == 0 && validate_setup()) { /* Save */ error = apply_changes(&mesh); + apply_workaround(&mesh); break; } else if (op == 3) { /* Quit */ gpart_revert_all(&mesh); @@ -390,6 +392,43 @@ return (0); } +static void +apply_workaround(struct gmesh *mesh) +{ + struct gclass *classp; + struct ggeom *gp; + struct gconfig *gc; + const char *scheme = NULL, *modified = NULL; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "PART") == 0) + break; + } + + if (strcmp(classp->lg_name, "PART") != 0) { + dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE); + return; + } + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + LIST_FOREACH(gc, &gp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) { + scheme = gc->lg_val; + } else if (strcmp(gc->lg_name, "modified") == 0) { + modified = gc->lg_val; + } + } + + if (scheme && strcmp(scheme, "GPT") == 0 && + modified && strcmp(modified, "true") == 0) { + if (getenv("WORKAROUND_LENOVO")) + gpart_set_root(gp->lg_name, "lenovofix"); + if (getenv("WORKAROUND_GPTACTIVE")) + gpart_set_root(gp->lg_name, "active"); + } + } +} + static struct partedit_item * read_geom_mesh(struct gmesh *mesh, int *nitems) { Index: usr.sbin/bsdinstall/scripts/auto =================================================================== --- usr.sbin/bsdinstall/scripts/auto +++ usr.sbin/bsdinstall/scripts/auto @@ -31,6 +31,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 +f_include $BSDCFG_SHARE/dialog.subr ############################################################ FUNCTIONS @@ -51,6 +52,54 @@ fi } +hline_arrows_tab_enter="Press arrows, TAB or ENTER" +msg_gpt_active_fix="Your hardware is known to have issues booting in BIOS mode from GPT partitions that are not set active. Would you like the installer to apply this workaround for you?" +msg_lenovo_fix="Your model of Lenovo is known to have a BIOS bug that prevents it booting from GPT partitions without UEFI. Would you like the installer to apply a workaround for you?" +msg_no="NO" +msg_yes="YES" + +# dialog_workaround +# +# Ask the user if they wish to apply a workaround +# +dialog_workaround() +{ + local passed_msg="$1" + local title="$DIALOG_TITLE" + local btitle="$DIALOG_BACKTITLE" + local prompt # Calculated below + local hline="$hline_arrows_tab_enter" + + local height=8 width=50 prefix=" " + local plen=${#prefix} list= line= + local max_width=$(( $width - 3 - $plen )) + + local yes no defaultno extra_args format + if [ "$USE_XDIALOG" ]; then + yes=ok no=cancel defaultno=default-no + extra_args="--wrap --left" + format="$passed_msg" + else + yes=yes no=no defaultno=defaultno + extra_args="--cr-wrap" + format="$passed_msg" + fi + + # Add height for Xdialog(1) + [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 )) + + prompt=$( printf "$format" ) + f_dprintf "%s: Workaround prompt" "$0" + $DIALOG \ + --title "$title" \ + --backtitle "$btitle" \ + --hline "$hline" \ + --$yes-label "$msg_yes" \ + --$no-label "$msg_no" \ + $extra_args \ + --yesno "$prompt" $height $width +} + ############################################################ MAIN f_dprintf "Began Installation at %s" "$( date )" @@ -106,6 +155,47 @@ rm -f $PATH_FSTAB touch $PATH_FSTAB +# +# Try to detect known broken platforms and apply their workarounds +# + +if f_interactive; then + sys_maker=$( kenv -q smbios.system.maker ) + f_dprintf "smbios.system.maker=[%s]" "$sys_maker" + sys_model=$( kenv -q smbios.system.product ) + f_dprintf "smbios.system.product=[%s]" "$sys_model" + sys_version=$( kenv -q smbios.system.version ) + f_dprintf "smbios.system.version=[%s]" "$sys_version" + case "$sys_maker" in + "LENOVO") + case "$sys_version" in + "ThinkPad X220"|"ThinkPad T420"|"ThinkPad T520") + dialog_workaround "$msg_lenovo_fix" + retval=$? + f_dprintf "lenovofix_prompt=[%s]" "$retval" + if [ $retval -eq $DIALOG_OK ]; then + export ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix" + export WORKAROUND_LENOVO=1 + fi + ;; + esac + ;; + "Dell Inc.") + case "$sys_model" in + "Latitude E7440") + dialog_workaround "$msg_gpt_active_fix" + retval=$? + f_dprintf "gpt_active_fix_prompt=[%s]" "$retval" + if [ $retval -eq $DIALOG_OK ]; then + export ZFSBOOT_PARTITION_SCHEME="GPT + Active" + export WORKAROUND_GPTACTIVE=1 + fi + ;; + esac + ;; + esac +fi + PMODES="\ \"Auto (UFS)\" \"Guided Disk Setup\" \ Manual \"Manual Disk Setup (experts)\" \ Index: usr.sbin/bsdinstall/scripts/zfsboot =================================================================== --- usr.sbin/bsdinstall/scripts/zfsboot +++ usr.sbin/bsdinstall/scripts/zfsboot @@ -196,6 +196,8 @@ GPART_CREATE='gpart create -s %s "%s"' GPART_DESTROY_F='gpart destroy -F "%s"' GPART_SET_ACTIVE='gpart set -a active -i %s "%s"' +GPART_SET_LENOVOFIX='gpart set -a lenovofix "%s"' +GPART_SET_PMBR_ACTIVE='gpart set -a active "%s"' GRAID_DELETE='graid delete "%s"' LN_SF='ln -sf "%s" "%s"' MKDIR_P='mkdir -p "%s"' @@ -263,7 +265,7 @@ msg_null_poolname="NULL poolname" msg_ok="OK" msg_partition_scheme="Partition Scheme" -msg_partition_scheme_help="Toggle between GPT and MBR partitioning schemes" +msg_partition_scheme_help="Select partitioning scheme. GPT is recommended." msg_please_enter_a_name_for_your_zpool="Please enter a name for your zpool:" msg_please_enter_amount_of_swap_space="Please enter amount of swap space (SI-Unit suffixes\nrecommended; e.g., \`2g' for 2 Gigabytes):" msg_please_select_one_or_more_disks="Please select one or more disks to create a zpool:" @@ -779,7 +781,7 @@ # Check for unknown partition scheme before proceeding further case "$ZFSBOOT_PARTITION_SCHEME" in - ""|MBR|GPT) : known good ;; + ""|MBR|GPT*) : known good ;; *) f_dprintf "$funcname: %s is an unsupported partition scheme" \ "$ZFSBOOT_PARTITION_SCHEME" @@ -826,7 +828,7 @@ fi case "$ZFSBOOT_PARTITION_SCHEME" in - ""|GPT) f_dprintf "$funcname: Creating GPT layout..." + ""|GPT*) f_dprintf "$funcname: Creating GPT layout..." # # 1. Create GPT layout using labels # @@ -834,6 +836,17 @@ return $FAILURE # + # Apply workarounds if requested by the user + # + if [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Lenovo Fix" ]; then + f_eval_catch $funcname gpart "$GPART_SET_LENOVOFIX" \ + $disk || return $FAILURE + elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Active" ]; then + f_eval_catch $funcname gpart "$GPART_SET_PMBR_ACTIVE" \ + $disk || return $FAILURE + fi + + # # 2. Add small freebsd-boot partition labeled `boot#' # f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \ @@ -1584,6 +1597,10 @@ # Toggle between GPT and MBR if [ "$ZFSBOOT_PARTITION_SCHEME" = GPT ]; then ZFSBOOT_PARTITION_SCHEME=MBR + elif [ "$ZFSBOOT_PARTITION_SCHEME" = MBR ]; then + ZFSBOOT_PARTITION_SCHEME="GPT + Active" + elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Active" ]; then + ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix" else ZFSBOOT_PARTITION_SCHEME=GPT fi