File: pci_optrom_blacklist.txt
Syntax: <bus>,<device>,<function> Numbers or a single wildcard ('*') are allowed Each blacklisted device is placed on separate line
Examples: Blacklist device 01:04.0: 1,4,0 Blacklist all devices on bus 5: 5,*,*
TEST: Booted ASUS KFSN4-DRE with iPXE ROMs built in to CBFS; with the two add-on network devices blacklisted the add-on network ROMs were ignored while the on-board iPXE ROMs executed normally.
Signed-off-by: Timothy Pearson tpearson@raptorengineeringinc.com --- src/optionroms.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-)
diff --git a/src/optionroms.c b/src/optionroms.c index fbcb6ca..44967e7 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -1,5 +1,6 @@ // Option rom scanning code. // +// Copyright (C) 2015 Timothy Pearson tpearson@raptorengineeringinc.com // Copyright (C) 2008 Kevin O'Connor kevin@koconnor.net // Copyright (C) 2002 MandrakeSoft S.A. // @@ -346,12 +347,119 @@ init_pcirom(struct pci_device *pci, int isvga, u64 *sources) * Non-VGA option rom init ****************************************************************/
+u8 char_is_digit(const char c) { + if ((c >= '0') && (c <= '9')) + return 1; + else + return 0; +} + +int atoi(const char* c) +{ + int value = 0; + + while (char_is_digit(*c)) { + value *= 10; + value += (int) (*c - '0'); + c++; + } + + return value; +} + +/* 256: Match none + * 257: Match any + */ +struct pci_optrom_blacklist_entry { + u16 bus; + u16 device; + u16 function; +}; + +u8 pci_device_option_rom_is_blacklisted(struct pci_device *pci, struct pci_optrom_blacklist_entry *pci_optrom_blacklist, int pci_optrom_blacklist_count) +{ + if (!pci) + return 0; + + int i; + for (i=0; i<pci_optrom_blacklist_count; i++) { + if ((pci_optrom_blacklist[i].bus == pci_bdf_to_bus(pci->bdf)) || (pci_optrom_blacklist[i].bus == 257)) { + if ((pci_optrom_blacklist[i].device == pci_bdf_to_dev(pci->bdf)) || (pci_optrom_blacklist[i].device == 257)) { + if ((pci_optrom_blacklist[i].function == pci_bdf_to_fn(pci->bdf)) || (pci_optrom_blacklist[i].function == 257)) { + return 1; + } + } + } + } + + return 0; +} + void optionrom_setup(void) { if (! CONFIG_OPTIONROMS) return;
+ struct pci_optrom_blacklist_entry *pci_optrom_blacklist = NULL; + int pci_optrom_blacklist_count = 0; + + dprintf(3, "Checking for PCI option ROM blacklist\n"); + int filesize; + u8 *filedata = romfile_loadfile("pci_optrom_blacklist.txt", &filesize); + if (filedata) { + int i = 0; + while (filedata[i]) { + if (filedata[i] == '\n') + pci_optrom_blacklist_count++; + i++; + } + pci_optrom_blacklist = malloc_tmphigh(sizeof(struct pci_optrom_blacklist_entry) + * pci_optrom_blacklist_count); + int bdf_parse = 0; + int j = 0; + i=0; + u16 value = 0; + pci_optrom_blacklist_count = 0; + char bdf_tmp[4]; + while (filedata[i]) { + if ((j > 3) || (bdf_parse > 2)) { + dprintf(1, "WARNING: Incorrect value in PCI option ROM blacklist\n"); + pci_optrom_blacklist[pci_optrom_blacklist_count].bus = 256; + pci_optrom_blacklist[pci_optrom_blacklist_count].device = 256; + pci_optrom_blacklist[pci_optrom_blacklist_count].function = 256; + } else { + bdf_tmp[j] = filedata[i]; + j++; + if ((filedata[i] == ',') || (filedata[i] == '\n')) { + bdf_tmp[j] = 0; + if (bdf_tmp[0] == '*') + value = 257; + else + value = atoi(bdf_tmp); + if (bdf_parse == 0) + pci_optrom_blacklist[pci_optrom_blacklist_count].bus = value; + if (bdf_parse == 1) + pci_optrom_blacklist[pci_optrom_blacklist_count].device = value; + if (bdf_parse == 2) + pci_optrom_blacklist[pci_optrom_blacklist_count].function = value; + bdf_parse++; + j=0; + } + } + if (filedata[i] == '\n') { + dprintf(3, "PCI device %02x:%02x.%x added to PCI option ROM blacklist\n", + pci_optrom_blacklist[pci_optrom_blacklist_count].bus, + pci_optrom_blacklist[pci_optrom_blacklist_count].device, + pci_optrom_blacklist[pci_optrom_blacklist_count].function); + pci_optrom_blacklist_count++; + bdf_parse=0; + } + i++; + } + free(filedata); + } + dprintf(1, "Scan for option roms\n"); u64 sources[(BUILD_BIOS_ADDR - BUILD_ROM_START) / OPTION_ROM_ALIGN]; memset(sources, 0, sizeof(sources)); @@ -373,13 +481,15 @@ optionrom_setup(void) foreachpci(pci) { if (pci->class == PCI_CLASS_DISPLAY_VGA || pci->have_driver) continue; - init_pcirom(pci, 0, sources); + if (!pci_device_option_rom_is_blacklisted(pci, pci_optrom_blacklist, pci_optrom_blacklist_count)) + init_pcirom(pci, 0, sources); }
// Find and deploy CBFS roms not associated with a device. run_file_roms("genroms/", 0, sources); } rom_reserve(0); + free(pci_optrom_blacklist);
// All option roms found and deployed - now build BEV/BCV vectors.