summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c')
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c1045
1 files changed, 1045 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c
new file mode 100644
index 0000000..436ca18
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c
@@ -0,0 +1,1045 @@
+/** @file
+ This file contains an implementation of the function call interfaces
+ required by the main TXT PEIM file. Hopefully, future platform porting
+ tasks will be mostly limited to modifying the functions in this file.
+
+@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 "TxtPeiLib.h"
+#include "TxtLibrary.h"
+
+EFI_GUID mTxtBiosAcmPeiFileGuid = PEI_BIOS_ACM_FILE_GUID;
+EFI_GUID mTxtApStartupPeiFileGuid = PEI_AP_STARTUP_FILE_GUID;
+EFI_GUID mCpuMicrocodeFileGuid = CPU_MICROCODE_FILE_GUID;
+#define EFI_PEI_PCI_CFG2_PPI_GUID \
+ { 0x57a449a, 0x1fdc, 0x4c06, 0xbf, 0xc9, 0xf5, 0x3f, 0x6a, 0x99, 0xbb, 0x92 }
+
+EFI_GUID gPeiPciCfgPpiInServiceTableGuid2 = EFI_PEI_PCI_CFG2_PPI_GUID;
+///
+/**
+ This routine initializes and collects all PPIs and data required
+ by the routines in this file.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] mPS - A pointer to the PEI Service Table
+
+ @exception EFI_UNSUPPORTED - If any of the required PPIs or data are unavailable
+ @retval EFI_SUCCESS - In all cases not listed above
+**/
+EFI_STATUS
+InitializeTxtPeiLib (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ IN EFI_PEI_SERVICES **mPS
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Make sure our pointers start life as NULL pointers
+ ///
+ pctx->PeiStall = NULL;
+ pctx->BiosAcmBase = NULL;
+ pctx->ApStartup = NULL;
+ pctx->McuStart = NULL;
+
+ ///
+ /// Initialize all pointers
+ ///
+ pctx->PeiServices = mPS;
+ pctx->CpuIoPpi = (**mPS).CpuIo;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiPciCfgPpiInServiceTableGuid2,
+ 0,
+ NULL,
+ (VOID **) &(pctx->PciCfgPpi)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiStallPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &(pctx->PeiStall)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Find TxtInfoHob by platfrom code
+ ///
+ Status = CreateTxtInfoHob (pctx);
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: TXT Info Hob not found.\n"));
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Print out the TxtInfo HOB if TXT_DEBUG_INFO is set
+ ///
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtInfoHob passed from platform as:\n"));
+ DEBUG ((EFI_D_INFO, "TXTPEI: ChipsetIsTxtCapable = %x\n", pctx->Hob->Data.ChipsetIsTxtCapable));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtMode = %x\n", pctx->Hob->Data.TxtMode));
+ DEBUG ((EFI_D_INFO, "TXTPEI: PmBase = %x\n", pctx->Hob->Data.PmBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: SinitMemorySize = %x\n", pctx->Hob->Data.SinitMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtHeapMemorySize = %x\n", pctx->Hob->Data.TxtHeapMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtDprMemoryBase = %x\n", pctx->Hob->Data.TxtDprMemoryBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtDprMemorySize = %x\n", pctx->Hob->Data.TxtDprMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: BiosAcmBase = %x\n", pctx->Hob->Data.BiosAcmBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: BiosAcmSize = %x\n", pctx->Hob->Data.BiosAcmSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: McuUpdateDataAddr = %x\n", pctx->Hob->Data.McuUpdateDataAddr));
+ DEBUG ((EFI_D_INFO, "TXTPEI: SinitAcmBase = %x\n", pctx->Hob->Data.SinitAcmBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: SinitAcmSize = %x\n", pctx->Hob->Data.SinitAcmSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TgaSize = %x\n", pctx->Hob->Data.TgaSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtLcpPdBase = %x\n", pctx->Hob->Data.TxtLcpPdBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtLcpPdSize = %x\n", pctx->Hob->Data.TxtLcpPdSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: Flags = %x\n", pctx->Hob->Data.Flags));
+
+ ///
+ /// Check if platform specify BIOS ACM addrss by itself, BIOS ACM address must be 4K alignment in FLASH address space
+ ///
+ if (pctx->Hob->Data.BiosAcmBase != 0) {
+ DEBUG ((EFI_D_INFO, "TXTPEI: Customized BIOS ACM location at %x\n", pctx->Hob->Data.BiosAcmBase));
+ ///
+ /// Check BIOS ACM is 4K alignment or not
+ ///
+ if ((pctx->Hob->Data.BiosAcmBase & 0xFFF) != 0) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: Customized BIOS ACM is not 4K aligned, force TxtMode=0 and unloaded!!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Get BIOS ACM base from TxtInfoHob provided by platform code
+ ///
+ pctx->BiosAcmBase = (ACM_HEADER *) (UINT32) pctx->Hob->Data.BiosAcmBase;
+ } else {
+ ///
+ /// Get BIOS ACM by seaching PEI firmware volume
+ ///
+ Status = FindBiosAcmInVolume (pctx, (UINT32 **) &pctx->BiosAcmBase);
+
+ ///
+ /// BIOS ACM not found, disable TXT and return EFI_UNLOAD_IMAGE
+ ///
+ if (((pctx->BiosAcmBase) == 0) || (Status == EFI_NOT_FOUND)) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BIOS ACM not found, force TxtMode=0 and unloaded!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: Found BIOS ACM location at %x\n", pctx->BiosAcmBase));
+
+ ///
+ /// Check BIOS ACM is 4K alignment, if not disable TXT and return EFI_UNLOAD_IMAGE
+ ///
+ if (((UINT32) pctx->BiosAcmBase & 0xFFF) != 0) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BIOS ACM is not 4K aligned, force TxtMode=0 and unloaded!!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+ }
+ ///
+ /// Check ACM is matched to chipset or not, if not, disable TXT and return EFI_UNLOAD_IMAGE
+ ///
+ if (!CheckTxtAcmMatch (pctx, pctx->BiosAcmBase)) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BIOS ACM is not matched to chipset!! Force TxtMode=0 and unloaded!!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ pctx->BiosAcmSize = (pctx->BiosAcmBase->Size) << 2;
+
+ Status = FindApStartupInVolume (pctx, (UINT32 **) &(pctx->ApStartup));
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: AP Startup code not found.\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: Found AP init code at %x\n", pctx->ApStartup));
+
+ ///
+ /// Check if platform specify MCU addrss by itself
+ ///
+ if (pctx->Hob->Data.McuUpdateDataAddr != 0) {
+ DEBUG ((EFI_D_INFO, "Customized MCU location at %x\n", pctx->Hob->Data.McuUpdateDataAddr));
+ pctx->McuStart = (UINT32 *) (UINTN) pctx->Hob->Data.McuUpdateDataAddr;
+ } else {
+ ///
+ /// Find microcode update by searching PEI FV
+ ///
+ Status = FindMcuInVolume (pctx, (UINT32 **) &(pctx->McuStart));
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: MCU not found.\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: Found MCU at %x\n", pctx->McuStart));
+ }
+ ///
+ /// Initialize local APIC
+ ///
+ if ((((AsmReadMsr64 (MSR_IA32_APIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10)) {
+ AsmWriteMsr64 (EFI_MSR_EXT_XAPIC_SVR, 0x1FF);
+ } else {
+ ///
+ /// Determine address of Local APIC
+ ///
+ pctx->Ia32ApicBase = ((UINT32) AsmReadMsr64 (MSR_IA32_APIC_BASE)) & BASE_ADDR_MASK;
+ *(UINT32 *) (pctx->Ia32ApicBase + APIC_SPURIOUS_VECTOR_REGISTER) = 0x1FF;
+ }
+ ///
+ /// Initialize TxtInfoHob fields
+ ///
+ pctx->Hob->Data.BiosAcmBase = (UINTN) pctx->BiosAcmBase;
+ pctx->Hob->Data.BiosAcmSize = (UINTN) pctx->BiosAcmSize;
+ pctx->Hob->Data.McuUpdateDataAddr = (UINTN) pctx->McuStart;
+
+ ///
+ /// Make sure none of our pointers are still NULL
+ ///
+ if (!(pctx->PeiStall && pctx->BiosAcmBase && pctx->ApStartup && pctx->McuStart)) {
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Determines whether or not the current processor is TXT Capable.
+
+ @retval TRUE - If the current processor supports TXT
+ @retval FALSE - If the current processor does not support TXT
+**/
+BOOLEAN
+IsTxtProcessor (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+
+ AsmCpuid (1, &CpuidRegs.RegEax, &CpuidRegs.RegEbx, &CpuidRegs.RegEcx, &CpuidRegs.RegEdx);
+
+ return (CpuidRegs.RegEcx & B_CPUID_VERSION_INFO_ECX_SME) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not the current chipset is TXT Capable.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the current chipset supports TXT
+ @retval FALSE - If the current chipset doesn't supports TXT
+**/
+BOOLEAN
+IsTxtChipset (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ BOOLEAN TxtCapable;
+ UINT32 Data32;
+
+ TxtCapable = FALSE;
+ Data32 = CheckSmxCapabilities();
+
+ if ((Data32 & BIT0) != 0) {
+ TxtCapable = TRUE;
+ DEBUG ((EFI_D_INFO, "Platform/PCH - TXT supported\n"));
+ } else {
+ TxtCapable = FALSE;
+ DEBUG ((EFI_D_INFO, "Platform/PCH - TXT not supported!!!\n"));
+ }
+
+ return TxtCapable;
+}
+
+/**
+ Determines whether TXT is enabled by platform setting
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If TXT is enabled by platform setting
+ @retval FALSE - If TXT is disabled by platform setting
+**/
+BOOLEAN
+IsTxtEnabled (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ if (pctx->Hob == 0) {
+ return FALSE;
+ }
+
+ return (BOOLEAN) (pctx->Hob->Data.TxtMode);
+}
+
+/**
+ Determines ACM is matched to chipset or not
+
+ @param[in] pctx - Point to TXT_PEI_LIB_CONTEXT structure
+ @param[in] BiosAcmBase - A pointer to BIOS ACM location
+
+ @retval TRUE - BIOS ACM is matched to chipset
+ @retval FALSE - BIOS ACM is NOT matched to chipset
+**/
+BOOLEAN
+CheckTxtAcmMatch (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ IN ACM_HEADER *BiosAcmBase
+ )
+{
+ BOOLEAN ChipsetIsProduction;
+ BOOLEAN BiosAcmIsProduction;
+
+ if (BiosAcmBase == NULL) {
+ return FALSE;
+
+ }
+ ///
+ /// Initializing ChipsetIsProduction default value
+ ///
+ ChipsetIsProduction = (*(UINT32 *) (TXT_PUBLIC_BASE + 0x200) & BIT31) ? TRUE : FALSE;
+
+ ///
+ /// Check ACM is production or not
+ ///
+ BiosAcmIsProduction = (BiosAcmBase->ModuleID & BIT31) ? FALSE : TRUE;
+
+ return ChipsetIsProduction == BiosAcmIsProduction;
+}
+
+/**
+ Create TXT Info HOB
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - If TXT Info Hob is found
+ @retval EFI_NOT_FOUND - If TXT Info Hob is not found
+**/
+EFI_STATUS
+CreateTxtInfoHob (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ EFI_STATUS Status;
+ PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicy;
+ TXT_INFO_HOB *TxtInfoHob;
+
+ TxtInfoHob = NULL;
+
+ ///
+ /// Locate TPM Initialized Ppi to determine TPM is present and initialized properly.
+ ///
+ Status = PeiServicesLocatePpi (
+ &gPeiCpuPlatformPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &CpuPlatformPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Create hob for storing TXT data
+ ///
+ Status = (*(pctx->PeiServices))->CreateHob (
+ pctx->PeiServices,
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof (TXT_INFO_HOB),
+ (VOID **) &TxtInfoHob
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ pctx->Hob = TxtInfoHob;
+ TxtInfoHob->EfiHobGuidType.Name = gTxtInfoHobGuid;
+
+ ///
+ /// Initiate Txt Info Hob
+ ///
+ ZeroMem (&(TxtInfoHob->Data), sizeof (TXT_INFO_DATA));
+
+ TxtInfoHob->Data.ChipsetIsTxtCapable = IsTxtChipset (pctx);
+ if (CpuPlatformPolicy->CpuConfig->Txt == 1) {
+ TxtInfoHob->Data.TxtMode = 1;
+ }
+ TxtInfoHob->Data.PmBase = MmioRead32 (
+ MmPciAddress (0,
+ PCI_BUS_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_ACPI_BASE)
+ ) &~1;
+
+ TxtInfoHob->Data.SinitMemorySize = CpuPlatformPolicy->SecurityConfig->TxtConfig->SinitMemorySize;
+ TxtInfoHob->Data.TxtHeapMemorySize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtHeapMemorySize;
+ TxtInfoHob->Data.TxtDprMemoryBase = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtDprMemoryBase;
+ TxtInfoHob->Data.TxtDprMemorySize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtDprMemorySize;
+ TxtInfoHob->Data.BiosAcmBase = CpuPlatformPolicy->SecurityConfig->TxtConfig->BiosAcmBase;
+ TxtInfoHob->Data.BiosAcmSize = CpuPlatformPolicy->SecurityConfig->TxtConfig->BiosAcmSize;
+ TxtInfoHob->Data.McuUpdateDataAddr = CpuPlatformPolicy->SecurityConfig->TxtConfig->McuUpdateDataAddr;
+ TxtInfoHob->Data.TgaSize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TgaSize;
+ TxtInfoHob->Data.TxtLcpPdBase = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtLcpPdBase;
+ TxtInfoHob->Data.TxtLcpPdSize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtLcpPdSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Determines whether or not the platform has executed an TXT launch by
+ examining the TPM Establishment bit.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TPM establishment bit is asserted.
+ @retval FALSE - If the TPM establishment bit is unasserted.
+**/
+BOOLEAN
+IsEstablishmentBitAsserted (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 Access;
+ UINT16 TimeOutCount;
+
+ ///
+ /// Set TPM.ACCESS polling timeout about 750ms
+ ///
+ TimeOutCount = TPM_TIME_OUT;
+ do {
+ ///
+ /// Read TPM status register
+ ///
+
+ Access = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TPM_STATUS_REG_ADDRESS
+ );
+
+ ///
+ /// if TPM.Access == 0xFF, TPM is not present
+ ///
+ if (Access == 0xFF) {
+ return FALSE;
+ }
+ ///
+ /// Check tpmRegValidSts bit before checking establishment bit
+ ///
+ if (((pctx->PeiStall) != NULL) && ((Access & 0x80) != 0x80)) {
+ ///
+ /// Delay 1ms
+ ///
+ pctx->PeiStall->Stall (pctx->PeiServices, pctx->PeiStall, 1000);
+ } else {
+ ///
+ /// tpmRegValidSts set, we can check establishment bit now.
+ ///
+ break;
+ }
+
+ TimeOutCount--;
+ } while (TimeOutCount != 0);
+ ///
+ /// if tpmRegValidSts is not set, TPM is not usable
+ ///
+ if ((Access & 0x80) != 0x80) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: TPM Valid Status is not set!! TPM.ACCESS=%x\n", Access));
+ ASSERT (TRUE);
+ EFI_DEADLOOP ();
+ }
+ ///
+ /// The bit we're interested in uses negative logic:
+ /// If bit 0 == 1 then return False
+ /// Else return True
+ ///
+ return (Access & 0x1) ? FALSE : TRUE;
+}
+
+/**
+ Determines whether or not the platform has encountered an error during
+ a sleep or power-off state.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TXT_WAKE_ERROR bit is asserted.
+ @retval FALSE - If the TXT_WAKE_ERROR bit is unasserted.
+**/
+BOOLEAN
+IsTxtWakeError (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 Ests;
+
+ ///
+ /// Read TXT.ESTS register
+ ///
+ Ests = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_ERROR_STATUS_REG_OFF
+ );
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: TXT.ESTS=%x\n", Ests));
+
+ return (Ests & (0x1 << 6)) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not the platform memory has been locked
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If memroy is locked
+ @retval FALSE - If memory is unlocked
+**/
+BOOLEAN
+IsMemoryLocked (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT32 CpuMemLockStatus;
+
+ ///
+ /// Check status register for now.
+ ///
+ CpuMemLockStatus = pctx->CpuIoPpi->MemRead32 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_E2STS_REG_OFF
+ );
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: CPU_UNCORE_MEMLOCK_STATUS=%x\n", CpuMemLockStatus));
+ ///
+ /// if BLOCK_MEM_STS (BIT2) is set to 1, memory is in unlock.
+ ///
+ return (CpuMemLockStatus & TXT_BLOCK_MEM_STS) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not POISON bit is set in status register
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TXT_WAKE_ERROR bit is asserted.
+ @retval FALSE - If the TXT_WAKE_ERROR bit is unasserted.
+**/
+BOOLEAN
+IsTxtResetSet (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 Ests;
+
+ ///
+ /// Read TXT.ESTS register
+ ///
+ Ests = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_ERROR_STATUS_REG_OFF
+ );
+
+ return (Ests & (0x1 << 0)) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not SECRETS.STS bit is set in E2STS status register
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the LT.SECRETS.STS bit is asserted.
+ @retval FALSE - If the LT.SECRETS.STS bit is unasserted.
+**/
+BOOLEAN
+IsTxtSecretsSet (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 E2sts;
+
+ ///
+ /// Read TXT.E2STS register
+ ///
+ E2sts = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_E2STS_REG_OFF
+ );
+
+ return (E2sts & TXT_SECRETS_STS) ? TRUE : FALSE;
+}
+
+/**
+ Determines presence of TPM in system
+
+ @param[in] pctx - Point to TXT_PEI_LIB_CONTEXT structure
+ @param[in] TxtPeiCtx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - If the TPM is present.
+ @retval EFI_NOT_FOUND - If the TPM is not present.
+**/
+EFI_STATUS
+IsTpmPresent (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ EFI_STATUS Status;
+ VOID *TpmInitialize;
+
+ ///
+ /// Locate TPM Initialized Ppi to determine TPM is present and initialized properly.
+ ///
+ Status = PeiServicesLocatePpi (
+ &gPeiTpmInitializedPpiGuid,
+ 0,
+ NULL,
+ &TpmInitialize
+ );
+ if (EFI_ERROR (Status)) {
+ ///
+ /// TPM initiated failed
+ ///
+ pctx->Hob->Data.Flags |= TPM_INIT_FAILED;
+ }
+
+ return Status;
+}
+
+/**
+ Clear Sleep Type register.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Always
+**/
+EFI_STATUS
+ClearSlpTyp (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT32 Pm1Addr;
+ UINT32 Pm1Value;
+
+ ///
+ /// Make address for PM1_CNT
+ ///
+ Pm1Addr = ((UINT32) pctx->Hob->Data.PmBase) + 4;
+
+ ///
+ /// Read 32-bits from PM1_CNT
+ ///
+ Pm1Value = IoRead32 ((UINTN) Pm1Addr);
+
+ ///
+ /// Clear SLP_TYP bits 10-12
+ ///
+ Pm1Value = Pm1Value & 0xffffe3ff;
+ IoWrite32 (
+ (UINTN) Pm1Addr,
+ (UINT32) (Pm1Value)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Searches PEI firemare volume (FV_BB) for file containig BIOS ACM.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] BiosAcBase - A pointer to pointer to variable to hold found address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindBiosAcmInVolume (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **BiosAcBase
+ )
+{
+ EFI_STATUS Status;
+
+ Status = FindModuleInFlash (pctx, &mTxtBiosAcmPeiFileGuid, BiosAcBase);
+
+ ///
+ /// If BIOS ACM is not found - don't hang system. Assume that TXT
+ /// must be disabled.
+ ///
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (((((UINT32) (*BiosAcBase)) & 0xFFF) == 0) ? TRUE : FALSE);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Searches PEI firmware volume (FV_BB) for file containig AP Startup code
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] ApStartupBase - A pointer to pointer to variable to hold address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindApStartupInVolume (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **ApStartupBase
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID PeiBiosApStartupFileGuid;
+ BOOLEAN GoodPlacement;
+
+ PeiBiosApStartupFileGuid = mTxtApStartupPeiFileGuid;
+ Status = FindModuleInFlash (pctx, &PeiBiosApStartupFileGuid, ApStartupBase);
+ ///
+ /// If AP Startup code is not found - don't hang system. Assume that TXT
+ /// must be disabled.
+ ///
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (((((UINT32) (*ApStartupBase)) & 0xFFF) == 0) ? TRUE : FALSE);
+
+ GoodPlacement = (BOOLEAN) (((UINT32) (*ApStartupBase) >= 0xFFFE0000) && ((UINT32) (*ApStartupBase) <= 0xFFFFF000));
+
+ ASSERT (GoodPlacement);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Searches PEI firmware volume (FV_BB) for offset of currently loaded MCU patch
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] McuBase - A pointer to pointer to variable to hold found offset
+ @param[in] address.
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindMcuInVolume (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **McuBase
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID MicrocodeGuid;
+ MSR_REGISTER Reg;
+ UINT32 PlatformId;
+ UINT32 McuRevision;
+ EFI_CPUID_REGISTER CpuidRegs;
+ MCU *McuAddr;
+ UINT8 *i;
+ UINT8 *j;
+ UINT8 *b;
+ UINT32 c;
+ //(AMI_CHG+)>
+ UINT32 MicroCodeFfsMaxSize;
+ EFI_FFS_FILE_HEADER *MicroCodeFfs;
+ UINT8 *McuFfsAddress;
+ MicroCodeFfs = NULL;
+ //<(AMI_CHG+)
+ McuAddr = NULL;
+
+ McuRevision = 0;
+ MicrocodeGuid = mCpuMicrocodeFileGuid;
+ Status = FindModuleInFlash (pctx, &MicrocodeGuid, (UINT32 **) &McuAddr);
+ ///
+ /// If MCU update is not found - don't hang system. Assume that TXT
+ /// must be disabled.
+ ///
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //(AMI_CHG+)>
+ McuFfsAddress = (UINT8 *) McuAddr;
+ MicroCodeFfs = (EFI_FFS_FILE_HEADER *)(McuFfsAddress - sizeof (EFI_FFS_FILE_HEADER));
+ MicroCodeFfsMaxSize = (UINT32)MicroCodeFfs->Size[2]*0x10000 + (UINT32)MicroCodeFfs->Size[1]*0x100 + (UINT32)MicroCodeFfs->Size[0];
+ DEBUG ((EFI_D_ERROR, "TXTPEI: MicroCodeFfsMaxSize = %X\n", MicroCodeFfsMaxSize));
+ //<(AMI_CHG+)
+ ///
+ /// MCU base address has been found. Find exact address of MCU
+ /// loaded in BSP
+ ///
+ Reg.Qword = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
+ PlatformId = (Reg.Dwords.High >> (PLATFORM_ID_SHIFT - 32)) & PLATFORM_ID_MASK;
+
+ AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
+
+ AsmCpuid (1, &CpuidRegs.RegEax, &CpuidRegs.RegEbx, &CpuidRegs.RegEcx, &CpuidRegs.RegEdx);
+
+ Reg.Qword = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
+
+ McuRevision = Reg.Dwords.High;
+
+ ///
+ /// if BSP MCU is not loaded before. Return EFI_NOT_FOUND
+ /// This is pre-requisit.
+ ///
+ if (McuRevision == 0) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BSP microcode is not loaded!! TXT aborted!\n"));
+ return EFI_NOT_FOUND;
+ }
+ //(AMI_CHG+)>
+ //for (i = (UINT8 *) McuAddr; i < ((UINT8 *) McuAddr) + 0x10000; i = i + 0x400) {
+ for (i = (UINT8 *) McuAddr; i < ((UINT8 *) McuAddr) + MicroCodeFfsMaxSize; i = i + 0x400) {
+ //<(AMI_CHG+)
+ if (((MCU *) i)->revision != McuRevision) {
+ continue;
+ }
+
+ if (!(((MCU *) i)->procFlags & (UINT32) LShiftU64 (1, PlatformId))) {
+ continue;
+ }
+
+ if ((((MCU *) i)->signature) == CpuidRegs.RegEax) {
+ *McuBase = (UINT32 *) i;
+ return EFI_SUCCESS;
+ }
+
+ if ((((MCU *) i)->dataSize) == 0) {
+ continue;
+ }
+
+ if ((((MCU *) i)->dataSize + sizeof (MCU)) >= (((MCU *) i)->totalSize)) {
+ continue;
+ }
+ ///
+ /// Extended signature table exists.
+ ///
+ b = i + (((MCU *) i)->dataSize);
+ ///
+ /// Base of EST table
+ ///
+ c = ((EST *) b)->count;
+ ///
+ /// Count of entries
+ ///
+ b += sizeof (EST);
+ ///
+ /// Base of PSS table entries
+ ///
+ for (j = b; j < b + (c * sizeof (PSS)); j = j + sizeof (PSS)) {
+ if ((((PSS *) j)->signature) == CpuidRegs.RegEax) {
+ *McuBase = (UINT32 *) i;
+ return EFI_SUCCESS;
+ }
+ }
+
+ continue;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Searches PEI firmware volume (FV_BB) for the file with specified GUID through pGuid
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] Guid - A pointer GUID
+ @param[in] Module - A pointer to pointer to variable to hold address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI ERROR - If address has not been found
+**/
+EFI_STATUS
+FindModuleInFlash (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ IN EFI_GUID *Guid,
+ OUT UINT32 **Module
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FFS_FILE_HEADER *FfsFile;
+ EFI_STATUS Status;
+ UINTN Instance;
+
+ Instance = BFV;
+
+ while (TRUE) {
+ Status = (*(pctx->PeiServices))->FfsFindNextVolume (pctx->PeiServices, Instance, &FvHeader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FfsFile = NULL;
+ ///
+ /// Start new search in volume
+ ///
+ while (TRUE) {
+ Status = (*(pctx->PeiServices))->FfsFindNextFile (pctx->PeiServices, EFI_FV_FILETYPE_RAW, FvHeader, &FfsFile);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ if (CompareGuid (&(FfsFile->Name), Guid)) {
+ *Module = (UINT32 *) ((UINT8 *) FfsFile + sizeof (EFI_FFS_FILE_HEADER));
+ return EFI_SUCCESS;
+ }
+ }
+
+ Instance += 1;
+ }
+}
+
+/**
+ Initializes values passed to AP
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+**/
+VOID
+PrepareApParams (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT32 TxtPublicSpace;
+
+ TxtPublicSpace = TXT_PUBLIC_BASE;
+
+ *(UINT32 *) (TxtPublicSpace + BIOACM_ADDR) = (UINT32) (pctx->BiosAcmBase);
+
+ *(UINT32 *) (TxtPublicSpace + MCU_BASE_ADDR) = (UINT32) (pctx->McuStart);
+
+ *(UINT32 *) (TxtPublicSpace + APINIT_ADDR) = (UINT32) (pctx->ApStartup);
+
+ *(UINT32 *) (TxtPublicSpace + SEMAPHORE) = 0;
+
+}
+
+/**
+ Returns CPU count
+
+ @retval Number of CPUs
+**/
+UINT32
+GetCpuCount (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+ AsmCpuid (1, &CpuidRegs.RegEax, &CpuidRegs.RegEbx, &CpuidRegs.RegEcx, &CpuidRegs.RegEdx);
+ return CpuidRegs.RegEbx >> 16;
+}
+
+/**
+ Invokes the SCLEAN function from the TXT BIOS ACM.
+ 1. Clearing of sleep type is necessary because SCLEAN destroys memory
+ context, so S3 after it is run and system is reset is impossible. We
+ do it here since there is no any indication that can sustain reset
+ for any other module to do it on our behalf.
+ 2. APs are initialized before calling of SCLEAN
+ 3. SCLEAN function is invoked.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+DoSclean (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ ClearSlpTyp (pctx);
+
+ PrepareApParams (pctx);
+#ifdef BOOT_GUARD_SUPPORT_FLAG
+#if BOOT_GUARD_SUPPORT_FLAG == 1
+ //
+ // Disable PBET before send IPI to APs
+ //
+ StopPbeTimer ();
+#endif
+#endif
+
+ LaunchBiosAcmSclean ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unlock memory when security is set and TxT is not enabled
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Complete memory unlock
+ @exception EFI_UNSUPPORTED - CPU doesn't support TxT.
+**/
+EFI_STATUS
+UnlockMemory (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ BOOLEAN EstablishmentBitAsserted;
+
+ EstablishmentBitAsserted = IsEstablishmentBitAsserted (pctx);
+
+ ///
+ /// Need to read FED40000 before unlocking memory
+ ///
+ if (!EstablishmentBitAsserted) {
+ DEBUG ((EFI_D_INFO, "TXTPEI::Unlock memory\n"));
+ AsmWriteMsr64 (0x2e6, 0);
+ } else {
+ ///
+ /// Lunch SCLEAN if wake error bit is set.
+ ///
+ if (IsTxtWakeError (pctx)) {
+ ///
+ /// If TXTRESET is set , we must clean TXTRESET bit otherwise SCLEAN
+ /// will fail
+ ///
+ if (IsTxtResetSet (pctx)) {
+ DoGlobalReset ();
+ }
+
+ if ((pctx->BiosAcmBase == 0) || (pctx->ApStartup == 0) || (pctx->McuStart == 0)) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Setup and Launch SCLEAN
+ ///
+ DEBUG ((EFI_D_INFO, "TXTPEI::Entering SCLEAN to unlock memory\n"));
+ DoSclean (pctx);
+
+ ///
+ /// Reset platform - performed by DoSclean, should not return to execute the following dead looping
+ ///
+ EFI_DEADLOOP ();
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}