diff options
author | Jan Janssen <medhefgo@web.de> | 2022-09-06 10:46:27 +0200 |
---|---|---|
committer | Jan Janssen <medhefgo@web.de> | 2022-09-07 12:55:55 +0200 |
commit | 97f077df052c75224dcc73375bfaaa69af6a1c26 (patch) | |
tree | e6b284581b54cc4501b4820b61b16f5285e19d92 | |
parent | boot: Use proper scan codes (diff) | |
download | systemd-97f077df052c75224dcc73375bfaaa69af6a1c26.tar.xz systemd-97f077df052c75224dcc73375bfaaa69af6a1c26.zip |
boot: Avoid magic values in timeout EFI vars
-rw-r--r-- | docs/BOOT_LOADER_INTERFACE.md | 6 | ||||
-rw-r--r-- | src/boot/efi/boot.c | 55 |
2 files changed, 51 insertions, 10 deletions
diff --git a/docs/BOOT_LOADER_INTERFACE.md b/docs/BOOT_LOADER_INTERFACE.md index f7be50421c..fc9336085b 100644 --- a/docs/BOOT_LOADER_INTERFACE.md +++ b/docs/BOOT_LOADER_INTERFACE.md @@ -31,7 +31,11 @@ variables. All EFI variables use the vendor UUID * The EFI variable `LoaderConfigTimeout` contains the boot menu timeout currently in use. It may be modified both by the boot loader and by the host. The value should be formatted as numeric, NUL-terminated, decimal - string, in UTF-16. The time is specified in µs. + string, in UTF-16. The time is specified in seconds. A value of `menu-force` + will disable the timeout and show the menu indefinitely. If set to `0` or + `menu-hidden` the default entry is booted immediately without showing a menu. + The boot loader should provide a way to interrupt this by for example + listening for key presses for a brief moment before booting. * Similarly, the EFI variable `LoaderConfigTimeoutOneShot` contains a boot menu timeout for a single following boot. It is set by the OS in order to request diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index ac08650c29..a7ef57cb99 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -1037,11 +1037,20 @@ static bool menu_run( } if (timeout_efivar_saved != config->timeout_sec_efivar) { - if (config->timeout_sec_efivar == TIMEOUT_UNSET) + switch (config->timeout_sec_efivar) { + case TIMEOUT_UNSET: efivar_set(LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE); - else + break; + case TIMEOUT_MENU_FORCE: + efivar_set(LOADER_GUID, u"LoaderConfigTimeout", u"menu-force", EFI_VARIABLE_NON_VOLATILE); + break; + case TIMEOUT_MENU_HIDDEN: + efivar_set(LOADER_GUID, u"LoaderConfigTimeout", u"menu-hidden", EFI_VARIABLE_NON_VOLATILE); + break; + default: efivar_set_uint_string(LOADER_GUID, L"LoaderConfigTimeout", config->timeout_sec_efivar, EFI_VARIABLE_NON_VOLATILE); + } } clear_screen(COLOR_NORMAL); @@ -1532,6 +1541,34 @@ static void config_entry_add_type1( TAKE_PTR(entry); } +static EFI_STATUS efivar_get_timeout(const char16_t *var, uint32_t *ret_value) { + _cleanup_free_ char16_t *value = NULL; + EFI_STATUS err; + + assert(var); + assert(ret_value); + + err = efivar_get(LOADER_GUID, var, &value); + if (err != EFI_SUCCESS) + return err; + + if (streq16(value, u"menu-force")) { + *ret_value = TIMEOUT_MENU_FORCE; + return EFI_SUCCESS; + } + if (streq16(value, u"menu-hidden")) { + *ret_value = TIMEOUT_MENU_HIDDEN; + return EFI_SUCCESS; + } + + uint64_t timeout; + if (!parse_number16(value, &timeout, NULL)) + return EFI_INVALID_PARAMETER; + + *ret_value = MIN(timeout, TIMEOUT_TYPE_MAX); + return EFI_SUCCESS; +} + static void config_load_defaults(Config *config, EFI_FILE *root_dir) { _cleanup_free_ char *content = NULL; UINTN value; @@ -1557,20 +1594,20 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { if (err == EFI_SUCCESS) config_defaults_load_from_file(config, content); - err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &value); - if (err == EFI_SUCCESS) { - config->timeout_sec_efivar = MIN(value, TIMEOUT_TYPE_MAX); + err = efivar_get_timeout(u"LoaderConfigTimeout", &config->timeout_sec_efivar); + if (err == EFI_SUCCESS) config->timeout_sec = config->timeout_sec_efivar; - } + else if (err != EFI_NOT_FOUND) + log_error_stall(u"Error reading LoaderConfigTimeout EFI variable: %r", err); - err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &value); + err = efivar_get_timeout(u"LoaderConfigTimeoutOneShot", &config->timeout_sec); if (err == EFI_SUCCESS) { /* Unset variable now, after all it's "one shot". */ (void) efivar_set(LOADER_GUID, L"LoaderConfigTimeoutOneShot", NULL, EFI_VARIABLE_NON_VOLATILE); - config->timeout_sec = MIN(value, TIMEOUT_TYPE_MAX); config->force_menu = true; /* force the menu when this is set */ - } + } else if (err != EFI_NOT_FOUND) + log_error_stall(u"Error reading LoaderConfigTimeoutOneShot EFI variable: %r", err); err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value); if (err == EFI_SUCCESS) |