]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: add reboot-on-error config option
authornkraetzschmar <9020053+nkraetzschmar@users.noreply.github.com>
Tue, 11 Mar 2025 12:23:14 +0000 (13:23 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 12 Mar 2025 14:47:38 +0000 (15:47 +0100)
Enabling this option will cause the system to reboot in case the selected
entry fails to load.

man/loader.conf.xml
src/boot/boot.c
tools/command_ignorelist

index 8e67c2bc1ae381dd92d6a1e78e3ced0c1ab64d5f..22deb8568b718ae7edc18fb5c63a03d60ac0485e 100644 (file)
@@ -399,6 +399,36 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e
 
         <xi:include href="version-info.xml" xpointer="v251"/></listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term>reboot-on-error</term>
+
+        <listitem><para>Controls auto reboot in case the selected entry fails to start.
+
+        <variablelist>
+          <varlistentry>
+            <term><option>yes</option></term>
+            <listitem><para>Reboot the system if the selected boot entry failed to start.</para></listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term><option>no</option></term>
+            <listitem><para>Don't reboot - pass control back to EFI firmware.</para></listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term><option>auto</option></term>
+            <listitem>
+            <para>Perform the reboot if and only if boot counting is enabled for this entry and the tries left counter wasn't already at 0.</para>
+            <para>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.</para>
+            </listitem>
+          </varlistentry>
+
+        </variablelist>
+        </para>
+
+        <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index cf36c105f669da084e65696c1c6d069c034c3c5c..af7ab4e79371f9b0f67359b86c9979a55a6a3955 100644 (file)
@@ -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;
index 5e746a46659a3dc099bd230528c4b6b2c1c60b09..5ebdd2b7b48db2a5139aaf606e8bfd1b87a35503 100644 (file)
@@ -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"]