diff options
Diffstat (limited to 'ReferenceCode/Haswell/Txt/TxtInit')
25 files changed, 7512 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c new file mode 100644 index 0000000..ef7ca8b --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c @@ -0,0 +1,171 @@ +/** @file + This is the main DXE file for TXT. It represents an abstract outline of the + steps required during DXE for enabling TXT. Each individual step is further + abstracted behind a function call interface. This is intended to minimize + the need to modify this file when porting TXT to future platforms. + +@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 + +**/ + +/// +/// 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 "Txt.h" +#include "TxtDxeLib.h" +#endif + +TXT_DXE_LIB_CONTEXT mTxtDxeCtx; + +/** + This function gets registered as a callback to run the SCHECK function + from the TXT BIOS ACM as a result of Boot Events. + + @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. + + **/ +EFI_STATUS +EFIAPI +ScheckCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((EFI_D_INFO, "TXTDXE::Running of DoScheck\n")); + + DoScheck (&mTxtDxeCtx); + /// + /// Closed the event to avoid call twice when launch shell + /// + gBS->CloseEvent (Event); + + return EFI_SUCCESS; +} +/** + This is the entry point to the TXT DXE Driver. This routine checks to see if + the platform should be configured for TXT and if so, configures the platform + by reserving and initializing TXT Configuration Space and TXT Device Memory and + registering a callback to run SCHECK from the TXT BIOS ACM prior to boot. + + If the platform should not be configured for TXT, this routine checks the + establishment bit in the TPM and resets it if it is asserted. + + @param[in] ImageHandle - A handle for this module + @param[in] SystemTable - A pointer to the EFI System Table + + @retval EFI_SUCCESS - If TXT initialization succeed + @retval EFI_UNLOAD_IMAGE - If TXT criterias are not met +**/ +EFI_STATUS +EFIAPI +DriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT ReadyToBootEvent; + /// + /// Initialize the platform specific code + /// + Status = InitializeTxtDxeLib (ImageHandle, SystemTable, &mTxtDxeCtx); + /// + /// If failure - assume TXT is not enabled + /// + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "TXTDXE::InitializeTxtDxeLib failed.... Unloading\n")); + return EFI_UNLOAD_IMAGE; + } + /// + /// If ESTS.TXTRESET bit is set, skip all other functions since + /// attempt to execute GETSEC will hang system. Skipping allows to + /// boot to OS and let MLE assess situation. + /// + if (IsTxtResetSet (&mTxtDxeCtx)) { + DEBUG ((EFI_D_ERROR, "TXTDXE::TXT_RESET bit is set.... Unloading\n")); + return EFI_UNLOAD_IMAGE; + } + /// + /// If TXT is enabled, configure platform appropriately. + /// Code assumes that if TXT is enabled by CPU driver than all checks + /// are passed, i.e. TPM is present, CPU and CS are TXT capable. + /// + /// + /// Add to check CPU TXT capable in case CPU drivers do not check additional requirements + /// + if ((mTxtDxeCtx.TxtInfoData->ChipsetIsTxtCapable) && IsTxtProcessor () && IsTxtEnabled (&mTxtDxeCtx)) { + DEBUG ((EFI_D_INFO, "TXTDXE::TXT Enabled\n")); + /// + /// Mark TXT Config Space as System Reserved in Memory Map + /// + ReserveTxtConfigSpace (&mTxtDxeCtx); + + /// + /// Allocate and Initialize TXT Device Memory + /// + Status = SetupTxtDeviceMemory (&mTxtDxeCtx); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "TXTDXE::SetupTxtDeviceMemory failed.... Unloading\n")); + return EFI_UNLOAD_IMAGE; + } + /// + /// Create callback to run SCHECK on a Legacy Boot event + /// + Status = EfiCreateEventReadyToBootEx ( + EFI_TPL_CALLBACK, + ScheckCallback, + NULL, + &ReadyToBootEvent + ); + ASSERT_EFI_ERROR (Status); + + } else { + /// + /// TXT is not enabled, so make sure TPM Establishment + /// bit is de-asserted + /// + DEBUG ((EFI_D_INFO, "TXTDXE::TXT Disabled\n")); + + if (IsTxtEstablished (&mTxtDxeCtx)) { + /// + /// We can invoke BIOS ACM function only if CS and CPU are TXT + /// capable + /// + if ((mTxtDxeCtx.TxtInfoData->ChipsetIsTxtCapable) && + IsTxtProcessor () && + !(mTxtDxeCtx.TxtInfoData->Flags & TPM_INIT_FAILED) + ) { + DEBUG ((EFI_D_INFO, "TXTDXE::Resetting TPM Establishment bit\n")); + ResetTpmEstBit (&mTxtDxeCtx); + } + } + /// + /// Reset AUX + /// + Status = ResetTpmAux (&mTxtDxeCtx); + ASSERT_EFI_ERROR (Status); + } + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif new file mode 100644 index 0000000..2add449 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif @@ -0,0 +1,18 @@ +<component> + name = "TxtDxe" + category = ModulePart + LocalRoot = "ReferenceCode\Haswell\Txt\TxtInit\Dxe\" + RefName = "TxtDxe" +[files] +"TxtDxe.c" +"TxtDxe.dxs" +"TxtDxe.mak" +"TxtDxe.sdl" +"TxtDxeLib.c" +"TxtDxeLib.h" +"TxtDxe.inf" +"TxtDxeOem.c" +"x64\TxtDxeBsp.asm" +"x64\TxtDxeAp.asm" +"x64\Mmx64.inc" +<endComponent> diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs new file mode 100644 index 0000000..7120727 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs @@ -0,0 +1,50 @@ +/** @file + This is the Dependency expression for the TXT Dxe architectural 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 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" +#include EFI_PROTOCOL_DEFINITION (MpService) +#include EFI_PROTOCOL_DEFINITION (BootScriptSave) +#include EFI_PROTOCOL_DEFINITION (SmmBase) +#include EFI_PROTOCOL_DEFINITION (PciIo) +#include EFI_PROTOCOL_DEFINITION (CpuIo) +#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy) +#endif + +DEPENDENCY_START + EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID AND + EFI_MP_SERVICES_PROTOCOL_GUID AND + EFI_SMM_BASE_PROTOCOL_GUID AND + DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID AND + + EFI_CPU_IO_PROTOCOL_GUID +DEPENDENCY_END diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf new file mode 100644 index 0000000..f6c1e20 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf @@ -0,0 +1,117 @@ +## @file +# Component description file for TXTDXE module +# +#@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 +# + + +[defines] +BASE_NAME = TxtDxe +FILE_GUID = FF917E22-A228-448d-BDAA-68EFCCDDA5D3 +COMPONENT_TYPE = BS_DRIVER + +[sources.common] + TxtDxe.c + TxtDxeLib.c + TxtDxeOem.c + X64/TxtDxeBsp.asm + X64/TxtDxeAp.asm + +# +# Edk II Glue Driver Entry Point +# + EdkIIGlueDxeDriverEntryPoint.c + +[includes.common] + . + ./X64 + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT) + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Framework/Protocol + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Sample/Include + +# +# Edk II Glue Library, some hearder are included by R9 header so have to include +# + + $(EFI_SOURCE) + $(EFI_SOURCE)/Framework + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/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_CPU_ROOT)/SampleCode + +[libraries.common] + EfiGuidLib + EdkFrameworkProtocolLib + EdkProtocolLib + EfiScriptLib + CpuGuidLib + CpuProtocolLib + EdkIIGlueBaseLib + EdkIIGlueBaseMemoryLib + EdkIIGlueBasePciLibPciExpress + EdkIIGlueDxeReportStatusCodeLib + EdkIIGlueDxeServicesTableLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueUefiRuntimeServicesTableLib + EdkIIGlueUefiLib + EdkIIGlueDxeHobLib + CpuProtocolLib + +# +# 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. +# + CpuSampleProtocolLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = TxtDxe.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=DriverEntry + C_FLAGS = $(C_FLAGS) -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__ + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_UEFI_LIB__ \ + -D __EDKII_GLUE_DXE_HOB_LIB__ diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak new file mode 100644 index 0000000..876fc41 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak @@ -0,0 +1,72 @@ +# MAK file for the ModulePart:TxtDxe +#-jeff debug +all : TxtDxe + +TxtDxe : $(BUILD_DIR)\TxtDxe.mak TxtDxeBin + +$(BUILD_DIR)\TxtDxe.mak : $(TxtDxe_DIR)\$(@B).cif $(TxtDxe_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(TxtDxe_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +TxtDxe_INCLUDES=\ + $(MISCFRAMEWORK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(PROJECT_CPU_INCLUDES)\ + $(TXT_INCLUDES)\ + +TxtDxe_DEFINES=\ + $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=DriverEntry"\ + /D PlatformPciExpressBaseAddress=$(PCIEX_BASE_ADDRESS) \ + /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_LIB__ \ + /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \ + /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_DXE_HOB_LIB__ \ + +TxtDxe_LIBS=\ + $(EFIGUIDLIB)\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + $(EDKPROTOCOLLIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueBaseLib_LIB)\ + $(EdkIIGlueBaseLibX64_LIB)\ + $(EdkIIGlueBaseMemoryLib_LIB)\ + $(EdkIIGlueDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueDxeServicesTableLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueUefiLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(EdkIIGlueBasePciExpressLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EdkIIGlueBaseTimerLibLocalApic_LIB)\ + $(EdkIIGlueDxeHobLib_LIB)\ + $(EdkIIGlueHiiLib_LIB)\ + $(EFIDRIVERLIB)\ + $(UEFIEFIIFRSUPPORTLIB)\ + $(EFISCRIPTLIB)\ + $(CpuProtocolLib_LIB)\ + $(CpuGuidLib_LIB)\ + $(SaPcieDxeLib_LIB)\ + $(CPUIA32LIB) + +TxtDxeBin : $(TxtDxe_LIBS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\TxtDxe.mak all\ + "MY_INCLUDES=$(TxtDxe_INCLUDES)"\ + "MY_DEFINES=$(TxtDxe_DEFINES)"\ + "GUID=FF917E22-A228-448d-BDAA-68EFCCDDA5D3"\ + "AFLAGS=$(AFLAGS) $(PROJECT_CPU_INCLUDES)"\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=BS_DRIVER \ + EDKIIModule=DXEDRIVER\ + DEPEX1=$(TxtDxe_DIR)\TxtDxe.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\ + COMPRESS=1\ diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl new file mode 100644 index 0000000..c17f497 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl @@ -0,0 +1,27 @@ +TOKEN + Name = "TxtDxe_SUPPORT" + Value = "1" + Help = "Main switch to enable TXT DXE init support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +PATH + Name = "TxtDxe_DIR" + Help = "TXT DXE source directory" +End + +MODULE + Help = "Includes TXTDXE.mak into project" + File = "TXTDXE.mak" +End + +ELINK + Name = "$(BUILD_DIR)\TxtDxe.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End +
\ No newline at end of file diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c new file mode 100644 index 0000000..6aef615 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c @@ -0,0 +1,1080 @@ +/** @file + This file contains an implementation of the function call interfaces + required by the main TXT DXE file. Hopefully, future platform porting + tasks will be mostly limited to modifying the functions in this file. + +@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 + +**/ + +/// +/// 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 "Txt.h" +#include "TxtDxeLib.h" +#include "EfiScriptLib.h" +#include EFI_PROTOCOL_DEFINITION (PciIo) +#include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo) +#include EFI_PROTOCOL_DEPENDENCY (FirmwareVolume) +#endif + +EFI_GUID mTxtBiosAcmPeiFileGuid = PEI_BIOS_ACM_FILE_GUID; + +UINT64 mMcuAddr; +UINT64 mAcmBase; +UINT64 mApMtrrTab[2 * (IA32_MTRR_PHYSMASK9 - IA32_MTRR_PHYSBASE0 + 1) + 1]; +UINT64 mApIdt[2]; +UINT64 mApCr4; +UINT64 mApSavedIa32ThermInterruptMSR[2]; +UINT32 mApSavedApicThermalValue; + +/** + This routine initializes and collects all Protocols and data required + by the routines in this file. + + @param[in] ImageHandle - A pointer to the Image Handle for this file. + @param[in] SystemTable - A pointer to the EFI System Table + @param[in] TxtDxeCtx - A pointer to a caller allocated data structure that contains + all of the Protocols and data required by the routines + in this file. + + @retval EFI_SUCCESS - Return EFI_SUCCESS if no error happen + @retval EFI_UNLOAD_IMAGE - If TxtInfoHob is not found +**/ +EFI_STATUS +InitializeTxtDxeLib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN OUT TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + EFI_STATUS Status; + VOID *HobList; + TXT_INFO_HOB *TxtInfoHob; + UINTN tmp; + + INITIALIZE_SCRIPT (ImageHandle, SystemTable); + + TxtDxeCtx->ImageHandle = ImageHandle; + TxtDxeCtx->SystemTable = SystemTable; + + /// + /// Find the TxtPolicyprotocol + /// + Status = gBS->LocateProtocol ( + &gDxeCpuPlatformPolicyProtocolGuid, + NULL, + (VOID **) &(TxtDxeCtx->CpuPlatformPolicy) + ); + + if (EFI_ERROR (Status)) { + TxtDxeCtx->CpuPlatformPolicy = NULL; + } + /// + /// Find the CpuIo protocol + /// + Status = gBS->LocateProtocol ( + &gEfiCpuIoProtocolGuid, + NULL, + (VOID **) &(TxtDxeCtx->CpuIo) + ); + + ASSERT_EFI_ERROR (Status); + /// + /// Find the MpService Protocol + /// + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + (VOID **) &(TxtDxeCtx->MpService) + ); + + ASSERT_EFI_ERROR (Status); + /// + /// Initialize CpuCount info. Current implemetation of + /// GetGeneralMPInfo doesn't honor optionality of arguments. Don't use + /// NULL pointers. + /// + Status = TxtDxeCtx->MpService->GetGeneralMPInfo ( + TxtDxeCtx->MpService, + &(TxtDxeCtx->CpuCount), + &tmp, + &tmp, + &tmp, + &tmp + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Find TxtInfoHob + /// + HobList = GetFirstGuidHob (&gTxtInfoHobGuid); + if (HobList == NULL) { + return EFI_UNLOAD_IMAGE; + } + + TxtInfoHob = (TXT_INFO_HOB *) HobList; + TxtDxeCtx->TxtInfoData = &(TxtInfoHob->Data); + + /// + /// Print out the TxtInfo HOB + /// + DEBUG ((EFI_D_INFO, "TXTDXE: TxtInfoHob passed from platform as:\n")); + DEBUG ((EFI_D_INFO, "TXTDXE: ChipsetIsTxtCapable = %x\n", TxtDxeCtx->TxtInfoData->ChipsetIsTxtCapable)); + DEBUG ((EFI_D_INFO, "TXTDXE: TxtMode = %x\n", TxtDxeCtx->TxtInfoData->TxtMode)); + DEBUG ((EFI_D_INFO, "TXTDXE: PmBase = %x\n", TxtDxeCtx->TxtInfoData->PmBase)); + DEBUG ((EFI_D_INFO, "TXTDXE: SinitMemorySize = %x\n", TxtDxeCtx->TxtInfoData->SinitMemorySize)); + DEBUG ((EFI_D_INFO, "TXTDXE: TxtHeapMemorySize = %x\n", TxtDxeCtx->TxtInfoData->TxtHeapMemorySize)); + DEBUG ((EFI_D_INFO, "TXTDXE: TxtDprMemoryBase = %x\n", TxtDxeCtx->TxtInfoData->TxtDprMemoryBase)); + DEBUG ((EFI_D_INFO, "TXTDXE: TxtDprMemorySize = %x\n", TxtDxeCtx->TxtInfoData->TxtDprMemorySize)); + DEBUG ((EFI_D_INFO, "TXTDXE: BiosAcmBase = %x\n", TxtDxeCtx->TxtInfoData->BiosAcmBase)); + DEBUG ((EFI_D_INFO, "TXTDXE: BiosAcmSize = %x\n", TxtDxeCtx->TxtInfoData->BiosAcmSize)); + DEBUG ((EFI_D_INFO, "TXTDXE: McuUpdateDataAddr = %x\n", TxtDxeCtx->TxtInfoData->McuUpdateDataAddr)); + DEBUG ((EFI_D_INFO, "TXTDXE: SinitAcmBase = %x\n", TxtDxeCtx->TxtInfoData->SinitAcmBase)); + DEBUG ((EFI_D_INFO, "TXTDXE: SinitAcmSize = %x\n", TxtDxeCtx->TxtInfoData->SinitAcmSize)); + DEBUG ((EFI_D_INFO, "TXTDXE: TgaSize = %x\n", TxtDxeCtx->TxtInfoData->TgaSize)); + DEBUG ((EFI_D_INFO, "TXTDXE: TxtLcpPdBase = %x\n", TxtDxeCtx->TxtInfoData->TxtLcpPdBase)); + DEBUG ((EFI_D_INFO, "TXTDXE: TxtLcpPdSize = %x\n", TxtDxeCtx->TxtInfoData->TxtLcpPdSize)); + DEBUG ((EFI_D_INFO, "TXTDXE: Flags = %x\n", TxtDxeCtx->TxtInfoData->Flags)); + return EFI_SUCCESS; +} + +/** + Determines whether or not the platform has executed an TXT launch by + examining the TPM Establishment bit. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval TRUE - If the TPM establishment bit is asserted. + @retval FALSE - If the TPM establishment bit is unasserted. +**/ +BOOLEAN +IsTxtEstablished ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + EFI_STATUS Status; + UINT8 AccessReg; + UINT16 TimeOutCount; + + /// + /// TO-DO: We might locate TCG protocol to access TPM status + /// + /// + /// Set TPM.ACCESS polling timeout about 750ms + /// + TimeOutCount = TPM_TIME_OUT; + do { + /// + /// Read TPM status register + /// + Status = TxtDxeCtx->CpuIo->Mem.Read ( + TxtDxeCtx->CpuIo, + EfiCpuIoWidthUint8, + (UINT64) TPM_STATUS_REG_ADDRESS, + 1, + &AccessReg + ); + ASSERT_EFI_ERROR (Status); + /// + /// if TPM.Access == 0xFF, TPM is not present + /// + if (AccessReg == 0xFF) { + return FALSE; + } + /// + /// Check tpmRegValidSts bit before checking establishment bit + /// + if ((AccessReg & 0x80) != 0x80) { + /// + /// Delay 1ms and read again + /// + gBS->Stall (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 ((AccessReg & 0x80) != 0x80) { + DEBUG ((EFI_D_ERROR, "TXTDXE: TPM Valid Status is not set!! TPM.ACCESS=%x\n", AccessReg)); + ASSERT (TRUE); + EFI_DEADLOOP (); + } + /// + /// The bit we're interested in uses negative logic: + /// If bit 0 == 1 then return False + /// Else return True + /// + return (AccessReg & 0x1) ? FALSE : TRUE; +} + +/** + Determines whether or not the platform has executed an TXT launch by + examining the TPM Establishment bit. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval TRUE - If the TPM establishment bit is asserted. + @retval FALSE - If the TPM establishment bit is unasserted. +**/ +BOOLEAN +IsTxtResetSet ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + EFI_STATUS Status; + UINT8 EstsReg; + + /// + /// TO-DO: We might locate TCG protocol to access TPM status + /// + /// + /// Read TPM status register + /// + Status = TxtDxeCtx->CpuIo->Mem.Read ( + TxtDxeCtx->CpuIo, + EfiCpuIoWidthUint8, + (UINT64) TXT_PUBLIC_BASE + TXT_ERROR_STATUS_REG_OFF, + 1, + &EstsReg + ); + ASSERT_EFI_ERROR (Status); + + return (EstsReg & 0x1) ? TRUE : FALSE; +} + +/** + Determines whether or not the platform requires initialization for TXT use. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval TRUE - If the the platoform should be configured for TXT. + @retval FALSE - If TXT is not to be used. +**/ +BOOLEAN +IsTxtEnabled ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + + UINT64 Ia32FeatureControl; + TXT_INFO_DATA *TxtInfoData; + + TxtInfoData = TxtDxeCtx->TxtInfoData; + + /// + /// If TxtInfoHob reported TXT disabled, return FALSE to indicate TXT should be be used + /// + if (TxtInfoData->TxtMode == 0) { + return FALSE; + } + + Ia32FeatureControl = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL); + + return ((Ia32FeatureControl & TXT_OPT_IN_VMX_AND_SMX_MSR_VALUE) == TXT_OPT_IN_VMX_AND_SMX_MSR_VALUE) ? TRUE : FALSE; +} + +/** + 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; +} + +/** + 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. + + @retval None +**/ +VOID +AppendElement ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx, + IN UINT32 Type, + IN VOID *Buffer, + OUT UINT32 *Size + ) +{ + VOID *Element; + UINT32 NumberOfAcm; + UINT64 *AcmBase; + + NumberOfAcm = 1; + AcmBase = NULL; + Element = NULL; + *Size = 0; + + switch (Type) { + case HEAP_EXTDATA_TYPE_BIOS_SPEC_VER: + /// + /// Fill BIOS spec ver element + /// + Element = AllocatePool (sizeof (HEAP_BIOS_SPEC_VER_ELEMENT)); + + 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 + /// + Element = AllocatePool (sizeof (HEAP_BIOSACM_ELEMENT) + NumberOfAcm * sizeof (UINT64)); + + 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 = TxtDxeCtx->TxtInfoData->BiosAcmBase; + } + break; + + case HEAP_EXTDATA_TYPE_END: + /// + /// Fill end type element + /// + Element = AllocatePool (sizeof (HEAP_EXT_DATA_ELEMENT)); + + 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); + FreePool (Element); + } +} + +/** + 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_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + EFI_PHYSICAL_ADDRESS TopAddr; + UINT64 *Ptr64; + UINT64 Value64; + UINT32 Value32; + UINT64 TxtHeapMemoryBase; + UINT64 TxtSinitMemoryBase; + BOOLEAN Locked; + BIOS_OS_DATA_REGION *BiosOsDataRegion; + TXT_INFO_DATA *TxtInfoData; + UINT8 *Ptr8; + + TxtHeapMemoryBase = 0; + TxtSinitMemoryBase = 0; + Locked = FALSE; + Ptr8 = NULL; + Value32 = 0; + + TxtInfoData = TxtDxeCtx->TxtInfoData; + + if ((TxtInfoData == 0) || + (TxtInfoData->TxtDprMemoryBase == 0) || + (TxtInfoData->TxtDprMemorySize == 0) || + (TxtInfoData->TxtHeapMemorySize == 0) || + (TxtInfoData->SinitMemorySize == 0) + ) { + return EFI_UNSUPPORTED; + } else { + /// + /// Use address passed from PEI + /// + TopAddr = TxtInfoData->TxtDprMemoryBase + TxtInfoData->TxtDprMemorySize; + + TxtHeapMemoryBase = (UINT64) (TopAddr - TxtInfoData->TxtHeapMemorySize); + + TxtSinitMemoryBase = TxtHeapMemoryBase - TxtInfoData->SinitMemorySize; + } + /// + /// Program TXT Device Memory Chipset Registers and record them in + /// BootScript so they will be saved and restored on S3 + /// + ASSERT ((TopAddr & 0x0FFFFF) == 0); + + /// + /// DPR registers + /// + Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_DPR_SIZE_REG_OFF); + Value64 = RShiftU64 (TxtInfoData->TxtDprMemorySize, 16) | 1; + *Ptr64 = Value64 | TopAddr; + /// + /// Assert error if programmed value is different from requested. This + /// means error is requested size. + /// + Value64 = *Ptr64; + ASSERT ((LShiftU64 ((Value64 & 0xFFE), 16)) == TxtInfoData->TxtDprMemorySize); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINT64) (UINTN) (Ptr64), + 2, + &Value64 + ); + + /// + /// HEAP Registers + /// Program size register first + /// + Ptr64 = (UINT64 *) (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 + /// + *Ptr64 = TEST_PATTERN; + Value64 = *Ptr64; + if (Value64 != TEST_PATTERN) { + Locked = TRUE; + } else { + /// + /// To be safe invert pattern and try again + /// + *Ptr64 = (UINT64) ~TEST_PATTERN; + Value64 = *Ptr64; + if (Value64 != (UINT64) ~TEST_PATTERN) { + Locked = TRUE; + } + } + + if (!Locked) { + + *Ptr64 = TxtInfoData->TxtHeapMemorySize; + /// + /// Assert error if programmed value is different from requested. This + /// means error is requested size. + /// + Value64 = *Ptr64; + ASSERT (Value64 == TxtInfoData->TxtHeapMemorySize); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINT64) (UINTN) (Ptr64), + 2, + &Value64 + ); + + /// + /// Program base register. + /// + Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_HEAP_BASE_REG_OFF); + *Ptr64 = TxtHeapMemoryBase; + + /// + /// Assert error if programmed value is different from requested. This + /// means error is requested size. + /// + Value64 = *Ptr64; + ASSERT (Value64 == TxtHeapMemoryBase); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINT64) (UINTN) (Ptr64), + 2, + &Value64 + ); + } + /// + /// SINIT Registers + /// Program size register first + /// + Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_SINIT_SIZE_REG_OFF); + *Ptr64 = TxtInfoData->SinitMemorySize; + /// + /// Assert error if programmed value is different from requested. This + /// means error is requested size. + /// + Value64 = *Ptr64; + ASSERT (Value64 == TxtInfoData->SinitMemorySize); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINT64) (UINTN) (Ptr64), + 2, + &Value64 + ); + + /// + /// Program base register + /// + Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_SINIT_BASE_REG_OFF); + *Ptr64 = TxtSinitMemoryBase; + /// + /// Assert error if programmed value is different from requested. This + /// means error is requested size. + /// + Value64 = *Ptr64; + ASSERT (Value64 == TxtSinitMemoryBase); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINT64) (UINTN) (Ptr64), + 2, + &Value64 + ); + + /// + /// Make sure TXT Device Memory has been zeroed + /// + ZeroMem ( + (VOID *) ((UINTN) TxtSinitMemoryBase), + (UINTN) (TopAddr - TxtSinitMemoryBase) + ); + + if (TxtInfoData->TgaSize) { + ; + /// + /// Placeholder for Trusted graphics support + /// + } + + Ptr64 = (UINT64 *) TxtHeapMemoryBase; + *Ptr64 = sizeof (BIOS_OS_DATA_REGION); + /// + /// BiosOsDataSize plus sizew of data size feld itself + /// + BiosOsDataRegion = (BIOS_OS_DATA_REGION *) (Ptr64 + 1); + BiosOsDataRegion->Version = BIOS_OS_DATAREGION_VERSION; + BiosOsDataRegion->BiosSinitSize = 0; + BiosOsDataRegion->LcpPdBase = TxtInfoData->TxtLcpPdBase; + BiosOsDataRegion->LcpPdSize = TxtInfoData->TxtLcpPdSize; + BiosOsDataRegion->NumOfLogicalProcessors = (UINT32) (TxtDxeCtx->CpuCount); + BiosOsDataRegion->Flags = TxtInfoData->Flags; + Ptr8 = (UINT8 *) (UINTN) &(BiosOsDataRegion->ExtData); + AppendElement (TxtDxeCtx, HEAP_EXTDATA_TYPE_BIOS_SPEC_VER, Ptr8, &Value32); + Ptr8 += Value32; + AppendElement (TxtDxeCtx, HEAP_EXTDATA_TYPE_BIOSACM, Ptr8, &Value32); + Ptr8 += Value32; + AppendElement (TxtDxeCtx, HEAP_EXTDATA_TYPE_END, Ptr8, &Value32); + Value64 = (UINT64) Ptr8 - TxtHeapMemoryBase + Value32; + *Ptr64 = Value64; + + return EFI_SUCCESS; +} + +/** + Adds and allocates architecturally defined TXT Configuration Space memory + region to GCD. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - Always. +**/ +EFI_STATUS +ReserveTxtConfigSpace ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS BaseAddr; + + BaseAddr = TXT_PRIVATE_BASE; + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeReserved, + TXT_PRIVATE_BASE, + TXT_CONFIG_SPACE_LENGTH, + 0 + ); + + ASSERT_EFI_ERROR (Status); + + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeReserved, + 12, ///< 4K Boundary + TXT_CONFIG_SPACE_LENGTH, + &BaseAddr, + TxtDxeCtx->ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Invokes TxtDxeLibLaunchBiosAcm to execute the SCHECK function. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - Always. +**/ +EFI_STATUS +DoScheck ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + return TxtDxeLibLaunchBiosAcm (TxtDxeCtx, TXT_LAUNCH_SCHECK); +} + +/** + Invokes TxtDxeLibLaunchBiosAcm to reset the TPM's establishment bit. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - Always. +**/ +EFI_STATUS +ResetTpmEstBit ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + return TxtDxeLibLaunchBiosAcm (TxtDxeCtx, TXT_RESET_EST_BIT); +} + +/** + Sets up the system and then launches the TXT BIOS ACM to run the function + requested by AcmFunction. + + @param[in] AcmFunction - Constant that represents the function from the BIOS ACM + that should be executed. + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - BIOS ACM is set up. + @retval EFI_INVALID_PARAMETER - Wrong data in TxtInfoHob. + @retval EFI_NOT_FOUND - BIOS ACM is not found +**/ +EFI_STATUS +TxtDxeLibLaunchBiosAcm ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx, + IN UINT64 AcmFunction + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + UINTN CpuCount; + UINTN MyCpuNumber; + UINTN Index; + UINTN i; + EFI_MP_SERVICES_PROTOCOL *MpService; + + UINTN NoHandles; + EFI_HANDLE *Buffer; + UINTN Size; + UINT32 FvStatus; + EFI_FV_FILETYPE FileType; + EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN NumPages; + EFI_PHYSICAL_ADDRESS Addr; + EFI_PHYSICAL_ADDRESS AlignedAddr; + + FwVol = NULL; + /// + /// Initialize local variables + /// + CpuCount = TxtDxeCtx->CpuCount; + MpService = TxtDxeCtx->MpService; + Size = 0; + FvStatus = 0; + NumPages = 0; + Addr = 0; + + if (TxtDxeCtx->TxtInfoData == NULL) { + return EFI_INVALID_PARAMETER; + } + /// + /// Get current running CPU number + /// + Status = MpService->WhoAmI ( + MpService, + &MyCpuNumber + ); + ASSERT_EFI_ERROR (Status); + + if ((TxtDxeCtx->TxtInfoData->BiosAcmBase == 0) || (TxtDxeCtx->TxtInfoData->BiosAcmSize == 0)) { + /// + /// If no information about placement of TXT BIOS ACM has been + /// passed from PEI - find it and load into memory dynamically. + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &NoHandles, + &Buffer + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + for (i = 0; i < NoHandles; i++) { + + Status = gBS->HandleProtocol ( + Buffer[i], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &FwVol + ); + + ASSERT_EFI_ERROR (Status); + + /// + /// No output buffer - get size only + /// + Status = FwVol->ReadFile ( + FwVol, + &mTxtBiosAcmPeiFileGuid, + NULL, + &Size, + &FileType, + &Attributes, + &FvStatus + ); + if (Status == EFI_SUCCESS) { + break; + } + } + + ASSERT (Size); + /// + /// Assert if file not found. + /// + FreePool (Buffer); + + if (FwVol == NULL) { + return EFI_NOT_FOUND; + } + /// + /// Allocate 4K aligned memory to load BIOS ACM. For this allocate + /// 1 page more than BIOS ACM size. + /// + NumPages = (Size + EFI_PAGE_SIZE - 1) / EFI_PAGE_SIZE; + + /// + /// Allocate buffer for BIOS ACM + /// + Status = (gBS->AllocatePages) (AllocateAnyPages, EfiRuntimeServicesData, NumPages, &Addr); + + ASSERT_EFI_ERROR (Status); + + AlignedAddr = Addr &~(EFI_PAGE_SIZE - 1); + AlignedAddr = AlignedAddr < Addr ? (AlignedAddr + EFI_PAGE_SIZE) : AlignedAddr; + + /// + /// Read BIOS ACM into prepared buffer. + /// + Status = FwVol->ReadFile ( + FwVol, + &mTxtBiosAcmPeiFileGuid, + ((VOID **) &AlignedAddr), + &Size, + &FileType, + &Attributes, + &FvStatus + ); + } else { + /// + /// Use address passed from PEI + /// + AlignedAddr = TxtDxeCtx->TxtInfoData->BiosAcmBase; + } + /// + /// Save AP configuration. Run on one AP since all must be programmed + /// identically + /// + MpService->StartupThisAP ( + MpService, + (EFI_AP_PROCEDURE) ApSaveConfig, + 1, + NULL, + 0, + NULL + ); + + /// + /// Initialize APs. Prepare data for DoApInit + /// + mAcmBase = AlignedAddr; + mMcuAddr = TxtDxeCtx->TxtInfoData->McuUpdateDataAddr; + + DisableSmiSources (TxtDxeCtx, TRUE); + +#if defined(TXT_RLP_INIT) && (TXT_RLP_INIT == 1) + /// + /// Execute DoApInit on every AP + /// + MpService->StartupAllAPs ( + MpService, + (EFI_AP_PROCEDURE) DoApInit, + TRUE, + NULL, + MP_TIMEOUT_FOR_STARTUP_ALL_APS, + NULL, + NULL + ); +#endif + /// + /// Disable every AP and put in WFS state + /// + for (Index = 0; Index < CpuCount; Index++) { + if (Index != MyCpuNumber) { + /// + /// Halt CPU otherwise it will not be re-enabled + /// + Status = MpService->EnableDisableAP ( + MpService, + Index, + FALSE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = MpService->SendIPI ( + MpService, + Index, + 0, + DELIVERY_MODE_INIT + ); + ASSERT_EFI_ERROR (Status); + } + } + /// + /// Launch the BIOS ACM to run the requested function + /// + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + + LaunchBiosAcm (AlignedAddr, AcmFunction); + + gBS->RestoreTPL (OldTpl); + + /// + /// Free memory only if it was allocated + /// + if (Addr != 0) { + (gBS->FreePages)(Addr, NumPages); + } + /// + /// Restart APs + /// + for (Index = 0; Index < CpuCount; Index++) { + if (Index != MyCpuNumber) { + Status = MpService->EnableDisableAP ( + MpService, + Index, + TRUE, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + } + /// + /// Restore AP configuration + /// + Status = MpService->StartupAllAPs ( + MpService, + (EFI_AP_PROCEDURE) ApRestoreConfig, + TRUE, + NULL, + MP_TIMEOUT_FOR_STARTUP_ALL_APS, + NULL, + NULL + ); + + ASSERT_EFI_ERROR (Status); + + DisableSmiSources (TxtDxeCtx, FALSE); + + return EFI_SUCCESS; +} + +/** + Disable or restore possible SMI sources before or after POST SCHECK + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + @param[in] Operation - Boolean value telling what operation is requested: + TRUE - to save and then disable possible SMI sources + FALSE - to restore original SMI settings + + @retval EFI_SUCCESS - always return EFI_SUCCESS +**/ +EFI_STATUS +DisableSmiSources ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx, + IN BOOLEAN Operation + ) +{ + EFI_STATUS Status; + UINT64 GlobalSmiControlIoAddr; + UINT32 LocalApicBaseAddr; + static UINT64 SavedIa32ThermInterruptMSR; + static UINT32 SavedSmiControl; + static UINT32 SavedApicThermalValue; + BOOLEAN x2ApicEnabled; + + x2ApicEnabled = (BOOLEAN) (((AsmReadMsr64 (MSR_IA32_APIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10); + GlobalSmiControlIoAddr = TxtDxeCtx->TxtInfoData->PmBase + 0x30; + LocalApicBaseAddr = ((UINT32) AsmReadMsr64 (MSR_IA32_APIC_BASE)) & BASE_ADDR_MASK; + + if (Operation == TRUE) { + /// + /// Save IA32_THERMAL_INTERRUPT MSR and disable the interrupts + /// + SavedIa32ThermInterruptMSR = AsmReadMsr64 ((UINT32) IA32_THERM_INTERRUPT); + AsmWriteMsr64 ( + (UINT32) IA32_THERM_INTERRUPT, + (UINT64) (SavedIa32ThermInterruptMSR &~(BIT0 + BIT1 + BIT2 + BIT4 + BIT15 + BIT23)) + ); + /// + /// Save THERMAL LVT in local APIC and mask THERMAL LVT + /// + if (x2ApicEnabled) { + SavedApicThermalValue = (UINT32) AsmReadMsr64 (MSR_EXT_XAPIC_LVT_THERM); + AsmWriteMsr64 ( + MSR_EXT_XAPIC_LVT_THERM, + ((SavedApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | (B_INTERRUPT_MASK | V_MODE_SMI)) + ); + } else { + SavedApicThermalValue = *(UINT32 *) (UINTN) (LocalApicBaseAddr + LOCAL_APIC_THERMAL_DEF); + *(UINT32 *) (UINTN) (LocalApicBaseAddr + LOCAL_APIC_THERMAL_DEF) = (UINT32) ((SavedApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | (B_INTERRUPT_MASK | V_MODE_SMI)); + } + /// + /// Save SMI control register and try to disable all SMIs indivitually. + /// + SavedSmiControl = IoRead32 ((UINTN) GlobalSmiControlIoAddr); + /// + /// We can not disable Global SMI since it should be locked after SCHECK. we can only disable SMI sources indivitually. + /// Call to TxtDxeOemDisableSmi() for platform specific SMIs. + /// + Status = TxtDxeOemDisableSmi (TxtDxeCtx, TRUE); + ASSERT_EFI_ERROR (Status); + + 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 indivitually. + /// Restore original SMI setting after SCHECK + /// Call to TxtDxeOemDisableSmi() for platform specific SMIs. + /// + Status = TxtDxeOemDisableSmi (TxtDxeCtx, FALSE); + ASSERT_EFI_ERROR (Status); + + IoWrite32 ( + (UINTN) GlobalSmiControlIoAddr, + (UINT32) (SavedSmiControl) + ); + /// + /// Restore IA32_THERMAL_INTERRUPT MSR + /// + AsmWriteMsr64 ( + (UINT32) IA32_THERM_INTERRUPT, + (UINT64) SavedIa32ThermInterruptMSR + ); + if (x2ApicEnabled) { + AsmWriteMsr64 (MSR_EXT_XAPIC_LVT_THERM, SavedApicThermalValue); + } else { + *(UINT32 *) (UINTN) (LocalApicBaseAddr + LOCAL_APIC_THERMAL_DEF) = (UINT32) SavedApicThermalValue; + + } + } + + return EFI_SUCCESS; +} + +/** + Read policy protocol to reset AUX content + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - No error happend + @retval EFI_NOT_FOUND - TxtPolicyProtocol is not found +**/ +EFI_STATUS +ResetTpmAux ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + /// + /// Check if TxtPolicy protocol installed + /// + if (TxtDxeCtx->CpuPlatformPolicy == NULL) { + return EFI_NOT_FOUND; + } + /// + /// + /// + if (TxtDxeCtx->CpuPlatformPolicy->SecurityConfig->TxtFunctionConfig->ResetAux == 1) { + DEBUG ((EFI_D_INFO, "TXTDXE: Reset AUX content\n")); + Status = TxtDxeLibLaunchBiosAcm (TxtDxeCtx, TXT_RESET_AUX); + } + + return Status; +} diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h new file mode 100644 index 0000000..573a06a --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h @@ -0,0 +1,289 @@ +/** @file + This file contains function definitions that can determine + the TXT capabilities of a platform during DXE and perform + certain specific platform tasks that are required for TXT + during DXE. + +@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 _TXT_DXE_LIB_H_ +#define _TXT_DXE_LIB_H_ + +#include EFI_PROTOCOL_DEFINITION (MpService) +#include "CpuAccess.h" + +#include EFI_PROTOCOL_DEFINITION (BootScriptSave) +#include EFI_PROTOCOL_DEFINITION (CpuIo) +#include EFI_GUID_DEFINITION (TxtInfoHob) +#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy) + +/// +/// The following switch is used in EfiScriptLib.h file. If enabled - +/// forces linking to EfiScriptLib library +/// +#define BASE_ADDR_MASK 0xFFFFF000 +#define TEST_PATTERN 0x5A5A5A5A5A5A5A5A +#define MP_TIMEOUT_FOR_STARTUP_ALL_APS 0 ///< Set 0 for BSP always wait for APs + +/// +/// Chispet register +/// +#define TXT_OPT_IN_VMX_AND_SMX_MSR_VALUE 0xFF03 + +#define IA32_MTRR_PHYSBASE0 0x200 +#define IA32_MTRR_PHYSMASK9 0x213 + +#define LOCAL_APIC_THERMAL_DEF 0x330 + #define B_INTERRUPT_MASK (1 << 16) + #define B_DELIVERY_MODE (0x07 << 8) + #define V_MODE_SMI (0x02 << 8) + #define B_VECTOR (0xFF << 0) + +#pragma pack(push, 1) +typedef struct _TXT_DXE_LIB_CONTEXT_ { + EFI_HANDLE ImageHandle; + EFI_SYSTEM_TABLE *SystemTable; + EFI_CPU_IO_PROTOCOL *CpuIo; + EFI_MP_SERVICES_PROTOCOL *MpService; + + UINTN CpuCount; + TXT_INFO_DATA *TxtInfoData; + DXE_CPU_PLATFORM_POLICY_PROTOCOL *CpuPlatformPolicy; +} TXT_DXE_LIB_CONTEXT; +#pragma pack(pop) + +/** + This routine initializes and collects all Protocols and data required + by the routines in this file. + + @param[in] ImageHandle - A pointer to the Image Handle for this file. + @param[in] SystemTable - A pointer to the EFI System Table + @param[in] TxtDxeCtx - A pointer to a caller allocated data structure that contains + all of the Protocols and data required by the routines + in this file. + + @retval EFI_SUCCESS - Return EFI_SUCCESS if no error happen + @retval EFI_UNLOAD_IMAGE - If TxtInfoHob is not found +**/ +EFI_STATUS +InitializeTxtDxeLib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN OUT TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); +/** + 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 + ); +/** + Determines whether or not the platform has executed an TXT launch by + examining the TPM Establishment bit. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval TRUE - If the TPM establishment bit is asserted. + @retval FALSE - If the TPM establishment bit is unasserted. +**/ +BOOLEAN +IsTxtEstablished ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); + +/** + Determines whether or not the platform has executed an TXT launch by + examining the TPM Establishment bit. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval TRUE - If the TPM establishment bit is asserted. + @retval FALSE - If the TPM establishment bit is unasserted. +**/ +BOOLEAN +IsTxtResetSet ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); +/** + Determines whether or not the platform requires initialization for TXT use. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval TRUE - If the the platoform should be configured for TXT. + @retval FALSE - If TXT is not to be used. +**/ +BOOLEAN +IsTxtEnabled ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); +/** + Adds and allocates architecturally defined TXT Configuration Space memory + region to GCD. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - Always. +**/ +EFI_STATUS +ReserveTxtConfigSpace ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); +/** + 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. + @retval EFI_ERROR - TXT Device memory not awailable. +**/ +EFI_STATUS +SetupTxtDeviceMemory ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); +/** + Invokes TxtDxeLibLaunchBiosAcm to execute the SCHECK function. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - Always. +**/ +EFI_STATUS +DoScheck ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); +/** + Invokes TxtDxeLibLaunchBiosAcm to reset the TPM's establishment bit. + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - Always. +**/ +EFI_STATUS +ResetTpmEstBit ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); +/** + Sets up the system and then launches the TXT BIOS ACM to run the function + requested by AcmFunction. + + @param[in] AcmBase - Base address of BIOS ACM location + @param[in] Funct - Function number of BIOS ACM to be executed + + @retval EFI_SUCCESS - Always. +**/ +VOID +LaunchBiosAcm ( + IN UINT64 AcmBase, + IN UINT64 Funct + ); + +/** + Sets up the system and then launches the TXT BIOS ACM to run the function + requested by AcmFunction. + + @param[in] AcmFunction - Constant that represents the function from the BIOS ACM + that should be executed. + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - Always. +**/ +EFI_STATUS +TxtDxeLibLaunchBiosAcm ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx, + IN UINT64 AcmFunction + ); +/** + AP initial routine executed through MP service for TXT SCHECK +**/ +VOID +DoApInit ( + VOID + ); + +/** + Save AP configuration routine executed through MP service for TXT SCHECK +**/ +VOID +ApSaveConfig ( + VOID + ); + +/** + Restore AP configuration routine executed through MP service for TXT SCHECK +**/ +VOID +ApRestoreConfig ( + VOID + ); + +/** + Disable or restore possible SMI sources before or after POST SCHECK + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + @param[in] Operation - Boolean value telling what operation is requested: + TRUE - to save and then disable possible SMI sources + FALSE - to restore original SMI settings + + @retval EFI_SUCCESS - always return EFI_SUCCESS +**/ +EFI_STATUS +DisableSmiSources ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx, + IN BOOLEAN Operation + ); + +/** + This function gets called before/after run the SCHECK function, intend to avoid platform specific SMIs to interfere in BIOS POST + if BIOS SMM MP services or synchonization code is not well considered that some of APs are not waken up from Wait-for-SIPI state. + Function should preserve original SMI enabling setting in augument is TRUE, and then restore it in augurment is FALSE. + The caller is DisableSmiSources() in TxtDxeLib.c + + @param[in] Operation = TRUE - Calling before SCHECK to saved and disable platform specific SMIs setting + = FALSE - Calling after SCHECK to restore platform specific SMIs setting + + @retval EFI_SUCCESS - Always. +**/ +extern +EFI_STATUS +EFIAPI +TxtDxeOemDisableSmi ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx, + IN BOOLEAN Operation + ); + +/** + Read policy protocol to reset AUX content + + @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure + + @retval EFI_SUCCESS - No error happend + @retval EFI_NOT_FOUND - TxtPolicyProtocol is not found +**/ +EFI_STATUS +ResetTpmAux ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx + ); + +#endif diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c new file mode 100644 index 0000000..bed83ec --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c @@ -0,0 +1,78 @@ +/** @file + This file contain OEM/Platform implementation for TXT in DXE phase. It represents an abstract outline of the + steps required during DXE for enabling TXT. Each individual step is further + abstracted behind a function call interface. This is intended to minimize + the need to modify this file when porting TXT to future platforms. + +@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 +**/ + +/// +/// 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 "Txt.h" +#include "TxtDxeLib.h" +#endif + +/** + This function gets called before/after run the SCHECK function, intend to avoid platform specific SMIs to interfere in BIOS POST + if BIOS SMM MP services or synchonization code is not well considered that some of APs are not waken up from Wait-for-SIPI state. + Function should preserve original SMI enabling setting in augument is TRUE, and then restore it in augurment is FALSE. + The caller is DisableSmiSources() in TxtDxeLib.c + + @param[in] TxtDxeCtx - Point to TXT_DXE_LIB_CONTEXT structure + @param[in] Operation = TRUE - Calling before SCHECK to saved and disable platform specific SMIs setting + = FALSE - Calling after SCHECK to restore platform specific SMIs setting + + @retval EFI_SUCCESS - Always. + + **/ +EFI_STATUS +EFIAPI +TxtDxeOemDisableSmi ( + IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx, + IN BOOLEAN Operation + ) +{ + static UINT16 SavedSmiControlDev29; + static UINT16 SavedSmiControlDev26; + + if (Operation == TRUE) { + /// + /// Save and disable OEM/Platform specific SMIs + /// + /// Disable EHCI SMIs before giving control to TXT ACM. EHCI controller generating SMI during TXT ACM results in USB kbd issue + /// + SavedSmiControlDev26 = MmioRead16 (MmPciAddress (0, 0, 0, 0x1A, 0x6C)); + SavedSmiControlDev29 = MmioRead16 (MmPciAddress (0, 0, 0, 0x1D, 0x6C)); + + MmioWrite16 (MmPciAddress (0, 0, 0, 0x1A, 0x6C), 0); + MmioWrite16 (MmPciAddress (0, 0, 0, 0x1D, 0x6C), 0); + } else { + /// + /// Restore or re-enable OEM/Platform specific SMIs + /// + /// Enable EHCI SMIs before giving control to TXT ACM. + /// + MmioWrite16 (MmPciAddress (0, 0, 0, 0x1A, 0x6C), SavedSmiControlDev26); + MmioWrite16 (MmPciAddress (0, 0, 0, 0x1D, 0x6C), SavedSmiControlDev29); + } + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc new file mode 100644 index 0000000..027e32e --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc @@ -0,0 +1,494 @@ +;@file +; This file contains macros supporting 64 bit assembly +; +;@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 +; + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: _movq +; +; Input: rxx - general perpose 64 bit register +; mmx - MMX register +; +; Output: None +; +; Registers: +; +; Description: Performs "movq rxx, mmx" and "movq mmx, rxx" operations +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +_movq MACRO toReg:REQ, frReg:REQ + LOCAL gReg, mReg, op + db 48h ; ; REX.W prefix +IFIDNI <toReg>, <rax> + gReg = 00h + op = 7Eh +ELSEIFIDNI <toReg>, <rcx> + gReg = 01h + op = 7Eh +ELSEIFIDNI <toReg>, <rdx> + gReg = 02h + op = 7Eh +ELSEIFIDNI <toReg>, <rbx> + gReg = 03h + op = 7Eh +ELSEIFIDNI <toReg>, <rsp> + gReg = 04h + op = 7Eh +ELSEIFIDNI <toReg>, <rbp> + gReg = 05h + op = 7Eh +ELSEIFIDNI <toReg>, <rsi> + gReg = 06h + op = 7Eh +ELSEIFIDNI <toReg>, <rdi> + gReg = 07h + op = 7Eh +ELSEIFIDNI <toReg>, <mm0> + mReg = 0C0h + 0 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm1> + mReg = 0C0h + 1 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm2> + mReg = 0C0h + 2 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm3> + mReg = 0C0h + 3 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm4> + mReg = 0C0h + 4 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm5> + mReg = 0C0h + 5 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm6> + mReg = 0C0h + 6 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm7> + mReg = 0C0h + 7 * 08h + op = 6Eh +ENDIF + +;; If op = 7E format movq rxx, mmx + +IFIDNI <frReg>, <rax> + gReg = 00h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rcx> + gReg = 01h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rdx> + gReg = 02h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rbx> + gReg = 03h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rsp> + gReg = 04h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rbp> + gReg = 05h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rsi> + gReg = 06h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rdi> + gReg = 07h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm0> + mReg = 0C0h + 0 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm1> + mReg = 0C0h + 1 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm2> + mReg = 0C0h + 2 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm3> + mReg = 0C0h + 3 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm4> + mReg = 0C0h + 4 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm5> + mReg = 0C0h + 5 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm6> + mReg = 0C0h + 6 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm7> + mReg = 0C0h + 7 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ENDIF + db 0Fh, op, gReg + mReg +ENDM + + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: _movd +; +; Input: exx - general perpose 32 bit register +; mmx - MMX register +; +; Output: None +; +; Registers: +; +; Description: Performs "movd exx, mmx" and "movd mmx, exx" operations +; coded to perform in compatibility or protected mode but +; assembled by ml64 +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + + +_movd MACRO toReg:REQ, frReg:REQ + LOCAL gReg, mReg, op +IFIDNI <toReg>, <eax> + gReg = 00h + op = 7Eh +ELSEIFIDNI <toReg>, <ecx> + gReg = 01h + op = 7Eh +ELSEIFIDNI <toReg>, <edx> + gReg = 02h + op = 7Eh +ELSEIFIDNI <toReg>, <ebx> + gReg = 03h + op = 7Eh +ELSEIFIDNI <toReg>, <esp> + gReg = 04h + op = 7Eh +ELSEIFIDNI <toReg>, <ebp> + gReg = 05h + op = 7Eh +ELSEIFIDNI <toReg>, <esi> + gReg = 06h + op = 7Eh +ELSEIFIDNI <toReg>, <edi> + gReg = 07h + op = 7Eh +ELSEIFIDNI <toReg>, <mm0> + mReg = 0C0h + 0 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm1> + mReg = 0C0h + 1 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm2> + mReg = 0C0h + 2 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm3> + mReg = 0C0h + 3 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm4> + mReg = 0C0h + 4 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm5> + mReg = 0C0h + 5 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm6> + mReg = 0C0h + 6 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm7> + mReg = 0C0h + 7 * 08h + op = 6Eh +ENDIF + +;; If op = 7E format movq exx, mmx + +IFIDNI <frReg>, <eax> + gReg = 00h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <ecx> + gReg = 01h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <edx> + gReg = 02h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <ebx> + gReg = 03h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <esp> + gReg = 04h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <ebp> + gReg = 05h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <esi> + gReg = 06h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <edi> + gReg = 07h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm0> + mReg = 0C0h + 0 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm1> + mReg = 0C0h + 1 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm2> + mReg = 0C0h + 2 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm3> + mReg = 0C0h + 3 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm4> + mReg = 0C0h + 4 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm5> + mReg = 0C0h + 5 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm6> + mReg = 0C0h + 6 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm7> + mReg = 0C0h + 7 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ENDIF + db 0Fh, op, gReg + mReg +ENDM + +;----------------------------------------------------------------------------- +; 64 bit macros +; + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: PUSHA_64 +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Saves all registers on stack +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +PUSHA_64 MACRO + push rsp + push rbp + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 +ENDM + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: POPA_64 +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Restores all registers from stack +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +POPA_64 MACRO + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + pop rbp + pop rsp +ENDM + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: START_FRAME +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Starts frame declaration. Creates variable to hold total +; size of all local vars. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +START_FRAME MACRO + SZ = 0 +ENDM + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: MAKE_LOCAL +; +; Input: ARG - var definition in form Label[Count]:QuolifiedType +; +; Output: None +; +; Registers: +; +; Description: Defines local procedure variable. Adds size of created variable +; to total size of locals. +; size of all local vars. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +MAKE_LOCAL MACRO ARG:REQ + LOCAL brk, rbrk, clm, lbl, cnt, qtp + brk INSTR <ARG>, <[> + rbrk INSTR <ARG>, <]> + clm INSTR <ARG>, <:> + IF brk GT 0 + lbl SUBSTR <ARG>, 1, brk-1 + cnt SUBSTR <ARG>, brk+1, rbrk-brk-1 + qtp SUBSTR <ARG>, clm+1 + LOCAL lbl[cnt]:qtp + ELSE + lbl SUBSTR <ARG>, 1, clm-1 + qtp SUBSTR <ARG>, clm+1 + LOCAL lbl:qtp + ENDIF + + SZ = SZ + sizeof lbl +ENDM + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: END_FRAME +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Ends frame declaration. Creates stack sufficient to hold +; all declared variables. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +END_FRAME MACRO + SZ = SZ + 10h ; Margin + enter SZ, 0 ; With spare room on stack + .allocstack SZ + .endprolog +ENDM + + + +SAVED_GDT TEXTEQU <mm0> +SAVED_SS TEXTEQU <mm1> +SAVED_ESP TEXTEQU <mm2> +SAVED_EBP TEXTEQU <mm3> +
\ No newline at end of file diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm new file mode 100644 index 0000000..f1c44b9 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm @@ -0,0 +1,364 @@ +;/*++ +; 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 +;--*/ +; +;/*++ +; +; Copyright (c) 1999 - 2011 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. +; +; +; Module Name: +; +; TxtDxeAp.asm +; +; Abstract: +; +; This file contains DXE AP initialization code. +; +;--*/ + + .xlist + include txt.inc + include mmx64.inc + .list + + + _TEXT SEGMENT + + +EXTERN mAcmBase:QWORD +EXTERN mMcuAddr:QWORD +EXTERN mApMtrrTab:QWORD +EXTERN mApIdt:QWORD +EXTERN mApCr4:QWORD +EXTERN mApSavedIa32ThermInterruptMSR:QWORD +EXTERN mApSavedApicThermalValue:DWORD + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: DoApInit +; +; Input: AcmBase - Base address of LT BIOS ACM +; McuAddr - Address of MCU patch in flash +; +; Output: None +; +; Registers: All are preserved +; +; Description: Initiatialize AP before GETSEC as per TXT BWG +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +DoApInit PROC FRAME + + START_FRAME + MAKE_LOCAL ACM_SIZE_TO_CACHE:QWORD + MAKE_LOCAL ACM_BASE_TO_CACHE:QWORD + MAKE_LOCAL NEXT_MTRR_INDEX:QWORD + MAKE_LOCAL NEXT_MTRR_SIZE:QWORD + ; jmp $ + END_FRAME + + pushf + cli + PUSHA_64 + ; + ; Check uCode was loaded or not + ; + mov rcx, MCU_REV_MSR + xor rax, rax + xor rdx, rdx + wrmsr + mov rax, 1 + cpuid + mov rcx, MCU_REV_MSR + rdmsr + or rdx, rdx + jnz uCode_loaded + + ; + ; Load uCode update + ; + mov rax, 1 + cpuid + + mov rax, mMcuAddr + lea rax, [rax + SIZEOF MCU] ; RAX -> MCU data (after header) + xor rdx, rdx + mov rcx, MCU_LOAD_MSR ; Trigger to load MCU + + wrmsr ; Load MCU + + mov rax, 1 + cpuid +uCode_loaded: +;----------------------------------------------------------------------------- +; +; Section: Initial RLPs cache requirements +; +; Description: Ensure CR0.CD and CR0.NW are cleared +; +;----------------------------------------------------------------------------- + ; + ; Clear CR0.CD and CR0.NW + ; + mov rax, cr0 + and rax, NOT (CR0_CD_MASK + CR0_NW_MASK) + mov cr0, rax + +;----------------------------------------------------------------------------- +; +; Section: Clean all MCi_STATUS MSR registers +; +; Description: MCA registers are cleaned +; +;----------------------------------------------------------------------------- + + mov rcx, MCG_CAP + rdmsr + movzx rbx, al ; ebx = MCR bank count + xor rax, rax ; Write 0 into all MCi_STATUS registers + xor rdx, rdx + mov rcx, MC0_STATUS + +McaErrorCleanLoopStart: + wrmsr + dec rbx + jz @F + add rcx, 4 ; ecx = number of MSRs per bank + jmp McaErrorCleanLoopStart + +@@: + + mov rcx,IA32_APIC_BASE + rdmsr + and rax,BIT11+BIT10 + cmp rax,BIT11+BIT10 + jne x2ApicDisabled + mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM + rdmsr + and eax, NOT (B_INTERRUPT_MASK + B_DELIVERY_MODE + B_VECTOR) + or eax, (B_INTERRUPT_MASK + V_MODE_SMI) + wrmsr + jmp @f +x2ApicDisabled: + ; mask thermal LVT + mov rcx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and rax, BASE_ADDR_MASK ; Just need the address + mov edx, [rax+LOCAL_APIC_THERMAL_DEF] + and edx, NOT (B_INTERRUPT_MASK + B_DELIVERY_MODE + B_VECTOR) + or edx, (B_INTERRUPT_MASK + V_MODE_SMI) + mov DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF], edx ;disable DTS SMIs +@@: + POPA_64 + popf + + leave + ret 0 +DoApInit ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: ApSaveConfig +; +; Input: None +; +; Output: None +; +; Registers: All are preserved +; +; Description: Saves AP configuration +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +ApSaveConfig PROC FRAME + START_FRAME + END_FRAME + + pushf + cli + PUSHA_64 + + mov rcx, IA32_MTRR_CAP + rdmsr + and rax, 0FFh + shl rax, 1 + mov rcx, rax + + lea rbx, mApMtrrTab + +SaveNextMtrr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + rdmsr + mov QWORD PTR [rbx+0], rax + mov QWORD PTR [rbx+8], rdx + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + add rbx, 10h + loop SaveNextMtrr + + mov rcx, IA32_MTRR_DEF_TYPE + rdmsr + mov QWORD PTR [rbx+0], rax + mov QWORD PTR [rbx+8], rdx + + lea rbx, mApIdt + sidt [rbx] + lea rbx, mApCr4 + mov rax, cr4 + mov QWORD PTR [rbx], rax + + mov rcx,IA32_APIC_BASE + rdmsr + and rax,BIT11+BIT10 + cmp rax,BIT11+BIT10 + jne x2ApicDisabled + mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM + rdmsr + lea rbx, mApSavedApicThermalValue + mov DWORD PTR [rbx], eax ; read and save thermal LVT + jmp @f +x2ApicDisabled: + + mov rcx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and rax, BASE_ADDR_MASK ; Just need the address + lea rbx, mApSavedApicThermalValue + mov edx, DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF] + mov DWORD PTR [rbx], edx ; read and save thermal LVT +@@: + mov rcx, EFI_MSR_IA32_THERM_INTERRUPT + rdmsr ; + lea rbx, mApSavedIa32ThermInterruptMSR + mov QWORD PTR [rbx+0], rax + mov QWORD PTR [rbx+8], rdx + ;disable THERMAL INT + and rax, NOT (BIT0+BIT1+BIT2+BIT4+BIT15+BIT23) + wrmsr + + wbinvd + + POPA_64 + popf + + leave + ret 0 +ApSaveConfig ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: ApRestoreConfig +; +; Input: None +; +; Output: None +; +; Registers: All are preserved +; +; Description: Saves AP configuration +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +ApRestoreConfig PROC FRAME + START_FRAME + END_FRAME + + pushf + cli + PUSHA_64 + + ; + ; Disable cache + ; + mov rax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW + or rax, CR0_CD_MASK OR CR0_NE_MASK + and rax, NOT CR0_NW_MASK + mov cr0, rax + wbinvd + + mov rcx, IA32_MTRR_CAP + rdmsr + and rax, 0FFh + shl rax, 1 + mov rcx, rax + + lea rbx, mApMtrrTab + +RestoreNextMtrr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + mov rax, QWORD PTR [rbx+0] + mov rdx, QWORD PTR [rbx+8] + wrmsr + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + add rbx, 10h + loop RestoreNextMtrr + + mov rax, QWORD PTR [rbx+0] + mov rdx, QWORD PTR [rbx+8] + mov rcx, IA32_MTRR_DEF_TYPE + wrmsr + + lea rbx, mApIdt + lidt FWORD PTR [rbx] + lea rbx, mApCr4 + mov rax, QWORD PTR [rbx] + mov cr4, rax + + mov rcx, EFI_MSR_IA32_THERM_INTERRUPT + lea rbx, mApSavedIa32ThermInterruptMSR + mov rax, QWORD PTR [rbx+0] + mov rdx, QWORD PTR [rbx+8] + wrmsr + + mov rcx,IA32_APIC_BASE + rdmsr + and rax,BIT11+BIT10 + cmp rax,BIT11+BIT10 + jne x2ApicDisabled + mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM + lea rbx, mApSavedApicThermalValue + mov eax,DWORD PTR [rbx] ;restore thermal LVT + xor rdx,rdx + wrmsr + jmp @f +x2ApicDisabled: + + mov rcx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and rax, BASE_ADDR_MASK ; Just need the address + lea rbx, mApSavedApicThermalValue + mov edx, DWORD PTR [rbx] + mov DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF], edx ; restore thermal LVT +@@: + ; + ; Enable cache + ; + mov rax, cr0 + and rax, NOT CR0_CD_MASK + mov cr0, rax + + POPA_64 + popf + + leave + ret 0 +ApRestoreConfig ENDP + +_TEXT ENDS + + END diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm new file mode 100644 index 0000000..00f9c87 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm @@ -0,0 +1,712 @@ +;/*++ +; 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 +;--*/ +; +;/*++ +; +; Copyright (c) 1999 - 2011 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. +; +; +; Module Name: +; +; TxtDxeBsp.asm +; +; Abstract: +; +; This file contains code to launch BIOS ACM functions in DXE phase +; +;--*/ + .xlist + include txt.inc + include mmx64.inc + .list + + + _TEXT SEGMENT + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: LaunchBiosAcm +; +; Input: AcmBase - Base address of LT BIOS ACM +; Function - function number to execute +; +; Output: None +; +; Registers: None are preserved +; +; Description: Setup GETSEC environment (protected mode, mtrrs, etc) and +; invoke GETSEC:ENTERACCS with requested BIOS ACM entry point. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +LaunchBiosAcm PROC FRAME + + START_FRAME + MAKE_LOCAL AcmBase:QWORD + MAKE_LOCAL Funct:QWORD + MAKE_LOCAL BIOS_GDT[2]:QWORD + MAKE_LOCAL CompModeSel:QWORD + MAKE_LOCAL CompModeOff:QWORD + MAKE_LOCAL LongModeSel:QWORD + MAKE_LOCAL LongModeOff:QWORD + MAKE_LOCAL SavedCR3:QWORD + MAKE_LOCAL SavedCR4:QWORD + MAKE_LOCAL SavedDS:QWORD + MAKE_LOCAL SavedES:QWORD + MAKE_LOCAL SavedGS:QWORD + MAKE_LOCAL SavedFS:QWORD + MAKE_LOCAL SavedMiscEnablesRax:QWORD + MAKE_LOCAL SavedMiscEnablesRdx:QWORD + MAKE_LOCAL MtrrTab[2*(IA32_MTRR_PHYSMASK9 - IA32_MTRR_PHYSBASE0 + 1)]:QWORD + MAKE_LOCAL ACM_SIZE_TO_CACHE:QWORD + MAKE_LOCAL ACM_BASE_TO_CACHE:QWORD + MAKE_LOCAL NEXT_MTRR_INDEX:QWORD + MAKE_LOCAL NEXT_MTRR_SIZE:QWORD + MAKE_LOCAL MTRR_COUNT:QWORD + MAKE_LOCAL MtrrTypeRax:QWORD + MAKE_LOCAL MtrrTypeRdx:QWORD + END_FRAME + + ; + ; Save input parameters + ; + mov AcmBase, rcx + + mov Funct, rdx + + sgdt BIOS_GDT ; save gdtr + + ; + ; Save the general purpose register state + ; + pushf + cli + + PUSHA_64 + ; + ; Tell where we are + ; + in ax, 80h + mov ah, BYTE PTR Funct + or ah, PORT80_CODE_PREFIX + out 80h, ax + ; + ; Save segment registers. + ; + mov ax, ds + mov SavedDS, rax + mov ax, es + mov SavedES, rax + mov ax, gs + mov SavedGS, rax + mov ax, fs + mov SavedFS, rax + + ; Save cr4 + ; + mov rax, cr4 + mov SavedCR4, rax + + ; + ; Save IA32_MISC_ENABLES MSR + ; + mov rcx, IA32_MISC_ENABLE_MSR + rdmsr + mov SavedMiscEnablesRax, rax + mov SavedMiscEnablesRdx, rdx + +;----------------------------------------------------------------------------- +; +; Section: Save variable MTRRs +; +; Description: All variable MTRRs are saved in local variables. +; They will be restored after runnong of BIOS ACM +; +;----------------------------------------------------------------------------- + mov rcx, IA32_MTRR_CAP + rdmsr + and rax, 0FFh + shl rax, 1 + mov MTRR_COUNT, rax + mov rcx, rax + lea rbx, MtrrTab + +SaveNextMtrr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + rdmsr + mov [rbx+0], rax + mov [rbx+8], rdx + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + add rbx, 10h + loop SaveNextMtrr + + ; + ; Save IA32_MTRR_DEF_TYPE MSR + ; + mov rcx, IA32_MTRR_DEF_TYPE + rdmsr + mov MtrrTypeRax, rax + mov MtrrTypeRdx, rdx + +;----------------------------------------------------------------------------- +; +; Section: Program MTRRs +; +; Description: Variable MTRRs are programmed to cache ACM as WB +; +;----------------------------------------------------------------------------- + ; + ; Enable SMXE, SSE and debug extensions + ; + mov rax, cr4 + or rax, CR4_OSFXSR + CR4_DE + CR4_SMXE + mov cr4, rax + + ; + ; Disable cache + ; + mov rax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW + or rax, CR0_CD_MASK OR CR0_NE_MASK + and rax, NOT CR0_NW_MASK + mov cr0, rax + wbinvd + ; + ; Disable MTRRs, set Default Type to UC + ; + mov rcx, IA32_MTRR_DEF_TYPE + xor rax, rax + xor rdx, rdx + wrmsr + + ; + ; Clear all of the Variable MTRRs + ; + mov rcx, MTRR_COUNT + +ClearNextMttr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + wrmsr + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + loop ClearNextMttr + + ; + ; Determine size of AC module + ; + mov rsi, AcmBase + xor rax, rax + mov eax, DWORD PTR [rsi+ACM_HEADER.AcmSize] + shl rax, 2 ; ...in bytes (ACM header has size in dwords) + ; + ; Round up to page size + ; + add rax, 0FFFh ; + and rax, 0FFFFF000h ; Aligned to a page (4KB) + + ; + ; Program MTRRs to cover BIOS ACM + ; + sub rcx, rcx + mov NEXT_MTRR_INDEX, rcx ; Start from MTRR0 + + ; + ; Save remaining size to cache + ; + mov ACM_SIZE_TO_CACHE, rax ; Size of ACM that must be cached + mov ACM_BASE_TO_CACHE, rsi ; Base ACM address + +nextMtrr: + ; + ; Get remaining size to cache + ; + mov rax, ACM_SIZE_TO_CACHE + and rax, rax + jz done ; If no left size - we are done + ; + ; Determine next size to cache. + ; We start from bottom up. Use the following algorythm: + ; 1. Get our own alignment. Max size we can cache equals to our alignment + ; 2. Determine what is bigger - alignment or remaining size to cache. + ; If aligment is bigger - cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; If remaining size to cache is bigger + ; Determine the biggest 2^N part of it and cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; 3. End when there is no left size to cache or no left MTRRs + ; + mov rsi, ACM_BASE_TO_CACHE + bsf rcx, rsi ; Get index of lowest bit set in base address + ; + ; Convert index into size to be cached by next MTRR + ; + mov rdx, 1h + shl rdx, cl ; Alignment is in rdx + cmp rdx, rax ; What is bigger, alignment or remaining size? + jbe gotSize ; JIf aligment is less + ; + ; Remaining size is bigger. Get the biggest part of it, 2^N in size + ; + bsr rcx, rax ; Get index of highest set bit + ; + ; Convert index into size to be cached by next MTRR + ; + mov rdx, 1 + shl rdx, cl ; Size to cache + +gotSize: + mov rax, rdx + mov NEXT_MTRR_SIZE, rax ; Save + + ; + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; + dec rax ; eax - size to cache less one byte + not rax ; eax contains low 32 bits of mask + or rax, MTRR_VALID ; Set valid bit + ; + ; Program mask register + ; + mov rcx, IA32_MTRR_PHYSMASK0 ; setup variable mtrr + mov rbx, NEXT_MTRR_INDEX + add rcx, rbx + + mov rdx, 0Fh + wrmsr + ; + ; Program base register + ; + sub rdx, rdx + mov rcx, IA32_MTRR_PHYSBASE0 ; setup variable mtrr + add rcx, rbx ; ebx is still NEXT_MTRR_INDEX + + mov rax, ACM_BASE_TO_CACHE + or rax, WB ; set type to write back + wrmsr + ; + ; Advance and loop + ; Reduce remaining size to cache + ; + mov rbx, ACM_SIZE_TO_CACHE + mov rax, NEXT_MTRR_SIZE + sub rbx, rax + mov ACM_SIZE_TO_CACHE, rbx + + ; + ; Increment MTRR index + ; + mov rbx, NEXT_MTRR_INDEX + add rbx, 2 + mov NEXT_MTRR_INDEX, rbx + ; + ; Increment base address to cache + ; + mov rbx, ACM_BASE_TO_CACHE + mov rax, NEXT_MTRR_SIZE + add rbx, rax + mov ACM_BASE_TO_CACHE, rbx + + jmp nextMtrr + +done: + ; + ; Enable Variable MTRRs + ; + xor rdx, rdx + mov rax, MTRR_ENABLE + mov rcx, IA32_MTRR_DEF_TYPE + wrmsr + ; + ; Enable cache + ; + mov rax, cr0 + and rax, NOT CR0_CD_MASK + mov cr0, rax + + ; + ; Clean all MCi_STATUS MSR registers + ; SCLEAN will generate GPF otherwise + ; + mov rcx, MCG_CAP + rdmsr + movzx rbx, al ; ebx = MCR bank count + xor rax, rax ; Write 0 into all MCi_STATUS registers + xor rdx, rdx + mov rcx, MC0_STATUS + +McaErrorCleanLoopStart: + wrmsr + dec rbx + jz @F + add rcx, 4 ; ecx = number of MSRs per bank + jmp McaErrorCleanLoopStart + +@@: +;----------------------------------------------------------------------------- +; +; Section: Find Compatible Segment Descriptor in GDT +; +; Description: GDT is scanned until code descriptor with L bit = 0 is found +; +;----------------------------------------------------------------------------- + + lea rax, BIOS_GDT + add rax, 2 ; Point to base + mov rax, [rax] ; Get base of GDT + mov rbx, rax ; Save GDT base + + mov cx, WORD PTR BIOS_GDT + movzx rcx, cx + inc rcx ; rcx - total size of GDT in bytes + add rcx, rax ; rcx - end of GDT + +loopStart: + cmp QWORD PTR [rax], 0 ; Reserved? + je ApplicationDescriptor + test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, MASK D_T + jz nextDescriptor ; JIf system descriptor + ; + ; Application descriptor found + ; + test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, 8 ; Bit 3 of sType - code segment if set + jz nextDescriptor ; JIf data descriptor + ; + ; Code descriptor is found + ; + test byte ptr [rax].SEG_DESCRIPTOR.LAR16_23, MASK L + jnz nextDescriptor + ; + ; Compatibility mode code descriptor is found + ; + sub rax, rbx ; rax is compatibility segment selector + jmp CompatibilityModeJump + +nextDescriptor: + cmp rax, rcx + jb @F + jmp $ ; Nothing found - impossible situation + +@@: + test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, MASK D_T + jz @F + +ApplicationDescriptor: + ; + ; Application descriptor - 8 bytes + ; + add rax, 8 + jmp loopStart + +@@: + add rax, 16 + jmp loopStart + +;----------------------------------------------------------------------------- +; +; Section: Jump to compatibility mode +; +; Description: Found selector and known label offset +; are used to transfer control to compatibility mode. +; +; NOTE! +; Code programmed from this point on till the return to long mode +; looks differently than code actually executed by CPU +; This is because assembler is in x64 mode whereas CPU is not. +; Whereever differences are present between written and executed code, +; actual instructions are shown in comments. +; +; Example1: Programmed: mov rax, cr4 +; Executed: mov eax, cr4 +; Assembler fails to assemble "mov eax, cr4" since CR4 is +; 64 bits wide in x64 mode. Generated opcodes are nevertheless +; correct. +; +; Example2: Programmed: mov eax, DWORD PTR [rbx+0] +; Executed: mov eax, DWORD PTR [ebx+0] +; Default addressing in x64 mode is 64 bit. If ebx were coded +; in this example, assembler would generate unneeded REX prefix. +; By programming rbx this prefix is not generated and +; opcode corresponds to ebx addressing in compatibility mode +; +;----------------------------------------------------------------------------- + +CompatibilityModeJump: + ; + ; Save Long mode and Compatibility mode selectors and offsets before transition + ; + mov CompModeSel, rax ; Save Compatibility Mode selector + mov rcx, OFFSET ProtectedMode2 + mov CompModeOff, rcx + mov cx, cs + movzx rcx, cx + mov LongModeSel, rcx + mov rcx, OFFSET LongMode2 + mov LongModeOff, rcx + + shl rax, 32 + mov rcx, OFFSET CompatibilityMode + or rax, rcx + push rax + retf + +CompatibilityMode: +;----------------------------------------------------------------------------- +; +; Section: Jump to protected mode +; +; Description: Compatibility mode is disabled since BIOS ACM must run +; in protected 32 bit mode. +; +;----------------------------------------------------------------------------- + + ; + ; Disable paging + ; + mov rcx, cr0 + and ecx, DWORD PTR (NOT BIT31) + mov cr0, rcx + ; + ; Clear EFER.LME + ; + mov ecx, IA32_EFER_MSR + rdmsr + and eax, NOT LME + wrmsr + jmp ProtectedMode + +ProtectedMode: + +;----------------------------------------------------------------------------- +; +; Section: Launch BIOS ACM +; +; Description: Prepare and execute GETSEC[ENTERACCS] +; +;----------------------------------------------------------------------------- + + ; + ; Save return values in MMX registers + ; + + mov ax, ss + movzx eax,ax +% _movd SAVED_SS, eax +% _movd SAVED_EBP, ebp +% _movd SAVED_ESP, esp + lea eax, BIOS_GDT +% _movd SAVED_GDT, eax + mov rax, cr3 ; mov eax, cr3 - in 32 bit mode + mov DWORD PTR SavedCR3, eax + ; + ; Call GETSEC[ENTERACCS] + ; + mov esi, DWORD PTR Funct ; esi = ACM function + mov eax, DWORD PTR AcmBase + mov ebx, eax ; ebx = AcmBase + mov ecx, DWORD PTR [rbx+ACM_HEADER.AcmSize] ; mov DWORD PTR [ebx+ACM_HEADER.AcmSize] - in 32 bit mode + ; ecx = size of ACM in dwords + shl ecx, 2 ; ecx = size of ACM in bytes + xor edx, edx + xor edi, edi + mov eax, ENTERACCS ; eax = ENTERACCS + + _GETSEC + +;for debugging only +; mov ax, 055AAh +; out 80h, ax +;; jmp $ +;----------------------------------------------------------------------------- +; +; Section: Restore protected mode environment +; +; Description: Since BIOS ACM changes GDT, +; BIOS GDT, stack and and CS selector are restored. +; +; +;----------------------------------------------------------------------------- + + ; + ; Reload the GDTR. Upon return CPU is loaded with selector from ACM GDT + ; The following instruction works simply because whatever CS selector is + ; currently, it is flat selector. + ; +% _movd eax, SAVED_GDT + lgdt FWORD ptr [rax] ; lgdt FWORD ptr [eax] - in 32 bit mode + + ; + ; Restore the stack + ; +% _movd eax, SAVED_EBP + mov ebp, eax ; restore ebp +% _movd eax, SAVED_ESP + mov esp, eax ; restore esp +% _movd eax, SAVED_SS + mov ss, ax ; restore ss + + ; + ; Reload cs register + ; + mov eax, DWORD PTR CompModeSel + push rax ; push eax - in 32 bit mode + + mov eax, DWORD PTR CompModeOff + push rax ; push eax - in 32 bit mode + retf ; will jump to Protected label below + +ProtectedMode2: + +;----------------------------------------------------------------------------- +; +; Section: Restore MTRRs +; +; Description: BIOS MTRR values are restored. +; +;----------------------------------------------------------------------------- + ; + ; Disable paging + ; + mov rax, cr0 + and eax, DWORD PTR (NOT CR0_PG_MASK) + mov cr0, rax + + mov rcx, MTRR_COUNT + lea ebx, MtrrTab + +RestoreNextMtrr: + add ecx, IA32_MTRR_PHYSBASE0 - 1 + mov eax, DWORD PTR [rbx+0] ; mov eax, DWORD PTR [ebx+0] - in 32 bit mode + mov edx, DWORD PTR [rbx+8] ; mov eax, DWORD PTR [ebx+8] - in 32 bit mode + wrmsr + sub ecx, IA32_MTRR_PHYSBASE0 - 1 + add ebx, 10h + loop RestoreNextMtrr + + mov rcx, IA32_MTRR_DEF_TYPE + mov rdx, MtrrTypeRdx + mov rax, MtrrTypeRax + wrmsr +;----------------------------------------------------------------------------- +; +; Section: Switch to compatibility mode +; +; Description: Compatibility mode i srestored by enabling of paging - +; this is done by restoring CR4 contenxt, and setting of LME bit. +; +;----------------------------------------------------------------------------- + + ; + ; Enable PAE in CR4 + ; + mov eax, DWORD PTR SavedCR4 + or eax, CR4_PAE + mov cr4, rax + + ; + ; Reload CR3 + ; + mov eax, DWORD PTR SavedCR3 + mov cr3, rax + + ; + ; Set EFER.LME to re-enable ia32-e + ; + mov ecx, IA32_EFER_MSR + rdmsr + or eax, LME + wrmsr + ; + ; Enable paging + ; + mov rax, cr0 + or eax, CR0_PG_MASK + mov cr0, rax + + jmp CompatibilityMode2 + +CompatibilityMode2: + wbinvd ; Flush and invalidate the cache + ; + ; Now we're in Compatibility mode - restore segment registers. + ; + mov rax, SavedDS + mov ds, ax + mov rax, SavedES + mov es, ax + mov rax, SavedGS + mov gs, ax + mov rax, SavedFS + mov fs, ax + ; + ; Reastore IA32_MISC_ENABLES MSR + ; + mov rcx, IA32_MISC_ENABLE_MSR + mov rdx, SavedMiscEnablesRdx + mov rax, SavedMiscEnablesRax + wrmsr + + +;----------------------------------------------------------------------------- +; +; Section: Switch to long mode +; +; Description: Previously saved selector and offset are used to return +; CPU to long mode. +; +;----------------------------------------------------------------------------- + ; + ; Reload cs register + ; + mov eax, DWORD PTR LongModeSel + push rax ; push eax - in 32 bit mode + + mov eax, DWORD PTR LongModeOff + push rax ; push eax - in 32 bit mode + retf + +LongMode2: +;----------------------------------------------------------------------------- +; +; Section: Resore registers, stack and exit. +; +; Description: Previously saved registers are restored. Stack is restored +; by execution leave instruction and control is returned to +; caller. +; +; NOTE! +; This section ends differences between programmed and +; executed code. +; +;----------------------------------------------------------------------------- + ; + ; Now we're in Long Mode + ; Restore control registers + ; + mov rax, SavedCR4 + mov cr4, rax + + POPA_64 + popf + + leave + ret 0 + +LaunchBiosAcm ENDP + +_TEXT ENDS + + END diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.asm16 b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.asm16 new file mode 100644 index 0000000..9855257 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.asm16 @@ -0,0 +1,305 @@ +;/*++ +; 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 +;--*/ +; +;/*++ +; +; Copyright (c) 1999 - 2011 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. +; +; +; Module Name: +; +; TxtPeiAp.asm +; +; Abstract: +; +; This file contains AP initialization code in PEI phase +; +;--*/ + + .XLIST + include txt.inc + .LIST + + .586p + .MMX + +TxtSegment16 SEGMENT PARA USE16 PUBLIC 'TXTCODE' + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: Entry point of AP startup code. Target of SIPI vector. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; +; This point is 4K aligned somewhere in boot block. +; + jmp code16bitStart + + ORG 10h + +GDTAddress: + dw GDTLen ; The length of the GDT + dd OFFSET GDTStart ; The 32-bit physical address + +; +; AP GDT table +; + ALIGN 16 +GDTStart LABEL BYTE + + SEG_DESCRIPTOR <> ; Unused (selector 0) + +; +; Selector 8 +; +TXT_DATA32 EQU $ - GDTStart + +TXT_DATA32_OFF SEG_DESCRIPTOR {0FFFFh,\ + 0000h, \ + 00h, \ + <SEG_PRESENT, 0, APPLSEGMENT, DATATYPE>, \ + <PAGEGRANULARITY, BIGSEGMENT,,,0Fh>, \ + 00h} + +GDTLen EQU $ - GDTStart - 1 + + +code16bitStart: + +;L1: jmp $ + cli + + mov si, OFFSET GDTAddress + ; + ; Set DS and ES limits + ; + db 66h ; Force 32 bit load + lgdt FWORD PTR cs:[si] + + mov eax, CR0 ; get CPU control word 0 + or al, 01 ; enable CPU protected mode + mov CR0, eax ; write back to CPU control word 0 + jmp target + +target: + + mov ax, TXT_DATA32 + mov ds, ax ; set DS limit + mov es, ax ; set ES limit + mov fs, ax ; set FS limit + mov gs, ax ; set GS limit + mov ss, ax ; set SS limit + + ; + ; Disable protected mode + ; + mov eax, CR0 ; get CPU control word 0 + and al, 0FEh ; disable CPU protected mode + mov CR0, eax ; write back to CPU control word 0 + jmp target3 + +target3: + xor ax, ax + mov ds, ax ; set flat DS + mov es, ax ; set flat ES + + ; + ; Fall through to main code + ; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; +; Procedure: LoadVsmcuRetNS - Variable Size Processor Microcode Update (Stackless) +; +; Input: SP = Return address +; +; Output: None +; +; Registers: All but SP are modified +; +; Description: +; Load MCU into processor. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +LoadVsmcuRetNS PROC NEAR PUBLIC + ; + ; Check uCode was loaded or not + ; + xor eax, eax + xor edx, edx + mov ecx, MCU_REV_MSR + wrmsr + mov eax, 1 + cpuid + mov ecx, MCU_REV_MSR + rdmsr + or edx, edx + jnz uCode_loaded + + ; + ; Restore MCU address from scratch register + ; + mov eax, 1 + cpuid + + mov eax, TXT_PUBLIC_BASE + MCU_BASE_ADDR + mov eax, [eax] + + lea eax, [eax + SIZEOF MCU] ; EAX -> MCU data (after header) + xor edx, edx + mov ecx, MCU_LOAD_MSR ; Trigger to load MCU + + wrmsr ; Load MCU + + mov eax, 1 + cpuid +uCode_loaded: + ; + ; Fall through + ; +LoadVsmcuRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: TxtPrepareCacheForAcModuleRetNS +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: Cache initialization per TXT BIOS spec +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +TxtPrepareCacheForAcModuleRetNS PROC NEAR PUBLIC + + ; + ; Ensure CR0.CD and CR0.NW are cleared + ; + mov eax, cr0 ; + and eax, NOT (CR0_CD_MASK + CR0_NW_MASK) + mov cr0, eax + ; + ; Fall through + ; +TxtPrepareCacheForAcModuleRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: TxtCleanMcaNS +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: MCA registers are cleaned +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +TxtCleanMcaNS PROC NEAR PUBLIC + ; + ; Clean MC[i]_STATUS MSR registers + ; SCLEAN will generate GPF otherwise + ; + mov ecx, MCG_CAP + rdmsr + movzx ebx, al ; Bank count to ebx + sub eax, eax ; Write 0 into all MCi_STATUS registers + sub edx, edx + mov ecx, MC0_STATUS + +McaErrorCleanLoopStart: + wrmsr + dec ebx + jz continue + add ecx, 4 ; Number of MSRs per bank + jmp McaErrorCleanLoopStart + +continue: + ; + ; Fall through + ; +TxtCleanMcaNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: TxtHaltLoopNS +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: APs enter halt loop +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +TxtHaltLoopNS PROC NEAR PUBLIC + + mov eax, CR4 + or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE + mov CR4, eax + + mov eax, 1 + cpuid + shr ebx, 24 ; ebx is initial APIC ID shifted rightmostly + + ; + ; Since accesses to semaphore cannot be serialized, accesses among different CPUs + ; are orchestrated as following: + ; BSP will only READ semaphore + ; All APs will keep READING semaphore until its value EQUALS to that AP's + ; APIC ID minus 1. Only AFTER that AP will INCREMENT semaphore. + ; This allows BSP to judge WHEN all APs finished. + ; + mov ecx, [TXT_PUBLIC_BASE + SEMAPHORE] + +keepWaiting: + mov eax, [ecx] + inc eax + cmp eax, ebx + jb keepWaiting + ja hltLoop + mov [ecx], eax + +hltLoop: + cli + hlt + jmp hltLoop + +TxtHaltLoopNS ENDP + +TxtSegment16 ENDS + +END diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.inf b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.inf new file mode 100644 index 0000000..a6e8185 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for TXTPEIAP module +# +#@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 +# + +[defines] +BASE_NAME = TxtPeiAp +FILE_GUID = D1E59F50-E8C3-4545-BF61-11F002233C97 +COMPONENT_TYPE = USER_DEFINED + +[sources.common] + +[sources.ia32] + TxtPeiAp.asm16 + +[includes.common] + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include + +[libraries.common] + +[nmake.common] diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiApV7.inf b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiApV7.inf new file mode 100644 index 0000000..e649127 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiApV7.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for TXTPEIAP module +# +#@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 +# + +[defines] +BASE_NAME = TxtPeiAp +FILE_GUID = D1E59F50-E8C3-4545-BF61-11F002233C97 +COMPONENT_TYPE = FILE +BUILD_TYPE = MAKEFILE + +[sources.common] + +[sources.ia32] + TxtPeiAp.asm16 + +[includes.common] + +[libraries.common] + +[nmake.common] diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiBsp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiBsp.asm new file mode 100644 index 0000000..066aedc --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiBsp.asm @@ -0,0 +1,1387 @@ +;/*++ +; 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 +;--*/ +; +;/*++ +; +; Copyright (c) 1999 - 2011 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. +; +; +; Module Name: +; +; TxtPeiBsp.asm +; +; Abstract: +; +; This file contains the code to launch BIOS ACM functions in PEI phase +; +;--*/ + + .XLIST + include txt.inc + .LIST + + .686P + .MMX + .XMM + .MODEL FLAT,C + .CODE + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: LaunchBiosAcmSclean +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: Setup GETSEC environment (protected mode, mtrrs, etc) and +; invoke GETSEC:ENTERACCS with requested BIOS ACM entry point. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +LaunchBiosAcmSclean PROC PUBLIC + ; + ; Tell where we are + ; + mov eax, 11110000h + in ax, 80h + mov ah, PORT80_CODE_PREFIX + TXT_LAUNCH_SCLEAN + out 80h, eax + + ; + ; Enable SMXE, SSE and debug extensions always. + ; + mov eax, CR4 + or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE + mov CR4, eax + + ; + ; Prepare cache of BSP + ; + mov esi, TXT_PUBLIC_BASE + BIOACM_ADDR + mov edi, 0 + + CALL_NS PrepareCacheForAcModuleRetNS + + CALL_NS CleanMcaRetNS + +ifdef MKF_TXT_RLP_INIT + if MKF_TXT_RLP_INIT + CALL_NS InitializeApsRetNS + endif +endif + + + ; + ; Call GETSEC[ENTERACCS] + ; + cli + mov eax, ENTERACCS ; eax = ENTERACCS + mov ebx, TXT_PUBLIC_BASE + BIOACM_ADDR + mov ebx, [ebx] + mov ecx, [ebx].ACM_HEADER.AcmSize + shl ecx, 2 + xor edx, edx + xor edi, edi + mov esi, 0 + + _GETSEC + + jmp DoPowerCycleReset +LaunchBiosAcmSclean ENDP + +DoGlobalReset PROC PUBLIC + mov dx, 0CF8h ; Make warm system reset through port 0CF9h + mov eax, 8000F8ACh ; to be global system reset - set bit 20 + out dx, eax ; of device 1F + mov dx, 0CFCh + in eax, dx + or eax, (1 SHL 20) + out dx, eax + + mov dx, 0CF9h ; After return from SCLEAN function + mov al, 0 ; system must be reset. + out dx, al + mov dx, 0CF9h ; After return from SCLEAN function + mov al, 6 ; system must be reset. + out dx, al + cli + hlt + jmp $ + +DoGlobalReset ENDP + +DoPowerCycleReset PROC PUBLIC + mov dx, 0CF8h ; Make warm system reset through port 0CF9h + mov eax, 8000F8ACh ; to be global system reset - set bit 20 + out dx, eax ; of device 1F + mov dx, 0CFCh + in eax, dx + and eax, NOT (1 SHL 20) + out dx, eax + + mov dx, 0CF9h ; After return from SCLEAN function + mov al, 0 ; system must be reset. + out dx, al + mov dx, 0CF9h ; After return from SCLEAN function + mov al, 0Eh ; system must be reset. + out dx, al + cli + hlt + jmp $ + +DoPowerCycleReset ENDP + +DoHostReset PROC PUBLIC + mov dx, 0CF8h ; Make warm system reset through port 0CF9h + mov eax, 8000F8ACh ; to be global system reset - set bit 20 + out dx, eax ; of device 1F + mov dx, 0CFCh + in eax, dx + and eax, NOT (1 SHL 20) + out dx, eax + + mov dx, 0CF9h ; After return from SCLEAN function + mov al, 0 ; system must be reset. + out dx, al + mov dx, 0CF9h ; After return from SCLEAN function + mov al, 6 ; system must be reset. + out dx, al + cli + hlt + jmp $ + +DoHostReset ENDP + +DoCpuReset PROC PUBLIC + mov dx, 0CF8h ; Make warm system reset through port 0CF9h + mov eax, 8000F8ACh ; to be global system reset - clear bit 20 + out dx, eax ; of device 1F + mov dx, 0CFCh + in eax, dx + and eax, NOT (1 SHL 20) + out dx, eax + + mov dx, 0CF9h ; Issue a CPU only reset by CF9h + mov al, 0 ; toggle bit2 from 0 to 1 + out dx, al + mov dx, 0CF9h ; Issue a CPU only reset by CF9h + mov al, 4 ; + out dx, al + cli + hlt + jmp $ + +DoCpuReset ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: PrepareCacheForAcModuleRetNS +; +; Input: esi - bios acm address +; edi - in memory flag +; +; Output: None +; +; Registers: None are preserved +; +; Description: MTRRs are set per BIOS spec +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +PrepareCacheForAcModuleRetNS PROC FAR PUBLIC + ; + ; Enable local APIC + ; + mov ecx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and eax, BASE_ADDR_MASK ; Just need the address + mov DWORD PTR [eax+SPURIOUS_VECTOR_1], 1FFh ; Enable APIC, keep spurious vector + ; + ; Disable cache + ; + mov eax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW + or eax, CR0_CD_MASK OR CR0_NE_MASK + and eax, NOT CR0_NW_MASK + mov cr0, eax + cmp edi, 0 + je @F ; JIf stackless environment + wbinvd ; Invalidate the cache + jmp disableMtrrs + +@@: + invd + +disableMtrrs: + ; + ; Disable all MTRRs + ; + xor eax, eax + xor edx, edx + mov ecx, IA32_MTRR_DEF_TYPE + wrmsr + + ; + ; Disable NEM + ; + mov ecx, NO_EVICT_MODE + rdmsr + and eax, NOT (BIT1) + wrmsr ; Clear No-Eviction Mode Run bit + mov ecx, NO_EVICT_MODE + rdmsr + and eax, NOT (BIT0) + wrmsr ; Clear No-Eviction Mode SETUP bit + + invd + + ; + ; Clear all variable MTRRs + ; + mov ecx, IA32_MTRR_CAP + rdmsr + and eax, 0FFh + shl eax, 1 + mov ecx, eax + xor eax, eax + xor edx, edx +@@: + add ecx, IA32_MTRR_PHYSBASE0 - 1 + wrmsr + sub ecx, IA32_MTRR_PHYSBASE0 - 1 + loop @B + + ; + ; Determine size of AC module + ; + mov esi, [esi] + mov eax, [esi].ACM_HEADER.AcmSize + shl eax, 2 ; ...in bytes (ACM header has size in dwords) + ; + ; Round up to page size + ; + mov ecx, eax ; Save + and ecx, 0FFFFF000h ; Number of pages in AC module + and eax, 0FFFh ; Number of "less-than-page" bytes + jz rounded + mov eax, 1000h ; Add the whole page size + +rounded: + add eax, ecx ; eax - rounded up AC module size + + ; + ; Define "local" vars for this routine + ; + ACM_SIZE_TO_CACHE TEXTEQU <mm0> + ACM_BASE_TO_CACHE TEXTEQU <mm1> + NEXT_MTRR_INDEX TEXTEQU <mm2> + NEXT_MTRR_SIZE TEXTEQU <mm3> + ; + ; Initialize "locals" + ; + sub ecx, ecx + movd NEXT_MTRR_INDEX, ecx ; Start from MTRR0 + + ; + ; Save remaining size to cache + ; + movd ACM_SIZE_TO_CACHE, eax ; Size of ACM that must be cached + movd ACM_BASE_TO_CACHE, esi ; Base ACM address + +nextMtrr: + ; + ; Get remaining size to cache + ; + movd eax, ACM_SIZE_TO_CACHE + and eax, eax + jz done ; If no left size - we are done + ; + ; Determine next size to cache. + ; We start from bottom up. Use the following algorythm: + ; 1. Get our own alignment. Max size we can cache equals to our alignment + ; 2. Determine what is bigger - alignment or remaining size to cache. + ; If aligment is bigger - cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; If remaining size to cache is bigger + ; Determine the biggest 2^N part of it and cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; 3. End when there is no left size to cache or no left MTRRs + ; + movd esi, ACM_BASE_TO_CACHE + bsf ecx, esi ; Get index of lowest bit set in base address + ; + ; Convert index into size to be cached by next MTRR + ; + mov edx, 1h + shl edx, cl ; Alignment is in edx + cmp edx, eax ; What is bigger, alignment or remaining size? + jbe gotSize ; JIf aligment is less + ; + ; Remaining size is bigger. Get the biggest part of it, 2^N in size + ; + bsr ecx, eax ; Get index of highest set bit + ; + ; Convert index into size to be cached by next MTRR + ; + mov edx, 1 + shl edx, cl ; Size to cache + +gotSize: + mov eax, edx + movd NEXT_MTRR_SIZE, eax ; Save + + ; + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; + dec eax ; eax - size to cache less one byte + not eax ; eax contains low 32 bits of mask + or eax, MTRR_VALID ; Set valid bit + + ; + ; Program mask register + ; + mov ecx, IA32_MTRR_PHYSMASK0 ; setup variable mtrr + movd ebx, NEXT_MTRR_INDEX + add ecx, ebx + + mov edx, 0Fh ; 8K range (FFFFFFE800) + wrmsr + ; + ; Program base register + ; + sub edx, edx + mov ecx, IA32_MTRR_PHYSBASE0 ; setup variable mtrr + add ecx, ebx ; ebx is still NEXT_MTRR_INDEX + + movd eax, ACM_BASE_TO_CACHE + or eax, WB ; set type to write back + wrmsr + ; + ; Advance and loop + ; Reduce remaining size to cache + ; + movd ebx, ACM_SIZE_TO_CACHE + movd eax, NEXT_MTRR_SIZE + sub ebx, eax + movd ACM_SIZE_TO_CACHE, ebx + + ; + ; Increment MTRR index + ; + movd ebx, NEXT_MTRR_INDEX + add ebx, 2 + movd NEXT_MTRR_INDEX, ebx + ; + ; Increment base address to cache + ; + movd ebx, ACM_BASE_TO_CACHE + movd eax, NEXT_MTRR_SIZE + add ebx, eax + movd ACM_BASE_TO_CACHE, ebx + + jmp nextMtrr + +done: + ; + ; Enable variable MTRRs + ; + xor edx, edx + mov eax, MTRR_ENABLE; enable mtrrs (but not fixed ones) + mov ecx, IA32_MTRR_DEF_TYPE + wrmsr + ; + ; Enable cache + ; + mov eax, cr0 ; Enable caching - WB (NW stays clear) + and eax, NOT CR0_CD_MASK + mov cr0, eax + + RET_NS +PrepareCacheForAcModuleRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: CleanMcaRetNS +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: Setup GETSEC environment (protected mode, mtrrs, etc) +; invoke GETSEC:ENTERACCS with requested module +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +CleanMcaRetNS PROC NEAR PUBLIC + + ; + ; Clean all MCi_STATUS MSR registers + ; SCLEAN will generate GPF otherwise + ; + mov ecx, MCG_CAP + rdmsr + movzx ebx, al ; Bank count to ebx + sub eax, eax ; Write 0 into all MCi_STATUS registers + sub edx, edx + mov ecx, MC0_STATUS + +McaErrorCleanLoopStart: + wrmsr + dec ebx + jz exit + add ecx, 4 ; Number of MSRs per bank + jmp McaErrorCleanLoopStart + +exit: + RET_NS +CleanMcaRetNS ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: InitializeApsRetNS +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +InitializeApsRetNS PROC NEAR + mov eax, 1 + cpuid + shr ebx, 16 ; Total Logical Proc Count in BL + cmp bl, 1 ; If 1 thread - nothing to do + je exit + + ; + ; Init Timer 1 + ; + mov al, 54h + out 43h, al + mov al, 12h + out 41h, al + + ; + ; More than one thread + ; Get APIC address + ; + mov ecx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and eax, BASE_ADDR_MASK ; Just need the address + mov edi, eax ; edi points to APIC base + + mov esi, TXT_PUBLIC_BASE ; esi points to public space + + ; + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + + ; + ; Broadcast INIT message to put all APs into Wait for SIPI state + ; C0500 -> Destination = All excl self, Delivery = INIT + ; + mov DWORD PTR ICR_LOW[edi], 000C0500h + mov edx, NeverStatusRetNS + mov ecx, 667 + CALL_NS ltWaitStatusRetNS ; Wait full 10ms + ; + ; Create vector used in the following SIPI message + ; Below address is the real mode address of AP code in Boot Block + ; LTCACHE.BIN containg AP thread code must be placed at the above address + ; in Boot block (FFFF0000h). See file LTCACHE.ASM + ; + + mov ebx, [esi+APINIT_ADDR] + shr ebx, 12 + and ebx, 0FFh + or ebx, 0C0600h ; This is message + + ; + ; Broadcast SIPI message with our vector + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + ; + ; Send message + ; + mov ICR_LOW[edi], ebx + ; + ; Wait 200us as recommended + ; + mov edx, NeverStatusRetNS + mov ecx, 14 + CALL_NS ltWaitStatusRetNS + ; + ; Broadcast second SIPI message with our vector + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + ; + ; Send message + ; + mov ICR_LOW[edi], ebx + ; + ; Wait for semaphore reflect number of CPUs + ; + mov eax, 1 + cpuid + shr ebx, 16 ; Total Logical Proc Count in BL + dec bl ; bl is number of APs + + mov edx, SemaphoreStatusRetNS + mov ecx, 6670 + CALL_NS ltWaitStatusRetNS ; Wait for up to 100ms + + ; + ; Broadcast INIT message to put all APs back into Wait for SIPI state + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + ; + ; Send message + ; + mov DWORD PTR ICR_LOW[edi], 000C0500h + + mov edx, NeverStatusRetNS + mov ecx, 667 + CALL_NS ltWaitStatusRetNS ; Wait full 10ms + +exit: + RET_NS +InitializeApsRetNS ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: SaveApConfig +; +; Input: ApCfg - pointer to save area +; +; Output: None +; +; Registers: All are preserved +; +; Description: Function is called in memory present environment on S3 resume +; path. Saves contents of all MTRRs into table plus some registers. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +SaveApConfig PROC NEAR PUBLIC, ApCfg:PTR QWORD + + pushad + + mov esi, ApCfg + mov ecx, IA32_MTRR_CAP + rdmsr + and eax, 0FFh + shl eax, 1 + mov ecx, eax + +@@: + add ecx, IA32_MTRR_PHYSBASE0 - 1 + rdmsr + mov [esi], eax + mov [esi+4], edx + add esi, SIZEOF QWORD + sub ecx, IA32_MTRR_PHYSBASE0 - 1 + loop @B + + mov ecx, IA32_MTRR_DEF_TYPE + rdmsr + mov [esi], eax + mov [esi+4], edx + + sidt [esi+8] + + mov ecx, IA32_MISC_ENABLE_MSR + rdmsr + mov [esi+010h], eax + mov [esi+014h], edx + + popad + ret +SaveApConfig ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: StartupAllAPs +; +; Input: pFunction - pointer to function to execute on AP +; pParam - pointre to pFunction parameters +; +; Output: None +; +; Registers: All are preserved +; +; Description: Procedure is called in memmory present enironment on S3 +; resume path and is executed on BSP +; It saves memory at address 1000h into buffer +; It then copies AP start-up code into address 1000h +; Then variables in the 1000h area are updated and APs are started +; After APs finish execution of function passed as parameter they +; are halted. BSP restores contents 1000h area from buffer and +; returns. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +Func TYPEDEF PROTO + +PFUNC TYPEDEF PTR Func + +StartUp STRUCT + db 0FAh ; cli + db 066h, 0BBh ; mov ebx, OFFSET gdtLim + db StartUp.gdtLim, 0,0,0 + db 066h + db 067h, 02Eh, 00Fh, 001h, 013h ; lgdt FWORD PTR cs:[ebx] + db 00Fh, 020h, 0C0h ; mov eax, CR0 + db 00Ch, 001h ; or al, 01 + db 00Fh, 022h, 0C0h ; mov CR0, eax + ; + ; 32 bit jump to 32 bit Function handler + ; + db 066h + db 0eah +fOff dd 0 +fCs dw 0 + + ALIGN 16 +fDs dw 0 +gdtLim dw ? ; Size of LT GDT in bytes +gdtBas dd ? ; Physical address of LT GDT +fParam dd ? +smphr dd ? +StartUp ENDS + + +StartupAllAPs PROC NEAR, pFunction:PFUNC, pParam:PTR QWORD + LOCAL buffer:StartUp + LOCAL savedESP:DWORD + + pushad + mov savedESP, esp + mov eax, 1 + cpuid + shr ebx, 16 ; Total Logical Proc Count in BL + cmp bl, 1 ; If 1 thread - nothing to do + je exit + + ; + ; Init Timer 1 + ; + mov al, 54h + out 43h, al + mov al, 12h + out 41h, al + + ; + ; More than one thread. Prepare Startup area + ; + mov esi, 1000h ; Source + lea edi, buffer ; Destination + mov ecx, sizeof StartUp / 4 + CALL_NS MemCopyRetNS + + mov esi, offset ApHandler16 ; Source + mov edi, 1000h ; Destination + mov ecx, sizeof StartUp / 4 + CALL_NS MemCopyRetNS + ; + ; Update Srartup area variables + ; + mov edi, 1000h + mov ds:[edi].StartUp.fCs, cs + mov ds:[edi].StartUp.fDs, ds + mov eax, pFunction + mov ds:[edi].StartUp.fOff, eax + sub eax, eax + mov ds:[edi].StartUp.smphr, eax + mov eax, pParam + mov ds:[edi].StartUp.fParam, eax + sgdt ds:[edi].StartUp.gdtLim + + ; + ; Get APIC address + ; + mov ecx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and eax, BASE_ADDR_MASK ; Just need the address + mov edi, eax ; edi points to APIC base + + ; + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + + ; + ; Broadcast INIT message to put all APs into Wait for SIPI state + ; C0500 -> Destination = All excl self, Delivery = INIT + ; + mov DWORD PTR ICR_LOW[edi], 000C0500h + mov edx, NeverStatusRetNS + mov ecx, 667 + CALL_NS ltWaitStatusRetNS ; Wait full 10ms + ; + ; Create vector used in the following SIPI message + ; + mov ebx, 0C0600h + (1000h SHR 12) + ; + ; Broadcast SIPI message with our vector + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + ; + ; Send message + ; + mov ICR_LOW[edi], ebx + ; + ; Wait 200us as recommended + ; + mov edx, NeverStatusRetNS + mov ecx, 14 + CALL_NS ltWaitStatusRetNS + ; + ; Broadcast second SIPI message with our vector + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + ; + ; Send message + ; + mov ICR_LOW[edi], ebx + ; + ; Wait for semaphore reflect number of CPUs + ; + mov eax, 1 + cpuid + shr ebx, 16 ; Total Logical Proc Count in BL + dec bl ; bl is number of APs + + mov edx, SemaphoreStatus2RetNS + mov ecx, 6670 + CALL_NS ltWaitStatusRetNS ; Wait for up to 100ms + ; + ; Restore StartUp area + ; + lea esi, buffer ; Source + mov edi, 1000h ; Destination + mov ecx, sizeof StartUp / 4 + CALL_NS MemCopyRetNS + +exit: + mov esp, savedESP + popad + ret + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Section: ApHandler16 +; +; Input: None +; +; Output: None +; +; Registers: Irrelevant +; +; Description: This code is copied over address 0:1000. After recieving SIPI +; AP is directed to this address where it starts execution in real mode. +; AP first switches to protected mode, loads the same GDT which is used +; by BSP and jumps to Procedure at fCs:fOff +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + + ALIGN 16 + ; + ; Note After coppying this code must be aligned on page boundary! + ; + +ApHandler16 StartUp <> + +StartupAllAPs ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: PutApsInWfs +; +; Input: None +; +; Output: None +; +; Registers: All are preserved +; +; Description: Procedure is called in memory present environment on S3 resume path. +; INIT SIPI message is sent to all APs. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +PutApsInWfs PROC PUBLIC + LOCAL savedESP:DWORD + pushad + mov savedESP, esp + + mov eax, 1 + cpuid + shr ebx, 16 ; Total Logical Proc Count in BL + cmp bl, 1 ; If 1 thread - nothing to do + je exit + + ; + ; Get APIC address + ; + mov ecx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and eax, BASE_ADDR_MASK ; Just need the address + mov edi, eax ; edi points to APIC base + ; + ; Broadcast INIT message to put all APs back into Wait for SIPI state + ; Wait for APIC ready + ; + mov edx, IcrStatusRetNs + mov ecx, 15 + CALL_NS ltWaitStatusRetNS + ; + ; Send message + ; + mov DWORD PTR ICR_LOW[edi], 000C0500h + + mov edx, NeverStatusRetNS + mov ecx, 667 + CALL_NS ltWaitStatusRetNS ; Wait full 10ms + +exit: + mov esp, savedESP + popad + ret +PutApsInWfs ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: LaunchBiosAcmScheck +; +; Input: None +; +; Output: None +; +; Registers: None are preserved +; +; Description: Setup GETSEC environment (protected mode, mtrrs, etc) and +; invoke GETSEC:ENTERACCS with requested BIOS ACM entry point. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +LaunchBiosAcmScheck PROC PUBLIC, BiosAcAddr:PTR QWORD + + LOCAL SavedGdtr:QWORD + LOCAL SavedSS:dword + LOCAL SavedESP:dword + LOCAL SavedCS:dword + LOCAL SavedCR3:dword + pushf + cli + pushad + ; + ; Tell where we are + ; + in ax, 80h + mov ah, PORT80_CODE_PREFIX + TXT_LAUNCH_SCHECK + out 80h, ax + ; + ; Save control registers + ; + mov eax, cr4 + push eax + mov eax, cr0 + push eax + ; + ; Save segment registers + ; + push ds + push es + push gs + push fs + ; + ; Save CS + ; + sub eax, eax ; Clean upper word + mov ax, cs + mov SavedCS, eax + ; + ; Save stack at this level + ; + mov ax, ss + mov SavedSS, eax + mov SavedESP, esp + mov eax, cr3 + mov SavedCR3, eax + + ; + ; Save GDT + ; + sgdt SavedGdtr ; save value of gdtr in local variable + ; + ; Define "local" vars for this routine + ; + SAVED_EBP TEXTEQU <mm4> + ; + ; Save ebp in MMX register + ; + movd SAVED_EBP, ebp ; Size of ACM that must be cached + + ; + ; Enable SMXE, SSE and debug extensions always. + ; + mov eax, CR4 + or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE + mov CR4, eax + ; + ; Prepare cache of BSP + ; + mov esi, BiosAcAddr + mov edi, 1 + + CALL_NS PrepareCacheForAcModuleRetNS + + CALL_NS CleanMcaRetNS + + ; + ; Call GETSEC[ENTERACCS] + ; + mov eax, ENTERACCS ; eax = ENTERACCS + mov ebx, BiosAcAddr + mov ebx, [ebx] + mov ecx, [ebx].ACM_HEADER.AcmSize + shl ecx, 2 + xor edx, edx + mov edi, S3_RESUME_PATH + mov esi, 4 + + _GETSEC + + ; + ; Return point after ACEXIT. + ; + movd ebp, SAVED_EBP + lea eax, SavedGdtr + lgdt FWORD PTR [eax] + mov eax, SavedSS + mov ss, ax + mov esp, SavedESP + mov eax, SavedCR3 + mov cr3, eax + ; + ; Restore segment registers + ; + pop fs + pop gs + pop es + pop ds + ; + ; Restore control registers + ; + pop eax + ; + ;remain cache disabled until MTRRs restored + ; + or eax, CR0_CD_MASK + and eax, NOT CR0_NW_MASK + wbinvd +; + mov cr0, eax + pop eax + mov cr4, eax + ; + ; Restore CS + ; + mov eax, SavedCS + push eax + push OFFSET ReloadCS + retf + +ReloadCS: + popad + popf + emms + + ret +LaunchBiosAcmScheck ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: RestoreMtrrProgramming +; +; Input: ApMtrrTab - pointer to save area +; +; Output: None +; +; Registers: All are preserved +; +; Description: Function is executed on BSP in memory present environment on S3 +; resume path. Restores contents of all MTRRs from table +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +RestoreMtrrProgramming PROC NEAR PUBLIC, ApMtrrTab:PTR QWORD + LOCAL savedESP:DWORD + pushad + mov savedESP, esp + + mov esi, ApMtrrTab + CALL_NS RestoreMtrrProgrammingRetNS + + mov esp, savedESP + popad + ret +RestoreMtrrProgramming ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: RestoreMtrrProgrammingRetNS +; +; Input: esi - pointer to save area +; +; Output: None +; +; Registers: None are preserved +; +; Description: Restores contents of all MTRRs from table +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +RestoreMtrrProgrammingRetNS PROC NEAR PUBLIC + mov eax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW + or eax, CR0_CD_MASK OR CR0_NE_MASK + and eax, NOT CR0_NW_MASK + mov cr0, eax + wbinvd ; flush and invalidate the cache + + xor edx, edx + mov eax, MTRR_ENABLE + MTRR_FIXED_ENABLE ; enable mtrrs + mov ecx, 2FFh + wrmsr + + mov ecx, IA32_MTRR_CAP + rdmsr + and eax, 0FFh + shl eax, 1 + mov ecx, eax + +@@: + add ecx, IA32_MTRR_PHYSBASE0 - 1 + mov eax, [esi] + mov edx, [esi+4] + wrmsr + add esi, SIZEOF QWORD + sub ecx, IA32_MTRR_PHYSBASE0 - 1 + loop @B + + mov ecx, IA32_MTRR_DEF_TYPE + mov eax, [esi] + mov edx, [esi+4] + wrmsr + mov ecx, IA32_MISC_ENABLE_MSR + mov eax, [esi+010h] + mov edx, [esi+014h] + wrmsr + + mov eax, cr0 ; Enable caching - WB (NW stays clear) + and eax, NOT CR0_CD_MASK + mov cr0, eax + + RET_NS +RestoreMtrrProgrammingRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: RestoreApConfig +; +; Input: esi - pointer to save area +; +; Output: None +; +; Registers: None are preserved +; +; Description: Function is executed on AP in memory present environment on S3 +; resume path. Restores contents of all MTRRs from table +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +RestoreApConfig PROC NEAR PUBLIC + mov eax, CR4 + or eax, CR4_OSFXSR + CR4_DE + mov CR4, eax + + mov esi, 1000h + mov ds, cs:[esi].StartUp.fDs + mov es, cs:[esi].StartUp.fDs + mov fs, cs:[esi].StartUp.fDs + mov gs, cs:[esi].StartUp.fDs + mov ss, cs:[esi].StartUp.fDs + + mov esi, [esi].StartUp.fParam + + CALL_NS RestoreMtrrProgrammingRetNS + + lidt FWORD PTR [esi+8] + + jmp updateSemaphore + +RestoreApConfig ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: DoApInit +; +; Input: Contents of startup area at 1000h +; +; Output: None +; +; Registers: None are preserved +; +; Description: Executed on AP. Persforms CPU initialization for running +; of GETSEC +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +DoApInit PROC NEAR PUBLIC + mov eax, CR4 + or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE + mov CR4, eax + + mov esi, 1000h + mov ds, cs:[esi].StartUp.fDs + + mov esi, [esi].StartUp.fParam + mov edi, 1 + + CALL_NS PrepareCacheForAcModuleRetNS + + CALL_NS CleanMcaRetNS + +updateSemaphore:: + mov ecx, 1000h + StartUp.smphr + lock inc DWORD PTR [ecx] + +hltLoop: + cli + hlt + jmp hltLoop + +DoApInit ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: MemCopyRetNS +; +; Input: esi - from linear address +; edi - to linear address +; ecx - swap size in dwords +; ds - flat segment +; +; Output: None +; +; Registers: None +; +; Description: Swaps contents of two input buffers. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +MemCopyRetNS PROC NEAR + +start: + mov eax, ds:[esi] ; source + mov ds:[edi], eax + add esi, 4 + add edi, 4 + loop start + RET_NS +MemCopyRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: ltWaitStatusRetNS +; +; Input: cx - Refresh bit Toggle count +; 750000us = 50000 toggles +; edx - offset of Status procedure +; +; Output: Z if status is met +; NZ - timeout occured +; NC - always +; +; Stack: Not available +; +; Registers: cx, ax, esp +; +; Description: Calls status procedure. If status is met - returns Z and +; NZ otherwise. +; Status procedure is required to return Z if status is met and +; NZ if not +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +ltWaitStatusRetNS PROC NEAR + + in al, PORTB ; Read initial setting. + and al, PORTBMASK ; Keep what we care about. + mov ah, al ; Keep a copy of the data. + +waitLoop: + CALL_NS edx ; Call status procedure. + jz exit ; Z - status met + +waitLoop0: + in al, PORTB + and al, PORTBMASK + cmp al, ah ; Refresh bit changed ? + je waitLoop0 + + mov ah, al + loop waitLoop + or ax, 1 ; Clear the ZERO flag - timeout. + ; This also clears C flag +exit: + RET_NS +ltWaitStatusRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: IcrStatusRetNS +; +; Input: ds: Flat, edi - xAPIC Base Address +; +; Output: Z if status is met +; +; Stack: Not available +; +; Registers: all are preserved +; +; Description: Returns Z if ICR is idle +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +IcrStatusRetNS PROC NEAR PUBLIC + test DWORD PTR ICR_LOW[edi], BIT12 + RET_NS +IcrStatusRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: SemaphoreStatusRetNS +; +; Input: ds: Flat +; +; Output: Z if status is met +; +; Stack: Not available +; +; Registers: all are preserved +; +; Description: Returns Z if semaphore is 0 +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +SemaphoreStatusRetNS PROC NEAR PUBLIC + bswap eax + mov al, BYTE PTR [esi+SEMAPHORE] + cmp al, bl + bswap eax + RET_NS +SemaphoreStatusRetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: SemaphoreStatus2RetNS +; +; Input: ds: Flat +; +; Output: Z if status is met +; +; Stack: Not available +; +; Registers: Upper byte of eax is modified +; +; Description: Returns Z if semaphore is 0 +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +SemaphoreStatus2RetNS PROC NEAR PUBLIC + bswap eax + mov al, BYTE PTR [esi].StartUp.smphr + cmp al, bl + bswap eax + RET_NS +SemaphoreStatus2RetNS ENDP + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: NeverStatusRetNS +; +; Input: +; +; Output: Z if status is met +; +; Stack: Not available +; +; Registers: All are preserved +; +; Description: Returns Z if ICR is idle +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +NeverStatusRetNS PROC NEAR PUBLIC + or dx, dx ; dx is never 0 so return is NZ + RET_NS +NeverStatusRetNS ENDP + + + +END diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/makefile.new b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/makefile.new new file mode 100644 index 0000000..e27781e --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/makefile.new @@ -0,0 +1,69 @@ +#++ +# 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 +#-- +#++ +# +# Copyright (c) 1999 - 2011 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. +# +# Module Name: +# +# makefile.new +# +# Abstract: +# +# makefile for TxtPeiAp.asm16 file +# +#-- + + +# +# Globals +# +BIN_DIR = $(BUILD_DIR)\$(PROCESSOR) +TOOLCHAIN = TOOLCHAIN_$(PROCESSOR) + +TOOLBIN_DIR = $(BUILD_DIR)\Tools + +# +# Include CommonTools.env enviroment +# + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +AP_GUID = D1E59F50-E8C3-4545-BF61-11F002233C97 + +all : $(BIN_DIR)\TxtPeiAp.bin + +$(BIN_DIR)\TxtPeiAp.bin: $(BIN_DIR)\TxtPeiAp.obj + +$(BIN_DIR)\TxtPeiAp.obj: $(SOURCE_DIR)\TxtPeiAp.asm16 + $(ASM) /c /nologo /Fl /Sa /I$(SOURCE_DIR)\..\..\..\..\Include /Fo$(BIN_DIR)\TxtPeiAp.obj $(SOURCE_DIR)\TxtPeiAp.asm16 + cd $(BIN_DIR) + $(ASMLINK) TxtPeiAp.obj, TxtPeiAp.com,,,, + copy TxtPeiAp.com TxtPeiAp.bin + $(GENFFSFILE) -B $(BIN_DIR) -V -P1 <<$(BIN_DIR)\txtpeiap.pkg +PACKAGE.INF +[.] +BASE_NAME = TxtPeiAp +FFS_FILEGUID = $(AP_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_RAW +FFS_ATTRIB_CHECKSUM = FALSE +FFS_ALIGNMENT = 5 + +IMAGE_SCRIPT = +{ + txtpeiap.bin +} +<<KEEP + + diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.c b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.c new file mode 100644 index 0000000..b1b1ec5 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.c @@ -0,0 +1,241 @@ +/** @file + This is the main PEIM file for TXT. It represents an abstract outline of the + steps required during PEI for enabling TXT. Each individual step is further + abstracted behind a function call interface. This is intended to minimize + the need to modify this file when porting TXT to future platforms. + +@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 + +**/ + +/// +/// External include files do NOT need to be explicitly specified in real EDKII +/// environment +/// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGluePeim.h" +#include "TxtPeiLib.h" +/// +/// #include EFI_PPI_DEFINITION (BootScriptDone) +/// +#include EFI_PPI_DEFINITION (TxtMemoryUnlocked) +#include EFI_PPI_DEFINITION (EndOfPeiSignal) +#include EFI_GUID_DEFINITION (TxtInfoHob) +#include EFI_GUID_DEFINITION (SaDataHob) +#endif + +STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiTxtMemoryUnlockedPpiGuid, + NULL +}; + +STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyDesc = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEndOfPeiSignalPpiGuid, + DprUpdate +}; + +/** + This is the entry point to the TXT PEIM. The TXT PEIM checks for an TXT + capable platform and determines whether SCLEAN should be run. If so, + it launches the BIOS ACM to run SCLEAN (which will reset the platform). + If not, the PEIM checks to see if the platform is resuming from S3. + + If the platform is resuming from S3, this code will register a callback + so that SCHECK will be run when BootScript is done restoring the platform's + configuration. + + @param[in] FfsHeader - A pointer the the FFS File containing this PEIM. + @param[in] PeiServices - A Pointer to the PEI Services Table. + + @exception EFI_UNSUPPORTED - If the platform is not TXT capable. + @retval EFI_SUCCESS - In all other cases not listed above. +**/ +EFI_STATUS +EFIAPI +PeimEntry ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + TXT_PEI_LIB_CONTEXT ctx; + BOOLEAN TxtEnvInitFail; + TxtEnvInitFail = FALSE; + + /// + /// Install PPI to tell memory code that it can run. + /// Do it always. + /// + Status = PeiServicesInstallPpi (&mPpiList); + ASSERT_EFI_ERROR (Status); + + /// + /// Initialize the TXT PEI Lib functions + /// + Status = InitializeTxtPeiLib ( + &ctx, + PeiServices + ); + + if (EFI_ERROR (Status)) { + TxtEnvInitFail = TRUE; + DEBUG ((EFI_D_ERROR, "TXTPEI::PEI Lib initialization failure\n")); + } + /// + /// Determine TPM presence. If TPM is not present - disabling TXT through TxtInfoHob by setting TxtMode=0 + /// Incase TXT had been enabled but TPM was removed suddenly. Although TPM presence is precondition of this module + /// since all commands executed by BIOS ACM don't depend on TPM state. + /// TPM_NV_read will be successfully executed even if TPM is disabled + /// and/or deactivated because all indices defined for BIOS ACM + /// usage don't require authorization. TPM_ResetEstablishmentBit + /// doesn't depend on TPM state at all and can + /// be executed with disabled/deactivated TPM always. + /// Case when TPM is completely not functional is not considered. + /// + Status = IsTpmPresent (&ctx); + if (EFI_ERROR (Status)) { + /// + /// If TPM is not present / not supported, set TxtMode=0 incase TPM was removed after TXT enabled + /// + if (Status == EFI_UNSUPPORTED) { + DEBUG ((EFI_D_WARN, "TXTPEI::TPM Support is Disabled in BIOS! Disabling TXT! TxtMode=%x\n", ctx.Hob->Data.TxtMode)); + } else { + DEBUG ((EFI_D_WARN, "TXTPEI::TPM is not present! Disabling TXT! TxtMode=%x\n", ctx.Hob->Data.TxtMode)); + } + + TxtEnvInitFail = TRUE; + } + /// + /// Detect TXT capable Processor & PCH + /// + if (!IsTxtChipset (&ctx)) { + DEBUG ((EFI_D_WARN, "TXTPEI::Platform or PCH is not TXT capable\n")); + return EFI_UNSUPPORTED; + } else if (!IsTxtProcessor ()) { + DEBUG ((EFI_D_WARN, "TXTPEI::Processor is not TXT capable\n")); + return EFI_UNSUPPORTED; + } else { + DEBUG ((EFI_D_WARN, "TXTPEI::Processor, PCH & Platform is TXT capable\n")); + /// + /// If Txt Lib or TPM is initiated successful, disable TxT support. + /// + if (TxtEnvInitFail) { + UnlockMemory (&ctx); + ctx.Hob->Data.TxtMode = 0; + ASSERT (TRUE); + return EFI_UNSUPPORTED; + } + } + /// + /// Memory is supposed to lock if system is TxT capable. + /// Check if we need to run SCLEAN. TxT BIOS spec Section 6.2.5 + /// + if (IsEstablishmentBitAsserted (&ctx) && IsTxtWakeError (&ctx)) { + + DEBUG ((EFI_D_INFO, "TXTPEI::EstablishmentBit is set\n")); + /// + /// If TXTRESET is set , we must clean TXTRESET bit otherwise SCLEAN + /// will fail + /// + if (IsTxtResetSet (&ctx)) { + DoGlobalReset (); + } + /// + /// Setup and Launch SCLEAN + /// + DEBUG ((EFI_D_INFO, "TXTPEI::Entering SCLEAN\n")); + + DoSclean (&ctx); + + /// + /// Reset platform - performed by DoSclean, should not return to execute the following dead looping + /// + EFI_DEADLOOP (); + } else { + /// + /// Unlock memory, and then continue running + /// + DEBUG ((EFI_D_INFO, "TXTPEI::EstablishmentBit not asserted - Unlock Memory\n")); + AsmWriteMsr64 (0x2e6, 0); + } + + Status = PeiServicesNotifyPpi (&mNotifyDesc); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Fix up pointers since they are located in real memory now. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] NotifyDescriptor The notification structure this PEIM registered on install. + @param[in] Ppi The memory discovered PPI. Not used. + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFI_STATUS +EFIAPI +DprUpdate ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + TXT_INFO_HOB *TxtInfoHob; + SA_DATA_HOB *SaDataHob; + DPR_DIRECTORY_ENTRY *DprDirectory; + UINT16 Index; + + TxtInfoHob = NULL; + SaDataHob = NULL; + DprDirectory = NULL; + Index = 0; + + // + // Get TxtInfoHob + // + TxtInfoHob = (TXT_INFO_HOB *)GetFirstGuidHob (&gTxtInfoHobGuid); + if (TxtInfoHob == NULL) { + return EFI_NOT_FOUND; + } + TxtInfoHob->Data.TxtDprMemoryBase = 0; + + // + // Get SaDataHob + // + SaDataHob = (SA_DATA_HOB *)GetFirstGuidHob (&gSaDataHobGuid); + if (SaDataHob == NULL) { + return EFI_NOT_FOUND; + } + DprDirectory = (DPR_DIRECTORY_ENTRY *)&(SaDataHob->DprDirectory[0]); + + // + // Find TxT DPR Directory + // + for (Index=0; Index<DPR_DIRECTORY_MAX; Index++) { + if (DprDirectory[Index].Type == DPR_DIRECTORY_TYPE_TXT) { + TxtInfoHob->Data.TxtDprMemoryBase = (EFI_PHYSICAL_ADDRESS)DprDirectory[Index].PhysBase; + break; + } + } + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.dxs b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.dxs new file mode 100644 index 0000000..fa940d7 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.dxs @@ -0,0 +1,49 @@ +/** @file + This is the Dependency expression for the TXT Pei PPI + +@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" +#include EFI_PPI_DEFINITION (Stall) +#include EFI_PPI_CONSUMER (BootMode) +#endif + +#include EFI_PPI_DEFINITION (TpmInitialized) +#include EFI_PPI_DEFINITION (CpuPlatformPolicy) +#include EFI_PPI_DEPENDENCY (SaPeiInit) + +DEPENDENCY_START + PEI_STALL_PPI_GUID AND + PEI_MASTER_BOOT_MODE_PEIM_PPI AND + PEI_CPU_PLATFORM_POLICY_PPI_GUID AND + SA_PEI_INIT_PPI_GUID +DEPENDENCY_END + diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.inf b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.inf new file mode 100644 index 0000000..428372a --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.inf @@ -0,0 +1,104 @@ +## @file +# Component description file for TXT PEI module +# +#@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 +# + +[defines] +BASE_NAME = TxtPei +FILE_GUID = CA9D8617-D652-403b-B6C5-BA47570116AD +COMPONENT_TYPE = PE32_PEIM + +[sources.common] + TxtPei.c + TxtPeiLib.c + Ia32/TxtPeiBsp.asm + +# +# Edk II Glue Driver Entry Point +# + EdkIIGluePeimEntryPoint.c + +[includes.common] + . + $(EFI_SOURCE)/$(PROJECT_SA_ROOT) + $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT) + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include + $(EDK_SOURCE)/Foundation/Framework/Ppi/Stall + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + +# +# Edk II Glue Library, some hearder are included by R9 header so have to include +# + + $(EFI_SOURCE) + $(EFI_SOURCE)/Framework + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/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_CPU_ROOT)/SampleCode + +[libraries.common] + EdkFrameworkPpiLib + SaGuidLib + CpuPpiLib + CpuGuidLib + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseLib + EdkIIGlueBaseMemoryLib + EdkIIGlueBasePciLibPciExpress + EdkIIGluePeiDebugLibReportStatusCode + EdkIIGluePeiReportStatusCodeLib + EdkIIGluePeiServicesLib + EdkIIGluePeiMemoryAllocationLib + EdkIIGluePeiHobLib + AnchorCoveLib + TxtLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = TxtPei.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PeimEntry + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_LIB__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_PEI_SERVICES_LIB__ diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.mak b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.mak new file mode 100644 index 0000000..ecb55ef --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.mak @@ -0,0 +1,105 @@ +# MAK file for the ModulePart:TxtPei + +all : TxtPei + +TxtPei : $(BUILD_DIR)\TxtPei.mak TxtPeiBin TxtPeiAp.bin $(BUILD_DIR)\TxtPeiap.ffs + +$(BUILD_DIR)\TxtPei.mak : $(TxtPei_DIR)\$(@B).cif $(TxtPei_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(TxtPei_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +MY_DEFINES=\ + /DAMI_MICROCODE_PPI\ +!IF "$(TXT_DEBUG_INFO)"=="1" + /D"TXT_DEBUG_INFO=1"\ +!ELSE + /D"TXT_DEBUG_INFO=0"\ +!ENDIF + +TxtPei_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(TXT_INCLUDES)\ + $(PROJECT_CPU_INCLUDES)\ + $(PROJECT_INCLUDES)\ + $(INTEL_MCH_INCLUDES)\ + $(TCG_INCLUDES)\ + +TxtPei_DEFINES=\ + $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PeimEntry"\ + /D PlatformPciExpressBaseAddress=$(PCIEX_BASE_ADDRESS) \ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_BASE_LIB__ \ + /D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + /D __EDKII_GLUE_PEI_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_PEI_SERVICES_LIB__\ + /D __EDKII_GLUE_PEI_SERVICES_TABLE_POINTER_LIB_MM7__ \ + +TxtPei_OBJECTS=\ + $(BUILD_DIR)\$(TxtPei_DIR)\TxtPei.obj\ + $(BUILD_DIR)\$(TxtPei_DIR)\TxtPeiLib.obj\ + $(BUILD_DIR)\$(TxtPei_DIR)\Ia32\TxtPeiBsp.obj + +TxtPei_LIBS=\ + $(EDKFRAMEWORKPPILIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(BUILD_DIR)\IA32\EdkIIGlueBaseLib.lib\ + $(EdkIIGlueBaseMemoryLib_LIB)\ + $(EdkIIGluePeiDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGluePeiReportStatusCodeLib_LIB)\ + $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\ + $(EdkIIGluePeiServicesLib_LIB)\ + $(EdkIIGluePeiHobLib_LIB)\ + $(EdkIIGluePeiMemoryAllocationLib_LIB)\ + $(CpuGuidLib_LIB)\ + $(CPU_PPI_LIB)\ + $(SaGuidLib_LIB)\ + $(PEIHOBLIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(EdkIIGlueBasePciExpressLib_LIB)\ + $(PchPlatformPeiLib_LIB)\ + $(CpuPlatformLib_LIB)\ + $(BootGuardLib_LIB)\ + $(TxtLib_LIB) + +TxtPeiBin : $(TxtPei_LIBS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\TxtPei.mak all\ + "MY_INCLUDES=$(TxtPei_INCLUDES)"\ + "MY_DEFINES=$(TxtPei_DEFINES)"\ + "OBJECTS=$(TxtPei_OBJECTS)" \ + "AFLAGS=$(AFLAGS) $(PROJECT_CPU_INCLUDES)"\ + GUID=CA9D8617-D652-403b-B6C5-BA47570116AD\ + ENTRY_POINT=_ModuleEntryPoint\ + TYPE=PEIM \ + EDKIIModule=PEIM\ + DEPEX1=$(TxtPei_DIR)\TxtPei.dxs \ + DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \ + COMPRESS=0\ + +TxtPeiAp.bin: $(BUILD_DIR)\TxtPeiap.bin + +$(BUILD_DIR)\TxtPeiap.bin: $(BUILD_DIR)\TxtPeiAp.obj + +$(BUILD_DIR)\TxtPeiAp.obj:$(TxtPei_DIR)\Ia32\TxtPeiAp.asm16 + $(ASM) /c /nologo $(PROJECT_CPU_INCLUDES) /Fo$(BUILD_DIR)\TxtPeiAp.obj $(TxtPei_DIR)\Ia32\TxtPeiAp.asm16 + $(ASMLINK) $(BUILD_DIR)\TxtPeiAp.obj, $*.exe, $*.map,,, + exe2bin $*.exe $*.bin + +$(BUILD_DIR)\TxtPeiap.ffs : $(BUILD_DIR)\TxtPeiap.bin + $(MAKE) /f Core\FFS.mak \ + BUILD_DIR=$(BUILD_DIR) \ + GUID=$(AP_GUID) \ + TYPE=EFI_FV_FILETYPE_RAW \ + FFS_CHECKSUM=0 \ + FFS_ALIGNMENT=5 \ + RAWFILE=$(BUILD_DIR)\TxtPeiap.bin \ + COMPRESS=0 \ + FFSFILE=$@ \ + NAME=DummyName + +TXT_AP_FIXUP: + $(TxtTools_DIR)\STAFixup.exe $(AP_GUID) $(AMI_ROM) $(AP_FIXUP_FILE) $(AP_OFFSET) + +AFTER_ROM: TXT_AP_FIXUP diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.sdl b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.sdl new file mode 100644 index 0000000..b438250 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.sdl @@ -0,0 +1,86 @@ +TOKEN + Name = "TxtPei_SUPPORT" + Value = "1" + Help = "Main switch to enable TXT Pei init support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +PATH + Name = "TxtPei_DIR" + Help = "TXT PEI source directory" +End + +TOKEN + Name = "TXT_TOOL_DIR" + Value = "$(TXT_DIR)\Tools" + Help = "TXT tools directory" + TokenType = Expression + TargetMAK = Yes + TargetH = Yes +END + +TOKEN + Name = "AP_GUID" + Value = "D1E59F50-E8C3-4545-BF61-11F002233C97" + Help = "GUID of AP initialization file." + TokenType = Expression + TargetMAK = Yes + TargetH = Yes +End + +TOKEN + Name = "AP_FIXUP_FILE" + Value = "$(TXT_TOOL_DIR)\Apfixup.txt" + Help = "Name of AP FFS fixup table file." + TokenType = Expression + TargetMAK = Yes + TargetH = Yes +End + +TOKEN + Name = "AP_OFFSET" + Value = "$(FV_BB_BLOCKS)*$(FLASH_BLOCK_SIZE)" + Help = "End-of-file offset of AP initialization file." + TokenType = Integer + TargetMAK = Yes + TargetH = Yes +End + +MODULE + Help = "Includes TXTPEI.mak into project" + File = "TXTPEI.mak" +End + +ELINK + Name = "$(BUILD_DIR)\txtpeiap.ffs" + Parent = "FV_BB" + Priority = -2000 + InvokeOrder = AfterParent +End + +ELINK + Name = "TYPE:HOLE LOCATION:0xfffff000" + Parent = "$(BUILD_DIR)\txtpeiap.ffs" + InvokeOrder = AfterParent +End + +ELINK + Name = "$(BUILD_DIR)\TxtPei.ffs" + Parent = "FV_BB" + InvokeOrder = BeforeParent +End + +ELINK + Name = "TXT_INCLUDES" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "/I$(TxtPei_DIR)" + Parent = "TXT_INCLUDES" + InvokeOrder = AfterParent +End
\ No newline at end of file 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; +} diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.h b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.h new file mode 100644 index 0000000..28c1303 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.h @@ -0,0 +1,560 @@ +/** @file + This file contains function definitions that can determine + the TXT capabilities of a platform during PEI and perform + certain specific platform tasks that are required for TXT + during PEI. + +@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 _TXT_PEI_LIB_H_ +#define _TXT_PEI_LIB_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 "EdkIIGluePeim.h" +#include "Txt.h" +#include "CpuAccess.h" +#include "BootGuardLibrary.h" + +#include EFI_PPI_DEPENDENCY (Variable) +#include EFI_PPI_DEPENDENCY (Stall) +#include EFI_PPI_DEFINITION (TxtMemoryUnlocked) +#include EFI_GUID_DEFINITION (TxtInfoHob) +#include EFI_PPI_PRODUCER (CpuPlatformPolicy) +#endif +#include EFI_PPI_CONSUMER (TpmInitialized) + +#define RESET_PORT 0x0CF9 +#define FULL_RESET_VALUE 0xE + +#define PCI_BUS_NUMBER_PCH_LPC 0 +#define PCI_DEVICE_NUMBER_PCH_LPC 31 +#define PCI_FUNCTION_NUMBER_PCH_LPC 0 +#define R_PCH_LPC_ACPI_BASE 0x40 + +#define APIC_SPURIOUS_VECTOR_REGISTER 0xF0 +#define DEST_FIELD (0 << 18) +#define ALL_EXCLUDING_SELF BIT19 + BIT18 +#define SIPI BIT10 + BIT9 +#define INIT BIT10 + BIT8 +#define LEVEL_ASSERT BIT14 +#define LEVEL_DEASSERT (0 << 14) +#define DELIVERY_STATUS BIT13 +#define BASE_ADDR_MASK 0xFFFFF000 +/// +/// #define EFI_MSR_EXT_XAPIC_LVT_THERM 0x833 +/// +#define EFI_MSR_EXT_XAPIC_SVR 0x80F +#define AP_STARTUP_SIZE 0x1000 +#define AP_STARTUP_ADDR 0x1000 +#define AP_STARTUP_STKOFF AP_STARTUP_ADDR + 0xFF0 + +#define BFV 0 ///< Boot Firmware Voume +#define PCI_CMD 0x0004 ///< PCI Command Register +#define BM_BIT 0x4 ///< Bus Master bit +#define PCI_SCC 0x000A ///< Sub Class Code Register +#define PCI_HDR 0x000E ///< Header Type Register +#define MF_BIT 0x80 ///< Multi-function bit +/// +/// Machne check architecture MSR registers +/// +#define MCG_CAP 0x179 +#define MCG_STATUS 0x17A +#define MCG_CTL 0x17B +#define MC0_CTL 0x400 +#define MC0_STATUS 0x401 +#define MC0_ADDR 0x402 +#define MC0_MISC 0x403 + +typedef struct _ACM_HEADER { + UINT32 ModuleType; ///< Module type + UINT32 HeaderLen; ///< 4 4 Header length (in multiples of four bytes) + /// (161 for version 0.0) + /// + UINT32 HeaderVersion; ///< 8 4 Module format version + UINT32 ModuleID; ///< 12 4 Module release identifier + UINT32 ModuleVendor; ///< 16 4 Module vendor identifier + UINT32 Date; ///< 20 4 Creation date (BCD format: + /// year.month.day) + /// + UINT32 Size; ///< 24 4 Module size (in multiples of four bytes) + UINT32 Reserved1; ///< 28 4 Reserved for future extensions + UINT32 CodeControl; ///< 32 4 Authenticated code control flags + UINT32 ErrorEntryPoint; ///< 36 4 Error response entry point offset (bytes) + UINT32 GDTLimit; ///< 40 4 GDT limit (defines last byte of GDT) + UINT32 GDTBasePtr; ///< 44 4 GDT base pointer offset (bytes) + UINT32 SegSel; ///< 48 4 Segment selector initializer + UINT32 EntryPoint; ///< 52 4 Authenticated code entry point offset (bytes) + UINT32 Reserved2; ///< 56 64 Reserved for future extensions + UINT32 KeySize; ///< 120 4 Module public key size less the exponent + /// (in multiples of four bytes + /// - 64 for version 0.0) + /// + UINT32 ScratchSize; ///< 124 4 Scratch field size (in multiples of four bytes) + /// (2 * KeySize + 15 for version 0.0) + /// + UINT8 RSAPubKey[65 * 4]; ///< 128 KeySize * 4 + 4 Module public key + UINT8 RSASig[256]; ///< 388 256 PKCS #1.5 RSA Signature. +} ACM_HEADER; + +typedef struct _TXT_PEI_LIB_CONTEXT { + EFI_PEI_SERVICES **PeiServices; + PEI_CPU_IO_PPI *CpuIoPpi; + PEI_PCI_CFG_PPI *PciCfgPpi; + PEI_STALL_PPI *PeiStall; + ACM_HEADER *BiosAcmBase; + UINT32 BiosAcmSize; + VOID *ApStartup; + UINT32 *McuStart; + UINT32 Ia32ApicBase; + TXT_INFO_HOB *Hob; +} TXT_PEI_LIB_CONTEXT; + +#pragma pack(1) +typedef union _MSR_REGISTER { + UINT64 Qword; + + struct _DWORDS { + UINT32 Low; + UINT32 High; + } Dwords; + + struct _BYTES { + UINT8 FirstByte; + UINT8 SecondByte; + UINT8 ThirdByte; + UINT8 FouthByte; + UINT8 FifthByte; + UINT8 SixthByte; + UINT8 SeventhByte; + UINT8 EighthByte; + } Bytes; + +} MSR_REGISTER; + + +#pragma pack() + +#define PLATFORM_ID_SHIFT 50 +#define PLATFORM_ID_MASK 7 ///< Bits 52:50 +typedef struct _MCU { + UINT32 headerVer; ///< MCU Header Version ( = 00000001h ) + UINT32 revision; ///< MCU Revision + UINT32 date; ///< MCU Date + UINT32 signature; ///< MCU Processor Signature + UINT32 checksum; ///< MCU Main checksum + UINT32 loaderRev; ///< MCU Loader Revision + UINT32 procFlags; ///< MCU Processor Flags (Platform ID) + UINT32 dataSize; ///< MCU Data Size + UINT32 totalSize; ///< MCU Total Size + UINT32 reserved[3]; +} MCU; + +typedef struct _EST { + UINT32 count; ///< EST Count + UINT32 checksum; ///< EST Checksum + UINT32 reserved[3]; +} EST; + +typedef struct _PSS { + UINT32 signature; ///< PSS Processor Signature + UINT32 procFlags; ///< PSS Processor Flags (Platform ID) + UINT32 checksum; ///< PSS Checksum +} PSS; + +/** + Returns CPU count + + @retval Number of CPUs +**/ +UINT32 +GetCpuCount ( + VOID + ); + +/** + Execute SCLEAN through BIOS ACM +**/ +VOID +LaunchBiosAcmSclean ( + VOID + ); + +/** + Issue a global reset through PCH and PORTCF9 +**/ +VOID +DoGlobalReset ( + VOID + ); + +/** + Issue a cpu-only reset through PCH and PORTCF9 +**/ +VOID +DoCpuReset ( + VOID + ); + +/** + Issue a HOST reset through PCH and PORTCF9 +**/ +VOID +DoHostReset ( + VOID + ); + +/** + Dispatch APs to execute *Function with parameter pointed by *Param + + @param[in] (*Function) - Address of Function to be executed by APs + @param[in] Param - Function parameter to be passed to +**/ +VOID +StartupAllAPs ( + VOID (*Function)(), + UINT64 *Param + ); + +/** + Put All APs into Wait-for-SIPI state +**/ +VOID +PutApsInWfs ( + VOID + ); + +/** + Restore MTRR registers + + @param[in] ApCfg - Point to the MTRR buffer +**/ +VOID +RestoreMtrrProgramming ( + UINT64 *ApCfg + ); + +/** + Restore APs' registers + + @param[in] ApCfg - Point to APs' registers buffer +**/ +VOID +RestoreApConfig ( + UINT64 *ApCfg + ); + +/** + Initializes values passed to AP + + @param[in] pctx - A pointer to an initialized TXT PEI Context data structure +**/ +VOID +PrepareApParams ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx, + IN EFI_PEI_SERVICES **mPS + ); + +/** + 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 + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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 + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + @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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx, + ACM_HEADER *BiosAcmBase + ); + +/** + Clear Sleep Type register. + + @param[in] pctx - A pointer to an initialized TXT PEI Context data structure + + @retval EFI_SUCCESS - Always +**/ +EFI_STATUS +ClearSlpTyp ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + Determines presence of TPM in system + + @param[in] pctx - Point to TXT_PEI_LIB_CONTEXT structure + + @retval EFI_SUCCESS - If the TPM is present. + @retval EFI_NOT_FOUND - If the TPM is not present. +**/ +EFI_STATUS +IsTpmPresent ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + 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] pBIOSAC_BASE - 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 ( + TXT_PEI_LIB_CONTEXT *pctx, + OUT UINT32 **pBIOSAC_BASE + ); + +/** + 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] pAP_STARTUP - A pointer to pointer to variable to hold address + @param[in] address. + + @retval EFI_SUCCESS - If address has been found + @retval EFI_NOT_FOUND - If address has not been found +**/ +EFI_STATUS +FindApStartupInVolume ( + TXT_PEI_LIB_CONTEXT *pctx, + OUT UINT32 **pAP_STARTUP + ); + +/** + 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] pMCU - 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 ( + TXT_PEI_LIB_CONTEXT *pctx, + OUT UINT32 **pMCU + ); + +/** + 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] pGuid - A pointer GUID + @param[in] pModule - 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 ( + TXT_PEI_LIB_CONTEXT *pctx, + EFI_GUID *pGuid, + OUT UINT32 **pModule + ); + +/** + Parses Hob list for 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 ( + TXT_PEI_LIB_CONTEXT *pctx + ); + +/** + Unlock memory when security is set ant 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 + ); + +/** + Fix up pointers since they are located in real memory now. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] NotifyDescriptor The notification structure this PEIM registered on install. + @param[in] Ppi The memory discovered PPI. Not used. + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFI_STATUS +DprUpdate ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +#endif diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Txtpei.cif b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Txtpei.cif new file mode 100644 index 0000000..7cba3eb --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Txtpei.cif @@ -0,0 +1,19 @@ +<component> + name = "TxtPei" + category = ModulePart + LocalRoot = "ReferenceCode\Haswell\Txt\TxtInit\Pei\" + RefName = "TxtPei" +[files] +"TxtPei.sdl" +"TxtPei.mak" +"TxtPei.c" +"TxtPeiLib.c" +"TxtPeiLib.h" +"TxtPei.dxs" +"TxtPei.inf" +"Ia32\TxtPeiBsp.asm" +"Ia32\TxtPeiAp.asm16" +"Ia32\TxtPeiAp.inf" +"Ia32\TxtPeiApV7.inf" +"Ia32\makefile.new" +<endComponent> |