Kyösti Mälkki has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/48828 )
Change subject: device/pci: Add early PCI dump ......................................................................
device/pci: Add early PCI dump
Change-Id: Ic095213ab51a3c29af462782fdb75cfcd409714f Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- M src/device/Makefile.inc A src/device/pci_dump.c M src/include/device/pci.h 3 files changed, 117 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/28/48828/1
diff --git a/src/device/Makefile.inc b/src/device/Makefile.inc index bb125af..85c1324 100644 --- a/src/device/Makefile.inc +++ b/src/device/Makefile.inc @@ -35,6 +35,9 @@ ramstage-y += pci_ops.c smm-y += pci_ops.c
+romstage-y += pci_dump.c +ramstage-y += pci_dump.c + ramstage-$(CONFIG_PCIX_PLUGIN_SUPPORT) += pcix_device.c ramstage-$(CONFIG_PCIEXP_PLUGIN_SUPPORT) += pciexp_device.c ramstage-$(CONFIG_CARDBUS_PLUGIN_SUPPORT) += cardbus_device.c diff --git a/src/device/pci_dump.c b/src/device/pci_dump.c new file mode 100644 index 0000000..737b782 --- /dev/null +++ b/src/device/pci_dump.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + + +#include <console/console.h> +#include <device/pci_ops.h> +#include <device/pci_def.h> +#include <stdint.h> +#include <device/device.h> +#include <device/pci.h> + +/* Output is in format of lspci -nxxxx so that lspci -F can parse it. */ +static int pci_s_dump_and_probe(pci_devfn_t bdf, uint8_t *last_bus) +{ + /* FIXME: Should use some macros here. */ + uint8_t bus = (bdf >> 20) & 0xff; + uint8_t dev = (bdf >> 15) & 0x1f; + uint8_t fn = (bdf >> 12) & 0x7; + + int i, j; + int ret = 0; + + uint32_t didvid, classrev; + uint8_t htype; + union { + uint8_t r8[16]; + uint16_t r16[8]; + uint32_t r32[4]; + } cfgdump; + + didvid = pci_s_read_config32(bdf, PCI_VENDOR_ID); + if (didvid == (uint32_t)-1ull) + return (fn == 0) ? -1 : 0; + + htype = pci_s_read_config8(bdf, PCI_HEADER_TYPE); + if ((fn == 0) && !(htype & 0x80)) + ret = -1; + htype &= ~0x80; + + classrev = pci_s_read_config32(bdf, PCI_CLASS_REVISION); + printk(BIOS_DEBUG, "%02x:%02x.%x %04x: (%04x:%04x) (rev %02x)\n", + bus, dev, fn, classrev >> 16, + didvid & 0xffff, didvid >> 16, classrev & 0xff); + + int max_reg = CONFIG(MMCONF_SUPPORT) ? 4096 : 256; + for (i = 0; i < max_reg / 16; i++) { + int non_zero = 0; + for (j = 0; j < 16; j += sizeof(uint32_t)) { + cfgdump.r32[j / sizeof(uint32_t)] = pci_s_read_config32(bdf, 16 * i + j); + if (cfgdump.r32[j / sizeof(uint32_t)]) + non_zero++; + } + + /* Standard 64 header is always printed, other lines only + if they are not all zeroes. */ + if ((i < 4) || non_zero) { + printk(BIOS_DEBUG, "%02x:", 16 * i); + for (j = 0; j < 16; j++) + printk(BIOS_DEBUG, " %02x", cfgdump.r8[j]); + printk(BIOS_DEBUG, "\n"); + } + } + printk(BIOS_DEBUG, "\n"); + + if (htype == PCI_HEADER_TYPE_BRIDGE) { + uint8_t bsec = pci_s_read_config8(bdf, PCI_SECONDARY_BUS); + uint8_t bsub = pci_s_read_config8(bdf, PCI_SUBORDINATE_BUS); + if ((bsub >= bsec) && (bsub > *last_bus)) + *last_bus = bsub; + } + return ret; +} + +void pci_s_dump_one(pci_devfn_t bdf) +{ + uint8_t dummy_pci_bus; + + printk(BIOS_DEBUG, "** PCI_DUMP START **\n"); + pci_s_dump_and_probe(bdf, &dummy_pci_bus); + printk(BIOS_DEBUG, "** PCI_DUMP END **\n"); +} + +void pci_dump_one(struct device *dev) +{ + pci_s_dump_one(PCI_BDF(dev)); +} + +void pci_dump_all(void) +{ + uint8_t bus, dev, fn; + uint8_t last_pci_bus = 0; + pci_devfn_t bdf; + + printk(BIOS_DEBUG, "** PCI_DUMP START **\n"); + for (bus = 0; bus <= last_pci_bus; bus++) { + for (dev = 0; dev <= 31; dev++) { + for (fn = 0; fn <= 7; fn++) { + bdf = PCI_DEV(bus, dev, fn); + if (pci_s_dump_and_probe(bdf, &last_pci_bus) < 0) + fn = 7; + } + } + } + printk(BIOS_DEBUG, "** PCI_DUMP END **\n"); +} + +void pci_dump_final(struct device *unused) +{ + pci_dump_all(); +} diff --git a/src/include/device/pci.h b/src/include/device/pci.h index 045eec1..3df64d4 100644 --- a/src/include/device/pci.h +++ b/src/include/device/pci.h @@ -106,6 +106,11 @@ int pci_msix_table_bar(struct device *dev, u32 *offset, u8 *idx); struct msix_entry *pci_msix_get_table(struct device *dev);
+void pci_s_dump_one(pci_devfn_t bdf); +void pci_dump_one(struct device *dev); +void pci_dump_all(void); +void pci_dump_final(struct device *dev); + #define PCI_IO_BRIDGE_ALIGN 4096 #define PCI_MEM_BRIDGE_ALIGN (1024*1024)