From 85e503e6416e14e357e021632a6ae48d2cf8b208 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Tue, 11 Feb 2025 14:53:55 +0100 Subject: [PATCH] device/pci_rom: Keep track of VBIOS Currently the VBIOS is placed somewhere in DRAM when necessary. While generating ACPI tables the code attempts to find the VBIOS by looking at "known" places. Simplify the code and keep track of the VBIOS using a pointer in struct device by filling it in pci_rom_load(). The following patches will reuse this pointer to generalize the code even more. Change-Id: Ib27d30e3b07740d6098d4f7a5c4f5d8bce976f00 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/86385 Reviewed-by: Angel Pons Reviewed-by: Felix Held Tested-by: build bot (Jenkins) --- src/device/pci_rom.c | 101 ++++++++++++++++-------------------- src/include/device/device.h | 12 +++++ 2 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c index 229c6fae4a..49b9923d47 100644 --- a/src/device/pci_rom.c +++ b/src/device/pci_rom.c @@ -169,12 +169,15 @@ struct rom_header *pci_rom_load(struct device *dev, memcpy((void *)PCI_VGA_RAM_IMAGE_START, rom_header, rom_size); } + + dev->pci_vga_option_rom = (struct rom_header *)(PCI_VGA_RAM_IMAGE_START); return (struct rom_header *)(PCI_VGA_RAM_IMAGE_START); } printk(BIOS_DEBUG, "Copying non-VGA ROM image from %p to %p, 0x%x bytes\n", rom_header, pci_ram_image_start, rom_size); + dev->pci_vga_option_rom = (struct rom_header *)pci_ram_image_start; memcpy(pci_ram_image_start, rom_header, rom_size); pci_ram_image_start += rom_size; return (struct rom_header *)(pci_ram_image_start-rom_size); @@ -183,30 +186,6 @@ struct rom_header *pci_rom_load(struct device *dev, /* ACPI */ #if CONFIG(HAVE_ACPI_TABLES) -/* VBIOS may be modified after oprom init so use the copy if present. */ -static struct rom_header *check_initialized(const struct device *dev) -{ - struct rom_header *run_rom; - struct pci_data *rom_data; - - if (!CONFIG(VGA_ROM_RUN) && !CONFIG(RUN_FSP_GOP)) - 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_le16(&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 ati_rom_acpi_fill_vfct(const struct device *device, acpi_vfct_t *vfct_struct, unsigned long current) @@ -214,7 +193,8 @@ ati_rom_acpi_fill_vfct(const struct device *device, acpi_vfct_t *vfct_struct, acpi_vfct_image_hdr_t *header = &vfct_struct->image_hdr; struct rom_header *rom; - rom = check_initialized(device); + /* Already loaded into DRAM? */ + rom = device->pci_vga_option_rom; if (!rom) rom = pci_rom_probe(device); if (!rom) { @@ -273,6 +253,7 @@ pci_rom_write_acpi_tables(const struct device *device, unsigned long current, void pci_rom_ssdt(const struct device *device) { + const struct rom_header *rom; static size_t ngfx; /* Only handle display devices */ @@ -283,12 +264,43 @@ void pci_rom_ssdt(const struct device *device) if (!device->enabled) return; - /* Probe for option rom */ - const struct rom_header *rom = pci_rom_probe(device); - if (!rom || !rom->size) { - printk(BIOS_WARNING, "%s: Missing PCI Option ROM\n", - dev_path(device)); - return; + /* Already loaded into DRAM? */ + rom = device->pci_vga_option_rom; + if (!rom) { + /* Probe for option rom */ + rom = pci_rom_probe(device); + if (!rom || !rom->size) { + printk(BIOS_WARNING, "%s: Missing PCI Option ROM\n", + dev_path(device)); + return; + } + + /* Supports up to four devices. */ + if ((CBMEM_ID_ROM0 + ngfx) > CBMEM_ID_ROM3) { + printk(BIOS_ERR, "%s: Out of CBMEM IDs.\n", dev_path(device)); + return; + } + + /* Prepare memory */ + const size_t cbrom_length = rom->size * 512; + if (!cbrom_length) { + printk(BIOS_ERR, "%s: ROM has zero length!\n", + dev_path(device)); + return; + } + + void *cbrom = cbmem_add(CBMEM_ID_ROM0 + ngfx, cbrom_length); + if (!cbrom) { + printk(BIOS_ERR, "%s: Failed to allocate CBMEM.\n", + dev_path(device)); + return; + } + /* Increment CBMEM id for next device */ + ngfx++; + + memcpy(cbrom, rom, cbrom_length); + + rom = cbrom; } const char *scope = acpi_device_path(device); @@ -297,34 +309,9 @@ void pci_rom_ssdt(const struct device *device) return; } - /* Supports up to four devices. */ - if ((CBMEM_ID_ROM0 + ngfx) > CBMEM_ID_ROM3) { - printk(BIOS_ERR, "%s: Out of CBMEM IDs.\n", dev_path(device)); - return; - } - - /* Prepare memory */ - const size_t cbrom_length = rom->size * 512; - if (!cbrom_length) { - printk(BIOS_ERR, "%s: ROM has zero length!\n", - dev_path(device)); - return; - } - - void *cbrom = cbmem_add(CBMEM_ID_ROM0 + ngfx, cbrom_length); - if (!cbrom) { - printk(BIOS_ERR, "%s: Failed to allocate CBMEM.\n", - dev_path(device)); - return; - } - /* Increment CBMEM id for next device */ - ngfx++; - - memcpy(cbrom, rom, cbrom_length); - /* write _ROM method */ acpigen_write_scope(scope); - acpigen_write_rom(cbrom, cbrom_length); + acpigen_write_rom((void *)rom, rom->size * 512); acpigen_pop_len(); /* pop scope */ } #endif diff --git a/src/include/device/device.h b/src/include/device/device.h index 901f717624..ad9d9c5318 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -36,6 +36,7 @@ struct chip_operations { struct bus; struct acpi_rsdp; +struct rom_header; struct device_operations { void (*read_resources)(struct device *dev); @@ -127,6 +128,17 @@ struct device { struct device_operations *ops; struct chip_operations *chip_ops; const char *name; + /* + * A pointer to the corresponding PCI Option ROM. + * + * When set the Option ROM has been placed in usable DRAM in + * an area that is marked as reserved. This can be for example + * the legacy C-segment or a CBMEM area. The Option ROM is + * read writeable and guaranteed to be used by the device. + * The PCIR data header might still have a different vendor and + * device ID. + */ + struct rom_header *pci_vga_option_rom; #if CONFIG(GENERATE_SMBIOS_TABLES) u8 smbios_slot_type; u8 smbios_slot_data_width;