summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/SaInit/Dxe')
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.c849
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.h66
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.c368
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.h76
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.c483
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.h224
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.c1371
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.h43
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaFvi.c105
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.c842
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.dxs65
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.h194
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.inf137
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.cif30
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.mak86
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.sdl24
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.c958
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.h267
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.c934
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.h70
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.c1094
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.h132
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.c955
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.h281
24 files changed, 9654 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.c
new file mode 100644
index 0000000..a55603a
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.c
@@ -0,0 +1,849 @@
+/** @file
+ This is the driver that initializes the CPU Audio device.
+
+@copyright
+ Copyright (c) 1999 - 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 "AudioInit.h"
+
+extern SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL mSaGlobalNvsAreaProtocol;
+
+///
+/// Global variables
+///
+UINT32 *mVerbCodecSaveAddress = NULL;
+UINT8 mVerbCount = 0;
+
+UINT32 mSaHdaVerbTableDataDefault[] = {
+ ///
+ /// Audio Verb Table - 0x80862807
+ ///
+ ///
+ /// Pin Widget 5 - PORT B
+ ///
+ 0x00571C10,
+ 0x00571D00,
+ 0x00571E56,
+ 0x00571F18,
+ ///
+ /// Pin Widget 6 - PORT C
+ ///
+ 0x00671C20,
+ 0x00671D00,
+ 0x00671E56,
+ 0x00671F18,
+ ///
+ /// Pin Widget 7 - PORT D
+ ///
+ 0x00771C30,
+ 0x00771D00,
+ 0x00771E56,
+ 0x00771F18
+};
+
+SA_HDA_VERB_TABLE mSaHdaVerbTableDefault[] = {
+ {
+ ///
+ /// VerbTable:
+ /// Revision ID = 0xFF
+ /// Codec Vendor: 0x80862807
+ ///
+ {
+ 0x80862807, ///< Vendor ID/Device ID
+ 0x0000, ///< SubSystem ID
+ 0xFF, ///< Revision ID
+ 0x02, ///< Front panel support (1=yes, 2=no)
+ 0x0003, ///< Number of Rear Jacks
+ 0x0000 ///< Number of Front Jacks
+ },
+ 0 ///< Pointer to verb table data, need to be inited in the code.
+ }
+};
+
+/**
+ Polling the Status bit
+
+ @param[in] StatusReg The regsiter address to read the status
+ @param[in] PollingBitMap The bit mapping for polling
+ @param[in] PollingData The Data for polling
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT Polling the bit map time out
+**/
+EFI_STATUS
+StatusPolling (
+ IN UINT32 StatusReg,
+ IN UINT16 PollingBitMap,
+ IN UINT16 PollingData
+ )
+{
+ UINT32 LoopTime;
+
+ for (LoopTime = 0; LoopTime < SA_HDA_MAX_LOOP_TIME; LoopTime++) {
+ if ((MmioRead16 (StatusReg) & PollingBitMap) == PollingData) {
+ break;
+ } else {
+ PchPmTimerStall (SA_HDA_WAIT_PERIOD);
+ }
+ }
+
+ if (LoopTime >= SA_HDA_MAX_LOOP_TIME) {
+ DEBUG ((EFI_D_ERROR, "Polling StatusReg 0x%X BitMap 0x%x TimeOut\n", StatusReg, PollingBitMap));
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send the command to the codec via the Immediate Command mechanism is written
+ to the IC register
+
+ @param[in] HdaBar Base address of Intel HD Audio memory mapped configuration registers
+ @param[in, out] CodecCommandData The Codec Command to be sent to the codec
+ @param[in] ReadBack Whether to get the response received from the codec
+
+ @exception EFI_DEVICE_ERROR Device status error, operation failed
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+SendCodecCommand (
+ IN UINT32 HdaBar,
+ IN OUT UINT32 *CodecCommandData,
+ IN BOOLEAN ReadBack
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Wait for Command Busy (ICB) bit to be cleared
+ ///
+ Status = StatusPolling (HdaBar + R_HDA_IRS, (UINT16) B_HDA_IRS_ICB, (UINT16) 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ICB bit is not zero before SendCodecCommand! \n"));
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Clear Result Valid (IRV) bit (by writing a one to it) before issuing a new command
+ ///
+ MmioOr16 ((UINTN) (HdaBar + R_HDA_IRS), (UINT16) (B_HDA_IRS_IRV));
+ ///
+ /// Send command to codec
+ ///
+ MmioWrite32 (HdaBar + R_HDA_IC, *CodecCommandData);
+ ///
+ /// Set ICB bit to issue the command currently stored in IC to the codec.
+ ///
+ MmioOr16 ((UINTN) (HdaBar + R_HDA_IRS), (UINT16) (B_HDA_IRS_ICB));
+ ///
+ /// Wait for Command Busy (ICB) bit to be cleared
+ ///
+ Status = StatusPolling (HdaBar + R_HDA_IRS, (UINT16) B_HDA_IRS_ICB, (UINT16) 0);
+ if (EFI_ERROR (Status)) {
+ MmioAnd16 ((UINTN) (HdaBar + R_HDA_IRS), (UINT16)~(B_HDA_IRS_ICB));
+ return Status;
+ }
+
+ ///
+ /// Save Codec command for runtime code
+ ///
+ if (mVerbCodecSaveAddress != NULL) {
+ if ((mVerbCount * 4) < AUDIO_CODEC_MAX_SIZE) {
+ *(mVerbCodecSaveAddress + mVerbCount) = *CodecCommandData;
+ mVerbCount++;
+ DEBUG ((EFI_D_ERROR, "SendCodecCommand(0x%x): 0x%x \n",(mVerbCodecSaveAddress + (mVerbCount)), *CodecCommandData));
+ } else {
+ DEBUG ((EFI_D_ERROR, "Codec Command Save Area Overflow max value of %d\n", AUDIO_CODEC_MAX_SIZE));
+ }
+ }
+
+ if (ReadBack == TRUE) {
+ if ((MmioRead16 (HdaBar + R_HDA_IRS) & B_HDA_IRS_IRV) != 0) {
+ *CodecCommandData = MmioRead32 (HdaBar + R_HDA_IR);
+ } else {
+ DEBUG ((EFI_D_ERROR, "SendCodecCommand: ReadBack fail! \n"));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set a "Send Codec Command" S3 dispatch item
+
+ @param[in] HdaBar Base address of Intel HD Audio memory mapped configuration registers
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+SendCodecCommandS3Item (
+ IN UINT32 HdaBar
+ )
+{
+ UINT16 BitMask;
+ UINT16 BitValue;
+ UINT16 Data16And;
+ UINT16 Data16Or;
+
+ ///
+ /// Wait for Command Busy (ICB) bit to be cleared
+ ///
+ BitMask = (UINT16) B_HDA_IRS_ICB;
+ BitValue = (UINT16) 0;
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ HdaBar + R_HDA_IRS,
+ &BitMask,
+ &BitValue,
+ SA_HDA_WAIT_PERIOD,
+ SA_HDA_MAX_LOOP_TIME
+ );
+ ///
+ /// Clear Result Valid (IRV) bit (by writing a one to it) before issuing a new command
+ ///
+ Data16And = 0xFFFF;
+ Data16Or = (UINT16) (B_HDA_IRS_IRV);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (HdaBar + R_HDA_IRS),
+ &Data16Or, /// Data to be ORed
+ &Data16And /// Data to be ANDed
+ );
+
+ ///
+ /// Send command to codec
+ ///
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + R_HDA_IC),
+ 1,
+ (VOID *) (UINTN) (HdaBar + R_HDA_IC)
+ );
+
+ ///
+ /// Set ICB bit to issue the command currently stored in IC to the codec.
+ ///
+ Data16And = 0xFFFF;
+ Data16Or = (UINT16) (B_HDA_IRS_ICB );
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (HdaBar + R_HDA_IRS),
+ &Data16Or, /// Data to be ORed
+ &Data16And /// Data to be ANDed
+ );
+
+ ///
+ /// Wait for Command Busy (ICB) bit to be cleared
+ ///
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ HdaBar + R_HDA_IRS,
+ &BitMask,
+ &BitValue,
+ SA_HDA_WAIT_PERIOD,
+ SA_HDA_MAX_LOOP_TIME
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Detect And Initialize SA Audio Codec
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - Legacy Region protocol installed
+ @retval Other - No protocol installed, unload driver.
+**/
+EFI_STATUS
+DetectAndInitializeCodec (
+ IN EFI_HANDLE mImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ UINT32 VendorDeviceId;
+ UINT32 RevisionId;
+ UINT8 ByteReg;
+ UINTN AudioBase;
+ UINT8 AudioSDINo;
+ UINT32 HdaBar;
+ UINT32 *VerbTable;
+ UINT32 LoopTime;
+ SA_HDA_VERB_TABLE_HEADER *VerbHeaderTable;
+ EFI_PHYSICAL_ADDRESS BaseAddressBarMem;
+ UINT8 VerbTableNum;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT32 Data32;
+ UINT32 CodecCmdData;
+ UINT16 AudioDeviceId;
+ UINT16 Data16;
+ UINT16 BitMask;
+ UINT16 BitValue;
+ CPU_STEPPING CpuSteppingId;
+ CPU_FAMILY CpuFamilyId;
+ UINT16 IsUlx;
+
+ CpuFamilyId = GetCpuFamily();
+ CpuSteppingId = GetCpuStepping();
+
+ AudioBase = MmPciAddress (0, SA_HDA_BUS_NUM, SA_HDA_DEV_NUM, SA_HDA_FUN_NUM, 0);
+ AudioDeviceId = MmioRead16 (AudioBase + PCI_DEVICE_ID_OFFSET);
+
+ ///
+ /// Allocate resource for HDBAR
+ ///
+ BaseAddressBarMem = 0x0FFFFFFFF;
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchBottomUp,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 14,
+ SA_HDA_HDBAR_SIZE,
+ &BaseAddressBarMem,
+ mImageHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// System BIOS should ensure that the High Definition Audio HDBAR D27:F0:Reg 10-17h contains a valid address value
+ /// and is enabled by setting D3:F0:Reg 04h[1].
+ ///
+ HdaBar = (UINT32) BaseAddressBarMem;
+ MmioWrite32 (AudioBase + SA_HDA_HDBARL, HdaBar);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (AudioBase + SA_HDA_HDBARL),
+ 1,
+ (VOID *) (UINTN) (AudioBase + SA_HDA_HDBARL)
+ );
+
+ MmioWrite32 (AudioBase + SA_HDA_HDBARU, 0);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (AudioBase + SA_HDA_HDBARU),
+ 1,
+ (VOID *) (UINTN) (AudioBase + SA_HDA_HDBARU)
+ );
+
+ MmioOr16 ((UINTN) (AudioBase + PCI_COMMAND_OFFSET), (UINT16) BIT1);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (AudioBase + PCI_COMMAND_OFFSET),
+ 1,
+ (VOID *) (UINTN) (AudioBase + PCI_COMMAND_OFFSET)
+ );
+
+ ///
+ /// AudioWA: Apply until C0, program Chicken bit: set Dev3 mmio 101C bit 29
+ ///
+ if (((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId < EnumHswC0)) ||
+ ((CpuFamilyId == EnumCpuCrw) && (CpuSteppingId < EnumCrwC0))) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) (BIT29);
+ MmioOr32 ((UINTN) (HdaBar + 0x101C), Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + 0x101C),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+ if (DxePlatformSaPolicy->Revision >=4) {
+ IsUlx = 0;
+ Data16 = McD2PciCfg16 (0x2);
+ if ((Data16 == 0xA0E) || (Data16 == 0xA1E)) {
+ IsUlx = 1;
+ }
+ Data32Or = 4;
+ Data32 = 75;
+ if (DxePlatformSaPolicy->IgdConfig->CdClkVar != 0) {
+ if (DxePlatformSaPolicy->IgdConfig->CdClk == 0) {
+ Data32Or = 16;
+ Data32 = 225;
+ }
+ if (DxePlatformSaPolicy->IgdConfig->CdClk == 2) {
+ Data32Or = 4;
+ Data32 = 90;
+ }
+ }
+ if(IsUlx == 1) {
+ Data32Or = 16;
+ Data32 = 225;
+ }
+ ///
+ /// Program Dev3 EM4 and EM5 MMIO registers [17:00] based on Cd Clk frequency
+ ///
+ Data32And = 0xFFFC0000;
+ Mmio32AndThenOr ((UINTN) HdaBar, 0x100c, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + 0x100c),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+
+ Data32And = 0xFFFC0000;
+ Data32Or = Data32;
+ Mmio32AndThenOr ((UINTN) HdaBar, 0x1010, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + 0x1010),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+
+ mSaGlobalNvsAreaProtocol.Area->AudioWaA = MmioRead32(HdaBar + 0x1010);
+ mSaGlobalNvsAreaProtocol.Area->AudioWaB = MmioRead32(HdaBar + 0x101C);
+ mSaGlobalNvsAreaProtocol.Area->AudioWaC = MmioRead32(HdaBar + 0x100C);
+
+ ///
+ /// Allocate an ACPI NVS memory buffer for Saving Codec value for Adapter Power on restore
+ /// , zero initialize, and set the pointer in the SA NVS area structure.
+ ///
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, AUDIO_CODEC_MAX_SIZE, (VOID **) &mVerbCodecSaveAddress);
+ if (EFI_ERROR(Status)) {
+ mSaGlobalNvsAreaProtocol.Area->AudioCodecSaveAddress = 0;
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ ZeroMem ((VOID *) mVerbCodecSaveAddress, AUDIO_CODEC_MAX_SIZE);
+ mSaGlobalNvsAreaProtocol.Area->AudioCodecSaveAddress = (UINT32) (UINTN) (mVerbCodecSaveAddress);
+ }
+
+ ///
+ /// Codec Initialization Programming Sequence
+ /// System BIOS should also ensure that the Controller Reset# bit of Global Control register
+ /// in memory-mapped space (HDBAR+08h[0]) is set to 1 and read back as 1.
+ /// Deassert the HDA controller RESET# to start up the link
+ ///
+ DEBUG ((EFI_D_INFO, "Codec Initialization...\n"));
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) (B_HDA_GCTL_CRST);
+ MmioOr32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + R_HDA_GCTL),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+
+ BitMask = (UINT16) B_HDA_GCTL_CRST;
+ BitValue = (UINT16) B_HDA_GCTL_CRST;
+ Status = StatusPolling (HdaBar + R_HDA_GCTL, BitMask, BitValue);
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ HdaBar + R_HDA_GCTL,
+ &BitMask,
+ &BitValue,
+ SA_HDA_WAIT_PERIOD,
+ SA_HDA_MAX_LOOP_TIME
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Reset SA dHDA Codec - Set Controller Reset# bit and Poll: Time Out - 0! \n"));
+ goto ExitInitAudio;
+ }
+ ///
+ /// Read GCAP and write the same value back to the register once after Controller Reset# bit is set
+ ///
+ Data16 = MmioRead16 (HdaBar + R_HDA_GCAP);
+ MmioWrite16 (HdaBar + R_HDA_GCAP, Data16);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (HdaBar + R_HDA_GCAP),
+ 1,
+ (VOID *) (UINTN) (HdaBar + R_HDA_GCAP)
+ );
+ ///
+ /// Clear the "State Change Status Register" STATESTS bits for
+ /// each of the "SDIN Stat Change Status Flag"
+ ///
+ MmioOr8 ((UINTN) (HdaBar + R_HDA_STATESTS), (UINT8) (SA_HDA_MAX_SID_MASK));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (HdaBar + R_HDA_STATESTS),
+ 1,
+ (VOID *) (UINTN) (HdaBar + R_HDA_STATESTS)
+ );
+ ///
+ /// Turn off the link and poll RESET# bit until it reads back as 0 to get hardware reset report
+ ///
+ Data32And = (UINT32) (~B_HDA_GCTL_CRST);
+ Data32Or = (UINT32) 0;
+ MmioAnd32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32And);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + R_HDA_GCTL),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+
+ BitMask = (UINT16) B_HDA_GCTL_CRST;
+ BitValue = 0;
+ Status = StatusPolling (HdaBar + R_HDA_GCTL, BitMask, BitValue);
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ HdaBar + R_HDA_GCTL,
+ &BitMask,
+ &BitValue,
+ SA_HDA_WAIT_PERIOD,
+ SA_HDA_MAX_LOOP_TIME
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Reset SA dHDA Codec - Turn off the link and Poll: Time Out - 1! \n"));
+ goto ExitInitAudio;
+ }
+ ///
+ /// Turn on the link and poll RESET# bit until it reads back as 1
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) (B_HDA_GCTL_CRST);
+ MmioOr32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + R_HDA_GCTL),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ ///
+ /// For some combo card that will need this delay because each codec has different latency to come out from RESET.
+ /// This delay can make sure all codecs be recognized by BIOS after RESET sequence.
+ /// Additional delay might be required to allow codec coming out of reset prior to subsequent operations,
+ /// please contact your codec vendor for detail. When clearing this bit and setting it afterward,
+ /// BIOS must ensure that minimum link timing requirements (minimum RESET# assertion time, etc.) are met..
+ ///
+ PchPmTimerStall (SA_HDA_WAIT_PERIOD);
+ SCRIPT_STALL (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, 300 * STALL_ONE_MICRO_SECOND);
+
+ BitMask = (UINT16) B_HDA_GCTL_CRST;
+ BitValue = (UINT16) B_HDA_GCTL_CRST;
+ Status = StatusPolling (HdaBar + R_HDA_GCTL, BitMask, BitValue);
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ HdaBar + R_HDA_GCTL,
+ &BitMask,
+ &BitValue,
+ SA_HDA_WAIT_PERIOD,
+ SA_HDA_MAX_LOOP_TIME
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Reset SA dHDA Codec - Turn on the link and Poll: Time Out - 2! \n"));
+ goto ExitInitAudio;
+ }
+ ///
+ /// Read the "State Change Status Register" STATESTS bits twice to find out if any SDIN is connected
+ /// to a codec.
+ ///
+ for (LoopTime = 0, ByteReg = 0, AudioSDINo = 0; LoopTime < SA_HDA_MAX_LOOP_TIME; LoopTime++) {
+ ByteReg = MmioRead8 (HdaBar + R_HDA_STATESTS) & SA_HDA_MAX_SID_MASK;
+ if (ByteReg != 0 && (ByteReg == AudioSDINo)) {
+ break;
+ } else {
+ AudioSDINo = ByteReg;
+ }
+
+ PchPmTimerStall (SA_HDA_WAIT_PERIOD);
+ }
+ ///
+ /// BIT3(1000) -- SDI3
+ /// BIT2(0100) -- SDI2
+ /// BIT1(0010) -- SDI1
+ /// BIT0(0001) -- SDI0
+ ///
+ if (ByteReg == 0) {
+ ///
+ /// No Codec Detected, Turn off the link
+ ///
+ DEBUG ((EFI_D_INFO, "No Codec device is detected.\n"));
+ Data32And = (UINT32) (~B_HDA_GCTL_CRST);
+ Data32Or = (UINT32) 0;
+ MmioAnd32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32And);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (HdaBar + R_HDA_GCTL),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ Status = EFI_DEVICE_ERROR;
+ goto ExitInitAudio;
+ }
+
+ for (AudioSDINo = 0; AudioSDINo < SA_HDA_MAX_SID_NUMBER; AudioSDINo++, ByteReg >>= 1) {
+ if ((ByteReg & 0x1) == 0) {
+ ///
+ /// SDIx has no Codec Device
+ ///
+ DEBUG ((EFI_D_INFO, "SDI%d has no Codec device.\n", AudioSDINo));
+ continue;
+ }
+ ///
+ /// Verb: 31~28 27 26~20 19~0
+ /// CAd 1 NID Verb Command and data
+ /// 0/1/2
+ ///
+ /// Read the Vendor ID/Device ID pair from the attached codec
+ ///
+ VendorDeviceId = 0x000F0000 | (AudioSDINo << 28);
+ Status = SendCodecCommand (HdaBar, &VendorDeviceId, TRUE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Read the Codec Vendor ID/Device ID fail! \n"));
+ goto ExitInitAudio;
+ }
+ ///
+ /// Read the Revision ID from the attached codec
+ ///
+ RevisionId = 0x000F0002 | (AudioSDINo << 28);
+ Status = SendCodecCommand (HdaBar, &RevisionId, TRUE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Read the Codec Revision ID fail! \n"));
+ goto ExitInitAudio;
+ }
+
+ RevisionId = (RevisionId >> 8) & 0xFF;
+
+ ///
+ /// Get the match codec verb table, RevID of 0xFF applies to all steppings.
+ ///
+ if (DxePlatformSaPolicy->MiscConfig->SaHdaVerbTableNum == 0) {
+ ///
+ /// Init Verb Table Data
+ ///
+ DxePlatformSaPolicy->MiscConfig->SaHdaVerbTable[0].VerbTableData = mSaHdaVerbTableDataDefault;
+ DxePlatformSaPolicy->MiscConfig->SaHdaVerbTableNum = sizeof (mSaHdaVerbTableDefault) / sizeof (SA_HDA_VERB_TABLE);
+ }
+ for (VerbTableNum = 0, VerbHeaderTable = NULL, VerbTable = NULL;
+ VerbTableNum < DxePlatformSaPolicy->MiscConfig->SaHdaVerbTableNum;
+ VerbTableNum++
+ ) {
+ if ((VendorDeviceId == DxePlatformSaPolicy->MiscConfig->SaHdaVerbTable[VerbTableNum].VerbTableHeader.VendorDeviceId) &&
+ (
+ (DxePlatformSaPolicy->MiscConfig->SaHdaVerbTable[VerbTableNum].VerbTableHeader.RevisionId == 0xFF) ||
+ (RevisionId == DxePlatformSaPolicy->MiscConfig->SaHdaVerbTable[VerbTableNum].VerbTableHeader.RevisionId)
+ )
+ ) {
+ VerbHeaderTable = &(DxePlatformSaPolicy->MiscConfig->SaHdaVerbTable[VerbTableNum].VerbTableHeader);
+ VerbTable = DxePlatformSaPolicy->MiscConfig->SaHdaVerbTable[VerbTableNum].VerbTableData;
+ if (VerbTable == 0) {
+ DEBUG ((EFI_D_ERROR, "VerbTableData of VendorID:0x%X is null.\n", VendorDeviceId));
+ Status = EFI_INVALID_PARAMETER;
+ goto ExitInitAudio;
+ }
+
+ DEBUG ((EFI_D_INFO, "Detected SA HDA Codec with verb table, VendorID = 0x%X", VendorDeviceId));
+ DEBUG ((EFI_D_INFO, " on SDI%d, revision = 0x%0x.\n", AudioSDINo, RevisionId));
+ ///
+ /// Enable 3rd Pin and Converter Widget
+ /// Clear CAd Field
+ ///
+ CodecCmdData = SA_HDA_ENABLE_3RD_PIN_WIDGET;
+ ///
+ /// Program CAd Field per the SDI number got during codec detection
+ ///
+ CodecCmdData |= (UINT32) (AudioSDINo << 28);
+ Status = SendCodecCommand (HdaBar, &CodecCmdData, FALSE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error occurs at loading Verb 0x00878101"));
+ ///
+ /// Skip the verb table loading when find the verb table content is not
+ /// properly matched with the HDA hardware, though IDs match.
+ ///
+ DEBUG (
+ (EFI_D_ERROR,
+ "Detected Codec of VendorID:0x%X, error occurs during loading verb table.\n",
+ VendorDeviceId)
+ );
+ goto ExitInitAudio;
+ }
+
+ SendCodecCommandS3Item (HdaBar);
+ ///
+ /// Send the entire list of verbs in the matching verb table one by one to the codec
+ ///
+ for (Index = 0; Index < (UINT32) ((VerbHeaderTable->NumberOfFrontJacks + VerbHeaderTable->NumberOfRearJacks) * 4); Index++) {
+ ///
+ /// Clear CAd Field
+ ///
+ CodecCmdData = VerbTable[Index] & (UINT32)~(BIT31 | BIT30 | BIT29 | BIT28);
+ ///
+ /// Program CAd Field per the SDI number got during codec detection
+ ///
+ CodecCmdData |= (UINT32) (AudioSDINo << 28);
+ Status = SendCodecCommand (HdaBar, &CodecCmdData, FALSE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error occurs at loading Command Index:%x\n", Index));
+ ///
+ /// Skip the verb table loading when find the verb table content is not
+ /// properly matched with the HDA hardware, though IDs match.
+ ///
+ DEBUG (
+ (EFI_D_ERROR,
+ "Detected Codec of VendorID:0x%X, error occurs during loading verb table.\n",
+ VendorDeviceId)
+ );
+ goto ExitInitAudio;
+ }
+
+ SendCodecCommandS3Item (HdaBar);
+ }
+ ///
+ /// Disable 3rd Pin and Converter Widget
+ /// Clear CAd Field
+ ///
+ CodecCmdData = SA_HDA_DISABLE_3RD_PIN_WIDGET;
+ ///
+ /// Program CAd Field per the SDI number got during codec detection
+ ///
+ CodecCmdData |= (UINT32) (AudioSDINo << 28);
+ Status = SendCodecCommand (HdaBar, &CodecCmdData, FALSE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error occurs at loading verb 0x00878100"));
+ ///
+ /// Skip the verb table loading when find the verb table content is not
+ /// properly matched with the HDA hardware, though IDs match.
+ ///
+ DEBUG (
+ (EFI_D_ERROR,
+ "Detected Codec of VendorID:0x%X, error occurs during loading verb table.\n",
+ VendorDeviceId)
+ );
+ goto ExitInitAudio;
+ }
+
+ SendCodecCommandS3Item (HdaBar);
+
+ DEBUG ((EFI_D_INFO, "Verb Table loading complete to Codec on SDI%d\n", AudioSDINo));
+ break;
+ }
+ }
+
+ if (VerbTableNum >= DxePlatformSaPolicy->MiscConfig->SaHdaVerbTableNum) {
+ DEBUG (
+ (EFI_D_INFO,
+ "Detected SA High Definition Audio Codec, VendorID = 0x%08x on SDI%d,",
+ VendorDeviceId,
+ AudioSDINo)
+ );
+ DEBUG ((EFI_D_INFO, " but no matching verb table found.\n"));
+ }
+ } // end of for
+ Status = EFI_SUCCESS;
+
+ExitInitAudio:
+ ///
+ /// Clear HdaBar and disable memory map access
+ ///
+ MmioAnd16 ((UINTN) (AudioBase + PCI_COMMAND_OFFSET), (UINT16) (~BIT1));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (AudioBase + PCI_COMMAND_OFFSET),
+ 1,
+ (VOID *) (UINTN) (AudioBase + PCI_COMMAND_OFFSET)
+ );
+
+ MmioWrite32 (AudioBase + SA_HDA_HDBARL, 0);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (AudioBase + SA_HDA_HDBARL),
+ 1,
+ (VOID *) (UINTN) (AudioBase + SA_HDA_HDBARL)
+ );
+
+ MmioWrite32 (AudioBase + SA_HDA_HDBARU, 0);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (AudioBase + SA_HDA_HDBARU),
+ 1,
+ (VOID *) (UINTN) (AudioBase + SA_HDA_HDBARU)
+ );
+
+ gDS->FreeMemorySpace (
+ BaseAddressBarMem,
+ SA_HDA_HDBAR_SIZE
+ );
+ ///
+ /// Save the final count of Audio Codec Save data in SA NVS
+ ///
+ mSaGlobalNvsAreaProtocol.Area->AudioCodecSaveCount = mVerbCount;
+
+ return Status;
+}
+
+/**
+ Initialize SystemAgent Audio Device/Codec.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - Audio/Codec initialization done
+**/
+EFI_STATUS
+AudioInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+{
+ EFI_STATUS Status;
+
+ if ((DxePlatformSaPolicy->MiscConfig->AudioEnable == 0) || (McD2PciCfg16 (R_SA_IGD_VID) == 0xFFFF)) {
+ DEBUG ((
+ EFI_D_INFO, "Skip Audio Initialization when BIOS option set to disable Or iGfx is not enabled.\n"
+ )
+ );
+ return EFI_SUCCESS;
+ }
+
+ Status = DetectAndInitializeCodec (ImageHandle, DxePlatformSaPolicy);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SA Audio Codec initialization failure!\n"));
+ }
+
+ DEBUG ((EFI_D_INFO, "AudioInit() End\n"));
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.h
new file mode 100644
index 0000000..cd7bc33
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/AudioInit.h
@@ -0,0 +1,66 @@
+/** @file
+ Header file for initialization of CPU Audio device.
+
+@copyright
+ Copyright (c) 1999 - 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
+**/
+#ifndef _AUDIO_INIT_H_
+#define _AUDIO_INIT_H_
+
+#include "EdkIIGlueDxe.h"
+#include "Pci22.h"
+#include "SaAccess.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+#include "EfiScriptLib.h"
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+
+#include EFI_PROTOCOL_DEPENDENCY (BootScriptSave)
+#include EFI_PROTOCOL_DEFINITION (SaPlatformPolicy)
+#include EFI_PROTOCOL_DEFINITION (PciHostBridgeResourceAllocation)
+#include EFI_PROTOCOL_DEPENDENCY (SaGlobalNvsArea)
+
+#define SA_HDA_MAX_LOOP_TIME 10
+#define SA_HDA_WAIT_PERIOD 100
+#define SA_HDA_MAX_SID_NUMBER 4
+#define SA_HDA_MAX_SID_MASK ((1 << SA_HDA_MAX_SID_NUMBER) - 1)
+
+#define AUDIO_CODEC_MAX_SIZE 0x80
+
+#define SA_HDA_ENABLE_3RD_PIN_WIDGET 0x00878101
+#define SA_HDA_DISABLE_3RD_PIN_WIDGET 0x00878100
+
+///
+/// Functions
+///
+/**
+ Initialize SystemAgent Audio Device/Codec.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - Audio/Codec initialization Done.
+**/
+EFI_STATUS
+AudioInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+;
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.c
new file mode 100644
index 0000000..5c91336
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.c
@@ -0,0 +1,368 @@
+/** @file
+ This code provides a private implementation of the Legacy Region protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 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 "LegacyRegion.h"
+
+///
+/// Module Global:
+/// Since this driver will only ever produce one instance of the Private Data
+/// protocol you are not required to dynamically allocate the PrivateData.
+///
+LEGACY_REGION_INSTANCE mPrivateData;
+
+UINT8 mRomData[16] = {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+UINT8 mLockData[16] = {
+ 0x01,
+ 0x10,
+ 0x01,
+ 0x10,
+ 0x01,
+ 0x10,
+ 0x01,
+ 0x10,
+ 0x01,
+ 0x10,
+ 0x01,
+ 0x10, /// it was: 0x03, 0x30, 0x03, 0x30, <-- why ??
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10
+};
+
+UINT8 mUnlockData[16] = {
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x30,
+ 0x30,
+ 0x30,
+ 0x30
+};
+
+UINT8 mMaskData[16] = {
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x30,
+ 0x03,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+UINT8 mReg[16] = {
+ R_SA_PAM1,
+ R_SA_PAM1,
+ R_SA_PAM2,
+ R_SA_PAM2,
+ R_SA_PAM3,
+ R_SA_PAM3,
+ R_SA_PAM4,
+ R_SA_PAM4,
+ R_SA_PAM5,
+ R_SA_PAM5,
+ R_SA_PAM6,
+ R_SA_PAM6,
+ R_SA_PAM0,
+ R_SA_PAM0,
+ R_SA_PAM0,
+ R_SA_PAM0
+};
+
+EFI_STATUS
+LegacyRegionManipulation (
+ IN EFI_LEGACY_REGION_PROTOCOL * This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ IN UINT32 Mode,
+ OUT UINT32 *Granularity OPTIONAL
+ )
+/**
+ Modify PAM registers for region specified to MODE state.
+
+ @param[in] This - Pointer to EFI_LEGACY_REGION_PROTOCOL instance.
+ @param[in] Start - Starting address of a memory region covered by PAM registers (C0000h - FFFFFh).
+ @param[in] Length - Memory region length.
+ @param[in] Mode - Action to perform on a PAM region: UNLOCK, LOCK or BOOTLOCK.
+ @param[out] Granularity - Granularity of region in bytes.
+
+ @retval EFI_SUCCESS - PAM region(s) state modified as requested.
+ @retval EFI_INVALID_PARAMETER - parameter out of boundary
+**/
+{
+ UINT8 Index;
+ UINT8 Data;
+ UINT8 TempData;
+ UINT32 TempAddr;
+ UINT32 NewStartAddr;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Pci;
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ UINT64 PciAddress;
+ UINT64 Attributes;
+ EFI_STATUS Status;
+
+ Pci = mPrivateData.PciRootBridgeIo;
+ if ((Start < 0xC0000) ||
+ (Start > 0xFFFFF) ||
+ (Length > 0x40000) ||
+ ((Start + Length - 1) > 0xFFFFF)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ TempAddr = Start;
+ Index = (UINT8) ((TempAddr - 0xC0000) / PAM_GRANULARITY);
+ NewStartAddr = TempAddr = (TempAddr / PAM_GRANULARITY) * PAM_GRANULARITY;
+ while (TempAddr <= (Start + Length - 1)) {
+ if (Index >= 16) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((Mode == LOCK) || (Mode == BOOTLOCK)) {
+ Data = mLockData[Index];
+ } else {
+ if (Mode == UNLOCK) {
+ Data = mUnlockData[Index];
+ } else {
+ Data = mRomData[Index];
+ }
+ }
+
+ PciAddress = EFI_PCI_ADDRESS (0, 0, 0, mReg[Index]);
+ Pci->Pci.Read (Pci, EfiPciWidthUint8, PciAddress, 1, &TempData);
+ TempData = (UINT8) ((TempData & mMaskData[Index]) | Data);
+ Pci->Pci.Write (Pci, EfiPciWidthUint8, PciAddress, 1, &TempData);
+ TempAddr += PAM_GRANULARITY;
+ Index++;
+ }
+
+ if (Granularity != NULL) {
+ *Granularity = PAM_GRANULARITY;
+ }
+ ///
+ /// Program the MTRRs
+ ///
+ switch (Mode) {
+
+ case UNLOCK:
+ Attributes = EFI_MEMORY_WT;
+ break;
+
+ case LOCK:
+ Attributes = EFI_MEMORY_WP;
+ break;
+
+ case BOOTLOCK:
+ Attributes = EFI_MEMORY_WP;
+ break;
+
+ default:
+ Attributes = EFI_MEMORY_UC;
+
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiCpuArchProtocolGuid,
+ NULL,
+ (VOID **) &CpuArch
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = CpuArch->SetMemoryAttributes (
+ CpuArch,
+ NewStartAddr,
+ TempAddr - NewStartAddr,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+LegacyRegionDecode (
+ IN EFI_LEGACY_REGION_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ IN BOOLEAN *On
+ )
+/**
+ Enable/Disable decoding of the given region
+
+ @param[in] This - Pointer to EFI_LEGACY_REGION_PROTOCOL instance.
+ @param[in] Start - Starting address of region.
+ @param[in] Length - Length of region in bytes.
+ @param[in] On - 0 = Disable decoding, 1 = Enable decoding.
+
+ @retval EFI_SUCCESS - Decoding change affected.
+**/
+{
+ UINT32 Granularity;
+ if (*On) {
+ return LegacyRegionManipulation (This, Start, Length, UNLOCK, &Granularity);
+ } else {
+ return LegacyRegionManipulation (This, Start, Length, LEGACY_REGION_DECODE_ROM, &Granularity);
+ }
+}
+
+EFI_STATUS
+EFIAPI
+LegacyRegionBootLock (
+ IN EFI_LEGACY_REGION_PROTOCOL * This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity OPTIONAL
+ )
+/**
+ Make the indicated region read from RAM / write to ROM.
+
+ @param[in] This - Pointer to EFI_LEGACY_REGION_PROTOCOL instance.
+ @param[in] Start - Starting address of region.
+ @param[in] Length - Length of region in bytes.
+ @param[out] Granularity - Granularity of region in bytes.
+
+ @retval EFI_SUCCESS - Region locked or made R/O.
+**/
+{
+ return LegacyRegionManipulation (This, Start, Length, BOOTLOCK, Granularity);
+}
+
+EFI_STATUS
+EFIAPI
+LegacyRegionLock (
+ IN EFI_LEGACY_REGION_PROTOCOL * This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity OPTIONAL
+ )
+/**
+ Make the indicated region read from RAM / write to ROM.
+
+ @param[in] This - Pointer to EFI_LEGACY_REGION_PROTOCOL instance.
+ @param[in] Start - Starting address of region.
+ @param[in] Length - Length of region in bytes.
+ @param[out] Granularity - Granularity of region in bytes.
+
+ @retval EFI_SUCCESS - Region locked or made R/O.
+**/
+{
+ return LegacyRegionManipulation (This, Start, Length, LOCK, Granularity);
+}
+
+EFI_STATUS
+EFIAPI
+LegacyRegionUnlock (
+ IN EFI_LEGACY_REGION_PROTOCOL * This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity OPTIONAL
+ )
+/**
+ Make the indicated region read from RAM / write to RAM.
+
+ @param[in] This - Pointer to EFI_LEGACY_REGION_PROTOCOL instance.
+ @param[in] Start - Starting address of region.
+ @param[in] Length - Length of region in bytes.
+ @param[out] Granularity - Granularity of region in bytes.
+
+ @retval EFI_SUCCESS - Region unlocked or made R/W.
+**/
+{
+ return LegacyRegionManipulation (This, Start, Length, UNLOCK, Granularity);
+}
+
+EFI_STATUS
+LegacyRegionInstall (
+ IN EFI_HANDLE ImageHandle
+ )
+/**
+ Install Driver to produce Legacy Region protocol.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS - Legacy Region protocol installed
+ @retval Other - No protocol installed, unload driver.
+**/
+{
+ EFI_STATUS Status;
+ LEGACY_REGION_INSTANCE *Private;
+ Private = &mPrivateData;
+
+ ///
+ /// Grab a copy of all the protocols we depend on. Any error would
+ /// be a dispatcher bug!.
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ (VOID **) &Private->PciRootBridgeIo
+ );
+ Private->Signature = LEGACY_REGION_INSTANCE_SIGNATURE;
+ Private->LegacyRegion.Decode = LegacyRegionDecode;
+ Private->LegacyRegion.Lock = LegacyRegionLock;
+ Private->LegacyRegion.BootLock = LegacyRegionBootLock;
+ Private->LegacyRegion.UnLock = LegacyRegionUnlock;
+ Private->ImageHandle = ImageHandle;
+
+ ///
+ /// Make a new handle and install the protocol
+ ///
+ Private->Handle = NULL;
+ return gBS->InstallProtocolInterface (
+ &Private->Handle,
+ &gEfiLegacyRegionProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Private->LegacyRegion
+ );
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.h
new file mode 100644
index 0000000..d2e9b2d
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/LegacyRegion.h
@@ -0,0 +1,76 @@
+/** @file
+ This code supports a private implementation of the Legacy Region protocol.
+
+@copyright
+ Copyright (c) 1999 - 2012 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
+**/
+#ifndef _LEGACY_REGION_H_
+#define _LEGACY_REGION_H_
+
+#include "EdkIIGlueDxe.h"
+#include "Pci22.h"
+
+#include EFI_PROTOCOL_PRODUCER (LegacyRegion)
+#include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo)
+#define LEGACY_REGION_INSTANCE_SIGNATURE EFI_SIGNATURE_32 ('R', 'E', 'G', 'N')
+
+#include EFI_ARCH_PROTOCOL_CONSUMER (Cpu)
+#define LEGACY_REGION_DECODE_ROM 3
+
+#include "SaAccess.h"
+
+///
+/// PAM registers granularity is 16 KB
+///
+#define PAM_GRANULARITY 0x4000
+#define UNLOCK 0x0000
+#define LOCK 0x0001
+#define BOOTLOCK 0x0002
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_LEGACY_REGION_PROTOCOL LegacyRegion;
+ EFI_HANDLE ImageHandle;
+
+ ///
+ /// Protocol for PAM register access
+ ///
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+} LEGACY_REGION_INSTANCE;
+
+#define LEGACY_REGION_INSTANCE_FROM_THIS (this) CR (this, \
+ LEGACY_REGION_INSTANCE, \
+ LegacyRegion, \
+ LEGACY_REGION_INSTANCE_SIGNATURE \
+ )
+
+/**
+ Install Driver to produce Legacy Region protocol.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS - Legacy Region protocol installed
+ @retval Other - No protocol installed, unload driver.
+**/
+EFI_STATUS
+LegacyRegionInstall (
+ IN EFI_HANDLE ImageHandle
+ )
+;
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.c
new file mode 100644
index 0000000..921ae94
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.c
@@ -0,0 +1,483 @@
+/** @file
+ This driver does SA PCI Express initialization.
+
+@copyright
+ Copyright (c) 1999 - 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 "PciExpressInit.h"
+
+extern SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL mSaGlobalNvsAreaProtocol;
+
+EFI_STATUS
+PciExpressInit (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ PCI Express Dxe Initialization.
+ Run before PCI Bus Init, where assignment of Bus, Memory,
+ and I/O Resources are assigned.
+
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - Pci Express successfully started and ready to be used
+ @exception EFI_UNSUPPORTED - Pci Express can't be initialized
+**/
+{
+ EFI_STATUS Status;
+ UINT64 EgressPortBar;
+ UINT64 MchBar;
+ UINT64 PciExpressBar;
+ UINT64 DmiBar;
+ UINT32 PchRootComplexBar;
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuSteppingId;
+
+ CpuFamilyId = GetCpuFamily();
+ CpuSteppingId = GetCpuStepping();
+
+ ///
+ /// The SA Represents Component ID 1 (CID1), while the PCH represents
+ /// Component ID 2 (CID2). This code will completely configure both Components
+ /// CID1 Integrated Ports:
+ /// Egress Port = Port 0
+ /// DMI Port = Port 1
+ /// Peg Port10 = Port 2
+ /// Peg Port11 = Port 3
+ /// Peg Port12 = Port 4
+ /// CID2 Integated Ports:
+ /// Egress Port = Port 0
+ /// Root Port 1 = Port 1
+ /// Root Port 2 = Port 2
+ /// Root Port 3 = Port 3
+ /// Root Port 4 = Port 4
+ /// Azalia = Port 5
+ ///
+ ///
+ /// Get BAR registers
+ ///
+ PchRootComplexBar = MmPci32 (0, 0, 31, 0, 0xF0) &~BIT0;
+ PciExpressBar = McD0PciCfg64 (R_SA_PCIEXBAR) & (B_SA_PCIEXBAR_PCIEXBAR_MASK | B_SA_PCIEXBAR_ADMSK128_MASK | B_SA_PCIEXBAR_ADMSK64_MASK);
+ EgressPortBar = McD0PciCfg64 (R_SA_PXPEPBAR) &~BIT0;
+ MchBar = McD0PciCfg64 (R_SA_MCHBAR) &~BIT0;
+ DmiBar = McD0PciCfg64 (R_SA_DMIBAR) &~BIT0;
+
+ ///
+ /// Configure the Egress Port (0) in CID1
+ ///
+ Status = Cid1EgressPort0Init (EgressPortBar);
+
+#ifdef PEG_FLAG
+ if ((CpuFamilyId == EnumCpuHsw) || (CpuFamilyId == EnumCpuCrw)) {
+ ///
+ /// Configure the PEG Ports in CID1
+ ///
+ Status = Cid1PegPortInit (DxePlatformSaPolicy);
+ }
+#endif // PEG_FLAG
+
+ ///
+ /// Configure the SA DMI Port (1) in CID1 and the PCH DMI Port (0) in CID2.
+ /// Note that both links must be fully configured before the link
+ /// should be checked for negotiation between the 2 CIDs.
+ ///
+ DEBUG ((EFI_D_INFO, " Going to call Cid1Cid2DmiPortInit\n"));
+ Status = Cid1Cid2DmiPortInit (DmiBar, DxePlatformSaPolicy);
+
+ ///
+ /// Configure the RootComplex Topology in CID1.
+ ///
+ DEBUG ((EFI_D_INFO, " Going to call Cid1TopologyInit\n"));
+ Status = Cid1TopologyInit (EgressPortBar, DmiBar, PchRootComplexBar);
+
+ ///
+ /// Configure the RootComplex Topology in CID2.
+ ///
+ DEBUG ((EFI_D_INFO, " Going to call Cid2TopologyInit\n"));
+ Status = Cid2TopologyInit (PchRootComplexBar, DmiBar);
+
+ if (((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId >= EnumHswC0)) ||
+ ((CpuFamilyId == EnumCpuCrw) && (CpuSteppingId >= EnumCrwC0))) {
+ if (DxePlatformSaPolicy->Revision >= DXE_SA_PLATFORM_POLICY_PROTOCOL_REVISION_7) {
+ mSaGlobalNvsAreaProtocol.Area->C7Allowed = DxePlatformSaPolicy->PcieConfig->C7Allowed; //Update the Run-time C7 Allowed for ASL usage
+ }
+ }
+
+ mSaGlobalNvsAreaProtocol.Area->PackageCstateLimit = (UINT8)(AsmReadMsr64(MSR_PMG_CST_CONFIG) & B_PACKAGE_C_STATE_LIMIT);
+
+
+ return Status;
+}
+
+UINT32
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+ @param[in] Function - Pci Function Number
+ @param[in] CapId - CAPID to search for
+
+ @retval 0 - CAPID not found
+ @retval Other - CAPID found, Offset of desired CAPID
+**/
+{
+ UINT8 CapHeader;
+
+ ///
+ /// Always start at Offset 0x34
+ ///
+ CapHeader = MmPci8 (0, Bus, Device, Function, PCI_CAPP);
+ if (CapHeader == 0xFF) {
+ return 0;
+ }
+
+ while (CapHeader != 0) {
+ ///
+ /// Bottom 2 bits of the pointers are reserved per PCI Local Bus Spec 2.2
+ ///
+ CapHeader &= ~(BIT1 + BIT0);
+ ///
+ /// Search for desired CapID
+ ///
+ if (MmPci8 (0, Bus, Device, Function, CapHeader) == CapId) {
+ return CapHeader;
+ }
+
+ CapHeader = MmPci8 (0, Bus, Device, Function, CapHeader + 1);
+ }
+
+ return 0;
+}
+
+UINT32
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Rreporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+ @param[in] Function - Pci Function Number
+ @param[in] CapId - Extended CAPID to search for
+
+ @retval 0 - CAPID not found
+ @retval Other - CAPID found, Offset of desired CAPID
+**/
+{
+ UINT16 CapHeaderOffset;
+ UINT16 CapHeaderId;
+
+ ///
+ /// Start to search at Offset 0x100
+ /// Get Capability Header
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = 0x100;
+
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) {
+ ///
+ /// Search for desired CapID
+ ///
+ CapHeaderId = MmPci16 (0, Bus, Device, Function, CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ return CapHeaderOffset;
+ }
+
+ CapHeaderOffset = (MmPci16 (0, Bus, Device, Function, CapHeaderOffset + 2) >> 4);
+ }
+
+ return 0;
+}
+
+VOID
+PcieSetClkreq (
+ IN UINT8 Bus,
+ IN UINT8 Device
+ )
+/**
+ This function enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+**/
+{
+ UINT8 Function;
+ UINT32 CapOffset;
+
+ ///
+ /// Parse through all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if
+ /// exists then enable the CLKREQ# bit (BIT8) on that function
+ ///
+ for (Function = 0; Function < 8; Function++) {
+ ///
+ /// Find the PCIe Cap Id (offset 10h)
+ ///
+ CapOffset = PcieFindCapId (Bus, Device, Function, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+ ///
+ /// Check if CLKREQ# is supported by the endpoints
+ ///
+ if ((MmPci32 (0, Bus, Device, Function, (CapOffset + 0x0C)) & BIT18) != BIT18) {
+ ///
+ /// CLKREQ# is not supported so dont do anything
+ ///
+ return ;
+ }
+ }
+ ///
+ /// Now enable the CLKREQ#
+ ///
+ for (Function = 0; Function < 8; Function++) {
+ ///
+ /// Find the PCIe Cap Id (offset 10h)
+ ///
+ CapOffset = PcieFindCapId (Bus, Device, Function, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ MmPci16Or (0, Bus, Device, Function, (CapOffset + 0x010), BIT8);
+ }
+}
+
+VOID
+AdditionalDMIProgramStepsBeforeASPM (
+ IN UINT64 DmiBar,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Additional DMI Programming Steps as in SA BIOS spec
+
+ @param[in] DmiBar - DMIBAR Address
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ ///
+ /// Configure the De-emphasis control on DMI
+ ///
+ Data32And = (UINT32) ~BIT6;
+ Data32Or = (UINT32) ((DxePlatformSaPolicy->PcieConfig->DmiDeEmphasis & 0x1) << 6);
+ Mmio32AndThenOr (DmiBar, R_SA_DMIBAR_LCTL2_OFFSET, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + R_SA_DMIBAR_LCTL2_OFFSET),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Set 0x22C[31] to 1 before enabling ASPM
+ ///
+ Data32And = (UINT32) ~(BIT31);
+ Data32Or = (UINT32) BIT31;
+ Mmio32AndThenOr (DmiBar, R_SA_DMIBAR_L0SLAT_OFFSET, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + R_SA_DMIBAR_L0SLAT_OFFSET),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Set 0x238 bit29 for DMI before enabling ASPM
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = BIT29;
+ Mmio32Or (DmiBar, 0x238, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x238),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Set DMI Offset 0xC28 [4:0]
+ ///
+ Data32And = 0xFFFFFFE0;
+ Data32Or = 0x13;
+ Mmio32AndThenOr (DmiBar, R_SA_PEG_AFE_PM_TMR_OFFSET, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + R_SA_PEG_AFE_PM_TMR_OFFSET),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+}
+
+VOID
+AdditionalPEGProgramStepsBeforeASPM (
+ IN UINT8 Bus,
+ IN UINT8 pegDev,
+ IN UINT8 pegFn,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Additional PEG Programming Steps as in SA BIOS spec
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] pegDev - Pci Device Number
+ @param[in] pegFn - Pci Func Number
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT32 PegBaseAddress;
+
+ PegBaseAddress = (UINT32) MmPciAddress (0x0, Bus, pegDev, pegFn, 0x0);
+
+ ///
+ /// Permanently set PEGUESEV[CTS](0x1CC bit14) to 1b during BIOS boot for all the PEG controllers
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = BIT14;
+ Mmio32Or (PegBaseAddress, 0x1CC, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0x1CC),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Configure the De-emphasis control on PEG
+ ///
+ Data32And = (UINT32)~BIT6;
+ Data32Or = (DxePlatformSaPolicy->PcieConfig->PegDeEmphasis[pegFn] & BIT0) << 6;
+ Mmio32AndThenOr (PegBaseAddress, R_SA_PEG_LCTL2_OFFSET, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_LCTL2_OFFSET),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Set 0x22C[31] to 1 before enabling ASPM
+ ///
+ Data32And = (UINT32) ~(BIT31);
+ Data32Or = (UINT32) BIT31;
+ Mmio32AndThenOr (PegBaseAddress, R_SA_PEG_L0SLAT_OFFSET, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_L0SLAT_OFFSET),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Program 0x250 bit[22:20] to 010b for all the PEG controllers before enabling ASPM
+ ///
+ Data32And = (UINT32)~(BIT22 + BIT21 + BIT20);
+ Data32Or = 0x02 << 20;
+ Mmio32AndThenOr (PegBaseAddress, 0x250, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0x250),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Set 0x238 bit29 for PEG controller before enabling ASPM
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = BIT29;
+ Mmio32Or (PegBaseAddress, 0x238, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0x238),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Set PEG Offset 0x1F8 bit16
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = BIT16;
+ Mmio32Or (PegBaseAddress, 0x1F8, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0x1F8),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Set PEG Offset 0xC28 [4:0]
+ ///
+ Data32And = 0xFFFFFFE0;
+ Data32Or = 0x13;
+ Mmio32AndThenOr (PegBaseAddress, R_SA_PEG_AFE_PM_TMR_OFFSET, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_AFE_PM_TMR_OFFSET),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+}
+
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.h
new file mode 100644
index 0000000..05037b9
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PciExpressInit.h
@@ -0,0 +1,224 @@
+/** @file
+ Header file for PciExpress Initialization Driver.
+
+@copyright
+ Copyright (c) 1999 - 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
+**/
+#ifndef _PCIEXPRESS_INITIALIZATION_DRIVER_H_
+#define _PCIEXPRESS_INITIALIZATION_DRIVER_H_
+
+#include "EdkIIGlueDxe.h"
+#include "SaAccess.h"
+#include "PchAccess.h"
+#include "pci23.h"
+#include "EfiScriptLib.h"
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+#include "cpu.h"
+
+#include EFI_PROTOCOL_CONSUMER (ExitPmAuth)
+#include EFI_PROTOCOL_DEPENDENCY (BootScriptSave)
+#include EFI_PROTOCOL_CONSUMER (SaPlatformPolicy)
+#include EFI_PROTOCOL_DEPENDENCY (SaGlobalNvsArea)
+
+#define DISABLED 0
+#define AUTO 1
+#define ENABLED 1
+
+#define GEN1 1
+#define GEN2 2
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 Slot;
+ UINT8 Bus2;
+ UINT8 Device2;
+ UINT8 Function2;
+} PEG_PORT_DEVICE;
+
+///
+/// Function prototypes
+///
+/**
+ PCI Express Dxe Initialization.
+ Run before PCI Bus Init, where assignment of Bus, Memory,
+ and I/O Resources are assigned.
+
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - Pci Express successfully started and ready to be used
+ @exception EFI_UNSUPPORTED - Pci Express can't be initialized
+**/
+EFI_STATUS
+PciExpressInit (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+;
+
+/**
+ Find the Offset to a given Capabilities ID
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+ @param[in] Function - Pci Function Number
+ @param[in] CapId - CAPID to search fo
+
+ @retval 0 - CAPID not found
+ @retval Other - CAPID found, Offset of desired CAPID
+**/
+UINT32
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+;
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+ @param[in] Function - Pci Function Number
+ @param[in] CapId - Extended CAPID to search for
+
+ @retval 0 - CAPID not found
+ @retval Other - CAPID found, Offset of desired CAPID
+**/
+UINT32
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+;
+
+/**
+ This function enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+**/
+VOID
+PcieSetClkreq (
+ IN UINT8 Bus,
+ IN UINT8 Device
+ )
+;
+
+/**
+ Perform Egress Port 0 Initialization.
+
+ @param[in] EgressPortBar - EPBAR Address
+**/
+EFI_STATUS
+Cid1EgressPort0Init (
+ IN UINT64 EgressPortBar
+ )
+;
+
+#ifdef PEG_FLAG
+/**
+ Conditionally perform PEG Port Initialization.
+ bugbug: organize this code in a way that can utilize the
+ PchS3ItemTypeInitPcieRootPortDownstream EFI_PCH_S3_DISPATCH_ITEM_TYPE
+
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+EFI_STATUS
+Cid1PegPortInit (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+;
+#endif // PEG_FLAG
+
+/**
+ DMI Port Initialization for both CID1 (Port 1 in MCH) and CID2 (Port 0 in ICH).
+
+ @param[in] DmiBar - DMIBAR Address
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+EFI_STATUS
+Cid1Cid2DmiPortInit (
+ IN UINT64 DmiBar,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+;
+
+/**
+ Perform Root Complex Topology Initialization for CID1.
+
+ @param[in] EgressPortBar - EPBAR Address
+ @param[in] DmiBar - DMIBAR Address
+ @param[in] PchRootComplexBar - ICH RCBA Address
+**/
+EFI_STATUS
+Cid1TopologyInit (
+ IN UINT64 EgressPortBar,
+ IN UINT64 DmiBar,
+ IN UINT32 PchRootComplexBar
+ )
+;
+
+/**
+ Perform Root Complex Topology Initialization for CID2.
+
+ @param[in] DmiBar - DMIBAR Address
+ @param[in] PchRootComplexBar - ICH RCBA Address
+**/
+EFI_STATUS
+Cid2TopologyInit (
+ IN UINT32 PchRootComplexBar,
+ IN UINT64 DmiBar
+ )
+;
+
+/**
+ Additional PEG Programming Steps as in SA BIOS spec
+
+ @param[in] Bus - Bus Number of PEG device
+ @param[in] pegDev - Dev Number of PEG device
+ @param[in] pegFn - Func Number of PEG device
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+VOID
+AdditionalPEGProgramStepsBeforeASPM (
+ IN UINT8 Bus,
+ IN UINT8 pegDev,
+ IN UINT8 pegFn,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+;
+
+/**
+ Additional DMI Programming Steps as in SA BIOS spec
+
+ @param[in] DmiBar - DMIBAR Address
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+VOID
+AdditionalDMIProgramStepsBeforeASPM (
+ IN UINT64 DmiBar,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+;
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.c
new file mode 100644
index 0000000..bf4b367
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.c
@@ -0,0 +1,1371 @@
+/** @file
+ This file will perform SA PCIE Root Complex initialization.
+
+@copyright
+ Copyright (c) 1999 - 2012 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 "SaBuildFlags.h"
+#include "PciExpressInit.h"
+#include "EdkIIGluePcdPciExpressLib.h"
+#include "SaPcieLib.h"
+#include "PcieComplex.h"
+#include <Token.h>
+///
+/// Global variables
+///
+UINT8 HwStrap;
+extern UINT16 mSaIotrapSmiAddress;
+extern BOOLEAN mInitPcieAspmAfterOprom;
+extern DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy;
+
+#ifdef PEG_FLAG
+PEG_PORT_DEVICE PegDeviceTable[] = {
+ ///
+ /// Bus, Device, Function, Slot, Bus2, Device2, Function2
+ ///
+ { SA_PEG_BUS_NUM, SA_PEG10_DEV_NUM, SA_PEG10_FUN_NUM, 1, 2, 0, 0 }
+// AMI_OVERRID >>
+#if RC_PEG_1 == 1
+ ,{ SA_PEG_BUS_NUM, SA_PEG11_DEV_NUM, SA_PEG11_FUN_NUM, 2, 3, 0, 0 }
+#endif
+#if RC_PEG_2 == 1
+ ,{ SA_PEG_BUS_NUM, SA_PEG12_DEV_NUM, SA_PEG12_FUN_NUM, 3, 4, 0, 0 }
+#endif
+// AMI_OVERRID <<
+};
+#endif // PEG_FLAG
+
+///
+/// Functions
+///
+VOID
+EFIAPI
+SaLateInitSmiCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/**
+ This function gets registered as a callback to perform all SA late initialization
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+{
+ if (mSaIotrapSmiAddress != 0) {
+ DEBUG ((EFI_D_INFO, "[SA] Issue IOTRAP SMI %X\n", mSaIotrapSmiAddress));
+ IoWrite8 (mSaIotrapSmiAddress, 0);
+ }
+ if (Event != NULL) {
+ gBS->CloseEvent(Event);
+ }
+ return;
+}
+
+EFI_STATUS
+Cid1EgressPort0Init (
+ IN UINT64 EgressPortBar
+ )
+/**
+ Perform Egress Port 0 Initialization.
+
+ @param[in] EgressPortBar - EPBAR Address
+
+ @retval EFI_SUCCESS - Egress Port 0 initialization successed.
+**/
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT8 Data8And;
+ UINT8 Data8Or;
+ UINT8 BitMask;
+ UINT8 BitValue;
+
+ ///
+ /// Egress Port Configuration
+ ///
+ /// Egress Port Virtual Channel 0 Configuration
+ /// System BIOS must insure that only TC0 is mapped to VC0.
+ /// a. Set the Egress Port Register EPBAR offset 014h[7:1]=0000000b
+ ///
+ Data32And = BIT0;
+ Data32Or = 0;
+ Mmio32And (EgressPortBar, 0x14, Data32And);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x14),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// System BIOS must program the extended VC count field.
+ /// b. Set the Egress Port Register EPBAR offset 004h[2:0]=001b
+ ///
+ Data8And = (UINT8)~(0x07);
+ Data8Or = BIT0;
+ Mmio8AndThenOr (EgressPortBar, 0x4, Data8And, Data8Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (EgressPortBar + 0x4),
+ &Data8Or,
+ &Data8And
+ );
+
+ ///
+ /// Egress Port VC1 Configuration
+ /// a. Assign Virtual Channel ID 1 to VC1: by programming PXEPBAR Offset 020[26:24] = '001b'
+ /// b. Select and map TC1 to VC1: by programming PXPEPBAR Offset 020h[7:1] = '0000001b'
+ ///
+ Data32And = (UINT32)~(0x070000FE);
+ Data32Or = ((0x01 << 24) + BIT1);
+ Mmio32AndThenOr (EgressPortBar, 0x20, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x20),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// c. Enable VC1 (no hardware behind this bit, s/w compatibility flag only) BIT31
+ /// Program EXPEPBAR Offset 020h[31]=1
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = BIT31;
+ Mmio32Or (EgressPortBar, 0x20, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x20),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// d. Poll the VC1 Negotiation Pending bit until it reads 0:
+ /// Read the Egress Port Register EPBAR Offset 026h until [1]==0
+ ///
+ BitMask = (UINT8) BIT1;
+ BitValue = 0;
+ while ((Mmio8 (EgressPortBar, 0x26) & BitMask) != BitValue) {
+ };
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (EgressPortBar + 0x26),
+ &BitMask,
+ &BitValue,
+ 50,
+ 200000
+ );
+
+ return EFI_SUCCESS;
+}
+
+#ifdef PEG_FLAG
+EFI_STATUS
+Cid1PegPortInit (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Conditionally perform PEG Port Initialization.
+ bugbug: organize this code in a way that can utilize the
+ PchS3ItemTypeInitPcieRootPortDownstream EFI_PCH_S3_DISPATCH_ITEM_TYPE
+
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - PEG Port initialization successed.
+**/
+{
+ UINT32 Data32;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT16 Data16Or;
+ UINT16 Data16And;
+ UINT8 Data8;
+ UINT32 PegBaseAddress;
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Func;
+ UINT8 Slot;
+ UINT8 Bus2;
+ UINT8 Dev2;
+ UINT8 Func2;
+ UINT8 PegComplete;
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuSteppingId;
+
+ CpuFamilyId = GetCpuFamily();
+ CpuSteppingId = GetCpuStepping();
+
+ ///
+ /// Read HwStrap Register - PEG1CFGSEL D1.R 504h [17:16]
+ ///
+ HwStrap = (UINT8) ((McD1PciCfg32 (R_SA_PEG_FUSESCMN_OFFSET) & (BIT17 + BIT16)) >> 16);
+
+ ///
+ /// HSW - Scan/initialize PEG devices based on HW strapping.
+ ///
+ for (PegComplete = 0; PegComplete < ((sizeof (PegDeviceTable)) / (sizeof (PEG_PORT_DEVICE))); PegComplete++) {
+ ///
+ /// Get Peg Device BDF, Slot# and EndPoint(Temporary)
+ ///
+ Bus = PegDeviceTable[PegComplete].Bus;
+ Dev = PegDeviceTable[PegComplete].Device;
+ Func = PegDeviceTable[PegComplete].Function;
+ Slot = PegDeviceTable[PegComplete].Slot;
+ Bus2 = PegDeviceTable[PegComplete].Bus2;
+ Dev2 = PegDeviceTable[PegComplete].Device2;
+ Func2 = PegDeviceTable[PegComplete].Function2;
+
+ PegBaseAddress = (UINT32) MmPciAddress (0, Bus, Dev, Func, 0);
+ ///
+ /// Check if the PEG is Enabled. Since Graphics initialization has already
+ /// occurred, simply check for PEG presence.
+ /// bugbug: need to make sure this dependency is captured in the integration guide
+ ///
+ if (McDevFunPciCfg16 (Bus, Dev, Func, PCI_VID) != 0xFFFF) {
+ ///
+ /// PEG port enable and visible
+ ///
+ ///
+ /// Initialize Slot Implemented for PCI Express Port
+ ///
+ Data16And = 0xFFFF;
+ Data16Or = BIT8;
+
+ McDevFunPciCfg16Or (Bus, Dev, Func, R_SA_PEG_CAP_OFFSET, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PegBaseAddress + R_SA_PEG_CAP_OFFSET),
+ &Data16Or,
+ &Data16And
+ );
+
+ ///
+ /// Initialize "Physical Slot Number" for PCI Express Port
+ ///
+ Data32 = McDevFunPciCfg32 (Bus, Dev, Func, R_SA_PEG_SLOTCAP_OFFSET);
+ Data32 &= 0x0007FFFF;
+ ///
+ /// Set [31:19] - Slot # based on Peg Port
+ ///
+ Data32 |= (Slot << 19);
+
+ ///
+ /// Initialize Slot Power Limit for PCI Express Port and Power Limit Scale.
+ /// Note: this register is a write once.
+ ///
+ /// Set [14:7] - 75 Watts (Default)
+ ///
+ Data32 &= 0xFFFE007F;
+ Data32 |= (75 << 7);
+ ///
+ /// [16:15] - 1.0 Watt Scale
+ ///
+ Data32 |= (0 << 15);
+
+ McDevFunPciCfg32 (Bus, Dev, Func, R_SA_PEG_SLOTCAP_OFFSET) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_SLOTCAP_OFFSET),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Additional Programming Steps
+ ///
+ /// Set PEG D.F.R 006h [15:0] = 0FFFFh
+ ///
+ Data32And = ~(0xFFFF0000);
+ Data32Or = 0xFFFF0000;
+
+ McDevFunPciCfg32AndThenOr (Bus, Dev, Func, 0x4, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0x4),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Set PEG D.F.R 01Eh [15:0] = 0FFFFh
+ ///
+ Data32And = ~(0xFFFF0000);
+ Data32Or = 0xFFFF0000;
+
+ McDevFunPciCfg32AndThenOr (Bus, Dev, Func, 0x1C, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0x1C),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Set PEG D.F.R 0AAh [15:0] = 0FFFFh
+ ///
+ Data32And = 0xFFFF;
+ Data32Or = 0xFFFF;
+
+ McDevFunPciCfg16Or (Bus, Dev, Func, 0xAA, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PegBaseAddress + 0xAA),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Set PEG D.F.R 1C4h [31:0] = 0FFFFFFFFh
+ ///
+ Data32 = 0xFFFFFFFF;
+
+ McDevFunPciCfg32Or (Bus, Dev, Func, R_SA_PEG_PEGUESTS_OFFSET, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_PEGUESTS_OFFSET),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Set PEG D.F.R 1D0h [31:0] = 0FFFFFFFFh
+ ///
+ Data32 = 0xFFFFFFFF;
+
+ McDevFunPciCfg32Or (Bus, Dev, Func, R_SA_PEG_PEGCESTS_OFFSET, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_PEGCESTS_OFFSET),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Set PEG D.F.R 1F0h [31:0] = 0FFFFFFFFh
+ ///
+ Data32 = 0xFFFFFFFF;
+
+ McDevFunPciCfg32Or (Bus, Dev, Func, 0x1F0, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0x1F0),
+ 1,
+ &Data32
+ );
+ ///
+ /// If HSW CPU steppingId >= B0 or CRW, set BIT19 of DCAP2 register of the PEG port,to enable OBFF support using WAKE# signaling
+ ///
+ if (((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId >= EnumHswB0)) ||
+ (CpuFamilyId == EnumCpuCrw)) {
+ Data32 = (UINT32) BIT19;
+ McDevFunPciCfg32Or (Bus, Dev, Func, R_SA_PEG_DCAP2_OFFSET, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_DCAP2_OFFSET),
+ 1,
+ &Data32
+ );
+ }
+ ///
+ /// Complete Common Port and Endpoint Configuration
+ ///
+ ///
+ /// Virtual Channel Configuration of PCI Express Port
+ /// Set the VC0RCTL register D1:F0 Offset 114h [7:1] = 7Fh
+ ///
+ Data32And = 0xFFFFFF01;
+ Data32Or = BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1;
+
+ McDevFunPciCfg32AndThenOr (Bus, Dev, Func, R_SA_PEG_VC0RCTL0_OFFSET, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_VC0RCTL0_OFFSET),
+ &Data32Or,
+ &Data32And
+ );
+ ///
+ /// 6.8 Additional Programming Steps before Enabling ASPM for PEG device
+ ///
+ AdditionalPEGProgramStepsBeforeASPM (Bus, Dev, Func, DxePlatformSaPolicy);
+
+ ///
+ /// 6.10 Interrupt Routing for PCI Express*
+ /// It is recommened to re-route the legacy interrupts (INTA -> INTB,C,D)
+ /// to avoid overcrowded INTA. ACPI PRT needs update.
+ /// The ACPI _PRT() methods for PEG controllers must match the legacy interrupt routing.
+ ///
+ if ((Dev == 1) && (Func == 1)) {
+ Data32And = (UINT32)~(BIT25 | BIT24);
+ Data32Or = BIT24 | BIT25;
+ McDevFunPciCfg32AndThenOr (Bus, Dev, Func, R_SA_PEG_CFG4_OFFSET, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_CFG4_OFFSET),
+ &Data32Or,
+ &Data32And
+ );
+ }
+
+ if ((Dev == 1) && (Func == 2)) {
+ Data32And = (UINT32)~(BIT25 | BIT24);
+ Data32Or = BIT25;
+ McDevFunPciCfg32AndThenOr (Bus, Dev, Func, R_SA_PEG_CFG4_OFFSET, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_CFG4_OFFSET),
+ &Data32Or,
+ &Data32And
+ );
+ }
+ }
+
+ ///
+ /// Lock offset 3Dh for Interrupt Pin
+ ///
+ Data8 = McDevFunPciCfg8 (Bus, Dev, Func, PCI_INTPIN);
+ McDevFunPciCfg8 (Bus, Dev, Func, PCI_INTPIN) = Data8;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (PegBaseAddress + PCI_INTPIN),
+ 1,
+ &Data8
+ );
+
+ ///
+ /// Lock DCAP register
+ ///
+ Data32 = McDevFunPciCfg32 (Bus, Dev, Func, R_SA_PEG_DCAP_OFFSET);
+ McDevFunPciCfg32 (Bus, Dev, Func, R_SA_PEG_DCAP_OFFSET) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + R_SA_PEG_DCAP_OFFSET),
+ 1,
+ &Data32
+ );
+
+ if ((CpuFamilyId == EnumCpuHsw) || (CpuFamilyId == EnumCpuCrw)
+ ){
+ if ((Bus == 0) && (Dev == 1) && (Func == 0)) {
+ Data32 = McDevFunPciCfg32 (Bus, Dev, Func, 0xCD0);
+ Data32 |= BIT11;
+ McDevFunPciCfg32 (Bus, Dev, Func, 0xCD0) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PegBaseAddress + 0xCD0),
+ 1,
+ &Data32
+ );
+ }
+ }
+
+ if ((HwStrap == SA_PEG_x16_x0_x0) && (PegComplete == 0)) {
+ break;
+ }
+ if ((HwStrap == SA_PEG_x8_x8_x0) && (PegComplete == 1)) {
+ break;
+ }
+ if ((HwStrap == SA_PEG_x8_x4_x4) && (PegComplete == 2)) {
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+#endif // PEG_FLAG
+
+EFI_STATUS
+Cid1Cid2DmiPortInit (
+ IN UINT64 DmiBar,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ DMI Port Initialization for both CID1 (Port 1 in MCH) and CID2 (Port 0 in PCH).
+
+ @param[in] DmiBar - DMIBAR Address
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - DMI Port initialization successed.
+**/
+{
+ UINT32 Data32Or;
+#ifdef DMI_FLAG
+ UINT8 Data8And;
+ UINT8 Data8Or;
+ CPU_FAMILY CpuFamilyId;
+
+ CpuFamilyId = GetCpuFamily();
+#endif // DMI_FLAG
+
+#ifdef DMI_FLAG
+ if ((CpuFamilyId == EnumCpuHsw) || (CpuFamilyId == EnumCpuCrw)) {
+ ///
+ /// Additional Programming Steps
+ ///
+ AdditionalDMIProgramStepsBeforeASPM (DmiBar, DxePlatformSaPolicy);
+ }
+#endif // DMI_FLAG
+
+ ///
+ /// Set DMIBAR Offset 1C4h [31:0] = 0FFFFFFFFh
+ ///
+ Data32Or = 0xFFFFFFFF;
+ Mmio32 (DmiBar, 0x1C4) = 0xFFFFFFFF;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x1C4),
+ 1,
+ &Data32Or
+ );
+
+ ///
+ /// Set DMIBAR Offset 1D0h [31:0] = 0FFFFFFFFh
+ ///
+ Data32Or = 0xFFFFFFFF;
+ Mmio32 (DmiBar, 0x1D0) = 0xFFFFFFFF;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x1D0),
+ 1,
+ &Data32Or
+ );
+
+#ifdef DMI_FLAG
+ if ((CpuFamilyId == EnumCpuHsw) || (CpuFamilyId == EnumCpuCrw)) {
+ ///
+ /// Enable `Active State PM'. DMILCTL register at DMIBAR 088h [1:0] = '11b'.
+ /// Based on the policy:
+ ///
+ if (DxePlatformSaPolicy->PcieConfig->DmiAspm == PcieAspmAutoConfig ||
+ DxePlatformSaPolicy->PcieConfig->DmiAspm == PcieAspmL0sL1
+ ) {
+ ///
+ /// Enable ASPM = L0s and L1 Entry
+ ///
+ Data8And = 0xFC;
+ Data8Or = 0x03;
+ Mmio8Or (DmiBar, 0x88, Data8Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (DmiBar + 0x088),
+ &Data8Or,
+ &Data8And
+ );
+ } else if (DxePlatformSaPolicy->PcieConfig->DmiAspm == PcieAspmL0s) {
+ ///
+ /// Enable ASPM = L0s
+ ///
+ Data8And = 0xFC;
+ Data8Or = 0x01;
+ Mmio8Or (DmiBar, 0x88, Data8Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (DmiBar + 0x088),
+ &Data8Or,
+ &Data8And
+ );
+ } else if (DxePlatformSaPolicy->PcieConfig->DmiAspm == PcieAspmL1) {
+ ///
+ /// Enable ASPM = L1
+ ///
+ Data8And = 0xFC;
+ Data8Or = 0x02;
+ Mmio8Or (DmiBar, 0x88, Data8Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (DmiBar + 0x088),
+ &Data8Or,
+ &Data8And
+ );
+ }
+
+ if (DxePlatformSaPolicy->PcieConfig->DmiExtSync == ENABLED) {
+ ///
+ /// Enable Extended Synch
+ ///
+ Data8And = 0xFF;
+ Data8Or = 0x10;
+ Mmio8Or (DmiBar, 0x88, Data8Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (DmiBar + 0x088),
+ &Data8Or,
+ &Data8And
+ );
+ }
+
+ if (DxePlatformSaPolicy->PcieConfig->DmiIot == ENABLED) {
+ ///
+ /// if DMI Iot is enabled, set DMIBAR offset 0xD34 = 0x44
+ ///
+ Data8Or = 0x44;
+ Mmio8 (DmiBar, 0xD34) = 0x44;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (DmiBar + 0xD34),
+ 1,
+ (VOID *) (UINTN) (DmiBar + 0xD34)
+ );
+ }
+ }
+#endif // DMI_FLAG
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Cid1TopologyInit (
+ IN UINT64 EgressPortBar,
+ IN UINT64 DmiBar,
+ IN UINT32 PchRootComplexBar
+ )
+/**
+ Perform Root Complex Topology Initialization for CID1.
+
+ @param[in] EgressPortBar - EPBAR Address
+ @param[in] DmiBar - DMIBAR Address
+ @param[in] PchRootComplexBar - PCH RCBA Address
+
+ @retval EFI_SUCCESS - Root Complex topology initialization for CID1 successed.
+**/
+{
+ UINT32 Data32;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT32 DwordReg;
+ UINT64 McD1Base;
+ UINT64 McD1F1Base;
+ UINT64 McD1F2Base;
+
+ McD1Base = MmPciAddress (0, 0, 1, 0, 0);
+ McD1F1Base = MmPciAddress (0, 0, 1, 1, 0);
+ McD1F2Base = MmPciAddress (0, 0, 1, 2, 0);
+
+ ///
+ /// Set the CID1 Egress Port 0 Topology
+ ///
+ ///
+ /// Step 1, Set the SA Component ID = 1.
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = BIT16;
+ Mmio32AndThenOr (EgressPortBar, 0x44, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x44),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 2, Set link 1 Target Component ID and valid (Bit 0 = 1b).
+ /// Set the Link 1 TCID = 1 (Bits 23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ Mmio32AndThenOr (EgressPortBar, 0x50, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x50),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 3, Set Link 1 to Reference the DMI RCRB (Bits 31:0 = DMI Base).
+ ///
+ Data32 = (UINT32) DmiBar;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x58, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x58),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x58 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x58 + 4),
+ 1,
+ &Data32
+ );
+
+#ifdef PEG_FLAG
+ ///
+ /// CID1 Egress port Root Topology and PciExpress Port (PEG Ports) Topology
+ /// Programming only if PEG devices are enabled.
+ ///
+ /// Step 1 PCI Express Enabled Check
+ /// Check and Configure CID1 root and Device 1 function 0
+ ///
+ if (McD1PciCfg16 (PCI_VID) != 0xFFFF) {
+ ///
+ /// Step 4, Set Link 2 to Reference the Device 1 function 0.
+ ///
+ Data32 = (UINT32) 0x8000;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x68, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x68),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x68 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x68 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 5, Set link 2 Target Component ID and valid bit(Offset 60h, Bit 0 = 1b)
+ /// Set the Link 2 TCID = 1 (Bits 23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ Mmio32AndThenOr (EgressPortBar, 0x60, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x60),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Set the CID1 PCI Express* Port Root Topology
+ ///
+ /// Step 2 Set the Link 1 CID = 1 144h(23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = BIT16;
+ MmioAndThenOr32 ((UINTN) McD1Base + 0x144, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1Base + 0x144),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 3. Set Link 1 to Reference the SA EP RCRB (Bits 31:0 = EPBAR).
+ ///
+ Data32 = (UINT32) EgressPortBar;
+ MmioWrite32 ((UINTN) McD1Base + 0x158, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1Base + 0x158),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) McD1Base + 0x158 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1Base + 0x158 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 4 Set link 1 Target Component ID and valid bit(Offset 150h, Bit 0 = 1b)
+ /// Set the Link 1 TCID = 1 (Bits 23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ MmioAndThenOr32 ((UINTN) McD1Base + 0x150, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1Base + 0x150),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 5 Program Read-Only Write-Once Registers
+ /// D1.F0.R 0C4h [31:0]
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) 0x00;
+ Data32 = McD1PciCfg32 (0xC4);
+ McD1PciCfg32 (0xC4) = Data32;
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1Base + 0xC4),
+ &Data32Or,
+ &Data32And
+ );
+ }
+ ///
+ /// Check and Configure CID1 root and Device 1 function 1
+ ///
+ if (McD1F1PciCfg16 (PCI_VID) != 0xFFFF) {
+ ///
+ /// Step 6, Set Link 3 to Reference the Device 1 function 1.
+ ///
+ Data32 = (UINT32) 0x9000;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x78, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x78),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x78 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x78 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 7. Set the Link 3 Target Component ID and Valid Bit 70h [0]
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ Mmio32AndThenOr (EgressPortBar, 0x70, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x70),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 2 Set the Link 1 CID = 1 144h(23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = BIT16;
+ MmioAndThenOr32 ((UINTN) McD1F1Base + 0x144, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F1Base + 0x144),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 3 Set Link 1 to Reference the IMC EP RCRB (Bits 31:0 = EPBAR).
+ ///
+ Data32 = (UINT32) EgressPortBar;
+ MmioWrite32 ((UINTN) McD1F1Base + 0x158, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F1Base + 0x158),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) McD1F1Base + 0x158 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F1Base + 0x158 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 4 Set link 1 Target Component ID and valid bit(Offset 150h, Bit 0 = 1b)
+ /// Set the Link 1 TCID = 1 (Bits 23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ MmioAndThenOr32 ((UINTN) McD1F1Base + 0x150, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F1Base + 0x150),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 5 Program Read-Only Write-Once Registers
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) 0x00;
+ Data32 = McD1F1PciCfg32 (0xC4);
+ McD1F1PciCfg32 (0xC4) = Data32;
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F1Base + 0xC4),
+ &Data32Or,
+ &Data32And
+ );
+ }
+ ///
+ /// Check and Configure CID1 root and Device 1 function 2
+ ///
+ if (McD1F2PciCfg16 (PCI_VID) != 0xFFFF) {
+ ///
+ /// Step 8, Set Link 4 to Reference the Device 1 function 2.
+ ///
+ Data32 = (UINT32) 0xA000;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x88, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x88),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) EgressPortBar + 0x88 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x88 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 9, Set the Link 4 Target Component ID and Valid Bit 80h [0]
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ Mmio32AndThenOr (EgressPortBar, 0x80, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (EgressPortBar + 0x80),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 2. Set the Link 1 CID = 1 144h(23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = BIT16;
+ MmioAndThenOr32 ((UINTN) McD1F2Base + 0x144, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F2Base + 0x144),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 3. Set Link 1 to Reference the IMC EP RCRB (Bits 31:0 = EPBAR).
+ ///
+ Data32 = (UINT32) EgressPortBar;
+ MmioWrite32 ((UINTN) McD1F2Base + 0x158, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F2Base + 0x158),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) McD1F2Base + 0x158 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F2Base + 0x158 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 4. Set link 1 Target Component ID and valid bit(Offset 150h, Bit 0 = 1b)
+ /// Set the Link 1 TCID = 1 (Bits 23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ MmioAndThenOr32 ((UINTN) McD1F2Base + 0x150, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F2Base + 0x150),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 5. Program Read-Only Write-Once Registers
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) 0x00;
+ Data32 = McD1F2PciCfg32 (0xC4);
+ McD1F2PciCfg32 (0xC4) = Data32;
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (McD1F2Base + 0xC4),
+ &Data32Or,
+ &Data32And
+ );
+ }
+#endif // PEG_FLAG
+
+ ///
+ /// Set the CID1 DMI Port Root Topology
+ ///
+ /// Step 1 Set the CID = 1 ( Bits 23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = BIT16;
+ Mmio32AndThenOr (DmiBar, 0x44, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x44),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 2. Set Link 1 Target Port Number = 0 (Bits 31:24 = 00h).
+ /// Step 3. Set Link 1 TCID = 2 (Bits 23:16 = 02h).
+ /// Step 4. Set Link 1 as valid (Bit 0 = 1b).
+ ///
+ Data32And = 0x0000FFFF;
+ Data32Or = (BIT17 + BIT0);
+ Mmio32AndThenOr (DmiBar, 0x50, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x50),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 5, Set Link 1 to Reference the PCH RCRB
+ ///
+ Data32 = PchRootComplexBar;
+ Mmio32 (DmiBar, 0x58) = PchRootComplexBar;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x58),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ Mmio32 (DmiBar, 0x58 + 4) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x58 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 6, Set Link 2 to Reference the IMC EP (Bits 31:0 = EP).
+ ///
+ Data32 = (UINT32) EgressPortBar;
+ MmioWrite32 ((UINTN) DmiBar + 0x68, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x68),
+ 1,
+ &Data32
+ );
+ Data32 = (UINT32) 0x00;
+ MmioWrite32 ((UINTN) DmiBar + 0x68 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x68 + 4),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Step 7, Set link 2 Target Component ID and valid Bit(Bit 0 = 1b)
+ /// Set the Link 2 TCID = 1 (Bits 23:16 = 01h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = (BIT16 | BIT0);
+ Mmio32AndThenOr (DmiBar, 0x60, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (DmiBar + 0x60),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// Step 8. Program RO and Write-Once Registers
+ /// DMIBAR Offset 004h [31:0]
+ /// DMIBAR Offset 084h [31:0]
+ ///
+ DwordReg = Mmio32 (DmiBar, 0x4);
+ Mmio32 (DmiBar, 0x4) = DwordReg;
+
+ DwordReg = Mmio32 (DmiBar, 0x84);
+ Mmio32 (DmiBar, 0x84) = DwordReg;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Cid2TopologyInit (
+ IN UINT32 PchRootComplexBar,
+ IN UINT64 DmiBar
+ )
+/**
+ Perform Root Complex Topology Initialization for CID2.
+ Note: This sequence follows PCH BIOS specification Ver 0.5 section 8.3
+ Root Complex Topology Programming
+
+ @param[in] PchRootComplexBar - PCH RCBA Address
+ @param[in] DmiBar - DMIBAR Address
+
+ @retval EFI_SUCCESS - Root Complex topology initialization for CID2 successed.
+**/
+{
+ UINT32 Data32;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ ///
+ /// PCH BIOS specification Ver 0.5 section 8.3 Note 1,2
+ /// program a value into this Component ID field to determine the Component ID of
+ /// ICH8, and this value must be different from the Component ID value of the MCH.
+ /// Set the CID = 2 (Offset 104h, Bits 23:16 = 02h).
+ ///
+ Data32And = 0xFF00FFFF;
+ Data32Or = BIT17;
+ MmioAndThenOr32 (PchRootComplexBar + 0x104, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PchRootComplexBar + 0x104),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// PCH BIOS specification Ver 0.5 section 8.3 Note 3,4
+ /// Note 3: This Target Port # field must be filled in by System BIOS with the Port
+ /// # of the RCRB DMI link in the MCH.
+ /// Note 4: This Target CID field must be filled in by System BIOS with the
+ /// Component ID of the MCH.
+ /// Set the Link 1 Target Port Number = 1 (Offset 110h, bits 31:24 = 01h).
+ /// Set the Link 1 Target Component ID = 1 (Offset 110h, bits 23:16 = 01h).
+ ///
+ Data32And = 0x0000FFFF;
+ Data32Or = (BIT24 | BIT16);
+ MmioAndThenOr32 (PchRootComplexBar + 0x110, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PchRootComplexBar + 0x110),
+ &Data32Or,
+ &Data32And
+ );
+
+ ///
+ /// PCH BIOS specification Ver 0.5 section 8.3 Note 5
+ /// Fill the Base Address field with the same base address of the RCRB DMI link in
+ /// the MCH, This register field is located at RCBA+ 0118h[63:0],
+ /// and will be locked once written until the next reset.
+ ///
+ Data32 = (UINT32) DmiBar;
+ MmioWrite32 (PchRootComplexBar + 0x118, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PchRootComplexBar + 0x118),
+ 1,
+ &Data32
+ );
+
+ Data32 = *((UINT32 *) (&DmiBar) + 1);
+ MmioWrite32 (PchRootComplexBar + 0x118 + 4, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (PchRootComplexBar + 0x118 + 4),
+ 1,
+ &Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PegInitBeforeExitPmAuth (
+ VOID
+ )
+/**
+ This function performs Peg initialization before ExitPmAuth.
+
+ @retval EFI_SUCCESS - Always.
+**/
+{
+#if SA_PCIE_ASPM_IN_SMM == 1
+ EFI_EVENT ReadyToBoot;
+ EFI_STATUS Status;
+#endif
+ BOOLEAN AspmHasBeenHandled;
+
+ DEBUG ((EFI_D_ERROR, "[SA] Pcie before ExitPmAuth callback.\n"));
+ AspmHasBeenHandled = FALSE;
+ ///
+ /// SMM mode ASPM handling
+ /// Check if supported and enabled
+ ///
+#if SA_PCIE_ASPM_IN_SMM == 1
+ if ((mInitPcieAspmAfterOprom == 1) && (mSaIotrapSmiAddress != 0)) {
+ ///
+ /// Do the Phase 1 SMI callback
+ /// This will enumerate PCIe downstream devices
+ ///
+ SaLateInitSmiCallback (NULL, NULL);
+
+ ///
+ /// Create an ReadyToBoot call back event to do the Phase 3 SMI callback
+ /// This will handle PEG ASPM programming after OROM execution
+ ///
+ Status = EfiCreateEventReadyToBootEx (
+ EFI_TPL_NOTIFY,
+ SaLateInitSmiCallback,
+ NULL,
+ &ReadyToBoot
+ );
+ ASSERT_EFI_ERROR (Status);
+ AspmHasBeenHandled = TRUE;
+ }
+#endif
+
+ ///
+ /// DXE mode ASPM handling
+ /// Check if SMM mode already taken care all things
+ /// TRUE to skip DXE mode task. Otherwise do DXE mode ASPM initialization
+ ///
+#if SA_PCIE_ASPM_IN_DXE == 1
+ if (AspmHasBeenHandled == FALSE) {
+ ///
+ /// Initialize ASPM before OpROM, S3 Save script supported
+ /// First initialize all policy settings
+ /// Initialize module global variables - Stepping ID and Platform Policy
+ ///
+ SaPcieInitPolicy (mDxePlatformSaPolicy);
+ ///
+ /// Do initialization
+ ///
+ SaPcieEnumCallback ();
+ SaPcieConfigAfterOpRom ();
+ }
+#endif
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SaSecurityInit (
+ VOID
+ )
+/**
+ This function performs SA Security locking in ExitPmAuth callback
+
+ @retval EFI_SUCCESS - Security lock has done
+ @retval EFI_UNSUPPORTED - Security lock not done successfully
+**/
+{
+ BOOLEAN SecurityHasBeenHandled;
+ SecurityHasBeenHandled = FALSE;
+#if SA_PCIE_ASPM_IN_SMM == 1
+ if ((mInitPcieAspmAfterOprom == 1) && (mSaIotrapSmiAddress != 0)) {
+ ///
+ /// Generate the Phase 2 of SA SMI to do security lock
+ ///
+ SaLateInitSmiCallback (NULL, NULL);
+
+ SecurityHasBeenHandled = TRUE;
+ }
+#endif
+
+ ///
+ /// Check if SMM mode already taken care this task
+ ///
+#if SA_PCIE_ASPM_IN_DXE == 1
+ if (SecurityHasBeenHandled == FALSE) {
+ SaSaveRestorePlatform (TRUE);
+ SaSecurityLock ();
+ SecurityHasBeenHandled = TRUE;
+ }
+#endif
+ ///
+ /// Security locking is important so fail to do this will be an ERROR.
+ ///
+ if (SecurityHasBeenHandled == TRUE) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.h
new file mode 100644
index 0000000..8a52de9
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/PcieComplex.h
@@ -0,0 +1,43 @@
+/** @file
+ This is header file for SA PCIE Root Complex initialization.
+
+@copyright
+ Copyright (c) 1999 - 2012 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
+**/
+
+EFI_STATUS
+PegInitBeforeExitPmAuth (
+ VOID
+ )
+/**
+ This function performs Peg initialization before ExitPmAuth.
+
+ @retval EFI_SUCCESS - Always.
+**/
+;
+
+EFI_STATUS
+SaSecurityInit (
+ VOID
+ )
+/**
+ This function performs SA Security locking in ExitPmAuth callback
+
+ @retval EFI_SUCCESS - Security lock has done
+ @retval EFI_UNSUPPORTED - Security lock not done successfully
+**/
+;
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaFvi.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaFvi.c
new file mode 100644
index 0000000..d88a5e7
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaFvi.c
@@ -0,0 +1,105 @@
+/** @file
+ SA Firmware Version Info implementation.
+
+@copyright
+ Copyright (c) 2011 - 2012 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 "SaInit.h"
+
+FVI_ELEMENT_AND_FUNCTION mSaFviElementsData[] = {
+ {
+ DEFAULT_FVI_ELEMENT_DATA(SA),
+ NULL
+ },
+ {
+ {
+ 1,
+ 0,
+ MEM_RC_VERSION,
+ MEM_FVI_STRING,
+ {
+ 0
+ },
+ },
+ NULL
+ },
+ {
+ {
+ 1,
+ 0,
+ PCIE_RC_VERSION,
+ PCIE_FVI_STRING,
+ {
+ 0
+ },
+ },
+ NULL
+ },
+ {
+ {
+ 1,
+ 2,
+ SA_CRID_VERSION,
+ SA_CRID_STATUS,
+ SA_CRID_DISABLED,
+ },
+ NULL
+ },
+ {
+ {
+ 1,
+ 0,
+ SA_CRID_VERSION,
+ SA_CRID_ORIGINAL_VALUE,
+ {
+ 0
+ },
+ },
+ NULL
+ },
+ {
+ {
+ 1,
+ 0,
+ SA_CRID_VERSION,
+ SA_CRID_NEW_VALUE,
+ {
+ 0
+ },
+ },
+ NULL
+ },
+ {
+ {
+ 1,
+ 0,
+ VBIOS_RC_VERSION,
+ VBIOS_FVI_STRING,
+ {
+ 0
+ },
+ },
+ NULL
+ }
+};
+
+FVI_DATA_HUB_CALLBACK_CONTEXT mSaFviVersionData = {
+ MISC_SUBCLASS_FVI_HEADER_ENTRY(SA),
+ mSaFviElementsData,
+};
+
+UINTN mSaFviElements = sizeof (mSaFviElementsData) / sizeof (FVI_ELEMENT_AND_FUNCTION);
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.c
new file mode 100644
index 0000000..af4d45a
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.c
@@ -0,0 +1,842 @@
+/** @file
+ This is the driver that initializes the Intel System Agent.
+
+@copyright
+ Copyright (c) 1999 - 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 "SaInit.h"
+#include EFI_GUID_DEFINITION (SaDataHob)
+#include <Protocol/PciEnumerationComplete.h>
+#include EFI_PROTOCOL_DEPENDENCY (SaGlobalNvsArea)
+#include EFI_GUID_DEFINITION (SaSsdtTableStorage)
+
+///
+/// Global Variables
+///
+SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL mSaGlobalNvsAreaProtocol;
+DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy;
+UINT16 mSaIotrapSmiAddress;
+BOOLEAN mInitPcieAspmAfterOprom;
+EFI_GUID gEfiPciEnumerationCompleteProtocolGuid = EFI_PCI_ENUMERATION_COMPLETE_GUID;
+
+EFI_STATUS
+InitializeSaSsdtAcpiTables (
+ VOID
+ )
+/**
+@brief
+ Initialize System Agent SSDT ACPI tables
+
+ @retval EFI_SUCCESS ACPI tables are initialized successfully
+ @retval EFI_NOT_FOUND ACPI tables not found
+**/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN AcpiTableKey;
+ UINT8 *CurrPtr;
+ UINT8 *EndPtr;
+ UINT32 *Signature;
+ EFI_ACPI_DESCRIPTION_HEADER *SaAcpiTable;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+
+ FwVol = NULL;
+ SaAcpiTable = NULL;
+
+ ///
+ /// Locate ACPI Table protocol
+ ///
+ DEBUG ((EFI_D_INFO, "Init SA SSDT table\n"));
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, &AcpiTable);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Fail to locate EfiAcpiTableProtocol.\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ ///
+ /// Locate protocol.
+ /// There is little chance we can't find an FV protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Looking for FV with ACPI storage file
+ ///
+ for (i = 0; i < NumberOfHandles; i++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ &gEfiFirmwareVolumeProtocolGuid,
+ &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &gSaSsdtAcpiTableStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ ///
+ /// If we found it, then we are done
+ ///
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol != NULL);
+ if (FwVol == NULL) {
+ DEBUG ((EFI_D_INFO, "SA Global NVS table not found\n"));
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Our exit status is determined by the success of the previous operations
+ /// If the protocol was found, Instance already points to it.
+ /// Read tables from the storage file.
+ ///
+ Instance = 0;
+ CurrentTable = NULL;
+ while (Status == EFI_SUCCESS) {
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gSaSsdtAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Check the table ID to modify the table
+ ///
+ if (((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->OemTableId == EFI_SIGNATURE_64 ('S', 'a', 'S', 's', 'd', 't', ' ', 0)) {
+ SaAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ ///
+ /// Locate the SSDT package
+ ///
+ CurrPtr = (UINT8 *) SaAcpiTable;
+ EndPtr = CurrPtr + SaAcpiTable->Length;
+
+ for (; CurrPtr <= EndPtr; CurrPtr++) {
+ Signature = (UINT32 *) (CurrPtr + 3);
+ if (*Signature == EFI_SIGNATURE_32 ('S', 'A', 'N', 'V')) {
+ ASSERT_EFI_ERROR (*(UINT32 *) (CurrPtr + 3 + sizeof (*Signature) + 2) == 0xFFFF0000);
+ ASSERT_EFI_ERROR (*(UINT16 *) (CurrPtr + 3 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) == 0xAA55);
+ ///
+ /// SA Global NVS Area address
+ ///
+ *(UINT32 *) (CurrPtr + 3 + sizeof (*Signature) + 2) = (UINT32) (UINTN) mSaGlobalNvsAreaProtocol.Area;
+ ///
+ /// SA Global NVS Area size
+ ///
+ *(UINT16 *) (CurrPtr + 3 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) =
+ sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA);
+
+ AcpiTableKey = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ SaAcpiTable,
+ SaAcpiTable->Length,
+ &AcpiTableKey
+ );
+ ASSERT_EFI_ERROR (Status);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ ///
+ /// Increment the instance
+ ///
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+ return Status;
+
+}
+
+EFI_STATUS
+EFIAPI
+SaInitEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/**
+ SystemAgent DXE Initialization.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+**/
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+ SA_INSTANCE_PRIVATE_DATA *SaInstance;
+ UINTN MCHBAR_BASE;
+ SA_DATA_HOB *SaDataHob;
+
+ DEBUG ((EFI_D_INFO, "SaInitDxe Start\n"));
+
+ INITIALIZE_SCRIPT (ImageHandle, SystemTable);
+ SaInstance = NULL;
+
+ MCHBAR_BASE = McD0PciCfg64 (R_SA_MCHBAR) &~BIT0;
+
+ ///
+ /// Get the platform setup policy.
+ ///
+ Status = gBS->LocateProtocol (&gDxePlatformSaPolicyGuid, NULL, (VOID **) &mDxePlatformSaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Dump SA Platform Policy
+ ///
+ SaDxePolicyDump (mDxePlatformSaPolicy);
+
+ ///
+ /// Get SaDataHob HOB and see if ASPM should be programmed before or after OpROM.
+ ///
+ mSaIotrapSmiAddress = 0;
+ mInitPcieAspmAfterOprom = 0;
+ SaDataHob = NULL;
+ SaDataHob = (SA_DATA_HOB *)GetFirstGuidHob (&gSaDataHobGuid);
+ if (SaDataHob != NULL) {
+ mSaIotrapSmiAddress = SaDataHob->SaIotrapSmiAddress;
+ mInitPcieAspmAfterOprom = SaDataHob->InitPcieAspmAfterOprom;
+ }
+
+ ///
+ /// If there was no DXE ASPM code, always executes SMM code
+ ///
+#if SA_PCIE_ASPM_IN_DXE == 0
+ mInitPcieAspmAfterOprom = 1;
+#endif
+ ///
+ /// If there was no SMM mode supported, always enable DXE mode
+ ///
+#if SA_PCIE_ASPM_IN_SMM == 0
+ mInitPcieAspmAfterOprom = 0;
+#endif
+
+ ///
+ /// Install System Agent Global NVS protocol
+ ///
+ DEBUG ((EFI_D_INFO, "Install SA GNVS protocol\n"));
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA), &mSaGlobalNvsAreaProtocol.Area);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem ((VOID *) mSaGlobalNvsAreaProtocol.Area, sizeof (SYSTEM_AGENT_GLOBAL_NVS_AREA));
+ mSaGlobalNvsAreaProtocol.Area->SaRcRevision = SA_RC_VERSION;
+ mSaGlobalNvsAreaProtocol.Area->XPcieCfgBaseAddress = (UINT32) (MmPciAddress (0, 0, 0, 0, 0x0));
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gSaGlobalNvsAreaProtocolGuid,
+ &mSaGlobalNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// PciExpress Dxe Initialization
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing PciExpress (Dxe)\n"));
+ PciExpressInit (mDxePlatformSaPolicy);
+
+ ///
+ /// Internal devices and Misc configurations.
+ ///
+ DEBUG ((EFI_D_INFO, "Internal Device and Misc Configurations\n"));
+ DeviceConfigure (mDxePlatformSaPolicy);
+ ProgramSvidSid (mDxePlatformSaPolicy);
+
+ ///
+ /// LegacyRegion Driver
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing Legacy Region\n"));
+ LegacyRegionInstall (ImageHandle);
+
+ ///
+ /// GtPostInit Initialization
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing GT PowerManagement and other GT POST related\n"));
+ GraphicsInit (ImageHandle, mDxePlatformSaPolicy);
+
+ ///
+ /// Audio (dHDA) Initialization
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing CPU Audio (dHDA) device\n"));
+ AudioInit (ImageHandle, mDxePlatformSaPolicy);
+
+ //
+ // @todo remove this VP SKIP and prepare for PO settings to skip this code.
+ //
+ ///
+ /// Vtd Initialization
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing VT-d\n"));
+ VtdInit (mDxePlatformSaPolicy);
+
+ ///
+ /// IgdOpRegion Install Initialization
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing IGD OpRegion\n"));
+ IgdOpRegionInit ();
+
+
+ ///
+ /// Create PCI Enumeration Completed callback for SA
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ EFI_TPL_CALLBACK,
+ SaPciEnumCompleteCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Create ExitPmAuth callback for SA
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ SaExitPmAuthCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Install SA_INFO_PROTOCOL
+ ///
+ SaInstance = AllocateZeroPool (sizeof (SA_INSTANCE_PRIVATE_DATA));
+ if (SaInstance == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SaInstance->SaInfo.Revision = SA_INFO_PROTOCOL_REVISION_1;
+ ///
+ /// RCVersion[31:0] is the release number.
+ /// For example:
+ /// SaFramework 0.6.0.01 should be 00 06 00 01 (0x00060001)
+ /// SaFramework 0.6.2 should be 00 06 02 00 (0x00060200)
+ ///
+ SaInstance->SaInfo.RCVersion = SA_RC_VERSION;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiSaInfoProtocolGuid,
+ &(SaInstance->SaInfo),
+ NULL
+ );
+
+ ///
+ /// Install System Agent Global NVS ACPI table
+ ///
+#ifndef Remove_SaSsdt_Data_To_Dsdt
+ Status = InitializeSaSsdtAcpiTables ();
+#endif //AMI_OVERRIDE
+
+#ifdef SG_SUPPORT
+
+ DEBUG ((EFI_D_INFO, "Initializing Switchable Graphics (Dxe)\n"));
+ SwitchableGraphicsInit (ImageHandle, SystemTable, mDxePlatformSaPolicy);
+
+#endif
+
+ DEBUG ((EFI_D_INFO, "SaInitDxe End\n"));
+
+ return EFI_SUCCESS;
+}
+
+VOID
+DeviceConfigure (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Initialize GT Post Routines.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+{
+ UINT64 MchBar;
+
+ MchBar = McD0PciCfg64 (R_SA_MCHBAR) &~BIT0;
+
+ ///
+ /// Enable/Disable CHAP device (B0,D7,F0).
+ ///
+ if (DxePlatformSaPolicy->MiscConfig->ChapDeviceEnable) {
+ McD0PciCfg32Or (R_SA_DEVEN, B_SA_DEVEN_D7EN_MASK);
+ } else {
+ McD0PciCfg32And (R_SA_DEVEN, ~(B_SA_DEVEN_D7EN_MASK));
+ }
+ ///
+ /// Enable/Disable Thermal device (B0,D4,F0).
+ ///
+ if (DxePlatformSaPolicy->MiscConfig->Device4Enable) {
+ McD0PciCfg32Or (R_SA_DEVEN, B_SA_DEVEN_D4EN_MASK);
+ } else {
+ McD0PciCfg32And (R_SA_DEVEN, ~(B_SA_DEVEN_D4EN_MASK));
+ }
+ ///
+ /// Enable/Disable Audio device (B0,D3,F0).
+ ///
+ if ((DxePlatformSaPolicy->MiscConfig->AudioEnable) && (McD2PciCfg16 (R_SA_IGD_VID) != 0xFFFF)) {
+ McD0PciCfg32Or (R_SA_DEVEN, B_SA_DEVEN_D3EN_MASK);
+ } else {
+ McD0PciCfg32And (R_SA_DEVEN, ~(B_SA_DEVEN_D3EN_MASK));
+ }
+
+ return ;
+}
+
+VOID
+ProgramSvidSid (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Program SA devices Subsystem Vendor Identifier (SVID) and Subsystem Identifier (SID).
+
+ @param[in] DxePlatformSaPolicy The SAPlatform Policy protocol instance
+**/
+{
+ UINT8 Index;
+ UINT8 BusNumber;
+ UINTN PciEAddressBase;
+ UINT8 DeviceNumber;
+ UINT8 FunctionNumber;
+ UINT8 SvidRegOffset;
+ UINT16 Data16;
+ STATIC SA_SVID_SID_INIT_ENTRY SvidSidInitTable[] = {
+ {
+ 0,
+ 0,
+ PCI_SVID_OFFSET
+ },
+ {
+ 1,
+ 0,
+ R_SA_PEG_SS_OFFSET
+ },
+ {
+ 1,
+ 1,
+ R_SA_PEG_SS_OFFSET
+ },
+ {
+ 1,
+ 2,
+ R_SA_PEG_SS_OFFSET
+ },
+ {
+ 2,
+ 0,
+ PCI_SVID_OFFSET
+ },
+ {
+ 3,
+ 0,
+ PCI_SVID_OFFSET
+ },
+ {
+ 4,
+ 0,
+ PCI_SVID_OFFSET
+ },
+ {
+ 7,
+ 0,
+ PCI_SVID_OFFSET
+ }
+ };
+
+ if ((DxePlatformSaPolicy->MiscConfig->DefaultSvidSid->SubSystemVendorId != 0) ||
+ (DxePlatformSaPolicy->MiscConfig->DefaultSvidSid->SubSystemId != 0)
+ ) {
+ for (Index = 0; Index < (sizeof (SvidSidInitTable) / sizeof (SA_SVID_SID_INIT_ENTRY)); Index++) {
+ BusNumber = 0;
+ DeviceNumber = SvidSidInitTable[Index].DeviceNumber;
+ FunctionNumber = SvidSidInitTable[Index].FunctionNumber;
+ SvidRegOffset = SvidSidInitTable[Index].SvidRegOffset;
+ PciEAddressBase = (UINT32) MmPciAddress (0, BusNumber, DeviceNumber, FunctionNumber, 0);
+ ///
+ /// Skip if the device is disabled
+ ///
+ if (MmioRead16 (PciEAddressBase + PCI_VID) == 0xFFFF) {
+ continue;
+ }
+ ///
+ /// Program SA devices Subsystem Vendor Identifier (SVID)
+ ///
+ Data16 = DxePlatformSaPolicy->MiscConfig->DefaultSvidSid->SubSystemVendorId;
+ MmioWrite16 (
+ (UINTN) (PciEAddressBase + SvidRegOffset),
+ Data16
+ );
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PciEAddressBase + SvidRegOffset),
+ 1,
+ (VOID *) (UINTN) (PciEAddressBase + SvidRegOffset)
+ );
+
+ ///
+ /// Program SA devices Subsystem Identifier (SID)
+ ///
+ Data16 = DxePlatformSaPolicy->MiscConfig->DefaultSvidSid->SubSystemId;
+ MmioWrite16 (
+ (UINTN) (PciEAddressBase + SvidRegOffset + 2),
+ Data16
+ );
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PciEAddressBase + SvidRegOffset + 2),
+ 1,
+ (VOID *) (UINTN) (PciEAddressBase + SvidRegOffset + 2)
+ );
+ }
+ }
+
+ return;
+}
+
+VOID
+SaFviExitPmAuth(
+ VOID
+ )
+/**
+ This function populates the SA FVI version numbers
+**/
+{
+ const UINT8 StrEnabled[sizeof (SA_CRID_ENABLED)] = SA_CRID_ENABLED;
+ const UINT8 StrDisabled[sizeof (SA_CRID_DISABLED)] = SA_CRID_DISABLED;
+ const CodeVersion PcieRcVersion = {
+#include "SaPcieVersion.h"
+ };
+ const CodeVersion MemRcVersion = {
+#include "MrcVersion.h"
+ };
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET RegSet;
+ UINT16 VbiosBuildNum;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+
+ if (mDxePlatformSaPolicy->MiscConfig->FviReport) {
+ InitFviDataHubCbContext (
+ mDxePlatformSaPolicy->MiscConfig->FviSmbiosType,
+ (UINT8) mSaFviElements,
+ &mSaFviVersionData
+ );
+ mSaFviElementsData[MEM_RC_VER].Element.Version.MajorVersion = (UINT8) MemRcVersion.Major;
+ mSaFviElementsData[MEM_RC_VER].Element.Version.MinorVersion = (UINT8) MemRcVersion.Minor;
+ mSaFviElementsData[MEM_RC_VER].Element.Version.Revision = (UINT8) MemRcVersion.Rev;
+ mSaFviElementsData[MEM_RC_VER].Element.Version.BuildNum = (UINT16) MemRcVersion.Build;
+ mSaFviElementsData[PCIE_VER].Element.Version.MajorVersion = (UINT8) PcieRcVersion.Major;
+ mSaFviElementsData[PCIE_VER].Element.Version.MinorVersion = (UINT8) PcieRcVersion.Minor;
+ mSaFviElementsData[PCIE_VER].Element.Version.Revision = (UINT8) PcieRcVersion.Rev;
+ mSaFviElementsData[PCIE_VER].Element.Version.BuildNum = (UINT16) PcieRcVersion.Build;
+ mSaFviElementsData[CRID_ORIGINAL].Element.Version.BuildNum = (UINT16) McD0PciCfg8 (PCI_REVISION_ID_OFFSET);
+
+ if (mDxePlatformSaPolicy->MiscConfig->CridEnable == TRUE) {
+ CopyMem (mSaFviElementsData[CRID_STATUS].Element.VerString, StrEnabled, sizeof (StrEnabled));
+ } else {
+ CopyMem (mSaFviElementsData[CRID_STATUS].Element.VerString, StrDisabled, sizeof (StrDisabled));
+ }
+
+ mSaFviElementsData[CRID_NEW].Element.Version.BuildNum = (UINT16) McD0PciCfg8 (PCI_REVISION_ID_OFFSET);
+ //
+ // Check IGFX device
+ //
+ VbiosBuildNum = 0xFFFF;
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (void **) &LegacyBios);
+ if (Status == EFI_SUCCESS) {
+ RegSet.X.AX = 0x5f01;
+ Status = LegacyBios->Int86 (LegacyBios, 0x15, &RegSet);
+ VbiosBuildNum = (((RegSet.X.DX & 0x0F00) << 4) | ((RegSet.X.DX & 0x000F) << 8) | ((RegSet.X.BX & 0x0F00) >> 4) | (RegSet.X.BX & 0x000F));
+ }
+ mSaFviElementsData[VBIOS_VER].Element.Version.BuildNum = VbiosBuildNum;
+
+ CreateRcFviDatahub (&mSaFviVersionData);
+ }
+}
+
+VOID
+EFIAPI
+SaPciEnumCompleteCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/**
+ This function gets registered as a callback to perform SA initialization before ExitPmAuth
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+{
+ 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 (&gEfiPciEnumerationCompleteProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ gBS->CloseEvent (Event);
+
+ Status = PegInitBeforeExitPmAuth ();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((EFI_D_ERROR, "[SA] Pcie initialization before ExitPmAuth Error, Status = %x \n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+VOID
+EFIAPI
+SaExitPmAuthCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/**
+ This function gets registered as a callback to perform SA configuration security lock
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+{
+ 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);
+
+ if (McD2PciCfg16 (R_SA_IGD_VID) != 0xFFFF) {
+ Status = PostPmInitExitPmAuth();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((EFI_D_ERROR, "[SA] ExitPmAuth GraphicsInit Error, Status = %x \n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ UpdateDmarExitPmAuth();
+
+ if (McD2PciCfg16 (R_SA_IGD_VID) != 0xFFFF) {
+ Status = GetVBiosVbtExitPmAuth();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((EFI_D_ERROR, "[SA] ExitPmAuth Op Region Error, Status = %x \n", Status));
+ }
+
+ Status = UpdateIgdOpRegionExitPmAuth();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((EFI_D_ERROR, "[SA] ExitPmAuth Update Op Region Error, Status = %x \n", Status));
+ }
+ }
+
+ SaFviExitPmAuth();
+
+ Status = SaSecurityInit ();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((EFI_D_ERROR, "[SA] Security lock Error, Status = %x \n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ return;
+}
+
+VOID
+SaDxePolicyDump (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy
+ )
+/**
+ This function prints the DXE phase platform policy.
+
+ @param[in] mDxePlatformSaPolicy - SA DxePlatformPolicy protocol
+**/
+{
+#ifdef EFI_DEBUG
+ INTN i;
+
+ DEBUG ((EFI_D_INFO, "\n------------------------ SA Platform Policy (DXE) dump BEGIN -----------------\n"));
+ DEBUG ((EFI_D_INFO, "Revision : %x\n", mDxePlatformSaPolicy->Revision));
+ DEBUG ((EFI_D_INFO, "------------------------ SA_VTD_CONFIGURATION -----------------\n"));
+ DEBUG ((EFI_D_INFO, " VtdEnable : %x\n", mDxePlatformSaPolicy->Vtd->VtdEnable));
+ DEBUG ((EFI_D_INFO, " RmrrUsbBaseAddress : %x\n", mDxePlatformSaPolicy->Vtd->RmrrUsbBaseAddress));
+
+ DEBUG ((EFI_D_INFO, " VtdBaseAddress[%d] :", SA_VTD_ENGINE_NUMBER));
+ for (i = 0; i < SA_VTD_ENGINE_NUMBER; i++) {
+ DEBUG ((EFI_D_INFO, " %x", mDxePlatformSaPolicy->Vtd->BaseAddress[i]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+
+ DEBUG ((EFI_D_INFO, "------------------------ SA_MEMORY_CONFIGURATION -----------------\n"));
+ DEBUG ((EFI_D_INFO, " SpdAddressTable[%d] :", SA_MC_MAX_SOCKETS));
+ for (i = 0; i < SA_MC_MAX_SOCKETS; i++) {
+ DEBUG ((EFI_D_INFO, " %x", mDxePlatformSaPolicy->MemoryConfig->SpdAddressTable[i]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+
+ DEBUG ((EFI_D_INFO, " ChannelASlotMap : %x\n", mDxePlatformSaPolicy->MemoryConfig->ChannelASlotMap));
+ DEBUG ((EFI_D_INFO, " ChannelBSlotMap : %x\n", mDxePlatformSaPolicy->MemoryConfig->ChannelBSlotMap));
+ DEBUG ((EFI_D_INFO, " RmtBdatEnable : %x\n", mDxePlatformSaPolicy->MemoryConfig->RmtBdatEnable));
+ DEBUG ((EFI_D_INFO, " MrcTimeMeasure : %x\n", mDxePlatformSaPolicy->MemoryConfig->MrcTimeMeasure));
+ DEBUG ((EFI_D_INFO, " MrcFastBoot : %x\n", mDxePlatformSaPolicy->MemoryConfig->MrcFastBoot));
+
+ DEBUG ((EFI_D_INFO, "------------------------ SA_PCIE_CONFIGURATION -----------------\n"));
+ DEBUG ((EFI_D_INFO, " DmiAspm : %x\n", mDxePlatformSaPolicy->PcieConfig->DmiAspm));
+
+ DEBUG ((EFI_D_INFO, " PegAspm[%d] :", SA_PEG_MAX_FUN));
+ for (i = 0; i < SA_PEG_MAX_FUN; i++) {
+ DEBUG ((EFI_D_INFO, " %x", mDxePlatformSaPolicy->PcieConfig->PegAspm[i]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+
+ DEBUG ((EFI_D_INFO, " PegAspmL0s[%d] :", SA_PEG_MAX_FUN));
+ for (i = 0; i < SA_PEG_MAX_FUN; i++) {
+ DEBUG ((EFI_D_INFO, " %x", mDxePlatformSaPolicy->PcieConfig->PegAspmL0s[i]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+
+ DEBUG ((EFI_D_INFO, " PegDeEmphasis[%d] :", SA_PEG_MAX_FUN));
+ for (i = 0; i < SA_PEG_MAX_FUN; i++) {
+ DEBUG ((EFI_D_INFO, " %x", mDxePlatformSaPolicy->PcieConfig->PegDeEmphasis[i]));
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+
+ DEBUG ((EFI_D_INFO, " DmiExtSync : %x\n", mDxePlatformSaPolicy->PcieConfig->DmiExtSync));
+ DEBUG ((EFI_D_INFO, " DmiDeEmphasis : %x\n", mDxePlatformSaPolicy->PcieConfig->DmiDeEmphasis));
+ DEBUG ((EFI_D_INFO, " DmiIot : %x\n", mDxePlatformSaPolicy->PcieConfig->DmiIot));
+
+ if (mDxePlatformSaPolicy->Revision >= DXE_SA_PLATFORM_POLICY_PROTOCOL_REVISION_2) {
+ if (mDxePlatformSaPolicy->PcieConfig->PcieAspmDevsOverride != NULL) {
+ DEBUG ((EFI_D_INFO, "------------------------ PCIE_ASPM_DEV_INFO -----------------\n"));
+ DEBUG ((EFI_D_INFO, " VendorId DeviceId RevId RootApmcMask EndpointApmcMask\n"));
+ i = 0;
+ while ((mDxePlatformSaPolicy->PcieConfig->PcieAspmDevsOverride[i].VendorId != SA_PCIE_DEV_END_OF_TABLE) &&
+ (i < MAX_PCIE_ASPM_OVERRIDE)) {
+ DEBUG ((EFI_D_INFO, " %04x %04x %02x %01x %01x\n",
+ mDxePlatformSaPolicy->PcieConfig->PcieAspmDevsOverride[i].VendorId,
+ mDxePlatformSaPolicy->PcieConfig->PcieAspmDevsOverride[i].DeviceId,
+ mDxePlatformSaPolicy->PcieConfig->PcieAspmDevsOverride[i].RevId,
+ mDxePlatformSaPolicy->PcieConfig->PcieAspmDevsOverride[i].RootApmcMask,
+ mDxePlatformSaPolicy->PcieConfig->PcieAspmDevsOverride[i].EndpointApmcMask));
+ i++;
+ }
+ DEBUG ((EFI_D_INFO, "------------------------ END_OF_TABLE -----------------------\n"));
+ }
+ if (mDxePlatformSaPolicy->PcieConfig->PcieLtrDevsOverride != NULL) {
+ DEBUG ((EFI_D_INFO, "------------------------ PCIE_LTR_DEV_INFO -----------------\n"));
+ DEBUG ((EFI_D_INFO, " VendorId DeviceId RevId SnoopLatency NonSnoopLatency\n"));
+ i = 0;
+ while ((mDxePlatformSaPolicy->PcieConfig->PcieLtrDevsOverride[i].VendorId != SA_PCIE_DEV_END_OF_TABLE) &&
+ (i < MAX_PCIE_LTR_OVERRIDE)) {
+ DEBUG ((EFI_D_INFO, " %04x %04x %02x %01x %01x\n",
+ mDxePlatformSaPolicy->PcieConfig->PcieLtrDevsOverride[i].VendorId,
+ mDxePlatformSaPolicy->PcieConfig->PcieLtrDevsOverride[i].DeviceId,
+ mDxePlatformSaPolicy->PcieConfig->PcieLtrDevsOverride[i].RevId,
+ mDxePlatformSaPolicy->PcieConfig->PcieLtrDevsOverride[i].SnoopLatency,
+ mDxePlatformSaPolicy->PcieConfig->PcieLtrDevsOverride[i].NonSnoopLatency));
+ i++;
+ }
+ DEBUG ((EFI_D_INFO, "------------------------ END_OF_TABLE ----------------------\n"));
+ }
+ }
+
+ for (i = 0; i < SA_PEG_MAX_FUN; i++) {
+ DEBUG ((EFI_D_INFO, " PegPwrOpt[%d].LtrEnable : %x\n", i, mDxePlatformSaPolicy->PcieConfig->PegPwrOpt[i].LtrEnable));
+ DEBUG ((EFI_D_INFO, " PegPwrOpt[%d].LtrMaxSnoopLatency : %x\n", i, mDxePlatformSaPolicy->PcieConfig->PegPwrOpt[i].LtrMaxSnoopLatency));
+ DEBUG ((EFI_D_INFO, " PegPwrOpt[%d].ObffEnable : %x\n", i, mDxePlatformSaPolicy->PcieConfig->PegPwrOpt[i].ObffEnable));
+ DEBUG ((EFI_D_INFO, " PegPwrOpt[%d].LtrMaxNoSnoopLatency : %x\n", i, mDxePlatformSaPolicy->PcieConfig->PegPwrOpt[i].LtrMaxNoSnoopLatency));
+ }
+
+ if (mDxePlatformSaPolicy->Revision >= DXE_SA_PLATFORM_POLICY_PROTOCOL_REVISION_3) {
+ DEBUG ((EFI_D_INFO, "------------------------ SA_SG_VBIOS_CONFIGURATION -----------------\n"));
+ DEBUG ((EFI_D_INFO, " LoadVbios : %x\n", mDxePlatformSaPolicy->VbiosConfig->LoadVbios));
+ DEBUG ((EFI_D_INFO, " ExecuteVbios : %x\n", mDxePlatformSaPolicy->VbiosConfig->ExecuteVbios));
+ DEBUG ((EFI_D_INFO, " VbiosSource : %x\n", mDxePlatformSaPolicy->VbiosConfig->VbiosSource));
+ }
+
+
+ DEBUG ((EFI_D_INFO, "------------------------ SA_IGD_CONFIGURATION -----------------\n"));
+ DEBUG ((EFI_D_INFO, " RenderStandby : %x\n", mDxePlatformSaPolicy->IgdConfig->RenderStandby));
+ DEBUG ((EFI_D_INFO, "------------------------ SA_MISC_CONFIGURATION -----------------\n"));
+ DEBUG ((EFI_D_INFO, " ChapDeviceEnable : %x\n", mDxePlatformSaPolicy->MiscConfig->ChapDeviceEnable));
+ DEBUG ((EFI_D_INFO, " Device4Enable : %x\n", mDxePlatformSaPolicy->MiscConfig->Device4Enable));
+ DEBUG ((EFI_D_INFO, " SubSystemVendorId : %x\n", mDxePlatformSaPolicy->MiscConfig->DefaultSvidSid->SubSystemVendorId));
+ DEBUG ((EFI_D_INFO, " SubSystemId : %x\n", mDxePlatformSaPolicy->MiscConfig->DefaultSvidSid->SubSystemId));
+ DEBUG ((EFI_D_INFO, " CridEnable : %x\n", mDxePlatformSaPolicy->MiscConfig->CridEnable));
+ DEBUG ((EFI_D_INFO, " AudioEnable : %x\n", mDxePlatformSaPolicy->MiscConfig->AudioEnable));
+ DEBUG ((EFI_D_INFO, " FviReport : %x\n", mDxePlatformSaPolicy->MiscConfig->FviReport));
+ DEBUG ((EFI_D_INFO, " FviSmbiosType : %x\n", mDxePlatformSaPolicy->MiscConfig->FviSmbiosType));
+ DEBUG ((EFI_D_INFO, "\n------------------------ SA Platform Policy (DXE) dump END -----------------\n"));
+#endif
+ return;
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.dxs b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.dxs
new file mode 100644
index 0000000..03c23ef
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.dxs
@@ -0,0 +1,65 @@
+/** @file
+ @todo ADD DESCRIPTION
+
+@copyright
+ Copyright (c) 1999 - 2012 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 a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+
+**/
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#endif
+
+#include EFI_PROTOCOL_DEPENDENCY (SaPlatformPolicy)
+#include EFI_PROTOCOL_DEPENDENCY (PciRootBridgeIo)
+#include EFI_PROTOCOL_DEPENDENCY (BootScriptSave)
+#include EFI_PROTOCOL_DEPENDENCY (AcpiSupport)
+#include EFI_PROTOCOL_DEPENDENCY (PciHostBridgeResourceAllocation)
+#include EFI_PROTOCOL_DEPENDENCY (CpuIo)
+#include EFI_PROTOCOL_DEPENDENCY (DataHub)
+#include EFI_PROTOCOL_DEPENDENCY (PowerMgmtInitDone)
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+#include EFI_PROTOCOL_DEPENDENCY (HiiDatabase)
+#else
+#include EFI_PROTOCOL_DEPENDENCY (HII)
+#endif
+#include EFI_PROTOCOL_DEPENDENCY (FirmwareVolume)
+
+DEPENDENCY_START
+ EFI_ACPI_SUPPORT_GUID AND
+ EFI_DATA_HUB_PROTOCOL_GUID AND
+ EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID AND
+ EFI_FIRMWARE_VOLUME_PROTOCOL_GUID AND
+ DXE_PLATFORM_SA_POLICY_GUID AND
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID AND
+ EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID AND
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GUID AND
+ EFI_CPU_IO_PROTOCOL_GUID AND
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_HII_DATABASE_PROTOCOL_GUID
+#else
+ EFI_HII_PROTOCOL_GUID
+#endif
+DEPENDENCY_END
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.h
new file mode 100644
index 0000000..a8c2b8f
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.h
@@ -0,0 +1,194 @@
+/** @file
+ Header file for SA Initialization Driver.
+
+@copyright
+ Copyright (c) 1999 - 2012 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
+**/
+#ifndef _SA_INITIALIZATION_DRIVER_H_
+#define _SA_INITIALIZATION_DRIVER_H_
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "EfiScriptLib.h"
+#include "SaBuildFlags.h"
+#include "LegacyRegion.h"
+#include "Vtd.h"
+#include "GraphicsInit.h"
+#include "IgdOpregion.h"
+#include "PciExpressInit.h"
+#include "AudioInit.h"
+#include "RcFviDxeLib.h"
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+#include "PcieComplex.h"
+#include "VTd.h"
+#include "SwitchableGraphicsInit.h"
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include EFI_PROTOCOL_DEFINITION (SaPlatformPolicy)
+#include EFI_PROTOCOL_PRODUCER (SaInfo)
+#endif
+///
+/// Data definitions
+///
+#define CRID_DATA 0x69
+#define CRID_LOCK 0x17
+
+typedef struct {
+ UINT64 BaseAddr;
+ UINT32 Offset;
+ UINT32 AndMask;
+ UINT32 OrMask;
+} BOOT_SCRIPT_REGISTER_SETTING;
+
+typedef struct {
+ UINT64 Address;
+ EFI_BOOT_SCRIPT_WIDTH Width;
+ UINT32 Value;
+} BOOT_SCRIPT_PCI_REGISTER_SAVE;
+
+typedef struct {
+ EFI_SA_INFO_PROTOCOL SaInfo;
+} SA_INSTANCE_PRIVATE_DATA;
+
+typedef struct {
+ UINT8 DeviceNumber;
+ UINT8 FunctionNumber;
+ UINT8 SvidRegOffset;
+} SA_SVID_SID_INIT_ENTRY;
+
+#define SA_FVI_STRING "Reference Code - SA - System Agent"
+#define SA_FVI_SMBIOS_TYPE 0xDD ///< Default value
+#define SA_FVI_SMBIOS_INSTANCE 0x06
+#define MEM_FVI_STRING "Reference Code - MRC"
+#define MEM_RC_VERSION \
+ { \
+ 0xFF, 0xFF, 0xFF, 0xFFFF \
+ }
+#define PCIE_FVI_STRING "SA - PCIe Version"
+#define PCIE_RC_VERSION \
+ { \
+ 0xFF, 0xFF, 0xFF, 0xFFFF \
+ }
+#define SA_CRID_STATUS "SA-CRID Status"
+#define SA_CRID_ORIGINAL_VALUE "SA-CRID Original Value"
+#define SA_CRID_NEW_VALUE "SA-CRID New Value"
+#define SA_CRID_ENABLED "Enabled "
+#define SA_CRID_DISABLED "Disabled"
+#define SA_CRID_VERSION \
+ { \
+ 0xFF, 0xFF, 0xFF, 0xFFFF \
+ }
+#define VBIOS_FVI_STRING "OPROM - VBIOS"
+#define VBIOS_RC_VERSION \
+ { \
+ 0xFF, 0xFF, 0xFF, 0xFFFF \
+ }
+
+enum {
+ SA_RC_VER = 0,
+ MEM_RC_VER,
+ PCIE_VER,
+ CRID_STATUS,
+ CRID_ORIGINAL,
+ CRID_NEW,
+ VBIOS_VER
+} SA_FVI_INDEX;
+
+extern FVI_ELEMENT_AND_FUNCTION mSaFviElementsData[];
+extern FVI_DATA_HUB_CALLBACK_CONTEXT mSaFviVersionData;
+extern UINTN mSaFviElements;
+
+///
+/// Function Prototype
+///
+VOID
+EFIAPI
+SaPciEnumCompleteCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/**
+ This function gets registered as a callback to perform SA initialization before ExitPmAuth
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+
+ @retval EFI_SUCCESS - Always.
+
+ **/
+;
+
+VOID
+EFIAPI
+SaExitPmAuthCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/**
+ This function gets registered as a callback to perform SA configuration security lock
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+
+ @retval EFI_SUCCESS - Always.
+
+ **/
+;
+
+VOID
+DeviceConfigure (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ This function performs SA internal devices enabling/disabling
+
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ **/
+;
+
+VOID
+ProgramSvidSid (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Program SA devices Subsystem Vendor Identifier (SVID) and Subsystem Identifier (SID).
+
+ @param[in] DxePlatformSaPolicy The SAPlatform Policy protocol instance
+**/
+;
+
+VOID
+SaDxePolicyDump (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy
+ )
+/**
+ This function prints the DXE phase platform policy.
+
+ @param[in] mDxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ **/
+;
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.inf b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.inf
new file mode 100644
index 0000000..638f6da
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInit.inf
@@ -0,0 +1,137 @@
+## @file
+# Component description file for SystemAgent Initialization driver
+#
+#@copyright
+# Copyright (c) 1999 - 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 a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+##
+
+[defines]
+BASE_NAME = SaInit
+FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE811
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ SaInit.h
+ SaInit.c
+ LegacyRegion.h
+ LegacyRegion.c
+ Vtd.c
+ Vtd.h
+ IgdOpRegion.h
+ IgdOpRegion.c
+ GraphicsInit.h
+ GraphicsInit.c
+ PciExpressInit.h
+ PciExpressInit.c
+ PcieComplex.c
+ PcieComplex.h
+ AudioInit.c
+ AudioInit.h
+ SaFvi.c
+ SwitchableGraphicsInit.c
+ SwitchableGraphicsInit.h
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ .
+ ../Common
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Library
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/core/Dxe
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/pcd
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EDK_SOURCE)/Foundation/Library/Dxe/UefiEfiIfrSupportLib
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Protocol
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/$(PROJECT_SA_MRC)/Pei/Source/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Library/SaPcieLib/Common
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Protocol
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/../MdePkg/Include
+
+#
+# Typically, the sample code referenced will be available in the code base already.
+# So, keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/SampleCode
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/SampleCode/Include
+
+[libraries.common]
+ EfiProtocolLib
+ EdkGuidLib
+ EfiCommonLib
+ EfiScriptLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueBasePciExpressLib
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGlueDxeHobLib
+ EdkIIGlueUefiLib
+ EdkIIGlueBasePciLibPciExpress
+ $(PROJECT_SA_FAMILY)ProtocolLib
+ $(PROJECT_PCH_FAMILY)ProtocolLib
+ RcFviDxeLib
+ PchPlatformLib
+ UefiEfiIfrSupportLib
+ SaGuidLib
+ EdkProtocolLib
+ CpuPlatformLib
+#
+# Comment out SaPcieDxeLib if ASPM initialization in DXE phase was not supported
+#
+ SaPcieDxeLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = SaInit.dxs
+
+ C_FLAGS = $(C_FLAGS) -D"__EDKII_GLUE_MODULE_ENTRY_POINT__=SaInitEntryPoint" \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__\
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_HOB_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ -D __EDKII_GLUE_UEFI_LIB__
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.cif b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.cif
new file mode 100644
index 0000000..f705e96
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.cif
@@ -0,0 +1,30 @@
+<component>
+ name = "SaInitDxe"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\SystemAgent\SaInit\Dxe"
+ RefName = "SaInitDxe"
+[files]
+"SaInitDxe.sdl"
+"SaInitDxe.mak"
+"SaInit.c"
+"SaInit.dxs"
+"SaInit.h"
+"SaInit.inf"
+"graphicsinit.c"
+"graphicsinit.h"
+"igdopregion.c"
+"igdopregion.h"
+"LegacyRegion.c"
+"LegacyRegion.h"
+"PcieComplex.c"
+"PcieComplex.h"
+"PciExpressInit.c"
+"PciExpressInit.h"
+"VTd.c"
+"VTd.h"
+"AudioInit.c"
+"AudioInit.h"
+"SaFvi.c"
+"SwitchableGraphicsInit.c"
+"SwitchableGraphicsInit.h"
+<endComponent>
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.mak b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.mak
new file mode 100644
index 0000000..809ba05
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.mak
@@ -0,0 +1,86 @@
+#---------------------------------------------------------------------------
+# Create SaInitDxe Driver
+#---------------------------------------------------------------------------
+EDK : SaInitDxe
+
+SaInitDxe: $(BUILD_DIR)\SaInitDxe.mak SaInitDxeBin
+
+$(BUILD_DIR)\SaInitDxe.mak : $(SaInitDxe_DIR)\$(@B).cif $(SaInitDxe_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SaInitDxe_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+SaInitDxe_INCLUDES=\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(INTEL_MCH_INCLUDES) \
+ $(INTEL_PCH_INCLUDES)\
+ $(IndustryStandard_INCLUDES)\
+ $(INTEL_PLATFORM_PROTOCOL_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ /I$(INTEL_SYSTEM_AGENT_DIR)\Library\SaPcieLib\Common\
+ /I$(INTEL_SYSTEM_AGENT_DIR)\SampleCode\
+
+SaInitDxe_DEFINES =$(MY_DEFINES)\
+ /D "__EDKII_GLUE_MODULE_ENTRY_POINT__=SaInitEntryPoint" \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__\
+ /D __EDKII_GLUE_DXE_HOB_LIB__ \
+ /D __EDKII_GLUE_UEFI_LIB__\
+ /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+
+SaInitDxe_LIB_LINKS =\
+ $(EFIPROTOCOLLIB)\
+ $(EDKGUIDLIB)\
+ $(EFICOMMONLIB)\
+ $(EFISCRIPTLIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EdkIIGlueDxeHobLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(INTEL_SA_PROTOCOL_LIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)\
+ $(IntelPlatformProtocolLib_LIB)\
+!IF $(EFI_SPECIFICATION_VERSION) >= 0x0002000A
+ $(UEFIEFIIFRSUPPORTLIB)\
+!ELSE
+ $(EFIIFRSUPPORTLIB) \
+!ENDIF
+ $(SaGuidLib_LIB)\
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EDKPROTOCOLLIB)\
+ $(RcFviDxeLib_LIB)\
+ $(PchPlatformDxeLib_LIB)\
+ $(CpuPlatformLib_LIB)\
+#
+# Comment out SaPcieDxeLib if ASPM initialization in DXE phase was not supported
+#
+ $(SaPcieDxeLib_LIB)\
+
+SaInitDxeBin: $(SaInitDxe_LIB_LINKS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\SaInitDxe.mak all \
+ "MY_INCLUDES=$(SaInitDxe_INCLUDES)"\
+ "MY_DEFINES=$(SaInitDxe_DEFINES)"\
+ GUID=DE23ACEE-CF55-4fb6-AA77-984AB53DE811\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=BS_DRIVER\
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(SaInitDxe_DIR)\SaInit.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ COMPRESS=1
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.sdl b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.sdl
new file mode 100644
index 0000000..e4a95b4
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SaInitDxe.sdl
@@ -0,0 +1,24 @@
+TOKEN
+ Name = "SaInitDxe_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable SaInitDxe support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "SaInitDxe_DIR"
+End
+
+MODULE
+ File = "SaInitDxe.mak"
+ Help = "Includes SaInitDxe.mak to Project"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SaInitDxe.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End \ No newline at end of file
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);
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.h
new file mode 100644
index 0000000..4d32f8f
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/SwitchableGraphicsInit.h
@@ -0,0 +1,267 @@
+/** @file
+ Header file for the SwitchableGraphics Dxe driver.
+ This driver loads SwitchableGraphics ACPI tables.
+
+@copyright
+ Copyright (c) 2010 - 2012 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
+
+**/
+
+#ifndef _SWITCHABLE_GRAPHICS_DXE_H_
+#define _SWITCHABLE_GRAPHICS_DXE_H_
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "EfiScriptLib.h"
+#endif
+
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+
+#include "PchAccess.h"
+#include "Acpi3_0.h"
+#include "SaAccess.h"
+
+#include EFI_PROTOCOL_DEPENDENCY (PciIo)
+#include EFI_PROTOCOL_DEPENDENCY (AcpiTable)
+#include EFI_PROTOCOL_DEPENDENCY (FirmwareVolume)
+#include EFI_PROTOCOL_DEPENDENCY (SaGlobalNvsArea)
+#include EFI_GUID_DEFINITION (SaDataHob)
+#include EFI_PROTOCOL_DEFINITION (SaPlatformPolicy)
+
+///
+/// SG ACPI table data storage file
+///
+#include EFI_GUID_DEFINITION (SgAcpiTableStorage)
+
+///
+/// Switchable Graphics defines.
+///
+#define CONVENTIONAL_MEMORY_TOP 0xA0000 ///< 640 KB
+#define BIN_FILE_SIZE_MAX 0x10000
+
+#define OPTION_ROM_SIGNATURE 0xAA55
+
+#define MemoryRead16(Address) * (UINT16 *) (Address)
+#define MemoryRead8(Address) * (UINT8 *) (Address)
+
+///
+/// PEG Capability Equates
+///
+#define PEG_CAP_ID 0x10
+#define PEG_CAP_VER 0x2
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Signature; ///< 0xAA55
+ UINT8 Reserved[22];
+ UINT16 PcirOffset;
+} VBIOS_OPTION_ROM_HEADER;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct {
+ UINT32 Signature; ///< "PCIR"
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 Reserved0;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 Reserved1;
+} VBIOS_PCIR_STRUCTURE;
+#pragma pack()
+
+/**
+ Initialize the SwitchableGraphics support.
+
+ @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
+**/
+EFI_STATUS
+SwitchableGraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+;
+
+/**
+ Load and execute the dGPU VBIOS.
+
+ @param[in] VbiosData - Pointer to VbiosData 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
+ )
+;
+
+/**
+ Initialize the runtime SwitchableGraphics support data for ACPI tables in GlobalNvs.
+ @param[in] SgInfoDataHob - Pointer to Hob for SG system details.
+ @param[in] DxePlatformSgPolicy - 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Rreporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+ @param[in] Function - Pci Function Number
+ @param[in] CapId - Extended CAPID to search for
+
+ @retval 0 - CAPID not found
+ @retval Other - CAPID found, Offset of desired CAPID
+**/
+UINT32
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+;
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus - Pci Bus Number
+ @param[in] Device - Pci Device Number
+ @param[in] Function - Pci Function Number
+ @param[in] CapId - CAPID to search for
+
+ @retval 0 - CAPID not found
+ @retval Other - CAPID found, Offset of desired CAPID
+**/
+UINT32
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ 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
+ )
+;
+
+/**
+ Load Intel SG SSDT Tables
+
+ @param[in] None
+
+ @retval EFI_SUCCESS - SG SSDT Table load successful.
+**/
+EFI_STATUS
+LoadAcpiTables (
+ VOID
+ )
+;
+
+
+VOID
+EFIAPI
+SgExitPmAuthCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.c
new file mode 100644
index 0000000..1dea621
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.c
@@ -0,0 +1,934 @@
+/** @file
+ This code provides a initialization of intel VT-d (Virtualization Technology for Directed I/O).
+
+@copyright
+ Copyright (c) 1999 - 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
+
+@todo assumption is ANDD table will use device path to be loaded dynamically, need to use pchplatformpolicy if assumption is incorrect.
+**/
+#include "SaInit.h"
+#include "VTd.h"
+
+UINT32 mPchRootComplexBar;
+DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy;
+DXE_PCH_PLATFORM_POLICY_PROTOCOL *mDxePlatformPchPolicy;
+PCH_SERIES mPchSeries;
+
+/**
+For device that specified by Device Num and Function Num,
+mDevEnMap is used to check device presence.
+ 0x80 means use Device ID to detemine presence
+
+ The structure is used to check if device scope is valid when update DMAR table
+**/
+UINT16 mDevEnMap[][2] = {
+ {
+ 0x0200,
+ 0x80
+ }, ///< D2F0
+ {
+ 0x1D00,
+ 0x80
+ }, ///< D29F0
+ {
+ 0x1A00,
+ 0x80
+ }, ///< D26F0
+ {
+ 0x1400,
+ 0x80
+ } ///< D20F0
+};
+
+BOOLEAN mInterruptRemappingSupport;
+
+UINT16
+GetFunDisableBit (
+ UINT8 DevNum,
+ UINT8 FunNum
+ )
+/**
+ Get the corresponding device Enable/Disable bit according DevNum and FunNum
+
+ @param[in] DevNum - Device Number
+ @param[in] FunNum - Function Number
+
+ @retval If the device is found, return disable/Enable bit in FD/Deven reigster
+ @retval If not found return 0xFF
+**/
+{
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof (mDevEnMap) / 4; Index++) {
+ if (mDevEnMap[Index][0] == ((DevNum << 0x08) | FunNum)) {
+ return mDevEnMap[Index][1];
+ }
+ }
+
+ return 0xFF;
+}
+
+VOID
+UpdateDRHD (
+ IN OUT VOID *DrhdEnginePtr
+ )
+/**
+ Update the DRHD structure
+
+ @param[in, out] DrhdEnginePtr - A pointer to DRHD structure
+**/
+{
+ UINT16 Length;
+ UINT16 DisableBit;
+ UINTN DeviceScopeNum;
+ BOOLEAN NeedRemove;
+ EFI_ACPI_DRHD_ENGINE1_STRUCT *DrhdEngine;
+
+ //
+ // Convert DrhdEnginePtr to EFI_ACPI_DRHD_ENGINE1_STRUCT Pointer
+ //
+ DrhdEngine = (EFI_ACPI_DRHD_ENGINE1_STRUCT *) DrhdEnginePtr;
+
+ Length = DrhdEngine->Length;
+ DeviceScopeNum = (DrhdEngine->Length - EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ DisableBit = GetFunDisableBit (
+ DrhdEngine->DeviceScope[0].PciPath[0],
+ DrhdEngine->DeviceScope[0].PciPath[1]
+ );
+ NeedRemove = FALSE;
+ if ((DisableBit == 0xFF) ||
+ (DrhdEngine->RegisterBaseAddress == 0) ||
+ ((DisableBit == 0x80) &&
+ (MmPci32 (0, 0, DrhdEngine->DeviceScope[0].PciPath[0], DrhdEngine->DeviceScope[0].PciPath[1], 0x00) == 0xFFFFFFFF))
+ ){
+ NeedRemove = TRUE;
+ }
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ }
+ ///
+ /// If no devicescope is left, we set the structure length as 0x00
+ ///
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->Flags == 0x01)) {
+ DrhdEngine->Length = Length;
+ } else {
+ DrhdEngine->Length = 0;
+ }
+}
+
+UINT8
+GetIoApicID (
+ VOID
+ )
+/**
+ Get IOAPIC ID from LPC
+
+ @retval APIC ID
+**/
+{
+ UINT8 VOLATILE *IoapicIndex;
+ UINT32 VOLATILE *IoapicData;
+ UINT32 Data32;
+
+ ///
+ /// Get IOAPIC base
+ ///
+ IoapicIndex = (UINT8 *) (UINTN) (R_PCH_IO_APIC_INDEX + ((PchMmRcrb16 (R_PCH_RCRB_OIC) & 0x0ff) << 12));
+ IoapicData = (UINT32 *) (UINTN) (R_PCH_IO_APIC_DATA + ((PchMmRcrb16 (R_PCH_RCRB_OIC) & 0x0ff) << 12));
+
+ ///
+ /// Get APIC ID from Identification Register (Index 0)
+ ///
+ *IoapicIndex = 0;
+ Data32 = (*IoapicData & 0x0F000000) >> 24;
+
+ return (UINT8) Data32;
+}
+
+VOID
+UpdateDRHD2 (
+ IN OUT VOID *DrhdEnginePtr
+ )
+/**
+ Update the second DRHD structure
+
+ @param[in, out] DrhdEnginePtr - A pointer to DRHD structure
+**/
+{
+ UINT16 Length;
+ UINTN DeviceScopeNum;
+ UINTN ValidDeviceScopeNum;
+ UINT16 Data16;
+ UINT16 HpetReg;
+ UINT16 Index;
+ UINT8 Bus;
+ UINT8 Path[2] = { 0, 0 };
+ BOOLEAN NeedRemove;
+ EFI_ACPI_DRHD_ENGINE2_STRUCT *DrhdEngine;
+
+ ///
+ /// Convert DrhdEnginePtr to EFI_ACPI_DRHD_ENGINE2_STRUCT Pointer
+ ///
+ DrhdEngine = (EFI_ACPI_DRHD_ENGINE2_STRUCT *) DrhdEnginePtr;
+
+ Length = DrhdEngine->Length;
+ DeviceScopeNum = (DrhdEngine->Length - EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ Data16 = 0;
+ Bus = 0;
+ HpetReg = R_PCH_LPC_HPET0;
+ ValidDeviceScopeNum = 0;
+
+ for (Index = 0; Index < DeviceScopeNum; Index++) {
+ NeedRemove = FALSE;
+ /**
+ For HPET and APIC, update device scope if Interrupt remapping is supported. remove device scope
+ if interrupt remapping is not supported.
+ - Index = 0 - IOAPIC
+ - Index = 1 - HPET
+ For Serial IO devices, they do not appear in PCI space, use platform policy to determine existence, also remove if PCH not LP
+ - Index = 2 - I2C0
+ - Index = 3 - I2C1
+ - Index = 4 - SPI0
+ - Index = 5 - SPI1
+ - Index = 6 - UART0
+ - Index = 7 - UART1
+ - Index = 8 - SDIO
+ **/
+ if (mInterruptRemappingSupport) {
+ if (Index == 0) {
+ ///
+ /// Update source id for IoApic's device scope entry
+ ///
+ Data16 = PchLpcPciCfg16 (R_PCH_LPC_IOXAPIC);
+ Bus = (UINT8) (Data16 >> 8);
+ if (Bus != 0x00) {
+ Path[0] = (UINT8) ((Data16 & 0xff) >> 3);
+ Path[1] = (UINT8) (Data16 & 0x7);
+ } else {
+ //
+ // BUGBUG: Here we just hardcode, because in this version, R_PCH_LPC_IOXAPIC is initialized AFTER Vtd run. We can NOT get proper setting from PCH
+ // We can NOT get proper setting from PCH
+ /// @todo check if code still needed
+ //
+ DEBUG ((EFI_D_WARN, "BUGBUG: UpdateApicHpet use hardcode value - To be fixed!\n"));
+ Bus = 0xF0;
+ Path[0] = 0x1F;
+ Path[1] = 0x0;
+ }
+ DrhdEngine->DeviceScope[Index].StartBusNumber = Bus;
+ //
+ // Update APIC ID
+ //
+ DrhdEngine->DeviceScope[Index].EnumId = GetIoApicID ();
+ }
+ if (Index == 1) {
+ ///
+ /// Update source id for HPET's device scope entry
+ ///
+ Data16 = PchLpcPciCfg16 (HpetReg);
+ Bus = (UINT8) (Data16 >> 8);
+ Path[0] = (UINT8) ((Data16 & 0xFF) >> 3);
+ Path[1] = (UINT8) (Data16 & 0x7);
+ DrhdEngine->DeviceScope[Index].StartBusNumber = Bus;
+ }
+ } else {
+ if ((Index == 0) || (Index == 1)) {
+ NeedRemove = TRUE;
+ }
+ }
+ /*
+ Pch removed device from PCI space and it is visible by ACPI only, we use platform policy to check
+ if device is present. If Pch is 2 chip, remove all serialio devices.
+ */
+#ifdef SERIAL_IO_FLAG
+ if (mPchSeries == PchLp){
+ if (Index == 2){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoI2c0 == 0){
+ NeedRemove = TRUE;
+ }
+ }
+ if (Index == 3){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoI2c1 == 0){
+ NeedRemove = TRUE;
+ }
+ }
+ if (Index == 4){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoSpi0 == 0){
+ NeedRemove = TRUE;
+ }
+ }
+ if (Index == 5){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoSpi1 == 0){
+ NeedRemove = TRUE;
+ }
+ }
+ if (Index == 6){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoUart0 == 0){
+ NeedRemove = TRUE;
+ }
+ }
+ if (Index == 7){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoUart1 == 0){
+ NeedRemove = TRUE;
+ }
+ }
+ if (Index == 8){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoSdio == 0){
+ NeedRemove = TRUE;
+ }
+ }
+ } else {
+#endif
+ if ((Index >= 2) && (Index <= 8)){
+ NeedRemove = TRUE;
+ }
+#ifdef SERIAL_IO_FLAG
+ }
+#endif
+ CopyMem (
+ &DrhdEngine->DeviceScope[ValidDeviceScopeNum],
+ &DrhdEngine->DeviceScope[Index],
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE)
+ );
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ } else {
+ ValidDeviceScopeNum++;
+ }
+ }
+ ///
+ /// If no devicescope is left, we set the structure length as 0x00
+ ///
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->Flags == 0x01)) {
+ DrhdEngine->Length = Length;
+ } else {
+ DrhdEngine->Length = 0;
+ }
+}
+
+VOID
+UpdateRMRR (
+ IN OUT VOID *RmrrPtr
+ )
+/**
+ Update the RMRR structure
+
+ @param[in, out] RmrrPtr - A pointer to RMRR structure
+**/
+{
+ UINT16 Length;
+ UINT16 DisableBit;
+ UINTN DeviceScopeNum;
+ UINTN ValidDeviceScopeNum;
+ UINTN Index;
+ BOOLEAN NeedRemove;
+ EFI_ACPI_RMRR_USB_STRUC *Rmrr;
+
+ ///
+ /// To make sure all devicescope can be checked,
+ /// we convert the RmrrPtr to EFI_ACPI_RMRR_USB_STRUC pointer
+ ///
+ Rmrr = (EFI_ACPI_RMRR_USB_STRUC *) RmrrPtr;
+ Length = Rmrr->Length;
+ ValidDeviceScopeNum = 0;
+ DeviceScopeNum = (Rmrr->Length - EFI_ACPI_RMRR_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ for (Index = 0; Index < DeviceScopeNum; Index++) {
+ ///
+ /// here we assume Device will exist on PCH if Device Number is greater than 0x0F
+ ///
+ DisableBit = GetFunDisableBit (
+ Rmrr->DeviceScope[Index].PciPath[0],
+ Rmrr->DeviceScope[Index].PciPath[1]
+ );
+ NeedRemove = FALSE;
+ if ((DisableBit == 0xFF) ||
+ ((DisableBit == 0x80) &&
+ (MmPci32 (0, 0, Rmrr->DeviceScope[Index].PciPath[0], Rmrr->DeviceScope[Index].PciPath[1], 0x00) == 0xFFFFFFFF))
+ ){
+ NeedRemove = TRUE;
+ }
+ CopyMem (
+ &Rmrr->DeviceScope[ValidDeviceScopeNum],
+ &Rmrr->DeviceScope[Index],
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE)
+ );
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ } else {
+ ValidDeviceScopeNum++;
+ }
+ }
+ ///
+ /// If No deviceScope is left, set length as 0x00
+ ///
+ if (Length > EFI_ACPI_RMRR_HEADER_LENGTH) {
+ Rmrr->Length = Length;
+ } else {
+ Rmrr->Length = 0;
+ }
+}
+
+VOID
+DmarTableUpdate (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+/**
+ Update the DMAR table
+
+ @param[in, out] TableHeader - The table to be set
+ @param[in, out] Version - Version to publish
+**/
+{
+ EFI_ACPI_DMAR_TABLE *DmarTable;
+ EFI_ACPI_DMAR_TABLE TempDmarTable;
+ UINTN Offset;
+ UINTN StructureLen;
+ UINT16 IgdMode;
+ UINT16 GttMode;
+ UINT32 IgdMemSize;
+ UINT32 GttMemSize;
+
+ IgdMemSize = 0;
+ GttMemSize = 0;
+ DmarTable = (EFI_ACPI_DMAR_TABLE *) TableHeader;
+
+ if (mInterruptRemappingSupport) {
+ DmarTable->Flags |= BIT0; ///< Set INTR_REMAP bit (BIT 0) if interrupt remapping is supported
+ }
+ ///
+ /// Find IGD memsize
+ ///
+ IgdMode = (McD0PciCfg16 (R_SA_GGC) & B_SA_GGC_GMS_MASK) >> 3;
+ if (IgdMode <= V_SA_GGC_GMS_512MB) {
+ IgdMemSize = IgdMode * 32 * (1024) * (1024);
+ } else {
+ IgdMemSize = 0;
+ }
+ ///
+ /// Find GTT mem size
+ ///
+ GttMode = (McD0PciCfg16 (R_SA_GGC) & B_SA_GGC_GGMS_MASK) >> 8;
+ if (GttMode <= V_SA_GGC_GGMS_2MB) {
+ GttMemSize = GttMode * (1024) * (1024);
+ } else {
+ GttMemSize = 0;
+ }
+
+ DmarTable->RmrrIgd.RmrBaseAddress = (McD0PciCfg32 (R_SA_TOLUD) &~(0x01)) - IgdMemSize - GttMemSize;
+ DmarTable->RmrrIgd.RmrLimitAddress = DmarTable->RmrrIgd.RmrBaseAddress + IgdMemSize + GttMemSize - 1;
+ DEBUG ((EFI_D_INFO, "RMRR Base address IGD %016lX\n", DmarTable->RmrrIgd.RmrBaseAddress));
+ DEBUG ((EFI_D_INFO, "RMRR Limit address IGD %016lX\n", DmarTable->RmrrIgd.RmrLimitAddress));
+
+ DmarTable->RmrrUsb.RmrBaseAddress = mDxePlatformSaPolicy->Vtd->RmrrUsbBaseAddress[0];
+ DmarTable->RmrrUsb.RmrLimitAddress = mDxePlatformSaPolicy->Vtd->RmrrUsbBaseAddress[1];
+
+ ///
+ /// Convert to 4KB alignment.
+ ///
+ DmarTable->RmrrUsb.RmrBaseAddress &= ~0xFFF;
+ DmarTable->RmrrUsb.RmrLimitAddress &= ~0xFFF;
+ DmarTable->RmrrUsb.RmrLimitAddress += 0x1000 - 1;
+
+ DEBUG ((EFI_D_INFO, "RMRR Base address USB %016lX\n", DmarTable->RmrrUsb.RmrBaseAddress));
+ DEBUG ((EFI_D_INFO, "RMRR Limit address USB %016lX\n", DmarTable->RmrrUsb.RmrLimitAddress));
+
+ ///
+ /// @todo check if this check is still needed.
+ ///
+ if (DmarTable->RmrrUsb.RmrBaseAddress == 0) {
+ DEBUG ((EFI_D_WARN, "BUGBUG: RmrrUsb.RmrBaseAddress is 0 - To be fixed\n"));
+ }
+ ///
+ /// Update DRHD structures of DmarTable
+ ///
+ DmarTable->DrhdEngine1.RegisterBaseAddress = (McMmio32 (R_SA_MCHBAR_VTD1_OFFSET) &~1);
+ DmarTable->DrhdEngine2.RegisterBaseAddress = (McMmio32 (R_SA_MCHBAR_VTD2_OFFSET) &~1);
+
+ DEBUG ((EFI_D_INFO, "VTD base address1 %x\n", DmarTable->DrhdEngine1.RegisterBaseAddress));
+ DEBUG ((EFI_D_INFO, "VTD base address2 %x\n", DmarTable->DrhdEngine2.RegisterBaseAddress));
+ ///
+ /// copy DmarTable to TempDmarTable to be processed
+ ///
+ CopyMem (&TempDmarTable, DmarTable, sizeof (EFI_ACPI_DMAR_TABLE));
+
+ ///
+ /// Update DRHD structures of temp DMAR table
+ ///
+ UpdateDRHD (&TempDmarTable.DrhdEngine1);
+ UpdateDRHD2 (&TempDmarTable.DrhdEngine2);
+
+ ///
+ /// Update RMRR structures of temp DMAR table
+ ///
+ UpdateRMRR ((VOID *) &TempDmarTable.RmrrUsb);
+ UpdateRMRR ((VOID *) &TempDmarTable.RmrrIgd);
+
+ ///
+ /// Remove unused device scope or entire DRHD structures
+ ///
+ Offset = (UINTN) (&TempDmarTable.DrhdEngine1);
+ if (TempDmarTable.DrhdEngine1.Length != 0) {
+ Offset += TempDmarTable.DrhdEngine1.Length;
+ }
+ if (TempDmarTable.DrhdEngine2.Length != 0) {
+ StructureLen = TempDmarTable.DrhdEngine2.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.DrhdEngine2, TempDmarTable.DrhdEngine2.Length);
+ Offset += StructureLen;
+ }
+ ///
+ /// Remove unused device scope or entire RMRR structures
+ ///
+ if (TempDmarTable.RmrrUsb.Length != 0) {
+ StructureLen = TempDmarTable.RmrrUsb.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.RmrrUsb, TempDmarTable.RmrrUsb.Length);
+ Offset += StructureLen;
+ }
+ if (TempDmarTable.RmrrIgd.Length != 0) {
+ StructureLen = TempDmarTable.RmrrIgd.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.RmrrIgd, TempDmarTable.RmrrIgd.Length);
+ Offset += StructureLen;
+ }
+#ifdef SERIAL_IO_FLAG
+ ///
+ /// Include necessary ANDD structures. If not PchLp, remove all ANDD.
+ ///
+ if (mPchSeries == PchLp){
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoI2c0 != 0) {
+ StructureLen = TempDmarTable.AnddI2C0.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C0, TempDmarTable.AnddI2C0.Length);
+ Offset += StructureLen;
+ }
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoI2c1 != 0) {
+ StructureLen = TempDmarTable.AnddI2C1.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddI2C1, TempDmarTable.AnddI2C1.Length);
+ Offset += StructureLen;
+ }
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoSpi0 != 0) {
+ StructureLen = TempDmarTable.AnddSpi0.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddSpi0, TempDmarTable.AnddSpi0.Length);
+ Offset += StructureLen;
+ }
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoSpi1 != 0) {
+ StructureLen = TempDmarTable.AnddSpi1.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddSpi1, TempDmarTable.AnddSpi1.Length);
+ Offset += StructureLen;
+ }
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoUart0 != 0) {
+ StructureLen = TempDmarTable.AnddUa00.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddUa00, TempDmarTable.AnddUa00.Length);
+ Offset += StructureLen;
+ }
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoUart1 != 0) {
+ StructureLen = TempDmarTable.AnddUa01.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddUa01, TempDmarTable.AnddUa01.Length);
+ Offset += StructureLen;
+ }
+ if (mDxePlatformPchPolicy->DeviceEnabling->SerialIoSdio != 0) {
+ StructureLen = TempDmarTable.AnddSdhc.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.AnddSdhc, TempDmarTable.AnddSdhc.Length);
+ Offset += StructureLen;
+ }
+ }
+#endif
+ Offset = Offset - (UINTN) &TempDmarTable;
+ TempDmarTable.Header.Checksum = (UINT8) (TempDmarTable.Header.Checksum + TempDmarTable.Header.Length - Offset);
+ TempDmarTable.Header.Length = (UINT32) Offset;
+ ///
+ /// Replace DMAR table with rebuilt table TempDmarTable
+ ///
+ CopyMem ((VOID *) DmarTable, (VOID *) &TempDmarTable, TempDmarTable.Header.Length);
+}
+
+EFI_STATUS
+WaForVc0RemappingEngine (
+ UINT64 MchBar
+ )
+/**
+ Workaround for VC0 remapping engine
+
+ @param[in] MchBar - MCHBAR address
+
+ @retval EFI_SUCCESS - successed.
+**/
+{
+ UINT16 DeviceId;
+ UINT32 Vc0RemapEngineBase;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ DeviceId = PchLpcPciCfg16(R_PCH_LPC_DEVICE_ID);
+ Vc0RemapEngineBase = Mmio32(MchBar, R_SA_MCHBAR_VTD2_OFFSET) & 0xFFFFFFFE;
+
+ ///
+ /// Disable VTD SuperPage policy when iGfx is enabled
+ ///
+ if (McD2PciCfg16(R_SA_IGD_VID) != 0xFFFF) {
+ Data32And = (UINT32)~(BIT25);
+ Data32Or = 0;
+ Mmio32And(Vc0RemapEngineBase, 0xFF0, Data32And);
+ SCRIPT_MEM_READ_WRITE
+ (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (Vc0RemapEngineBase + 0xFF0),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+UpdateDmarExitPmAuth (
+ VOID
+ )
+/**
+ ExitPmAuth routine for update DMAR
+**/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+ INTN Instance;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN AcpiTableHandle;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_ACPI_DESCRIPTION_HEADER *VtdAcpiTable;
+ STATIC BOOLEAN Triggered = FALSE;
+
+ if (Triggered) {
+ return;
+ }
+
+ Triggered = TRUE;
+
+ FwVol = NULL;
+ AcpiTable = NULL;
+ VtdAcpiTable = NULL;
+
+ ///
+ /// Locate PCH platform policy protocol and PCH series to support feature enabling/disabling
+ ///
+ Status = gBS->LocateProtocol (
+ &gDxePchPlatformPolicyProtocolGuid,
+ NULL,
+ (VOID**) &mDxePlatformPchPolicy
+ );
+ ASSERT_EFI_ERROR (Status);
+ mPchSeries = GetPchSeries();
+
+ if ((!mDxePlatformSaPolicy->Vtd->VtdEnable) || (McD0PciCfg32 (R_SA_MC_CAPID0_A_OFFSET) & BIT23)) {
+ DEBUG ((EFI_D_INFO, "Vtd Disabled, skip DMAR Table install\n"));
+
+ return;
+ }
+
+ ///
+ /// Locate ACPI support protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+
+ ///
+ /// Locate protocol.
+ /// There is little chance we can't find an FV protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Looking for FV with ACPI storage file
+ ///
+ for (i = 0; i < NumberOfHandles; i++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ &gEfiFirmwareVolumeProtocolGuid,
+ (VOID **) &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &gSaAcpiTableStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ ///
+ /// If we found it, then we are done
+ ///
+ if (Status == EFI_SUCCESS) {
+ 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
+ ///
+ FreePool (HandleBuffer);
+
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol);
+ if (FwVol == NULL) {
+ return ;
+ }
+ ///
+ /// 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;
+
+ ///
+ /// Read tables from the storage file.
+ ///
+ Instance = 0;
+ CurrentTable = NULL;
+
+ while (Status == EFI_SUCCESS) {
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gSaAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID **) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Check the Signature ID to modify the table
+ ///
+ switch (((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Signature) {
+
+ case EFI_ACPI_VTD_DMAR_TABLE_SIGNATURE:
+ VtdAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ DmarTableUpdate (VtdAcpiTable, &Version);
+ break;
+
+ default:
+ break;
+ }
+ ///
+ /// Increment the instance
+ ///
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+ ///
+ /// Update the VTD table in the ACPI tables.
+ ///
+ AcpiTableHandle = 0;
+ if (VtdAcpiTable != NULL) {
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ VtdAcpiTable,
+ VtdAcpiTable->Length,
+ &AcpiTableHandle
+ );
+ }
+}
+
+EFI_STATUS
+VtdInit (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+@brief
+ Locate the VT-d ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - Vtd initialization complete
+ @exception EFI_UNSUPPORTED - Vtd is not enabled by policy
+**/
+{
+ EFI_STATUS Status;
+ UINTN i;
+ UINT64 MchBar;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT32 VtdBase;
+ UINT32 VtBarReg [SA_VTD_ENGINE_NUMBER];
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuStepping;
+
+ mInterruptRemappingSupport = FALSE;
+ mPchRootComplexBar = MmPci32 (0, 0, 31, 0, 0xF0) &~BIT0;
+ MchBar = McD0PciCfg64 (R_SA_MCHBAR) &~BIT0;
+
+ VtBarReg[0] = R_SA_MCHBAR_VTD1_OFFSET;
+ VtBarReg[1] = R_SA_MCHBAR_VTD2_OFFSET;
+ mDxePlatformSaPolicy = DxePlatformSaPolicy;
+
+ ///
+ /// Check SA supports VTD and VTD is enabled in setup menu
+ ///
+ if ((!mDxePlatformSaPolicy->Vtd->VtdEnable) || (McD0PciCfg32 (R_SA_MC_CAPID0_A_OFFSET) & BIT23)) {
+ DEBUG ((EFI_D_WARN, "VTd disabled or no capability!\n"));
+ return EFI_UNSUPPORTED;
+ }
+ DEBUG ((EFI_D_INFO, "VTd enabled\n"));
+
+ ///
+ /// 14.1 Program Remap Engine Base Address
+ /// Configure VTD1 BAR
+ ///
+ i = 0;
+
+ ///
+ /// Skip GFXVTBAR if IGD is disabled
+ ///
+ if (McD2PciCfg16 (R_SA_IGD_VID) != 0xFFFF) {
+ Data32Or = mDxePlatformSaPolicy->Vtd->BaseAddress[i];
+ Data32Or |= 0x1;
+ Mmio32 (MchBar, R_SA_MCHBAR_VTD1_OFFSET) = Data32Or;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MchBar + R_SA_MCHBAR_VTD1_OFFSET),
+ 1,
+ &Data32Or
+ );
+ i++;
+ }
+
+ ///
+ /// Configure VTD2 BAR
+ ///
+ Data32Or = mDxePlatformSaPolicy->Vtd->BaseAddress[i];
+ Data32Or |= 0x1;
+ Mmio32 (MchBar, R_SA_MCHBAR_VTD2_OFFSET) = Data32Or;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MchBar + R_SA_MCHBAR_VTD2_OFFSET),
+ 1,
+ &Data32Or
+ );
+
+ ///
+ /// Workaround for VC0 remapping engine
+ ///
+ Status = WaForVc0RemappingEngine (MchBar);
+ ASSERT_EFI_ERROR (Status);
+
+ for (i = 0; i < SA_VTD_ENGINE_NUMBER; i++) {
+ VtdBase = Mmio32 (MchBar, VtBarReg[i]) & 0xfffffffe;
+
+ ///
+ /// skip if the VT bar is 0
+ ///
+ if (VtdBase == 0) {
+ continue;
+ }
+
+ CpuFamilyId = GetCpuFamily();
+ CpuStepping = GetCpuStepping();
+
+ if ((CpuFamilyId == EnumCpuHsw) || (CpuFamilyId == EnumCpuHswUlt) || (CpuFamilyId == EnumCpuCrw)
+ ) {
+ Data32And = (UINT32) ~(BIT15+BIT16+BIT17+BIT18+BIT19); ///< mask out 19:15
+ Data32Or = BIT15;
+ if (i == 1) {
+ Mmio32AndThenOr (VtdBase, 0xF04, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (VtdBase + 0xF04),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+ }
+ }
+ ///
+ /// 14.2 Set the remap engine policy bits
+ ///
+ Data32And = 0x0; ///< mask out all bits
+ Data32Or = 0;
+
+
+ if ((CpuFamilyId == EnumCpuHsw) || (CpuFamilyId == EnumCpuHswUlt) || (CpuFamilyId == EnumCpuCrw)) {
+ if (i == 0) {
+ Data32Or |= 0x02100000;
+ }
+ if (i == 1) {
+ if (McD2PciCfg16 (R_SA_IGD_VID) != 0xFFFF) {
+ Data32Or |= 0x000A5003;
+ } else {
+ Data32Or |= 0x020A5003;
+ }
+ }
+ }
+
+ ///
+ /// Set lock bit
+ ///
+ Data32Or |= BIT31;
+
+
+ Mmio32AndThenOr (VtdBase, 0xFF0, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (VtdBase + 0xFF0),
+ &Data32Or, ///< Data to be ORed
+ &Data32And ///< Data to be ANDed
+ );
+
+ ///
+ /// Check IR status
+ ///
+ if ((Mmio32 (VtdBase, VTD_ECAP_REG) & IR) && !(mInterruptRemappingSupport)) {
+ mInterruptRemappingSupport = TRUE;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.h
new file mode 100644
index 0000000..2d9daa4
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/VTd.h
@@ -0,0 +1,70 @@
+/** @file
+ This code provides a initialization of intel VT-d (Virtualization Technology for Directed I/O).
+
+@copyright
+ Copyright (c) 1999 - 2012 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
+**/
+#ifndef _VT_D_H_
+#define _VT_D_H_
+
+///
+/// Include files
+///
+#include "DmaRemappingTable.h"
+#include "SaAccess.h"
+#include "PchAccess.h"
+
+#include EFI_PROTOCOL_DEPENDENCY (AcpiTable)
+#include EFI_PROTOCOL_DEFINITION (SaPlatformPolicy)
+#include EFI_PROTOCOL_DEFINITION (PchPlatformPolicy)
+
+///
+/// SA ACPI table data storage file
+///
+#include EFI_GUID_DEFINITION (SaAcpiTableStorage)
+
+#define VTD_ECAP_REG 0x10
+#define IR BIT3
+
+#define VTD_GCMD_REG 0x18
+#define QIE BIT26
+#define IRE BIT25
+
+EFI_STATUS
+VtdInit (
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Locate the VT-d ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @param[in] DxePlatformSaPolicy SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - Vtd initialization complete
+ @retval Other - No Vtd function initiated
+**/
+;
+
+VOID
+UpdateDmarExitPmAuth (
+ VOID
+ )
+/**
+ ExitPmAuth routine for update DMAR
+**/
+;
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.c
new file mode 100644
index 0000000..2b1af13
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.c
@@ -0,0 +1,1094 @@
+/** @file
+ DXE driver for Initializing SystemAgent Graphics initialization.
+
+@copyright
+ Copyright (c) 1999 - 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 "GraphicsInit.h"
+#include EFI_PROTOCOL_DEFINITION (LegacyBios)
+#include EFI_PROTOCOL_DEFINITION (GopComponentName2)
+#ifndef AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+#if (defined(IntelSaGopDriver_SUPPORT) && (IntelSaGopDriver_SUPPORT == 1))
+#include "Include\Protocol\IntelSaGopDriver.h"
+#endif
+#endif
+UINT64 GTTMMADR;
+UINTN MCHBAR_BASE;
+UINT8 rP1GraphicsFreq;
+EFI_EVENT mExitPmAuthEvent;
+
+DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy;
+GOP_COMPONENT_NAME2_PROTOCOL *GopComponentName2Protocol = NULL;
+
+///
+/// RC6 Settings
+///
+BOOT_SCRIPT_REGISTER_SETTING gSaGtRC6Registers[] = {
+ 0x0,
+ 0xA090,
+ 0xFFFFFFFF,
+ 0x0,
+ ///
+ /// RC1e - RC6/6p - RC6pp Wake Rate Limits
+ ///
+ 0x0,
+ 0xA098,
+ 0xFFFFFFFF,
+ 0x3E80000,
+ 0x0,
+ 0xA09C,
+ 0xFFFFFFFF,
+ 0x00280000,
+ 0x0,
+ 0xA0A8,
+ 0xFFFFFFFF,
+ 0x1E848,
+ 0x0,
+ 0xA0AC,
+ 0xFFFFFFFF,
+ 0x19,
+ ///
+ /// Render/Video/Blitter Idle Max Count
+ ///
+ 0x0,
+ 0x2054,
+ 0x0,
+ 0xA,
+ 0x0,
+ 0x12054,
+ 0x0,
+ 0xA,
+ 0x0,
+ 0x22054,
+ 0x0,
+ 0xA,
+ 0x0,
+ 0x1a054,
+ 0x0,
+ 0xA,
+ ///
+ /// RC Sleep / RCx Thresholds
+ ///
+ 0x0,
+ 0xA0B0,
+ 0xFFFFFFFF,
+ 0,
+ 0x0,
+ 0xA0B4,
+ 0xFFFFFFFF,
+ 0x3E8,
+ 0x0,
+ 0xA0B8,
+ 0xFFFFFFFF,
+ 0xC350,
+ ///
+ /// RP Settings
+ ///
+ 0x0,
+ 0xA010,
+ 0xFFFFFFFF,
+ 0xF4240,
+ 0x0,
+ 0xA014,
+ 0xFFFFFFFF,
+ 0x12060000,
+ 0x0,
+ 0xA02C,
+ 0xFFFFFFFF,
+ 0x0000E808,
+ 0x0,
+ 0xA030,
+ 0xFFFFFFFF,
+ 0x0003BD08,
+ 0x0,
+ 0xA068,
+ 0xFFFFFFFF,
+ 0x000101D0,
+ 0x0,
+ 0xA06C,
+ 0xFFFFFFFF,
+ 0x00055730,
+ 0x0,
+ 0xA070,
+ 0xFFFFFFFF,
+ 0xA
+};
+
+///
+/// PM Lock Settings
+///
+BOOT_SCRIPT_REGISTER_SETTING gSaGtPmLockBits[] = {
+ 0x0,
+ 0xA248,
+ 0xFFFFFFFF,
+ BIT31,
+ 0x0,
+ 0xA004,
+ 0xFFFFFFFF,
+ BIT4,
+ 0x0,
+ 0xA080,
+ 0xFFFFFFFF,
+ BIT2,
+ 0x0,
+ 0xA180,
+ 0xFFFFFFFF,
+ BIT31
+};
+
+EFI_STATUS
+PmInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Initialize GT PowerManagement of SystemAgent.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - GT Power Management initialization complete
+**/
+{
+ UINT8 i;
+ UINT32 RegOffset;
+ UINT32 Data32;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT32 Data32Mask;
+ UINT32 Result;
+ CPU_STEPPING CpuSteppingId;
+ CPU_FAMILY CpuFamilyId;
+
+ CpuFamilyId = GetCpuFamily();
+ CpuSteppingId = GetCpuStepping();
+
+ ///
+ /// Multi Threaded Force Wake
+ ///
+ RegOffset = 0xA180;
+ Data32 = BIT5;
+ Mmio32 (GTTMMADR, RegOffset) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ 1,
+ &Data32
+ );
+
+ RegOffset = 0xA188;
+ Data32 = 0x00010001;
+ Mmio32 (GTTMMADR, RegOffset) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ 1,
+ &Data32
+ );
+ ///
+ /// Force Wake Acknowledge Bit
+ ///
+ RegOffset = 0x130044;
+ Data32Mask = BIT0;
+ Result = 1;
+ PollGtReady (GTTMMADR, RegOffset, Data32Mask, Result);
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ &Data32Mask,
+ &Result,
+ 50,
+ 200000
+ );
+
+ ///
+ /// Enable counters except Power Meter
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = 0x16;
+ Mmio32AndThenOr (GTTMMADR, 0xA248, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0xA248),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+
+ ///
+ /// GFXPAUSE Settings
+ ///
+ Data32 = 0x70020;
+
+
+ if (((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId < EnumHswC0) ) ||
+ ((CpuFamilyId == EnumCpuHswUlt) && (CpuSteppingId < EnumHswUltC0)) ||
+ ((CpuFamilyId == EnumCpuCrw) && (CpuSteppingId < EnumCrwC0) )) {
+ Data32 |= 0xFFFF;
+ }
+
+ Mmio32 (GTTMMADR, 0xA000) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0xA000),
+ 1,
+ &Data32
+ );
+
+
+ ///
+ /// ECO Settings
+ /// BIT28 = 1 GFX will be blocked from accessing memory (go=0) during CPD enter
+ /// BIT26 = 1 indicates to PCU that we are doing a fifo block due to RC6 and not CPD
+ /// BIT[24:22] = 100 RC6 Control
+ ///
+ RegOffset = 0xA180;
+ Data32And = 0xFFFFFFFF;
+ Data32Or = BIT28 + BIT26;
+ if (DxePlatformSaPolicy->IgdConfig->RenderStandby) {
+ Data32And = (UINT32)~(BIT23 + BIT22);
+ Data32Or |= BIT24;
+ }
+
+ ///
+ /// Force CPD Non-IA. for steppings less than C0 for HSW/CRW
+ ///
+ if (((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId < EnumHswC0)) ||
+ ((CpuFamilyId == EnumCpuCrw) && (CpuSteppingId < EnumCrwC0))) {
+ Data32Or |= BIT30;
+ }
+ ///
+ /// Force CPD Block memory bits. for stepping less than C0 for HSW/ULT/CRW
+ ///
+ if (((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId < EnumHswC0) ) ||
+ ((CpuFamilyId == EnumCpuHswUlt) && (CpuSteppingId < EnumHswUltC0)) ||
+ ((CpuFamilyId == EnumCpuCrw) && (CpuSteppingId < EnumCrwC0) )) {
+ Data32And &= (UINT32)~(BIT28);
+ Data32Or &= (UINT32)~(BIT28);
+ }
+
+ Mmio32AndThenOr (GTTMMADR, RegOffset, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+
+ ///
+ /// Clock Gating Settings
+ ///
+ Data32 = 0x3FD;
+ Mmio32 (GTTMMADR, 0x9424) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x9424),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Enable Unit Level Clock Gates
+ ///
+ Data32 = 0x80;
+ Mmio32 (GTTMMADR, 0x9400) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x9400),
+ 1,
+ &Data32
+ );
+
+ Data32 = 0x40401000;
+ Mmio32 (GTTMMADR, 0x9404) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x9404),
+ 1,
+ &Data32
+ );
+
+ Data32 = 0;
+ Mmio32 (GTTMMADR, 0x9408) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x9408),
+ 1,
+ &Data32
+ );
+
+ Data32 = 0x02000001;
+ Mmio32 (GTTMMADR, 0x940c) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x940c),
+ 1,
+ &Data32
+ );
+
+ Data32 = 0x08000000;
+ Mmio32 (GTTMMADR, 0xA008) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0xA008),
+ 1,
+ &Data32
+ );
+ ///
+ /// RC6 Settings
+ ///
+ for (i = 0; i < sizeof (gSaGtRC6Registers) / sizeof (BOOT_SCRIPT_REGISTER_SETTING); ++i) {
+ RegOffset = gSaGtRC6Registers[i].Offset;
+ Data32And = gSaGtRC6Registers[i].AndMask;
+ Data32Or = gSaGtRC6Registers[i].OrMask;
+
+ Mmio32AndThenOr (GTTMMADR, RegOffset, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+
+ ///
+ /// RP Control
+ ///
+ Data32 = 0xB92;
+ Mmio32 (GTTMMADR, 0xA024) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0xA024),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// HW RC6 Control Settings
+ ///
+ Data32 = 0;
+
+ if (DxePlatformSaPolicy->IgdConfig->RenderStandby) {
+ Data32 = 0x88040000;
+ }
+
+ Mmio32 (GTTMMADR, 0xA090) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0xA090),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Video frequency request
+ ///
+ Data32 = 0x08000000;
+ Mmio32 (GTTMMADR, 0xA00C) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0xA00C),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// RC6 Settings
+ ///
+ ///
+ /// Wait for Mailbox ready
+ ///
+ Data32Mask = BIT31;
+ Result = 0;
+
+ PollGtReady (GTTMMADR, 0x138124, Data32Mask, Result);
+
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x138124),
+ &Data32Mask,
+ &Result,
+ 50,
+ 200000
+ );
+
+ ///
+ /// Mailbox Data - RC6 VIDS
+ ///
+ Data32 = 0x0;
+ Mmio32 (GTTMMADR, 0x138128) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x138128),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Mailbox Command
+ ///
+ Data32 = 0x80000004;
+ Mmio32 (GTTMMADR, 0x138124) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x138124),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Wait for Mailbox ready
+ ///
+ Data32Mask = BIT31;
+ Result = 0;
+
+ PollGtReady (GTTMMADR, 0x138124, Data32Mask, Result);
+
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x138124),
+ &Data32Mask,
+ &Result,
+ 50,
+ 200000
+ );
+
+ ///
+ /// Enable PM Interrupts
+ ///
+ Data32 = 0x3000076;
+ Mmio32 (GTTMMADR, 0x4402C) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x4402C),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// RC6 setting
+ ///
+ if (mDxePlatformSaPolicy->IgdConfig->RenderStandby) {
+ ///
+ /// Software RC state - RC6
+ ///
+ Data32 = 0x40000;
+ Mmio32 (GTTMMADR, 0xA094) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (GTTMMADR + 0xA094),
+ 1,
+ &Data32
+ );
+ }
+
+ ///
+ /// PM Lock Settings
+ ///
+ for (i = 0; i < sizeof (gSaGtPmLockBits) / sizeof (BOOT_SCRIPT_REGISTER_SETTING); ++i) {
+ RegOffset = gSaGtPmLockBits[i].Offset;
+ Data32And = gSaGtPmLockBits[i].AndMask;
+ Data32Or = gSaGtPmLockBits[i].OrMask;
+
+ Mmio32AndThenOr (GTTMMADR, RegOffset, Data32And, Data32Or);
+
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PavpInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Initialize PAVP feature of SystemAgent.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - PAVP initialization complete
+**/
+{
+
+ UINT32 DwordData;
+ UINT32 PcmBase;
+ CPU_STEPPING CpuSteppingId;
+ CPU_FAMILY CpuFamilyId;
+
+ CpuFamilyId = GetCpuFamily();
+ CpuSteppingId = GetCpuStepping();
+
+ McD0PciCfg32And (R_SA_PAVPC, ~(B_SA_PAVPC_HVYMODSEL_MASK | B_SA_PAVPC_PCMBASE_MASK | B_SA_PAVPC_PAVPE_MASK | B_SA_PAVPC_PCME_MASK));
+ McD0PciCfg16Or (R_SA_PAVPC, B_SA_PAVPC_PCME_MASK | B_SA_PAVPC_PAVPE_MASK);
+ PcmBase = ((UINT32) RShiftU64 ((McD0PciCfg32 (R_SA_TOLUD)), 20)) - PAVP_PCM_SIZE_1_MB;
+ McD0PciCfg32Or (R_SA_PAVPC, (UINT32) LShiftU64 (PcmBase, 20));
+
+ if ((CpuFamilyId == EnumCpuHsw) ||
+ (CpuFamilyId == EnumCpuHswUlt) ||
+ (CpuFamilyId == EnumCpuCrw)
+ ){
+ McD0PciCfg32Or (R_SA_PAVPC, (BIT4));
+ }
+
+ DwordData = McD0PciCfg32 (R_SA_PAVPC);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0,
+ 0,
+ 0,
+ 0,
+ R_SA_PAVPC)),
+ 1,
+ &DwordData
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PostPmInitExitPmAuth (
+ VOID
+ )
+/**
+ Do Post GT PM Init Steps after VBIOS Initialization.
+
+ @retval EFI_SUCCESS Succeed.
+**/
+{
+ UINT32 RegOffset;
+ UINT32 Data32;
+ EFI_STATUS Status;
+ UINT32 Data32Mask;
+ UINT32 Result;
+ UINT16 Data16;
+ CHAR16 *DriverVersion;
+ UINTN Index;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios = NULL;
+
+ ///
+ /// Get the platform setup policy.
+ ///
+ Status = gBS->LocateProtocol (&gDxePlatformSaPolicyGuid, NULL, (VOID **) &mDxePlatformSaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// only 32bit read/write is legal for device 0:2:0
+ ///
+ GTTMMADR = (UINT64) (McD2PciCfg32 (R_SA_IGD_GTTMMADR));
+ GTTMMADR = LShiftU64 ((UINT64) McD2PciCfg32 (R_SA_IGD_GTTMMADR + 4), 32) | (GTTMMADR);
+
+ ///
+ /// Save the current GTMMADR value into S3 resume script before other S3 resume items in this function.
+ /// GTTMMADR may have been modified by the PCI enumeration code at this point,
+ /// but not saved into the S3 resume script yet.
+ ///
+ ///
+ /// only 32bit read/write is legal for device 0:2:0
+ ///
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0,
+ 0,
+ 2,
+ 0,
+ R_SA_IGD_GTTMMADR)),
+ 1,
+ &GTTMMADR
+ );
+
+ ///
+ /// only 32bit read/write is legal for device 0:2:0
+ ///
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0,
+ 0,
+ 2,
+ 0,
+ R_SA_IGD_GTTMMADR + 4)),
+ 1,
+ (&(UINT32) GTTMMADR) + 1
+ );
+
+ GTTMMADR = GTTMMADR &~(BIT2 | BIT1);
+
+ ///
+ /// Enable Bus Master, I/O and Memory access on 0:2:0
+ ///
+ McD2PciCfg16Or (R_SA_IGD_CMD, (BIT2 | BIT1));
+ Data16 = McD2PciCfg16(R_SA_IGD_CMD);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (MmPciAddress (0, 0, 2, 0, R_SA_IGD_CMD)),
+ 1,
+ &Data16
+ );
+
+ ///
+ /// Deassert Force Wake
+ RegOffset = 0xA188;
+ Data32 = 0x00010000;
+ Mmio32 (GTTMMADR, RegOffset) = Data32;
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ 1,
+ &Data32
+ );
+
+ RegOffset = 0x130044;
+ Data32Mask = BIT0;
+ Result = 0;
+ PollGtReady (GTTMMADR, RegOffset, Data32Mask, Result);
+
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ &Data32Mask,
+ &Result,
+ 50,
+ 200000
+ );
+
+ RegOffset = 0xA188;
+ Data32 = 0x00000001;
+ Mmio32 (GTTMMADR, RegOffset) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + RegOffset),
+ 1,
+ &Data32
+ );
+
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+
+
+#ifndef AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+#if (defined(IntelSaGopDriver_SUPPORT) && (IntelSaGopDriver_SUPPORT == 1))
+{
+ EFI_PHYSICAL_ADDRESS VbtAddress;
+ UINT32 VbtSize;
+ PLATFORM_GOP_POLICY_PROTOCOL *PlatformGOPPolicy;
+ EFI_GUID PlatformGOPPolicyGuid = EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID;
+ EFI_STATUS Status2 = EFI_SUCCESS;
+ //
+ // Locate Platform GOP policy protocol
+ //
+ Status = gBS->LocateProtocol (&PlatformGOPPolicyGuid, NULL, &PlatformGOPPolicy);
+ if (!EFI_ERROR(Status)) {
+ Status2 = PlatformGOPPolicy->GetVbtData(&VbtAddress, &VbtSize);
+ if (!EFI_ERROR(Status2)) LegacyBios = NULL;
+ }
+}
+#endif
+#endif // AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+
+ if (!LegacyBios) {
+ Status = gBS->LocateProtocol (&gGopComponentName2ProtocolGuid, NULL, (VOID **)&GopComponentName2Protocol);
+ if (!EFI_ERROR (Status)) {
+ Status = GopComponentName2Protocol->GetDriverVersion (
+ GopComponentName2Protocol,
+ "en-US",
+ &DriverVersion
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; (DriverVersion[Index] != '\0'); Index++) {
+ }
+ Index = (Index+1)*2;
+ CopyMem(mDxePlatformSaPolicy->IgdConfig->GopVersion, DriverVersion, Index);
+ }
+ }
+ }
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+Initialize GT Post Routines.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - GT POST initialization complete
+ @retval EFI_NOT_FOUND - Dxe System Table not found.
+**/
+{
+ EFI_PHYSICAL_ADDRESS MemBaseAddress;
+ UINT32 LoGTBaseAddress;
+ UINT32 HiGTBaseAddress;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ EFI_STATUS Status;
+ UINTN DwordData;
+ UINT32 Data32Mask;
+ UINT32 Result;
+ UINT16 Data16;
+ CPU_FAMILY CpuFamilyId;
+ UINT8 CpuSteppingId;
+ UINT32 Data32;
+ UINT16 IsUlx;
+
+ CpuFamilyId = GetCpuFamily();
+ CpuSteppingId = GetCpuStepping();
+
+ GTTMMADR = 0;
+ Status = EFI_SUCCESS;
+ MCHBAR_BASE = McD0PciCfg64 (0x48) &~BIT0;
+
+ ///
+ /// Read the RP1 Graphics Frequency
+ ///
+ rP1GraphicsFreq = (UINT8) ((Mmio32 (MCHBAR_BASE, 0x5998) >> 8) & 0xFF);
+
+ ///
+ /// If device 0:2:0 (Internal Graphics Device, or GT) is enabled, then Program GTTMMADR,
+ ///
+ if (McD2PciCfg16 (R_SA_IGD_VID) != 0xFFFF) {
+ gDS = NULL;
+ Status = EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT(gDS != NULL);
+ if (gDS == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ///
+ /// Means Allocate 4MB for GTTMADDR
+ ///
+ MemBaseAddress = 0x0ffffffffffffffff;
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAnySearchBottomUp,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ GTT_MEM_ALIGN,
+ GTTMMADR_SIZE_4MB,
+ &MemBaseAddress,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Program GT PM Settings if GTTMMADR allocation is Successful
+ ///
+ GTTMMADR = (UINTN) MemBaseAddress;
+
+ LoGTBaseAddress = (UINT32) (MemBaseAddress & 0xFFFFFFFF);
+ HiGTBaseAddress = (UINT32) RShiftU64 ((MemBaseAddress & 0xFFFFFFFF00000000), 32);
+ McD2PciCfg32 (R_SA_IGD_GTTMMADR) = LoGTBaseAddress | BIT2;
+ McD2PciCfg32 (R_SA_IGD_GTTMMADR + 4) = HiGTBaseAddress;
+
+ DwordData = McD2PciCfg32 (R_SA_IGD_GTTMMADR);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0,
+ 0,
+ 2,
+ 0,
+ R_SA_IGD_GTTMMADR)),
+ 1,
+ &DwordData
+ );
+
+ DwordData = McD2PciCfg32 (R_SA_IGD_GTTMMADR + 4);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0,
+ 0,
+ 2,
+ 0,
+ R_SA_IGD_GTTMMADR + 4)),
+ 1,
+ &DwordData
+ );
+
+ ///
+ /// Enable Bus Master, I/O and Memory access on 0:2:0
+ ///
+ McD2PciCfg16Or (R_SA_IGD_CMD, (BIT2 | BIT1));
+ Data16 = McD2PciCfg16 (R_SA_IGD_CMD);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (MmPciAddress (0, 0, 2, 0, R_SA_IGD_CMD)),
+ 1,
+ &Data16
+ );
+
+ ///
+ /// PAVP Initialization
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing PAVP\n"));
+ PavpInit (ImageHandle, DxePlatformSaPolicy);
+ ///
+ /// PmInit Initialization
+ ///
+ DEBUG ((EFI_D_INFO, "Initializing GT PowerManagement\n"));
+ PmInit (ImageHandle, DxePlatformSaPolicy);
+
+ ///
+ /// Enable PowerWell for DP and Audio: set Dev2 mmio 45400 bit 31 and poll bit30 (1 means enabled)
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) (BIT31);
+ Mmio32Or (GTTMMADR, 0x45400, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x45400),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+
+ Data32Mask = BIT30;
+ Result = BIT30;
+ PollGtReady (GTTMMADR, 0x45400, Data32Mask, Result);
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x45400),
+ &Data32Mask,
+ &Result,
+ 50,
+ 200000
+ );
+
+ if (DxePlatformSaPolicy->Revision >=4) {
+ IsUlx = 0;
+ Data16 = McD2PciCfg16 (0x2);
+ if ((Data16 == 0xA0E) || (Data16 == 0xA1E)) {
+ IsUlx = 1;
+ }
+ ///
+ /// BIOS to get supported CD frequency
+ ///
+ if (((MmioRead32 (GTTMMADR + 0x42014) & 0x1000000) != 0) || (IsUlx == 1) || (CpuFamilyId == EnumCpuHswUlt)) {
+ ///fixed frequency
+ mDxePlatformSaPolicy->IgdConfig->CdClkVar = 0;
+ } else {
+ ///choice of varying frequency
+ mDxePlatformSaPolicy->IgdConfig->CdClkVar = 2;
+ }
+
+ if (IsUlx == 1) {
+ Data32And = 0xF7FFFFFF;
+ Data32Or = 0x4000000;
+ } else {
+ if ((mDxePlatformSaPolicy->IgdConfig->CdClk) != 1) {
+ if ((mDxePlatformSaPolicy->IgdConfig->CdClkVar != 0)) {
+ ///540 or 337.5Mhz
+ Data32And = 0xF7FFFFFF;
+ Data32Or = 0x4000000;
+ }
+ } else {
+ ///450 Mhz
+ Data32And = 0xF3FFFFFF;
+ Data32Or = 0;
+ }
+ }
+ Mmio32AndThenOr (GTTMMADR, 0x130040, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x130040),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+
+ if ((CpuFamilyId == EnumCpuHswUlt)||(IsUlx == 1)) {
+ Data32 = 1;
+ if (((mDxePlatformSaPolicy->IgdConfig->CdClk) == 1) && (IsUlx == 0)) {
+ Data32 = 0;
+ }
+
+ Mmio32 (GTTMMADR, 0x138128) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x138128),
+ 1,
+ &Data32
+ );
+
+ Data32 = 0x0;
+ Mmio32 (GTTMMADR, 0x13812c) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x13812c),
+ 1,
+ &Data32
+ );
+
+ Data32 = 0x80000017;
+ Mmio32 (GTTMMADR, 0x138124) = Data32;
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (GTTMMADR + 0x138124),
+ 1,
+ &Data32
+ );
+ }
+ }
+
+ McD2PciCfg16And (R_SA_IGD_CMD, ~(BIT2 | BIT1));
+ Data16 = McD2PciCfg16(R_SA_IGD_CMD);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (MmPciAddress (0, 0, 2, 0, R_SA_IGD_CMD)),
+ 1,
+ &Data16
+ );
+
+ McD2PciCfg64 (R_SA_IGD_GTTMMADR) = 0;
+ DwordData = McD2PciCfg64(R_SA_IGD_GTTMMADR);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0, 0, 2, 0, R_SA_IGD_GTTMMADR)),
+ 1,
+ &DwordData
+ );
+
+ ///
+ /// Free allocated resources
+ ///
+ gDS->FreeMemorySpace (MemBaseAddress, GTTMMADR_SIZE_4MB);
+ }
+
+ ///
+ /// Lock PAVPC Register
+ ///
+ McD0PciCfg32Or (R_SA_PAVPC, B_SA_PAVPC_PAVPLCK_MASK);
+
+ DwordData = McD0PciCfg32 (R_SA_PAVPC);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0,
+ 0,
+ 0,
+ 0,
+ R_SA_PAVPC)),
+ 1,
+ &DwordData
+ );
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PollGtReady (
+ UINT64 Base,
+ UINT32 Offset,
+ UINT32 Mask,
+ UINT32 Result
+ )
+/**
+ "Poll Status" for GT Readiness
+
+ @param[in] Base - Base address of MMIO
+ @param[in] Offset - MMIO Offset
+ @param[in] Mask - Mask
+ @param[in] Result - Value to wait for
+**/
+{
+ UINT32 GtStatus;
+ UINT16 StallCount;
+
+ StallCount = 0;
+
+ ///
+ /// Register read
+ ///
+ GtStatus = Mmio32 (Base, Offset);
+
+ while (((GtStatus & Mask) != Result) && (StallCount < GT_WAIT_TIMEOUT)) {
+
+ GtStatus = Mmio32 (Base, Offset);
+ ///
+ /// 1mSec wait
+ ///
+ gBS->Stall (1000);
+ StallCount = StallCount + 1;
+ }
+
+ ASSERT ((StallCount != GT_WAIT_TIMEOUT));
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.h
new file mode 100644
index 0000000..d5696e3
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/graphicsinit.h
@@ -0,0 +1,132 @@
+/** @file
+ Header file for initialization of GT PowerManagement
+
+@copyright
+ Copyright (c) 1999 - 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
+**/
+#ifndef _GRAPHICS_INIT_H_
+#define _GRAPHICS_INIT_H_
+
+#include "EdkIIGlueDxe.h"
+#include "SaAccess.h"
+#include "EfiScriptLib.h"
+#include EFI_PROTOCOL_DEFINITION (SaPlatformPolicy)
+#include EFI_PROTOCOL_DEFINITION (PciHostBridgeResourceAllocation)
+#include EFI_PROTOCOL_CONSUMER (ExitPmAuth)
+#include "SaInit.h"
+#include "PchAccess.h"
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+
+///
+/// Data definitions
+///
+///
+/// GT RELATED EQUATES
+///
+#define GTT_MEM_ALIGN 22
+#define GTTMMADR_SIZE_4MB 0x400000
+#define GT_WAIT_TIMEOUT 3000 ///< ~3 seconds
+
+///
+/// PAVP Modes
+///
+#define PAVP_LITE_MODE 1
+#define PAVP_SERPENT_MODE 2
+#define PAVP_PCM_SIZE_1_MB 1
+
+EFI_STATUS
+PavpInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Initialize PAVP feature of SystemAgent.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - PAVP initialization complete
+**/
+;
+
+/**
+ Initialize PAVP.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - PAVP initialization complete
+**/
+EFI_STATUS
+PmInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Initialize GT PowerManagement of SystemAgent.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - GT Power Management initialization complete
+**/
+;
+
+EFI_STATUS
+GraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy
+ )
+/**
+ Initialize GT PowerManagement of SystemAgent.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] DxePlatformSaPolicy - SA DxePlatformPolicy protocol
+
+ @retval EFI_SUCCESS - GT Power Management initialization complete
+**/
+;
+
+VOID
+PollGtReady (
+ UINT64 Base,
+ UINT32 Offset,
+ UINT32 Mask,
+ UINT32 Result
+ )
+/**
+ "Poll Status" for GT Readiness
+
+ @param[in] Base - Base address of MMIO
+ @param[in] Offset - MMIO Offset
+ @param[in] Mask - Mask
+ @param[in] Result - Value to wait for
+**/
+;
+
+EFI_STATUS
+PostPmInitExitPmAuth (
+ VOID
+ )
+/**
+ Do Post GT PM Init Steps after VBIOS Initialization.
+
+ @retval EFI_SUCCESS Succeed.
+**/
+;
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.c
new file mode 100644
index 0000000..0774807
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.c
@@ -0,0 +1,955 @@
+/** @file
+ This is part of the implementation of an Intel Graphics drivers OpRegion /
+ Software SCI interface between system BIOS, ASL code, and Graphics drivers.
+ The code in this file will load the driver and initialize the interface
+
+ Supporting Specifiction: OpRegion / Software SCI SPEC 0.70
+
+ Acronyms:
+ IGD: Internal Graphics Device
+ NVS: ACPI Non Volatile Storage
+ OpRegion: ACPI Operational Region
+ VBT: Video BIOS Table (OEM customizable data)
+
+@copyright
+ Copyright (c) 1999 - 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 files
+///
+#include "IgdOpRegion.h"
+#include "CpuIA32.h"
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+#include <Protocol\SaPlatformPolicy\SaPlatformPolicy.h>
+#ifndef AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+#include "Token.h"
+#if (defined(IntelSaGopDriver_SUPPORT) && (IntelSaGopDriver_SUPPORT == 1))
+#include "Include\Protocol\IntelSaGopDriver.h"
+#endif
+#endif
+
+///
+/// Global variables
+///
+IGD_OPREGION_PROTOCOL mIgdOpRegion;
+EFI_GUID mMiscSubClass = EFI_MISC_SUBCLASS_GUID;
+EFI_EVENT mExitPmAuthEvent;
+BOOLEAN mRunExitPmAuthRoutine;
+SYSTEM_AGENT_GLOBAL_NVS_AREA_PROTOCOL *mSaGlobalNvsArea;
+DXE_PLATFORM_SA_POLICY_PROTOCOL *mDxePlatformSaPolicy;
+
+///
+/// Function implementations.
+///
+EFI_STATUS
+GetIntegratedIntelVbtPtr (
+ OUT VBIOS_VBT_STRUCTURE **VbtFileBuffer
+ )
+/**
+ Get VBT data using SaPlaformPolicy
+
+ @param[in] VbtFileBuffer Pointer to VBT data buffer.
+
+ @retval EFI_SUCCESS VBT data was returned.
+ @retval EFI_NOT_FOUND VBT data not found.
+ @exception EFI_UNSUPPORTED Invalid signature in VBT data.
+**/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS VbtAddress;
+ UINT32 Size;
+
+ ///
+ /// Get the platform SA policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gDxePlatformSaPolicyGuid,
+ NULL,
+ (VOID **) &mDxePlatformSaPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VbtAddress = mDxePlatformSaPolicy->IgdConfig->VbtAddress;
+ Size = mDxePlatformSaPolicy->IgdConfig->Size ;
+
+ if (VbtAddress == 0x00000000) {
+ return EFI_NOT_FOUND;
+ } else {
+ ///
+ /// Check VBT signature
+ ///
+ *VbtFileBuffer = NULL;
+ *VbtFileBuffer = (VBIOS_VBT_STRUCTURE *) (UINTN) VbtAddress;
+ if ((*((UINT32 *) ((*VbtFileBuffer)->HeaderSignature))) != VBT_SIGNATURE) {
+ FreePool (*VbtFileBuffer);
+ *VbtFileBuffer = NULL;
+ return EFI_UNSUPPORTED;
+ }
+ }
+ if (Size == 0) {
+ return EFI_NOT_FOUND;
+ } else {
+ ///
+ /// Check VBT size
+ ///
+ if ((*VbtFileBuffer)->HeaderVbtSize > Size) {
+ (*VbtFileBuffer)->HeaderVbtSize = (UINT16) Size;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetIntegratedIntelVBiosPtr (
+ OUT INTEL_VBIOS_OPTION_ROM_HEADER **VBiosImage
+ )
+/**
+ Get a pointer to an uncompressed image of the Intel video BIOS.
+
+ Note: This function would only be called if the video BIOS at 0xC000 is
+ missing or not an Intel video BIOS. It may not be an Intel video BIOS
+ if the Intel graphic contoller is considered a secondary adapter.
+
+ @param[in] VBiosImage - Pointer to an uncompressed Intel video BIOS. This pointer must
+ be set to NULL if an uncompressed image of the Intel Video BIOS
+ is not obtainable.
+
+ @retval EFI_SUCCESS - VBiosPtr is updated.
+ @exception EFI_UNSUPPORTED - No Intel video BIOS found.
+**/
+
+{
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ INTEL_VBIOS_OPTION_ROM_HEADER *VBiosRomImage;
+ ///
+ /// Set as if an umcompressed Intel video BIOS image was not obtainable.
+ ///
+ VBiosRomImage = NULL;
+
+ ///
+ /// Get all PCI IO protocols
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Find the video BIOS by checking each PCI IO handle for an Intel video
+ /// BIOS OPROM.
+ ///
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ VBiosRomImage = PciIo->RomImage;
+
+ ///
+ /// If this PCI device doesn't have a ROM image, skip to the next device.
+ ///
+ if (!VBiosRomImage) {
+ continue;
+ }
+ ///
+ /// Get pointer to PCIR structure
+ ///
+ PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *) ((UINT8 *) VBiosRomImage + VBiosRomImage->PcirOffset);
+
+ ///
+ /// Check if we have an Intel video BIOS OPROM.
+ ///
+ if ((VBiosRomImage->Signature == OPTION_ROM_SIGNATURE) &&
+ (PcirBlockPtr->VendorId == V_SA_MC_VID) &&
+ (PcirBlockPtr->ClassCode[0] == 0x00) &&
+ (PcirBlockPtr->ClassCode[1] == 0x00) &&
+ (PcirBlockPtr->ClassCode[2] == 0x03)
+ ) {
+ ///
+ /// Found Intel video BIOS.
+ ///
+ *VBiosImage = VBiosRomImage;
+ return EFI_SUCCESS;
+ }
+ }
+ ///
+ /// No Intel video BIOS found.
+ ///
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+GetVBiosVbtExitPmAuth (
+ VOID
+ )
+/**
+ Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size).
+ The VBT (Video BIOS Table) is a block of customizable data that is built
+ within the video BIOS and edited by customers.
+
+ @retval EFI_SUCCESS - Video BIOS VBT information returned.
+ @exception EFI_UNSUPPORTED - Could not find VBT information (*VBiosVbtPtr = NULL).
+**/
+{
+ INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr;
+ UINT16 PciVenderId;
+ INTEL_VBIOS_OPTION_ROM_HEADER *VBiosPtr;
+ VBIOS_VBT_STRUCTURE *VBiosVbtPtr;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_STATUS Status;
+ VBIOS_VBT_STRUCTURE *VbtFileBuffer;
+ UINTN Index;
+#ifndef AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+#if (defined(IntelSaGopDriver_SUPPORT) && (IntelSaGopDriver_SUPPORT == 1))
+ EFI_PHYSICAL_ADDRESS VbtAddress;
+ UINT32 VbtSize;
+ PLATFORM_GOP_POLICY_PROTOCOL *PlatformGOPPolicy;
+ EFI_GUID PlatformGOPPolicyGuid = EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID;
+ EFI_STATUS Status2 = EFI_SUCCESS;
+#endif
+#endif // AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+
+ if (!mRunExitPmAuthRoutine) {
+ return EFI_SUCCESS;
+ }
+
+ ///
+ /// Get the platform SA policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gDxePlatformSaPolicyGuid,
+ NULL,
+ (VOID **) &mDxePlatformSaPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios = NULL;
+ VBiosPtr = NULL;
+
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+
+#ifndef AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+#if (defined(IntelSaGopDriver_SUPPORT) && (IntelSaGopDriver_SUPPORT == 1))
+ //
+ // Locate Platform GOP policy protocol
+ //
+ Status = gBS->LocateProtocol (&PlatformGOPPolicyGuid, NULL, &PlatformGOPPolicy);
+ if (!EFI_ERROR(Status)) {
+ Status2 = PlatformGOPPolicy->GetVbtData(&VbtAddress, &VbtSize);
+ if (!EFI_ERROR(Status2)) LegacyBios = NULL;
+ }
+#endif
+#endif // AMI_OVERRIDE_FOR_INTEL_GOP_SUPPORT
+
+ if (LegacyBios) {
+ VBiosPtr = (INTEL_VBIOS_OPTION_ROM_HEADER *) (UINTN) (VBIOS_LOCATION_PRIMARY);
+ PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->PcirOffset);
+ PciVenderId = PcirBlockPtr->VendorId;
+ ///
+ /// If the video BIOS is not at 0xC0000 or it is not an Intel video BIOS get
+ /// the integrated Intel video BIOS (must be uncompressed).
+ ///
+ if ((VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != V_SA_MC_VID)) {
+ GetIntegratedIntelVBiosPtr (&VBiosPtr);
+ if (VBiosPtr != NULL) {
+ ///
+ /// Video BIOS found.
+ ///
+ PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->PcirOffset);
+ PciVenderId = PcirBlockPtr->VendorId;
+
+ if ((VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != V_SA_MC_VID)) {
+ ///
+ /// Intel video BIOS not found.
+ ///
+ VBiosVbtPtr = NULL;
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+ } else {
+ ///
+ /// No Video BIOS found, try to get VBT from FV.
+ ///
+ GetIntegratedIntelVbtPtr (&VbtFileBuffer);
+ if (VbtFileBuffer != NULL) {
+ ///
+ /// Video BIOS not found, use VBT from SaPlatformPolicy
+ ///
+ DEBUG ((EFI_D_INFO, "VBT data found\n"));
+ for (Index = 0; (mDxePlatformSaPolicy->IgdConfig->GopVersion[Index] != '\0'); Index++) {
+ }
+ Index = (Index+1)*2;
+ CopyMem (mIgdOpRegion.OpRegion->Header.DVER, mDxePlatformSaPolicy->IgdConfig->GopVersion, Index);
+ (gBS->CopyMem) (mIgdOpRegion.OpRegion->VBT.GVD1, VbtFileBuffer, VbtFileBuffer->HeaderVbtSize);
+ FreePool (VbtFileBuffer);
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (VBiosPtr == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "VBIOS found at 0x%X\n", VBiosPtr));
+ VBiosVbtPtr = (VBIOS_VBT_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->VbtOffset);
+
+ if ((*((UINT32 *) (VBiosVbtPtr->HeaderSignature))) != VBT_SIGNATURE) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// No PlatformGopPolicy.h in EDK II code
+ ///
+#if 0
+ GetSVER (mIgdOpRegion.OpRegion->Header.SVER);
+#endif
+ DEBUG ((EFI_D_INFO, "System BIOS ID is %a\n", mIgdOpRegion.OpRegion->Header.SVER));
+
+ ///
+ /// Initialize Video BIOS version with its build number.
+ ///
+ mIgdOpRegion.OpRegion->Header.VVER[0] = VBiosVbtPtr->CoreBlockBiosBuild[0];
+ mIgdOpRegion.OpRegion->Header.VVER[1] = VBiosVbtPtr->CoreBlockBiosBuild[1];
+ mIgdOpRegion.OpRegion->Header.VVER[2] = VBiosVbtPtr->CoreBlockBiosBuild[2];
+ mIgdOpRegion.OpRegion->Header.VVER[3] = VBiosVbtPtr->CoreBlockBiosBuild[3];
+ (gBS->CopyMem) (mIgdOpRegion.OpRegion->VBT.GVD1, VBiosVbtPtr, VBiosVbtPtr->HeaderVbtSize);
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+///
+/// No PlatformGopPolicy.h in EDK II code
+///
+#if 0
+EFI_STATUS
+GetSVER (
+ OUT UINT8 *SVER
+ )
+/**
+ Set the SVER (system BIOS ID) string with the system BIOS build number.
+
+ @param[in] SVER String to populate with system BIOS build number.
+
+ @retval EFI_SUCCESS The SVER string is populated.
+ @exception EFI_UNSUPPORTED The SVER string is not populated.
+**/
+{
+ EFI_SUBCLASS_TYPE1_HEADER *DataHeader;
+ EFI_DATA_HUB_PROTOCOL *DataHub;
+ EFI_MISC_BIOS_VENDOR *BiosVendor;
+ UINTN Length;
+ UINT64 MonotonicCount;
+ CHAR16 *NewString;
+ EFI_DATA_RECORD_HEADER *Record;
+ EFI_STATUS Status;
+
+ ///
+ /// Locate the data hub protocol.
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiDataHubProtocolGuid,
+ NULL,
+ &DataHub
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Get the BIOS ID from the data hub.
+ ///
+ MonotonicCount = 0;
+ Record = NULL;
+
+ do {
+ ///
+ /// Check each data class record
+ ///
+ Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {
+ ///
+ /// Check for BIOS vendor information
+ ///
+ DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
+ if (CompareGuid (&Record->DataRecordGuid, &mMiscSubClass) &&
+ (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)
+ ) {
+ BiosVendor = (EFI_MISC_BIOS_VENDOR *) (DataHeader + 1);
+
+ ///
+ /// Get the BIOS ID string from the HII database
+ ///
+ Status = GetStringFromToken (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Convert from Unicode to ASCII
+ ///
+ if (NewString != NULL) {
+ Length = StrLen (NewString);
+ ASSERT (Length <= SVER_SIZE);
+ ASPrint (SVER, Length, "%s", NewString);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ } while ((!EFI_ERROR (Status)) && (MonotonicCount != 0));
+
+ ///
+ /// We assume BIOS ID is present and required.
+ /// If this is not the case, BIOS ID will need to be determined in another way.
+ ///
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
+}
+
+#if (EFI_SPECIFICATION_VERSION < 0x0002000A)
+EFI_STATUS
+GetStringFromToken (
+ IN EFI_GUID *ProducerGuid,
+ IN STRING_REF Token,
+ OUT CHAR16 **String
+ )
+/**
+ Acquire the string associated with the ProducerGuid and return it.
+
+ @param[in] ProducerGuid - The Guid to search the HII database for
+ @param[in] Token - The token value of the string to extract
+ @param[in] String - The string that is extracted
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND The requested string was not found
+**/
+{
+ EFI_STATUS Status;
+ UINT16 HandleBufferLength;
+ EFI_HII_HANDLE *HiiHandleBuffer;
+ UINTN StringBufferLength;
+ UINTN NumberOfHiiHandles;
+ UINTN Index;
+ UINT16 Length;
+ EFI_GUID HiiGuid;
+ EFI_HII_PROTOCOL *Hii;
+
+ HandleBufferLength = 0x1000;
+ HiiHandleBuffer = NULL;
+
+ ///
+ /// Locate HII protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Get all the Hii handles
+ ///
+ HiiHandleBuffer = AllocateZeroPool (HandleBufferLength);
+
+ Status = Hii->FindHandles (Hii, &HandleBufferLength, HiiHandleBuffer);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Get the Hii Handle that matches the StructureNode->ProducerName
+ ///
+ NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);
+ for (Index = 0; Index < NumberOfHiiHandles; Index++) {
+ Length = 0;
+ Status = ExtractDataFromHiiHandle (
+ HiiHandleBuffer[Index],
+ &Length,
+ NULL,
+ &HiiGuid
+ );
+ if (CompareGuid (ProducerGuid, &HiiGuid)) {
+ break;
+ }
+ }
+ ///
+ /// Find the string based on the current language
+ ///
+ StringBufferLength = 0x100;
+ *String = AllocateZeroPool (0x100);
+ Status = Hii->GetString (
+ Hii,
+ HiiHandleBuffer[Index],
+ Token,
+ FALSE,
+ NULL,
+ &StringBufferLength,
+ *String
+ );
+
+ (gBS->FreePool) (HiiHandleBuffer);
+
+ if (EFI_ERROR (Status)) {
+ (gBS->FreePool) (*String);
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+#endif
+#endif
+
+EFI_STATUS
+IgdOpRegionInit (
+ VOID
+ )
+/**
+ Graphics OpRegion / Software SCI driver installation function.
+
+ @param[in] void - None
+ @retval EFI_SUCCESS - The driver installed without error.
+ @retval EFI_ABORTED - The driver encountered an error and could not complete
+ installation of the ACPI tables.
+**/
+
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ ///
+ /// VBIOS_VBT_STRUCTURE *VBiosVbtPtr;
+ ///
+ UINT32 DwordData;
+ EFI_CPU_IO_PROTOCOL *CpuIo;
+ UINT16 Data16;
+ UINT32 Data32;
+ UINT16 PchAcpiBaseAddress;
+ UINT16 DeviceId;
+ PCH_SERIES PchSeries;
+ CPU_FAMILY CpuFamilyId;
+ EFI_GUID DxePlatformSaPolicyGuid = DXE_PLATFORM_SA_POLICY_GUID;
+ DXE_PLATFORM_SA_POLICY_PROTOCOL *DxePlatformSaPolicy;
+
+ CpuFamilyId = GetCpuFamily();
+
+ ///
+ /// Get the platform SA policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gDxePlatformSaPolicyGuid,
+ NULL,
+ (VOID **) &mDxePlatformSaPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Locate the SA Global NVS Protocol.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &mSaGlobalNvsArea
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Allocate an ACPI NVS memory buffer as the IGD OpRegion, zero initialize
+ /// the first 1K, and set the IGD OpRegion pointer in the Global NVS
+ /// area structure.
+ ///
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (IGD_OPREGION_STRUC), (VOID **) &mIgdOpRegion.OpRegion);
+ ASSERT_EFI_ERROR (Status);
+
+ (gBS->SetMem) (mIgdOpRegion.OpRegion, 0x2000, 0);
+ mSaGlobalNvsArea->Area->IgdOpRegionAddress = (UINT32) (UINTN) (mIgdOpRegion.OpRegion);
+
+ ///
+ /// If IGD is disabled return
+ ///
+ mRunExitPmAuthRoutine = TRUE;
+ if (IgdMmPci32 (0) == 0xFFFFFFFF) {
+ mRunExitPmAuthRoutine = FALSE;
+ return EFI_SUCCESS;
+ }
+
+ PchSeries = GetPchSeries();
+ ///
+ /// Initialize OpRegion Header
+ ///
+ (gBS->CopyMem) (mIgdOpRegion.OpRegion->Header.SIGN, HEADER_SIGNATURE, sizeof (HEADER_SIGNATURE));
+ ///
+ /// Set OpRegion Size in KBs
+ ///
+ mIgdOpRegion.OpRegion->Header.SIZE = HEADER_SIZE / 1024;
+ mIgdOpRegion.OpRegion->Header.OVER = (UINT32) (LShiftU64 (HEADER_OPREGION_VER, 16) + LShiftU64 (HEADER_OPREGION_REV, 8));
+
+ ///
+ /// Get CPU Flavor by reading System Agent's Device ID (B0:D1F:F0:R02)
+ ///
+ DeviceId = McD0PciCfg16 (R_SA_MC_DEVICE_ID);
+ if (IS_SA_DEVICE_ID_MOBILE (DeviceId)) {
+ ///
+ /// For Mobile, all Mailbox are supported.
+ ///
+ mIgdOpRegion.OpRegion->Header.MBOX = HEADER_MBOX_SUPPORT_MOBILE;
+ } else if (IS_SA_DEVICE_ID_DESKTOP (DeviceId) || IS_SA_DEVICE_ID_SERVER (DeviceId)) {
+ ///
+ /// For Desktop and Server, Mailbox 1/3/5 are not supported.
+ ///
+ mIgdOpRegion.OpRegion->Header.MBOX = HEADER_MBOX_SUPPORT_DESKTOP;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Hang if unknown System Agent\n"));
+ ASSERT (FALSE);
+ ///
+ /// Hang if unknown System Agent
+ ///
+ }
+ ///
+ /// Initialize OpRegion Mailbox 1 (Public ACPI Methods).
+ ///
+ /// @todo: The initial setting of mailbox 1 fields is implementation specific.
+ /// Adjust them as needed many even coming from user setting in setup.
+ ///
+ ///
+ /// Initialize OpRegion Mailbox 3 (ASLE Interrupt and Power Conservation).
+ ///
+ /// @todo: The initial setting of mailbox 3 fields is implementation specific.
+ /// Adjust them as needed many even coming from user setting in setup.
+ ///
+ ///
+ /// Do not initialize TCHE. This field is written by the graphics driver only.
+ ///
+ ///
+ /// The ALSI field is generally initialized by ASL code by reading the embedded controller.
+ ///
+ if (mDxePlatformSaPolicy->Revision >= 5) {
+ mIgdOpRegion.OpRegion->Header.PCON = mDxePlatformSaPolicy->IgdConfig->PlatformConfig;
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ mIgdOpRegion.OpRegion->Header.PCON = mIgdOpRegion.OpRegion->Header.PCON | 0x2;
+ }
+ }
+ mIgdOpRegion.OpRegion->MBox3.BCLP = BACKLIGHT_BRIGHTNESS;
+
+ mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH);
+
+ ///
+ /// Reporting to driver for VR IMON Calibration. Bits [5-1] values supported 14A to 31A.
+ ///
+ mIgdOpRegion.OpRegion->MBox3.PCFT = (mSaGlobalNvsArea->Area->GfxTurboIMON << 1) & 0x003E;
+
+ ///
+ /// Set Initial current Brightness
+ ///
+ mIgdOpRegion.OpRegion->MBox3.CBLV = (INIT_BRIGHT_LEVEL | FIELD_VALID_BIT);
+
+ ///
+ /// <EXAMPLE> Create a static Backlight Brightness Level Duty cycle Mapping Table
+ /// Possible 20 entries (example used 10), each 16 bits as follows:
+ /// [15] = Field Valid bit, [14:08] = Level in Percentage (0-64h), [07:00] = Desired duty cycle (0 - FFh).
+ ///
+ mIgdOpRegion.OpRegion->MBox3.BCLM[0] = (0x0000 + WORD_FIELD_VALID_BIT); ///< 0%
+ ///
+ mIgdOpRegion.OpRegion->MBox3.BCLM[1] = (0x0A19 + WORD_FIELD_VALID_BIT); ///< 10%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[2] = (0x1433 + WORD_FIELD_VALID_BIT); ///< 20%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[3] = (0x1E4C + WORD_FIELD_VALID_BIT); ///< 30%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[4] = (0x2866 + WORD_FIELD_VALID_BIT); ///< 40%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[5] = (0x327F + WORD_FIELD_VALID_BIT); ///< 50%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[6] = (0x3C99 + WORD_FIELD_VALID_BIT); ///< 60%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[7] = (0x46B2 + WORD_FIELD_VALID_BIT); ///< 70%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[8] = (0x50CC + WORD_FIELD_VALID_BIT); ///< 80%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[9] = (0x5AE5 + WORD_FIELD_VALID_BIT); ///< 90%
+ mIgdOpRegion.OpRegion->MBox3.BCLM[10] = (0x64FF + WORD_FIELD_VALID_BIT); ///< 100%
+
+ mIgdOpRegion.OpRegion->MBox3.IUER = 0x00;
+
+ Status = gBS->LocateProtocol (&DxePlatformSaPolicyGuid, NULL, &DxePlatformSaPolicy);
+
+ if (!EFI_ERROR(Status)) {
+ mIgdOpRegion.OpRegion->MBox3.IUER = DxePlatformSaPolicy->IgdConfig->IuerStatusVal;
+ }
+
+ ///
+ /// Initialize hardware state:
+ /// Set ASLS Register to the OpRegion physical memory address.
+ /// Set SWSCI register bit 15 to a "1" to activate SCI interrupts.
+ ///
+ IgdMmPci32 (R_SA_IGD_ASLS_OFFSET) = (UINT32) (UINTN) (mIgdOpRegion.OpRegion);
+ IgdMmPci16AndThenOr (R_SA_IGD_SWSCI_OFFSET, ~(BIT0), BIT15);
+
+ DwordData = IgdMmPci32 (R_SA_IGD_ASLS_OFFSET);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0x0,
+ SA_IGD_BUS,
+ SA_IGD_DEV,
+ SA_IGD_FUN_0,
+ R_SA_IGD_ASLS_OFFSET)),
+ 1,
+ &DwordData
+ );
+ DwordData = IgdMmPci32 (R_SA_IGD_SWSCI_OFFSET);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MmPciAddress (0x0,
+ SA_IGD_BUS,
+ SA_IGD_DEV,
+ SA_IGD_FUN_0,
+ R_SA_IGD_SWSCI_OFFSET)),
+ 1,
+ &DwordData
+ );
+ PchAcpiBaseAddress = MmPci16 (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_ACPI_BASE
+ ) &~BIT0;
+
+ ///
+ /// Find the CPU I/O Protocol. ASSERT if not found.
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiCpuIoProtocolGuid,
+ NULL,
+ (VOID **) &CpuIo
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ CpuIo->Io.Read (
+ CpuIo,
+ EfiCpuIoWidthUint16,
+ PchAcpiBaseAddress + PCH_TCO_BASE + R_PCH_TCO1_STS,
+ 1,
+ &Data16
+ );
+ ///
+ /// Clear the B_DMISCI_STS bit in R_TCO1_STS by writing a '1'.
+ ///
+ Data16 &= B_PCH_TCO1_STS_DMISCI;
+
+ CpuIo->Io.Write (
+ CpuIo,
+ EfiCpuIoWidthUint16,
+ PchAcpiBaseAddress + PCH_TCO_BASE + R_PCH_TCO1_STS,
+ 1,
+ &Data16
+ );
+
+ if (PchSeries == PchLp) {
+ ///
+ /// Clear the ACPI TCO status.
+ ///
+ Data32 = B_PCH_ACPI_GPE0_STS_127_96_TC0SCI;
+ CpuIo->Io.Write (
+ CpuIo,
+ EfiCpuIoWidthUint32,
+ (UINT64) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0_STS_127_96),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Enable ACPI TCO SCI's.
+ ///
+ CpuIo->Io.Read (
+ CpuIo,
+ EfiCpuIoWidthUint16,
+ (UINT64) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0_EN_127_96),
+ 1,
+ &Data16
+ );
+ Data16 |= B_PCH_ACPI_GPE0_EN_127_96_TC0SCI;
+ CpuIo->Io.Write (
+ CpuIo,
+ EfiCpuIoWidthUint16,
+ (UINT64) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0_EN_127_96),
+ 1,
+ &Data16
+ );
+ } else if (PchSeries == PchH) {
+ ///
+ /// Clear the ACPI TCO status.
+ ///
+ Data32 = B_PCH_ACPI_GPE0a_STS_TC0SCI;
+ CpuIo->Io.Write (
+ CpuIo,
+ EfiCpuIoWidthUint32,
+ (UINT64) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0a_STS),
+ 1,
+ &Data32
+ );
+
+ ///
+ /// Enable ACPI TCO SCI's.
+ ///
+ CpuIo->Io.Read (
+ CpuIo,
+ EfiCpuIoWidthUint16,
+ (UINT64) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0a_EN),
+ 1,
+ &Data16
+ );
+ Data16 |= B_PCH_ACPI_GPE0a_EN_TC0SCI;
+ CpuIo->Io.Write (
+ CpuIo,
+ EfiCpuIoWidthUint16,
+ (UINT64) (PchAcpiBaseAddress + R_PCH_ACPI_GPE0a_EN),
+ 1,
+ &Data16
+ );
+ }
+
+ ///
+ /// Install OpRegion / Software SCI protocol
+ ///
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gIgdOpRegionProtocolGuid,
+ &mIgdOpRegion,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+UpdateIgdOpRegionExitPmAuth (
+ VOID
+ )
+/**
+ Update Graphics OpRegion after PCI enumeration.
+
+ @param[in] void - None
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+
+ Bus = 0;
+ Device = 0;
+ Function = 0;
+
+ DEBUG ((EFI_D_INFO, "UpdateIgdOpRegionExitPmAuth\n"));
+
+ mIgdOpRegion.OpRegion->Header.PCON |= BIT8; //Set External Gfx Adapter field is valid
+ mIgdOpRegion.OpRegion->Header.PCON &= (UINT32) (~BIT7); //Assume No External Gfx Adapter
+
+ ///
+ /// Get all PCI IO protocols handles
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ ///
+ /// Get the PCI IO Protocol Interface corresponding to each handle
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Read the PCI configuration space
+ ///
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+
+ ///
+ /// Find the display controllers devices
+ ///
+ if (!EFI_ERROR (Status) && IS_PCI_DISPLAY (&Pci)) {
+ Status = PciIo->GetLocation (
+ PciIo,
+ &Segment,
+ &Bus,
+ &Device,
+ &Function
+ );
+
+ //
+ // Assumption: Onboard devices will be sits on Bus no 0, while external devices will be sits on Bus no > 0
+ //
+ if (!EFI_ERROR (Status) && (Bus > 0)) {
+ //External Gfx Adapter Detected and Available
+ DEBUG ((EFI_D_INFO, "PCON - External Gfx Adapter Detected and Available\n"));
+ mIgdOpRegion.OpRegion->Header.PCON |= BIT7;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Free any allocated buffers
+ ///
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ ///
+ /// Return final status
+ ///
+ return Status;
+} \ No newline at end of file
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.h b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.h
new file mode 100644
index 0000000..085c665
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Dxe/igdopregion.h
@@ -0,0 +1,281 @@
+/** @file
+ This is part of the implementation of an Intel Graphics drivers OpRegion /
+ Software SCI interface between system BIOS, ASL code, and Graphics drivers.
+
+ Supporting Specifiction: OpRegion / Software SCI SPEC 0.70
+
+ Acronyms:
+ IGD: Internal Graphics Device
+ NVS: ACPI Non Volatile Storage
+ OpRegion: ACPI Operational Region
+ VBT: Video BIOS Table (OEM customizable data)
+
+@copyright
+ Copyright (c) 1999 - 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
+**/
+#ifndef _IGD_OPREGION_H_
+#define _IGD_OPREGION_H_
+
+///
+/// Statements that include other header files.
+///
+#include "EdkIIGlueDxe.h"
+#include "EfiScriptLib.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+#include "SaAccess.h"
+#include "EfiMgmtModeRuntimeLib.h"
+#include "EfiApi.h"
+#include "pci22.h"
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include EFI_GUID_DEFINITION (DataHubRecords)
+#include EFI_PROTOCOL_DEFINITION (SaPlatformPolicy)
+
+#include EFI_PROTOCOL_CONSUMER (PciIo)
+#include EFI_PROTOCOL_CONSUMER (PciRootBridgeIo)
+
+#include EFI_PROTOCOL_DEPENDENCY (CpuIo)
+#include EFI_PROTOCOL_DEPENDENCY (DataHub)
+#include EFI_PROTOCOL_DEPENDENCY (SaGlobalNvsArea)
+#include EFI_PROTOCOL_CONSUMER (ExitPmAuth)
+
+///
+/// Driver Produced Protocol Prototypes
+///
+#include EFI_PROTOCOL_PRODUCER (IgdOpRegion)
+
+///
+///
+/// OpRegion (Miscellaneous) #defines.
+///
+/// OpRegion Header #defines.
+///
+#define HEADER_SIGNATURE "IntelGraphicsMem"
+#define HEADER_SIZE 0x2000
+#define HEADER_OPREGION_VER 0x0200
+#define HEADER_OPREGION_REV 0x00
+#define HEADER_MBOX_SUPPORT (HD_MBOX5 + HD_MBOX4 + HD_MBOX3 + HD_MBOX2 + HD_MBOX1)
+#define HEADER_MBOX_SUPPORT_MOBILE HEADER_MBOX_SUPPORT
+#define HEADER_MBOX_SUPPORT_DESKTOP HEADER_MBOX_SUPPORT
+#define HD_MBOX1 BIT0
+#define HD_MBOX2 BIT1
+#define HD_MBOX3 BIT2
+#define HD_MBOX4 BIT3
+#define HD_MBOX5 BIT4
+#define SVER_SIZE 32
+
+///
+/// OpRegion Mailbox 1 EQUates.
+///
+/// OpRegion Mailbox 3 EQUates.
+///
+#define ALS_ENABLE BIT0
+#define BLC_ENABLE BIT1
+#define BACKLIGHT_BRIGHTNESS 0xFF
+#define FIELD_VALID_BIT BIT31
+#define WORD_FIELD_VALID_BIT BIT15
+#define PFIT_ENABLE BIT2
+#define PFIT_OPRN_AUTO 0x00000000
+#define PFIT_OPRN_SCALING 0x00000007
+#define PFIT_OPRN_OFF 0x00000000
+#define PFIT_SETUP_AUTO 0
+#define PFIT_SETUP_SCALING 1
+#define PFIT_SETUP_OFF 2
+#define INIT_BRIGHT_LEVEL 0x64
+#define PFIT_STRETCH 6
+
+///
+/// GMCH PCI register access #defines.
+///
+#define IgdMmPci32(Register) MmPci32 (0, SA_IGD_BUS, SA_IGD_DEV, SA_IGD_FUN_0, Register)
+#define IgdMmPci16Or(Register, OrData) MmPci16Or (0, SA_IGD_BUS, SA_IGD_DEV, SA_IGD_FUN_0, Register, OrData)
+#define IgdMmPci16AndThenOr(Register, AndData, OrData) \
+ MmPci16AndThenOr ( \
+ 0, \
+ SA_IGD_BUS, \
+ SA_IGD_DEV, \
+ SA_IGD_FUN_0, \
+ Register, \
+ AndData, \
+ OrData \
+ )
+
+///
+/// Video BIOS / VBT #defines
+///
+#define OPTION_ROM_SIGNATURE 0xAA55
+#define VBIOS_LOCATION_PRIMARY 0xC0000
+
+#define VBT_SIGNATURE EFI_SIGNATURE_32 ('$', 'V', 'B', 'T')
+///
+/// Typedef stuctures
+///
+#pragma pack(1)
+typedef struct {
+ UINT16 Signature; /// 0xAA55
+ UINT8 Size512;
+ UINT8 Reserved[21];
+ UINT16 PcirOffset;
+ UINT16 VbtOffset;
+} INTEL_VBIOS_OPTION_ROM_HEADER;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct {
+ UINT32 Signature; /// "PCIR"
+ UINT16 VendorId; /// 0x8086
+ UINT16 DeviceId;
+ UINT16 Reserved0;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 Reserved1;
+} INTEL_VBIOS_PCIR_STRUCTURE;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct {
+ UINT8 HeaderSignature[20];
+ UINT16 HeaderVersion;
+ UINT16 HeaderSize;
+ UINT16 HeaderVbtSize;
+ UINT8 HeaderVbtCheckSum;
+ UINT8 HeaderReserved;
+ UINT32 HeaderOffsetVbtDataBlock;
+ UINT32 HeaderOffsetAim1;
+ UINT32 HeaderOffsetAim2;
+ UINT32 HeaderOffsetAim3;
+ UINT32 HeaderOffsetAim4;
+ UINT8 DataHeaderSignature[16];
+ UINT16 DataHeaderVersion;
+ UINT16 DataHeaderSize;
+ UINT16 DataHeaderDataBlockSize;
+ UINT8 CoreBlockId;
+ UINT16 CoreBlockSize;
+ UINT16 CoreBlockBiosSize;
+ UINT8 CoreBlockBiosType;
+ UINT8 CoreBlockReleaseStatus;
+ UINT8 CoreBlockHWSupported;
+ UINT8 CoreBlockIntegratedHW;
+ UINT8 CoreBlockBiosBuild[4];
+ UINT8 CoreBlockBiosSignOn[155];
+} VBIOS_VBT_STRUCTURE;
+#pragma pack()
+///
+/// Driver Private Function definitions
+///
+EFI_STATUS
+GetSVER (
+ OUT UINT8 *SVER
+ )
+/**
+ Set the SVER (system BIOS ID) string with the system BIOS build number.
+
+ @param[in] SVER String to populate with system BIOS build number.
+
+ @retval EFI_SUCCESS The SVER string is populated.
+ @exception EFI_UNSUPPORTED The SVER string is not populated.
+**/
+;
+
+EFI_STATUS
+GetStringFromToken (
+ IN EFI_GUID *ProducerGuid,
+ IN STRING_REF Token,
+ OUT CHAR16 **String
+ )
+/**
+ Acquire the string associated with the ProducerGuid and return it.
+
+ @param[in] ProducerGuid - The Guid to search the HII database for
+ @param[in] Token - The token value of the string to extract
+ @param[in] String - The string that is extracted
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND The requested string was not found
+**/
+;
+
+EFI_STATUS
+IgdOpRegionInit (
+ void
+ )
+/**
+ Graphics OpRegion / Software SCI driver installation function.
+
+ @param[in] void - None
+ @retval EFI_SUCCESS - The driver installed without error.
+ @retval EFI_ABORTED - The driver encountered an error and could not complete
+ installation of the ACPI tables.
+**/
+;
+
+EFI_STATUS
+ExtractDataFromHiiHandle (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN OUT UINT16 *ImageLength,
+ OUT UINT8 *DefaultImage,
+ OUT EFI_GUID *Guid
+ )
+/**
+ Extract information pertaining to the HiiHandle
+
+ @param[in] HiiHandle - Hii handle
+ @param[in] ImageLength - For input, length of DefaultImage;
+ For output, length of actually required
+ @param[in] DefaultImage - Image buffer prepared by caller
+ @param[in] Guid - Guid information about the form
+
+ @retval EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+ @retval EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
+ @retval EFI_SUCCESS - Successfully extract data from Hii database.
+**/
+;
+
+EFI_STATUS
+GetVBiosVbtExitPmAuth (
+ VOID
+ )
+/**
+ Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size).
+ The VBT (Video BIOS Table) is a block of customizable data that is built
+ within the video BIOS and edited by customers.
+
+ @retval EFI_SUCCESS - Video BIOS VBT information returned.
+ @exception EFI_UNSUPPORTED - Could not find VBT information (*VBiosVbtPtr = NULL).
+**/
+;
+
+EFI_STATUS
+UpdateIgdOpRegionExitPmAuth (
+ VOID
+ )
+/**
+ Update Graphics OpRegion after PCI enumeration.
+
+ @param[in] void - None
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+;
+#endif