PCI Firmware Specification v3.0 defined a new optional device list,
allowing a single optionrom to handle several device IDs. Add support
for this list when looking for an optionrom for a PCI device.
Signed-off-by: Daniel Verkamp <daniel(a)drv.nu>
---
src/optionroms.c | 33 ++++++++++++++++++++++++++++-----
src/optionroms.h | 2 +-
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/src/optionroms.c b/src/optionroms.c
index 00697b2..0023d90 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -292,19 +292,42 @@ map_pcirom(struct pci_device *pci)
goto fail;
}
- if (pd->vendor == pci->vendor && pd->device == pci->device
- && pd->type == PCIROM_CODETYPE_X86)
- // A match
- break;
+ void *nextrom = (void*)((u32)rom + pd->ilen * 512);
+
+ if (pd->vendor == pci->vendor && pd->type == PCIROM_CODETYPE_X86)
+ {
+ if (pd->device == pci->device)
+ {
+ dprintf(6, "Matched device in PCI header\n");
+ goto found;
+ }
+
+ // PCI header device ID did not match, but vendor ID did
+ // search device list if available
+ if (pd->drevision >= 3 && pd->devicelist) {
+ u16 *devicelist = (u16*)((u32)pd + pd->devicelist);
+ dprintf(6, "Searching PCIv3 device ID list at %p\n", devicelist);
+ while (devicelist < (u16*)nextrom && *devicelist) {
+ dprintf(6, "Dev list entry: %04x\n", *devicelist);
+ if (*devicelist == pci->device) {
+ dprintf(6, "Matched device in PCIv3 device list\n");
+ goto found;
+ }
+ devicelist++;
+ }
+ dprintf(6, "Didn't match device ID list\n");
+ }
+ }
dprintf(6, "Didn't match dev/ven (got %04x:%04x) or type (got %d)\n"
, pd->vendor, pd->device, pd->type);
if (pd->indicator & 0x80) {
dprintf(6, "No more images left\n");
goto fail;
}
- rom = (void*)((u32)rom + pd->ilen * 512);
+ rom = nextrom;
}
+found:
rom = copy_rom(rom);
pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
return rom;
diff --git a/src/optionroms.h b/src/optionroms.h
index 94ca4ae..487ea45 100644
--- a/src/optionroms.h
+++ b/src/optionroms.h
@@ -20,7 +20,7 @@ struct pci_data {
u32 signature;
u16 vendor;
u16 device;
- u16 vitaldata;
+ u16 devicelist;
u16 dlen;
u8 drevision;
u8 class_lo;
--
1.7.8.6