[coreboot-gerrit] Change in coreboot[master]: [WIP] drv/intel/gma/opregion: Add common init_idg_opregion()

Patrick Rudolph (Code Review) gerrit at coreboot.org
Sat Aug 12 16:00:27 CEST 2017


Hello Matt DeVillier,

I'd like you to do a code review. Please visit

    https://review.coreboot.org/20969

to review the following change.


Change subject: [WIP] drv/intel/gma/opregion: Add common init_idg_opregion()
......................................................................

[WIP] drv/intel/gma/opregion: Add common init_idg_opregion()

Add a new common method to initialize ACPI OpRegion.
* Try to locate vbt.bin in CBFS.
* Try to locate VBIOS in CBFS.
* Keep existing code to probe at 0xc0000.

Change-Id: I8ee50ea9900537bd9e3ca5ab0cd3f48d2acec970
Signed-off-by: Matt DeVillier <matt.devillier at gmail.com>
Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
M src/drivers/intel/gma/opregion.c
1 file changed, 115 insertions(+), 48 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/69/20969/1

diff --git a/src/drivers/intel/gma/opregion.c b/src/drivers/intel/gma/opregion.c
index e9cbba1..d557204 100644
--- a/src/drivers/intel/gma/opregion.c
+++ b/src/drivers/intel/gma/opregion.c
@@ -17,6 +17,7 @@
 #include <arch/acpi.h>
 #include <types.h>
 #include <string.h>
+#include <cbfs.h>
 #include <device/device.h>
 #include <device/pci.h>
 #include <device/pci_ids.h>
@@ -67,12 +68,14 @@
 	}
 }
 
+/*
+ * Try to locate Intel VBIOS at 0xc0000. It might have been placed by
+ * Native Graphics Init as fake Option ROM or when coreboot did run the
+ * VBIOS on legacy platforms.
+ * TODO: Place generated fake VBT in CBMEM and get rid of this.
+ */
 static void *get_intel_vbios(void)
 {
-	/* This should probably be looking at CBFS or we should always
-	 * deploy the VBIOS on Intel systems, even if we don't run it
-	 * in coreboot (e.g. SeaBIOS only scenarios).
-	 */
 	u8 *vbios = (u8 *)0xc0000;
 
 	optionrom_header_t *oprom = (optionrom_header_t *)vbios;
@@ -80,61 +83,129 @@
 						oprom->pcir_offset);
 
 	printk(BIOS_DEBUG, "GET_VBIOS: %x %x %x %x %x\n",
-		oprom->signature, pcir->vendor, pcir->classcode[0],
-		pcir->classcode[1], pcir->classcode[2]);
+	       oprom->signature, pcir->vendor, pcir->classcode[0],
+	       pcir->classcode[1], pcir->classcode[2]);
 
 
 	if ((oprom->signature == OPROM_SIGNATURE) &&
-		(pcir->vendor == PCI_VENDOR_ID_INTEL) &&
-		(pcir->classcode[0] == 0x00) &&
-		(pcir->classcode[1] == 0x00) &&
-		(pcir->classcode[2] == 0x03))
+	    (pcir->vendor == PCI_VENDOR_ID_INTEL) &&
+	    (pcir->classcode[0] == 0x00) &&
+	    (pcir->classcode[1] == 0x00) &&
+	    (pcir->classcode[2] == 0x03))
 		return (void *)vbios;
 
 	return NULL;
 }
 
-static enum cb_err init_opregion_vbt(igd_opregion_t *opregion)
-{
-	void *vbios;
-	vbios = get_intel_vbios();
-	if (!vbios) {
-		printk(BIOS_DEBUG, "VBIOS not found.\n");
-		return CB_ERR;
-	}
-
-	printk(BIOS_DEBUG, " ... VBIOS found at %p\n", vbios);
-	optionrom_header_t *oprom = (optionrom_header_t *)vbios;
-	optionrom_vbt_t *vbt = (optionrom_vbt_t *)(vbios +
-						oprom->vbt_offset);
-
-	if (read32(vbt->hdr_signature) != VBT_SIGNATURE) {
-		printk(BIOS_DEBUG, "VBT not found!\n");
-		return CB_ERR;
-	}
-
-	memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild, 4);
-	memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size < 7168 ?
-						vbt->hdr_vbt_size : 7168);
-
-	return CB_SUCCESS;
-}
-
 /* Initialize IGD OpRegion, called from ACPI code and OS drivers */
