diff options
Diffstat (limited to 'src/device')
-rw-r--r-- | src/device/pci_device.c | 1 | ||||
-rw-r--r-- | src/device/pci_rom.c | 59 |
2 files changed, 60 insertions, 0 deletions
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 |