:: commit b2052c518c31a16f85733b83977f45b81ea2a0f3

mintsuki <mintsuki@protonmail.com> — 2024-03-21 02:18

parents: ba5c0004e6

menu: Add support for remembering last booted entry on UEFI

diff --git a/CONFIG.md b/CONFIG.md
index 85675598..9a11da18 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -61,6 +61,7 @@ Miscellaneous:
 * `SERIAL` - If set to `yes`, enable serial I/O for the bootloader.
 * `SERIAL_BAUDRATE` - If `SERIAL` is set to `yes`, this specifies the baudrate to use for serial I/O. Defaults to `9600`. BIOS only, ignored with Limine UEFI.
 * `DEFAULT_ENTRY` - 1-based entry index of the entry which will be automatically selected at startup. If unspecified, it is `1`.
+* `REMEMBER_LAST_ENTRY` - If set to `yes`, remember last booted entry. (UEFI only)
 * `GRAPHICS` - If set to `no`, force CGA text mode for the boot menu, else use a video mode. Ignored with Limine UEFI.
 * `VERBOSE` - If set to `yes`, print additional information during boot. Defaults to not verbose.
 * `RANDOMISE_MEMORY` - If set to `yes`, randomise the contents of RAM at bootup in order to find bugs related to non zeroed memory or for security reasons. This option will slow down boot time significantly. For the BIOS port of Limine, this will only randomise memory below 4GiB.
diff --git a/common/menu.c b/common/menu.c
index 4374db6d..d42840c3 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -23,6 +23,11 @@
 #include <protos/multiboot2.h>
 #include <protos/limine.h>
 
+#if defined (UEFI)
+EFI_GUID limine_efi_vendor_guid =
+    { 0x513ee0d0, 0x6e43, 0xcb05, { 0xb2, 0x72, 0xf1, 0x46, 0xa2, 0xfc, 0xb8, 0x8a } };
+#endif
+
 static char *menu_branding = NULL;
 static char *menu_branding_colour = NULL;
 
@@ -756,6 +761,7 @@ noreturn void _menu(bool first_run) {
     struct menu_entry *selected_menu_entry = NULL;
 
     size_t selected_entry = 0;
+
     char *default_entry = config_get_value(NULL, 0, "DEFAULT_ENTRY");
     if (default_entry != NULL) {
         selected_entry = strtoui(default_entry, NULL, 10);
@@ -763,6 +769,21 @@ noreturn void _menu(bool first_run) {
             selected_entry--;
     }
 
+#if defined (UEFI)
+    char *remember_last = config_get_value(NULL, 0, "REMEMBER_LAST_ENTRY");
+    if (remember_last != NULL && strcasecmp(remember_last, "yes") == 0) {
+        UINTN getvar_size = sizeof(size_t);
+        size_t last;
+        if (gRT->GetVariable(L"LimineLastBootedEntry",
+                             &limine_efi_vendor_guid,
+                             NULL,
+                             &getvar_size,
+                             &last) == 0 && getvar_size == sizeof(size_t)) {
+            selected_entry = last;
+        }
+    }
+#endif
+
     size_t timeout = 5;
     char *timeout_config = config_get_value(NULL, 0, "TIMEOUT");
     if (timeout_config != NULL) {
@@ -970,6 +991,15 @@ timeout_aborted:
                         reset_term();
                     }
                 }
+
+#if defined (UEFI)
+                gRT->SetVariable(L"LimineLastBootedEntry",
+                                 &limine_efi_vendor_guid,
+                                 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                                 sizeof(size_t),
+                                 &selected_entry);
+#endif
+
                 boot(selected_menu_entry->body);
             case 'e':
             case 'E': {
tab: 248 wrap: offon