-enum cb_err intel_gma_init_igd_opregion(igd_opregion_t *opregion)
+enum cb_err
+intel_gma_init_igd_opregion(igd_opregion_t *opregion)
 {
-	enum cb_err ret;
+	struct region_device vbt_rdev;
+	optionrom_vbt_t *vbt = NULL;
+	optionrom_vbt_t *ext_vbt;
+	struct cbfsf file_desc;
+	bool need_unmap = false;
 
-	memset((void *)opregion, 0, sizeof(igd_opregion_t));
+	/* try to locate vbt.bin in CBFS */
+	if (cbfs_boot_locate(&file_desc, "vbt.bin", NULL) == CB_SUCCESS) {
+		cbfs_file_data(&vbt_rdev, &file_desc);
+		vbt = rdev_mmap_full(&vbt_rdev);
+		if (vbt) {
+			uint32_t vbtsig = 0;
+			/* Validate the vbt file */
+			memcpy(&vbtsig, vbt, sizeof(uint32_t));
+			if (vbtsig == VBT_SIGNATURE) {
+				need_unmap = true;
+			} else {
+				printk(BIOS_ERR,
+				       "GMA: Invalid signature in VBT data"
+				       " file (vbt.bin)!\n");
+				rdev_munmap(&vbt_rdev, vbt);
+				vbt = NULL;
+			}
+		} else {
+			printk(BIOS_ERR, "GMA: VBT couldn't be read\n");
+		}
+	} else {
+		printk(BIOS_NOTICE,
+		       "GMA: Could not locate a VBT file in CBFS\n");
+	}
 
-	// FIXME if IGD is disabled, we should exit here.
+	/* If no vbt.bin, try to load from VBIOS in CBFS */
+	if (!vbt) {
+		optionrom_header_t *oprom = (optionrom_header_t *)
+			pci_rom_probe(dev_find_slot(0, PCI_DEVFN(0x2, 0)));
+		if (oprom) {
+			printk(BIOS_DEBUG, "GMA: VBIOS found at %p\n", oprom);
+			vbt = (optionrom_vbt_t *)(oprom + oprom->vbt_offset);
+			if (read32(vbt->hdr_signature) != VBT_SIGNATURE) {
+				printk(BIOS_DEBUG,
+				       "GMA: Invalid signature in VBT\n");
+				vbt = NULL;
+			}
+		} else {
+			printk(BIOS_NOTICE, "GMA: VBIOS not found in CFBS\n");
+		}
+	}
+
+	/* 3rd option - use generated fake VBT */
+	if (!vbt) {
+		/* FIXME: Read from CBMEM or generate using devicetree */
+		void *vbios = get_intel_vbios();
+		if (!vbios) {
+			printk(BIOS_NOTICE,
+			       "GMA: VBIOS not found at 0xc0000\n");
+		} else {
+			printk(BIOS_DEBUG, " ... VBIOS found at %p\n", vbios);
+			optionrom_header_t *oprom =
+				(optionrom_header_t *)vbios;
+			vbt = (optionrom_vbt_t *)(vbios + oprom->vbt_offset);
+			if (read32(vbt->hdr_signature) != VBT_SIGNATURE) {
+				printk(BIOS_NOTICE,
+				       "GMA: Invalid signature in VBT\n");
+				vbt = NULL;
+			}
+		}
+	}
+
+	if (!vbt) {
+		printk(BIOS_ERR, "GMA: VBT not found\n");
+		return CB_ERR;
+	}
+
+	memset(opregion, 0, sizeof(igd_opregion_t));
 
 	memcpy(&opregion->header.signature, IGD_OPREGION_SIGNATURE,
-		sizeof(opregion->header.signature));
+					sizeof(opregion->header.signature));
+	memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild,
+					ARRAY_SIZE(vbt->coreblock_biosbuild));
+	/* Extended VBT support */
+	if (vbt->hdr_vbt_size > sizeof(opregion->vbt.gvd1)) {
+		ext_vbt = cbmem_add(CBMEM_ID_EXT_VBT, vbt->hdr_vbt_size);
 
-	/* 8kb */
-	opregion->header.size = sizeof(igd_opregion_t) / 1024;
-	opregion->header.version = IGD_OPREGION_VERSION;
+		if (ext_vbt == NULL) {
+			printk(BIOS_ERR,
+			       "GMA: Unable to add Ext VBT to cbmem!\n");
+			if (need_unmap)
+				rdev_munmap(&vbt_rdev, vbt);
+			return CB_ERR;
+		}
+
+		memcpy(ext_vbt, vbt, vbt->hdr_vbt_size);
+		opregion->mailbox3.rvda = (uintptr_t)ext_vbt;
+		opregion->mailbox3.rvds = vbt->hdr_vbt_size;
+	} else {
+		/* Raw VBT size which can fit in gvd1 */
+		memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size);
+	}
+
+	if (need_unmap)
+		rdev_munmap(&vbt_rdev, vbt);
+
+	/* 8KiB */
+	opregion->header.size = sizeof(igd_opregion_t) / KiB;
+	opregion->header.version = (IGD_OPREGION_VERSION << 24);
 
 	// FIXME We just assume we're mobile for now
 	opregion->header.mailboxes = MAILBOXES_MOBILE;
@@ -157,10 +228,6 @@
 	opregion->mailbox3.bclm[8] = IGD_WORD_FIELD_VALID + 0x50cc;
 	opregion->mailbox3.bclm[9] = IGD_WORD_FIELD_VALID + 0x5ae5;
 	opregion->mailbox3.bclm[10] = IGD_WORD_FIELD_VALID + 0x64ff;
-
-	ret = init_opregion_vbt(opregion);
-	if (ret != CB_SUCCESS)
-		return ret;
 
 	/* Write ASLS PCI register and prepare SWSCI register. */
 	intel_gma_opregion_register((uintptr_t)opregion);

-- 
To view, visit https://review.coreboot.org/20969
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I8ee50ea9900537bd9e3ca5ab0cd3f48d2acec970
Gerrit-Change-Number: 20969
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <siro at das-labor.org>
Gerrit-Reviewer: Matt DeVillier <matt.devillier at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20170812/586c5cc8/attachment.html>


More information about the coreboot-gerrit mailing list