From: Jonathan Matthew Subject: amd64/efiboot: add mach fwsetup To: tech@openbsd.org Date: Fri, 8 Aug 2025 17:21:41 +1000 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));