#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)) {
- if (arg_graceful() == ARG_GRACEFUL_NO)
- return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Loader does not support 'menu-disabled'.");
+ 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);
- log_warning("Loader does not support 'menu-disabled', setting anyway.");
+ 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 */
}
- menu_disabled = true;
+
+ } 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 '%s'.", arg1);
+ log_warning("Using zero timeout instead of '%s'.", arg1);
+ timeout = 0;
+ arg1 = NULL;
+ }
+
} 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)
+ xsprintf(buf, USEC_FMT, MIN(timeout / USEC_PER_SEC, UINT32_MAX));
- encoded = utf8_to_utf16(utf8, SIZE_MAX);
+ char16_t *encoded = utf8_to_utf16(arg1 ?: buf, SIZE_MAX);
if (!encoded)
return log_oom();