From: nkraetzschmar <9020053+nkraetzschmar@users.noreply.github.com> Date: Tue, 11 Mar 2025 12:23:14 +0000 (+0100) Subject: boot: add reboot-on-error config option X-Git-Tag: v258-rc1~1105 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0bdf94e588c8d781a91e5738525d673c0966a510;p=thirdparty%2Fsystemd.git boot: add reboot-on-error config option Enabling this option will cause the system to reboot in case the selected entry fails to load. --- diff --git a/man/loader.conf.xml b/man/loader.conf.xml index 8e67c2bc1ae..22deb8568b7 100644 --- a/man/loader.conf.xml +++ b/man/loader.conf.xml @@ -399,6 +399,36 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e + + + reboot-on-error + + Controls auto reboot in case the selected entry fails to start. + + + + + Reboot the system if the selected boot entry failed to start. + + + + + Don't reboot - pass control back to EFI firmware. + + + + + + Perform the reboot if and only if boot counting is enabled for this entry and the tries left counter wasn't already at 0. + This is the default, as it is typically a safe option, that ensures a clean measurement log on each boot attempt, but also does not risk an unbounded reboot loop. + + + + + + + + diff --git a/src/boot/boot.c b/src/boot/boot.c index cf36c105f66..af7ab4e7937 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -79,6 +79,12 @@ typedef enum LoaderType { /* Whether to persistently save the selected entry in an EFI variable, if that's requested. */ #define LOADER_TYPE_SAVE_ENTRY(t) IN_SET(t, LOADER_EFI, LOADER_LINUX, LOADER_UKI, LOADER_UKI_URL, LOADER_TYPE2_UKI) +typedef enum { + REBOOT_NO, + REBOOT_YES, + REBOOT_AUTO, +} RebootOnError; + typedef struct BootEntry { char16_t *id; /* The unique identifier for this entry (typically the filename of the file defining the entry, possibly suffixed with a profile id) */ char16_t *id_without_profile; /* same, but without any profile id suffixed */ @@ -123,6 +129,7 @@ typedef struct { bool auto_poweroff; bool auto_reboot; bool reboot_for_bitlocker; + RebootOnError reboot_on_error; secure_boot_enroll secure_boot_enroll; bool force_menu; bool use_saved_entry; @@ -317,6 +324,20 @@ static void print_status(Config *config, char16_t *loaded_image_path) { printf(" beep: %ls\n", yes_no(config->beep)); printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker)); + switch (config->reboot_on_error) { + case REBOOT_NO: + printf(" reboot-on-error: no\n"); + break; + case REBOOT_YES: + printf(" reboot-on-error: yes\n"); + break; + case REBOOT_AUTO: + printf(" reboot-on-error: auto\n"); + break; + default: + assert_not_reached(); + } + switch (config->secure_boot_enroll) { case ENROLL_OFF: printf(" secure-boot-enroll: off\n"); @@ -1055,6 +1076,17 @@ static void config_defaults_load_from_file(Config *config, char *content) { log_error("Error parsing 'reboot-for-bitlocker' config option, ignoring: %s", value); + } else if (streq8(key, "reboot-on-error")) { + if (streq8(value, "auto")) + config->reboot_on_error = REBOOT_AUTO; + else { + bool reboot_yes_no; + if (!parse_boolean(value, &reboot_yes_no)) + log_error("Error parsing 'reboot-on-error' config option, ignoring: %s", value); + + config->reboot_on_error = reboot_yes_no ? REBOOT_YES : REBOOT_NO; + } + } else if (streq8(key, "secure-boot-enroll")) { if (streq8(value, "manual")) config->secure_boot_enroll = ENROLL_MANUAL; @@ -1421,6 +1453,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { .editor = true, .auto_entries = true, .auto_firmware = true, + .reboot_on_error = REBOOT_AUTO, .secure_boot_enroll = ENROLL_IF_SAFE, .idx_default_efivar = IDX_INVALID, .console_mode = CONSOLE_MODE_KEEP, @@ -2998,8 +3031,14 @@ static EFI_STATUS run(EFI_HANDLE image) { (void) process_random_seed(root_dir); err = ASSERT_PTR(entry->call)(entry, root_dir, image); - if (err != EFI_SUCCESS) + if (err != EFI_SUCCESS) { + if (config.reboot_on_error == REBOOT_YES || (config.reboot_on_error == REBOOT_AUTO && entry->tries_left > 0)) { + printf("Failed to start boot entry. Rebooting in 5s.\n"); + BS->Stall(5 * 1000 * 1000); + (void) call_reboot_system(/* entry= */ NULL, /* root_dir= */ NULL, /* parent_image= */ NULL); + } return err; + } menu = true; config.timeout_sec = 0; diff --git a/tools/command_ignorelist b/tools/command_ignorelist index 5e746a46659..5ebdd2b7b48 100644 --- a/tools/command_ignorelist +++ b/tools/command_ignorelist @@ -578,3 +578,6 @@ file-hierarchy.xml /refsect1[title="Home Directory"]/variablelist/varlistentry[t systemd-measure.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--linux=PATH"] systemd-nspawn.xml /refsect1[title="Hotkeys"]/variablelist/varlistentry[term="Ctrl-] Ctrl-] Ctrl-]"] run0.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--pty"] +loader.conf.xml /refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="yes"] +loader.conf.xml /refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="no"] +loader.conf.xml /refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="auto"]