sd-boot: Rearm the watchdog in console_key_read
Let's not disable the watchdog at all and instead rearm it inside of console_key_read(). This way, we are covered by the watchdog everywhere.
This commit is contained in:
+4
-6
@@ -449,7 +449,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
Print(L"OsIndicationsSupported: %d\n", get_os_indications_supported());
|
||||
|
||||
Print(L"\n--- press key ---\n\n");
|
||||
console_key_read(&key, 0);
|
||||
console_key_read(&key, UINT64_MAX);
|
||||
|
||||
Print(L"timeout: %u s\n", config->timeout_sec);
|
||||
if (config->timeout_sec_efivar != TIMEOUT_UNSET)
|
||||
@@ -495,7 +495,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
Print(L"LoaderEntryDefault: %s\n", defaultstr);
|
||||
|
||||
Print(L"\n--- press key ---\n\n");
|
||||
console_key_read(&key, 0);
|
||||
console_key_read(&key, UINT64_MAX);
|
||||
|
||||
for (UINTN i = 0; i < config->entry_count; i++) {
|
||||
ConfigEntry *entry;
|
||||
@@ -547,7 +547,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
entry->path, entry->next_name);
|
||||
|
||||
Print(L"\n--- press key ---\n\n");
|
||||
console_key_read(&key, 0);
|
||||
console_key_read(&key, UINT64_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@ static BOOLEAN menu_run(
|
||||
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len);
|
||||
}
|
||||
|
||||
err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : 0);
|
||||
err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : UINT64_MAX);
|
||||
if (err == EFI_TIMEOUT) {
|
||||
timeout_remain--;
|
||||
if (timeout_remain == 0) {
|
||||
@@ -2413,7 +2413,6 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
entry = config.entries[config.idx_default];
|
||||
if (menu) {
|
||||
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeMenuUSec", 0);
|
||||
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x10000, 0, NULL);
|
||||
if (!menu_run(&config, &entry, loaded_image_path))
|
||||
break;
|
||||
}
|
||||
@@ -2432,7 +2431,6 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
/* Optionally, read a random seed off the ESP and pass it to the OS */
|
||||
(VOID) process_random_seed(root_dir, config.random_seed_mode);
|
||||
|
||||
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 5 * 60, 0x10000, 0, NULL);
|
||||
err = image_start(root_dir, image, &config, entry);
|
||||
if (EFI_ERROR(err)) {
|
||||
graphics_mode(FALSE);
|
||||
|
||||
+34
-11
@@ -62,25 +62,48 @@ EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
|
||||
checked = TRUE;
|
||||
}
|
||||
|
||||
if (timeout_usec > 0) {
|
||||
err = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &timer);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Error creating timer event: %r", err);
|
||||
err = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &timer);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Error creating timer event: %r", err);
|
||||
events[n_events++] = timer;
|
||||
|
||||
/* Watchdog rearming loop in case the user never provides us with input or some
|
||||
* broken firmware never returns from WaitForEvent. */
|
||||
for (;;) {
|
||||
UINT64 watchdog_timeout_sec = 5 * 60,
|
||||
watchdog_ping_usec = watchdog_timeout_sec / 2 * 1000 * 1000;
|
||||
|
||||
/* SetTimer expects 100ns units for some reason. */
|
||||
err = uefi_call_wrapper(BS->SetTimer, 3, timer, TimerRelative, timeout_usec * 10);
|
||||
err = uefi_call_wrapper(
|
||||
BS->SetTimer, 3,
|
||||
timer,
|
||||
TimerRelative,
|
||||
MIN(timeout_usec, watchdog_ping_usec) * 10);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Error arming timer event: %r", err);
|
||||
|
||||
events[n_events++] = timer;
|
||||
}
|
||||
(void) uefi_call_wrapper(BS->SetWatchdogTimer, 4, watchdog_timeout_sec, 0x10000, 0, NULL);
|
||||
err = uefi_call_wrapper(BS->WaitForEvent, 3, n_events, events, &index);
|
||||
(void) uefi_call_wrapper(BS->SetWatchdogTimer, 4, watchdog_timeout_sec, 0x10000, 0, NULL);
|
||||
|
||||
err = uefi_call_wrapper(BS->WaitForEvent, 3, n_events, events, &index);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Error waiting for events: %r", err);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Error waiting for events: %r", err);
|
||||
|
||||
if (timeout_usec > 0 && timer == events[index])
|
||||
/* We have keyboard input, process it after this loop. */
|
||||
if (timer != events[index])
|
||||
break;
|
||||
|
||||
/* The EFI timer fired instead. If this was a watchdog timeout, loop again. */
|
||||
if (timeout_usec == UINT64_MAX)
|
||||
continue;
|
||||
else if (timeout_usec > watchdog_ping_usec) {
|
||||
timeout_usec -= watchdog_ping_usec;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The caller requested a timeout? They shall have one! */
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
/* TextInputEx might be ready too even if ConIn got to signal first. */
|
||||
if (TextInputEx && !EFI_ERROR(uefi_call_wrapper(BS->CheckEvent, 1, TextInputEx->WaitForKeyEx))) {
|
||||
|
||||
Reference in New Issue
Block a user