summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/Txt/TxtInit/Dxe
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Haswell/Txt/TxtInit/Dxe')
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c171
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif18
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs50
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf117
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak72
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl27
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c1080
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h289
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c78
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc494
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm364
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm712
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