From 1dc5ce31ced5baee363f6d30049ca418ce414866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Sat, 9 Jun 2018 08:25:03 +0300 Subject: [PATCH] coreinfo: Skip unpopulated PCI functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per PCI specification, function 0 must be present, so functions 1 to 7 can be skipped in this case. For a device that is not multi-function, it may not decode function number in the hardware at all. To avoid registering such a device eight times, skip scanning functions 1 to 7. Without the latter fix, a single-function PCI bridge may call pci_scan_bus() second time and secondary side devices would get appended second time in the array devices[]. At that point, quicksort() apparently hits an infinite recursion loop. Since pci_scan_bus() is called in part of the early modules->init() sequence early in main(), the errors here left coreinfo payload completely silent when PCI module was built-in on affected system. Terminal screen was cleared, though. Change-Id: Ifc6622f050b98afb7196de0cc3a863c4cdfa6c94 Signed-off-by: Kyösti Mälkki Reviewed-on: https://review.coreboot.org/26990 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- payloads/coreinfo/pci_module.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/payloads/coreinfo/pci_module.c b/payloads/coreinfo/pci_module.c index f79d543d5e..9f10b12703 100644 --- a/payloads/coreinfo/pci_module.c +++ b/payloads/coreinfo/pci_module.c @@ -183,8 +183,14 @@ static void pci_scan_bus(int bus) /* Nobody home. */ if (val == 0xffffffff || val == 0x00000000 || - val == 0x0000ffff || val == 0xffff0000) + val == 0x0000ffff || val == 0xffff0000) { + + /* If function 0 is not present, no need + * to test other functions. */ + if (func == 0) + func = 8; continue; + } /* FIXME: Remove this arbitrary limitation. */ if (devices_index >= MAX_PCI_DEVICES) @@ -197,7 +203,11 @@ static void pci_scan_bus(int bus) /* If this is a bridge, then follow it. */ hdr = pci_read_config8(dev, REG_HEADER_TYPE); - hdr &= 0x7f; + + if ((func == 0) && !(hdr & HEADER_TYPE_MULTIFUNCTION)) + func = 8; + + hdr &= ~HEADER_TYPE_MULTIFUNCTION; if (hdr == HEADER_TYPE_BRIDGE || hdr == HEADER_TYPE_CARDBUS) { unsigned int busses;