Index | Thread | Search

From:
Jonathan Matthew <jonathan@d14n.org>
Subject:
amd64/efiboot: add mach fwsetup
To:
tech@openbsd.org
Date:
Fri, 8 Aug 2025 17:21:41 +1000

Download raw body.

Thread
Since UEFI 2.4 (released 2013) there has been a mechanism for system
software to tell the machine to boot into the firmware setup interface,
described here:
  https://uefi.org/specs/UEFI/2.11/08_Services_Runtime_Services.html#exchanging-information-between-the-os-and-firmware

The diff below adds a 'mach fwsetup' command to amd64 efiboot that implements
this, so you can get into the firmware interface even if you can't hit F12
in the precise millisecond you need to in the normal boot process.

It's not a required feature, so on some machines (mostly servers as far as
I can tell) it'll just print an error message.

ok?


Index: boot/boot.8
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/boot/boot.8,v
diff -u -p -u -p -r1.36 boot.8
--- boot/boot.8	5 Nov 2024 09:42:48 -0000	1.36
+++ boot/boot.8	8 Aug 2025 07:08:09 -0000
@@ -236,6 +236,8 @@ Set the I/O base address for the serial 
 .It Nm diskinfo
 Prints a list of hard disks installed on your system including:
 BIOS device number, and the BIOS geometry.
+.It Nm fwsetup
+On EFI systems, reboot into the firmware user interface, if supported.
 .It Ic gop Op Ar mode
 On
 .Xr efifb 4
Index: efiboot/cmd_i386.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/cmd_i386.c,v
diff -u -p -u -p -r1.2 cmd_i386.c
--- efiboot/cmd_i386.c	25 Apr 2024 18:31:49 -0000	1.2
+++ efiboot/cmd_i386.c	8 Aug 2025 07:08:09 -0000
@@ -65,6 +65,7 @@ const struct cmd_table cmd_machine[] = {
 #ifdef IDLE_POWEROFF
 	{ "idle",	CMDT_CMD, Xidle_efi },
 #endif
+	{ "fwsetup",	CMDT_CMD, Xfwsetup_efi },
 	{ NULL, 0 }
 };
 
Index: efiboot/efiboot.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/efiboot.c,v
diff -u -p -u -p -r1.42 efiboot.c
--- efiboot/efiboot.c	25 Apr 2024 18:31:49 -0000	1.42
+++ efiboot/efiboot.c	8 Aug 2025 07:08:09 -0000
@@ -40,6 +40,8 @@
 
 #define	KERN_LOADSPACE_SIZE	(64 * 1024 * 1024)
 
+#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI	1ULL
+
 EFI_SYSTEM_TABLE	*ST;
 EFI_BOOT_SERVICES	*BS;
 EFI_RUNTIME_SERVICES	*RS;
@@ -1243,3 +1245,41 @@ Xidle_efi(void)
 	return 0;
 }
 #endif /* IDLE_POWEROFF */
+
+int
+Xfwsetup_efi(void)
+{
+	UINT64 osind;
+	UINTN osind_size = sizeof(osind);
+	UINT32 osind_attrs = 0x1 | 0x2 | 0x4;
+	EFI_GUID global = EFI_GLOBAL_VARIABLE;
+	EFI_STATUS status;
+
+	status = RS->GetVariable(L"OsIndicationsSupported", &global, NULL,
+	    &osind_size, &osind);
+	if (status == EFI_NOT_FOUND) {
+		printf("not supported on this machine.\n");
+		return -1;
+	} else if (status != EFI_SUCCESS) {
+		printf("%s: %d\n", __func__, status);
+		return -1;
+	}
+
+	if ((osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) == 0) {
+		printf("not supported on this machine.\n");
+		return -1;
+	}
+
+	osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+	status = RS->SetVariable(L"OsIndications", &global, osind_attrs,
+	    sizeof(osind), &osind);
+	if (status != EFI_SUCCESS) {
+		printf("%s: %d\n", __func__, status);
+		return -1;
+	}
+
+	RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+	for (;;)
+		continue;
+	return 0;
+}
Index: efiboot/efiboot.h
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/efiboot.h,v
diff -u -p -u -p -r1.6 efiboot.h
--- efiboot/efiboot.h	25 Apr 2024 18:31:49 -0000	1.6
+++ efiboot/efiboot.h	8 Aug 2025 07:08:09 -0000
@@ -40,6 +40,7 @@ int	 Xpoweroff_efi(void);
 #ifdef IDLE_POWEROFF
 int	 Xidle_efi(void);
 #endif
+int	 Xfwsetup_efi(void);
 
 extern void (*run_i386)(u_long, u_long, int, int, int, int, int, int, int, int)
     __attribute__ ((noreturn));