Tweak setting of boot timeout variables (#40125)
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user