From 6f978cfd1ab6a57e5729e19bed3df7702c4f09cb Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Wed, 19 Apr 2017 18:31:07 -0600 Subject: x86/acpi: Use initialized VBIOS in VFCT table AMD VBIOS option ROMs often modify themselves during initialization. Check for the presence of a VBIOS at 0xc0000 before populating the VFCT table. If a matching ROM is found, use it for the source of the copy. Tested on Gardenia (Stoney) variant by observing amdgpu driver's dmesg output. Change-Id: I5be7e1562bde51800c5b0e704c79812d85bcf362 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/19383 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/device/pci_rom.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c index 20621d36b2..a3f5775a1b 100644 --- a/src/device/pci_rom.c +++ b/src/device/pci_rom.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -172,6 +173,31 @@ struct rom_header *pci_rom_load(struct device *dev, /* ACPI */ #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) + +/* VBIOS may be modified after oprom init so use the copy if present. */ +static struct rom_header *check_initialized(struct device *dev) +{ + struct rom_header *run_rom; + struct pci_data *rom_data; + + if (!IS_ENABLED(CONFIG_VGA_ROM_RUN)) + return NULL; + + run_rom = (struct rom_header *)(uintptr_t)PCI_VGA_RAM_IMAGE_START; + if (read_le16(&run_rom->signature) != PCI_ROM_HDR) + return NULL; + + rom_data = (struct pci_data *)((u8 *)run_rom + + read_le32(&run_rom->data)); + + if (read_le32(&rom_data->signature) == PCI_DATA_HDR + && read_le16(&rom_data->device) == dev->device + && read_le16(&rom_data->vendor) == dev->vendor) + return run_rom; + else + return NULL; +} + static unsigned long pci_rom_acpi_fill_vfct(struct device *device, struct acpi_vfct *vfct_struct, @@ -182,12 +208,20 @@ pci_rom_acpi_fill_vfct(struct device *device, vfct_struct->VBIOSImageOffset = (size_t)header - (size_t)vfct_struct; - rom = pci_rom_probe(device); + rom = check_initialized(device); + if (!rom) + rom = pci_rom_probe(device); if (!rom) { printk(BIOS_ERR, "pci_rom_acpi_fill_vfct failed\n"); return current; } + printk(BIOS_DEBUG, " Copying %sVBIOS image from %p\n", + rom == (struct rom_header *) + (uintptr_t)PCI_VGA_RAM_IMAGE_START ? + "initialized " : "", + rom); + header->DeviceID = device->device; header->VendorID = device->vendor; header->PCIBus = device->bus->secondary; @@ -224,7 +258,7 @@ pci_rom_write_acpi_tables(struct device *device, /* AMD/ATI uses VFCT */ if (device->vendor == PCI_VENDOR_ID_ATI) { current = ALIGN(current, 8); - printk(BIOS_DEBUG, "ACPI: * VFCT at %lx\n", current); + printk(BIOS_DEBUG, "ACPI: * VFCT at %lx\n", current); vfct = (struct acpi_vfct *)current; acpi_create_vfct(device, vfct, pci_rom_acpi_fill_vfct); current += vfct->header.length; -- cgit v1.2.3