Tweak setting of boot timeout variables (#40125)

This commit is contained in:
Yu Watanabe
2026-01-05 06:50:49 +09:00
committed by GitHub
+44 -24
View File
@@ -15,51 +15,71 @@
#include "virt.h"
static int parse_timeout(const char *arg1, char16_t **ret_timeout, size_t *ret_timeout_size) {
char utf8[DECIMAL_STR_MAX(usec_t)];
char16_t *encoded;
char buf[DECIMAL_STR_MAX(usec_t)];
usec_t timeout;
bool menu_disabled = false;
uint64_t loader_features = 0;
int r;
assert(arg1);
assert(ret_timeout);
assert(ret_timeout_size);
assert_cc(STRLEN("menu-disabled") < ELEMENTSOF(utf8));
assert_cc(STRLEN("menu-force") < ELEMENTSOF(buf));
assert_cc(STRLEN("menu-hidden") < ELEMENTSOF(buf));
assert_cc(STRLEN("menu-disabled") < ELEMENTSOF(buf));
/* Note: Since there is no way to query if the bootloader supports the string tokens, we explicitly
* set their numerical value(s) instead. This means that some of the sd-boot internal ABI has leaked
* although the ship has sailed and the side-effects are self-contained.
/* Use feature EFI_LOADER_FEATURE_MENU_DISABLE as a mark that the boot loader supports the other
* string values too. When unsupported, convert to the timeout with the closest meaning.
*/
if (streq(arg1, "menu-force"))
timeout = USEC_INFINITY;
else if (streq(arg1, "menu-hidden"))
timeout = 0;
else if (streq(arg1, "menu-disabled")) {
uint64_t loader_features = 0;
if (streq(arg1, "menu-force")) {
(void) efi_loader_get_features(&loader_features);
if (!(loader_features & EFI_LOADER_FEATURE_MENU_DISABLE)) {
log_debug("Using maximum timeout instead of '%s'.", arg1);
timeout = USEC_INFINITY;
arg1 = NULL;
}
} else if (streq(arg1, "menu-hidden")) {
(void) efi_loader_get_features(&loader_features);
if (!(loader_features & EFI_LOADER_FEATURE_MENU_DISABLE)) {
log_debug("Using zero timeout instead of '%s'.", arg1);
timeout = 0;
arg1 = NULL; /* replace the arg by printed timeout value later */
}
} else if (streq(arg1, "menu-disabled")) {
(void) efi_loader_get_features(&loader_features);
if (!(loader_features & EFI_LOADER_FEATURE_MENU_DISABLE)) {
if (arg_graceful() == ARG_GRACEFUL_NO)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Loader does not support 'menu-disabled'.");
log_warning("Loader does not support 'menu-disabled', setting anyway.");
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Loader does not support '%s'.", arg1);
log_warning("Using zero timeout instead of '%s'.", arg1);
timeout = 0;
arg1 = NULL;
}
menu_disabled = true;
} else {
r = parse_time(arg1, &timeout, USEC_PER_SEC);
if (r < 0)
return log_error_errno(r, "Failed to parse timeout '%s': %m", arg1);
if (timeout != USEC_INFINITY && timeout > UINT32_MAX * USEC_PER_SEC)
log_warning("Timeout is too long and will be treated as 'menu-force' instead.");
assert_cc(USEC_INFINITY > UINT32_MAX * USEC_PER_SEC);
if (timeout > UINT32_MAX * USEC_PER_SEC && timeout != USEC_INFINITY)
log_debug("Timeout is too long and will be clamped to maximum timeout.");
arg1 = NULL;
}
if (menu_disabled)
xsprintf(utf8, "menu-disabled");
else
xsprintf(utf8, USEC_FMT, MIN(timeout / USEC_PER_SEC, UINT32_MAX));
if (!arg1) {
timeout = DIV_ROUND_UP(timeout, USEC_PER_SEC);
xsprintf(buf, USEC_FMT, MIN(timeout, UINT32_MAX));
}
encoded = utf8_to_utf16(utf8, SIZE_MAX);
char16_t *encoded = utf8_to_utf16(arg1 ?: buf, SIZE_MAX);
if (!encoded)
return log_oom();