summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/Library
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Haswell/Library
downloadzprj-master.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/Haswell/Library')
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib.cif11
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib.mak20
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib.sdl32
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf64
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c121
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib.cif12
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib.mak28
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib.sdl31
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf66
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c476
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h31
-rw-r--r--ReferenceCode/Haswell/Library/OcPlatformLib.cif12
-rw-r--r--ReferenceCode/Haswell/Library/OcPlatformLib.mak20
-rw-r--r--ReferenceCode/Haswell/Library/OcPlatformLib.sdl32
-rw-r--r--ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf69
-rw-r--r--ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c621
-rw-r--r--ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h352
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib.cif13
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib.mak40
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib.sdl26
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm238
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif9
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c245
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf67
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm45
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm45
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm216
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif11
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c272
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib.cif11
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib.mak16
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib.sdl32
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm99
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf60
34 files changed, 3443 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib.cif b/ReferenceCode/Haswell/Library/BootGuardLib.cif
new file mode 100644
index 0000000..2f3587a
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "BootGuardLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "BootGuardLib"
+[files]
+"BootGuardLib.sdl"
+"BootGuardLib.mak"
+"BootGuardLib\BootGuardLib.inf"
+"BootGuardLib\BootGuardLibrary.c"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib.mak b/ReferenceCode/Haswell/Library/BootGuardLib.mak
new file mode 100644
index 0000000..5fa59bc
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib.mak
@@ -0,0 +1,20 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(BootGuardLib_LIB) : BootGuardLib
+
+BootGuardLib : $(BUILD_DIR)\BootGuardLib.mak BootGuardLibBin
+
+$(BUILD_DIR)\BootGuardLib.mak : $(BootGuardLib_DIR)\$(@B).cif $(BootGuardLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(BootGuardLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+BootGuardLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\BootGuardLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(BootGuardLib_LIB)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ /f $(BUILD_DIR)\BootGuardLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(BootGuardLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib.sdl b/ReferenceCode/Haswell/Library/BootGuardLib.sdl
new file mode 100644
index 0000000..8356d53
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib.sdl
@@ -0,0 +1,32 @@
+TOKEN
+ Name = BootGuardLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable BootGuardLib support in Project"
+End
+
+TOKEN
+ Name = "BootGuardLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\BootGuardLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "BootGuardLib_DIR"
+End
+
+ELINK
+ Name = "/I$(BootGuardLib_DIR)\BootGuardLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+MODULE
+ Help = "Includes BootGuardLib.mak to Project"
+ File = "BootGuardLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf
new file mode 100644
index 0000000..5af1ded
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf
@@ -0,0 +1,64 @@
+## @file
+# Component description file for Boot Guard Library
+#
+#@copyright
+# Copyright (c) 2012 - 2013 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains an 'Intel Peripheral Driver' and uniquely
+# identified as "Intel Reference Module" and is
+# licensed for Intel CPUs and chipsets under the terms of your
+# license agreement with Intel or your vendor. This file may
+# be modified by the user, subject to additional terms of the
+# license agreement
+#
+
+[defines]
+BASE_NAME = BootGuardLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ BootGuardLibrary.c
+
+[sources.ia32]
+
+[sources.x64]
+
+[sources.ipf]
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(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
+
+[libraries.common]
+ EdkIIGlueBasePciLibPciExpress
+ CpuPlatformLib
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c
new file mode 100644
index 0000000..e35d42f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c
@@ -0,0 +1,121 @@
+/** @file
+ BootGuardLibrary implementation.
+
+@copyright
+ Copyright (c) 2012 - 2013 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#include "CpuPlatformLib.h"
+#endif
+
+/**
+ Determine if Boot Guard is supported
+
+ @retval TRUE - Processor is Boot Guard capable.
+ @retval FALSE - Processor is not Boot Guard capable.
+
+**/
+BOOLEAN
+IsBootGuardSupported (
+ VOID
+ )
+{
+ UINT64 BootGuardBootStatus;
+ UINT32 BootGuardAcmStatus;
+ UINT64 BootGuardCapability;
+ CPU_STEPPING CpuSteppingId;
+
+ //
+ // Return unsupported if processor is not ULT sku
+ //
+ if(GetCpuSku() != EnumCpuUlt) {
+ return FALSE;
+ }
+
+ BootGuardBootStatus = *(UINT64 *) (UINTN) (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_BOOTSTATUS);
+ BootGuardAcmStatus = *(UINT32 *) (UINTN) (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_ACM_STATUS);
+ BootGuardCapability = AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & BIT32;
+ CpuSteppingId = GetCpuStepping();
+
+ if (CpuSteppingId >= EnumHswUltC0) {
+ if (BootGuardCapability != 0) {
+ DEBUG ((EFI_D_ERROR, "Processor supports Boot Guard.\n"));
+ return TRUE;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Processor does not support Boot Guard.\n"));
+ return FALSE;
+ }
+ } else {
+ if(((BootGuardBootStatus & BIT62) == 0) && // Check for ACM not found in FIT
+ ((BootGuardAcmStatus & B_BOOT_GUARD_ACM_ERRORCODE_MASK) == 0) && // Check for ACM failed to load/run successfully
+ ((BootGuardAcmStatus & BIT31) == 0)) { // Check if ACM Entered
+ DEBUG ((EFI_D_ERROR, "Processor does not support Boot Guard.\n"));
+ return FALSE;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Processor supports Boot Guard.\n"));
+ return TRUE;
+ }
+ }
+}
+
+/**
+ Stop PBE timer if system is in Boot Guard boot
+
+ @retval EFI_SUCCESS - Stop PBE timer
+ @retval EFI_UNSUPPORTED - Not in Boot Guard boot mode.
+**/
+EFI_STATUS
+StopPbeTimer (
+ VOID
+ )
+{
+ UINT64 BootGuardBootStatus;
+ UINT64 BootGuardOperationMode;
+
+ if (IsBootGuardSupported()) {
+ BootGuardBootStatus = (*(UINT64 *) (UINTN) (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_BOOTSTATUS) & (BIT63|BIT62));
+ BootGuardOperationMode = AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO);
+
+ //
+ // Stop PBET if Verified/Measured/NEM bit is set in MSR 0x13A or
+ // Boot Guard fails to launch or fails to execute successfully for avoiding brick platform
+ //
+
+ if (BootGuardBootStatus == V_CPU_BOOT_GUARD_LOAD_ACM_SUCCESS) {
+ if (BootGuardOperationMode == 0) {
+ DEBUG ((EFI_D_ERROR, "Platform in Legacy boot mode.\n"));
+ return EFI_UNSUPPORTED;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Platform in Boot Guard Boot mode.\n"));
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "Boot Guard ACM launch failed or ACM execution failed.\n"));
+ }
+
+ DEBUG ((EFI_D_ERROR, "Disable PBET\n"));
+ AsmWriteMsr64 (MSR_BC_PBEC, B_STOP_PBET);
+ } else {
+ DEBUG ((EFI_D_ERROR, "Boot Guard is not supported.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib.cif b/ReferenceCode/Haswell/Library/CpuPlatformLib.cif
new file mode 100644
index 0000000..7f1e13c
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "CpuPlatformLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "CpuPlatformLib"
+[files]
+"CpuPlatformLib.sdl"
+"CpuPlatformLib.mak"
+"CpuPlatformLib\CpuPlatformLib.inf"
+"CpuPlatformLib\CpuPlatformLibrary.c"
+"CpuPlatformLib\CpuPlatformLibrary.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib.mak b/ReferenceCode/Haswell/Library/CpuPlatformLib.mak
new file mode 100644
index 0000000..a9151b4
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib.mak
@@ -0,0 +1,28 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(CpuPlatformLib_LIB) : CpuPlatformLib
+
+CpuPlatformLib : $(BUILD_DIR)\CpuPlatformLib.mak CpuPlatformLibBin
+
+$(BUILD_DIR)\CpuPlatformLib.mak : $(CpuPlatformLib_DIR)\$(@B).cif $(CpuPlatformLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CpuPlatformLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+CpuPlatformLib_MY_INCLUDES=\
+ $(EDK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ /I$(PROJECT_CPU_ROOT)\Library\CpuPlatformLib\
+ /I$(INTEL_PCH_DIR)\Include\
+ /I$(INTEL_PCH_DIR)\Include\Library
+
+CpuPlatformLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\CpuPlatformLib.mak all\
+ "MY_INCLUDES=$(CpuPlatformLib_MY_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(CpuPlatformLib_LIB)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ /f $(BUILD_DIR)\CpuPlatformLib.mak all\
+ "MY_INCLUDES=$(CpuPlatformLib_MY_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(CpuPlatformLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib.sdl b/ReferenceCode/Haswell/Library/CpuPlatformLib.sdl
new file mode 100644
index 0000000..eb60154
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib.sdl
@@ -0,0 +1,31 @@
+TOKEN
+ Name = CpuPlatformLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable ThunkLib support in Project"
+End
+
+TOKEN
+ Name = "CpuPlatformLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\CpuPlatformLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "CpuPlatformLib_DIR"
+End
+
+MODULE
+ Help = "Includes ThunkLib.mak to Project"
+ File = "CpuPlatformLib.mak"
+End
+
+ELINK
+ Name = "/I$(CpuPlatformLib_DIR)\CpuPlatformLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf
new file mode 100644
index 0000000..9a0e283
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf
@@ -0,0 +1,66 @@
+## @file
+# Component description file for CPU Platform Lib
+#
+#@copyright
+# Copyright (c) 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 = CpuPlatformLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ CpuPlatformLibrary.h
+ CpuPlatformLibrary.c
+
+[sources.ia32]
+
+[sources.x64]
+
+[sources.ipf]
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(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
+
+[libraries.common]
+ PchPlatformLib
+ EdkIIGlueBasePciLibPciExpress
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c
new file mode 100644
index 0000000..043bfae
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c
@@ -0,0 +1,476 @@
+/** @file
+ CPU Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+
+**/
+#include "CpuPlatformLibrary.h"
+
+/**
+ Return CPU Family ID
+
+ @retval CPU_FAMILY CPU Family ID
+**/
+CPU_FAMILY
+EFIAPI
+GetCpuFamily (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ return ((CPU_FAMILY) (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL));
+}
+
+/**
+ Return Cpu stepping type
+
+ @retval UINT8 Cpu stepping type
+**/
+CPU_STEPPING
+EFIAPI
+GetCpuStepping (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ return ((CPU_STEPPING) (Cpuid.RegEax & CPUID_FULL_STEPPING));
+}
+
+/**
+ Determine if CPU is supported
+
+ @retval TRUE CPU is supported
+ @retval FALSE CPU is not supported
+**/
+BOOLEAN
+IsCpuSupported (
+ VOID
+ )
+{
+ if (GetCpuFamily() == EnumCpuMax) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Return CPU Sku
+
+ @retval UINT8 CPU Sku
+**/
+UINT8
+EFIAPI
+GetCpuSku (
+ VOID
+ )
+{
+ UINT8 CpuType;
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ switch (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL) {
+ case CPUID_FULL_FAMILY_MODEL_HASWELL_ULT:
+ CpuType = EnumCpuUlt;
+ break;
+
+ case CPUID_FULL_FAMILY_MODEL_HASWELL:
+ case CPUID_FULL_FAMILY_MODEL_CRYSTALWELL:
+ CpuType = EnumCpuTrad;
+ break;
+
+ default:
+ CpuType = EnumCpuUnknown;
+ DEBUG ((EFI_D_ERROR, "Unsupported CPU SKU, CpuFamilyId: 0x%08X!\n", (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL)));
+ ASSERT (FALSE);
+ break;
+ }
+
+ return CpuType;
+}
+
+EFI_STATUS
+EFIAPI
+MailboxWrite (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ IN UINT32 MailboxData,
+ OUT UINT32 *MailboxStatus
+ )
+/**
+ Generic Mailbox function for mailbox write commands. This function will
+ poll the mailbox interface for control, issue the write request, poll
+ for completion, and verify the write was succussful.
+
+ @param[IN] MailboxType,
+ @param[IN] MailboxCommand,
+ @param[IN] MailboxData,
+ @param[OUT] *MailboxStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT64 MsrData;
+ UINT32 MchBar;
+ OC_MAILBOX_FULL OcMailboxFull;
+ OC_MAILBOX_FULL OcMailboxFullVerify;
+ PCODE_MAILBOX_FULL PcodeMailboxFull;
+ PCODE_MAILBOX_FULL PcodeMailboxFullVerify;
+
+ ///
+ /// Poll the run/busy to ensure the interface is available
+ ///
+ Status = PollMailboxReady(MailboxType);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Write Command = %2X\n", (UINT8)MailboxCommand));
+
+ switch (MailboxType)
+ {
+ case MAILBOX_TYPE_PCODE:
+ ///
+ /// Copy in Mailbox data and write the PCODE mailbox DATA field
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
+ PcodeMailboxFull.Data = MailboxData;
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+
+ MmioWrite32 ( (MchBar + PCODE_MAILBOX_DATA_OFFSET), PcodeMailboxFull.Data);
+
+ ///
+ /// Set the Run/Busy bit to signal mailbox data is ready to process
+ ///
+ PcodeMailboxFull.Interface.Fields.RunBusy = 1;
+ MmioWrite32 ( (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET), PcodeMailboxFull.Interface.InterfaceData);
+
+ ///
+ /// Poll run/busy to indicate the completion of write request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the BIOS PCODE mailbox to verify write completion success.
+ /// Mailbox protocol requires software to read back the interface twice
+ /// to ensure the read results are consistent.
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFull.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ ///
+ /// Read twice to verify data is consitent
+ ///
+ PcodeMailboxFullVerify.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFullVerify.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
+ if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy PCODE mailbox completion code
+ ///
+ *MailboxStatus = (UINT32) PcodeMailboxFull.Interface.Fields.Command;
+ break;
+
+ case MAILBOX_TYPE_OC:
+ ///
+ /// Set the Run/Busy bit to signal mailbox data is ready to process
+ ///
+ OcMailboxFull.Interface.InterfaceData = MailboxCommand;
+ OcMailboxFull.Data = MailboxData;
+ OcMailboxFull.Interface.Fields.RunBusy = 1;
+ CopyMem (&MsrData, &OcMailboxFull, sizeof(MsrData));
+
+ ///
+ /// Write mailbox command to OC mailbox
+ ///
+ AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);
+
+ ///
+ /// Poll run/busy to indicate the completion of write request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the mailbox command from OC mailbox. Read twice to ensure data.
+ ///
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFull, &MsrData, sizeof(OcMailboxFull));
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFullVerify, &MsrData, sizeof(OcMailboxFullVerify));
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (OcMailboxFull.Interface.InterfaceData != OcMailboxFullVerify.Interface.InterfaceData) {
+ if (OcMailboxFull.Data != OcMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy Overclocking mailbox completion code and read results
+ ///
+ *MailboxStatus = OcMailboxFull.Interface.Fields.CommandCompletion;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Unrecognized Mailbox Type.\n"));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Status = %2X\n", *MailboxStatus));
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+MailboxRead (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ OUT UINT32 *MailboxDataPtr,
+ OUT UINT32 *MailboxStatus
+ )
+/**
+ Generic Mailbox function for mailbox read commands. This function will write
+ the read request, and populate the read results in the output data.
+
+ @param[IN] MailboxType,
+ @param[IN] MailboxCommand,
+ @param[OUT] *MailboxDataPtr,
+ @param[OUT] *MailboxStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT64 MsrData;
+ UINT32 MchBar;
+ PCODE_MAILBOX_FULL PcodeMailboxFull;
+ PCODE_MAILBOX_FULL PcodeMailboxFullVerify;
+ OC_MAILBOX_FULL OcMailboxFull;
+ OC_MAILBOX_FULL OcMailboxFullVerify;
+
+ ///
+ /// Poll the run/busy to ensure the interface is available
+ ///
+ Status = PollMailboxReady(MailboxType);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Read Command = %2X\n", (UINT8)MailboxCommand));
+
+ switch (MailboxType)
+ {
+ case MAILBOX_TYPE_PCODE:
+ ///
+ /// Write the PCODE mailbox read request.
+ /// Read requests only require a write to the PCODE interface mailbox.
+ /// The read results will be updated in the data mailbox.
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
+ PcodeMailboxFull.Interface.Fields.RunBusy = 1;
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+
+ MmioWrite32 ( (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET), PcodeMailboxFull.Interface.InterfaceData);
+
+ ///
+ /// Poll run/busy to indicate the completion of read request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the BIOS PCODE mailbox to verify read completion success.
+ /// Mailbox protocol requires software to read back the interface twice
+ /// to ensure the read results are consistent.
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFull.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ ///
+ /// Read twice to verify data is consitent
+ ///
+ PcodeMailboxFullVerify.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFullVerify.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
+ if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy PCODE mailbox completion code and read results
+ ///
+ *MailboxStatus = (UINT32) PcodeMailboxFull.Interface.InterfaceData;
+ CopyMem(MailboxDataPtr, &PcodeMailboxFull.Data, sizeof(UINT32));
+ break;
+
+ case MAILBOX_TYPE_OC:
+ ///
+ /// Set the Run/Busy bit to signal mailbox data is ready to process
+ ///
+ OcMailboxFull.Interface.InterfaceData = MailboxCommand;
+ OcMailboxFull.Data = *MailboxDataPtr;
+ OcMailboxFull.Interface.Fields.RunBusy = 1;
+ CopyMem (&MsrData, &OcMailboxFull, sizeof(MsrData));
+
+ ///
+ /// Write mailbox command to OC mailbox
+ ///
+ AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);
+
+ ///
+ /// Poll run/busy to indicate the completion of write request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the OC mailbox to verify read completion success.
+ /// Mailbox protocol requires software to read back the interface twice
+ /// to ensure the read results are consistent.
+ ///
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFull, &MsrData, sizeof(OcMailboxFull));
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFullVerify, &MsrData, sizeof(OcMailboxFullVerify));
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (OcMailboxFull.Interface.InterfaceData != OcMailboxFullVerify.Interface.InterfaceData) {
+ if (OcMailboxFull.Data != OcMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy Overclocking mailbox completion code and read results
+ ///
+ *MailboxStatus = OcMailboxFull.Interface.Fields.CommandCompletion;
+ CopyMem(MailboxDataPtr, &OcMailboxFull.Data, sizeof(UINT32));
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Unrecognized Mailbox Type.\n"));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Status = %2X\n", *MailboxStatus));
+
+ return Status;
+}
+
+/**
+ Poll the run/busy bit of the mailbox until available or timeout expires.
+
+ @param[IN] MailboxType,
+
+ @retval EFI_STATUS
+**/
+EFI_STATUS
+EFIAPI
+PollMailboxReady (
+ IN UINT32 MailboxType
+ )
+{
+ EFI_STATUS Status;
+ UINT16 StallCount;
+ UINT8 RunBusyBit;
+ UINT64 MsrData;
+ UINT32 MchBar;
+ OC_MAILBOX_FULL OcMailboxFull;
+ PCODE_MAILBOX_INTERFACE PcodeMailboxInterface;
+
+ Status = EFI_SUCCESS;
+ StallCount = 0;
+ RunBusyBit = 1;
+
+ do {
+ switch (MailboxType)
+ {
+ case MAILBOX_TYPE_PCODE:
+ ///
+ /// Read the MMIO run/busy state
+ ///
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+ PcodeMailboxInterface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ RunBusyBit = (UINT8) PcodeMailboxInterface.Fields.RunBusy;
+ break;
+
+ case MAILBOX_TYPE_OC:
+ ///
+ /// Read the OC mailbox run/busy state
+ ///
+ MsrData = AsmReadMsr64(OC_MAILBOX_MSR);
+ CopyMem(&OcMailboxFull.Data, &MsrData, sizeof(OcMailboxFull));
+ RunBusyBit = OcMailboxFull.Interface.Fields.RunBusy;
+ break;
+ }
+ //
+ // Wait for 1us
+ //
+ PchPmTimerStall(MAILBOX_WAIT_STALL);
+ StallCount++;
+ }
+ while ((RunBusyBit == 1) && (StallCount < MAILBOX_WAIT_TIMEOUT));
+
+ if ((RunBusyBit == 1) && (StallCount == MAILBOX_WAIT_TIMEOUT)) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox interface timed out.\n"));
+ Status = EFI_TIMEOUT;
+ }
+ return Status;
+}
+
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h
new file mode 100644
index 0000000..4d5d720
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h
@@ -0,0 +1,31 @@
+/** @file
+ Header file for Cpu Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+**/
+#ifndef _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+#define _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#include "CpuPlatformLib.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+#endif
+
+#endif
diff --git a/ReferenceCode/Haswell/Library/OcPlatformLib.cif b/ReferenceCode/Haswell/Library/OcPlatformLib.cif
new file mode 100644
index 0000000..7699c9a
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OcPlatformLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "OcPlatformLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "OcPlatformLib"
+[files]
+"OcPlatformLib.sdl"
+"OcPlatformLib.mak"
+"OverclockingLib\OverclockingLib.inf"
+"OverclockingLib\OverclockingLibrary.c"
+"OverclockingLib\OverclockingLibrary.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/OcPlatformLib.mak b/ReferenceCode/Haswell/Library/OcPlatformLib.mak
new file mode 100644
index 0000000..512f086
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OcPlatformLib.mak
@@ -0,0 +1,20 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(OcPlatformLib_LIB) : OcPlatformLib
+
+OcPlatformLib : $(BUILD_DIR)\OcPlatformLib.mak OcPlatformLibBin
+
+$(BUILD_DIR)\OcPlatformLib.mak : $(OcPlatformLib_DIR)\$(@B).cif $(OcPlatformLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(OcPlatformLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+OcPlatformLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\OcPlatformLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(OcPlatformLib_LIB)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ /f $(BUILD_DIR)\OcPlatformLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(OcPlatformLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/OcPlatformLib.sdl b/ReferenceCode/Haswell/Library/OcPlatformLib.sdl
new file mode 100644
index 0000000..bd92181
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OcPlatformLib.sdl
@@ -0,0 +1,32 @@
+TOKEN
+ Name = OcPlatformLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable OcLib support in Project"
+End
+
+TOKEN
+ Name = "OcPlatformLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\OcPlatformLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "OcPlatformLib_DIR"
+End
+
+ELINK
+ Name = "/I$(OcPlatformLib_DIR)\OverclockingLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+MODULE
+ Help = "Includes OcPlatformLib.mak to Project"
+ File = "OcPlatformLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf
new file mode 100644
index 0000000..8c286ef
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf
@@ -0,0 +1,69 @@
+## @file
+# Component description file for CPU PPI library.
+#
+#@copyright
+# Copyright (c) 2005 - 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
+#
+
+[defines]
+BASE_NAME = OverclockingLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ OverclockingLibrary.c
+ OverclockingLibrary.h
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Library/CpuPlatformLib
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+
+#
+# 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
+
+[libraries.common]
+ CpuPlatformLib
+
+[nmake.common]
+C_STD_INCLUDE=
+
+
diff --git a/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c
new file mode 100644
index 0000000..e4576fc
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c
@@ -0,0 +1,621 @@
+/** @file
+ CPU Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+
+**/
+#include "OverclockingLibrary.h"
+#include "CpuPlatformLibrary.h"
+
+EFI_STATUS
+EFIAPI
+GetVoltageFrequencyItem (
+ OUT VOLTAGE_FREQUENCY_ITEM *VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Gets the Voltage and Frequency information for a given CPU domain
+
+ @param[OUT] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ UINT16 TempVoltageTarget;
+ INT16 TempVoltageOffset;
+ OC_MAILBOX_ITEM VfMsg;
+
+ Status = EFI_SUCCESS;
+
+ ZeroMem(&VfMsg,sizeof(VfMsg));
+ ///
+ /// Convert v/f command to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_VOLTAGE_FREQUENCY;
+
+ ConvertToMailboxFormat((VOID *)VfSettings, &VfMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, VfMsg.Interface.InterfaceData, &VfMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to VfSettings
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ VfSettings->VfSettings.MaxOcRatio = (UINT8) (VfMsg.Data & MAX_RATIO_MASK);
+ VfSettings->VfSettings.VoltageTargetMode = (UINT8) ( (VfMsg.Data & VOLTAGE_MODE_MASK) >> VOLTAGE_MODE_OFFSET);
+
+ TempVoltageTarget = (UINT16) (VfMsg.Data & VOLTAGE_TARGET_MASK) >> VOLTAGE_TARGET_OFFSET;
+ ConvertVoltageTarget(TempVoltageTarget, &VfSettings->VfSettings.VoltageTarget, CONVERT_TO_BINARY_MILLIVOLT);
+
+ TempVoltageOffset = (INT16)((VfMsg.Data & VOLTAGE_OFFSET_MASK) >> VOLTAGE_OFFSET_OFFSET);
+ ConvertVoltageOffset(TempVoltageOffset, &VfSettings->VfSettings.VoltageOffset, CONVERT_TO_BINARY_MILLIVOLT);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetVoltageFrequencyItem (
+ IN VOLTAGE_FREQUENCY_ITEM VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Sets the Voltage and Frequency information for a given CPU domain
+
+ @param[IN] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM VfMsg;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Convert v/f Commands to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_SET_VOLTAGE_FREQUENCY;
+ ConvertToMailboxFormat((VOID *)&VfSettings, &VfMsg, CommandId);
+
+ ///
+ /// Write the v/f Settings to the OC Mailbox
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_OC, VfMsg.Interface.InterfaceData, VfMsg.Data, LibStatus);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+GetFivrConfig (
+ OUT GLOBAL_CONFIG_ITEM *FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the global FIVR Configuration information
+
+ @param[OUT] *FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM FivrMsg;
+
+ Status = EFI_SUCCESS;
+ ZeroMem(&FivrMsg, sizeof(FivrMsg));
+
+ ///
+ /// Convert FIVR message to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_GLOBAL_CONFIG;
+ ConvertToMailboxFormat((VOID *)FivrConfig, &FivrMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, FivrMsg.Interface.InterfaceData, &FivrMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to FivrConfig
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ FivrConfig->DisableFivrFaults = FivrMsg.Data & FIVR_FAULTS_MASK;
+ FivrConfig->DisableFivrEfficiency = (FivrMsg.Data & FIVR_EFFICIENCY_MASK) >> FIVR_EFFICIENCY_OFFSET;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetFivrConfig (
+ IN GLOBAL_CONFIG_ITEM FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the Global FIVR Configuration information
+
+ @param[IN] FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM FivrMsg;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Convert FIVR Command to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_SET_GLOBAL_CONFIG;
+ ConvertToMailboxFormat((VOID *)&FivrConfig, &FivrMsg, CommandId);
+
+ ///
+ /// Write the FIVR Settings to the OC Mailbox
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_OC, FivrMsg.Interface.InterfaceData, FivrMsg.Data, LibStatus);
+
+ return Status;
+
+}
+
+EFI_STATUS
+EFIAPI
+GetSvidConfig (
+ OUT SVID_CONFIG_ITEM *SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the SVID Configuration information
+
+ @param[OUT] *SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM SvidMsg;
+
+ Status = EFI_SUCCESS;
+ ZeroMem(&SvidMsg, sizeof(SvidMsg));
+
+ ///
+ /// Convert SVID message to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_SVID_CONFIG;
+ ConvertToMailboxFormat((VOID *)SvidConfig, &SvidMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, SvidMsg.Interface.InterfaceData, &SvidMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to SvidConfig
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ SvidConfig->VoltageTarget = (UINT16) SvidMsg.Data & SVID_VOLTAGE_MASK;
+ SvidConfig->SvidDisable = (UINT8) ((SvidMsg.Data & SVID_DISABLE_MASK) >> SVID_DISABLE_OFFSET);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetSvidConfig (
+ IN SVID_CONFIG_ITEM SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the SVID Configuration information
+
+ @param[IN] SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM SvidMsg;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Convert SVID Commands to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_SET_SVID_CONFIG;
+ ConvertToMailboxFormat((VOID *)&SvidConfig, &SvidMsg, CommandId);
+
+ ///
+ /// Write the Svid Settings to the OC Mailbox
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_OC, SvidMsg.Interface.InterfaceData, SvidMsg.Data, LibStatus);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+GetOcCapabilities (
+ OUT OC_CAPABILITIES_ITEM *OcCapabilities,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the overclocking capabilities for a given CPU Domain
+
+ @param[OUT] *OcCapabilities
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM OcCapsMsg;
+
+ Status = EFI_SUCCESS;
+
+ ZeroMem(&OcCapsMsg,sizeof(OC_MAILBOX_ITEM));
+
+ ///
+ /// Convert OC capabilties message to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_OC_CAPABILITIES;
+ ConvertToMailboxFormat((VOID *)OcCapabilities, &OcCapsMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, OcCapsMsg.Interface.InterfaceData, &OcCapsMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to OC Capabilities structure
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ OcCapabilities->MaxOcRatioLimit =
+ (UINT8) OcCapsMsg.Data & OC_CAPS_MAX_RATIO_MASK;
+
+ OcCapabilities->RatioOcSupported =
+ (UINT8) ((OcCapsMsg.Data & OC_CAPS_RATIO_SUPPORT_MASK) >> OC_CAPS_RATIO_SUPPORT_OFFSET);
+
+ OcCapabilities->VoltageOverridesSupported =
+ (UINT8) ((OcCapsMsg.Data & OC_CAPS_OVERRIDE_SUPPORT_MASK) >> OC_CAPS_OVERRIDE_SUPPORT_OFFSET);
+
+ OcCapabilities->VoltageOffsetSupported =
+ (UINT8) ((OcCapsMsg.Data & OC_CAPS_OFFSET_SUPPORT_MASK) >> OC_CAPS_OFFSET_SUPPORT_OFFSET);
+ }
+
+ return Status;
+}
+
+VOID
+ConvertVoltageTarget (
+ IN UINT16 InputVoltageTarget,
+ OUT UINT16 *OutputVoltageTarget,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input voltage target to the fixed point U12.2.10 Volt format or
+ the Binary millivolts representation based on the ConversionType
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Binary millivolts
+**/
+{
+UINT32 Remainder;
+ /// Fixed point representation:
+ ///
+ /// U12.2.10V format
+ /// | | | |
+ /// | | | v
+ /// | | v Exponent
+ /// | v Significand Size
+ /// v Size
+ /// Signed/Unsigned
+ ///
+ /// Float Value = Significand x (Base ^ Exponent)
+ /// (Base ^ Exponent) = 2 ^ 10 = 1024
+ ///
+ Remainder = 0;
+
+ if (InputVoltageTarget == 0) {
+ *OutputVoltageTarget = 0;
+ return;
+ }
+
+ if (ConversionType == CONVERT_TO_FIXED_POINT_VOLTS) {
+ ///
+ /// Input Voltage is in number of millivolts. Clip the input Voltage
+ /// to the max allowed by the fixed point format
+ ///
+ if (InputVoltageTarget > MAX_TARGET_MV)
+ InputVoltageTarget = MAX_TARGET_MV;
+
+ ///
+ /// InputTargetVoltage is the significand in mV. Need to convert to Volts
+ ///
+ *OutputVoltageTarget = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageTarget * 1024), MILLIVOLTS_PER_VOLT,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageTarget += 1;
+ }
+ } else if (ConversionType == CONVERT_TO_BINARY_MILLIVOLT) {
+ ///
+ /// InputVoltage is specified in fixed point representation, need to
+ /// convert to millivolts
+ ///
+ *OutputVoltageTarget = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageTarget * MILLIVOLTS_PER_VOLT), 1024,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageTarget += 1;
+ }
+ }
+
+ return;
+}
+
+VOID
+ConvertVoltageOffset (
+ IN INT16 InputVoltageOffset,
+ OUT INT16 *OutputVoltageOffset,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input votlage Offset to the fixed point S11.0.10 Volt format or
+ to Binary illivolts representation based on the ConversionType.
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Signed Binary millivolts
+**/
+{
+ BOOLEAN NumIsNegative;
+ UINT32 Remainder;
+ /// Fixed point representation:
+ ///
+ /// S11.0.10V format
+ /// | | | |
+ /// | | | v
+ /// | | v Exponent
+ /// | v Significand Size
+ /// v Size
+ /// Signed/Unsigned
+ ///
+ /// Float Value = Significand x (Base ^ Exponent)
+ /// (Base ^ Exponent) = 2 ^ 10 = 1024
+ ///
+ *OutputVoltageOffset = 0;
+ NumIsNegative = FALSE;
+ Remainder = 0;
+
+ if (InputVoltageOffset == 0) {
+ *OutputVoltageOffset = 0;
+ return;
+ }
+
+ if (ConversionType == CONVERT_TO_FIXED_POINT_VOLTS) {
+ ///
+ /// Input Voltage is in INT16 representation. Check if numenr is negative
+ ///
+ if ( (InputVoltageOffset & INT16_SIGN_BIT_MASK) != 0) {
+ NumIsNegative = TRUE;
+ ///
+ /// Need to 2's complement adjust to make this number positive for
+ /// voltage calculation
+ ///
+ InputVoltageOffset = (~InputVoltageOffset+1) & (INT16_SIGN_BIT_MASK -1);
+ }
+
+ ///
+ /// Clip the input Voltage Offset to 500mv
+ ///
+ if (InputVoltageOffset > MAX_OFFSET_MV) {
+ InputVoltageOffset = MAX_OFFSET_MV;
+ }
+
+ ///
+ /// Convert to fixed point representation
+ ///
+ *OutputVoltageOffset = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageOffset * 1024), MILLIVOLTS_PER_VOLT,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageOffset += 1;
+ }
+
+ if (NumIsNegative) {
+ /// 2's complement back to a negative number
+ *OutputVoltageOffset = ~(*OutputVoltageOffset) + 1;
+ }
+ } else if (ConversionType == CONVERT_TO_BINARY_MILLIVOLT) {
+ ///
+ /// Input Voltage is in fixed point representation. Check if number negative
+ ///
+ if ( (InputVoltageOffset & FIXED_POINT_SIGN_BIT_MASK)!= 0) {
+ NumIsNegative = TRUE;
+ ///
+ /// Need to 2's complement adjust to make this number positive for
+ /// voltage calculation
+ ///
+ InputVoltageOffset = (~InputVoltageOffset+1) & (FIXED_POINT_SIGN_BIT_MASK -1);
+ }
+
+ ///
+ /// Convert to INT16 representation in millivolts
+ ///
+ *OutputVoltageOffset = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageOffset * MILLIVOLTS_PER_VOLT), 1024,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageOffset += 1;
+ }
+
+ if (NumIsNegative) {
+ /// 2's complement back to a negative number
+ *OutputVoltageOffset = ~(*OutputVoltageOffset) + 1;
+ }
+ }
+
+ return;
+}
+
+VOID
+ConvertToMailboxFormat (
+ IN VOID *InputData,
+ OUT OC_MAILBOX_ITEM *MailboxData,
+ IN UINT32 CommandId
+ )
+/**
+ Converts the input data to valid mailbox command format based on CommandID
+
+@param[IN] InputData
+@param[OUT] *MailboxData
+@param[IN] CommandId
+**/
+{
+ VOLTAGE_FREQUENCY_ITEM *VfItem;
+ SVID_CONFIG_ITEM *SvidItem;
+ OC_CAPABILITIES_ITEM *OcCapItem;
+ CORE_RATIO_LIMITS_ITEM *CoreRatioItem;
+ GLOBAL_CONFIG_ITEM *GlobalConfigItem;
+ VF_MAILBOX_COMMAND_DATA VfMailboxCommandData;
+ UINT16 TempVoltage;
+
+ ///
+ /// Initialize local varaibles and mailbox data
+ ///
+ ZeroMem ((UINT32 *)MailboxData, sizeof(OC_MAILBOX_ITEM));
+
+ ///
+ /// Then make a decision based on CommandId how to format
+ ///
+ switch (CommandId) {
+ case OC_LIB_CMD_GET_OC_CAPABILITIES:
+ OcCapItem = (OC_CAPABILITIES_ITEM *) InputData;
+ ///
+ /// OC Capabilities are returned on a per domain basis
+ ///
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_OC_CAPABILITIES;
+ MailboxData->Interface.Fields.Param1 = OcCapItem->DomainId;
+ break;
+
+ case OC_LIB_CMD_GET_PER_CORE_RATIO_LIMIT:
+ CoreRatioItem = (CORE_RATIO_LIMITS_ITEM *) InputData;
+ ///
+ /// Core Ratio Limits are only valid in the IA Core domain
+ ///
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_PER_CORE_RATIO_LIMIT;
+ MailboxData->Interface.Fields.Param1 = OC_LIB_DOMAIN_ID_IA_CORE;
+ MailboxData->Interface.Fields.Param2 = CoreRatioItem->Index;
+ break;
+
+ case OC_LIB_CMD_GET_VOLTAGE_FREQUENCY:
+ VfItem = (VOLTAGE_FREQUENCY_ITEM *) InputData;
+ ///
+ /// Voltage Frequency Settings are on a per domain basis
+ ///
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_VOLTAGE_FREQUENCY;
+ MailboxData->Interface.Fields.Param1 = VfItem->DomainId;
+ break;
+
+ case OC_LIB_CMD_SET_VOLTAGE_FREQUENCY:
+ VfItem = (VOLTAGE_FREQUENCY_ITEM *) InputData;
+ ///
+ /// Voltages are stored in a fixed point format
+ ///
+ VfMailboxCommandData.MaxOcRatio = VfItem->VfSettings.MaxOcRatio;
+
+ TempVoltage = 0;
+ ConvertVoltageTarget(VfItem->VfSettings.VoltageTarget, &TempVoltage, CONVERT_TO_FIXED_POINT_VOLTS);
+ VfMailboxCommandData.VoltageTargetU12 = TempVoltage;
+
+ VfMailboxCommandData.TargetMode = VfItem->VfSettings.VoltageTargetMode;
+
+ TempVoltage = 0;
+ ConvertVoltageOffset(VfItem->VfSettings.VoltageOffset, (INT16 *) &TempVoltage, CONVERT_TO_FIXED_POINT_VOLTS);
+ VfMailboxCommandData.VoltageOffsetS11 = TempVoltage;
+
+ CopyMem(&MailboxData->Data, &VfMailboxCommandData, sizeof(VfMailboxCommandData));
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_SET_VOLTAGE_FREQUENCY;
+ MailboxData->Interface.Fields.Param1 = VfItem->DomainId;
+ break;
+
+ case OC_LIB_CMD_GET_SVID_CONFIG:
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_SVID_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ case OC_LIB_CMD_SET_SVID_CONFIG:
+ SvidItem = (SVID_CONFIG_ITEM *) InputData;
+ ConvertVoltageTarget(SvidItem->VoltageTarget, &TempVoltage, CONVERT_TO_FIXED_POINT_VOLTS);
+ MailboxData->Data = TempVoltage | (SvidItem->SvidDisable << SVID_DISABLE_OFFSET);
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_SET_SVID_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ case OC_LIB_CMD_GET_GLOBAL_CONFIG:
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_GLOBAL_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ case OC_LIB_CMD_SET_GLOBAL_CONFIG:
+ GlobalConfigItem = (GLOBAL_CONFIG_ITEM *) InputData;
+ MailboxData->Data =
+ (GlobalConfigItem->DisableFivrFaults & BIT0_MASK) |
+ ((GlobalConfigItem->DisableFivrEfficiency & BIT0_MASK) << FIVR_EFFICIENCY_OFFSET);
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_SET_GLOBAL_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "(OC MAILBOX) Unknown Command ID\n"));
+
+ break;
+
+ }
+
+}
+
diff --git a/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h
new file mode 100644
index 0000000..fd32d1f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h
@@ -0,0 +1,352 @@
+/** @file
+ Header file for Cpu Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+**/
+#ifndef _OVERCLOCKING_LIBRARY_H_
+#define _OVERCLOCKING_LIBRARY_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#endif
+
+//
+// OC Mailbox MSR
+//
+#define MSR_OC_MAILBOX 0x00000150
+#define OC_LIB_WAIT_TIMEOUT 5000 ///< 5 milliseconds
+
+//
+// OC Mailbox commands
+//
+#define OC_LIB_CMD_GET_OC_CAPABILITIES 0x01
+#define OC_LIB_CMD_GET_PER_CORE_RATIO_LIMIT 0x02
+#define OC_LIB_CMD_GET_VOLTAGE_FREQUENCY 0x10
+#define OC_LIB_CMD_SET_VOLTAGE_FREQUENCY 0x11
+#define OC_LIB_CMD_GET_SVID_CONFIG 0x12
+#define OC_LIB_CMD_SET_SVID_CONFIG 0x13
+#define OC_LIB_CMD_GET_GLOBAL_CONFIG 0x14
+#define OC_LIB_CMD_SET_GLOBAL_CONFIG 0x15
+
+//
+// OC Mailbox completion codes
+//
+#define OC_LIB_COMPLETION_CODE_SUCCESS 0x00
+#define OC_LIB_COMPLETION_CODE_OC_LOCKED 0x01
+#define OC_LIB_COMPLETION_CODE_INVALID_DOMAIN 0x02
+#define OC_LIB_COMPLETION_CODE_MAX_RATIO_EXCEEDED 0x03
+#define OC_LIB_COMPLETION_CODE_MAX_VOLTAGE_EXCEEDED 0x04
+#define OC_LIB_COMPLETION_CODE_OC_NOT_SUPPORTED 0x05
+#define OC_LIB_COMPLETION_CODE_WRITE_FAILED 0x06
+#define OC_LIB_COMPLETION_CODE_READ_FAILED 0x07
+
+//
+// Domain ID definitions
+//
+#define OC_LIB_DOMAIN_ID_IA_CORE 0x00
+#define OC_LIB_DOMAIN_ID_GT 0x01
+#define OC_LIB_DOMAIN_ID_CLR 0x02
+#define OC_LIB_DOMAIN_ID_UNCORE 0x03
+#define OC_LIB_DOMAIN_ID_IOA 0x04
+#define OC_LIB_DOMAIN_ID_IOD 0x05
+
+//
+// Bit 10 is the S11.0.10V sign bit
+//
+#define FIXED_POINT_SIGN_BIT_MASK 0x0400
+#define INT16_SIGN_BIT_MASK 0x8000
+
+//
+// Voltage Conversion defines
+//
+#define MILLIVOLTS_PER_VOLT 1000
+#define MAX_TARGET_MV 4095
+#define MAX_OFFSET_MV 500
+
+#define CONVERT_TO_FIXED_POINT_VOLTS 0
+#define CONVERT_TO_BINARY_MILLIVOLT 1
+
+//
+// Masks and offsets
+//
+#define BIT0_MASK 0x1
+#define MAX_RATIO_MASK 0x000000FF
+#define VOLTAGE_TARGET_MASK 0x000FFF00
+#define VOLTAGE_TARGET_OFFSET 8
+#define VOLTAGE_MODE_MASK 0x00100000
+#define VOLTAGE_MODE_OFFSET 20
+#define VOLTAGE_OFFSET_MASK 0xFFE00000
+#define VOLTAGE_OFFSET_OFFSET 21
+
+#define SVID_DISABLE_MASK 0x80000000
+#define SVID_DISABLE_OFFSET 31
+#define SVID_VOLTAGE_MASK 0x00000FFF
+
+#define FIVR_FAULTS_MASK 0x00000001
+#define FIVR_EFFICIENCY_MASK 0x00000002
+#define FIVR_EFFICIENCY_OFFSET 1
+
+#define OC_CAPS_MAX_RATIO_MASK 0x000000FF
+#define OC_CAPS_RATIO_SUPPORT_MASK 0x00000100
+#define OC_CAPS_RATIO_SUPPORT_OFFSET 8
+#define OC_CAPS_OVERRIDE_SUPPORT_MASK 0x00000200
+#define OC_CAPS_OVERRIDE_SUPPORT_OFFSET 9
+#define OC_CAPS_OFFSET_SUPPORT_MASK 0x00000400
+#define OC_CAPS_OFFSET_SUPPORT_OFFSET 10
+
+//
+// Voltage offset definitions
+//
+#define OC_LIB_OFFSET_ADAPTIVE 0
+#define OC_LIB_OFFSET_OVERRIDE 1
+#define OC_LIB_VOLTAGE_DO_NOT_UPDATE 0xFFFF
+
+///
+/// OC Library structures
+///
+typedef struct {
+ UINT32 CommandData;
+ UINT8 CommandCompletion : 8;
+ UINT8 Param1 : 8;
+ UINT8 Param2 : 8;
+ UINT8 Reserved : 7;
+ UINT8 RunBusy : 1;
+} OC_LIBRARY_COMMAND;
+
+typedef union _OC_MAILBOX_COMMAND {
+ UINT32 InterfaceData;
+ struct {
+ UINT8 CommandCompletion : 8;
+ UINT8 Param1 : 8;
+ UINT8 Param2 : 8;
+ UINT8 Reserved : 7;
+ UINT8 RunBusy : 1;
+ } Fields;
+} OC_MAILBOX_COMMAND;
+
+typedef struct _OC_MAILBOX_ITEM {
+ UINT32 Data;
+ OC_MAILBOX_COMMAND Interface;
+} OC_MAILBOX_ITEM;
+
+typedef struct {
+ UINT8 MaxOcRatio;
+ UINT8 VoltageTargetMode;
+ UINT16 VoltageTarget;
+ INT16 VoltageOffset;
+} VOLTAGE_FREQUENCY_SETTINGS;
+
+typedef struct {
+ VOLTAGE_FREQUENCY_SETTINGS VfSettings;
+ UINT8 DomainId;
+} VOLTAGE_FREQUENCY_ITEM;
+
+typedef enum {
+ IaCore,
+ Gt,
+ Clr,
+ Uncore
+} CPU_DOMAIN_ID;
+
+typedef struct {
+ UINT16 VoltageTarget;
+ BOOLEAN SvidDisable;
+} SVID_CONFIG_ITEM;
+
+typedef struct {
+ UINT8 MaxOcRatioLimit;
+ BOOLEAN RatioOcSupported;
+ BOOLEAN VoltageOverridesSupported;
+ BOOLEAN VoltageOffsetSupported;
+ UINT8 DomainId;
+} OC_CAPABILITIES_ITEM;
+
+typedef struct {
+ UINT8 MaxOcRatioLimit1C;
+ UINT8 MaxOcRatioLimit2C;
+ UINT8 MaxOcRatioLimit3C;
+ UINT8 MaxOcRatioLimit4C;
+ UINT8 Index;
+} CORE_RATIO_LIMITS_ITEM;
+
+typedef struct {
+ UINT8 DisableFivrFaults;
+ UINT8 DisableFivrEfficiency;
+} GLOBAL_CONFIG_ITEM;
+
+typedef struct {
+ UINT32 MaxOcRatio : 8;
+ UINT32 VoltageTargetU12 : 12;
+ UINT32 TargetMode : 1;
+ UINT32 VoltageOffsetS11 : 11;
+} VF_MAILBOX_COMMAND_DATA;
+
+///
+/// OC Library Function Prototypes
+///
+EFI_STATUS
+EFIAPI GetVoltageFrequencyItem (
+ OUT VOLTAGE_FREQUENCY_ITEM *VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Gets the Voltage and Frequency information for a given CPU domain
+
+ @param[OUT] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI SetVoltageFrequencyItem (
+ IN VOLTAGE_FREQUENCY_ITEM VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Sets the Voltage and Frequency information for a given CPU domain
+
+ @param[IN] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI GetFivrConfig (
+ OUT GLOBAL_CONFIG_ITEM *FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the global FIVR Configuration information
+
+ @param[OUT] *FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI SetFivrConfig (
+ IN GLOBAL_CONFIG_ITEM FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the Global FIVR Configuration information
+
+ @param[IN] FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI GetSvidConfig (
+ OUT SVID_CONFIG_ITEM *SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the SVID Configuration information
+
+ @param[OUT] *SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI SetSvidConfig (
+ IN SVID_CONFIG_ITEM SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the SVID Configuration information
+
+ @param[IN] SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI GetOcCapabilities (
+ OUT OC_CAPABILITIES_ITEM *OcCapabilities,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the overclocking capabilities for a given CPU Domain
+
+ @param[OUT] *OcCapabilities
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+VOID
+ConvertVoltageTarget (
+ IN UINT16 InputVoltageTarget,
+ OUT UINT16 *OutputVoltageTarget,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input voltage target to the fixed point U12.2.10 Volt format or
+ the Binary millivolts representation based on the ConversionType
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Binary millivolts
+**/
+;
+
+VOID
+ConvertVoltageOffset (
+ IN INT16 InputVoltageOffset,
+ OUT INT16 *OutputVoltageOffset,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input votlage Offset to the fixed point S11.0.10 Volt format or
+ to Binary illivolts representation based on the ConversionType.
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Signed Binary millivolts
+**/
+;
+
+VOID
+ConvertToMailboxFormat (
+ IN VOID *InputData,
+ OUT OC_MAILBOX_ITEM *MailboxData,
+ IN UINT32 CommandId
+ )
+/**
+ Converts the input data to valid mailbox command format based on CommandID
+
+@param[IN] InputData
+@param[OUT] *MailboxData
+@param[IN] CommandId
+**/
+;
+
+#endif
diff --git a/ReferenceCode/Haswell/Library/ThunkLib.cif b/ReferenceCode/Haswell/Library/ThunkLib.cif
new file mode 100644
index 0000000..f8eda34
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "ThunkLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "ThunkLib"
+[files]
+"ThunkLib.sdl"
+"ThunkLib.mak"
+"ThunkLib\ThunkLib.inf"
+[parts]
+"ThunkLibIa32"
+"ThunkLibx64"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib.mak b/ReferenceCode/Haswell/Library/ThunkLib.mak
new file mode 100644
index 0000000..ead3c5e
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib.mak
@@ -0,0 +1,40 @@
+# MAK file for the ModulePart:ThunkLib
+ThunkLib_x64_OBJECTS =\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\x86Thunk.obj\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\Thunk16.obj\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\FxSave.obj\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\FxRestore.obj
+
+ThunkLib_IA32_OBJECTS =\
+$(BUILD_DIR)\IA32\ReferenceCode\IvyBridgeRc\Library\ThunkLib\Ia32\x86Thunk.obj\
+$(BUILD_DIR)\IA32\ReferenceCode\IvyBridgeRc\Library\ThunkLib\Ia32\Thunk16.obj
+
+ThunkLib_PORCESSOR_Ia32_CIF=$(ThunkLib_DIR)\ThunkLib\Ia32\ThunkLibIa32.cif
+ThunkLib_PORCESSOR_x64_CIF=$(ThunkLib_DIR)\ThunkLib\x64\ThunkLibx64.cif
+
+$(ThunkLib_LIB) : ThunkLib
+
+ThunkLib : $(BUILD_DIR)\ThunkLib.mak ThunkLibBin
+
+#-!IF "$(PROCESSOR)"=="x64"
+$(BUILD_DIR)\ThunkLib.mak : $(ThunkLib_DIR)\$(@B).cif $(ThunkLib_DIR)\$(@B).mak $(BUILD_RULES) $(ThunkLib_PORCESSOR_Ia32_CIF) $(ThunkLib_PORCESSOR_x64_CIF)
+ $(CIF2MAK) $(ThunkLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(ThunkLib_PORCESSOR_Ia32_CIF) $(ThunkLib_PORCESSOR_x64_CIF)
+#-!ELSE
+#-$(BUILD_DIR)\ThunkLib.mak : $(ThunkLib_DIR)\$(@B).cif $(ThunkLib_DIR)\$(@B).mak $(BUILD_RULES) $(ThunkLib_PORCESSOR_CIF)
+#- $(CIF2MAK) $(ThunkLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(ThunkLib_PORCESSOR_CIF)
+#-!ENDIF
+
+ThunkLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\
+ /f $(BUILD_DIR)\ThunkLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(ThunkLib_LIB)"\
+ "OBJECTS=$(ThunkLib_x64_OBJECTS)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32\
+ /f $(BUILD_DIR)\ThunkLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(ThunkLib_LIB)"\
+ "OBJECTS=$(ThunkLib_IA32_OBJECTS)"
+
diff --git a/ReferenceCode/Haswell/Library/ThunkLib.sdl b/ReferenceCode/Haswell/Library/ThunkLib.sdl
new file mode 100644
index 0000000..e56aae4
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib.sdl
@@ -0,0 +1,26 @@
+TOKEN
+ Name = ThunkLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable ThunkLib support in Project"
+End
+
+TOKEN
+ Name = "ThunkLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\ThunkLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "ThunkLib_DIR"
+End
+
+MODULE
+ Help = "Includes ThunkLib.mak to Project"
+ File = "ThunkLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm
new file mode 100644
index 0000000..af9d34c
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm
@@ -0,0 +1,238 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' 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) 2006 - 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:
+;
+; Thunk.asm
+;
+; Abstract:
+;
+; Real mode thunk
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .model flat,C
+ .const
+
+EXTERNDEF mCode16Size:DWORD
+mCode16Size DD _Code16End - _Code16Addr
+
+ .data
+ ALIGN 10h
+
+NullSegSel DQ 0
+_16CsSegSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9Bh
+ DB 8Fh ; 16-bit segment, 4GB limit
+ DB 0
+;_16DsSegSel LABEL QWORD
+; DW -1
+; DW 0
+; DB 0
+; DB 93h
+; DB 8Fh ; 16-bit segment, 4GB limit
+; DB 0
+_16Gdtr LABEL FWORD
+ DW $ - offset NullSegSel - 1
+ DD offset NullSegSel
+
+ .code
+
+IA32_REGS STRUC 4t
+_EDI DD ?
+_ESI DD ?
+_EBP DD ?
+_ESP DD ?
+_EBX DD ?
+_EDX DD ?
+_ECX DD ?
+_EAX DD ?
+_DS DW ?
+_ES DW ?
+_FS DW ?
+_GS DW ?
+_EFLAGS DD ?
+_EIP DD ?
+_CS DW ?
+_SS DW ?
+IA32_REGS ENDS
+
+_STK16 STRUC 1t
+RetEip DD ?
+RetCs DW ?
+ThunkFlags DW ?
+SavedGdtr FWORD ?
+Resvd1 DW ?
+SavedCr0 DD ?
+SavedCr4 DD ?
+_STK16 ENDS
+
+; IA32_REGISTER_SET *
+; EFIAPI
+; _Thunk16 (
+; IN OUT IA32_REGISTER_SET *RegisterSet,
+; IN UINT32 ThunkFlags,
+; IN UINT32 RealModeCs
+; );
+_Thunk16 PROC USES DS ES FS GS EDI ESI EBP EBX EDX ECX ; 10 dwords will be pushed
+ mov ebp, esp
+ add ebp, 40
+ mov ORG_SS, ss ; preserve SS & ESP
+ mov ORG_ESP, esp
+
+ mov esi, [ebp + 4] ; esi <- RegisterSet
+ movzx edx, (IA32_REGS ptr [esi])._SS ; find 16-bit stack linear address
+ shl edx, 4
+ add edx, (IA32_REGS ptr [esi])._ESP
+ add edx, - sizeof (IA32_REGS) - sizeof (_STK16) ; edx <- 16-bit stack linear address
+
+ mov edi, edx ; [RealMode.IA32_REGS] <- RegisterSet
+ push sizeof (IA32_REGS) / 4
+ pop ecx
+ rep movsd
+ lea eax, @F ; [RealMode._STK16.RetEip] <- ReturnOffset
+ stosd
+ mov eax, cs ; [RealMode._STK16.RetCs] <- ReturnSegment
+ stosw
+ mov eax, [ebp + 8] ; [RealMode._STK16.ThunkFlags] <- ThunkFlags
+ stosw
+ sgdt dword ptr [edi] ; [RealMode._STK16.SavedGdtr] <- GDTR
+ add edi, 8
+ mov eax, cr0 ; [RealMode._STK16.SavedCr0] <- CR0
+ stosd
+ mov esi, eax ; esi <- CR0 to set
+ and esi, 07FFFFFFEh ; clear BIT[24, 0]: PE & PG bits
+ mov eax, cr4 ; [RealMode._STK16.SavedCr4] <- CR4
+ stosd
+
+ push word ptr [ebp + 12] ; [STACK] <- RealModeCs, far jump address for into RealMode
+ pushw 0
+ pushd 8 ; transfer program control to a readable segment that has a limit of 64KB
+ pushd offset @16Bit
+ mov edi, edx ; edi <- 16-bit stack linear address
+
+ sidt fword ptr [ebp + 8] ; save IDTR
+ lgdt _16Gdtr
+ retf
+@16Bit:
+ mov cr0, esi ; disable PE & PG
+; db 066h
+; mov ecx, 0C0000080h
+; rdmsr
+; and ah, NOT 1
+; wrmsr ; clear LME bit
+ mov eax, cr4
+ and al, not 030h ; clear PAE & PSE
+ mov cr4, eax
+ retf
+@@:
+ xor eax, eax
+ mov eax, ss
+ shl eax, 4
+ add eax, esp ; [EAX] <- RegisterSet after x86 call..to return the execution result
+ mov ss, cs:word ptr [ORG_SS] ; restore SS & ESP
+ mov esp, cs:dword ptr [ORG_ESP]
+ lidt fword ptr [ebp + 8] ; restore IDTR
+
+ ret
+
+ORG_SS DW ?
+ORG_ESP DD ?
+
+_Thunk16 ENDP
+
+ ALIGN 10h
+
+; VOID
+; EFIAPI
+; _Code16Addr (
+; VOID
+; );
+_Code16Addr PROC
+_Code16Addr ENDP
+
+; Input: EDI <- 16-bit stack linear address
+RealMode PROC
+ db 066h ; movzx esp, di
+ movzx esp, di
+ db 033h, 0FFh ; xor di, di
+ db 066h ; shr edi, 4
+ shr edi, 4
+ mov ss, di ; mov ss, di
+
+ db 02Eh, 00Fh, 001, 01Eh ; lidt cs:[_16Idtr]
+ dw (_16Idtr - _Code16Addr)
+ db 066h ; popad
+ popa
+ pop ds
+ pop es
+ pop fs
+ pop gs
+ add esp, 4 ; skip EFLAGS
+
+ ; test if EFLAGS with _THUNK_INTERRUPT
+ db 067h, 00F7h, 044h, 024h, 00Eh, 001h, 000h ; test [esp + 0Eh]
+ jz @F
+ db 09Ch ; pushf
+@@:
+ push cs
+ db 068h ; pushw
+ dw (@FarCallRet - _Code16Addr)
+ jz @F
+ db 066h, 067h
+ jmp fword ptr [esp + 6]
+@@:
+ db 066h, 067h
+ jmp fword ptr [esp + 4]
+@FarCallRet:
+ pushf ; pushfd actually
+ push gs
+ push fs
+ push es
+ push ds
+ db 066h ; pushad
+ pusha
+ cli
+
+ db 066h, 067h
+ lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
+ db 066h, 067h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
+ mov cr4, eax
+; db 066h
+; mov ecx, 0C0000080h
+; rdmsr
+; or ah, 1
+; wrmsr ; set LME
+ db 066h, 067h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
+ mov cr0, eax
+ db 066h, 067h
+ jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
+
+RealMode ENDP
+
+_16Idtr FWORD (1 shl 10) - 1
+
+_Code16End:
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif
new file mode 100644
index 0000000..e0204e7
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif
@@ -0,0 +1,9 @@
+<component>
+ name = "ThunkLib Ia32"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\ThunkLib\Ia32"
+ RefName = "ThunkLibIa32"
+[files]
+"x86Thunk.c"
+"Thunk16.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c
new file mode 100644
index 0000000..ec1045f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c
@@ -0,0 +1,245 @@
+/** @file
+ Real Mode Thunk Functions for IA32 and X64
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "ThunkLib.h"
+#define _THUNK_INTERRUPT 0x10000
+#endif
+
+extern const UINTN mCode16Size;
+
+extern
+IA32_REGISTER_SET *
+EFIAPI
+_Thunk16 (
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags,
+ IN UINT32 RealModeCs
+ );
+
+extern
+VOID
+EFIAPI
+_Code16Addr (
+ VOID
+ );
+
+/**
+ Returns the properties of this real mode thunk implementation. Currently
+ there are 2 properties has been defined, the minimum real mode buffer size
+ and the minimum stack size.
+
+ @param[in] MinimumStackSize - The minimum size required for a 16-bit stack.
+
+ @retval The minimum size of the real mode buffer needed by this thunk implementation
+ @retval is returned.
+**/
+UINTN
+EFIAPI
+R8AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize
+ )
+{
+ ///
+ /// This size should be large enough to hold the register set as well as saved
+ /// CPU contexts including GDTR, CR0 and CR4
+ ///
+ if (MinimumStackSize) {
+ *MinimumStackSize = sizeof (IA32_REGISTER_SET) + 0x200;
+ }
+
+ return mCode16Size;
+}
+
+/**
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+ @param[in] ThunkContext - The thunk context whose properties to set.
+ @param[in] RealModeBuffer - The address of the buffer allocated by caller. It should be
+ aligned on a 16-byte boundary.
+ This buffer must be in identity mapped pages.
+ @param[in] BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by R8AsmThunk16GetProperties().
+**/
+THUNK16_CONTEXT *
+EFIAPI
+R8AsmThunk16SetProperties (
+ OUT THUNK16_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+{
+ BufferSize &= ~3;
+
+ ASSERT ((UINTN) RealModeBuffer < 0x100000);
+ ASSERT (((UINTN) RealModeBuffer & 0xf) == 0);
+ ASSERT (BufferSize >= mCode16Size);
+
+ ThunkContext->RealModeBuffer = (UINT32) ((UINTN) RealModeBuffer);
+ ThunkContext->DefaultStack = (UINT32) (ThunkContext->RealModeBuffer + BufferSize);
+ CopyMem (RealModeBuffer, (VOID *) (UINTN) _Code16Addr, mCode16Size);
+ return ThunkContext;
+}
+
+/**
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+ @param[in] ThunkContext - The thunk context to destroy.
+**/
+VOID
+EFIAPI
+R8AsmThunk16Destroy (
+ IN OUT THUNK16_CONTEXT *ThunkContext
+ )
+{
+ ThunkContext->RealModeBuffer = 0;
+}
+
+/**
+ Do the 16-bit thunk code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+static
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+{
+ ASSERT (ThunkContext->RealModeBuffer != 0);
+ ASSERT ((ThunkContext->RealModeBuffer & 0xf) == 0);
+
+ if (!(ThunkFlags & THUNK_USER_STACK)) {
+ RegisterSet->E.ESP = (UINT16) ThunkContext->DefaultStack;
+ RegisterSet->E.SS = (UINT16) ((ThunkContext->DefaultStack >> 4) & 0xf000);
+ }
+
+ ASSERT ((RegisterSet->E.ESP >> 16) == 0);
+
+ CopyMem (
+ RegisterSet,
+ _Thunk16 (RegisterSet,
+ (UINT16) (ThunkFlags >> 16),
+ ThunkContext->RealModeBuffer >> 4),
+ sizeof (IA32_REGISTER_SET)
+ );
+
+ return RegisterSet;
+}
+
+/**
+ Make a far call to 16-bit code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ CS:EIP points to the real mode code being called on input.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16FarCall86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags);
+}
+
+/**
+ Invoke a 16-bit interrupt handler.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16Int86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ RegisterSet->E.Eip = (UINT16) ((UINT32 *) NULL)[IntNumber];
+ RegisterSet->E.CS = (UINT16) (((UINT32 *) NULL)[IntNumber] >> 16);
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags | _THUNK_INTERRUPT);
+}
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf b/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf
new file mode 100644
index 0000000..8f760df
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf
@@ -0,0 +1,67 @@
+## @file
+# @todo ADD DESCRIPTION
+#
+#@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
+#
+
+[defines]
+BASE_NAME = ThunkLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+
+[sources.ia32]
+ Ia32/x86Thunk.c
+ Ia32/Thunk16.asm
+
+[sources.x64]
+ x64/x86Thunk.c
+ x64/Thunk16.asm
+ x64/FxSave.asm
+ x64/FxRestore.asm
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/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
+
+[libraries.common]
+
+[nmake.common]
+ C_FLAGS = $(C_FLAGS)
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm
new file mode 100644
index 0000000..54bab05
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm
@@ -0,0 +1,45 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' 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) 2006 - 2010 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:
+;
+; FxRestore.Asm
+;
+; Abstract:
+;
+; AsmFxRestore function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmFxRestore (
+; IN CONST IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxRestore PROC
+ fxrstor [rcx]
+ ret
+AsmFxRestore ENDP
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm
new file mode 100644
index 0000000..c95ba0b
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm
@@ -0,0 +1,45 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' 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) 2006 - 2010 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:
+;
+; FxSave.Asm
+;
+; Abstract:
+;
+; AsmFxSave function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmFxSave (
+; OUT IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxSave PROC
+ fxsave [rcx]
+ ret
+AsmFxSave ENDP
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm
new file mode 100644
index 0000000..89bb447
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm
@@ -0,0 +1,216 @@
+;/*++
+; This file contains an 'Intel Peripheral Driver' 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) 2006 - 2010 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:
+;
+; Thunk.asm
+;
+; Abstract:
+;
+; Real mode thunk
+;
+;------------------------------------------------------------------------------
+
+EXTERNDEF mCode16Size:QWORD
+
+ .const
+
+mCode16Size DQ _Code16End - _Code16Addr
+
+ .data
+
+NullSegSel DQ 0
+_16CsSegSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9bh
+ DB 8fh ; 16-bit segment
+ DB 0
+
+_16Gdtr LABEL FWORD
+ DW $ - offset NullSegSel - 1
+ DQ offset NullSegSel
+
+ .code
+
+IA32_REGS STRUC 4t
+_EDI DD ?
+_ESI DD ?
+_EBP DD ?
+_ESP DD ?
+_EBX DD ?
+_EDX DD ?
+_ECX DD ?
+_EAX DD ?
+_DS DW ?
+_ES DW ?
+_FS DW ?
+_GS DW ?
+_RFLAGS DQ ?
+_EIP DD ?
+_CS DW ?
+_SS DW ?
+IA32_REGS ENDS
+
+_STK16 STRUC 1t
+RetEip DD ?
+RetCs DW ?
+ThunkFlags DW ?
+SavedGdtr FWORD ?
+Resvd1 DW ?
+SavedCr0 DD ?
+SavedCr4 DD ?
+_STK16 ENDS
+
+_Thunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15
+
+ push fs
+ push gs
+
+ mov r12d, ds
+ mov r13d, es
+ mov r14d, ss
+ mov r15, rsp
+ mov rsi, rcx
+ movzx r10, (IA32_REGS ptr [rsi])._SS
+ xor rdi, rdi
+ mov edi, (IA32_REGS ptr [rsi])._ESP
+ add rdi, - sizeof (IA32_REGS) - sizeof (_STK16)
+ push rdi
+ imul rax, r10, 16
+ add rdi, rax
+ push sizeof (IA32_REGS) / 4
+ pop rcx
+ rep movsd
+ pop rbx ; rbx <- 16-bit stack offset
+ lea eax, @F ; return offset
+ stosd
+ mov eax, cs ; return segment
+ stosw
+ mov eax, edx ; THUNK Flags
+ stosw
+ sgdt fword ptr [rsp + 58h] ; save GDTR
+ mov rax, [rsp + 58h]
+ stosq
+ mov rax, cr0 ; save CR0
+ mov esi, eax ; esi <- CR0 to set
+ stosd
+ mov rax, cr4 ; save CR4
+ stosd
+ sidt fword ptr [rsp + 58h] ; save IDTR
+ and esi, 07ffffffeh ;NOT 080000001h ; clear PE & PG bits
+ mov rdi, r10 ; rdi <- 16-bit stack segment
+
+ shl r8, 16
+ push r8 ; far jmp address
+ lea eax, @16Bit
+ push rax
+ mov word ptr [rsp + 4], 8
+ lgdt _16Gdtr
+ retf
+@16Bit:
+ mov cr0, rsi ; disable PE & PG
+ DB 66h
+ mov ecx, 0c0000080h
+ rdmsr
+ and ah, NOT 1
+ wrmsr ; clear LME bit
+ mov rax, cr4
+ and al, NOT 30h ; clear PAE & PSE
+ mov cr4, rax
+ retf
+@@:
+ xor rax, rax
+ mov eax, ss
+ shl eax, 4
+ add eax, esp ; rax <- address of 16-bit stack
+ mov rsp, r15
+ lidt fword ptr [rsp + 58h] ; restore IDTR
+ mov ds, r12d
+ mov es, r13d
+ mov ss, r14d
+ pop gs
+ pop fs
+ ret
+_Thunk16 ENDP
+
+ ALIGN 10h
+
+_Code16Addr PROC
+_Code16Addr ENDP
+
+RealMode PROC
+ mov ss, edi
+ mov sp, bx ; set up 16-bit stack
+ DB 2eh, 0fh, 1, 1eh
+ DW _16Idtr - _Code16Addr ; lidt _16Idtr
+ DB 66h, 61h ; popad
+ DB 1fh ; pop ds
+ DB 7 ; pop es
+ pop fs
+ pop gs
+
+ add esp, 8 ; skip RFLAGS
+ DB 67h, 0f7h, 44h, 24h, 0eh, 1, 0 ; test [esp + 0eh], 1
+ jz @F
+ pushfq ; pushf, actually
+@@:
+ DB 0eh ; push cs
+ DB 68h ; push /iw
+ DW @FarCallRet - _Code16Addr
+ jz @F
+ DB 66h
+ jmp fword ptr [esp + 6]
+@@:
+ DB 66h
+ jmp fword ptr [esp + 4]
+@FarCallRet:
+ DB 66h
+ push 0 ; push a dword of zero
+ pushf ; pushfd, actually
+ push gs
+ push fs
+ DB 6 ; push es
+ DB 1eh ; push ds
+ DB 66h, 60h ; pushad
+ cli
+
+ DB 66h
+ lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
+ DB 66h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
+ mov cr4, rax
+ DB 66h
+ mov ecx, 0c0000080h
+ rdmsr
+ or ah, 1
+ wrmsr ; set LME
+ DB 66h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
+ mov cr0, rax
+ DB 66h
+ jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
+
+RealMode ENDP
+
+_16Idtr FWORD (1 SHL 10) - 1
+
+_Code16End:
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif b/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif
new file mode 100644
index 0000000..aa6ac0f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "ThunkLib x64"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\ThunkLib\x64"
+ RefName = "ThunkLibx64"
+[files]
+"x86Thunk.c"
+"Thunk16.asm"
+"FxSave.asm"
+"FxRestore.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c b/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c
new file mode 100644
index 0000000..dadb37e
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c
@@ -0,0 +1,272 @@
+/** @file
+ Real Mode Thunk Functions for IA32 and X64
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "ThunkLib.h"
+#define _THUNK_INTERRUPT 0x10000
+#endif
+
+extern const UINTN mCode16Size;
+
+extern
+IA32_REGISTER_SET *
+EFIAPI
+_Thunk16 (
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags,
+ IN UINT32 RealModeCs
+ );
+
+extern
+VOID
+EFIAPI
+_Code16Addr (
+ VOID
+ );
+
+extern
+void
+EFIAPI
+AsmFxRestore (
+ IN CONST IA32_FX_BUFFER *Buffer
+ );
+
+extern
+void
+EFIAPI
+AsmFxSave (
+ OUT IA32_FX_BUFFER *Buffer
+ );
+
+/**
+ Returns the properties of this real mode thunk implementation. Currently
+ there are 2 properties has been defined, the minimum real mode buffer size
+ and the minimum stack size.
+
+ @param[in] MinimumStackSize - The minimum size required for a 16-bit stack.
+
+ @retval The minimum size of the real mode buffer needed by this thunk implementation
+ @retval is returned.
+**/
+UINTN
+EFIAPI
+R8AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize
+ )
+{
+ ///
+ /// This size should be large enough to hold the register set as well as saved
+ /// CPU contexts including GDTR, CR0 and CR4
+ ///
+ if (MinimumStackSize) {
+ *MinimumStackSize = sizeof (IA32_REGISTER_SET) + 0x200;
+ }
+
+ return mCode16Size;
+}
+
+/**
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+ @param[in] ThunkContext - The thunk context whose properties to set.
+ @param[in] RealModeBuffer - The address of the buffer allocated by caller. It should be
+ aligned on a 16-byte boundary.
+ This buffer must be in identity mapped pages.
+ @param[in] BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by R8AsmThunk16GetProperties().
+**/
+THUNK16_CONTEXT *
+EFIAPI
+R8AsmThunk16SetProperties (
+ OUT THUNK16_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+{
+ BufferSize &= ~3;
+
+ ASSERT ((UINTN) RealModeBuffer < 0x100000);
+ ASSERT (((UINTN) RealModeBuffer & 0xf) == 0);
+ ASSERT (BufferSize >= mCode16Size);
+
+ ThunkContext->RealModeBuffer = (UINT32) (UINTN) RealModeBuffer;
+ ThunkContext->DefaultStack = (UINT32) (ThunkContext->RealModeBuffer + BufferSize);
+ CopyMem (RealModeBuffer, (VOID *) (UINTN) _Code16Addr, mCode16Size);
+ return ThunkContext;
+}
+
+/**
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+ @param[in] ThunkContext - The thunk context to destroy.
+**/
+VOID
+EFIAPI
+R8AsmThunk16Destroy (
+ IN OUT THUNK16_CONTEXT *ThunkContext
+ )
+{
+ ThunkContext->RealModeBuffer = 0;
+}
+
+/**
+ Do the 16-bit thunk code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+static
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+{
+ IA32_FX_BUFFER *FpSavedState;
+ UINT8 FpBuffer[sizeof (*FpSavedState) + 0x10];
+
+ ASSERT (ThunkContext->RealModeBuffer != 0);
+ ASSERT ((ThunkContext->RealModeBuffer & 0xf) == 0);
+
+ FpSavedState = (IA32_FX_BUFFER *) (((UINTN) FpBuffer + 0xf) &~0xf);
+
+ if (!(ThunkFlags & THUNK_USER_STACK)) {
+ RegisterSet->E.ESP = (UINT16) ThunkContext->DefaultStack;
+ RegisterSet->E.SS = (UINT16) ((ThunkContext->DefaultStack >> 4) & 0xf000);
+ }
+
+ if (ThunkFlags & THUNK_SAVE_FP_STATE) {
+ AsmFxSave (FpSavedState);
+ }
+
+ ASSERT ((RegisterSet->E.ESP >> 16) == 0);
+
+ CopyMem (
+ RegisterSet,
+ _Thunk16 (RegisterSet,
+ (UINT16) (ThunkFlags >> 16),
+ ThunkContext->RealModeBuffer >> 4),
+ sizeof (*RegisterSet)
+ );
+
+ if (ThunkFlags & THUNK_SAVE_FP_STATE) {
+ AsmFxRestore (FpSavedState);
+ }
+
+ return RegisterSet;
+}
+
+/**
+ Make a far call to 16-bit code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ CS:EIP points to the real mode code being called on input.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16FarCall86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags);
+}
+
+/**
+ Invoke a 16-bit interrupt handler.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16Int86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ RegisterSet->E.Eip = (UINT16) ((UINT32 *) NULL)[IntNumber];
+ RegisterSet->E.CS = (UINT16) (((UINT32 *) NULL)[IntNumber] >> 16);
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags | _THUNK_INTERRUPT);
+}
diff --git a/ReferenceCode/Haswell/Library/TxtLib.cif b/ReferenceCode/Haswell/Library/TxtLib.cif
new file mode 100644
index 0000000..3d672e9
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "TxtLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "TxtLib"
+[files]
+"TxtLib.sdl"
+"TxtLib.mak"
+"TxtLib\TxtLib.inf"
+"TxtLib\Ia32\TxtPeiLib.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/TxtLib.mak b/ReferenceCode/Haswell/Library/TxtLib.mak
new file mode 100644
index 0000000..f933155
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib.mak
@@ -0,0 +1,16 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(TxtLib_LIB) : TxtLib
+
+TxtLib : $(BUILD_DIR)\TxtLib.mak TxtLibBin
+
+$(BUILD_DIR)\TxtLib.mak : $(TxtLib_DIR)\$(@B).cif $(TxtLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(TxtLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+TxtLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\TxtLib.mak all\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ "AFLAGS=$(AFLAGS) $(PROJECT_CPU_INCLUDES)" \
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(TxtLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/TxtLib.sdl b/ReferenceCode/Haswell/Library/TxtLib.sdl
new file mode 100644
index 0000000..028362b
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib.sdl
@@ -0,0 +1,32 @@
+TOKEN
+ Name = TxtLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable TxtLib support in Project"
+End
+
+TOKEN
+ Name = "TxtLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\TxtLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "TxtLib_DIR"
+End
+
+ELINK
+ Name = "/I$(TxtLib_DIR)\TxtLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+MODULE
+ Help = "Includes TxtLib.mak to Project"
+ File = "TxtLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm b/ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm
new file mode 100644
index 0000000..34fcd35
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm
@@ -0,0 +1,99 @@
+;/*++
+; 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) 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.
+;
+;
+; Module Name:
+;
+; TxtPeiLib.asm
+;
+; Abstract:
+;
+; This file contains the code to determine Processor/Chipset TXT capaiblity
+;
+;--*/
+
+ .XLIST
+ include txt.inc
+ .LIST
+
+ .686P
+ .MMX
+ .XMM
+ .MODEL FLAT,C
+ .CODE
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: CheckSmxCapabilities
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Execute GETSEC[CAPABILITIES] to report the SMX capabilities
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+CheckSmxCapabilities PROC PUBLIC USES ebx
+
+ ;
+ ; Check whether SMX is supported
+ ;
+ mov eax, 1
+ cpuid
+ bt ecx, IA32_CPUID_SMX_B
+
+ .IF !CARRY?
+ mov eax, 0
+ jmp @F
+ .ENDIF
+
+ ;
+ ; Save cr4
+ ;
+ mov edx, CR4
+
+ ;
+ ; Enable SMXE
+ ;
+ mov eax, CR4
+ or eax, CR4_SMXE
+ mov CR4, eax
+
+ ;
+ ; Call GETSEC[CAPABILITIES]
+ ;
+ mov eax, CAPABILITIES ; eax = CAPABILITIES
+ mov ebx, 0
+ _GETSEC
+
+ ;
+ ; Restore cr4
+ ;
+ mov CR4, edx
+
+@@:
+ ret
+CheckSmxCapabilities ENDP
+
+END
diff --git a/ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf b/ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf
new file mode 100644
index 0000000..46ae16b
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf
@@ -0,0 +1,60 @@
+## @file
+# Component description file for TXT Lib
+#
+#@copyright
+# Copyright (c) 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 = TxtLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ Ia32/TxtPeiLib.asm
+
+[sources.ia32]
+
+[sources.x64]
+
+[sources.ipf]
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(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
+
+[libraries.common]
+
+[nmake.common]