Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Aug 2020 02:05:58 +0000 (UTC)
From:      D Scott Phillips <scottph@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r364795 - head/usr.sbin/efibootmgr
Message-ID:  <202008260205.07Q25wFp027678@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: scottph
Date: Wed Aug 26 02:05:58 2020
New Revision: 364795
URL: https://svnweb.freebsd.org/changeset/base/364795

Log:
  efibootmgr: Add option to request booting to the firmware user interface
  
  The OsIndications UEFI variable can request the firware to stop at
  its UI instead of continuing with boot. Add flags for setting and
  clearing this request.
  
  Reviewed by:	manu, bcr (manpages)
  Approved by:	scottl (implicit)
  MFC after:	1 week
  Sponsored by:	Ampere Computing, Inc.
  Differential Revision:	https://reviews.freebsd.org/D25839

Modified:
  head/usr.sbin/efibootmgr/efibootmgr.8
  head/usr.sbin/efibootmgr/efibootmgr.c

Modified: head/usr.sbin/efibootmgr/efibootmgr.8
==============================================================================
--- head/usr.sbin/efibootmgr/efibootmgr.8	Wed Aug 26 02:04:04 2020	(r364794)
+++ head/usr.sbin/efibootmgr/efibootmgr.8	Wed Aug 26 02:05:58 2020	(r364795)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 23, 2020
+.Dd August 25, 2020
 .Dt EFIBOOTMGR 8
 .Os
 .Sh NAME
@@ -55,6 +55,10 @@
 .Op Fl d
 .Op Fl p
 .Nm
+.Fl F
+.Nm
+.Fl f
+.Nm
 .Fl n
 .Fl b Ar bootnum
 .Nm
@@ -137,6 +141,9 @@ is specified, the UEFI device path to the ESP is repor
 If
 .Fl p -unix-path
 is specified, the mount point of the ESP is reported instead.
+.It Fl f -fw-ui , Fl F -no-fw-ui
+Set or clear the request to the system firmware to stop in its user
+interface on the next boot.
 .It Fl k -kernel Ar kernel
 The path to and name of the kernel.
 .It Fl l -loader Ar loader

Modified: head/usr.sbin/efibootmgr/efibootmgr.c
==============================================================================
--- head/usr.sbin/efibootmgr/efibootmgr.c	Wed Aug 26 02:04:04 2020	(r364794)
+++ head/usr.sbin/efibootmgr/efibootmgr.c	Wed Aug 26 02:05:58 2020	(r364795)
@@ -67,6 +67,8 @@ __FBSDID("$FreeBSD$");
 
 #define BAD_LENGTH	((size_t)-1)
 
+#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
+
 typedef struct _bmgr_opts {
 	char	*env;
 	char	*loader;
@@ -83,6 +85,8 @@ typedef struct _bmgr_opts {
 	bool    dry_run;
 	bool	device_path;
 	bool	esp_device;
+	bool    fw_ui;
+	bool    no_fw_ui;
 	bool	has_bootnum;
 	bool    once;
 	int	cp_src;
@@ -110,6 +114,8 @@ static struct option lopts[] = {
 	{"dry-run", no_argument, NULL, 'D'},
 	{"env", required_argument, NULL, 'e'},
 	{"esp", no_argument, NULL, 'E'},
+	{"fw-ui", no_argument, NULL, 'f'},
+	{"no-fw-ui", no_argument, NULL, 'F'},
 	{"help", no_argument, NULL, 'h'},
 	{"kernel", required_argument, NULL, 'k'},
 	{"label", required_argument, NULL, 'L'},
@@ -197,7 +203,7 @@ parse_args(int argc, char *argv[])
 {
 	int ch;
 
-	while ((ch = getopt_long(argc, argv, "AaBb:C:cdDe:Ehk:L:l:NnOo:pTt:v",
+	while ((ch = getopt_long(argc, argv, "AaBb:C:cdDe:EFfhk:L:l:NnOo:pTt:v",
 		    lopts, NULL)) != -1) {
 		switch (ch) {
 		case 'A':
@@ -232,6 +238,12 @@ parse_args(int argc, char *argv[])
 		case 'E':
 			opts.esp_device = true;
 			break;
+		case 'F':
+			opts.no_fw_ui = true;
+			break;
+		case 'f':
+			opts.fw_ui = true;
+			break;
 		case 'h':
 		default:
 			errx(1, "%s", USAGE);
@@ -825,6 +837,45 @@ print_boot_var(const char *name, bool verbose, bool cu
 }
 
 
+static bool
+os_indication_supported(uint64_t indication)
+{
+	uint8_t *data;
+	size_t size;
+	uint32_t attrs;
+	int ret;
+
+	ret = efi_get_variable(EFI_GLOBAL_GUID, "OsIndicationsSupported", &data,
+	    &size, &attrs);
+	if (ret < 0)
+		return false;
+	return (le64dec(data) & indication) == indication;
+}
+
+static uint64_t
+os_indications(void)
+{
+	uint8_t *data;
+	size_t size;
+	uint32_t attrs;
+	int ret;
+
+	ret = efi_get_variable(EFI_GLOBAL_GUID, "OsIndications", &data, &size,
+	    &attrs);
+	if (ret < 0)
+		return 0;
+	return le64dec(data);
+}
+
+static int
+os_indications_set(uint64_t mask, uint64_t val)
+{
+	uint8_t new[sizeof(uint64_t)];
+
+	le64enc(&new, (os_indications() & ~mask) | (val & mask));
+	return set_bootvar("OsIndications", new, sizeof(new));
+}
+
 /* Cmd epilogue, or just the default with no args.
  * The order is [bootnext] bootcurrent, timeout, order, and the bootvars [-v]
  */
@@ -841,7 +892,15 @@ print_boot_vars(bool verbose)
 	uint32_t attrs;
 	int ret, bolen;
 	uint16_t *boot_order = NULL, current;
+	bool boot_to_fw_ui;
 
+	if (os_indication_supported(EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) {
+		boot_to_fw_ui =
+		    (os_indications() & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0;
+		printf("Boot to FW : %s\n", boot_to_fw_ui != 0 ?
+		    "true" : "false");
+	}
+
 	ret = efi_get_variable(EFI_GLOBAL_GUID, "BootNext", &data, &size, &attrs);
 	if (ret > 0) {
 		printf("BootNext : %04x\n", le16dec(data));
@@ -987,6 +1046,23 @@ report_esp_device(bool do_dp, bool do_unix)
 	exit(0);
 }
 
+static void
+set_boot_to_fw_ui(bool to_fw)
+{
+	int ret;
+
+	if (!os_indication_supported(EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) {
+		if (to_fw)
+			errx(1, "boot to fw ui not supported");
+		else
+			return;
+	}
+	ret = os_indications_set(EFI_OS_INDICATIONS_BOOT_TO_FW_UI,
+	    to_fw ? ~0 : 0);
+	if (ret < 0)
+		errx(1, "failed to set boot to fw ui");
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -1021,6 +1097,10 @@ main(int argc, char *argv[])
 		handle_timeout(opts.timeout);
 	else if (opts.esp_device)
 		report_esp_device(opts.device_path, opts.unix_path);
+	else if (opts.fw_ui)
+		set_boot_to_fw_ui(true);
+	else if (opts.no_fw_ui)
+		set_boot_to_fw_ui(false);
 
 	print_boot_vars(opts.verbose);
 }



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