diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Chipset/SystemAgent/SaInit/Dxe | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/SaInit/Dxe')
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, + >TMMADR + ); + + /// + /// 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 |