summaryrefslogtreecommitdiffstats
path: root/src/drivers/intel/gma/opregion.c
diff options
context:
space:
mode:
authorMaulik V Vaghela <maulik.v.vaghela@intel.com>2021-06-09 11:36:20 +0530
committerTim Wawrzynczak <twawrzynczak@chromium.org>2021-07-01 16:36:47 +0000
commita6b60ebedbece7f2d008c57dc48bd492586989da (patch)
tree3eb13d88444e14f91b95a6dbd34f403ffad47ed1 /src/drivers/intel/gma/opregion.c
parent5bb7dc4e050b79390037a931681c6fbce639a052 (diff)
downloadcoreboot-a6b60ebedbece7f2d008c57dc48bd492586989da.tar.gz
coreboot-a6b60ebedbece7f2d008c57dc48bd492586989da.tar.bz2
coreboot-a6b60ebedbece7f2d008c57dc48bd492586989da.zip
drivers/intel/gma: Move extended VBT just below opregion
Currently the flow for opregion init is as below: 1. Allocate memory for opregion first (cbmem_add(opregion)) 2. Check if VBT size > 6 KiB (this requires extended VBT support) 3. In case of extended VBT requirement, we allocate another chunk of memory which is equal to size of VBT (cbmem_add(extended_vbt)) 4. Pass physical address pointer to OS via RVDA We can optimize the above flow to allocate single chunk of memory by checking VBT size in earlier step. The new optimized flow for opregion init is as below: 1. Check if VBT size > 6 KiB (this requires extended VBT support) 2. In case of extended VBT requirement, total memory to be allocated is calculated as sizeof(opregion) + sizeof (extended_vbt) In case where VBT size is < 6 KiB, total memory requirement would be equal to sizeof(opregion) 3. Based on above calculation, allocate single chunk of memory based on total size. This will also be helpful for the case of virtualization where guest users don't have access to physical address and when it needs relative address of VBT compared to absolute address. In case of opregion 2.1 spec, we need to pass relative address of VBT from opregion base in RVDA. This optimization will help in meeting this requirement since relative address of extended VBT is easy to get. This change will ensure that it meets opregion specification requirement and will be compatible with future versions as well. BUG=b:190019970 BRANCH=None TEST=check the address of extended VBT region and address is coming correctly. Change-Id: Ic0e255df63145409096b0b9312c6c51c05f49931 Signed-off-by: Maulik V Vaghela <maulik.v.vaghela@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/55341 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Diffstat (limited to 'src/drivers/intel/gma/opregion.c')
-rw-r--r--src/drivers/intel/gma/opregion.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/src/drivers/intel/gma/opregion.c b/src/drivers/intel/gma/opregion.c
index 49938e090a2e..799c7fdfafa4 100644
--- a/src/drivers/intel/gma/opregion.c
+++ b/src/drivers/intel/gma/opregion.c
@@ -265,13 +265,28 @@ static inline bool is_ext_vbt_required(igd_opregion_t *opregion, optionrom_vbt_t
return (vbt->hdr_vbt_size > sizeof(opregion->vbt.gvd1));
}
+/*
+ * Copy extended VBT at the end of opregion and fill rvda and rvds
+ * values correctly for the opregion.
+ */
+static void opregion_add_ext_vbt(igd_opregion_t *opregion, uint8_t *ext_vbt,
+ optionrom_vbt_t *vbt)
+{
+ /* Copy VBT into extended VBT region (at offset 8 KiB) */
+ memcpy(ext_vbt, vbt, vbt->hdr_vbt_size);
+
+ /* Fill RVDA value with address of physical pointer */
+ opregion->mailbox3.rvda = (uintptr_t)ext_vbt;
+ opregion->mailbox3.rvds = vbt->hdr_vbt_size;
+}
+
/* Initialize IGD OpRegion, called from ACPI code and OS drivers */
enum cb_err intel_gma_init_igd_opregion(void)
{
igd_opregion_t *opregion;
struct region_device rdev;
optionrom_vbt_t *vbt = NULL;
- optionrom_vbt_t *ext_vbt = NULL;
+ size_t opregion_size = sizeof(igd_opregion_t);
if (acpi_is_wakeup_s3())
return intel_gma_restore_opregion();
@@ -291,13 +306,16 @@ enum cb_err intel_gma_init_igd_opregion(void)
return CB_ERR;
}
- opregion = cbmem_add(CBMEM_ID_IGD_OPREGION, sizeof(*opregion));
+ if (is_ext_vbt_required(opregion, vbt))
+ opregion_size += vbt->hdr_vbt_size;
+
+ opregion = cbmem_add(CBMEM_ID_IGD_OPREGION, opregion_size);
if (!opregion) {
printk(BIOS_ERR, "GMA: Failed to add IGD OpRegion to CBMEM.\n");
return CB_ERR;
}
- memset(opregion, 0, sizeof(igd_opregion_t));
+ memset(opregion, 0, opregion_size);
memcpy(&opregion->header.signature, IGD_OPREGION_SIGNATURE,
sizeof(opregion->header.signature));
@@ -305,18 +323,9 @@ enum cb_err intel_gma_init_igd_opregion(void)
ARRAY_SIZE(vbt->coreblock_biosbuild));
/* Extended VBT support */
if (is_ext_vbt_required(opregion, vbt)) {
- ext_vbt = cbmem_add(CBMEM_ID_EXT_VBT, vbt->hdr_vbt_size);
-
- if (ext_vbt == NULL) {
- printk(BIOS_ERR,
- "GMA: Unable to add Ext VBT to cbmem!\n");
- rdev_munmap(&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;
+ /* Place extended VBT just after opregion */
+ uint8_t *ext_vbt = (uint8_t *)opregion + sizeof(*opregion);
+ opregion_add_ext_vbt(opregion, ext_vbt, vbt);
} else {
/* Raw VBT size which can fit in gvd1 */
memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size);