alder_lake_bios/Intel/AlderLake/ClientOneSiliconPkg/Cpu/LibraryPrivate/PeiTxtLib/TxtPeiLib.c

1261 lines
37 KiB
C

/** @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
INTEL CONFIDENTIAL
Copyright 2014 - 2020 Intel Corporation.
The source code contained or described herein and all documents related to the
source code ("Material") are owned by Intel Corporation or its suppliers or
licensors. Title to the Material remains with Intel Corporation or its suppliers
and licensors. The Material may contain trade secrets and proprietary and
confidential information of Intel Corporation and its suppliers and licensors,
and is protected by worldwide copyright and trade secret laws and treaty
provisions. No part of the Material may be used, copied, reproduced, modified,
published, uploaded, posted, transmitted, distributed, or disclosed in any way
without Intel's prior express written permission.
No license under any patent, copyright, trade secret or other intellectual
property right is granted to or conferred upon you by disclosure or delivery
of the Materials, either expressly, by implication, inducement, estoppel or
otherwise. Any license under such intellectual property rights must be
express and approved by Intel in writing.
Unless otherwise agreed by Intel in writing, you may not remove or alter
this notice or any other notice embedded in Materials by Intel or
Intel's suppliers or licensors in any way.
This file contains an 'Intel Peripheral Driver' and is 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.
@par Specification
**/
#include <Library/TxtPeiLib.h>
#include <Library/CpuCommonLib.h>
#include <Library/TxtLib.h>
#include <Library/ConfigBlockLib.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Register/Cpuid.h>
#include <Register/Msr.h>
#include <PchResetPlatformSpecific.h>
#include <Library/PmcLib.h>
#include <Library/LocalApicLib.h>
#include <Ppi/MpServices2.h>
#include <Register/CommonMsr.h>
/**
This routine initializes and collects all PPIs and data required
by the routines in this file.
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@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_INFO_HOB **TxtInfoHob
)
{
EFI_STATUS Status;
UINT32 Ia32ApicBase;
///
/// Find TxtInfoHob by platform code
///
Status = CreateTxtInfoHob (TxtInfoHob);
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_ERROR, "TXTPEI: TXT Info Hob not found or TXT is not supported.\n"));
return EFI_UNSUPPORTED;
}
///
/// Print out the TxtInfo HOB if TXT_DEBUG_INFO is set
///
DEBUG ((DEBUG_INFO, "TXTPEI: TxtInfoHob passed from platform as:\n"));
DEBUG ((DEBUG_INFO, "TXTPEI: ChipsetIsTxtCapable = %x\n", (*TxtInfoHob)->Data.ChipsetIsTxtCapable));
DEBUG ((DEBUG_INFO, "TXTPEI: ProcessorIsTxtCapable = %x\n", (*TxtInfoHob)->Data.ProcessorIsTxtCapable));
DEBUG ((DEBUG_INFO, "TXTPEI: TxtMode = %x\n", (*TxtInfoHob)->Data.TxtMode));
DEBUG ((DEBUG_INFO, "TXTPEI: TxtAcheckRequest = %x\n", (*TxtInfoHob)->Data.TxtAcheckRequest));
DEBUG ((DEBUG_INFO, "TXTPEI: ResetAux = %x\n", (*TxtInfoHob)->Data.ResetAux));
DEBUG ((DEBUG_INFO, "TXTPEI: AcpiBase = %x\n", (*TxtInfoHob)->Data.AcpiBase));
DEBUG ((DEBUG_INFO, "TXTPEI: SinitMemorySize = %x\n", (*TxtInfoHob)->Data.SinitMemorySize));
DEBUG ((DEBUG_INFO, "TXTPEI: TxtHeapMemorySize = %x\n", (*TxtInfoHob)->Data.TxtHeapMemorySize));
DEBUG ((DEBUG_INFO, "TXTPEI: TxtDprMemoryBase = %x\n", (*TxtInfoHob)->Data.TxtDprMemoryBase));
DEBUG ((DEBUG_INFO, "TXTPEI: TxtDprMemorySize = %x\n", (*TxtInfoHob)->Data.TxtDprMemorySize));
DEBUG ((DEBUG_INFO, "TXTPEI: BiosAcmBase = %x\n", (*TxtInfoHob)->Data.BiosAcmBase));
DEBUG ((DEBUG_INFO, "TXTPEI: BiosAcmSize = %x\n", (*TxtInfoHob)->Data.BiosAcmSize));
DEBUG ((DEBUG_INFO, "TXTPEI: SinitAcmBase = %x\n", (*TxtInfoHob)->Data.SinitAcmBase));
DEBUG ((DEBUG_INFO, "TXTPEI: SinitAcmSize = %x\n", (*TxtInfoHob)->Data.SinitAcmSize));
DEBUG ((DEBUG_INFO, "TXTPEI: TgaSize = %x\n", (*TxtInfoHob)->Data.TgaSize));
DEBUG ((DEBUG_INFO, "TXTPEI: TxtLcpPdBase = %x\n", (*TxtInfoHob)->Data.TxtLcpPdBase));
DEBUG ((DEBUG_INFO, "TXTPEI: TxtLcpPdSize = %x\n", (*TxtInfoHob)->Data.TxtLcpPdSize));
DEBUG ((DEBUG_INFO, "TXTPEI: Flags = %x\n", (*TxtInfoHob)->Data.Flags));
DEBUG ((DEBUG_INFO, "TXTPEI: ApStartupBase = %x\n", (*TxtInfoHob)->Data.ApStartupBase));
///
/// Check if platform specify BIOS ACM address by itself, BIOS ACM address must be 4K alignment in FLASH address space
///
if ((*TxtInfoHob)->Data.BiosAcmBase != 0) {
///
/// Check BIOS ACM is 4K alignment or not
///
if (((*TxtInfoHob)->Data.BiosAcmBase & 0xFFF) != 0) {
DEBUG ((DEBUG_WARN, "TXTPEI: BIOS ACM is not 4K aligned, force TxtMode=0 and unloaded!!\n"));
(*TxtInfoHob)->Data.TxtMode = 0;
return EFI_UNSUPPORTED;
}
} else {
DEBUG ((DEBUG_ERROR, "TXTPEI: BIOS ACM not found, force TxtMode=0 and unloaded!\n"));
(*TxtInfoHob)->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 ((ACM_HEADER*)(UINTN)((*TxtInfoHob)->Data.BiosAcmBase))) {
DEBUG ((DEBUG_ERROR, "TXTPEI: BIOS ACM is not matched to chipset!! Force TxtMode=0 and unloaded!!\n"));
(*TxtInfoHob)->Data.TxtMode = 0;
return EFI_UNSUPPORTED;
}
/// Read ACM size from ACM header
(*TxtInfoHob)->Data.BiosAcmSize = ((ACM_HEADER*)(UINTN)((*TxtInfoHob)->Data.BiosAcmBase))->Size << 2;
///
/// Check if platform specify AP starup address
///
if ((*TxtInfoHob)->Data.ApStartupBase == 0) {
///
/// Get AP startup base from TxtInfoHob provided by platform code
///
DEBUG ((DEBUG_INFO, "TXTPEI: AP Startup location not found\n"));
}
///
/// Initialize local APIC
///
if ((((AsmReadMsr64 (MSR_IA32_APIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10)) {
AsmWriteMsr64 (MSR_IA32_X2APIC_SIVR, 0x1FF);
} else {
///
/// Determine address of Local APIC
///
Ia32ApicBase = ((UINT32) AsmReadMsr64 (MSR_IA32_APIC_BASE)) & BASE_ADDR_MASK;
*(UINT32 *) (Ia32ApicBase + APIC_SPURIOUS_VECTOR_REGISTER) = 0x1FF;
}
///
/// Make sure none of our pointers are still NULL
///
if (!((*TxtInfoHob)->Data.BiosAcmBase)) {
(*TxtInfoHob)->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
)
{
CPUID_VERSION_INFO_ECX Ecx;
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &Ecx.Uint32, NULL);
return (BOOLEAN) (Ecx.Bits.SMX == 1);
}
/**
Determines whether or not the current chipset is TXT Capable.
@param[in] TxtContextDataPtr - 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 (
VOID
)
{
BOOLEAN TxtCapable;
UINT32 Data32;
TxtCapable = FALSE;
Data32 = CheckSmxCapabilities ();
if ((Data32 & BIT0) != 0) {
TxtCapable = TRUE;
} else {
TxtCapable = FALSE;
}
return TxtCapable;
}
/**
Determines whether TXT is enabled by platform setting
@param[in] TxtContextDataPtr - 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_INFO_HOB *TxtInfoHob
)
{
if (TxtInfoHob == NULL) {
return FALSE;
}
return (BOOLEAN)TxtInfoHob->Data.TxtMode;
}
/**
Determines whether Alias Check Request is enabled by platform setting
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@retval TRUE - If ACHECK REQUEST is enabled by platform setting
@retval FALSE - If ACHECK REQUEST is disabled by platform setting
**/
BOOLEAN
IsAcheckRequested (
IN TXT_INFO_HOB *TxtInfoHob
)
{
if (TxtInfoHob == NULL) {
return FALSE;
}
return (BOOLEAN) (TxtInfoHob->Data.TxtAcheckRequest);
}
/**
Determines ACM is matched to chipset or not
@param[in] TxtContextDataPtr - 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 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] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@retval EFI_SUCCESS - If TXT Info Hob is found
@exception EFI_NOT_FOUND - If TXT Info Hob is not found
@exception EFI_UNSUPPORTED - If the platform is not TXT capable.
**/
EFI_STATUS
CreateTxtInfoHob (
IN TXT_INFO_HOB **TxtInfoHob
)
{
EFI_STATUS Status;
SI_PREMEM_POLICY_PPI *SiPreMemPolicy;
CPU_SECURITY_PREMEM_CONFIG *CpuSecurityPreMemConfig;
CPU_TXT_PREMEM_CONFIG *CpuTxtPreMemConfig;
*TxtInfoHob = NULL;
//
// Get TxtInfoHob if it is already present, then this is the reinitalize, just reload the hob and exit
//
*TxtInfoHob = (TXT_INFO_HOB *) GetFirstGuidHob (&gTxtInfoHobGuid);
if (*TxtInfoHob != NULL) {
return EFI_SUCCESS;
}
///
/// Locate Cpu policy ppi to initialized.
///
Status = PeiServicesLocatePpi (
&gSiPreMemPolicyPpiGuid,
0,
NULL,
(VOID **) &SiPreMemPolicy
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gCpuSecurityPreMemConfigGuid, (VOID *) &CpuSecurityPreMemConfig);
ASSERT_EFI_ERROR (Status);
Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gCpuTxtPreMemConfigGuid, (VOID *) &CpuTxtPreMemConfig);
ASSERT_EFI_ERROR (Status);
///
/// Create hob for storing TXT data
///
Status = PeiServicesCreateHob (
EFI_HOB_TYPE_GUID_EXTENSION,
sizeof (TXT_INFO_HOB),
(VOID **) TxtInfoHob
);
if (EFI_ERROR (Status)) {
return Status;
}
(*TxtInfoHob)->EfiHobGuidType.Name = gTxtInfoHobGuid;
///
/// Initiate Txt Info Hob
///
ZeroMem (&((*TxtInfoHob)->Data), sizeof (TXT_INFO_DATA));
(*TxtInfoHob)->Data.ChipsetIsTxtCapable = IsTxtChipset ();
(*TxtInfoHob)->Data.ProcessorIsTxtCapable = IsTxtProcessor ();
if (CpuSecurityPreMemConfig->Txt == 1) {
(*TxtInfoHob)->Data.TxtMode = 1;
}
(*TxtInfoHob)->Data.AcpiBase = PmcGetAcpiBase ();
(*TxtInfoHob)->Data.TxtAcheckRequest = (BOOLEAN) CpuSecurityPreMemConfig->TxtAcheckRequest;
(*TxtInfoHob)->Data.ResetAux = (BOOLEAN) CpuSecurityPreMemConfig->ResetAux;
(*TxtInfoHob)->Data.SinitMemorySize = (UINT64) CpuTxtPreMemConfig->SinitMemorySize;
(*TxtInfoHob)->Data.TxtHeapMemorySize = (UINT64) CpuTxtPreMemConfig->TxtHeapMemorySize;
(*TxtInfoHob)->Data.TxtDprMemoryBase = CpuTxtPreMemConfig->TxtDprMemoryBase;
(*TxtInfoHob)->Data.TxtDprMemorySize = (UINT64) CpuTxtPreMemConfig->TxtDprMemorySize;
(*TxtInfoHob)->Data.BiosAcmBase = CpuTxtPreMemConfig->BiosAcmBase;
(*TxtInfoHob)->Data.BiosAcmSize = (UINT64) CpuTxtPreMemConfig->BiosAcmSize;
(*TxtInfoHob)->Data.TgaSize = (UINT64) CpuTxtPreMemConfig->TgaSize;
(*TxtInfoHob)->Data.TxtLcpPdBase = CpuTxtPreMemConfig->TxtLcpPdBase;
(*TxtInfoHob)->Data.TxtLcpPdSize = CpuTxtPreMemConfig->TxtLcpPdSize;
(*TxtInfoHob)->Data.ApStartupBase = CpuTxtPreMemConfig->ApStartupBase;
(*TxtInfoHob)->Data.Flags |= (UINT64)CpuTxtPreMemConfig->IsTPMPresence;
if ((*TxtInfoHob)->Data.BiosAcmBase != 0) {
//
// Parse the ACM header. Locate the ACM Info Table.
// Get the ACM major/minor version
//
ACM_HEADER *AcmHeader = (ACM_HEADER*)(UINTN)((*TxtInfoHob)->Data.BiosAcmBase);
UINT8 *AcmPtr = (UINT8 *)(AcmHeader + 1);
AcmPtr += AcmHeader->KeySize * 4;
if (AcmHeader->HeaderVersion < ACM_HEADER_VERSION_3) {
AcmPtr += 4;
AcmPtr += ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE;
} else {
AcmPtr += ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE;
}
AcmPtr += AcmHeader->ScratchSize * 4;
//
// Extract ACM Info Table version numbers
//
ACM_INFO_TABLE *AcmInfoTable = (ACM_INFO_TABLE *)AcmPtr;
if (CompareGuid(&(AcmInfoTable->Guid), &gTxtAcmInfoTableGuid)) {
(*TxtInfoHob)->Data.AcmMajorVersion = AcmInfoTable->AitRevision[0];
(*TxtInfoHob)->Data.AcmMinorVersion = AcmInfoTable->AitRevision[1];
(*TxtInfoHob)->Data.AcmRevision = AcmInfoTable->AitRevision[2];
}
}
return EFI_SUCCESS;
}
/**
Add extened elements to BiosOsData
@param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
@param[in] Type - The element's type
@param[in] Buffer - A pointer to buffer which need to append the element
@param[in] Size - return the size of the appened element.
**/
VOID
AppendElement (
IN TXT_INFO_HOB *TxtInfoHob,
IN UINT32 Type,
IN VOID *Buffer,
OUT UINT32 *Size
)
{
VOID *Element;
UINT32 NumberOfAcm;
UINT64 *AcmBase;
EFI_STATUS Status;
NumberOfAcm = 1;
AcmBase = NULL;
Element = NULL;
*Size = 0;
switch (Type) {
case HEAP_EXTDATA_TYPE_BIOS_SPEC_VER:
///
/// Fill BIOS spec ver element
///
Status = PeiServicesAllocatePool (sizeof (HEAP_BIOS_SPEC_VER_ELEMENT),&Element);
ASSERT_EFI_ERROR(Status);
if (Element != NULL) {
*Size = sizeof (HEAP_BIOS_SPEC_VER_ELEMENT);
((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->Header.Type = HEAP_EXTDATA_TYPE_BIOS_SPEC_VER;
((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->Header.Size = sizeof (HEAP_BIOS_SPEC_VER_ELEMENT);
((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->SpecVerMajor = TXT_BIOS_SPEC_VER_MAJOR;
((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->SpecVerMinor = TXT_BIOS_SPEC_VER_MINOR;
((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->SpecVerRevision = TXT_BIOS_SPEC_VER_REVISION;
}
break;
case HEAP_EXTDATA_TYPE_BIOSACM:
///
/// Fill BIOS ACM element
///
Status = PeiServicesAllocatePool (sizeof (HEAP_BIOSACM_ELEMENT) + NumberOfAcm * sizeof (UINT64),&Element);
ASSERT_EFI_ERROR(Status);
if (Element != NULL) {
*Size = sizeof (HEAP_BIOSACM_ELEMENT) + sizeof (UINT64) * NumberOfAcm;
((HEAP_BIOSACM_ELEMENT *) Element)->Header.Type = HEAP_EXTDATA_TYPE_BIOSACM;
((HEAP_BIOSACM_ELEMENT *) Element)->Header.Size = sizeof (HEAP_BIOSACM_ELEMENT) + NumberOfAcm * sizeof (UINT64);
((HEAP_BIOSACM_ELEMENT *) Element)->NumAcms = NumberOfAcm;
AcmBase = (UINT64 *) ((UINTN) Element + sizeof (HEAP_BIOSACM_ELEMENT));
*AcmBase = TxtInfoHob->Data.BiosAcmBase;
}
break;
case HEAP_EXTDATA_TYPE_END:
///
/// Fill end type element
///
Status = PeiServicesAllocatePool (sizeof (HEAP_EXT_DATA_ELEMENT),&Element);
ASSERT_EFI_ERROR(Status);
if (Element != NULL) {
*Size = sizeof (HEAP_EXT_DATA_ELEMENT);
((HEAP_EXT_DATA_ELEMENT *) Element)->Type = HEAP_EXTDATA_TYPE_END;
((HEAP_EXT_DATA_ELEMENT *) Element)->Size = sizeof (HEAP_EXT_DATA_ELEMENT);
}
break;
default:
break;
}
if (Element != NULL) {
CopyMem (Buffer, Element, *Size);
}
}
/**
Allocates 1 MB of 1MB-aligned memory for use as TXT Device Memory. Records
the location of TXT Device Memory in TXT Chipset registers and then adds
programming instructions for these registers into BootScript.
@param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
@retval EFI_SUCCESS - TXT Device memory has been successfully initialized.
@exception EFI_UNSUPPORTED - TXT Device memory not available.
**/
EFI_STATUS
SetupTxtDeviceMemory (
IN TXT_INFO_HOB *TxtInfoHob,
IN UINTN CpuCount
)
{
UINTN TopAddr;
UINTN *Ptr;
UINT64 Value64;
UINT32 Value32;
UINTN TxtHeapMemoryBase;
UINTN TxtSinitMemoryBase;
BOOLEAN Locked;
BIOS_OS_DATA_REGION *BiosOsDataRegion;
TXT_INFO_DATA *TxtInfoData;
UINT8 *Ptr8;
DEBUG ((DEBUG_INFO, "TXTPEI::SetupTxtDeviceMemory\n"));
TxtHeapMemoryBase = 0;
TxtSinitMemoryBase = 0;
Locked = FALSE;
Ptr8 = NULL;
Value32 = 0;
TxtInfoData = &(TxtInfoHob->Data);
if ((TxtInfoData == 0) ||
(TxtInfoData->TxtDprMemoryBase == 0) ||
(TxtInfoData->TxtDprMemorySize == 0) ||
(TxtInfoData->TxtHeapMemorySize == 0) ||
(TxtInfoData->SinitMemorySize == 0)
) {
DEBUG ((DEBUG_ERROR, "SetupTxtDeviceMemory : SinitMemorySize = 0x%x\n", TxtInfoData->SinitMemorySize));
DEBUG ((DEBUG_ERROR, "SetupTxtDeviceMemory : TxtHeapMemorySize = 0x%x\n", TxtInfoData->TxtHeapMemorySize));
DEBUG ((DEBUG_ERROR, "SetupTxtDeviceMemory : TxtDprMemoryBase = 0x%x\n", TxtInfoData->TxtDprMemoryBase));
DEBUG ((DEBUG_ERROR, "SetupTxtDeviceMemory : TxtDprMemorySize = 0x%x\n", TxtInfoData->TxtDprMemorySize));
return EFI_UNSUPPORTED;
} else {
///
/// Use address passed from PEI
///
TopAddr = (UINTN) (TxtInfoData->TxtDprMemoryBase + TxtInfoData->TxtDprMemorySize);
TxtHeapMemoryBase = (UINTN) (TopAddr - TxtInfoData->TxtHeapMemorySize);
TxtSinitMemoryBase = (UINTN) (TxtHeapMemoryBase - TxtInfoData->SinitMemorySize);
}
ASSERT ((TopAddr & 0x0FFFFF) == 0);
///
/// DPR registers
///
Ptr = (UINTN *) (UINTN) (TXT_PUBLIC_BASE + TXT_DPR_SIZE_REG_OFF);
Value64 = RShiftU64 (TxtInfoData->TxtDprMemorySize, 16) | 1;
*Ptr = (UINTN) (Value64 | TopAddr);
///
/// Assert error if programmed value is different from requested. This
/// means error is requested size.
///
Value64 = *Ptr;
ASSERT ((LShiftU64 ((Value64 & 0xFFE), 16)) == TxtInfoData->TxtDprMemorySize);
///
/// HEAP Registers
/// Program size register first
///
Ptr = (UINTN *) (UINTN) (TXT_PUBLIC_BASE + TXT_HEAP_SIZE_REG_OFF);
///
/// Test register locked status. If locked, skip programming since
/// this will be done by BIOS ACM
///
*Ptr = TEST_PATTERN;
Value32 = *Ptr;
if (Value32 != TEST_PATTERN) {
Locked = TRUE;
} else {
///
/// To be safe invert pattern and try again
///
*Ptr = (UINTN) ~TEST_PATTERN;
Value32 = *Ptr;
if (Value32 != (UINTN) ~TEST_PATTERN) {
Locked = TRUE;
}
}
if (!Locked) {
*Ptr = (UINTN) (TxtInfoData->TxtHeapMemorySize);
///
/// Assert error if programmed value is different from requested. This
/// means error is requested size.
///
Value64 = *Ptr;
ASSERT (Value64 == TxtInfoData->TxtHeapMemorySize);
///
/// Program base register.
///
Ptr = (UINTN *) (UINTN) (TXT_PUBLIC_BASE + TXT_HEAP_BASE_REG_OFF);
*Ptr = TxtHeapMemoryBase;
///
/// Assert error if programmed value is different from requested. This
/// means error is requested size.
///
Value64 = *Ptr;
ASSERT (Value64 == TxtHeapMemoryBase);
}
///
/// SINIT Registers
/// Program size register first
///
Ptr = (UINTN *) (UINTN) (TXT_PUBLIC_BASE + TXT_SINIT_SIZE_REG_OFF);
*Ptr = (UINT32) (TxtInfoData->SinitMemorySize);
///
/// Assert error if programmed value is different from requested. This
/// means error is requested size.
///
Value64 = *Ptr;
ASSERT (Value64 == TxtInfoData->SinitMemorySize);
///
/// Program base register
///
Ptr = (UINTN *) (UINTN) (TXT_PUBLIC_BASE + TXT_SINIT_BASE_REG_OFF);
*Ptr = TxtSinitMemoryBase;
///
/// Assert error if programmed value is different from requested. This
/// means error is requested size.
///
Value64 = *Ptr;
ASSERT (Value64 == TxtSinitMemoryBase);
///
/// Make sure TXT Device Memory has been zeroed
///
ZeroMem (
(VOID *) ((UINTN) TxtSinitMemoryBase),
(UINTN) (TopAddr - TxtSinitMemoryBase)
);
if (TxtInfoData->TgaSize) {
;
///
/// Placeholder for Trusted graphics support
///
}
Ptr = (UINTN *) TxtHeapMemoryBase;
*Ptr = sizeof (BIOS_OS_DATA_REGION);
///
/// BiosOsDataSize plus sizew of data size feld itself
///
BiosOsDataRegion = (BIOS_OS_DATA_REGION *) (Ptr + 2);
BiosOsDataRegion->Version = BIOS_OS_DATAREGION_VERSION;
BiosOsDataRegion->BiosSinitSize = 0;
BiosOsDataRegion->LcpPdBase = TxtInfoData->TxtLcpPdBase;
BiosOsDataRegion->LcpPdSize = TxtInfoData->TxtLcpPdSize;
BiosOsDataRegion->NumOfLogicalProcessors = CpuCount;
BiosOsDataRegion->Flags = TxtInfoData->Flags;
Ptr8 = (UINT8 *) (UINTN) &(BiosOsDataRegion->ExtData);
AppendElement (TxtInfoHob, HEAP_EXTDATA_TYPE_BIOS_SPEC_VER, Ptr8, &Value32);
Ptr8 += Value32;
AppendElement (TxtInfoHob, HEAP_EXTDATA_TYPE_BIOSACM, Ptr8, &Value32);
Ptr8 += Value32;
AppendElement (TxtInfoHob, HEAP_EXTDATA_TYPE_END, Ptr8, &Value32);
Value64 = (UINTN) Ptr8 - TxtHeapMemoryBase + Value32;
*Ptr = (Value64 & 0xFFFFFFFF);
*(Ptr+1) = (UINT32) (RShiftU64 (Value64,8));
return EFI_SUCCESS;
}
/**
Is Spt in PTT mode
@retval TRUE - If the PTT mode is asserted.
@retval FALSE - If the PTT mode is unasserted.
**/
BOOLEAN
IsSptPtt (
VOID
)
{
UINT32 RegRead;
RegRead = MmioRead32 (TXT_PUBLIC_BASE + TXT_PTT_FTIF_OFF);
DEBUG ((DEBUG_INFO, "IsSptPtt: LT FTIF = %x\n", RegRead));
RegRead = RegRead & TXT_PTT_PRESENT;
if (RegRead == TXT_PTT_PRESENT) {
DEBUG ((DEBUG_INFO, "IsSptPtt: PTT cycle\n"));
return TRUE;
} else {
return FALSE;
}
}
/**
Determines whether or not the platform has executed a TXT launch by
examining the TPM Establishment bit.
@param[in] TxtContextDataPtr - 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
TxtIsEstablishmentBitAsserted (
IN TXT_INFO_HOB *TxtInfoHob
)
{
UINT8 Access;
UINT16 TimeOutCount;
///
/// Set TPM.ACCESS polling timeout about 750ms
///
TimeOutCount = TPM_TIME_OUT;
do {
///
/// Read TPM status register
///
Access = MmioRead8 (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 ((Access & 0x80) != 0x80) {
///
/// Delay 1ms
///
MicroSecondDelay (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 ((DEBUG_ERROR, "TXTPEI: TPM Valid Status is not set!! TPM.ACCESS=%x\n", Access));
ASSERT (TRUE);
CpuDeadLoop ();
}
///
/// 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.
@retval TRUE - If the TXT_WAKE_ERROR bit is asserted.
@retval FALSE - If the TXT_WAKE_ERROR bit is unasserted.
**/
BOOLEAN
IsTxtWakeError (
VOID
)
{
UINT8 Ests;
///
/// Read TXT.ESTS register
///
Ests = MmioRead8 (TXT_PUBLIC_BASE + TXT_ERROR_STATUS_REG_OFF);
DEBUG ((DEBUG_INFO, "TXTPEI: TXT.ESTS=%x\n", Ests));
return (Ests & (0x1 << 6)) ? TRUE : FALSE;
}
/**
Determines whether or not the platform memory has been locked
@retval TRUE - If memroy is locked
@retval FALSE - If memory is unlocked
**/
BOOLEAN
IsMemoryLocked (
VOID
)
{
UINT32 CpuMemLockStatus;
///
/// Check status register for now.
///
CpuMemLockStatus = MmioRead32 (TXT_PUBLIC_BASE + TXT_E2STS_REG_OFF);
DEBUG ((DEBUG_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
@retval TRUE - If the TPM reset bit is asserted.
@retval FALSE - If the TPM reset bit is unasserted.
**/
BOOLEAN
IsTxtResetSet (
VOID
)
{
UINT8 Ests;
///
/// Read TXT.ESTS register
///
Ests = MmioRead8 (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
@retval TRUE - If the LT.SECRETS.STS bit is asserted.
@retval FALSE - If the LT.SECRETS.STS bit is unasserted.
**/
BOOLEAN
IsTxtSecretsSet (
VOID
)
{
UINT8 E2sts;
///
/// Read TXT.E2STS register
///
E2sts = MmioRead8 (TXT_PUBLIC_BASE + TXT_E2STS_REG_OFF);
DEBUG ((DEBUG_INFO, "TXTPEI: TXT.E2STS=%x\n", E2sts));
return (E2sts & TXT_SECRETS_STS) ? TRUE : FALSE;
}
/**
Determines presence of TPM in system
@param[in] TxtContextDataPtr - 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.
@exception EFI_NOT_FOUND - If the TPM is not present.
**/
EFI_STATUS
IsTpmPresent (
IN TXT_INFO_HOB *TxtInfoHob
)
{
if((TxtInfoHob->Data.Flags & TPM_INIT_FAILED) == 0){
return EFI_SUCCESS;
} else {
return EFI_DEVICE_ERROR;
}
}
/**
Clear Sleep Type register.
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@retval EFI_SUCCESS - Always
**/
EFI_STATUS
ClearSlpTyp (
IN TXT_INFO_HOB *TxtInfoHob
)
{
UINT32 Pm1Addr;
UINT32 Pm1Value;
///
/// Make address for PM1_CNT
///
Pm1Addr = ((UINT32) TxtInfoHob->Data.AcpiBase) + 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;
}
/**
Issue a Global Reset
**/
VOID
IssueGlobalReset(
VOID
)
{
PCH_RESET_DATA ResetData;
CopyMem (&ResetData.Guid, &gPchGlobalResetGuid, sizeof (EFI_GUID));
StrCpyS (ResetData.Description, PCH_RESET_DATA_STRING_MAX_LENGTH, PCH_PLATFORM_SPECIFIC_RESET_STRING);
(*GetPeiServicesTablePointer ())->ResetSystem2 (EfiResetPlatformSpecific, EFI_SUCCESS, sizeof (PCH_RESET_DATA), &ResetData);
}
/**
Initializes values passed to AP
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
**/
VOID
PrepareApParams (
IN TXT_INFO_HOB *TxtInfoHob
)
{
UINT32 TxtPublicSpace;
TxtPublicSpace = TXT_PUBLIC_BASE;
*(UINT32 *) (TxtPublicSpace + BIOACM_ADDR) = (UINT32) (TxtInfoHob->Data.BiosAcmBase);
*(UINT32 *) (TxtPublicSpace + APINIT_ADDR) = (UINT32) (TxtInfoHob->Data.ApStartupBase);
*(UINT32 *) (TxtPublicSpace + SEMAPHORE) = 0;
}
/**
Invokes the SCLEAN/ACHECK function from the TXT BIOS ACM.
1. Clearing of sleep type is necessary because SCLEAN/ACHECK 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/ACHECK
3. SCLEAN/ACHECK function is invoked.
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@param[in] func - Acm function to be launch
@retval EFI_SUCCESS - Always.
**/
EFI_STATUS
DoAcmLaunch (
IN TXT_INFO_HOB *TxtInfoHob,
IN UINT8 func
)
{
EFI_STATUS Status;
SI_PREMEM_POLICY_PPI *SiPreMemPolicy;
CPU_SECURITY_PREMEM_CONFIG *CpuSecurityPreMemConfig;
Status = PeiServicesLocatePpi (
&gSiPreMemPolicyPpiGuid,
0,
NULL,
(VOID **) &SiPreMemPolicy
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gCpuSecurityPreMemConfigGuid, (VOID *) &CpuSecurityPreMemConfig);
ASSERT_EFI_ERROR (Status);
ClearSlpTyp (TxtInfoHob);
PrepareApParams (TxtInfoHob);
if (CpuSecurityPreMemConfig->SkipStopPbet != TRUE) {
///
/// Disable PBET before send IPI to APs
///
StopPbeTimer ();
}
if (func == TXT_LAUNCH_CLEAR_SECRETS) {
LaunchBiosAcmClearSecrets ();
} else if (func == TXT_LAUNCH_ACHECK) {
LaunchBiosAcmAcheck ();
}
return EFI_SUCCESS;
}
/**
Launching of SCHECK function from the TXT BIOS ACM.
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@retval EFI_SUCCESS - Always.
**/
VOID
EFIAPI
DummyFunc (
IN OUT VOID *Buffer
)
{
return;
}
/**
Invoke BIOS ACM function
@param[in]
TxtInfoHob: pointer to TXT_INFO_HOB struct
Function: index of ACM function to invoke
BootMode: Cold boot or S3
**/
EFI_STATUS
DoPeiLaunchAcm (
IN EFI_PEI_SERVICES **PeiServices,
IN TXT_INFO_HOB *TxtInfoHob,
IN UINT64 Function,
IN UINT64 BootMode
)
{
///
/// ApCfg array contains 10 elements for 8 MTRRs + 10 element for
/// IA32_MTRR_DEF_TYPE MTRR + 1 element for IDT + 1 element for
/// IA32_MISC_ENABLE MSR
///
UINT64 ApCfg[MSR_IA32_MTRR_PHYSMASK9 - MSR_IA32_MTRR_PHYSBASE0 + 4];
UINT64 BiosAcAddr;
UINT64 SavedSmiSourcesVariables[2];
UINTN NumberOfProcessors;
UINTN NumberOfEnabledProcessors;
UINTN MyCpuNumber;
UINTN Index;
EDKII_PEI_MP_SERVICES2_PPI *MpServices2Ppi = NULL;
EFI_STATUS Status = EFI_SUCCESS;
Status = PeiServicesLocatePpi (
&gEdkiiPeiMpServices2PpiGuid,
0,
NULL,
(VOID **) &MpServices2Ppi);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return Status;
}
Status = MpServices2Ppi->GetNumberOfProcessors (MpServices2Ppi, (UINTN *)&NumberOfProcessors, (UINTN *)&NumberOfEnabledProcessors);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return Status;
}
Status = MpServices2Ppi->WhoAmI (
MpServices2Ppi,
&MyCpuNumber
);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return Status;
}
BiosAcAddr = (UINT64) (UINTN) TxtInfoHob->Data.BiosAcmBase;
SaveApConfig (ApCfg);
DisableSmiSources (TxtInfoHob, SavedSmiSourcesVariables, TRUE);
///
/// Disable APs and put in WFS state
///
for (Index = 0; Index < NumberOfProcessors; Index++) {
if (Index != MyCpuNumber) {
DEBUG ((DEBUG_INFO, "TXTPEI: disable AP Index=%x\n", Index));
Status = MpServices2Ppi->EnableDisableAP (
MpServices2Ppi,
Index,
FALSE,
NULL
);
ASSERT_EFI_ERROR (Status);
}
}
SendInitIpiAllExcludingSelf();
// Give the APs time to enter wait-for-SIPI state
MicroSecondDelay (10 * STALL_ONE_MILLI_SECOND);
///
/// Launch the BIOS ACM to run the requested function
///
DEBUG ((DEBUG_INFO, "TXTPEI::Running of LaunchBiosAcm\n"));
LaunchBiosAcm (&BiosAcAddr,Function,BootMode);
///
/// Restart APs
///
for (Index = 0; Index < NumberOfProcessors; Index++) {
if (Index != MyCpuNumber) {
DEBUG ((DEBUG_INFO, "TXTPEI: restart AP Index=%x\n", Index));
Status = MpServices2Ppi->EnableDisableAP (
MpServices2Ppi,
Index,
TRUE,
NULL
);
ASSERT_EFI_ERROR (Status);
}
}
DisableSmiSources (TxtInfoHob, SavedSmiSourcesVariables, FALSE);
RestoreMtrrProgramming (ApCfg);
return EFI_SUCCESS;
}
/**
Disable or restore possible SMI sources before or after SCHECK on S3 resume.
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@param[in] SavedSmiSourcesVariablesPointer - Saved SMI source Variable
@param[in] Operation
- Boolean value telling what operation is requested:
- TRUE: save and then disable possible SMI sources.
- FALSE: restore original SMI settings.
@retval EFI_SUCCESS - Always.
**/
EFI_STATUS
DisableSmiSources (
IN TXT_INFO_HOB *TxtInfoHob,
IN UINT64* SavedSmiSourcesVariablesPointer,
IN BOOLEAN Operation
)
{
UINT64 GlobalSmiControlIoAddr;
UINT32 SavedSmiControl;
UINT64 SavedIa32ThermInterruptMsr;
GlobalSmiControlIoAddr = TxtInfoHob->Data.AcpiBase + 0x30;
if (Operation == TRUE) {
SavedIa32ThermInterruptMsr = AsmReadMsr64 ((UINT32) MSR_IA32_THERM_INTERRUPT);
//
// Cannot use static variables because of PEI phase, static variables would be in code region which is read-only.
//
*SavedSmiSourcesVariablesPointer = SavedIa32ThermInterruptMsr;
AsmWriteMsr64 (
(UINT32) MSR_IA32_THERM_INTERRUPT,
(UINT64) (SavedIa32ThermInterruptMsr & ~(BIT0 + BIT1 + BIT2 + BIT4 + BIT15 + BIT23))
);
SavedSmiControl = IoRead32 ((UINTN) GlobalSmiControlIoAddr);
*((UINT64 *) (SavedSmiSourcesVariablesPointer + 1)) = SavedSmiControl;
//
// We can not disable Global SMI since it should be locked after SCHECK. we can only disable SMI sources individually.
//
IoWrite32 ((UINTN) GlobalSmiControlIoAddr, (UINT32) (SavedSmiControl & 0x01));
} else {
//
// We can not disable Global SMI since it should be locked after SCHECK. we can only disable SMI sources individually.
// Restore original SMI setting after SCHECK
//
SavedSmiControl = (UINT32) *((UINT64 *) (SavedSmiSourcesVariablesPointer + 1));
IoWrite32 (
(UINTN) GlobalSmiControlIoAddr,
(UINT32) (SavedSmiControl)
);
SavedIa32ThermInterruptMsr = *SavedSmiSourcesVariablesPointer;
//
// Restore IA32_THERMAL_INTERRUPT MSR
//
AsmWriteMsr64 (
(UINT32) MSR_IA32_THERM_INTERRUPT,
(UINT64) SavedIa32ThermInterruptMsr
);
}
return EFI_SUCCESS;
}
/**
Unlock memory when security is set and TxT is not enabled
@param[in] TxtContextDataPtr - A pointer to an initialized TXT PEI Context data structure
@retval EFI_SUCCESS - If address has been found
@exception EFI_UNSUPPORTED - CPU doesn't support TxT.
**/
EFI_STATUS
TxtUnlockMemory (
IN TXT_INFO_HOB *TxtInfoHob
)
{
BOOLEAN EstablishmentBitAsserted;
EstablishmentBitAsserted = TxtIsEstablishmentBitAsserted (TxtInfoHob);
///
/// Need to read FED40000 before unlocking memory
///
if (!EstablishmentBitAsserted) {
DEBUG ((DEBUG_INFO, "TXTPEI::Unlock memory\n"));
AsmWriteMsr64 (MSR_LT_UNLOCK_MEMORY, 0);
} else {
///
/// Lunch SCLEAN if wake error bit is set.
///
if (IsTxtWakeError ()) {
///
/// If TXTRESET is set , we must clean TXTRESET bit otherwise SCLEAN
/// will fail
///
if (IsTxtResetSet ()) {
IssueGlobalReset ();
}
if ((TxtInfoHob->Data.BiosAcmBase == 0) || (TxtInfoHob->Data.ApStartupBase == 0)) {
return EFI_UNSUPPORTED;
}
///
/// Setup and Launch SCLEAN
///
DEBUG ((DEBUG_INFO, "TXTPEI::Entering SCLEAN to unlock memory\n"));
} else {
return EFI_UNSUPPORTED;
}
}
return EFI_SUCCESS;
}
/**
This routine provides TXT status information from S_ACM.
@retval TRUE - If Bit 30 of LT_SPAD is set by S-ACM , otherwise FALSE
**/
BOOLEAN
IsBptTxtPassed (
VOID
)
{
UINT64 TxtSpad;
TxtSpad = MmioRead64(TXT_PUBLIC_BASE + TXT_SPAD_REG_OFF);
return (TxtSpad & B_BPT_TXT_PASSED) ? TRUE : FALSE;
}