Page MenuHomeFreeBSD
Authored By
corvink
Nov 12 2021, 11:31 AM
Size
43 KB
Referenced Files
None
Subscribers
None

GVT-d_v1.diff

diff --git a/MdePkg/Include/Uefi/UefiBaseType.h b/MdePkg/Include/Uefi/UefiBaseType.h
index 45e2aa63bb..084c52cd0f 100644
--- a/MdePkg/Include/Uefi/UefiBaseType.h
+++ b/MdePkg/Include/Uefi/UefiBaseType.h
@@ -53,6 +53,8 @@ typedef UINT64 EFI_PHYSICAL_ADDRESS;
///
typedef UINT64 EFI_VIRTUAL_ADDRESS;
+#define NUMERIC_VALUE_AS_POINTER(Type, Value) ((Type *) ((UINTN)(Value)))
+
///
/// EFI Time Abstraction:
/// Year: 1900 - 9999
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
index 9ccdb4d91c..e7de6937da 100644
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
@@ -245,6 +245,16 @@ InstallAcpiTables (
{
EFI_STATUS Status;
+ Status = InstallBhyveTables (AcpiTable);
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ if (Status != EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_INFO, "%a: unable to install bhyve's ACPI tables (%r)\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+
Status = InstallOvmfFvTables (AcpiTable);
return Status;
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
index 994ee2c7cd..1a99838e8e 100644
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
@@ -46,6 +46,12 @@ BhyveInstallAcpiTable(
OUT UINTN *TableKey
);
+EFI_STATUS
+EFIAPI
+InstallBhyveTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
+ );
+
EFI_STATUS
EFIAPI
InstallXenTables (
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
index 595fd055f9..a2efa3feb1 100644
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -37,12 +37,12 @@
[LibraryClasses]
BaseLib
BaseMemoryLib
- BhyveFwCtlLib
DebugLib
DxeServicesTableLib
MemoryAllocationLib
OrderedCollectionLib
PcdLib
+ QemuFwCfgLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
index 01ee894746..e2c543516a 100644
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
@@ -9,8 +9,55 @@
#include "AcpiPlatform.h"
#include <Library/BaseMemoryLib.h>
-#include <Library/BhyveFwCtlLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/QemuFwCfgLib.h> // QemuFwCfgFindFile()
+
+#define BHYVE_ACPI_PHYSICAL_ADDRESS ((UINTN)0x000F2400)
+#define BHYVE_BIOS_PHYSICAL_END ((UINTN)0x00100000)
+
+#pragma pack (1)
+
+typedef struct
+{
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT64 Tables[0];
+} EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+STATIC
+EFI_STATUS
+EFIAPI
+BhyveGetCpuCount (
+ OUT UINT32 *CpuCount
+ )
+{
+ EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM Item;
+ UINTN Size;
+
+ if (!QemuFwCfgIsAvailable ()) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get index of FW_CFG file
+ //
+ Status = QemuFwCfgFindFile ("opt/bhyve/hw.ncpu", &Item, &Size);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ } else if (Size != sizeof (*CpuCount)) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //
+ // Get data of FW_CFG file
+ //
+ QemuFwCfgSelectItem (Item);
+ QemuFwCfgReadBytes (Size, CpuCount);
+
+ return EFI_SUCCESS;
+}
STATIC
EFI_STATUS
@@ -23,7 +70,6 @@ BhyveInstallAcpiMadtTable (
)
{
UINT32 CpuCount;
- UINTN cSize;
UINTN NewBufferSize;
EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;
@@ -36,9 +82,8 @@ BhyveInstallAcpiMadtTable (
ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
// Query the host for the number of vCPUs
- CpuCount = 0;
- cSize = sizeof(CpuCount);
- if (BhyveFwCtlGet ("hw.ncpu", &CpuCount, &cSize) == RETURN_SUCCESS) {
+ Status = BhyveGetCpuCount (&CpuCount);
+ if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Retrieved CpuCount %d\n", CpuCount));
ASSERT (CpuCount >= 1);
} else {
@@ -130,3 +175,231 @@ BhyveInstallAcpiTable (
TableKey
);
}
+
+/**
+ Get the address of bhyve's ACPI Root System Description Pointer (RSDP).
+
+ @param RsdpPtr Return pointer to RSDP.
+
+ @return EFI_SUCCESS Bhyve's RSDP successfully found.
+ @return EFI_NOT_FOUND Couldn't find bhyve's RSDP.
+ @return EFI_UNSUPPORTED Revision is lower than 2.
+ @return EFI_PROTOCOL_ERROR Invalid RSDP found.
+
+**/
+EFI_STATUS
+EFIAPI
+BhyveGetAcpiRsdp (
+ OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
+ )
+{
+ UINTN RsdpAddress;
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+
+ if (RsdpPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Detect the RSDP
+ //
+ for (RsdpAddress = BHYVE_ACPI_PHYSICAL_ADDRESS;
+ RsdpAddress < BHYVE_BIOS_PHYSICAL_END;
+ RsdpAddress += 0x10) {
+ Rsdp = NUMERIC_VALUE_AS_POINTER (
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
+ RsdpAddress
+ );
+ if (Rsdp->Signature != EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
+ continue;
+ }
+ if (Rsdp->Revision < 2) {
+ DEBUG ((DEBUG_INFO, "%a: unsupported RSDP found\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // For ACPI 1.0/2.0/3.0 the checksum of first 20 bytes should be 0.
+ // For ACPI 2.0/3.0 the checksum of the entire table should be 0.
+ //
+ UINT8 Sum = CalculateCheckSum8 (
+ (CONST UINT8 *)Rsdp,
+ sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
+ );
+ if (Sum != 0) {
+ DEBUG ((DEBUG_INFO, "%a: RSDP header checksum not valid: 0x%02x\n",
+ __FUNCTION__, Sum));
+ return EFI_PROTOCOL_ERROR;
+ }
+ Sum = CalculateCheckSum8 (
+ (CONST UINT8 *)Rsdp,
+ sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
+ );
+ if (Sum != 0) {
+ DEBUG ((DEBUG_INFO, "%a: RSDP table checksum not valid: 0x%02x\n",
+ __FUNCTION__, Sum));
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // RSDP was found and is valid
+ //
+ *RsdpPtr = Rsdp;
+
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a: RSDP not found\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Get bhyve's ACPI tables from the RSDP. And install bhyve's ACPI tables
+ into the RSDT/XSDT using InstallAcpiTable.
+
+ @param AcpiProtocol Protocol instance pointer.
+
+ @return EFI_SUCCESS All tables were successfully inserted.
+ @return EFI_UNSUPPORTED Bhyve's ACPI tables doesn't include a XSDT.
+ @return EFI_PROTOCOL_ERROR Invalid XSDT found.
+
+ @return Error codes propagated from underlying functions.
+**/
+EFI_STATUS
+EFIAPI
+InstallBhyveTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
+ )
+{
+ EFI_STATUS Status;
+ UINTN TableHandle;
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+ EFI_ACPI_DESCRIPTION_HEADER *Dsdt;
+
+ Rsdp = NULL;
+ Facs = NULL;
+ Dsdt = NULL;
+
+ //
+ // Try to find bhyve ACPI tables
+ //
+ Status = BhyveGetAcpiRsdp (&Rsdp);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: can't get RSDP (%r)\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ //
+ // Bhyve should always provide a XSDT
+ //
+ EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE * CONST Xsdt =
+ NUMERIC_VALUE_AS_POINTER (
+ EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE,
+ Rsdp->XsdtAddress
+ );
+ if (Xsdt == NULL) {
+ DEBUG ((DEBUG_INFO, "%a: XSDT not found\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+ if (Xsdt->Header.Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
+ DEBUG ((DEBUG_INFO, "%a: invalid XSDT length\n", __FUNCTION__));
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // Install ACPI tables
+ //
+ CONST UINTN NumberOfTableEntries =
+ (Xsdt->Header.Length - sizeof (Xsdt->Header)) / sizeof (UINT64);
+ for (UINTN Index = 0; Index < NumberOfTableEntries; Index++) {
+ EFI_ACPI_DESCRIPTION_HEADER * CONST CurrentTable =
+ NUMERIC_VALUE_AS_POINTER (
+ EFI_ACPI_DESCRIPTION_HEADER,
+ Xsdt->Tables[Index]
+ );
+ Status = AcpiProtocol->InstallAcpiTable (
+ AcpiProtocol,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: failed to install ACPI table %c%c%c%c (%r)\n",
+ __FUNCTION__,
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[0],
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[1],
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[2],
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[3],
+ Status));
+ return Status;
+ }
+
+ if (CurrentTable->Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE * CONST Fadt =
+ (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE * CONST)CurrentTable;
+ if (Fadt->XFirmwareCtrl) {
+ Facs = NUMERIC_VALUE_AS_POINTER (
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE,
+ Fadt->XFirmwareCtrl
+ );
+ } else {
+ Facs = NUMERIC_VALUE_AS_POINTER (
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE,
+ Fadt->FirmwareCtrl
+ );
+ }
+ if (Fadt->XDsdt) {
+ Dsdt = NUMERIC_VALUE_AS_POINTER (
+ EFI_ACPI_DESCRIPTION_HEADER,
+ Fadt->XDsdt
+ );
+ } else {
+ Dsdt = NUMERIC_VALUE_AS_POINTER (
+ EFI_ACPI_DESCRIPTION_HEADER,
+ Fadt->Dsdt
+ );
+ }
+ }
+ }
+
+ //
+ // Install FACS
+ //
+ if (Facs != NULL) {
+ Status = AcpiProtocol->InstallAcpiTable (
+ AcpiProtocol,
+ Facs,
+ Facs->Length,
+ &TableHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: failed to install FACS (%r)\n", __FUNCTION__,
+ Status));
+ return Status;
+ }
+ }
+
+ //
+ // Install DSDT
+ // If it's not found, something bad happened. Don't continue execution.
+ //
+ if (Dsdt == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: failed to find DSDT\n", __FUNCTION__));
+ CpuDeadLoop ();
+ }
+
+ Status = AcpiProtocol->InstallAcpiTable (
+ AcpiProtocol,
+ Dsdt,
+ Dsdt->Length,
+ &TableHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: failed to install DSDT (%r)\n", __FUNCTION__,
+ Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index d8fe607d1c..53f061eeb3 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -163,9 +163,7 @@
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
- QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
- QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
- BhyveFwCtlLib|OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
@@ -284,6 +282,7 @@
!endif
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -354,6 +353,7 @@
!endif
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
MpInitLib|UefiCpuPkg/Library/MpInitLibUp/MpInitLibUp.inf
+ QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
[LibraryClasses.common.UEFI_APPLICATION]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -416,7 +416,6 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
[PcdsFixedAtBuild]
- gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
@@ -622,10 +621,11 @@
UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
UefiCpuPkg/CpuDxe/CpuDxe.inf
PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+ OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
<LibraryClasses>
- PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLibScan/PciHostBridgeLibScan.inf
+ PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
}
@@ -660,6 +660,7 @@
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
OvmfPkg/VirtioRngDxe/VirtioRng.inf
+ OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.inf
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
diff --git a/OvmfPkg/Bhyve/BhyveX64.fdf b/OvmfPkg/Bhyve/BhyveX64.fdf
index b3b4d44cef..20d9aa7e6c 100644
--- a/OvmfPkg/Bhyve/BhyveX64.fdf
+++ b/OvmfPkg/Bhyve/BhyveX64.fdf
@@ -205,6 +205,7 @@ INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
INF UefiCpuPkg/CpuDxe/CpuDxe.inf
INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+INF OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
INF OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -217,6 +218,7 @@ INF OvmfPkg/Virtio10Dxe/Virtio10.inf
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
INF OvmfPkg/VirtioRngDxe/VirtioRng.inf
+INF OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.inf
!if $(SECURE_BOOT_ENABLE) == TRUE
INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/Bhyve/PlatformPei/MemDetect.c b/OvmfPkg/Bhyve/PlatformPei/MemDetect.c
index 1b556be69c..80ac24a813 100644
--- a/OvmfPkg/Bhyve/PlatformPei/MemDetect.c
+++ b/OvmfPkg/Bhyve/PlatformPei/MemDetect.c
@@ -30,6 +30,7 @@ Module Name:
#include <Library/PcdLib.h>
#include <Library/PciLib.h>
#include <Library/PeimEntryPoint.h>
+#include <Library/QemuFwCfgLib.h>
#include <Library/ResourcePublicationLib.h>
#include <Library/MtrrLib.h>
@@ -352,6 +353,9 @@ PublishPeiMemory (
VOID
)
{
+ EFI_E820_ENTRY64 E820Entry;
+ FIRMWARE_CONFIG_ITEM Item;
+ UINTN ItemSize;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS MemoryBase;
UINT64 MemorySize;
@@ -407,6 +411,78 @@ PublishPeiMemory (
}
}
+ //
+ // Bhyve uses an E820 table to reserve certain kinds of memory like Graphics
+ // Stolen Memory. These reserved memory regions could overlap with the PEI
+ // core memory which leads to undefined behaviour. Check the E820 table for
+ // a memory region starting at or below MemoryBase which is equal or larger
+ // than MemorySize.
+ //
+ if (!EFI_ERROR (QemuFwCfgFindFile("etc/e820", &Item, &ItemSize))) {
+ //
+ // Set a new base address based on E820 table.
+ //
+
+ EFI_PHYSICAL_ADDRESS MaxAddress;
+ UINT64 EntryEnd;
+ UINT64 EndAddr;
+
+ if (ItemSize % sizeof (E820Entry) != 0) {
+ DEBUG ((DEBUG_INFO, "%a: invalid E820 size\n", __FUNCTION__));
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ QemuFwCfgSelectItem(Item);
+
+ MaxAddress = MemoryBase + MemorySize;
+ MemoryBase = 0;
+
+ for (UINTN i = 0; i < ItemSize; i += sizeof (E820Entry)) {
+
+ QemuFwCfgReadBytes (sizeof (E820Entry), &E820Entry);
+
+ if (E820Entry.BaseAddr > MaxAddress) {
+ //
+ // E820 is always sorted in ascending order. For that reason, BaseAddr
+ // will always be larger than MaxAddress for the following entries.
+ //
+ break;
+ } else if (E820Entry.Type != EfiAcpiAddressRangeMemory) {
+ continue;
+ }
+
+ //
+ // Since MemoryBase should be at top of the memory, calculate the end
+ // address of the entry. Additionally, MemoryBase and MemorySize are page
+ // aligned. For that reason, page align EntryEnd too.
+ //
+ EntryEnd = (E820Entry.BaseAddr + E820Entry.Length) & ~EFI_PAGE_MASK;
+ if (E820Entry.BaseAddr > EntryEnd) {
+ //
+ // Either BaseAddr + Length overflows or the entry is smaller than a
+ // page. In both cases, we can't use it.
+ //
+ continue;
+ }
+
+ EndAddr = MIN (EntryEnd, MaxAddress);
+ if (EndAddr - E820Entry.BaseAddr < MemorySize) {
+ //
+ // E820 entry is too small for the Pei core memory.
+ //
+ continue;
+ }
+
+ MemoryBase = EndAddr - MemorySize;
+ }
+
+ if (MemoryBase == 0) {
+ DEBUG ((DEBUG_ERROR, "%a: Unable to find suitable PeiCore address\n",
+ __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
//
// Publish this memory to the PEI Core
//
diff --git a/OvmfPkg/Bhyve/PlatformPei/Platform.c b/OvmfPkg/Bhyve/PlatformPei/Platform.c
index c23b906733..788198e70e 100644
--- a/OvmfPkg/Bhyve/PlatformPei/Platform.c
+++ b/OvmfPkg/Bhyve/PlatformPei/Platform.c
@@ -27,6 +27,7 @@
#include <Library/PciLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
+#include <Library/QemuFwCfgLib.h>
#include <Library/ResourcePublicationLib.h>
#include <Guid/MemoryTypeInformation.h>
#include <Ppi/MasterBootMode.h>
@@ -487,6 +488,110 @@ DebugDumpCmos (
}
+STATIC
+EFI_STATUS
+E820ReserveMemory (
+ VOID
+ )
+{
+ EFI_E820_ENTRY64 E820Entry;
+ FIRMWARE_CONFIG_ITEM Item;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Status = QemuFwCfgFindFile ("etc/e820", &Item, &Size);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: E820 not found: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ if (Size % sizeof (E820Entry) != 0) {
+ DEBUG ((DEBUG_INFO, "%a: invalid E820 size\n", __FUNCTION__));
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ QemuFwCfgSelectItem (Item);
+ for (UINTN i = 0; i < Size; i += sizeof (E820Entry)) {
+ UINT64 Base;
+ UINT64 End;
+
+ QemuFwCfgReadBytes (sizeof (E820Entry), &E820Entry);
+
+ DEBUG_CODE (
+ CHAR8 *E820TypeName;
+ switch (E820Entry.Type) {
+ case EfiAcpiAddressRangeMemory:
+ E820TypeName = "RAM ";
+ break;
+ case EfiAcpiAddressRangeReserved:
+ E820TypeName = "Reserved";
+ break;
+ case EfiAcpiAddressRangeACPI:
+ E820TypeName = "ACPI ";
+ break;
+ case EfiAcpiAddressRangeNVS:
+ E820TypeName = "NVS ";
+ break;
+ default:
+ E820TypeName = "Unknown ";
+ break;
+ }
+ DEBUG ((DEBUG_INFO, "E820 entry [ %16lx, %16lx] (%a)\n",
+ E820Entry.BaseAddr, E820Entry.BaseAddr + E820Entry.Length,
+ E820TypeName));
+ );
+
+ //
+ // Round down base and round up length to page boundary
+ //
+ Base = E820Entry.BaseAddr & ~(UINT64)EFI_PAGE_MASK;
+ End = ALIGN_VALUE (
+ E820Entry.BaseAddr + E820Entry.Length,
+ (UINT64)EFI_PAGE_SIZE
+ );
+
+ switch (E820Entry.Type) {
+ case EfiAcpiAddressRangeReserved:
+ BuildMemoryAllocationHob (
+ Base,
+ End - Base,
+ EfiReservedMemoryType
+ );
+ break;
+
+ case EfiAcpiAddressRangeACPI:
+ BuildMemoryAllocationHob (
+ Base,
+ End - Base,
+ EfiACPIReclaimMemory
+ );
+ break;
+
+ case EfiAcpiAddressRangeNVS:
+ BuildMemoryAllocationHob (
+ Base,
+ End - Base,
+ EfiACPIMemoryNVS
+ );
+ break;
+
+ case EfiAcpiAddressRangeMemory:
+ //
+ // EfiAcpiAddressRangeMemory is usable. Do not build an Allocation HOB.
+ //
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Unknown E820 type %d\n", __FUNCTION__,
+ E820Entry.Type));
+ return EFI_PROTOCOL_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
VOID
S3Verification (
VOID
@@ -563,6 +668,10 @@ InitializePlatform (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
+ EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM Item;
+ UINTN Size;
+
DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
//
@@ -575,6 +684,16 @@ InitializePlatform (
DebugDumpCmos ();
+ //
+ // If an E820 table exists, Memory should be reserved by E820.
+ //
+ if (!EFI_ERROR (QemuFwCfgFindFile("etc/e820", &Item, &Size))) {
+ Status = E820ReserveMemory ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
BootModeInitialization ();
AddressWidthInitialization ();
MaxCpuCountInitialization ();
diff --git a/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf b/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
index 739d63098b..557a8f890e 100644
--- a/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
@@ -59,6 +59,7 @@
PeiServicesLib
PeiServicesTablePointerLib
PcdLib
+ QemuFwCfgLib
ResourcePublicationLib
[Pcd]
diff --git a/OvmfPkg/Include/IndustryStandard/IgdOpRegion.h b/OvmfPkg/Include/IndustryStandard/IgdOpRegion.h
new file mode 100644
index 0000000000..4e9180c86b
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/IgdOpRegion.h
@@ -0,0 +1,181 @@
+/** @file
+ IGD OpRegion definition from Intel Integrated Graphics Device OpRegion
+ Specification.
+
+ https://01.org/sites/default/files/documentation/skl_opregion_rev0p5.pdf
+
+ @note Fixed bug in the spec Mailbox3 - RM31 size from 0x45(69) to 0x46(70)
+
+ Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _IGD_OPREGION_H_
+#define _IGD_OPREGION_H_
+
+#define IGD_OPREGION_HEADER_SIGN "IntelGraphicsMem"
+#define IGD_OPREGION_HEADER_MBOX1 BIT0
+#define IGD_OPREGION_HEADER_MBOX2 BIT1
+#define IGD_OPREGION_HEADER_MBOX3 BIT2
+#define IGD_OPREGION_HEADER_MBOX4 BIT3
+#define IGD_OPREGION_HEADER_MBOX5 BIT4
+
+#define IGD_OPREGION_VBT_SIZE_6K (6 * SIZE_1KB)
+
+/**
+ OpRegion structures:
+ Sub-structures define the different parts of the OpRegion followed by the
+ main structure representing the entire OpRegion.
+
+ @note These structures are packed to 1 byte offsets because the exact
+ data location is required by the supporting design specification due to
+ the fact that the data is used by ASL and Graphics driver code compiled
+ separately.
+**/
+#pragma pack(1)
+///
+/// OpRegion Mailbox 0 Header structure. The OpRegion Header is used to
+/// identify a block of memory as the graphics driver OpRegion.
+/// Offset 0x0, Size 0x100
+///
+typedef struct {
+ CHAR8 SIGN[0x10]; ///< Offset 0x00 OpRegion Signature
+ UINT32 SIZE; ///< Offset 0x10 OpRegion Size
+ UINT32 OVER; ///< Offset 0x14 OpRegion Structure Version
+ UINT8 SVER[0x20]; ///< Offset 0x18 System BIOS Build Version
+ UINT8 VVER[0x10]; ///< Offset 0x38 Video BIOS Build Version
+ UINT8 GVER[0x10]; ///< Offset 0x48 Graphic Driver Build Version
+ UINT32 MBOX; ///< Offset 0x58 Supported Mailboxes
+ UINT32 DMOD; ///< Offset 0x5C Driver Model
+ UINT32 PCON; ///< Offset 0x60 Platform Configuration
+ CHAR16 DVER[0x10]; ///< Offset 0x64 GOP Version
+ UINT8 RM01[0x7C]; ///< Offset 0x84 Reserved Must be zero
+} IGD_OPREGION_HEADER;
+
+///
+/// OpRegion Mailbox 1 - Public ACPI Methods
+/// Offset 0x100, Size 0x100
+///
+typedef struct {
+ UINT32 DRDY; ///< Offset 0x100 Driver Readiness
+ UINT32 CSTS; ///< Offset 0x104 Status
+ UINT32 CEVT; ///< Offset 0x108 Current Event
+ UINT8 RM11[0x14]; ///< Offset 0x10C Reserved Must be Zero
+ UINT32 DIDL[8]; ///< Offset 0x120 Supported Display Devices ID List
+ UINT32 CPDL[8]; ///< Offset 0x140 Currently Attached Display Devices List
+ UINT32 CADL[8]; ///< Offset 0x160 Currently Active Display Devices List
+ UINT32 NADL[8]; ///< Offset 0x180 Next Active Devices List
+ UINT32 ASLP; ///< Offset 0x1A0 ASL Sleep Time Out
+ UINT32 TIDX; ///< Offset 0x1A4 Toggle Table Index
+ UINT32 CHPD; ///< Offset 0x1A8 Current Hotplug Enable Indicator
+ UINT32 CLID; ///< Offset 0x1AC Current Lid State Indicator
+ UINT32 CDCK; ///< Offset 0x1B0 Current Docking State Indicator
+ UINT32 SXSW; ///< Offset 0x1B4 Display Switch Notification on Sx State Resume
+ UINT32 EVTS; ///< Offset 0x1B8 Events supported by ASL
+ UINT32 CNOT; ///< Offset 0x1BC Current OS Notification
+ UINT32 NRDY; ///< Offset 0x1C0 Driver Status
+ UINT8 DID2[0x1C]; ///< Offset 0x1C4 Extended Supported Devices ID List (DOD)
+ UINT8 CPD2[0x1C]; ///< Offset 0x1E0 Extended Attached Display Devices List
+ UINT8 RM12[4]; ///< Offset 0x1FC - 0x1FF Reserved Must be zero
+} IGD_OPREGION_MBOX1;
+
+///
+/// OpRegion Mailbox 2 - Software SCI Interface
+/// Offset 0x200, Size 0x100
+///
+typedef struct {
+ UINT32 SCIC; ///< Offset 0x200 Software SCI Command / Status / Data
+ UINT32 PARM; ///< Offset 0x204 Software SCI Parameters
+ UINT32 DSLP; ///< Offset 0x208 Driver Sleep Time Out
+ UINT8 RM21[0xF4]; ///< Offset 0x20C - 0x2FF Reserved Must be zero
+} IGD_OPREGION_MBOX2;
+
+///
+/// OpRegion Mailbox 3 - BIOS/Driver Notification - ASLE Support
+/// Offset 0x300, Size 0x100
+///
+typedef struct {
+ UINT32 ARDY; ///< Offset 0x300 Driver Readiness
+ UINT32 ASLC; ///< Offset 0x304 ASLE Interrupt Command / Status
+ UINT32 TCHE; ///< Offset 0x308 Technology Enabled Indicator
+ UINT32 ALSI; ///< Offset 0x30C Current ALS Luminance Reading
+ UINT32 BCLP; ///< Offset 0x310 Requested Backlight Brightness
+ UINT32 PFIT; ///< Offset 0x314 Panel Fitting State or Request
+ UINT32 CBLV; ///< Offset 0x318 Current Brightness Level
+ UINT16 BCLM[0x14]; ///< Offset 0x31C Backlight Brightness Levels Duty Cycle Mapping Table
+ UINT32 CPFM; ///< Offset 0x344 Current Panel Fitting Mode
+ UINT32 EPFM; ///< Offset 0x348 Enabled Panel Fitting Modes
+ UINT8 PLUT[0x4A]; ///< Offset 0x34C Panel Look Up Table & Identifier
+ UINT32 PFMB; ///< Offset 0x396 PWM Frequency and Minimum Brightness
+ UINT32 CCDV; ///< Offset 0x39A Color Correction Default Values
+ UINT32 PCFT; ///< Offset 0x39E Power Conservation Features
+ UINT32 SROT; ///< Offset 0x3A2 Supported Rotation Angles
+ UINT32 IUER; ///< Offset 0x3A6 Intel Ultrabook(TM) Event Register
+ UINT64 FDSS; ///< Offset 0x3AA DSS Buffer address allocated for IFFS feature
+ UINT32 FDSP; ///< Offset 0x3B2 Size of DSS buffer
+ UINT32 STAT; ///< Offset 0x3B6 State Indicator
+ UINT64 RVDA; ///< Offset 0x3BA Absolute/Relative Address of Raw VBT Data from OpRegion Base
+ UINT32 RVDS; ///< Offset 0x3C2 Raw VBT Data Size
+ UINT8 RSVD3[0x3A]; ///< Offset 0x3C6 - 0x3FF Reserved Must be zero. Bug in spec 0x45(69)
+} IGD_OPREGION_MBOX3;
+
+///
+/// OpRegion Mailbox 4 - VBT Video BIOS Table
+/// Offset 0x400, Size 0x1800
+///
+typedef struct {
+ UINT8 RVBT[IGD_OPREGION_VBT_SIZE_6K]; ///< Offset 0x400 - 0x1BFF Raw VBT Data
+} IGD_OPREGION_MBOX4;
+
+///
+/// OpRegion Mailbox 5 - BIOS/Driver Notification - Data storage BIOS to Driver data sync
+/// Offset 0x1C00, Size 0x400
+///
+typedef struct {
+ UINT32 PHED; ///< Offset 0x1C00 Panel Header
+ UINT8 BDDC[0x100]; ///< Offset 0x1C04 Panel EDID (DDC data)
+ UINT8 RM51[0x2FC]; ///< Offset 0x1D04 - 0x1FFF Reserved Must be zero
+} IGD_OPREGION_MBOX5;
+
+///
+/// IGD OpRegion Structure
+///
+typedef struct {
+ IGD_OPREGION_HEADER Header; ///< OpRegion header (Offset 0x0, Size 0x100)
+ IGD_OPREGION_MBOX1 MBox1; ///< Mailbox 1: Public ACPI Methods (Offset 0x100, Size 0x100)
+ IGD_OPREGION_MBOX2 MBox2; ///< Mailbox 2: Software SCI Interface (Offset 0x200, Size 0x100)
+ IGD_OPREGION_MBOX3 MBox3; ///< Mailbox 3: BIOS to Driver Notification (Offset 0x300, Size 0x100)
+ IGD_OPREGION_MBOX4 MBox4; ///< Mailbox 4: Video BIOS Table (VBT) (Offset 0x400, Size 0x1800)
+ IGD_OPREGION_MBOX5 MBox5; ///< Mailbox 5: BIOS to Driver Notification Extension (Offset 0x1C00, Size 0x400)
+} IGD_OPREGION_STRUCTURE;
+
+///
+/// VBT Header Structure
+///
+typedef struct {
+ UINT8 Product_String[20];
+ UINT16 Version;
+ UINT16 Header_Size;
+ UINT16 Table_Size;
+ UINT8 Checksum;
+ UINT8 Reserved1;
+ UINT32 Bios_Data_Offset;
+ UINT32 Aim_Data_Offset[4];
+} VBT_HEADER;
+
+typedef struct {
+ UINT8 BDB_Signature[16];
+ UINT16 BDB_Version;
+ UINT16 BDB_Header_Size;
+ UINT16 BDB_Size;
+} VBT_BIOS_DATA_HEADER;
+
+#pragma pack()
+
+#endif
diff --git a/OvmfPkg/Include/Protocol/PlatformGopPolicy.h b/OvmfPkg/Include/Protocol/PlatformGopPolicy.h
new file mode 100644
index 0000000000..9c3a9a07c8
--- /dev/null
+++ b/OvmfPkg/Include/Protocol/PlatformGopPolicy.h
@@ -0,0 +1,68 @@
+/*++
+
+Copyright (c) 1999 - 2019, Intel Corporation. All rights reserved
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+--*/
+
+/** @file
+**/
+
+#ifndef _PLATFORM_GOP_POLICY_PROTOCOL_H_
+#define _PLATFORM_GOP_POLICY_PROTOCOL_H_
+
+#define EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID \
+ { 0xec2e931b, 0x3281, 0x48a5, 0x81, 0x7, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d }
+
+#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01 0x01
+#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_02 x0222
+
+#pragma pack(1)
+
+typedef enum {
+ LidClosed,
+ LidOpen,
+ LidStatusMax
+} LID_STATUS;
+
+typedef enum {
+ Docked,
+ UnDocked,
+ DockStatusMax
+} DOCK_STATUS;
+
+typedef
+EFI_STATUS
+(EFIAPI *GET_PLATFORM_LID_STATUS) (
+ OUT LID_STATUS *CurrentLidStatus
+);
+
+typedef
+EFI_STATUS
+(EFIAPI *GET_VBT_DATA) (
+ OUT EFI_PHYSICAL_ADDRESS *VbtAddress,
+ OUT UINT32 *VbtSize
+);
+
+#pragma pack()
+
+typedef struct _PLATFORM_GOP_POLICY_PROTOCOL {
+ UINT32 Revision;
+ GET_PLATFORM_LID_STATUS GetPlatformLidStatus;
+ GET_VBT_DATA GetVbtData;
+} PLATFORM_GOP_POLICY_PROTOCOL;
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPlatformGOPPolicyGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 340d83f794..b4bc2355e8 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -148,6 +148,7 @@
gEfiLegacyInterruptProtocolGuid = {0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe}}
gEfiVgaMiniPortProtocolGuid = {0xc7735a2f, 0x88f5, 0x4882, {0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3}}
gOvmfLoadedX86LinuxKernelProtocolGuid = {0xa3edc05d, 0xb618, 0x4ff6, {0x95, 0x52, 0x76, 0xd7, 0x88, 0x63, 0x43, 0xc8}}
+ gPlatformGOPPolicyGuid = {0xec2e931b, 0x3281, 0x48a5, {0x81, 0x07, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d}}
[PcdsFixedAtBuild]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0
diff --git a/OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.c b/OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.c
new file mode 100644
index 0000000000..ebff16b795
--- /dev/null
+++ b/OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.c
@@ -0,0 +1,295 @@
+/** @file
+ Platform GOP Policy
+
+ GOP drivers calls GetVbtData to get the Video BIOS Table of the Intel Graphics
+ Device.
+
+ Copyright (C) 1999 - 2019, Intel Corporation. All rights reserved
+ Copyright (C) 2021, Beckhoff Automation GmbH & Co. KG. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PlatformGopPolicy.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PciLib.h>
+
+#include <IndustryStandard/IgdOpRegion.h>
+#include <IndustryStandard/Pci22.h>
+
+//
+// IGD is always located at 0:2.0
+//
+#define IGD_PCI_BUS 0
+#define IGD_PCI_SLOT 2
+#define IGD_PCI_FUNC 0
+
+#define IGD_PCI_ASLS_OFFSET 0xFC
+
+#define IGD_PCI_VENDOR_ID 0x8086
+
+PLATFORM_GOP_POLICY_PROTOCOL mPlatformGOPPolicy;
+VBT_HEADER *mVbt;
+
+/**
+ The function returns the Platform Lid Status. IBV/OEM can customize this code
+ for their specific policy action.
+
+ @param[out] CurrentLidStatus Current LID Status.
+
+ @retval EFI_UNSUPPORTED Function isn't implemented yet.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformLidStatus (
+ OUT LID_STATUS *CurrentLidStatus
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The function returns the Video Bios Table size and address.
+
+ @param[out] VbtAddress Physical Address of Video BIOS Table
+
+ @param[out] VbtSize Size of Video BIOS Table
+
+ @retval EFI_STATUS Successfully returned Video BIOS Table address and
+ size.
+
+**/
+
+EFI_STATUS
+EFIAPI
+GetVbtData (
+ OUT EFI_PHYSICAL_ADDRESS *VbtAddress,
+ OUT UINT32 *VbtSize
+)
+{
+ EFI_STATUS Status;
+ IGD_OPREGION_STRUCTURE *OpRegion;
+ VBT_HEADER *Vbt;
+ UINT8 CheckSum = 0;
+ UINT16 VersionMajor;
+ UINT16 VersionMinor;
+ UINT32 VbtSizeMax = 0;
+ UINT16 VendorId;
+ UINT32 ClassCode;
+
+ //
+ // Check if vendor is Intel
+ //
+ VendorId = PciRead16 (
+ PCI_LIB_ADDRESS (
+ IGD_PCI_BUS,
+ IGD_PCI_SLOT,
+ IGD_PCI_FUNC,
+ PCI_VENDOR_ID_OFFSET
+ )
+ );
+ if (VendorId == 0xFFFF) {
+ return EFI_NOT_FOUND;
+ } else if (VendorId != IGD_PCI_VENDOR_ID) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check if class is display device
+ //
+ ClassCode = PciRead32 (
+ PCI_LIB_ADDRESS (
+ IGD_PCI_BUS,
+ IGD_PCI_SLOT,
+ IGD_PCI_FUNC,
+ PCI_CLASSCODE_OFFSET & ~0x3
+ )
+ );
+ if (((ClassCode >> 24) & 0xFF) != PCI_CLASS_DISPLAY ||
+ ((ClassCode >> 16) & 0xFF) != PCI_CLASS_DISPLAY_VGA ||
+ ((ClassCode >> 8) & 0xFF) != PCI_IF_VGA_VGA) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get OpRegion.
+ //
+ OpRegion = (IGD_OPREGION_STRUCTURE *)(UINTN)PciRead32 (
+ PCI_LIB_ADDRESS (
+ 0,
+ 2,
+ 0,
+ IGD_PCI_ASLS_OFFSET
+ )
+ );
+ if (OpRegion == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: Failed to get OpRegion address\n",
+ __FUNCTION__));
+ }
+
+ //
+ // Check if Intel Graphics Device has an OpRegion.
+ //
+ if (!OpRegion) {
+ DEBUG ((EFI_D_ERROR, "%a: No OpRegion found\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check OpRegion signature.
+ //
+ if (CompareMem (OpRegion->Header.SIGN, IGD_OPREGION_HEADER_SIGN, sizeof (OpRegion->Header.SIGN)) != 0) {
+ DEBUG ((EFI_D_ERROR, "%a: Invalid OpRegion signature (%a), expected %a\n",
+ __FUNCTION__, OpRegion->Header.SIGN, IGD_OPREGION_HEADER_SIGN));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ VersionMajor = OpRegion->Header.OVER >> 24;
+ VersionMinor = OpRegion->Header.OVER >> 16 & 0xFF;
+
+ //
+ // Only OpRegion v2.0 and higher is supported.
+ //
+ if (VersionMajor < 2) {
+ DEBUG ((EFI_D_ERROR, "%a: Unsupported OpRegion version %d.%d\n", __FUNCTION__,
+ VersionMajor, VersionMinor));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If the size of the Video BIOS Table larger then 6K, the Video BIOS Table is
+ // stored outside the OpRegion. In that case, the address and size of the
+ // Video BIOS Table are stored in MailBox3 (RVDA and RVDS). When OpRegion v2.0
+ // is used, RVDA is a physical address. In a virtual environment this physical
+ // address is invalid. For that reason, we do not support a Video BIOS Table
+ // which is larger than 6K for OpRegion v2.0.
+ //
+ if (VersionMajor == 2 &&
+ VersionMinor == 0 &&
+ OpRegion->MBox3.RVDA &&
+ OpRegion->MBox3.RVDS) {
+ DEBUG ((EFI_D_ERROR,
+ "%a: VBT larger than 6K is unsupported for OpRegion v2.0\n",
+ __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get Video BIOS Table size.
+ //
+ VbtSizeMax = IGD_OPREGION_VBT_SIZE_6K;
+ if (OpRegion->MBox3.RVDA && OpRegion->MBox3.RVDS) {
+ Vbt = (VBT_HEADER *)((UINT8 *)OpRegion + OpRegion->MBox3.RVDA);
+ VbtSizeMax = *VbtSize;
+ } else {
+ Vbt = (VBT_HEADER *)&OpRegion->MBox4;
+ VbtSizeMax = IGD_OPREGION_VBT_SIZE_6K;
+ }
+
+ //
+ // Free old Video BIOS Table.
+ //
+ if (mVbt) {
+ Status = gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS)mVbt,
+ EFI_SIZE_TO_PAGES (VbtSizeMax)
+ );
+ }
+
+ //
+ // Allocate Video BIOS Table.
+ //
+ mVbt = (VBT_HEADER *)(SIZE_4GB - 1);
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (VbtSizeMax),
+ (EFI_PHYSICAL_ADDRESS *)&mVbt
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR,
+ "%a: AllocatePages failed for VBT size 0x%x status %d\n", __FUNCTION__,
+ VbtSizeMax, Status));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy Video BIOS Table to allocated space.
+ //
+ ZeroMem ((VOID*)mVbt, VbtSizeMax);
+ CopyMem((VOID*)mVbt, (VOID*)Vbt, Vbt->Table_Size);
+
+ //
+ // Fix checksum.
+ //
+ for (UINT32 i = 0; i < mVbt->Table_Size; i++) {
+ CheckSum = (CheckSum + ((UINT8*)mVbt)[i]) & 0xFF;
+ }
+ mVbt->Checksum += (0x100 - CheckSum);
+
+ //
+ // Return Video BIOS Table address and size.
+ //
+ *VbtAddress = (EFI_PHYSICAL_ADDRESS)mVbt;
+ *VbtSize = mVbt->Table_Size;
+ DEBUG ((DEBUG_INFO, "%a: VBT Version %d size 0x%x\n", __FUNCTION__,
+ ((VBT_BIOS_DATA_HEADER*)((VOID *)mVbt + mVbt->Bios_Data_Offset))->BDB_Version,
+ mVbt->Table_Size));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry point for the Platform GOP Policy Driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+
+ @return Error codes propagated from underlying functions.
+**/
+
+EFI_STATUS
+EFIAPI
+PlatformGOPPolicyEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+
+{
+ EFI_STATUS Status;
+
+ gBS = SystemTable->BootServices;
+
+ mPlatformGOPPolicy.Revision = PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01;
+ mPlatformGOPPolicy.GetPlatformLidStatus = GetPlatformLidStatus;
+ mPlatformGOPPolicy.GetVbtData = GetVbtData;
+
+ //
+ // Install protocol to allow access to this Policy.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPlatformGOPPolicyGuid,
+ &mPlatformGOPPolicy,
+ NULL
+ );
+
+ return Status;
+}
diff --git a/OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.inf b/OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.inf
new file mode 100644
index 0000000000..8bf6f60f8f
--- /dev/null
+++ b/OvmfPkg/PlatformGopPolicy/PlatformGopPolicy.inf
@@ -0,0 +1,52 @@
+## @file
+# Platform GOP Policy
+#
+# GOP drivers calls GetVbtData to get the Video BIOS Table of the Intel Graphics
+# Device.
+#
+# Copyright (c) 1999 - 2019, Intel Corporation. All rights reserved
+# Copyrigth (C) 2021, Beckhoff Automation GmbH & Co. KG. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformGOPPolicy
+ FILE_GUID = 9737D7CA-D869-45e5-A5EF-75D9438688DE
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformGOPPolicyEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources.common]
+ PlatformGopPolicy.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ PciLib
+
+[Protocols]
+ gPlatformGOPPolicyGuid
+
+[Depex]
+ TRUE

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4224220
Default Alt Text
GVT-d_v1.diff (43 KB)

Event Timeline