<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>
/* 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 */
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;
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");
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;
.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,
(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;