lib/bli: implement timeout control

This commit is contained in:
programmerlexi
2026-04-11 18:57:50 +02:00
committed by Mintsuki
parent 9c3ead9386
commit bc5d1e4b8f
3 changed files with 98 additions and 6 deletions

View File

@@ -41,6 +41,28 @@ void uint64_to_decwstr(uint64_t value, wchar_t *buf) {
buf[i] = '\0';
}
bool decwstr_to_size(const wchar_t *buf, size_t buf_size, size_t *value) {
size_t i = 0;
size_t tmp = 0;
if (buf == NULL) {
return false;
}
while (i * 2 < buf_size && buf[i]) {
wchar_t c = buf[i];
if (!(c >= L'0' && c <= L'9')) {
return false;
}
tmp = tmp * 10 + (c - L'0');
i++;
}
*value = tmp;
return true;
}
void bli_set_loader_time(wchar_t *variable, uint64_t time) {
if (time == 0)
return;
@@ -67,6 +89,15 @@ void init_bli(void) {
sizeof(LIMINE_BRAND),
LIMINE_BRAND);
uint64_t features = (1 << 0) | // Timeout control
(1 << 1) | // Oneshot timeout control
(1 << 13); // menu-disabled support
gRT->SetVariable(L"LoaderFeatures",
&bli_vendor_guid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(features),
&features);
char part_uuid_str[37];
guid_to_string(&boot_volume->part_guid, part_uuid_str);
@@ -87,4 +118,46 @@ void bli_on_boot(void) {
bli_set_loader_time(L"LoaderTimeExecUSec", rdtsc_usec());
}
static bool handle_timeout(wchar_t *variable, bool erase, size_t *timeout, bool *skip_timeout) {
wchar_t timeout_buf[256];
UINTN getvar_size = sizeof(timeout_buf) - 2;
uint32_t attrs;
if (gRT->GetVariable(variable,
&bli_vendor_guid,
&attrs,
&getvar_size,
timeout_buf) == 0 && getvar_size > 0) {
if (erase) {
gRT->SetVariable(variable, &bli_vendor_guid,
attrs,
0, NULL);
}
if (getvar_size == 24 && memcmp(timeout_buf, L"menu-force",24) == 0) {
*skip_timeout = true;
return true;
}
if ((getvar_size == 24 && memcmp(timeout_buf, L"menu-hidden",24) == 0) || (getvar_size == 28 && memcmp(timeout_buf, L"menu-disabled",28) == 0)) {
// TODO: menu-hidden should enable quiet & set timeout >= 1
*timeout = 0;
return true;
}
size_t t;
if (!decwstr_to_size(timeout_buf, getvar_size, &t)) {
return false;
}
*timeout = t;
return true;
}
return false;
}
bool bli_update_oneshot_timeout(size_t *timeout, bool *skip_timeout) {
return handle_timeout(L"LoaderConfigTimeoutOneShot", true, timeout, skip_timeout);
}
bool bli_update_timeout(size_t *timeout, bool *skip_timeout) {
return handle_timeout(L"LoaderConfigTimeout", false, timeout, skip_timeout);
}
#endif

View File

@@ -5,6 +5,8 @@
void init_bli(void);
void bli_on_boot(void);
bool bli_update_oneshot_timeout(size_t *timeout, bool *skip_timeout);
bool bli_update_timeout(size_t *timeout, bool *skip_timeout);
#endif

View File

@@ -4,6 +4,7 @@
#include <stdnoreturn.h>
#include <config.h>
#include <menu.h>
#include <lib/bli.h>
#include <lib/print.h>
#include <lib/misc.h>
#include <lib/libc.h>
@@ -1187,14 +1188,30 @@ noreturn void _menu(bool first_run) {
}
size_t timeout = 5;
char *timeout_config = config_get_value(NULL, 0, "TIMEOUT");
if (timeout_config != NULL) {
if (!strcmp(timeout_config, "no"))
skip_timeout = true;
else
timeout = strtoui(timeout_config, NULL, 10);
bool has_timeout = false;
#if defined (UEFI)
has_timeout = bli_update_oneshot_timeout(&timeout, &skip_timeout);
#endif
if (!has_timeout) {
char *timeout_config = config_get_value(NULL, 0, "TIMEOUT");
if (timeout_config != NULL) {
has_timeout = true;
if (!strcmp(timeout_config, "no"))
skip_timeout = true;
else
timeout = strtoui(timeout_config, NULL, 10);
}
}
#if defined (UEFI)
if (!has_timeout) {
has_timeout = bli_update_timeout(&timeout, &skip_timeout);
}
#endif
#if defined(UEFI)
bool reboot_to_firmware_supported = reboot_to_fw_ui_supported();
#endif