]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Add ability to reboot to firmware setup menu
authorMichael Brown <mcb30@ipxe.org>
Mon, 28 Apr 2025 13:01:17 +0000 (14:01 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 28 Apr 2025 13:01:17 +0000 (14:01 +0100)
Add the ability to reboot to the firmware setup menu (if supported) by
setting the relevant value in the OsIndications variable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/hci/commands/reboot_cmd.c
src/include/ipxe/reboot.h
src/interface/efi/efi_reboot.c

index f344684011666a5335b9d10e51fcf9e20f1d0ffa..5d4e151b8b58f0e8e5cd5e98ef9b9d9638f39625 100644 (file)
@@ -38,12 +38,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 struct reboot_options {
        /** Perform a warm reboot */
        int warm;
+       /** Reboot to firmware setup */
+       int setup;
 };
 
 /** "reboot" option list */
 static struct option_descriptor reboot_opts[] = {
        OPTION_DESC ( "warm", 'w', no_argument,
                      struct reboot_options, warm, parse_flag ),
+       OPTION_DESC ( "setup", 's', no_argument,
+                     struct reboot_options, setup, parse_flag ),
 };
 
 /** "reboot" command descriptor */
@@ -69,6 +73,8 @@ static int reboot_exec ( int argc, char **argv ) {
        /* Reboot system */
        if ( opts.warm )
                flags |= REBOOT_WARM;
+       if ( opts.setup )
+               flags |= REBOOT_SETUP;
        reboot ( flags );
 
        return 0;
index 2d8dadecaad4d81cf4bb1fcf532b3877f2c5132f..cfd5b546d8f82899d5b135214e6ed0ece6cf0938 100644 (file)
@@ -56,6 +56,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 void reboot ( int flags );
 
 #define REBOOT_WARM    0x00000001 /**< Perform a warm reboot */
+#define REBOOT_SETUP   0x00000002 /**< Reboot to firmware setup */
 
 /**
  * Power off system
index eb389a4b10ea17fa1e87bfd7376a650da1e94436..7ed9f5c8421d48a1681f00f9eab23109dbb993f7 100644 (file)
@@ -31,7 +31,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  */
 
 #include <errno.h>
+#include <string.h>
 #include <ipxe/efi/efi.h>
+#include <ipxe/efi/Guid/GlobalVariable.h>
 #include <ipxe/reboot.h>
 
 /**
@@ -41,7 +43,28 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  */
 static void efi_reboot ( int flags ) {
        EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
+       static CHAR16 wname[] = EFI_OS_INDICATIONS_VARIABLE_NAME;
+       UINT64 osind;
+       UINT32 attrs;
        EFI_RESET_TYPE type;
+       EFI_STATUS efirc;
+       int rc;
+
+       /* Request boot to firmware setup, if applicable */
+       if ( flags & REBOOT_SETUP ) {
+               osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+               attrs = ( EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                         EFI_VARIABLE_RUNTIME_ACCESS |
+                         EFI_VARIABLE_NON_VOLATILE );
+               if ( ( efirc = rs->SetVariable ( wname, &efi_global_variable,
+                                                attrs, sizeof ( osind ),
+                                                &osind ) ) != 0 ) {
+                       rc = -EEFI ( efirc );
+                       DBGC ( efi_systab, "EFI could not set %ls: %s\n",
+                              wname, strerror ( rc ) );
+                       /* Continue to reboot anyway */
+               }
+       }
 
        /* Use runtime services to reset system */
        type = ( ( flags & REBOOT_WARM ) ? EfiResetWarm : EfiResetCold );