From: Christian Storm <[email protected]> Refactor the watchdog probing in terms of (1) renaming scan_devices() to probe_watchdogs(), and (2) replacing the static upper-bounded PCI device enumeration with a dynamic one based on EFI's LocateHandleBuffer().
Signed-off-by: Christian Storm <[email protected]> --- main.c | 105 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/main.c b/main.c index 0bec838..b11c5fb 100644 --- a/main.c +++ b/main.c @@ -27,72 +27,75 @@ extern const unsigned long init_array_start[]; extern const unsigned long init_array_end[]; extern CHAR16 *boot_medium_path; -static EFI_STATUS probe_watchdog(EFI_LOADED_IMAGE *loaded_image, - EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, - UINT16 pci_device_id, UINTN timeout) -{ - const unsigned long *entry; - - for (entry = init_array_start; entry < init_array_end; entry++) { - EFI_STATUS (*probe)(EFI_PCI_IO *, UINT16, UINT16, UINTN); - - probe = loaded_image->ImageBase + *entry; - if (probe(pci_io, pci_vendor_id, pci_device_id, timeout) == - EFI_SUCCESS) { - return EFI_SUCCESS; - } - } +#define PCI_GET_VENDOR_ID(id) id +#define PCI_GET_PRODUCT_ID(id) id >> 16 - return EFI_UNSUPPORTED; -} - -static EFI_STATUS scan_devices(EFI_LOADED_IMAGE *loaded_image, UINTN timeout) +static EFI_STATUS probe_watchdogs(EFI_LOADED_IMAGE *loaded_image, UINTN timeout) { - EFI_HANDLE devices[1000]; - UINTN count, size = sizeof(devices); - EFI_PCI_IO *pci_io; - EFI_STATUS status; - UINT32 value; - - status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, - &PciIoProtocol, NULL, &size, devices); - if (EFI_ERROR(status)) { - return status; + if (init_array_end - init_array_start == 0) { + WARNING(L"No watchdog drivers registered.\n"); + return EFI_NOT_FOUND; } - count = size / sizeof(EFI_HANDLE); - if (count == 0) { - return probe_watchdog(loaded_image, NULL, 0, 0, timeout); + UINTN handle_count = 0; + EFI_HANDLE *handle_buffer = NULL; + EFI_STATUS status = uefi_call_wrapper(BS->LocateHandleBuffer, 5, + ByProtocol, &PciIoProtocol, NULL, + &handle_count, &handle_buffer); + if (EFI_ERROR(status) || (handle_count == 0)) { + WARNING(L"No PCI I/O Protocol handles found.\n"); + if (handle_buffer) { + FreePool(handle_buffer); + } + return EFI_UNSUPPORTED; } - do { - EFI_HANDLE device = devices[count - 1]; - - count--; - - status = uefi_call_wrapper(BS->OpenProtocol, 6, device, - &PciIoProtocol, (VOID **)&pci_io, - this_image, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); + EFI_PCI_IO_PROTOCOL *pci_io; + UINT32 value; + for (UINTN index = 0; index < handle_count; index++) { + status = uefi_call_wrapper(BS->OpenProtocol, 6, + handle_buffer[index], &PciIoProtocol, + (VOID **)&pci_io, this_image, NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); if (EFI_ERROR(status)) { - error_exit(L"Cannot open PciIoProtocol while probing watchdogs", - status); + ERROR(L"Cannot not open PciIoProtocol: %r\n", status); + FreePool(handle_buffer); + return status; } status = uefi_call_wrapper(pci_io->Pci.Read, 5, pci_io, EfiPciIoWidthUint32, PCI_VENDOR_ID, 1, &value); if (EFI_ERROR(status)) { - error_exit(L"Cannot read from PCI device while probing watchdogs", - status); + WARNING( + L"Cannot not read from PCI device, skipping: %r\n", + status); + (VOID) uefi_call_wrapper( + BS->CloseProtocol, 4, handle_buffer[index], + &PciIoProtocol, this_image, NULL); + continue; } - status = probe_watchdog(loaded_image, pci_io, (UINT16)value, - value >> 16, timeout); + EFI_STATUS (*probe)(EFI_PCI_IO *, UINT16, UINT16, UINTN); + for (const unsigned long *entry = init_array_start; + entry < init_array_end; entry++) { + probe = loaded_image->ImageBase + *entry; + if ((status = probe(pci_io, PCI_GET_VENDOR_ID(value), + PCI_GET_PRODUCT_ID(value), + timeout)) == EFI_SUCCESS) { + break; + } + } + + (VOID) uefi_call_wrapper(BS->CloseProtocol, 4, + handle_buffer[index], &PciIoProtocol, + this_image, NULL); - uefi_call_wrapper(BS->CloseProtocol, 4, device, &PciIoProtocol, - this_image, NULL); - } while (status != EFI_SUCCESS && count > 0); + if (status == EFI_SUCCESS) { + break; + } + } + FreePool(handle_buffer); return status; } @@ -168,7 +171,7 @@ EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) if (bg_loader_params.timeout == 0) { WARNING(L"Watchdog is disabled.\n"); } else { - status = scan_devices(loaded_image, bg_loader_params.timeout); + status = probe_watchdogs(loaded_image, bg_loader_params.timeout); if (EFI_ERROR(status)) { error_exit(L"Cannot probe watchdog", status); } -- 2.33.0 -- You received this message because you are subscribed to the Google Groups "EFI Boot Guard" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/efibootguard-dev/20210824140714.368156-1-christian.storm%40siemens.com.
