lib/bli: implement timeout control
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user