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:
Jan Janssen
2021-10-17 11:52:36 +02:00
parent 9f04812331
commit 6ae9a5a0bb
2 changed files with 38 additions and 17 deletions
+4 -6
View File
@@ -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
View File
@@ -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))) {