summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.c')
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.c958
1 files changed, 958 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.c
new file mode 100644
index 0000000..599a01a
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.c
@@ -0,0 +1,958 @@
+/** @file
+ SwitchableGraphics Dxe driver.
+ This DXE driver loads SwitchableGraphics acpi tables
+ for the platform.
+
+@copyright
+ Copyright (c) 2010 - 2013 Intel Corporation. All rights reserved.
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+
+#include "SwitchableGraphicsInit.h"
+#include EFI_PROTOCOL_CONSUMER (ExitPmAuth)
+#include <Token.h> //<< AMI_OVERRIDE >>
+
+extern DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy;
+
+EFI_BOOT_SERVICES *gBS;
+SA_DATA_HOB *SaDataHob;
+
+EFI_GUID gSaDataHobGuid = SA_DATA_HOB_GUID;
+EFI_GUID gSgAcpiTableStorageGuid = SG_ACPI_TABLE_STORAGE_GUID;
+EFI_GUID gSgAcpiTablePchStorageGuid = SG_ACPI_TABLE_PCH_STORAGE_GUID;
+
+VOID *VbiosAddress = NULL;
+BOOLEAN DgpuOpRomCopied;
+UINT32 VbiosSize;
+
+UINT8 EndpointBus;
+UINT16 GpioBaseAddress;
+UINT8 GpioSupport;
+
+UINT8 RootPortDev;
+UINT8 RootPortFun;
+
+CPU_FAMILY CpuFamilyId;
+
+// AMI MODIFY BEGIN
+EFI_STATUS
+LoadTpvAcpiTables(
+ VOID
+ );
+// AMI MODIFY END
+
+/**
+ Initialize the SwitchableGraphics support (DXE).
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - SwitchableGraphics initialization complete
+ @retval EFI_OUT_OF_RESOURCES - Unable to allocated memory
+ @retval EFI_NOT_FOUND - SA DataHob not found
+ @retval EFI_DEVICE_ERROR - Error Accessing SG GPIO
+**/
+EFI_STATUS
+SwitchableGraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+ UINTN PciD31F0RegBase;
+ UINT32 RootComplexBar;
+ UINT32 RpFn;
+
+ CpuFamilyId = GetCpuFamily();
+
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ /// For SwitchableGraphics support the dGPU is present on PCH RootPort
+ RootPortDev = PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS;
+ //AMI override begin
+ RootPortFun = SG_ULT_PORT_FUNC;
+ //RootPortFun = PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5;
+ //AMI override end
+
+ PciD31F0RegBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ 0
+ );
+ RootComplexBar = MmioRead32 (PciD31F0RegBase + R_PCH_LPC_RCBA) & B_PCH_LPC_RCBA_BAR;
+ RpFn = MmioRead32 (RootComplexBar + R_PCH_RCRB_RPFN);
+ /// dGPU sits on Root Port 5 [1-based]
+ /// Root Port 5 Function Number (RP5FN) = RPFN[18:16]
+ //AMI override begin
+ //RootPortFun = (UINT8) ((RpFn >> (4 * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN);
+ RootPortFun = (UINT8) ((RpFn >> (RootPortFun * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN);
+ ////AMI override end
+ } else {
+ /// Assume: For SwitchableGraphics support the dGPU is present on PEG RootPort by default
+ RootPortDev = SA_PEG10_DEV_NUM;
+ RootPortFun = SA_PEG10_FUN_NUM;
+ }
+
+ DEBUG ((EFI_D_INFO, "dGPU Rootport info[B/D/F] : [0x00/0x%x/0x%x]\n", RootPortDev, RootPortFun));
+
+ gBS = SystemTable->BootServices;
+
+ ///
+ /// Get SG GPIO info from SA HOB.
+ ///
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, (VOID **) &SaDataHob);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SaDataHob = GetNextGuidHob (&gSaDataHobGuid, SaDataHob);
+ if (SaDataHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ GpioSupport = SaDataHob->SgInfo.SgGpioSupport;
+
+ ///
+ /// Read GPIO base
+ ///
+ GpioBaseAddress = McDevFunPciCfg16 (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GPIO_BASE) &~BIT0;
+ if (GpioBaseAddress == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ ///
+ /// Update GlobalNvs data for runtime usage
+ ///
+ Status = UpdateGlobalNvsData (SaDataHob->SgInfo, DxePlatformSaPolicy);
+// AMI MODIFY BEGIN
+ DEBUG ((EFI_D_INFO, "SG:: OEM SSDT start"));
+#if SGOEMSSDT_SUPPORT
+ // Load OEM SSDT
+ if (SaDataHob->SgInfo.SgMode == SgModeDgpu) { // In PEG mode
+
+ DEBUG ((EFI_D_INFO, "SG:: OEM SSDT start1"));
+ Status = LoadAndExecuteDgpuVbios (mDxePlatformSaPolicy->VbiosConfig);
+ return Status;
+ }
+#endif
+// AMI MODIFY END
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Load Intel SG SSDT tables
+ ///
+ Status = LoadAcpiTables ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Check to see if Switchable Graphics Mode is enabled
+ ///
+ if (SaDataHob->SgInfo.SgMode == SgModeMuxless) {
+ ///
+ /// Create ReadyToBoot callback for SG
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ SgExitPmAuthCallback,
+ NULL,
+ &Registration
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Initialize the runtime SwitchableGraphics support data for ACPI tables in GlobalNvs.
+
+ @param[in] SaDataHob->SgInfo - Pointer to Hob for SG system details.
+ @param[in] DxePlatformSaPolicy - Pointer to the loaded image protocol for this driver.
+
+ @retval EFI_SUCCESS - The data updated successfully.
+**/
+EFI_STATUS
+UpdateGlobalNvsData (
+ IN SG_INFO_HOB SgInfo,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+{
+ SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL *SaGlobalNvsArea;
+ UINT8 CapOffset;
+ UINT16 ExtendedCapOffset;
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ ///
+ /// Locate the SA Global NVS Protocol.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &SaGlobalNvsArea
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// SG Mode for ASL usage
+ ///
+ SaGlobalNvsArea->Area->SgMode |= SaDataHob->SgInfo.SgMode;
+
+ SaGlobalNvsArea->Area->PXFixedDynamicMode = SaDataHob->SgInfo.PXFixedDynamicMode; // AMI_OVERRIDE_FOR ATI 5.0 Fixed/Dynamic
+
+ SaGlobalNvsArea->Area->GpioBaseAddress = GpioBaseAddress;
+
+ SaGlobalNvsArea->Area->SgGPIOSupport = SaDataHob->SgInfo.SgGpioSupport;
+
+ DEBUG ((EFI_D_INFO, "SG:: Switchable Graphics Mode : 0x%x\n", SaDataHob->SgInfo.SgMode));
+
+ if (SaDataHob->SgInfo.SgMode == SgModeMuxless) {
+ ///
+ /// SG Feature List for ASL usage
+ ///
+ //SaGlobalNvsArea->Area->SgFeatureList |= DxePlatformSaPolicy->FeatureList->WirelessDisplay;
+
+ if (SaDataHob->SgInfo.SgGpioSupport) {
+ ///
+ /// GPIO Assignment for ASL usage
+ ///
+ SaGlobalNvsArea->Area->SgDgpuPwrOK = SaDataHob->SgInfo.SgDgpuPwrOK;
+ SaGlobalNvsArea->Area->SgDgpuHoldRst = SaDataHob->SgInfo.SgDgpuHoldRst;
+ SaGlobalNvsArea->Area->SgDgpuPwrEnable = SaDataHob->SgInfo.SgDgpuPwrEnable;
+ SaGlobalNvsArea->Area->SgDgpuPrsnt = SaDataHob->SgInfo.SgDgpuPrsnt;
+
+ DEBUG ((EFI_D_INFO, "SG:: dGPU_PWROK GPIO GPIO assigned = %d\n", SaDataHob->SgInfo.SgDgpuPwrOK & 0x7f));
+ DEBUG ((EFI_D_INFO, "SG:: dGPU_HOLD_RST# GPIO assigned = %d\n", SaDataHob->SgInfo.SgDgpuHoldRst & 0x7f));
+ DEBUG ((EFI_D_INFO, "SG:: dGPU_PWR_EN# GPIO assigned = %d\n", SaDataHob->SgInfo.SgDgpuPwrEnable & 0x7f));
+ DEBUG ((EFI_D_INFO, "SG:: dGPU_PRSNT# GPIO assigned = %d\n", SaDataHob->SgInfo.SgDgpuPrsnt & 0x7f));
+ }
+
+ DEBUG ((EFI_D_INFO, "SG:: VBIOS Configurations:\n"));
+ DEBUG (
+ (
+ EFI_D_INFO, "SG:: Load VBIOS (0=No Vbios;1=Load VBIOS) =%d\n", DxePlatformSaPolicy->VbiosConfig->
+ LoadVbios
+ )
+ );
+ DEBUG (
+ (
+ EFI_D_INFO, "SG:: Execute VBIOS (0=Do not execute;1=Execute Vbios) =%d\n", DxePlatformSaPolicy->VbiosConfig->
+ ExecuteVbios
+ )
+ );
+ DEBUG (
+ (
+ EFI_D_INFO, "SG:: VBIOS Source (0=PCIE Card;1=FW Volume) =%d\n", DxePlatformSaPolicy->VbiosConfig->
+ VbiosSource
+ )
+ );
+
+ ///
+ /// PEG Endpoint Base Addresses and Capability Structure Offsets for ASL usage
+ ///
+
+ ///
+ /// Save bus numbers on the PEG/PCH bridge.
+ ///
+ Data32 = MmPci32 (0, 0, RootPortDev, RootPortFun, PCI_PBUS);
+ Data32 &= 0x00FFFF00;
+
+ ///
+ /// Set PEG/PCH PortBus = 1 to Read Endpoint.
+ ///
+ MmPci32AndThenOr (0, 0, RootPortDev, RootPortFun, PCI_PBUS, 0xFF0000FF, 0x00010100);
+
+ ///
+ /// A config write is required in order for the device to re-capture the Bus number,
+ /// according to PCI Express Base Specification, 2.2.6.2
+ /// Write to a read-only register VendorID to not cause any side effects.
+ ///
+ McDevFunPciCfg16 (1, 0, 0, PCI_VID) = 0;
+
+ EndpointBus = MmPci8 (0, 0, RootPortDev, RootPortFun, PCI_SBUS);
+
+ if (EndpointBus != 0xFF) {
+ //AMI override begin
+ SaGlobalNvsArea->Area->EndpointBaseAddress = (UINT32) (MmPciAddress (0, EndpointBus, 0, 0, 0x0));
+ //AMI override end
+ SaGlobalNvsArea->Area->CapStrPresence = 0;
+
+ CapOffset = (UINT8) PcieFindCapId (EndpointBus, 0, 0, PEG_CAP_ID);
+ SaGlobalNvsArea->Area->EndpointPcieCapOffset = CapOffset;
+ DEBUG ((EFI_D_INFO, "SG:: Endpoint PCI Express Capability Offset : 0x%x\n", SaGlobalNvsArea->Area->EndpointPcieCapOffset));
+
+ ExtendedCapOffset = (UINT16) PcieFindExtendedCapId (EndpointBus, 0, 0, PEG_CAP_VER);
+ if (ExtendedCapOffset != 0) {
+ SaGlobalNvsArea->Area->CapStrPresence |= BIT0;
+ SaGlobalNvsArea->Area->EndpointVcCapOffset = ExtendedCapOffset;
+ DEBUG ((EFI_D_INFO, "SG:: Endpoint Virtual Channel Capability Offset : 0x%x\n", SaGlobalNvsArea->Area->EndpointVcCapOffset));
+ }
+ }
+
+ ///
+ /// Restore bus numbers on the PEG/PCH bridge.
+ ///
+ MmPci32AndThenOr (0, 0, RootPortDev, RootPortFun, PCI_PBUS, 0xFF0000FF, Data32);
+ } else {
+ DEBUG ((EFI_D_ERROR, "SG:: Switchable Graphics Mode disabled!!!\n"));
+ Status = EFI_LOAD_ERROR;
+ }
+
+ return Status;
+}
+
+/**
+ Load and execute the dGPU VBIOS.
+
+ @param[in] VbiosConfig - Pointer to VbiosConfig policy for Load/Execute and VBIOS Source.
+ LoadVbios - 0 = Do Not Load ; 1 = Load VBIOS
+ ExecuteVbios - 0 = Do Not Execute; 1 = Execute VBIOS
+ VbiosSource - 0 = PCIE Device ; 1 = FirmwareVolume => TBD
+
+ @retval EFI_SUCCESS - Load and execute successful.
+ @exception EFI_UNSUPPORTED - Secondary VBIOS not loaded.
+**/
+EFI_STATUS
+LoadAndExecuteDgpuVbios (
+ IN SA_SG_VBIOS_CONFIGURATION *VbiosConfig
+ )
+{
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ VBIOS_PCIR_STRUCTURE *PcirBlockPtr;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ VBIOS_OPTION_ROM_HEADER *VBiosRomImage;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_IA32_REGISTER_SET RegSet;
+ EFI_PHYSICAL_ADDRESS ImageLocation;
+ UINTN Offset;
+
+ HandleBuffer = NULL;
+ DgpuOpRomCopied = FALSE;
+
+ DEBUG ((EFI_D_INFO, "SG:: LoadAndExecuteDgpuVbios\n"));
+
+ ///
+ /// Endpoint Device Bus#
+ ///
+ EndpointBus = MmPci8 (0, 0, RootPortDev, RootPortFun, PCI_SBUS);
+
+ ///
+ /// Endpoint Device Not found
+ ///
+ if (EndpointBus == 0xFF) {
+ DEBUG ((EFI_D_ERROR, "SG:: 0x00/0x%x/0x%x Rootport's Endpoint Device Not found\n", RootPortDev, RootPortFun));
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// Check Policy setting for loading VBIOS
+ ///
+ if (VbiosConfig->LoadVbios != 0) {
+
+ DEBUG ((EFI_D_INFO, "SG:: Start to load dGPU VBIOS if available\n"));
+
+ ///
+ /// Set as if an umcompressed video BIOS image was not obtainable.
+ ///
+ VBiosRomImage = NULL;
+
+ ///
+ /// Get all PCI IO protocols
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Find the video BIOS by checking each PCI IO handle for DGPU video
+ /// BIOS OPROM.
+ ///
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ if (EFI_ERROR (Status) || (PciIo->RomImage == NULL)) {
+ ///
+ /// If this PCI device doesn't have a ROM image, skip to the next device.
+ ///
+ continue;
+ }
+
+ VBiosRomImage = PciIo->RomImage;
+
+ ///
+ /// Get pointer to PCIR structure
+ ///
+ PcirBlockPtr = (VBIOS_PCIR_STRUCTURE *) ((UINTN) VBiosRomImage + VBiosRomImage->PcirOffset);
+ //AMI override begin
+ if (( PcirBlockPtr->VendorId != 0x10DE) && (PcirBlockPtr->VendorId != 0x1002)){
+ continue;
+ }
+ //AMI override end
+ ///
+ /// Check if we have an video BIOS OPROM for DGPU.
+ ///
+ if ((VBiosRomImage->Signature == OPTION_ROM_SIGNATURE) &&
+ (McDevFunPciCfg16 (EndpointBus, 0, 0, PCI_VID) == PcirBlockPtr->VendorId) &&
+ (PcirBlockPtr->ClassCode[2] == 0x03)
+ ) {
+
+ DEBUG ((EFI_D_INFO, "SG:: Loading dGPU VBIOS...\n"));
+
+ ///
+ /// Allocate space for copying Oprom
+ ///
+ VbiosSize = (PcirBlockPtr->ImageLength) * 512;
+ Status = (gBS->AllocatePool) (EfiBootServicesData, VbiosSize, &VbiosAddress);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ ///
+ /// Execute VBIOS based on Policy setting
+ ///
+ if (VbiosConfig->ExecuteVbios) {
+ DEBUG ((EFI_D_INFO, "SG:: Execute dGPU VBIOS...\n"));
+ ///
+ /// Memory IO Bus Master needs to be enabled when we execute the vbios
+ ///
+ ///
+ /// Enable Memory Access, IO Access Bus Master enable on PEG/PCH ROOT PORT
+ ///
+ MmPci16Or (0, 0, RootPortDev, RootPortFun, PCI_CMD, BIT0 + BIT1 + BIT2);
+
+ ///
+ /// Enable Memory Access, IO Access Bus Master enable and Rom Enable on Peg/PCH Endpoint device
+ ///
+ McDevFunPciCfg16Or (EndpointBus, 0, 0, PCI_CMD, BIT0 + BIT1 + BIT2);
+
+ ///
+ /// Allocate 64kb under 1MB memory region
+ ///
+ Status = AllocateLegacyMemory (
+ AllocateMaxAddress,
+ CONVENTIONAL_MEMORY_TOP,
+ (BIN_FILE_SIZE_MAX / 4096),
+ &ImageLocation
+ );
+ if (!EFI_ERROR (Status)) {
+ (gBS->SetMem) ((VOID *) (UINTN) ImageLocation, BIN_FILE_SIZE_MAX, 0);
+
+ ///
+ /// After allocation copy VBIOS to buffer
+ ///
+ (gBS->CopyMem) ((VOID *) (UINTN) ImageLocation, PciIo->RomImage, VbiosSize);
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+ if (!EFI_ERROR (Status)) {
+ (gBS->SetMem) (&RegSet, sizeof (EFI_IA32_REGISTER_SET), 0);
+
+ RegSet.H.AH = MmPci8 (0, 0, RootPortDev, RootPortFun, PCI_SBUS);
+ Offset = MemoryRead16 ((UINTN) ImageLocation + 0x40);
+ LegacyBios->FarCall86 (
+ LegacyBios,
+ ((UINT16) RShiftU64 ((ImageLocation & 0x000FFFF0),
+ 4)),
+ ((UINT16) Offset),
+ &RegSet,
+ NULL,
+ 0
+ );
+
+ Offset = MemoryRead16 ((UINTN) ImageLocation + 0x42) + (UINTN) ImageLocation;
+ if (MemoryRead16 ((UINTN) ImageLocation + 0x44) == 0x0) {
+ VbiosSize = MemoryRead8 ((UINTN) ImageLocation + 0x2) * 512;
+ } else {
+ VbiosSize = MemoryRead16 ((UINTN) ImageLocation + 0x44) * 512;
+ }
+ ///
+ /// Copy Oprom to allocated space for the following scenario:
+ /// # Load vbios and Execute vbios policy setting
+ ///
+ DEBUG ((EFI_D_INFO, "Copy Oprom to allocated space: Load & Execute policy satisfied\n"));
+ (gBS->CopyMem) (VbiosAddress, (VOID *) Offset, VbiosSize);
+ DgpuOpRomCopied = TRUE;
+ (gBS->SetMem) ((VOID *) (UINTN) ImageLocation, BIN_FILE_SIZE_MAX, 0);
+ }
+ (gBS->FreePages) (ImageLocation, (BIN_FILE_SIZE_MAX / 4096));
+ }
+
+ ///
+ /// Disable Memory Access, IO Access Bus Master enable and Rom Enable on PEG/PCH Endpoint device
+ ///
+ McDevFunPciCfg16And (EndpointBus, 0, 0, PCI_CMD, ~(BIT0 + BIT1 + BIT2));
+
+ ///
+ /// Disable Memory Access, IO Access Bus Master enable on PEG/PCH Root Port
+ ///
+ MmPci16And (0, 0, RootPortDev, RootPortFun, PCI_CMD, ~(BIT0 + BIT1 + BIT2));
+ }
+
+ ///
+ /// Copy Oprom to allocated space for the following scenario:
+ /// # Load vbios and Execute vbios policy setting in which dGPU execution is not called
+ /// # Load vbios but don't Execute vbios policy setting
+ ///
+ if ((VbiosAddress!=NULL) && (!DgpuOpRomCopied)) {
+ DEBUG ((EFI_D_INFO, "Copy Oprom to allocated space: Load policy satisfied\n"));
+ (gBS->CopyMem) (VbiosAddress, PciIo->RomImage, VbiosSize);
+ DgpuOpRomCopied = TRUE;
+ }
+
+ // AMI MODIFY BEGIN
+ //
+ //
+#ifdef AMI_SgTpv_SUPPORT
+ if (!EFI_ERROR (Status)) {
+ Status = LoadTpvAcpiTables ();
+ }
+#endif // AMI_SgTpv_SUPPORT
+ //
+ // AMI MODIFY ENDS
+ //
+ break;
+ }
+ }
+
+ }
+
+
+ if (VbiosAddress!=NULL) {
+ (gBS->FreePool) (VbiosAddress);
+ }
+
+ if (HandleBuffer!=NULL) {
+ (gBS->FreePool) (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read SG GPIO value
+
+ @param[in] Value - PCH GPIO number and Active value
+ Bit0 to Bit7 - PCH GPIO Number
+ Bit8 - GPIO Active value (0 = Active Low; 1 = Active High)
+
+ @retval GPIO read value.
+**/
+BOOLEAN
+GpioRead (
+ IN UINT8 Value
+ )
+{
+ BOOLEAN Active;
+ UINT32 Data;
+ UINT16 BitOffset=0;
+ UINT16 Offset=0;
+
+ ///
+ /// Check if SG GPIOs are supported
+ ///
+ if (GpioSupport == 0) {
+ return FALSE;
+ }
+ ///
+ /// Extract GPIO number and Active value
+ ///
+ Active = (BOOLEAN) (Value >> 7);
+ Value &= 0x7F;
+
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ Offset = R_PCH_GP_N_CONFIG0 + (Value * 0x08);
+ BitOffset = 30; //GPI_LVL
+ } else {
+ if (Value < 0x20) {
+ Offset = R_PCH_GPIO_LVL;
+ BitOffset = Value;
+ } else if (Value < 0x40) {
+ Offset = R_PCH_GPIO_LVL2;
+ BitOffset = Value - 0x20;
+ } else {
+ Offset = R_PCH_GPIO_LVL3;
+ BitOffset = Value - 0x40;
+ }
+ }
+
+ ///
+ /// Read specified value GPIO
+ ///
+ Data = IoRead32 (GpioBaseAddress + Offset);
+ Data >>= BitOffset;
+
+ if (Active == 0) {
+ Data = ~Data;
+ }
+
+ return (BOOLEAN) (Data & 0x1);
+}
+
+/**
+ Write SG GPIO value
+
+ @param[in] Value - PCH GPIO number and Active value
+ Bit0 to Bit7 - PCH GPIO Number
+ Bit8 - GPIO Active value (0 = Active Low; 1 = Active High)
+ @param[in] Level - Write data (0 = Disable; 1 = Enable)
+**/
+VOID
+GpioWrite (
+ IN UINT8 Value,
+ IN BOOLEAN Level
+ )
+{
+ BOOLEAN Active;
+ UINT32 Data;
+ UINT16 BitOffset=0;
+ UINT16 Offset=0;
+
+ ///
+ /// Check if SG GPIOs are supported
+ ///
+ if (GpioSupport == 0) {
+ return ;
+ }
+
+ Active = (BOOLEAN) (Value >> 7);
+ Value &= 0x7F;
+
+ if (Active == 0) {
+ Level = (~Level) & 0x1;
+ }
+
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ Offset = R_PCH_GP_N_CONFIG0 + (Value * 0x08);
+ BitOffset = 31; //GPO_LVL
+ } else {
+ if (Value < 0x20) {
+ Offset = R_PCH_GPIO_LVL;
+ BitOffset = Value;
+ } else if (Value < 0x40) {
+ Offset = R_PCH_GPIO_LVL2;
+ BitOffset = Value - 0x20;
+ } else {
+ Offset = R_PCH_GPIO_LVL3;
+ BitOffset = Value - 0x40;
+ }
+ }
+
+ Data = IoRead32 (GpioBaseAddress + Offset);
+ Data &= ~(0x1 << BitOffset);
+ Data |= (Level << BitOffset);
+ IoWrite32 (GpioBaseAddress + Offset, Data);
+
+ return ;
+}
+
+/**
+ Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode
+ memory.
+
+ @param[in] AllocateType - Allocated Legacy Memory Type
+ @param[in] StartPageAddress - Start address of range
+ @param[in] Pages - Number of pages to allocate
+ @param[in, out] Result - Result of allocation
+
+ @retval EFI_SUCCESS - Legacy16 code loaded
+ @retval Other - No protocol installed, unload driver.
+**/
+EFI_STATUS
+AllocateLegacyMemory (
+ IN EFI_ALLOCATE_TYPE AllocateType,
+ IN EFI_PHYSICAL_ADDRESS StartPageAddress,
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS MemPage;
+
+ ///
+ /// Allocate Pages of memory less <= StartPageAddress
+ ///
+ MemPage = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress;
+ Status = (gBS->AllocatePages) (AllocateType, EfiBootServicesCode, Pages, &MemPage);
+
+ ///
+ /// Do not ASSERT on Status error but let caller decide since some cases
+ /// memory is already taken but that is ok.
+ ///
+ if (!EFI_ERROR (Status)) {
+ *Result = (EFI_PHYSICAL_ADDRESS) (UINTN) MemPage;
+ }
+
+ return Status;
+}
+
+/**
+ Load Intel SG SSDT Tables
+
+ @param[in] None
+
+ @retval EFI_SUCCESS - SG SSDT Table load successful.
+**/
+EFI_STATUS
+LoadAcpiTables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ BOOLEAN LoadTable;
+ UINTN NumberOfHandles;
+ UINTN Index;
+ INTN Instance;
+ UINTN Size;
+ UINT32 FvStatus;
+ UINTN TableHandle;
+ EFI_GUID AcpiTableGuid;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+ EFI_ACPI_COMMON_HEADER *Table;
+
+ FwVol = NULL;
+ Table = NULL;
+
+ AcpiTableGuid = gSgAcpiTableStorageGuid;
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ AcpiTableGuid = gSgAcpiTablePchStorageGuid;
+ }
+
+ DEBUG ((EFI_D_INFO, "SG:: Loading ACPI Tables...\n"));
+
+ ///
+ /// Locate FV protocol.
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Look for FV with ACPI storage file
+ ///
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolumeProtocolGuid,
+ (VOID **) &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (FwVol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &AcpiTableGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ ///
+ /// If we found it, then we are done
+ ///
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ ///
+ /// Our exit status is determined by the success of the previous operations
+ /// If the protocol was found, Instance already points to it.
+ ///
+ ///
+ /// Free any allocated buffers
+ ///
+ (gBS->FreePool) (HandleBuffer);
+
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol);
+
+ ///
+ /// By default, a table belongs in all ACPI table versions published.
+ ///
+ Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+
+ ///
+ /// Locate ACPI tables
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+
+ ///
+ /// Read tables from the storage file.
+ ///
+ if (FwVol == NULL) {
+ ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+ return EFI_NOT_FOUND;
+ }
+ Instance = 0;
+
+ while (Status == EFI_SUCCESS) {
+ ///
+ /// Read the ACPI tables
+ ///
+ Status = FwVol->ReadSection (
+ FwVol,
+ &AcpiTableGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID **) &Table,
+ &Size,
+ &FvStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// check and load SwitchableGraphics SSDT table
+ ///
+ LoadTable = FALSE;
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
+
+ if (((EFI_ACPI_DESCRIPTION_HEADER *) TableHeader)->OemTableId == EFI_SIGNATURE_64 (
+ 'S',
+ 'g',
+ 'P',
+ 'e',
+ 'g',
+ 0,
+ 0,
+ 0
+ )
+ ) {
+ ///
+ /// This is SG SSDT [dGPU is present on PEG RootPort]
+ ///
+ DEBUG ((EFI_D_INFO, "SG:: ---- SG SSDT ----\n"));
+ DEBUG ((EFI_D_INFO, "SG:: Found out SSDT:SgPeg [SgSsdt.asl]. dGPU is present on PEG RootPort.\n"));
+ LoadTable = TRUE;
+ }
+
+ if (((EFI_ACPI_DESCRIPTION_HEADER *) TableHeader)->OemTableId == EFI_SIGNATURE_64 (
+ 'S',
+ 'g',
+ 'P',
+ 'c',
+ 'h',
+ 0,
+ 0,
+ 0
+ )
+ ) {
+ ///
+ /// This is SG SSDT [dGPU is present on PCH RootPort]
+ ///
+ DEBUG ((EFI_D_INFO, "SG:: ---- SG SSDT ----\n"));
+ DEBUG ((EFI_D_INFO, "SG:: Found out SSDT:SgPch [SgSsdtPch.asl]. dGPU is present on PCH RootPort.\n"));
+ LoadTable = TRUE;
+ }
+
+ ///
+ /// Add the table
+ ///
+ if (LoadTable) {
+ TableHandle = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ TableHeader,
+ TableHeader->Length,
+ &TableHandle
+ );
+ }
+ ///
+ /// Increment the instance
+ ///
+ Instance++;
+ Table = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+SgExitPmAuthCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+
+ ///
+ /// Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+ /// if it is, we will skip it until real event is triggered
+ ///
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ gBS->CloseEvent (Event);
+
+ DEBUG ((EFI_D_INFO, "SG:: ExitPmAuth Callback\n"));
+ ///
+ /// Load and Execute dGPU VBIOS
+ ///
+ Status = LoadAndExecuteDgpuVbios (mDxePlatformSaPolicy->VbiosConfig);
+}