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)
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;
entry->path, entry->next_name);
Print(L"\n--- press key ---\n\n");
- console_key_read(&key, 0);
+ console_key_read(&key, UINT64_MAX);
}
}
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) {
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;
}
/* 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);
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))) {