From cb341090d061084accc9a45ec4b1d258954adba2 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Wed, 4 Oct 2023 11:51:47 +0100 Subject: [PATCH] sd-boot: add auto-reboot and auto-poweroff entries Currently only an auto-reboot-to-firmware entry is available. For other features - like reboot and power off - one needs to press the uppercase B and O respectively. Embedded devices may be missing a full fledged keyboard, so allow for sd-boot to generate those entries. v2: - add to the config parser/man/bootctl/sd-boot info screen - keep them off by default - add the (O)ff and re(B)oot help text if boot entries are not shown - drop irrelevant get_os_indications_supported() comment - s/ShutDown/Shutdown/ v3: - cast shutdown_system() reboot_system() to void v4: - shutdown -> poweroff - add trailing ",ignoring" in parser message - drop explicit default state assignment to "false" Signed-off-by: Emil Velikov --- man/loader.conf.xml | 8 ++++++ src/boot/efi/boot.c | 60 ++++++++++++++++++++++++++++++++++++++++--- src/shared/bootspec.c | 2 ++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/man/loader.conf.xml b/man/loader.conf.xml index c7794cd195f..748276c9cfd 100644 --- a/man/loader.conf.xml +++ b/man/loader.conf.xml @@ -100,6 +100,14 @@ auto-osx macOS + + auto-poweroff + Power Off The System + + + auto-reboot + Reboot The System + auto-reboot-to-firmware-setup Reboot Into Firmware Interface diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 0f61c302a38..de801ceb37d 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -86,6 +86,8 @@ typedef struct { bool editor; bool auto_entries; bool auto_firmware; + bool auto_poweroff; + bool auto_reboot; bool reboot_for_bitlocker; secure_boot_enroll secure_boot_enroll; bool force_menu; @@ -512,6 +514,8 @@ static void print_status(Config *config, char16_t *loaded_image_path) { printf(" editor: %ls\n", yes_no(config->editor)); printf(" auto-entries: %ls\n", yes_no(config->auto_entries)); printf(" auto-firmware: %ls\n", yes_no(config->auto_firmware)); + printf(" auto-poweroff: %ls\n", yes_no(config->auto_poweroff)); + printf(" auto-reboot: %ls\n", yes_no(config->auto_reboot)); printf(" beep: %ls\n", yes_no(config->beep)); printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker)); @@ -618,6 +622,16 @@ static EFI_STATUS reboot_into_firmware(void) { assert_not_reached(); } +static EFI_STATUS poweroff_system(void) { + RT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + assert_not_reached(); +} + +static EFI_STATUS reboot_system(void) { + RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + assert_not_reached(); +} + static bool menu_run( Config *config, ConfigEntry **chosen_entry, @@ -886,7 +900,9 @@ static bool menu_run( case KEYPRESS(0, 0, 'H'): case KEYPRESS(0, 0, '?'): /* This must stay below 80 characters! Q/v/Ctrl+l/f deliberately not advertised. */ - status = xstrdup16(u"(d)efault (t/T)imeout (e)dit (r/R)esolution (p)rint (O)ff re(B)oot (h)elp"); + status = xasprintf("(d)efault (t/T)imeout (e)dit (r/R)esolution (p)rint %s%s(h)elp", + config->auto_poweroff ? "" : "(O)ff ", + config->auto_reboot ? "" : "re(B)oot "); break; case KEYPRESS(0, 0, 'Q'): @@ -1019,11 +1035,11 @@ static bool menu_run( break; case KEYPRESS(0, 0, 'O'): /* Only uppercase, so that it can't be hit so easily fat-fingered, but still works safely over serial */ - RT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + (void) poweroff_system(); break; case KEYPRESS(0, 0, 'B'): /* ditto */ - RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + (void) reboot_system(); break; default: @@ -1258,6 +1274,20 @@ static void config_defaults_load_from_file(Config *config, char *content) { continue; } + if (streq8(key, "auto-poweroff")) { + err = parse_boolean(value, &config->auto_poweroff); + if (err != EFI_SUCCESS) + log_error("Error parsing 'auto-poweroff' config option, ignoring: %s", value); + continue; + } + + if (streq8(key, "auto-reboot")) { + err = parse_boolean(value, &config->auto_reboot); + if (err != EFI_SUCCESS) + log_error("Error parsing 'auto-reboot' config option, ignoring: %s", value); + continue; + } + if (streq8(key, "beep")) { err = parse_boolean(value, &config->beep); if (err != EFI_SUCCESS) @@ -2648,6 +2678,30 @@ static void config_load_all_entries( config_add_entry(config, entry); } + if (config->auto_poweroff) { + ConfigEntry *entry = xnew(ConfigEntry, 1); + *entry = (ConfigEntry) { + .id = xstrdup16(u"auto-poweroff"), + .title = xstrdup16(u"Power Off The System"), + .call = poweroff_system, + .tries_done = -1, + .tries_left = -1, + }; + config_add_entry(config, entry); + } + + if (config->auto_reboot) { + ConfigEntry *entry = xnew(ConfigEntry, 1); + *entry = (ConfigEntry) { + .id = xstrdup16(u"auto-reboot"), + .title = xstrdup16(u"Reboot The System"), + .call = reboot_system, + .tries_done = -1, + .tries_left = -1, + }; + config_add_entry(config, entry); + } + /* find if secure boot signing keys exist and autoload them if necessary otherwise creates menu entries so that the user can load them manually if the secure-boot-enroll variable is set to no (the default), we do not diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 42d5fec754c..f347ccdd8a8 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -1145,6 +1145,8 @@ int boot_config_augment_from_loader( "auto-windows", "Windows Boot Manager", "auto-efi-shell", "EFI Shell", "auto-efi-default", "EFI Default Loader", + "auto-poweroff", "Power Off The System", + "auto-reboot", "Reboot The System", "auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface", NULL, };