[coreboot-gerrit] New patch to review for coreboot: device/pci_rom: Implement ACPI table VFCT

Patrick Rudolph (siro@das-labor.org) gerrit at coreboot.org
Fri Apr 1 11:21:55 CEST 2016


Patrick Rudolph (siro at das-labor.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14224

-gerrit

commit 8e4eeb51b2848f45d93663025df65b9aeadea0b8
Author: Patrick Rudolph <siro at das-labor.org>
Date:   Thu Mar 31 20:04:23 2016 +0200

    device/pci_rom: Implement ACPI table VFCT
    
    The ACPI table VFCT (VBIOS Fetch Table) is used by AMD to
    fetch the VBIOS.
    
    Only fill VFCT for enabled AMD VGA devices.
    
    Test system:
     * Gigabyte GA-B75M-D3H
     * Intel Pentium CPU G2130
     * AMD Radeon HD4870
    
    Change-Id: I3b4a587c71e7165338cad3aca77ed5afa085a63c
    Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
 src/arch/x86/acpi.c              | 25 +++++++++++++++++
 src/arch/x86/include/arch/acpi.h | 29 +++++++++++++++++++
 src/device/pci_device.c          |  1 +
 src/device/pci_rom.c             | 60 ++++++++++++++++++++++++++++++++++++++++
 src/include/device/pci_rom.h     |  5 ++++
 5 files changed, 120 insertions(+)

diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c
index 5640ad0..206c4d6 100644
--- a/src/arch/x86/acpi.c
+++ b/src/arch/x86/acpi.c
@@ -536,6 +536,31 @@ void acpi_create_hpet(acpi_hpet_t *hpet)
 	header->checksum = acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
 }
 
