Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Jul 2015 21:12:29 +0000 (UTC)
From:      Allan Jude <allanjude@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r285769 - in stable/10/usr.sbin/bsdinstall: partedit scripts
Message-ID:  <201507212112.t6LLCTRp057855@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: allanjude (doc committer)
Date: Tue Jul 21 21:12:28 2015
New Revision: 285769
URL: https://svnweb.freebsd.org/changeset/base/285769

Log:
  MFC: r285679
  	Add auto-detecting workaround for Lenovo GPT boot issue
  	Add auto-detecting workaround for "GPT Active" boot issue
  	Allow user to select partitioning scheme in the ufs wizard
  
  PR:		184910
  PR:		194359
  Approved by:	re (gjb), marcel
  Relnotes:	yes
  Sponsored by:	ScaleEngine Inc.
  Differential Revision:	https://reviews.freebsd.org/D3144

Modified:
  stable/10/usr.sbin/bsdinstall/partedit/gpart_ops.c
  stable/10/usr.sbin/bsdinstall/partedit/part_wizard.c
  stable/10/usr.sbin/bsdinstall/partedit/partedit.c
  stable/10/usr.sbin/bsdinstall/partedit/partedit.h
  stable/10/usr.sbin/bsdinstall/scripts/auto
  stable/10/usr.sbin/bsdinstall/scripts/zfsboot
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.sbin/bsdinstall/partedit/gpart_ops.c
==============================================================================
--- stable/10/usr.sbin/bsdinstall/partedit/gpart_ops.c	Tue Jul 21 21:07:18 2015	(r285768)
+++ stable/10/usr.sbin/bsdinstall/partedit/gpart_ops.c	Tue Jul 21 21:12:28 2015	(r285769)
@@ -206,12 +206,11 @@ newfs_command(const char *fstype, char *
 	}
 }
 
-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,30 +227,61 @@ gpart_partition(const char *lg_name, con
 		    "Bootable on Sun SPARC systems", 0 },
 	};
 
+parttypemenu:
+	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 NULL;
+
+	if (!is_scheme_bootable(items[choice].name)) {
+		char message[512];
+		sprintf(message, "This partition scheme (%s) is not "
+		    "bootable on this platform. Are you sure you want "
+		    "to proceed?", items[choice].name);
+		dialog_vars.defaultno = TRUE;
+		cancel = dialog_yesno("Warning", message, 0, 0);
+		dialog_vars.defaultno = FALSE;
+		if (cancel) /* cancel */
+			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) {
-		dialog_vars.default_item = __DECONST(char *, default_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;
+		scheme = choose_part_type(default_scheme());
 
-		if (cancel)
+		if (scheme == NULL)
 			return (-1);
 
-		if (!is_scheme_bootable(items[choice].name)) {
+		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?", items[choice].name);
+			    "to proceed?", scheme);
 			dialog_vars.defaultno = TRUE;
 			cancel = dialog_yesno("Warning", message, 0, 0);
 			dialog_vars.defaultno = FALSE;
-			if (cancel) /* cancel */
+			if (cancel) { /* cancel */
+				/* Reset scheme so user can choose another */
+				scheme = NULL;
 				goto schememenu;
+			}
 		}
-
-		scheme = items[choice].name;
 	}
 
 	r = gctl_get_handle();
@@ -322,6 +352,26 @@ gpart_activate(struct gprovider *pp)
 	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)
 {

Modified: stable/10/usr.sbin/bsdinstall/partedit/part_wizard.c
==============================================================================
--- stable/10/usr.sbin/bsdinstall/partedit/part_wizard.c	Tue Jul 21 21:07:18 2015	(r285768)
+++ stable/10/usr.sbin/bsdinstall/partedit/part_wizard.c	Tue Jul 21 21:12:28 2015	(r285769)
@@ -257,8 +257,10 @@ query:
 			goto query;
 
 		gpart_destroy(gpart);
-		gpart_partition(disk, default_scheme());
-		scheme = default_scheme();
+		scheme = choose_part_type(default_scheme());
+		if (scheme == NULL)
+			return NULL;
+		gpart_partition(disk, scheme);
 	}
 
 	if (scheme == NULL || choice == 0) {
@@ -272,8 +274,10 @@ query:
 			gpart_destroy(gpart);
 		}
 
-		gpart_partition(disk, default_scheme());
-		scheme = default_scheme();
+		scheme = choose_part_type(default_scheme());
+		if (scheme == NULL)
+			return NULL;
+		gpart_partition(disk, scheme);
 	}
 
 	if (strcmp(scheme, "PC98") == 0 || strcmp(scheme, "MBR") == 0) {

Modified: stable/10/usr.sbin/bsdinstall/partedit/partedit.c
==============================================================================
--- stable/10/usr.sbin/bsdinstall/partedit/partedit.c	Tue Jul 21 21:07:18 2015	(r285768)
+++ stable/10/usr.sbin/bsdinstall/partedit/partedit.c	Tue Jul 21 21:12:28 2015	(r285769)
@@ -44,6 +44,7 @@ struct pmetadata_head part_metadata;
 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,8 @@ main(int argc, const char **argv)
 
 			if (op == 0 && validate_setup()) { /* Save */
 				error = apply_changes(&mesh);
+				if (!error)
+					apply_workaround(&mesh);
 				break;
 			} else if (op == 3) { /* Quit */
 				gpart_revert_all(&mesh);
@@ -390,6 +393,43 @@ apply_changes(struct gmesh *mesh)
 	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)
 {

Modified: stable/10/usr.sbin/bsdinstall/partedit/partedit.h
==============================================================================
--- stable/10/usr.sbin/bsdinstall/partedit/partedit.h	Tue Jul 21 21:07:18 2015	(r285768)
+++ stable/10/usr.sbin/bsdinstall/partedit/partedit.h	Tue Jul 21 21:12:28 2015	(r285769)
@@ -72,6 +72,8 @@ void gpart_commit(struct gmesh *mesh);
 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);

Modified: stable/10/usr.sbin/bsdinstall/scripts/auto
==============================================================================
--- stable/10/usr.sbin/bsdinstall/scripts/auto	Tue Jul 21 21:07:18 2015	(r285768)
+++ stable/10/usr.sbin/bsdinstall/scripts/auto	Tue Jul 21 21:12:28 2015	(r285769)
@@ -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 @@ error() {
 	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 @@ fi
 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)\" \

Modified: stable/10/usr.sbin/bsdinstall/scripts/zfsboot
==============================================================================
--- stable/10/usr.sbin/bsdinstall/scripts/zfsboot	Tue Jul 21 21:07:18 2015	(r285768)
+++ stable/10/usr.sbin/bsdinstall/scripts/zfsboot	Tue Jul 21 21:12:28 2015	(r285769)
@@ -196,6 +196,8 @@ GPART_BOOTCODE_PART='gpart bootcode -b "
 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_index_argument="NULL index argu
 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 @@ zfs_create_diskpart()
 
 	# 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 @@ zfs_create_diskpart()
 	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 @@ zfs_create_diskpart()
 		             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" \
@@ -1581,6 +1594,10 @@ while :; do
 		# 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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507212112.t6LLCTRp057855>