diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Haswell/Library | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Haswell/Library')
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] |