+void acpi_create_vfct(struct device *device,
+		      struct acpi_vfct *vfct,
+		      unsigned long (*acpi_fill_vfct)(struct device *device, struct acpi_vfct *vfct_struct, unsigned long current))
+{
+	acpi_header_t *header = &(vfct->header);
+	unsigned long current = (unsigned long)vfct + sizeof(struct acpi_vfct);
+
+	memset((void *)vfct, 0, sizeof(struct acpi_vfct));
+
+	/* Fill out header fields. */
+	memcpy(header->signature, "VFCT", 4);
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+
+	header->length = sizeof(struct acpi_vfct);
+	header->revision = 1; /* ACPI 1.0: N/A, ACPI 2.0/3.0/4.0: 1 */
+
+	current = acpi_fill_vfct(device, vfct, current);
+
+	/* (Re)calculate length and checksum. */
+	header->length = current - (unsigned long)vfct;
+	header->checksum = acpi_checksum((void *)vfct, header->length);
+}
+
 void acpi_create_ivrs(acpi_ivrs_t *ivrs,
 		      unsigned long (*acpi_fill_ivrs)(acpi_ivrs_t* ivrs_struct, unsigned long current))
 {
diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h
index 276ca52..eb2892c 100644
--- a/src/arch/x86/include/arch/acpi.h
+++ b/src/arch/x86/include/arch/acpi.h
@@ -192,6 +192,31 @@ typedef struct acpi_madt {
 	u32 flags;			/* Multiple APIC flags */
 } __attribute__ ((packed)) acpi_madt_t;
 
+
+/* VFCT image header */
+struct acpi_vfct_image_hdr {
+	u32  PCIBus;          //0x4C
+	u32  PCIDevice;       //0x50
+	u32  PCIFunction;     //0x54
+	u16 VendorID;        //0x58
+	u16 DeviceID;        //0x5A
+	u16 SSVID;           //0x5C
+	u16 SSID;            //0x5E
+	u32  Revision;        //0x60
+	u32  ImageLength;     //0x64
+	u8  VbiosContent;     // dummy - copy VBIOS here
+} __attribute__ ((packed));
+
+/* VFCT (VBIOS Fetch Table) */
+struct acpi_vfct {
+	struct acpi_table_header header;
+	u8 TableUUID[16];    //0x24
+	u32 VBIOSImageOffset; //0x34.
+	u32 Lib1ImageOffset;  //0x38.
+	u32 Reserved[4];      //0x3C
+	struct acpi_vfct_image_hdr image_hdr;
+} __attribute__ ((packed));
+
 typedef struct acpi_ivrs_info {
 } __attribute__ ((packed)) acpi_ivrs_info_t;
 
@@ -565,6 +590,10 @@ void acpi_create_srat(acpi_srat_t *srat,
 void acpi_create_slit(acpi_slit_t *slit,
 		      unsigned long (*acpi_fill_slit)(unsigned long current));
 
+void acpi_create_vfct(struct device *device,
+		      struct acpi_vfct *vfct,
+		      unsigned long (*acpi_fill_vfct)(struct device *device, struct acpi_vfct *vfct_struct, unsigned long current));
+
 void acpi_create_ivrs(acpi_ivrs_t *ivrs,
 		      unsigned long (*acpi_fill_ivrs)(acpi_ivrs_t* ivrs_struct, unsigned long current));
 
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 5f02955..b51e650 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -664,6 +664,7 @@ struct device_operations default_pci_ops_dev = {
 	.read_resources   = pci_dev_read_resources,
 	.set_resources    = pci_dev_set_resources,
 	.enable_resources = pci_dev_enable_resources,
+	.write_acpi_tables = pci_rom_write_acpi_tables,
 	.init             = pci_dev_init,
 	.scan_bus         = 0,
 	.enable           = 0,
diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c
index 288a5f0..0b3a6d8 100644
--- a/src/device/pci_rom.c
+++ b/src/device/pci_rom.c
@@ -251,3 +251,63 @@ void pci_rom_load_and_run(struct device *dev)
 	printk(BIOS_DEBUG, "VGA Option ROM was run\n");
 #endif /* CONFIG_VGA_ROM_RUN */
 }
+
+static unsigned long
+pci_rom_acpi_fill_vfct(struct device *device,
+					   struct acpi_vfct *vfct_struct,
+					   unsigned long current)
+{
+	struct acpi_vfct_image_hdr *header = &vfct_struct->image_hdr;
+	struct rom_header *rom, *ram;
+
+	vfct_struct->VBIOSImageOffset = (size_t)header - (size_t)vfct_struct;
+
+	rom = pci_rom_probe(device);
+	if (!rom) {
+		printk(BIOS_DEBUG, "pci_rom_probe: %p\n", rom);
+		return current;
+	}
+
+	ram = pci_rom_load(device, rom, (void *)&header->VbiosContent);
+	if (!ram) {
+		printk(BIOS_DEBUG, "pci_rom_load: %p\n", rom);
+		return current;
+	}
+	header->DeviceID = device->device;
+	header->VendorID = device->vendor;
+	header->PCIBus = device->bus->secondary;
+	header->PCIFunction = PCI_FUNC(device->path.pci.devfn);
+	header->PCIDevice = PCI_SLOT(device->path.pci.devfn);
+	header->ImageLength = ram->size * 512;
+
+	current += header->ImageLength;
+	return current;
+}
+
+unsigned long
+pci_rom_write_acpi_tables(struct device *device,
+						  unsigned long current,
+						  struct acpi_rsdp *rsdp)
+{
+	struct acpi_vfct *vfct;
+
+	/* only handle VGA devices */
+	if ((device->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+		return current;
+
+	/* only handle enabled devices */
+	if (!device->enabled)
+		return current;
+
+	/* AMD/ATI uses VFCT */
+	if (device->vendor == PCI_VENDOR_ID_ATI) {
+		current = ALIGN(current, 8);
+		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;
+		acpi_add_table(rsdp, vfct);
+	}
+
+	return current;
+}
diff --git a/src/include/device/pci_rom.h b/src/include/device/pci_rom.h
index 1dff9a7..ebda54c 100644
--- a/src/include/device/pci_rom.h
+++ b/src/include/device/pci_rom.h
@@ -2,6 +2,7 @@
 #define PCI_ROM_H
 #include <endian.h>
 #include <stddef.h>
+#include <arch/acpi.h>
 
 #define PCI_ROM_HDR 0xAA55
 #define PCI_DATA_HDR (uint32_t) ( ('R' << 24) | ('I' << 16) | ('C' << 8) | 'P' )
@@ -37,6 +38,10 @@ struct rom_header *pci_rom_probe(struct device *dev);
 struct rom_header *pci_rom_load(struct device *dev,
 								struct rom_header *rom_header,
 								void *load_addr);
+unsigned long
+pci_rom_write_acpi_tables(struct device *device,
+						  unsigned long current,
+						  struct acpi_rsdp *rsdp);
 void pci_rom_load_and_run(struct device *dev);
 u32 map_oprom_vendev(u32 vendev);
 



More information about the coreboot-gerrit mailing list