diff options
Diffstat (limited to 'ReferenceCode/Haswell/Txt/TxtInit/Dxe')
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c | 171 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif | 18 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs | 50 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf | 117 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak | 72 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl | 27 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c | 1080 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h | 289 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c | 78 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc | 494 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm | 364 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm | 712 |
12 files changed, 3472 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 |