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 <emil.velikov@collabora.com>
This commit is contained in:
Emil Velikov 2023-10-04 11:51:47 +01:00 committed by Emil Velikov
parent 28052aa8cd
commit cb341090d0
3 changed files with 67 additions and 3 deletions

View File

@ -100,6 +100,14 @@
<entry>auto-osx</entry>
<entry>macOS</entry>
</row>
<row>
<entry>auto-poweroff</entry>
<entry>Power Off The System</entry>
</row>
<row>
<entry>auto-reboot</entry>
<entry>Reboot The System</entry>
</row>
<row>
<entry>auto-reboot-to-firmware-setup</entry>
<entry>Reboot Into Firmware Interface</entry>

View File

@ -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

View File

@ -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,
};