diff --git a/man/loader.conf.xml b/man/loader.conf.xml
index 22deb8568b..f14b77b537 100644
--- a/man/loader.conf.xml
+++ b/man/loader.conf.xml
@@ -373,6 +373,29 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e
+
+ secure-boot-enroll-action
+
+ Specifies the action to take after the automatic enrollment of secure boot keys is completed.
+
+
+ reboot
+
+ Reboot the system after enrollment. This is the default.
+
+
+
+ shutdown
+
+ Shut down the system after enrollment.
+
+
+
+ This option is only relevant if secure-boot-enroll is enabled.
+
+
+
+
reboot-for-bitlocker
diff --git a/src/boot/boot.c b/src/boot/boot.c
index c7f354506c..830ba5b458 100644
--- a/src/boot/boot.c
+++ b/src/boot/boot.c
@@ -141,6 +141,7 @@ typedef struct {
bool reboot_for_bitlocker;
RebootOnError reboot_on_error;
secure_boot_enroll secure_boot_enroll;
+ secure_boot_enroll_action secure_boot_enroll_action;
bool force_menu;
bool use_saved_entry;
bool use_saved_entry_efivar;
@@ -325,34 +326,35 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
if (config->entry_oneshot)
printf(" default (one-shot): %ls\n", config->entry_oneshot);
if (config->entry_saved)
- printf(" saved entry: %ls\n", config->entry_saved);
- 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));
- printf(" reboot-on-error: %s\n", reboot_on_error_to_string(config->reboot_on_error));
- printf(" secure-boot-enroll: %s\n", secure_boot_enroll_to_string(config->secure_boot_enroll));
+ printf(" saved entry: %ls\n", config->entry_saved);
+ 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));
+ printf(" reboot-on-error: %s\n", reboot_on_error_to_string(config->reboot_on_error));
+ printf(" secure-boot-enroll: %s\n", secure_boot_enroll_to_string(config->secure_boot_enroll));
+ printf("secure-boot-enroll-action: %s\n", secure_boot_enroll_action_to_string(config->secure_boot_enroll_action));
switch (config->console_mode) {
case CONSOLE_MODE_AUTO:
- printf(" console-mode (config): auto\n");
+ printf(" console-mode (config): auto\n");
break;
case CONSOLE_MODE_KEEP:
- printf(" console-mode (config): keep\n");
+ printf(" console-mode (config): keep\n");
break;
case CONSOLE_MODE_FIRMWARE_MAX:
- printf(" console-mode (config): max\n");
+ printf(" console-mode (config): max\n");
break;
default:
- printf(" console-mode (config): %" PRIi64 "\n", config->console_mode);
+ printf(" console-mode (config): %" PRIi64 "\n", config->console_mode);
}
/* EFI var console mode is always a concrete value or unset. */
if (config->console_mode_efivar != CONSOLE_MODE_KEEP)
- printf("console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar);
+ printf(" console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar);
if (!ps_continue())
return;
@@ -1080,7 +1082,14 @@ static void config_defaults_load_from_file(Config *config, char *content) {
else
log_error("Error parsing 'secure-boot-enroll' config option, ignoring: %s",
value);
-
+ } else if (streq8(key, "secure-boot-enroll-action")) {
+ if (streq8(value, "reboot"))
+ config->secure_boot_enroll_action = ENROLL_ACTION_REBOOT;
+ else if (streq8(value, "shutdown"))
+ config->secure_boot_enroll_action = ENROLL_ACTION_SHUTDOWN;
+ else
+ log_error("Error parsing 'secure-boot-enroll-action' config option, ignoring: %s",
+ value);
} else if (streq8(key, "console-mode")) {
if (streq8(value, "auto"))
config->console_mode = CONSOLE_MODE_AUTO;
@@ -1436,6 +1445,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
.auto_firmware = true,
.reboot_on_error = REBOOT_AUTO,
.secure_boot_enroll = ENROLL_IF_SAFE,
+ .secure_boot_enroll_action = ENROLL_ACTION_REBOOT,
.idx_default_efivar = IDX_INVALID,
.console_mode = CONSOLE_MODE_KEEP,
.console_mode_efivar = CONSOLE_MODE_KEEP,
@@ -2723,7 +2733,7 @@ static void save_selected_entry(const Config *config, const BootEntry *entry) {
static EFI_STATUS call_secure_boot_enroll(const BootEntry *entry, EFI_FILE *root_dir, EFI_HANDLE parent_image) {
assert(entry);
- return secure_boot_enroll_at(root_dir, entry->path, /* force= */ true);
+ return secure_boot_enroll_at(root_dir, entry->path, /* force= */ true, /* action= */ ENROLL_ACTION_REBOOT);
}
static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir) {
@@ -2774,7 +2784,7 @@ static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir)
strcaseeq16(dirent->FileName, u"auto"))
/* If we auto enroll successfully this call does not return.
* If it fails we still want to add other potential entries to the menu. */
- secure_boot_enroll_at(root_dir, entry->path, config->secure_boot_enroll == ENROLL_FORCE);
+ secure_boot_enroll_at(root_dir, entry->path, config->secure_boot_enroll == ENROLL_FORCE, config->secure_boot_enroll_action);
}
return EFI_SUCCESS;
diff --git a/src/boot/secure-boot.c b/src/boot/secure-boot.c
index b6948586e5..f44a6f149b 100644
--- a/src/boot/secure-boot.c
+++ b/src/boot/secure-boot.c
@@ -69,7 +69,7 @@ static EFI_STATUS set_custom_mode(bool enable) {
attr, sizeof(mode), &mode);
}
-EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force) {
+EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action) {
assert(root_dir);
assert(path);
@@ -185,11 +185,21 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool
}
}
- printf("Custom Secure Boot keys successfully enrolled, rebooting the system now!\n");
/* The system should be in secure boot mode now and we could continue a regular boot. But at least
- * TPM PCR7 measurements should change on next boot. Reboot now so that any OS we load does not end
- * up relying on the old PCR state. */
- RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ * TPM PCR7 measurements should change on next boot. Reboot/poweroff now so that any OS we load
+ * does not end up relying on the old PCR state.
+ */
+
+ if (action == ENROLL_ACTION_SHUTDOWN) {
+ printf("Custom Secure Boot keys successfully enrolled, powering off the system now!\n");
+ console_key_read(/* ret_key= */ NULL, /* timeout_usec= */ 2 * 1000 * 1000); /* wait a bit so user can see the message */
+ RT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+ } else {
+ assert(action == ENROLL_ACTION_REBOOT);
+ printf("Custom Secure Boot keys successfully enrolled, rebooting the system now!\n");
+ console_key_read(/* ret_key= */ NULL, /* timeout_usec= */ 2 * 1000 * 1000); /* wait a bit so user can see the message */
+ RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
assert_not_reached();
out_deallocate:
@@ -295,4 +305,10 @@ static const char *secure_boot_enroll_table[_SECURE_BOOT_ENROLL_MAX] = {
[ENROLL_FORCE] = "force"
};
+static const char *secure_boot_enroll_action_table[_SECURE_BOOT_ENROLL_ACTION_MAX] = {
+ [ENROLL_ACTION_REBOOT] = "reboot",
+ [ENROLL_ACTION_SHUTDOWN] = "shutdown"
+};
+
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(secure_boot_enroll, secure_boot_enroll);
+DEFINE_STRING_TABLE_LOOKUP_TO_STRING(secure_boot_enroll_action, secure_boot_enroll_action);
diff --git a/src/boot/secure-boot.h b/src/boot/secure-boot.h
index 5349fc039e..da5eccb615 100644
--- a/src/boot/secure-boot.h
+++ b/src/boot/secure-boot.h
@@ -12,10 +12,16 @@ typedef enum {
_SECURE_BOOT_ENROLL_MAX,
} secure_boot_enroll;
+typedef enum {
+ ENROLL_ACTION_REBOOT, /* Reboot the system after enrollment */
+ ENROLL_ACTION_SHUTDOWN, /* Shutdown the system after enrollment */
+ _SECURE_BOOT_ENROLL_ACTION_MAX,
+} secure_boot_enroll_action;
+
bool secure_boot_enabled(void);
SecureBootMode secure_boot_mode(void);
-EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force);
+EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action);
typedef bool (*security_validator_t)(
const void *ctx,
@@ -27,3 +33,4 @@ void install_security_override(security_validator_t validator, const void *valid
void uninstall_security_override(void);
const char* secure_boot_enroll_to_string(secure_boot_enroll e) _const_;
+const char* secure_boot_enroll_action_to_string(secure_boot_enroll_action e) _const_;
diff --git a/tools/command_ignorelist b/tools/command_ignorelist
index fed0bf052d..9408d5a5f9 100644
--- a/tools/command_ignorelist
+++ b/tools/command_ignorelist
@@ -579,3 +579,5 @@ 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"]
+loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="reboot"]
+loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="shutdown"]