diff options
-rw-r--r-- | src/commonlib/include/commonlib/cbmem_id.h | 10 | ||||
-rw-r--r-- | src/device/pci_device.c | 1 | ||||
-rw-r--r-- | src/device/pci_rom.c | 59 | ||||
-rw-r--r-- | src/include/device/pci_rom.h | 2 |
4 files changed, 71 insertions, 1 deletions
diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h index 2595655b4d..9a66246001 100644 --- a/src/commonlib/include/commonlib/cbmem_id.h +++ b/src/commonlib/include/commonlib/cbmem_id.h @@ -71,6 +71,10 @@ #define CBMEM_ID_WIFI_CALIBRATION 0x57494649 #define CBMEM_ID_EC_HOSTEVENT 0x63ccbbc3 #define CBMEM_ID_EXT_VBT 0x69866684 +#define CBMEM_ID_ROM0 0x524f4d30 +#define CBMEM_ID_ROM1 0x524f4d31 +#define CBMEM_ID_ROM2 0x524f4d32 +#define CBMEM_ID_ROM3 0x524f4d33 #define CBMEM_ID_TO_NAME_TABLE \ { CBMEM_ID_ACPI, "ACPI " }, \ @@ -122,5 +126,9 @@ { CBMEM_ID_VPD, "VPD " }, \ { CBMEM_ID_WIFI_CALIBRATION, "WIFI CLBR " }, \ { CBMEM_ID_EC_HOSTEVENT, "EC HOSTEVENT"}, \ - { CBMEM_ID_EXT_VBT, "EXT VBT"}, + { CBMEM_ID_EXT_VBT, "EXT VBT"}, \ + { CBMEM_ID_ROM0, "VGA ROM #0 "}, \ + { CBMEM_ID_ROM1, "VGA ROM #1 "}, \ + { CBMEM_ID_ROM2, "VGA ROM #2 "}, \ + { CBMEM_ID_ROM3, "VGA ROM #3 "}, #endif /* _CBMEM_ID_H_ */ diff --git a/src/device/pci_device.c b/src/device/pci_device.c index ffc679facf..dbe76b54f5 100644 --- a/src/device/pci_device.c +++ b/src/device/pci_device.c @@ -744,6 +744,7 @@ struct device_operations default_pci_ops_dev = { .enable_resources = pci_dev_enable_resources, #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) .write_acpi_tables = pci_rom_write_acpi_tables, + .acpi_fill_ssdt_generator = pci_rom_ssdt, #endif .init = pci_dev_init, .scan_bus = 0, diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c index a411f06acf..15b0c4c23f 100644 --- a/src/device/pci_rom.c +++ b/src/device/pci_rom.c @@ -25,6 +25,8 @@ #include <device/pci_ops.h> #include <string.h> #include <cbfs.h> +#include <cbmem.h> +#include <arch/acpigen.h> /* Rmodules don't like weak symbols. */ u32 __attribute__((weak)) map_oprom_vendev(u32 vendev) { return vendev; } @@ -267,4 +269,61 @@ pci_rom_write_acpi_tables(struct device *device, return current; } + +void pci_rom_ssdt(struct device *device) +{ + static size_t ngfx; + + /* Only handle VGA devices */ + if ((device->class >> 8) != PCI_CLASS_DISPLAY_VGA) + return; + + /* Only handle enabled devices */ + 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; + } + + const char *scope = acpi_device_path(device); + if (!scope) { + printk(BIOS_ERR, "%s: Missing ACPI scope\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); + + /* write _ROM method */ + acpigen_write_scope(scope); + acpigen_write_rom(cbrom, cbrom_length); + acpigen_pop_len(); /* pop scope */ +} #endif diff --git a/src/include/device/pci_rom.h b/src/include/device/pci_rom.h index c5ace4c788..a4aa52aa09 100644 --- a/src/include/device/pci_rom.h +++ b/src/include/device/pci_rom.h @@ -43,6 +43,8 @@ pci_rom_write_acpi_tables(struct device *device, unsigned long current, struct acpi_rsdp *rsdp); +void pci_rom_ssdt(struct device *device); + u32 map_oprom_vendev(u32 vendev); #endif |