diff options
Diffstat (limited to 'Core/CPU')
132 files changed, 25486 insertions, 0 deletions
diff --git a/Core/CPU/CPU.h b/Core/CPU/CPU.h new file mode 100644 index 0000000..8795524 --- /dev/null +++ b/Core/CPU/CPU.h @@ -0,0 +1,443 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CPU.h 3 10/17/12 2:20a Davidhsieh $ +// +// $Revision: 3 $ +// +// +// $Date: 10/17/12 2:20a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CPU.h $ +// +// 3 10/17/12 2:20a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Setup items CTDP BIOS, C8, C9 and C10 created +// +// 2 9/26/12 10:53a Davidhsieh +// [TAG] None +// [Description] Add CPU APIC ID data variable for S3 resume +// +// 1 2/07/12 3:58a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// Name: Cpu.h +// +// Description: Common header for the CPU. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef __CPU_H__ +#define __CPU_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include <efi.h> + +#ifdef PEI_COMPILE //In PEI, this must be defined before including this file. +#include <pei.h> +#include <Ppi/Stall.h> +#endif + +#define MP_CPU_APIC_ID_DATA_GUID \ + {0x1456cc6e, 0x22ac, 0x5289, 0x33, 0xba, 0x2e, 0x13, 0xbb, 0xda, 0xba, 0xee} + +// Define the equates here +//CPU APIC includes +#define APIC_ALL_EXCLUDING_SELF (3 << 18) +#define APIC_SIPI (6 << 8) +#define APIC_INIT (5 << 8) +#define APIC_SMI (2 << 8) +#define APIC_DELIVERY_STATUS (1 << 12) +#define APIC_LEVEL_ASSERT (1 << 14) +#define APIC_LEVEL_DEASSERT (0 << 14) +#define APIC_NO_SHORT_HAND (0 << 18) + + +#define MSR_XAPIC_BASE 0x1B +#define XAPIC_BASE_BSP_BIT 8 +#define XAPIC_X2APIC_ENABLE_BIT 10 +#define XAPIC_GLOBAL_ENABLE_BIT 11 + + +#define XAPIC_ENABLE_BIT 8 // SVR SW APIC Enable/Disable Bit +#define APIC_PRESENT_BIT 9 // APIC Present bit in Feature Flags + +#define MASK_ICR_CLEAR 0xFFF33000 // AND mask for ICR reserved bit +#define OR_MASK_INIT_IPI 0x00004500 // OR mask to send INIT IPI +#define OR_MASK_USE_DEST_FIELD 0x00000000 // OR mask to set dest field = "Dest Field" + +//Cstate +#define C1_SUB_STATES_MASK 0x000000f0 +#define C3_SUB_STATES_MASK 0x00000f00 +#define C6_SUB_STATES_MASK 0x0000f000 +#define C7_SUB_STATES_MASK 0x000f0000 +#define C8_SUB_STATES_MASK 0x00f00000 +#define C9_SUB_STATES_MASK 0x0f000000 +#define C10_SUB_STATES_MASK 0xf0000000 + +//----------------------------------------------------------------------------- +// Local APIC Register Equates +//----------------------------------------------------------------------------- +#define LOCAL_APIC_ID 0x20 +#define LOCAL_APIC_VERSION 0x30 +#define LOCAL_APIC_TASK_PRI 0x80 +#define LOCAL_APIC_ARB_PRI 0x90 +#define LOCAL_APIC_PROC_PRI 0xa0 +#define LOCAL_APIC_EOI 0xb0 +#define LOCAL_APIC_LDR 0xd0 +#define LOCAL_APIC_DEST_FORMAT 0xe0 +#define LOCAL_APIC_SVR 0xf0 +#define LOCAL_APIC_ISR0 0x100 +#define LOCAL_APIC_TMR0 0x180 +#define LOCAL_APIC_IRR0 0x200 +#define LOCAL_APIC_ERR_STAT 0x280 +#define LOCAL_APIC_ICR_LO 0x300 +#define LOCAL_APIC_ICR_HI 0x310 +#define LOCAL_APIC_LVT 0x320 +#define LOCAL_APIC_PERF 0x340 +#define LOCAL_APIC_LVT_LINT0 0x350 +#define LOCAL_APIC_LVT_LINT1 0x360 +#define LOCAL_APIC_LVT_ERR 0x370 +#define LOCAL_APIC_ITC 0x380 +#define LOCAL_APIC_TIMER 0x390 +#define LOCAL_APIC_TMR_DIV 0x3e0 + +#define PSD_SW_ALL 0xfc +#define PSD_SW_ANY 0xfd +#define PSD_HW_ALL 0xfe + +#define TSD_HW_ALL 0xfe + +#define MSR_IA32_PLATFORM_ID 0x17 +#define MSR_CHL_CONTROLS 0x2d + #define B_FORWARD_CODE_DISABLE (1<<9) +#define MSR_IA32_CR_PIC_MSG_CONTROL 0x2e +#define MSR_CORE_THREAD_COUNT 0x35 +#define MSR_IA32_FEATURE_CONTROL 0x3a + #define SMRR_LOCK_BIT 0x1 + #define SMRR_ENABLE_BIT 0x3 + #define SMRR_ENABLE_MASK (1<<3) +#define MSR_SMM_SAVE_CONTROL 0x3e +#define MSR_IA32_BIOS_UPDT_TRIG 0x79 +#define MSR_IA32_BIOS_SIGN_ID 0x8b +#define MSR_PMG_CST_CONFIG_CONTROL 0xe2 +#define MSR_PMG_IO_CAPTURE_ADDR 0xe4 +#define MSR_PLATFORM_INFO 0xce + #define TCC_ACTIVE_OFFSET_PROGRAMMABLE_BIT 30 + #define XE_TDP_TDC_PROGRAMMABLE_BIT 29 + #define XE_CORE_RATIO_PROGRAMMABLE_BIT 28 + #define SMM_SAVE_CONTROL_BIT 16 + #define MAX_NON_TURBO_RATIO_OFFSET 8 + #define MAX_NON_TURBO_RATIO_MASK 0xff +#define MSR_FEATURE_CONFIG 0x13c + #define MSR_FEATURE_CONFIG_LOCK 1 +#define MSR_IA32_MCG_CAP 0x179 +#define MSR_IA32_MCG_CTL 0x17b +#define MSR_FLEX_RATIO 0x194 +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_PERF_CTL 0x199 +#define MSR_IA32_CLOCK_MODULATION 0x19a + #define CLK_MOD_ENABLE 0x10 +#define MSR_IA32_MISC_ENABLE 0x1a0 + #define TURBO_DISABLE_MASK ((UINT64)1 << 38) + #define TURBO_MODE_DISABLE_BIT 38 +#define MSR_MISC_FEATURE_CONTROL 0x1a4 + #define DATA_REUSE_OPT 0x40 + #define DCU_IP_PREFETCHER 0x8 + #define DCU_STREAMER_PREFETCHER 0x4 + #define MLC_SPATIAL_PREFETCHER 0x2 + #define MLC_STREAMER_PREFETCHER 0x1 +#define MSR_MISC_PWR_MGMT 0x1aa + #define EIST_HW_COORD_DIS_BIT 0 + #define ENG_PERF_BIAS_EN_BIT 1 + #define LOCK_TM_INT_BIT 22 +#define MSR_TURBO_POWER_CURRENT_LIMIT 0x1ac + #define TDC_LIMIT_OVERRIDE_ENABLE_BIT 31 + #define TDC_LIMIT_MASK 0x7FFF0000 + #define TDC_LIMIT_OFFSET 16 + #define TDP_LIMIT_OVERRIDE_ENABLE_BIT 15 + #define TDP_LIMIT_MASK 0x7FFF + #define TDP_LIMIT_OFFSET 0 +#define MSR_TURBO_RATIO_LIMIT 0x1ad + #define MAX_RATIO_LIMIT_8C_OFFSET 56 + #define MAX_RATIO_LIMIT_7C_OFFSET 48 + #define MAX_RATIO_LIMIT_6C_OFFSET 40 + #define MAX_RATIO_LIMIT_5C_OFFSET 32 + #define MAX_RATIO_LIMIT_4C_OFFSET 24 + #define MAX_RATIO_LIMIT_3C_OFFSET 16 + #define MAX_RATIO_LIMIT_2C_OFFSET 8 + #define MAX_RATIO_LIMIT_1C_OFFSET 0 + #define MAX_RATIO_LIMIT_MASK 0xff +#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0 +#define MSR_FERR_CAPABILITY 0x1f1 +#define MSR_EMRR_PHYSBASE 0x1f4 +#define MSR_EMRR_PHYSMASK 0x1f5 +#define B_EMRR_VALID (1 << 11) +#define MSR_IA32_PLATFORM_DCA_CAP 0x1f8 +#define MSR_IA32_DCA_CAP 0x1f9 +#define MSR_IA32_DCA_0_CAP 0x1fa +#define MSR_POWER_CTL 0x1fc +#define MSR_IA32_MC0_CTL 0x400 +#define MSR_IA32_MC0_STATUS 0x401 + +// Generic MTRR equates +#define MTRR_ATTRIB_WB 6 + +#define MSR_IA32_MTRR_CAP 0xfe + #define SMRR_SUPPORT_BIT 11 + #define SMRR_SUPPORT_MASK (1 << 11) + #define EMRR_SUPPORT_MASK (1 << 12) +#define MTRR_PHYS_BASE_0 0x200 +#define MTRR_PHYS_MASK_0 0x201 +#define MTRR_PHYS_BASE_1 0x202 +#define MTRR_PHYS_MASK_1 0x203 +#define MTRR_PHYS_BASE_2 0x204 +#define MTRR_PHYS_MASK_2 0x205 +#define MTRR_PHYS_BASE_3 0x206 +#define MTRR_PHYS_MASK_3 0x207 +#define MTRR_PHYS_BASE_4 0x208 +#define MTRR_PHYS_MASK_4 0x209 +#define MTRR_PHYS_BASE_5 0x20a +#define MTRR_PHYS_MASK_5 0x20b +#define MTRR_PHYS_BASE_6 0x20c +#define MTRR_PHYS_MASK_6 0x20d +#define MTRR_PHYS_BASE_7 0x20e +#define MTRR_PHYS_MASK_7 0x20f +#define MTRR_FIX_64K_00000 0x250 +#define MTRR_FIX_16K_80000 0x258 +#define MTRR_FIX_16K_A0000 0x259 +#define MTRR_FIX_4K_C0000 0x268 +#define MTRR_FIX_4K_C8000 0x269 +#define MTRR_FIX_4K_D0000 0x26a +#define MTRR_FIX_4K_D8000 0x26b +#define MTRR_FIX_4K_E0000 0x26c +#define MTRR_FIX_4K_E8000 0x26d +#define MTRR_FIX_4K_F0000 0x26e +#define MTRR_FIX_4K_F8000 0x26f +#define MSR_IA32_MC8_CTL2 0x288 +#define MTRR_DEF_TYPE 0x2ff +#define MSR_NO_EVICT_MODE 0x2e0 +#define B_MSR_NO_EVICT_MODE_SETUP 1 +#define B_MSR_NO_EVICT_MODE_RUN 2 +#define MSR_UNCORE_CR_MEMLOCK_COMMANDS 0x2e2 + +#define MSR_PP0_CURRENT_CONFIG 0x601 +#define MSR_PP1_CURRENT_CONFIG 0x602 +#define MSR_PACKAGE_POWER_SKU_LIMIT 0x606 +#define MSR_PKGC3_IRTL 0x60a +#define MSR_PKGC6_IRTL 0x60b +#define MSR_PKGC7_IRTL 0x60c +#define MSR_TURBO_POWER_LIMIT 0x610 + #define POWER_LIMIT_1_MASK 0x7fff + #define POWER_LIMIT_1_TIME_MASK 0xfe0000 + #define POWER_LIMIT_2_MASK (UINT64)0x7fff00000000 +#define MSR_PACKAGE_POWER_SKU 0x614 +#define MSR_PP0_POWER_LIMIT 0x638 +#define MSR_PP1_POWER_LIMIT 0x640 + +#define MSR_EXT_XAPIC_LOGICAL_APIC_ID 0x802 +#define MSR_EXT_XAPIC_VERSION 0x803 +#define MSR_EXT_XAPIC_SVR 0x80f +#define B_MSR_XAPIC_SVR_SOFTWARE_ENABLE (1 << 8) +#define MSR_EXT_XAPIC_ICR 0x830 +#define MSR_EXT_XAPIC_LVT_LINT0 0x835 +#define MSR_EXT_XAPIC_LVT_LINT1 0x836 + +#define GAINESTOWN 0x106a0 +#define WESTMERE 0x206c0 +#define NEHALEM_EX 0x206e0 +#define WESTMERE_EX 0x206f0 +#define SANDY_BRIDGE 0x206a0 +#define JAKETOWN 0x206d0 +#define IVY_BRIDGE 0x306a0 + +#define NUM_OF_FIXED_MTRRS 11 + +VOID LockInc32(UINT32 *); + +typedef struct { + UINT32 SmrrSupport:1; + UINT32 DcaSupport:1; + UINT32 Rsv1:30; + UINT32 Rsv2:32; +} BOARD_ADDITIONAL_FEATURE_FLAGS; + +typedef struct { + UINT32 FeatureEcx; + UINT32 FeatureEdx; + UINT32 ExtFeatureEax; + UINT32 ExtFeatureEbx; + UINT32 ExtFeatureEcx; + UINT32 ExtFeatureEdx; + BOARD_ADDITIONAL_FEATURE_FLAGS Flags; +} BOARD_CPU_FEATURES; + +UINT32 GetMinCpuFeatures( + IN UINT8 NumCpus, + IN VOID *MpData, + IN BOARD_CPU_FEATURES *AllFeatures, + OUT BOARD_CPU_FEATURES *Feature +); + + +#pragma pack (1) +typedef struct { + UINT16 Limit; + UINTN Base; //This shared between 32 bit and 64 bit. +} DESCRIPTOR_TABLE; + +typedef struct _MP_CPU_APICID_DATA { + UINT8 NumberOfCpu; + UINT8 ApicId[32]; +} MP_CPU_APICID_DATA; +#pragma pack() + +#define MP_AP_ONLY 0 +#define MP_BSP_AP 1 + +#define MP_PARALLEL 0 +#define MP_SERIALIZE 1 + +#define MP_FREERUN 0 +#define MP_WAIT 1 +UINT32 StartCpus( +#ifdef PEI_COMPILE + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STALL_PPI *PeiStall, +#endif + IN VOID *ApGlobalData OPTIONAL, + IN BOOLEAN AllCpus, + IN UINT32 ApicId, //If only 1 cpu + IN VOID *Address +); + +VOID StartAllAps( +#ifdef PEI_COMPILE + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STALL_PPI *PeiStall, +#endif + OUT VOID **MpData +); +VOID PrepareApsForNormalExec( +#ifdef PEI_COMPILE + IN EFI_PEI_SERVICES **PeiServices, +#endif + IN VOID *MpData +); +VOID EarlyExecuteFunctionOnRunningCpus( + IN VOID *MpData, + IN VOID (*Function)(UINT32, VOID *Context), //First parameters will always be 0. + IN VOID *Context +); +VOID RestartAp( +#ifdef PEI_COMPILE + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STALL_PPI *PeiStall, +#endif + IN VOID *MpData, + IN UINT32 Cpu +); + +VOID SetHaltFunction( + IN VOID *MpData, + IN VOID *Function +); + +UINT32 GetNumCpus(VOID *MpData); +VOID ExecuteFunctionOnRunningCpus( + IN VOID *MpData, + IN BOOLEAN ExecuteOnBsp, + IN BOOLEAN Serialize, + IN BOOLEAN Block, + IN VOID (*Function)(UINT32 Cpu, VOID *Context), + IN VOID *Context +); +BOOLEAN ExecuteFunctionOnCpu( + IN VOID *MpData, + IN UINT32 Cpu, + IN BOOLEAN Block, + IN VOID (*Function)(UINT32 Cpu, VOID *Context), + IN VOID *Context +); +VOID HaltAllAps( + IN VOID *MpData, + IN BOOLEAN WaitUntilHalted +); +VOID HaltCpu( + IN VOID *MpData, + IN UINT32 Cpu, + IN BOOLEAN WaitUntilHalted +); +BOOLEAN IsCpuHalted( + IN VOID *MpData, + IN UINT32 Cpu +); + +BOOLEAN IsCpuIdle( + IN VOID *MpData, + IN UINT32 Cpu +); + +BOOLEAN AreCpusIdle( + IN VOID *MpData +); + +UINT32 WhoIsBsp(VOID *MpData); + +UINT32 GetCpuBist(IN VOID *MpData, IN UINT32 Cpu); +UINT32 GetCpuNumByApicId(VOID *MpData, UINT32 ApicId); + +VOID SwitchBsp( +#ifdef PEI_COMPILE + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STALL_PPI *PeiStall, +#endif + IN VOID *MpData, + IN UINT32 NewBsp +); + +VOID ProgramLocalApic(IN UINT32 Cpu, IN VOID *Context); + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/CPUCore.cif b/Core/CPU/CPUCore.cif new file mode 100644 index 0000000..6e1b63d --- /dev/null +++ b/Core/CPU/CPUCore.cif @@ -0,0 +1,30 @@ +<component> + name = "CPU Core" + category = ModulePart + LocalRoot = "Core\CPU" + RefName = "CPU Core" +[files] +"CPU.h" +"CpuCspLib.c" +"CPUCspLib.h" +"CpuDxe.c" +"CpuDxe.dxs" +"CpuDxe.h" +"CpuPei.c" +"CpuPei.dxs" +"CpuPei.h" +"CpuPeiFuncs.c" +"CpuDxeFuncs.c" +"CpuPeiBeforeMem.c" +"CpuSmbios.c" +"MBIOSMAC.MAC" +"ResetVector.asm" +"Startup32.asm" +[parts] +"CPU Hobs" +"CpuPPIs" +"CpuProtocols" +"MicrocodeUpdate" +"CpuTools" +"MiscX64Lib" +<endComponent> diff --git a/Core/CPU/CPUCspLib.h b/Core/CPU/CPUCspLib.h new file mode 100644 index 0000000..94f282a --- /dev/null +++ b/Core/CPU/CPUCspLib.h @@ -0,0 +1,333 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CPUCspLib.h 5 2/07/13 3:57a Hsingyingchung $ +// +// $Revision: 5 $ +// +// $Date: 2/07/13 3:57a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CPUCspLib.h $ +// +// 5 2/07/13 3:57a Hsingyingchung +// [TAG] EIP112631 +// [Category] Improvement +// +// 4 12/20/12 10:27a Hsingyingchung +// [TAG] EIP108128 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] "Max non-turbo ratio" can't show in BIOS setup when first +// boot after flashing BIOS +// [RootCause] Doesn't initialize max non-turbo ratio value when first +// boot after flashing BIOS. +// [Solution] Add initialize code for max non-turbo ratio. +// +// 3 11/23/12 2:08a Hsingyingchung +// [TAG] EIP99095 +// [Category] Improvement +// [Description] Update by XTU 4.X +// +// 2 5/17/12 9:40p Davidhsieh +// +// 1 2/07/12 3:58a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// Name: CpuCspLib.h +// +// Description: Header file for Cpu Csp Lib. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef __CPULIB_H__ +#define __CPULIB_H__ + +#include <efi.h> +#include <pei.h> +#include "amihobs.h" +#include "smm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT32 Bist; +} AMI_STATUS_CODE_CPU_BIST_DATA; + +#pragma pack(push, 1) + +typedef struct { + UINT32 HeaderVersion; + UINT32 UpdateRevision; + UINT32 Date; + UINT32 CpuSignature; + UINT32 Checksum; + UINT32 LoaderRevison; + UINT32 Flags:8; + UINT32 RV3:24; + UINT32 DataSize; + UINT32 TotalSize; + UINT32 RV4[3]; +} MICROCODE_HEADER; + +typedef struct { + UINT32 CpuSignature; + UINT32 Flags; + UINT32 Checksum; +} PROC_SIG; + +typedef struct { + UINT32 Count; + UINT32 Checksum; + UINT8 Rsv[12]; + PROC_SIG ProcSig[1]; +} MICROCODE_EXT_PROC_SIG_TABLE; + +#pragma pack(pop) + +// {CD541D77-6699-4b36-A31E-1AA4C5D5B946} +#define AMI_STATUS_CODE_CPU_BIST_DATA_GUID \ + {0xcd541d77, 0x6699, 0x4b36, 0xa3, 0x1e, 0x1a, 0xa4, 0xc5, 0xd5, 0xb9, 0x46} + +UINT64 ReadMsr (UINT32 Msr); +VOID WriteMsr(UINT32 Msr, UINT64 Value); +VOID ReadWriteMsr(UINT32 Msr, UINT64 Value, UINT64 Mask); +VOID CPULib_CpuID(UINT32 CpuIDIndex, UINT32 * RegEAX, UINT32 * RegEBX, + UINT32 * RegECX, UINT32 * RegEDX); +UINT32 GetCpuSignature(); +UINT32 GetCpuFamily(UINT32 CpuSignature); +UINT32 GetCpuModel(UINT32 CpuSignature); +UINT32 GetCpuPlatformId(); +UINT32 GetSmrrBaseMsr(); +UINT8 NumSupportedThreadsPerCore(); +UINT8 NumSupportedCpuCores(); +UINT8 NumCpuCores(); +UINT8 NumLogicalCpus(); +BOOLEAN IsHtEnabled(); +BOOLEAN IsHt0(); +BOOLEAN IsCore0(); +BOOLEAN isXDSupported(CPU_FEATURES *Features); +BOOLEAN isTurboModeSupported(); +BOOLEAN isFullUnlockCpuSuuported(); +BOOLEAN isXETdcTdpLimitSupported(); +BOOLEAN isXECoreRatioLimitSupported(); +BOOLEAN isLimitCpuidSupported(); +BOOLEAN IsMachineCheckSupported(CPU_FEATURES *Features); +BOOLEAN IsEnergyPerfBiasSupported(); +BOOLEAN IsCxInterruptFilteringSupported(); +BOOLEAN IsVmxSupported(CPU_FEATURES *Features); +BOOLEAN IsSmxSupported(CPU_FEATURES *Features); +BOOLEAN IsSmrrSupported(CPU_FEATURES *Features); +BOOLEAN IsX64Supported(CPU_FEATURES *Features); + +BOOLEAN CPULib_IsVmxEnabled(); +BOOLEAN CPULib_IsSmxEnabled(); +BOOLEAN CPULib_IsSmrrEnabled(); +BOOLEAN CPULib_IsLocalX2ApicEnabled(); +BOOLEAN CPULib_IsFeatureControlLocked(); +UINT32 NumberOfCpuSocketsPopulated(); +VOID DisableCacheInCR0(); +VOID EnableCacheInCR0(); +VOID CPULib_DisableInterrupt(); +VOID CPULib_EnableInterrupt(); +BOOLEAN CPULib_GetInterruptState(); +VOID* CPULIB_GetPageTable(); +VOID CPULib_Pause(); +UINT16 GetCsSegment(); +UINT64 ReadRtdsc(); +VOID WaitForever(); +VOID HltCpu(); +VOID WaitForSemaphore(volatile VOID*); +VOID WaitUntilZero8(volatile VOID*); +VOID WaitUntilZero32(volatile VOID*); +UINT16 GetCsSegment(); +UINT32 CPULIB_GetCstateLatency(IN UINT8 Cstate); +UINT32 CPULIB_GetCstatePower(IN UINT8 Cstate); +VOID* CPULib_FindMicrocode(); +UINT32 CPULib_GetMicrocodeVer(); +VOID ClearDirectionFlag(); + +UINT32 SmmGetBaseSaveBufferSize(); +VOID SmmSetupDefaultHandler(IN VOID *SmmBaseSaveBuffer, IN SMM_HOB *SmmHob); +VOID SmmRemoveDefaultHandler(IN VOID *SmmBaseSaveBuffer); +VOID SmmBaseChangeOnCpu(VOID *SmmBase); + +VOID CPU_GetSaveState ( + UINT8 *SmmBase, + EFI_SMI_CPU_SAVE_STATE *SstSaveState); + +VOID CPU_RestoreSaveState( + UINT8 *SmmBase, + EFI_SMI_CPU_SAVE_STATE *SstSaveState); + +VOID CPU_SmmMemoryInit(IN SMM_HOB *SmmHob); + +typedef struct { + UINT8 ClkModEn; //> 0 if Clk Mod En. +} CPU_LIB_SMM_SAVE_RESTORE_DATA; + +VOID CpuLib_SmmSaveCpuState(IN OUT CPU_LIB_SMM_SAVE_RESTORE_DATA*); +VOID CpuLib_SmmRestoreCpuState(IN CPU_LIB_SMM_SAVE_RESTORE_DATA*); + +BOOLEAN IsSwSmiTrigger(UINT8 *SmmBase, UINT16 SwSmiPort); + +EFI_STATUS CPULib_SmmReadSaveState( + UINT8 *SmmBase, + UINT8 *SstSaveState, + BOOLEAN UseSstSaveState, + IN UINT8 Width, + IN UINT32 Register, + OUT VOID *Buffer +); +EFI_STATUS CpuLib_SmmReadSaveStateFxSave( + IN UINT8 *FxSave, + IN UINT8 Width, + IN UINT32 Register, + OUT VOID *Buffer +); +EFI_STATUS CPULib_SmmWriteSaveState( + UINT8 *SmmBase, + UINT8 *SstSaveState, + BOOLEAN UseSstSaveState, + IN UINT8 Width, + IN UINT32 Register, + OUT CONST VOID *Buffer +); +EFI_STATUS CpuLib_SmmWriteSaveStateFxSave( + IN UINT8 *FxSave, + IN UINT8 Width, + IN UINT32 Register, + OUT VOID *Buffer +); + +EFI_STATUS CPUProgramPAMRegisters( + EFI_BOOT_SERVICES *gBS, EFI_RUNTIME_SERVICES *gRS, + UINT32 StartAddress, UINT32 Length, UINT8 Setting, UINT32 *Granularity +); + +VOID EnableMachineCheck(); + +VOID CPULib_LockByteInc(UINT8* ptr); +VOID CPULib_LockByteDec(UINT8* ptr); +VOID CPULib_LoadGdt(VOID *ptr); +VOID CPULib_SaveGdt(VOID *ptr); +VOID CPULib_LoadIdt(VOID *ptr); +VOID CPULib_SaveIdt(VOID *ptr); + +UINT32 MemRead32(UINT32 *Address); +VOID MemReadWrite32(UINT32 *Address, UINT32 Value, UINT32 Mask); + +UINT8 IsPowerCycle(); +BOOLEAN isBCLKRatioSuuported(); +EFI_STATUS GetOcCapability(IN UINT8 DomainID, OUT UINT64 *MsrBuf); +EFI_STATUS GetSVIDConfig(OUT UINT64 *MsrBuf); +EFI_STATUS GetVoltFreq(IN UINT8 DomainID, OUT UINT64 *MsrBuf); +EFI_STATUS GetFIVRConfig(OUT UINT64 *MsrBuf); + + +#ifdef PERF_TUNE_SUPPORT +#if PERF_TUNE_SUPPORT == 1 + +#define AMI_OVERCLOCK_CONFIG_HOB_GUID \ + {0x27a29ef7, 0x90e7, 0x4592, 0x99, 0xbe, 0xa3, 0xae, 0x97, 0xca, 0xdb, 0x2a} + +#define AMI_INTERNAL_CPU_RATIO_LIMIT \ + {0xdf2982fa, 0xaa6c, 0x4b8d, 0x8a, 0x82, 0x85, 0xf8, 0x1e, 0xe8, 0x72, 0x19} + +#pragma pack(1) +//Domain ID define +#define DOMAIN_MAX_NUM 6 +#define IA 0 +#define GT 1 +#define RING 2 +#define SA 3 +#define IOD 4 +#define IOA 5 + +typedef struct { + UINT8 MaxOcRatioLimit; + BOOLEAN RatioOcSupported; + BOOLEAN VoltageOverridesSupported; + BOOLEAN VoltageOffsetSupported; +} OC_CAP_ITEM; //overclocking capability + +typedef struct { + UINT8 MaxOcRatio; + BOOLEAN VoltageTargetMode; // 0: Adaptive, 1: Override + UINT16 VoltageTarget; + INT16 VoltageOffset; +} VOLT_FREQ_DEF_ITEM; + +typedef struct { + OC_CAP_ITEM OCCap[DOMAIN_MAX_NUM]; + VOLT_FREQ_DEF_ITEM VFDef[DOMAIN_MAX_NUM]; + BOOLEAN SvidDisable; // 0: Disable, 1: Enable + UINT16 SvidVoltageOverride; // External VR voltage override + BOOLEAN FivrFaultsDisable; // 0: Disable, 1: Enable + BOOLEAN FivrEfficiencyDisable; // 0: Disable, 1: Enable + BOOLEAN OcSupport; + UINT8 IsPowerCycle; // 0: Not power cycle, 1: power cycle + UINT8 IsCpuRunDefault; // 0: Not run default, 1: Cpu Change, 2:Watch Dog timeout +} OVERCLOCKING_CONFIG_DATA; + +typedef struct _OVERCLOCKING_CONFIG_HOB { + EFI_HOB_GUID_TYPE EfiHobGuidType; + OVERCLOCKING_CONFIG_DATA OverclockData; +} OVERCLOCKING_CONFIG_HOB; + +typedef struct { + UINT8 MaxNonTurboRatio; +} CPU_RATIO_LIMIT_DATA; + +typedef struct _CPU_RATIO_LIMIT_HOB { + EFI_HOB_GUID_TYPE EfiHobGuidType; + CPU_RATIO_LIMIT_DATA CpuRatioLimitData; + BOOLEAN IsChangeCpu; +} CPU_RATIO_LIMIT_HOB; + +#pragma pack() + +#endif //end of #if PERF_TUNE_SUPPORT == 1 +#endif //end of #ifdef PERF_TUNE_SUPPORT == 1 + +#ifdef __cplusplus +} +#endif +#endif + + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-20113, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + diff --git a/Core/CPU/CpuCspLib.c b/Core/CPU/CpuCspLib.c new file mode 100644 index 0000000..549d979 --- /dev/null +++ b/Core/CPU/CpuCspLib.c @@ -0,0 +1,2461 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuCspLib.c 6 5/22/15 6:07a Crystallee $ +// +// $Revision: 6 $ +// +// $Date: 5/22/15 6:07a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuCspLib.c $ +// +// 6 5/22/15 6:07a Crystallee +// [TAG] EIP219394 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Static code analysis issues found in Aptio4 Intel Haswell +// module +// [RootCause] Didn't update register content. +// [Solution] Update register content. +// +// 5 8/14/13 4:55a Davidhsieh +// [TAG] EIP131295 +// [Category] Improvement +// [Description] Add token to force turbo mode is not supported for i3 +// Cpu +// +// 4 2/07/13 3:56a Hsingyingchung +// [TAG] EIP112631 +// [Category] Improvement +// [Description] add IsPowerCycle function. +// +// 3 11/23/12 2:08a Hsingyingchung +// [TAG] EIP99095 +// [Category] Improvement +// [Description] Update by XTU 4.X +// +// 2 8/21/12 11:28p Davidhsieh +// [TAG] None +// [Category] Bug Fix +// [Severity] Important +// [Symptom] EFI_SMM_CPU_PROTOCOL-> ReadSaveState can't get CR4 value +// [RootCause] The index for CR4 is incorrect. +// +// [Solution] Correct the index value +// +// 1 2/07/12 3:58a Davidhsieh +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuCspLib.c +// +// Description: +// Contains the CPU library related functions. These functions can be linked +// with various components in the project. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <efi.h> +#include <token.h> +#include <AmiDxeLib.h> +#include <smm.h> +#include <Pcie.h> + +#include "Cpu.h" +#include "CpuCspLib.h" +#include "AmiCspLibInc.h" + +#ifndef FV_MICROCODE_BASE +#define FV_MICROCODE_BASE FV_MAIN_BASE +#endif + +#define MAX_NR_BUS ((PCIEX_LENGTH/0x100000)-1) + +static EFI_GUID gMicrocodeFfsGuid = + {0x17088572, 0x377F, 0x44ef, 0x8F, 0x4E, 0xB0, 0x9F, 0xFF, 0x46, 0xA0, 0x70}; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsPowerCycle +// +// Description: If Power Cycle is or not. +// +// Input: +// NULL +// +// Output: +// UINT8 , 0 - Not Power Cycle +// 1 - Power Cycle +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 IsPowerCycle(){ + // + // This is the sample code for Sharkbay with Lynx Point(ver0.7.0 spec.) + // Please program properly for your platform + // + UINT16 Buff16; + Buff16 = READ_PCI16_SB(0xA2); + + if (((Buff16 & BIT5) != 0) /*&& ((Buff16 & BIT7) != 0)*/) + { + return 0; + } else { + return 1; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PchPmTimerStall +// +// Description: Delay N*Usec +// +// Input: UINTN Usec +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID PchPmTimerStall (IN UINTN Usec) +{ + UINTN Counter = Usec * 3; + UINTN i; + UINT32 Data32; + UINT32 PrevData; + + PrevData = IoRead32(PM_BASE_ADDRESS + 8); + for (i=0; i < Counter; ) { + Data32 = IoRead32(PM_BASE_ADDRESS + 8); + if (Data32 < PrevData) { // Reset if there is a overlap + PrevData=Data32; + continue; + } + i += (Data32 - PrevData); + PrevData=Data32; + } + + return; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PollMailboxReady +// +// Description: Return OC Mailbox is ready or busy. +// +// Input: UINT64 *MsrBuf +// +// Output: UINT8 (1: busy, 0: ready) +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 PollMailboxReady() +{ + UINT64 MsrData; + UINT32 WaitTime = 1000; + + do{ + MsrData = ReadMsr(0x150); //Overclock Mailbox: 0x150 + if(!(Shr64(MsrData,63) & 0x1)) break; + //gStallPpi->Stall(gPeiServices, gStallPpi, 1000); //delay 1ms + PchPmTimerStall(1000); //delay 1ms + WaitTime--; + }while((Shr64(MsrData,63) & 0x1) && WaitTime>0); //check run/busy bit, 1 is busy + + if((Shr64(MsrData,63) & 1) && WaitTime == 0) + return 1; //busy + else + return 0; //ready +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ReadMSR150 +// +// Description: Return Msr0x150 data +// +// Input: UINT64 *MsrBuf +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ReadMSR150(OUT UINT64 *MsrBuf) +{ + UINT64 MsrData; + UINT64 MsrDataVerify; + + MsrData = ReadMsr(0x150); + + //gStallPpi->Stall(gPeiServices, gStallPpi, 10000); //wait 10ms + PchPmTimerStall(10000); //delay 1ms + + MsrDataVerify = ReadMsr(0x150); + + if((UINT32)MsrData != (UINT32)MsrDataVerify) return EFI_DEVICE_ERROR; + + *MsrBuf = MsrData; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetOcCapability +// +// Description: Get the overclocking capabilities for a given CPU Domain +// by reading/writing MSR 0x150 +// +// Input: UINT8 DomainID (0:IA, 1:GT, 2:Ring, 3:SA, 4:IOD, 5:IOA) +// UINT64 *MsrBuf +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetOcCapability(IN UINT8 DomainID, OUT UINT64 *MsrBuf) +{ + UINT64 MsrData; + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + MsrData = 0; + MsrData |= Shl64(DomainID,40); //Param1 + MsrData |= Shl64(0x01,32); //Command, Overclocking Capability + MsrData |= Shl64(0x01,63); //run/busy bit + + WriteMsr(0x150,MsrData); //Overclock Mailbox: 0x150 + + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + if(ReadMSR150(&MsrData)) return EFI_DEVICE_ERROR; + + *MsrBuf = MsrData; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetSVIDConfig +// +// Description: Get the SVID Configuration information +// by reading/writing MSR 0x150 +// +// Input: UINT64 *MsrBuf +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetSVIDConfig(OUT UINT64 *MsrBuf) +{ + UINT64 MsrData; + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + MsrData = 0; + MsrData |= Shl64(0,40); //Param1, 0 = IVR input + MsrData |= Shl64(0x12,32); //Command, Read SVID Config + MsrData |= Shl64(0x01,63); //run/busy bit + + WriteMsr(0x150,MsrData); //Overclock Mailbox: 0x150 + + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + if(ReadMSR150(&MsrData)) return EFI_DEVICE_ERROR; + + *MsrBuf = MsrData; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetVoltFreq +// +// Description: Gets the Voltage and Frequency information for a given CPU domain +// by reading/writing MSR 0x150 +// +// Input: UINT8 DomainID (0:IA, 1:GT, 2:Ring) +// UINT64 *MsrBuf +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetVoltFreq(IN UINT8 DomainID, OUT UINT64 *MsrBuf) +{ + UINT64 MsrData; + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + MsrData = 0; + MsrData |= Shl64(DomainID,40); //Param1, 0 = IVR input + MsrData |= Shl64(0x10,32); //Command, Read Voltage/Frequency + MsrData |= Shl64(0x01,63); //run/busy bit + + WriteMsr(0x150,MsrData); //Overclock Mailbox: 0x150 + + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + if(ReadMSR150(&MsrData)) return EFI_DEVICE_ERROR; + + *MsrBuf = MsrData; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetFIVRConfig +// +// Description: Get the FIVR Configuration information +// by reading/writing MSR 0x150 +// +// Input: UINT64 *MsrBuf +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetFIVRConfig(OUT UINT64 *MsrBuf) +{ + UINT64 MsrData; + + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + MsrData = 0; + MsrData |= Shl64(0x0,40); //Param1 + MsrData |= Shl64(0x14,32); //Command, Read Misc Global Config + MsrData |= Shl64(0x01,63); //run/busy bit + + WriteMsr(0x150,MsrData); //Overclock Mailbox: 0x150 + + if(PollMailboxReady()) return EFI_DEVICE_ERROR; + + if(ReadMSR150(&MsrData)) return EFI_DEVICE_ERROR; + + *MsrBuf = MsrData; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isBCLKRatioSuuported +// +// Description: Determine if CPU supports BCLK coarse ratio support. +// +// Input: None +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN isBCLKRatioSuuported() +{ + UINT32 PciAddress; + +// PciAddress = (0x1) << 31 | ((0x0) << 16) | ((0x0) << 11) | ((0x0) << 8) | 0xE4; + PciAddress = (0x1) << 31 | 0xE4; + IoWrite32(0x0cf8,PciAddress); + if ( IoRead32(0x0cfc) & BIT18 ){ + return FALSE; + } + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetCpuSignature +// +// Description: Get the cpu signature. +// +// Input: VOID +// +// Output: Cpu Signature +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 GetCpuSignature() +{ + UINT32 CpuSignature, CpuIdEBX, CpuIdECX, CpuIdEDX; + CPULib_CpuID(1, &CpuSignature, &CpuIdEBX, &CpuIdECX, &CpuIdEDX); + return CpuSignature; +} + +typedef struct { + UINT32 Stepping:4; + UINT32 Model:4; + UINT32 Family:4; + UINT32 Type:2; + UINT32 RV:2; + UINT32 ExtModel:4; + UINT32 ExtFamily:8; +} CPU_SIGNATURE; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetCpuFamily +// +// Description: Get the cpu family from signature. +// +// Input: UINT32 CpuSignature +// +// Output: UINT32 - Cpu Family +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 GetCpuFamily(UINT32 CpuSignature) +{ + CPU_SIGNATURE *Signature = (CPU_SIGNATURE*)&CpuSignature; + return Signature->ExtFamily + Signature->Family; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetCpuModel +// +// Description: Get the cpu model from signature. +// +// Input: UINT32 CpuSignature +// +// Output: UINT32 - Cpu Model +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 GetCpuModel(UINT32 CpuSignature) +{ + CPU_SIGNATURE *Signature = (CPU_SIGNATURE*)&CpuSignature; + return (Signature->ExtModel << 4) + Signature->Model; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetCpuPlatformId +// +// Description: Get the cpu platform Id. +// +// Input: VOID +// +// Output: Cpu Platform Id +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 GetCpuPlatformId(VOID) +{ + return (UINT32)Shr64(ReadMsr(0x17), 50) & 7; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetSmrrBaseMsr +// +// Description: Return the Smrr Base Msr +// +// Input: VOID +// +// Output: SMRR Base +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 GetSmrrBaseMsr() +{ + return 0x1f2; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ReadWriteMsr +// +// Description: This function writes the CPU MSR with the value provided. +// +// Input: +// Msr 32bit MSR index +// Value 64bit OR Value +// Mask 64Bit AND Mask Value +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ReadWriteMsr(UINT32 Msr, UINT64 Value, UINT64 Mask) +{ + UINT64 OrigData = ReadMsr(Msr); + UINT64 WriteData = (OrigData & Mask) | Value; + WriteMsr(Msr, WriteData); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NumSupportedThreadsPerCore +// +// Description: Get number of supported threads per core. +// +// Input: VOID +// +// Output: UINT8 Number of Threads per core. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 NumSupportedThreadsPerCore() +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + + RegEcx = 0; + CPULib_CpuID(0xb, &RegEax, &RegEbx, &RegEcx, &RegEdx); + return (UINT8)RegEbx; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NumSupportedCpuCores +// +// Description: Get number of supported Cpu Cores per package. +// +// Input: VOID +// +// Output: UINT8 Number of supported Cpu Cores per package. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 NumSupportedCpuCores() +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT8 TotLogicalCpus; + UINT8 LogicalCpusPerCore; + + RegEcx = 1; + CPULib_CpuID(0xb, &RegEax, &RegEbx, &RegEcx, &RegEdx); + TotLogicalCpus = (UINT8)RegEbx; + + RegEcx = 0; + CPULib_CpuID(0xb, &RegEax, &RegEbx, &RegEcx, &RegEdx); + LogicalCpusPerCore = (UINT8)RegEbx; + + return TotLogicalCpus / LogicalCpusPerCore; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NumLogicalCpus +// +// Description: Get number of logical CPUs. +// +// Input: VOID +// +// Output: UINT8 Number of logical CPUs. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 NumLogicalCpus() +{ + UINT64 MsrData = ReadMsr(MSR_CORE_THREAD_COUNT); + return (UINT8)MsrData; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsHtEnabled +// +// Description: Determine if CPU is HT. +// +// Input: VOID +// +// Output: True if HT CPU. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN IsHtEnabled() +{ + UINT8 NumLogCPUs, NumCpuCores; + UINT64 MsrData = ReadMsr(MSR_CORE_THREAD_COUNT); + UINT32 CpuSignature = GetCpuSignature() & 0xfffffff0; + + NumCpuCores = (UINT8)((UINT32)MsrData >> 16); + + // Westmere work around + if (CpuSignature == WESTMERE) NumCpuCores &= 0xf; + + NumLogCPUs = (UINT8)MsrData; + + if ((NumLogCPUs / NumCpuCores) <= 1) return FALSE; + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NumCpuCores +// +// Description: Returns number of CPU Cores +// +// Input: VOID +// +// Output: Number of CPU Cores. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 NumCpuCores() +{ + UINT32 CpuSignature = GetCpuSignature() & 0xfffffff0; + UINT64 MsrData = ReadMsr(MSR_CORE_THREAD_COUNT); + UINT8 NumCpuCores = (UINT8)((UINT32)MsrData >> 16); + + // Westmere work around + if (CpuSignature == WESTMERE) NumCpuCores &= 0xf; + + return NumCpuCores; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsHt0 +// +// Description: Determine if CPU thread is logical CPU 0 executing. +// +// Input: VOID +// +// Output: True if logical CPU 0. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsHt0() +{ + UINT32 ApicMask; + UINT32 ApicId; + UINT8 ThreadsPerCore = NumSupportedThreadsPerCore(); + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + + if (ThreadsPerCore < 2) return TRUE; //Check if Ht Capable. + ApicMask = ThreadsPerCore - 1; + + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + ApicId = RegEbx >> 24; + + //Use APIC ID to determine if logical CPU. + if ((ApicId & ApicMask) == 0) return TRUE; //All logical CPU0 will have bit 0 clear. + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsCore0 +// +// Description: Determine if CPU thread is CPU Core 0 executing. +// +// Input: VOID +// +// Output: True if logical CPU 0. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsCore0() +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT8 MaxThreadsPackage; + UINT32 ApicMask; + UINT32 ApicId; + + ApicMask = ~(NumSupportedThreadsPerCore() - 1); + + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + + MaxThreadsPackage = (UINT8)(RegEbx >> 16); + + ApicMask &= MaxThreadsPackage - 1; + ApicId = RegEbx >> 24; + + //Use APIC ID to determine if logical CPU. + if ((ApicId & ApicMask) == 0) return TRUE; + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsX64Supported +// +// Description: Determine if CPU supports X64. +// +// Input: CPU_FEATURES *Features +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsX64Supported(CPU_FEATURES *Features) +{ + return ((Features->ExtFeatureEdx) >> 29) & 1; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isXDSupported +// +// Description: Determine if CPU supports Execute Disable. +// +// Input: CPU_FEATURES *Features +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN isXDSupported(CPU_FEATURES *Features) +{ + return !!(Features->ExtFeatureEdx & (1 << 20)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isTurboModeSupported +// +// Description: Determine if CPU supports Turbo mode. +// +// Input: None +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN isTurboModeSupported() +{ + BOOLEAN ret; + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + + UINT64 MsrData = ReadMsr(MSR_IA32_MISC_ENABLE); + +#if defined(I3_CPU_NON_TURBO) && (I3_CPU_NON_TURBO == 1) +{ + CHAR8 BrandStrBuff[49]; + CHAR8 *BrandString = BrandStrBuff; + + CPULib_CpuID(0x80000002, &RegEax, &RegEbx, &RegEcx, &RegEdx); + *(UINT32*)BrandString = RegEax; BrandString +=4; + *(UINT32*)BrandString = RegEbx; BrandString +=4; + *(UINT32*)BrandString = RegEcx; BrandString +=4; + *(UINT32*)BrandString = RegEdx; BrandString +=4; + + + CPULib_CpuID(0x80000003, &RegEax, &RegEbx, &RegEcx, &RegEdx); + *(UINT32*)BrandString = RegEax; BrandString +=4; + *(UINT32*)BrandString = RegEbx; BrandString +=4; + *(UINT32*)BrandString = RegEcx; BrandString +=4; + *(UINT32*)BrandString = RegEdx; BrandString +=4; + + CPULib_CpuID(0x80000004, &RegEax, &RegEbx, &RegEcx, &RegEdx); + *(UINT32*)BrandString = RegEax; BrandString +=4; + *(UINT32*)BrandString = RegEbx; BrandString +=4; + *(UINT32*)BrandString = RegEcx; BrandString +=4; + *(UINT32*)BrandString = RegEdx; BrandString +=4; + *BrandString = '\0'; + + BrandString = BrandStrBuff; + + while(*BrandString) { + if (MemCmp(BrandString, "i3", 2) == 0) return FALSE; + ++BrandString; + } +} +#endif + CPULib_CpuID(6, &RegEax, &RegEbx, &RegEcx, &RegEdx); + ret = ((RegEax >> 1) & 1) | (UINT32) (Shr64(MsrData,TURBO_MODE_DISABLE_BIT) & 1); + return ret; + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isFullUnlockCpuSuuported +// +// Description: Determine if CPU supports Full unlock. +// +// Input: None +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN isFullUnlockCpuSuuported() +{ + UINT64 MsrData = ReadMsr(MSR_FLEX_RATIO); + + if((UINT32)(Shr64(MsrData, 17)) == 0x7) return TRUE; + return FALSE; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isXETdcTdpLimitSupported +// +// Description: Determine if CPU supports Programmable TDC/TDP Limit for the Turbo mode. +// +// Input: None +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN isXETdcTdpLimitSupported() +{ + + BOOLEAN ret; + UINT64 MsrData = ReadMsr(MSR_PLATFORM_INFO); + ret = (UINT32) (MsrData & (1 << XE_TDP_TDC_PROGRAMMABLE_BIT)) ? 1:0; + return ret; + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isXECoreRatioLimitSupported +// +// Description: Determine if CPU supports Programmable Core Ratio Limit for the Turbo mode. +// +// Input: None +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + + BOOLEAN isXECoreRatioLimitSupported() + { + + BOOLEAN ret; + UINT64 MsrData = ReadMsr(MSR_PLATFORM_INFO); + ret = (UINT32) (MsrData & (1 << XE_CORE_RATIO_PROGRAMMABLE_BIT)) ? 1:0; + return ret; + } +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isLimitCpuidSupported +// +// Description: Determine if CPU supports limiting CpuId to 3. +// +// Input: VOID +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN isLimitCpuidSupported() +{ + UINT32 RegEbx, RegEcx, RegEdx; + UINT32 LargestCPUIDFunc; + CPULib_CpuID(0, &LargestCPUIDFunc, &RegEbx, &RegEcx, &RegEdx); + return LargestCPUIDFunc > 3; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: isMachineCheckSupported +// +// Description: Determine if CPU supports machine check. +// +// Input: CPU_FEATURES *Features +// +// Output: True if supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsMachineCheckSupported(CPU_FEATURES *Features) +{ + //Check if MCE and MCA supported. + return ((Features->FeatureEdx & ((1 << 7) + (1 << 14))) == ((1 << 7) + (1 << 14))); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsVmxSupported +// +// Description: Determine if CPU supports VT extensions Vmx. +// +// Input: CPU_FEATURES *Features +// +// Output: True if Vmx supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsVmxSupported(CPU_FEATURES *Features) +{ + return Features->FeatureEcx & (1 << 5); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsSmxSupported +// +// Description: Determine if CPU supports VT extensions Smx. +// +// Input: CPU_FEATURES *Features +// +// Output: True if Smx supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsSmxSupported(CPU_FEATURES *Features) +{ + return Features->FeatureEcx & (1 << 6); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPU_IsSmrrSupported +// +// Description: Determine if CPU supports Smrr. +// +// Input: CPU_FEATURES *Features +// +// Output: True if Smx supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsSmrrSupported(CPU_FEATURES *Features) +{ + return (BOOLEAN)Features->Flags.SmrrSupport; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsEnergyPerfBiasSupported +// +// Description: Determine if Energy Performance Bias supported. +// +// Input: VOID +// +// Output: BOOLEAN - True if Energy Performance Bias supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +// BOOLEAN IsEnergyPerfBiasSupported() +// { +// UINT32 RegEax; +// UINT32 RegEbx; +// UINT32 RegEcx; +// UINT32 RegEdx; +// +// UINT32 CpuSignature = GetCpuSignature(); +// UINT32 CpuSigNoVer = CpuSignature & 0xfffffff0; +// UINT32 CpuVer = CpuSignature & 0xf; +// +// BOOLEAN Support = FALSE; +// +// //This is also used to control setup question. No recommendation in BWG. +// //Thus, for now Sandy Bridge Energy Bias Support is coded separately from previous CPUs. +// //if (CpuSigNoVer == SANDY_BRIDGE && CpuVer >= 3) +// // return TRUE; +// +// if (CpuSigNoVer == NEHALEM_EX && CpuVer >= 5) Support = TRUE; +// else if (CpuSigNoVer == WESTMERE) Support = TRUE; +// else if (CpuSigNoVer == WESTMERE_EX) Support = TRUE; +// +// if (!Support) return FALSE; +// ReadWriteMsr(MSR_MISC_PWR_MGMT, (1 << ENG_PERF_BIAS_EN_BIT), (UINT64)-1); //Energy Performance Bias Enable +// +// CPULib_CpuID(6, &RegEax, &RegEbx, &RegEcx, &RegEdx); +// return !!(RegEcx & BIT3); +// } +// +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsCxInterruptFilteringSupported +// +// Description: Determine if C-state interrupting state supported. +// +// Input: VOID +// +// Output: BOOLEAN - True if C-state interrupting supported. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +// BOOLEAN IsCxInterruptFilteringSupported() +// { +// return FALSE; +// +// //Not supported until this is used on a project that can test this functionality. +// //DEBUG UINT32 CpuSignature = GetCpuSignature(); +// //DEBUG if (CpuSignature != 0x00020652) return FALSE; +// //DEBUG if ((INT32)Shr64(ReadMsr(MSR_IA32_BIOS_SIGN_ID), 32) < 3) return FALSE; +// //DEBUG return TRUE; +// } + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_IsVmxEnabled +// +// Description: Determine if Vmx is enabled. +// +// Input: VOID +// +// Output: True if Vmx enabled. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CPULib_IsVmxEnabled() +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT8 Msr; + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + if (!(RegEcx & (1 << 5))) return FALSE; + + Msr = (UINT8)ReadMsr(MSR_IA32_FEATURE_CONTROL); + return !!(Msr & (1 << 2)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_IsSmxEnabled +// +// Description: Determine if Smx is enabled. +// +// Input: VOID +// +// Output: True if Smx enabled. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CPULib_IsSmxEnabled() +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT8 Msr; + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + if (!(RegEcx & BIT6)) return FALSE; + + Msr = (UINT8)ReadMsr(MSR_IA32_FEATURE_CONTROL); + return !!(Msr & BIT1); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_IsSmrrEnabled +// +// Description: Determine if Smrr is enabled. +// +// Input: BOOLEAN +// +// Output: True if Smrr is enabled. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CPULib_IsSmrrEnabled() +{ + //Once SMRR is enabled, the opened SMM Area can't be read outside of SMM. +#if SMM_CACHE_SUPPORT == 0 + return FALSE; +#else + //Some CPUs, SMRR has an enable bit. Nehalem only has a capability bit. + UINT32 MtrrCap = (UINT32)ReadMsr(MSR_IA32_MTRR_CAP); + return !!(MtrrCap & SMRR_SUPPORT_MASK); +#endif +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULIB_IsLocalX2ApicEnabled +// +// Description: Get C-state latency. +// +// Input: VOID +// +// Output: BOOLEAN - True if enabled +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN CPULib_IsLocalX2ApicEnabled() +{ + UINT32 Msr = (UINT32)ReadMsr(MSR_XAPIC_BASE); + return !!(Msr & (1 << XAPIC_X2APIC_ENABLE_BIT)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_IsFeatureControlLocked +// +// Description: Check to see if the MSR_IA32_FEATURE_CONTROL is locked. +// +// Input: VOID +// +// Output: BOOLEAN - True if MSR_IA32_FEATURE_CONTROL is locked. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CPULib_IsFeatureControlLocked() { + UINT8 Ia32FeatureCntrl = (UINT8)ReadMsr(MSR_IA32_FEATURE_CONTROL); + return Ia32FeatureCntrl & 1; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NumberOfCpuSocketsPopulated +// +// Description: Returns number of CPU sockets are populated. +// +// Input: VOID +// +// Output: UINT32 - Number of CPU sockets populated. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 NumberOfCpuSocketsPopulated() +{ +#if NUMBER_CPU_SOCKETS > 1 + UINT32 CpuSignature = GetCpuSignature(); + UINT32 CpuSigNoVer = CpuSignature & 0xfffffff0; + UINT32 NumCpuSockets = 0; + UINT32 i; + UINT32 BusNum; + + //Sandy Bridge Server. + if (CpuSigNoVer == JAKETOWN) { + UINT32 *PciAddress = (UINT32*)PCIE_CFG_ADDR(0, 0, 0, 0); + if (*PciAddress != 0xffffffff) ++NumCpuSockets; +#if NUMBER_CPU_SOCKETS >= 4 + PciAddress = (UINT32*)PCIE_CFG_ADDR(0x40, 0, 0, 0); + if (*PciAddress != 0xffffffff) ++NumCpuSockets; +#endif + PciAddress = (UINT32*)PCIE_CFG_ADDR(0x80, 0, 0, 0); + if (*PciAddress != 0xffffffff) ++NumCpuSockets; +#if NUMBER_CPU_SOCKETS >= 4 + PciAddress = (UINT32*)PCIE_CFG_ADDR(0xc0, 0, 0, 0); + if (*PciAddress != 0xffffffff) ++NumCpuSockets; +#endif + return NumCpuSockets; + } + for (i = 0, BusNum = MAX_NR_BUS; i < NUMBER_CPU_SOCKETS; ++i, --BusNum) { + UINT32 *PciAddress = (UINT32*)PCIE_CFG_ADDR(BusNum, 0, 0, 0); + if (*PciAddress != 0xffffffff) ++NumCpuSockets; + } + return NumCpuSockets; +#else + return 1; +#endif +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULIB_GetCstateLatency +// +// Description: Get C-state latency. +// +// Input: IN UINT8 Cstate +// +// Output: UINT32 - C-state latentcy in uS. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 CPULIB_GetCstateLatency(IN UINT8 Cstate) +{ + UINT32 CpuSigNoVer = GetCpuSignature() & 0xfffffff0; + BOOLEAN IsSandyBridge = CpuSigNoVer == SANDY_BRIDGE || CpuSigNoVer == JAKETOWN || CpuSigNoVer == IVY_BRIDGE; + + if (IsSandyBridge) { + switch(Cstate) { + case 1: return 1; + case 3: return 80; + case 6: return 104; + case 7: return 109; + } + } + + switch(Cstate) { + case 1: return 3; + case 3: return 205; + case 6: return 245; + case 7: return 245; + } + return 0; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULIB_GetCstatePower +// +// Description: Get C-state power. +// +// Input: IN UINT8 Cstate +// +// Output: UINT32 - C-state power in mW. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 CPULIB_GetCstatePower(IN UINT8 Cstate) +{ + switch(Cstate) { + case 1: return 1000; + case 3: return 500; + case 6: return 350; + case 7: return 200; + } + return 0; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_FindMicrocodeInFv +// +// Description: Find the microcode address for the CPU calling this in specific firmware volume. +// +// Input: VOID *Fv -- Firmware Volume +// +// Output: VOID * -- 0 if not found or the Microcode Address. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID * CPULib_FindMicrocodeInFv(VOID *Fv) +{ + UINT8 *pEndOfFv = (UINT8*)Fv + ((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->FvLength - 1; + UINT8 *pFfs = (UINT8*)Fv + ((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->HeaderLength; + UINT8 *pEndOfFfs; + UINT32 FfsSize; + + MICROCODE_HEADER *pUc; + UINT32 UcSize; + UINT32 CpuSignature = GetCpuSignature(); + UINT8 CpuFlags = (UINT8)(Shr64(ReadMsr(0x17), 50)) & 7; + UINT8 UcFlag = 1 << CpuFlags; + + //Check for corrupt firmware volume. + if (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Signature != 'HVF_') return 0; + if (pEndOfFv <= pFfs) return 0; + + while(TRUE) { + if (*(UINT32*)pFfs == 0xffffffff) return 0; + if (pFfs >= pEndOfFv) return 0; + + FfsSize = *(UINT32*)&((EFI_FFS_FILE_HEADER*)pFfs)->Size & 0xffffff; + + //Find Microcode file + if (guidcmp(&((EFI_FFS_FILE_HEADER*)pFfs)->Name, &gMicrocodeFfsGuid) == 0) + break; + if ((pFfs + FfsSize) <= pFfs) return 0; //Corruption? + pFfs += FfsSize; //Next file. + pFfs = (UINT8*)(((UINT32)pFfs + 7) & ~7); //Align on 8 byte boundary. + } + + pEndOfFfs = pFfs + FfsSize; +#if MPDTable_CREATED + pEndOfFfs -= *(UINT16*)(pEndOfFfs - 2); //Last 2 bytes is MPDT Length. Don't look in the MPDT for uC. +#endif + + //Find Microcode + pUc = (MICROCODE_HEADER*)(pFfs + sizeof(EFI_FFS_FILE_HEADER)); + + while(TRUE) { + if (pUc->HeaderVersion != 1) return 0; //End of microcode or corrupt. + UcSize = pUc->DataSize ? pUc->TotalSize : 2048; + + if (pUc->CpuSignature == CpuSignature && (pUc->Flags & UcFlag)) + break; + + if (pUc->TotalSize > (pUc->DataSize + 48)) { //Extended signature count. + MICROCODE_EXT_PROC_SIG_TABLE *SigTable = (MICROCODE_EXT_PROC_SIG_TABLE*)((UINT8*)pUc + pUc->DataSize + 48); + UINT32 ExtSigCount = SigTable->Count; + UINT8 i; + + if (ExtSigCount >= 20) return 0; //Corrupt microcode. + + for (i = 0; i < ExtSigCount; ++i) { + if (SigTable->ProcSig[i].CpuSignature == CpuSignature && (SigTable->ProcSig[i].Flags & UcFlag)) break; + } + } + +#if PACK_MICROCODE + UcSize = (UcSize + (16 - 1)) & ~(16 - 1); +#else + UcSize = (UcSize + (MICROCODE_BLOCK_SIZE - 1)) & ~(MICROCODE_BLOCK_SIZE - 1); +#endif + if (((UINT64)(UINTN)pUc + UcSize) >= (UINT64)(UINTN)pEndOfFfs) return 0; //End of uc or corrupt + + pUc = (MICROCODE_HEADER*)((UINT8*)pUc + UcSize); + } + return pUc; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_FindMicrocode +// +// Description: Find the microcode address for the CPU calling this. +// +// Input: VOID +// +// Output: VOID * -- 0 if not found or the Microcode Address. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID * CPULib_FindMicrocode() +{ + VOID *Microcode; +#if MICROCODE_SPLIT_BB_UPDATE + Microcode = CPULib_FindMicrocodeInFv((VOID*)FV_MICROCODE_UPDATE_BASE); + if (Microcode == NULL) Microcode = CPULib_FindMicrocodeInFv((VOID*)FV_MICROCODE_BASE); +#else + Microcode = CPULib_FindMicrocodeInFv((VOID*)FV_MICROCODE_BASE); +#endif + return Microcode; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_GetMicrocodeVer +// +// Description: Get Microcode Version +// +// Input: VOID +// +// Output: UINT32 - Microcode Version +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 CPULib_GetMicrocodeVer() +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + + //Clear IA32_BIOS_SIGN_ID of microcode loaded. + WriteMsr(MSR_IA32_BIOS_SIGN_ID, 0); + + //Reading CPU ID 1, updates the MSR to the microcode revision. + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + + return (UINT32)Shr64(ReadMsr(MSR_IA32_BIOS_SIGN_ID), 32); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmBaseChangeCopy +// +// Description: This is SMM code copied to 3000:8000 to set the SmmBase and IED. +// +// Input: None +// +// Output: None +// +// Notes: +// This is in real mode. To generate 16-bit code opcodes, use a small asm +// file to generate a listing. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//TODO: Move this array into assembly file. It is getting too big. +UINT8 SmmBaseChangeCopy[] = +{ //cs = 0x3000 + 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, //0x8000 mov eax, SMM_BASE + 0xbb, 0x00, 0x00, //0x8006 mov bx, 0 ;Location SM BASE OFFSET + 0x66, 0x2e, 0x89, 0x07, //0x8009 mov cs:[bx], eax + + 0x66, 0xbb, 0x01, 0x00, 0x00, 0x00, //0x800d mov ebx, 1 + 0x67, 0x66, 0x89, 0x98, 4,0x80,0,0, //0x8013 mov [eax + 8004h], ebx ;Set SMM initialization + 0x66, 0xb8, 0xff, 0xff, 0xff, 0xff, //0x801b mov eax, IED_BASE + 0xbb, 0x00, 0x00, //0x8021 mov bx, 0 ;Location of IED_SAVESTATE_OFFSET + 0x66, 0x2e, 0x89, 0x07, //0x8024 mov cs:[bx], eax + + 0xbb, 0x00, 0x00, //0x8028 mov bx, 0 + 0x0b, 0xdb, //0x802b or bx, bx + 0x75, 0x32, //0x802d jnz FirstIedInit + + 0x66, 0x89, 0xc3, //0x802f mov ebx, eax + 0x66, 0x8b, 0xf8, //0x8032 mov edi, eax + 0x66, 0x81, 0xc7, 0x0, 0, 0x10, 0, //0x8035 add edi, 0x10 0000 + 0x66, 0xb9, 0x00, 0x20, 0x00, 0x00, //0x803c mov ecx, 32 * 1024 /4 + 0x66, 0x33, 0xc0, //0x8042 xor eax, eax +//@@: + 0x66, 0x67, 0xab, //0x8045 stosd //clear IED 32k + 0x67, 0xe2, 0xfa, //0x8048 loop @b + + 0x66, 0x89, 0xdf, //0x804b mov edi, ebx + 0x66, 0x81, 0xc7, 0x0, 0, 0x20, 0, //0x804e add edi, 0x20 0000 + 0x66, 0xb9, 0x00, 0x00, 0x08, 0x00, //0x8055 mov ecx, 0x200000 / 4 +//@@: + 0x66, 0x67, 0xab, //0x805b stosd //clear IED 2MB + 0x67, 0xe2, 0xfa, //0x805e loop @b + +//FirstIedInit: + + 0xeb, 0x24, //0x8061 jmp NO_SMRR ;If SMRR, this will be changed to NOPs. +//SMRR: + 0x66, 0xb9, 0x00, 0x00, 0x00, 0x00, //0x8063 mov ecx, 0 ;MSR_SMRR_PHYS_BASE will be updated after copy. + 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, //0x8069 mov eax, 0 ;This will be updated after copy. + 0x66, 0xba, 0x00, 0x00, 0x00, 0x00, //0x806f mov edx, 0 ;This will be updated after copy. + 0x0f, 0x30, //0x8075 wrmsr + 0x66, 0x41, //0x8077 inc ecx ;MSR_SMRR_PHYS_MASK + 0x66, 0xb8, 0x00, 0x00, 0x00, 0x00, //0x8079 mov eax, 0 ;This will be updated after copy. + 0x66, 0xba, 0x00, 0x00, 0x00, 0x00, //0x807f mov edx, 0 ;This will be updated after copy. + 0x0f, 0x30, //0x8085 wrmsr +//NO_SMRR: + 0xb0, 0x01, //0x8087 mov al, 1 + 0x2e, 0xa2, 0x8f, 0x80, //0x8089 mov cs:[0x8076], al ;set flag + 0x0f, 0xaa, //0x808d rsm + 0x00 //0x808f SmmBaseChangeFlag label byte +}; + +#define SMM_ASM_FIXUP_SMM_BASE 0x38002 +#define SMM_ASM_FIXUP_SMM_BASE_SAVESTATE_OFFSET 0x38007 +#define SMM_ASM_FIXUP_IED_BASE 0x3801d +#define SMM_ASM_FIXUP_IED_SAVESTATE_OFFSET 0x38022 +#define SMM_ASM_FIXUP_IED_ZERO_MEM 0x38029 +#define SMM_ASM_FIXUP_USE_SMRR 0x38061 +#define SMM_ASM_FIXUP_MSR_SMRR_BASE 0x38065 +#define SMM_ASM_FIXUP_SMRR_BASE_EAX 0x3806b +#define SMM_ASM_FIXUP_SMRR_BASE_EDX 0x38071 +#define SMM_ASM_FIXUP_SMRR_MASK_EAX 0x3807b +#define SMM_ASM_FIXUP_SMRR_MASK_EDX 0x38081 +#define SMM_ASM_BASE_CHANGE_FLAG 0x3808f + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmGetBaseSaveBufferSize +// +// Description: Return about of memory required for the SMM handler change. +// +// Input: VOID +// +// Output: +// UINT32 Amount of memory required for SMM handler change. +// +// Notes: +// The memory will need to be allocated to use in SmmSetupDefaultHandler. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 SmmGetBaseSaveBufferSize() +{ + return sizeof(SmmBaseChangeCopy) + MAX_SMM_SAVE_STATE_SIZE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmSetupDefaultHandler +// +// Description: Save original memory, and copy SMM default handler. +// +// Input: +// IN VOID *SmmBaseSaveBuffer +// IN SMM_HOB *SmmHob +// +// Output: +// VOID +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SmmSetupDefaultHandler(IN VOID *SmmBaseSaveBuffer, IN SMM_HOB *SmmHob) +{ + //Perserve 3000:8000 used by SMM. It will be overwritten. + MemCpy(SmmBaseSaveBuffer, (VOID*)0x38000, sizeof(SmmBaseChangeCopy)); + + MemCpy((UINT8*)SmmBaseSaveBuffer + sizeof(SmmBaseChangeCopy), (UINT8*)0x40000 - MAX_SMM_SAVE_STATE_SIZE, MAX_SMM_SAVE_STATE_SIZE); + MemCpy((VOID*)0x38000, SmmBaseChangeCopy, sizeof(SmmBaseChangeCopy)); + + *(UINT16*)SMM_ASM_FIXUP_SMM_BASE_SAVESTATE_OFFSET = SMM_BASE_SAVE_STATE_OFFSET; + *(UINT16*)SMM_ASM_FIXUP_IED_SAVESTATE_OFFSET = IED_SAVESTATE_OFFSET; + *(UINT32*)SMM_ASM_FIXUP_IED_BASE = SmmHob->IedStart; //IED Start + + //Initialize SMRR + if(CPULib_IsSmrrEnabled()) { //Could be disabled. Reset may not clear lock. + UINT64 TsegMask = (0xfffffffff & (~(SmmHob->TsegLength - 1))) | (1 << 11); + *(UINT16*)SMM_ASM_FIXUP_USE_SMRR = 0x9090; //Jmp changed to NOPs. + //Update SMRR MSR. + *(UINT32*)SMM_ASM_FIXUP_MSR_SMRR_BASE = GetSmrrBaseMsr(); + //Update SMRR Base + *(UINT32*)SMM_ASM_FIXUP_SMRR_BASE_EAX = (UINT32)SmmHob->Tseg | 6; //Lower 32-bits. 6 = WB. + *(UINT32*)SMM_ASM_FIXUP_SMRR_BASE_EDX = 0; //Upper 32-bits. + //Update SMRR Mask + *(UINT32*)SMM_ASM_FIXUP_SMRR_MASK_EAX = (UINT32)TsegMask; //Lower 32-bits. + *(UINT32*)SMM_ASM_FIXUP_SMRR_MASK_EDX = 0; //Upper 32-bits. SMRR Mask Reserved bits. + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmBaseChangeOnCpu +// +// Description: Execute on each CPU to change its own base. +// +// Input: +// VOID *SmmBase +// +// Output: +// VOID +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SmmBaseChangeOnCpu(IN VOID *SmmBase) +{ + *(UINT32*)SMM_ASM_FIXUP_SMM_BASE = (UINT32)SmmBase; + *(UINT8*)SMM_ASM_BASE_CHANGE_FLAG = 0; //Initialize Flag + + //Send SMM IPI + if (CPULib_IsLocalX2ApicEnabled()) { + UINT32 ApicId = (UINT32) ReadMsr(MSR_EXT_XAPIC_LOGICAL_APIC_ID); + ReadWriteMsr(MSR_EXT_XAPIC_ICR, + Shl64(ApicId, 32) + APIC_NO_SHORT_HAND + APIC_LEVEL_ASSERT + APIC_SMI, + 0xfff32000 + ); + } else { + UINT8 ApicId = (UINT8)(*(UINT32*)(LOCAL_APIC_BASE + APIC_ID_REGISTER) >> 24); + MemReadWrite32((UINT32*)(LOCAL_APIC_BASE + APIC_ICR_HIGH_REGISTER), ApicId << 24, 0x00ffffff); + MemReadWrite32((UINT32*)(LOCAL_APIC_BASE + APIC_ICR_LOW_REGISTER), APIC_NO_SHORT_HAND + APIC_LEVEL_ASSERT + APIC_SMI, 0); + } + + while (!(*(volatile UINT8*)SMM_ASM_BASE_CHANGE_FLAG)) CPULib_Pause(); //Wait on Flag + ++*(UINT16*)SMM_ASM_FIXUP_IED_ZERO_MEM; //Only 0, for first thread to clear IED memory. +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmRemoveDefaultHandler +// +// Description: Remove default SMM Handler from memory and restore original data. +// +// Input: +// IN VOID *SmmBaseSaveBuffer +// +// Output: +// VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SmmRemoveDefaultHandler(IN VOID *SmmBaseSaveBuffer) +{ + //Restore 3000:8000 overwritten for SMM + MemCpy((VOID*)0x38000, SmmBaseSaveBuffer, sizeof(SmmBaseChangeCopy)); + MemCpy((UINT8*)0x40000 - MAX_SMM_SAVE_STATE_SIZE, (UINT8*)SmmBaseSaveBuffer + sizeof(SmmBaseChangeCopy), MAX_SMM_SAVE_STATE_SIZE); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPUProgramPAMRegisters +// +// Description: Program 0xc0000 - 0xfffff regions to Lock/Unlock. +// +// Input: +// UINT32 StartAddress +// UINT32 Length +// UINT8 Setting +// UINT32 *Granularity +// +// Output: EFI_STATUS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CPUProgramPAMRegisters( + EFI_BOOT_SERVICES *gBS, + EFI_RUNTIME_SERVICES *gRS, + UINT32 StartAddress, + UINT32 Length, + UINT8 Setting, + UINT32 *Granularity +) +{ + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuLib_SaveCpuState +// +// Description: Save CPU state in SMM. +// +// Input: +// IN OUT CPU_LIB_SMM_SAVE_RESTORE_DATA *State - Track CPU state. +// +// Output: VOID +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CpuLib_SmmSaveCpuState(IN OUT CPU_LIB_SMM_SAVE_RESTORE_DATA* State) +{ + UINT64 ClkMod = ReadMsr(MSR_IA32_CLOCK_MODULATION); + + State->ClkModEn = (UINT8)ClkMod & CLK_MOD_ENABLE; + ClkMod &= ~(UINT64)CLK_MOD_ENABLE; + WriteMsr(MSR_IA32_CLOCK_MODULATION, ClkMod); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuLib_SmmRestoreCpuState +// +// Description: Restore CPU state in SMM. +// +// Input: +// IN CPU_LIB_SMM_SAVE_RESTORE_DATA *State - Track CPU state. +// +// Output: VOID +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CpuLib_SmmRestoreCpuState(IN CPU_LIB_SMM_SAVE_RESTORE_DATA* State) +{ + if (State->ClkModEn) ReadWriteMsr(MSR_IA32_CLOCK_MODULATION, CLK_MOD_ENABLE, (UINT64)-1); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPU_GetSaveStateId30006 +// +// Description: +// This routines saves the necessary values from Revison 3006 +// SMM save state area. +// +// Input: +// SmmBase Pointer to CPU SMM save state. +// SstSaveState Pointer to copied SMM save state. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CPU_GetSaveStateId30006( + UINT8 *SmmBase, + EFI_SMI_CPU_SAVE_STATE *SstSaveState, + UINT32 SmmRevision +) +{ + SstSaveState->SMBASE = *(UINT32*)(SmmBase + 0xfef8); + SstSaveState->SMMRevId = *(UINT32*)(SmmBase + 0xfefc); +#if (((CORE_MAJOR_VERSION << 16) + (CORE_MINOR_VERSION << 8) + CORE_REVISION) > 0x040603) + SstSaveState->GDTBase = *(UINT32*)(SmmBase + 0xfe8c); + SstSaveState->IDTBase = *(UINT32*)(SmmBase + 0xfe94); + SstSaveState->CR4 = *(UINT32*)(SmmBase + 0xfe40); +#endif + SstSaveState->ES = *(UINT16*)(SmmBase + 0xffa8); + SstSaveState->CS = *(UINT16*)(SmmBase + 0xffac); + SstSaveState->SS = *(UINT16*)(SmmBase + 0xffb0); + SstSaveState->DS = *(UINT16*)(SmmBase + 0xffb4); + SstSaveState->FS = *(UINT16*)(SmmBase + 0xffb8); + SstSaveState->GS = *(UINT16*)(SmmBase + 0xffbc); + SstSaveState->LDTBase = *(UINT32*)(SmmBase + 0xfe9c); + SstSaveState->TR = *(UINT32*)(SmmBase + 0xffc4); + SstSaveState->DR7 = *(UINT32*)(SmmBase + 0xffc8); + SstSaveState->DR6 = *(UINT32*)(SmmBase + 0xffd0); + SstSaveState->EAX = *(UINT32*)(SmmBase + 0xff5c); + SstSaveState->ECX = *(UINT32*)(SmmBase + 0xff64); + SstSaveState->EDX = *(UINT32*)(SmmBase + 0xff6c); + SstSaveState->EBX = *(UINT32*)(SmmBase + 0xff74); + SstSaveState->ESP = *(UINT32*)(SmmBase + 0xff7c); + SstSaveState->EBP = *(UINT32*)(SmmBase + 0xff84); + SstSaveState->ESI = *(UINT32*)(SmmBase + 0xff8c); + SstSaveState->EDI = *(UINT32*)(SmmBase + 0xff94); + SstSaveState->EIP = *(UINT32*)(SmmBase + 0xffd8); + SstSaveState->EFLAGS = *(UINT32*)(SmmBase + 0xffe8); + SstSaveState->CR3 = *(UINT32*)(SmmBase + 0xfff0); + SstSaveState->CR0 = *(UINT32*)(SmmBase + 0xfff8); + + if (SmmRevision < 0x30100) { + SstSaveState->IORestart = *(UINT16*)(SmmBase + 0xff02); + SstSaveState->AutoHALTRestart = *(UINT16*)(SmmBase + 0xff00); + } else { + SstSaveState->AutoHALTRestart = *(UINT16*)(SmmBase + 0xff02); + SstSaveState->IORestart = *(UINT16*)(SmmBase + 0xff00); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPU_RestoreSaveStateId30006 +// +// Description: +// This routines restores the necessary values from Revision 3006 +// SMM save state area. +// +// Input: +// SmmBase Pointer to SMM save state +// SstSaveState Standard SMM save state +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CPU_RestoreSaveStateId30006( + UINT8 *SmmBase, + EFI_SMI_CPU_SAVE_STATE *SstSaveState, + UINT32 SmmRevision +) +{ + *(UINT16*)(SmmBase + 0xffa8) = SstSaveState->ES; + *(UINT16*)(SmmBase + 0xffac) = SstSaveState->CS; + *(UINT16*)(SmmBase + 0xffb0) = SstSaveState->SS; + *(UINT16*)(SmmBase + 0xffb4) = SstSaveState->DS; + *(UINT16*)(SmmBase + 0xffb8) = SstSaveState->FS; + *(UINT16*)(SmmBase + 0xffbc) = SstSaveState->GS; + *(UINT32*)(SmmBase + 0xff5c) = SstSaveState->EAX; + *(UINT32*)(SmmBase + 0xff64) = SstSaveState->ECX; + *(UINT32*)(SmmBase + 0xff6c) = SstSaveState->EDX; + *(UINT32*)(SmmBase + 0xff74) = SstSaveState->EBX; + *(UINT32*)(SmmBase + 0xff7c) = SstSaveState->ESP; + *(UINT32*)(SmmBase + 0xff84) = SstSaveState->EBP; + *(UINT32*)(SmmBase + 0xff8c) = SstSaveState->ESI; + *(UINT32*)(SmmBase + 0xff94) = SstSaveState->EDI; + *(UINT32*)(SmmBase + 0xffd8) = SstSaveState->EIP; + *(UINT32*)(SmmBase + 0xffe8) = SstSaveState->EFLAGS; + + if (SmmRevision < 0x30100) { + *(UINT16*)(SmmBase + 0xff02) = SstSaveState->IORestart; + *(UINT16*)(SmmBase + 0xff00) = SstSaveState->AutoHALTRestart; + } else { + *(UINT16*)(SmmBase + 0xff02) = SstSaveState->AutoHALTRestart; + *(UINT16*)(SmmBase + 0xff00) = SstSaveState->IORestart; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPU_RestoreDefaultSaveState +// +// Description: +// This routines copies the necessary values from standard +// SMM save state area to version 0x30003 SMM save state area. +// +// Input: +// SmmBase Pointer to CPU SMM save state. +// SstSaveState Pointer to copied SMM save state. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CPU_RestoreDefaultSaveState +( + UINT8 *SmmBase, + EFI_SMI_CPU_SAVE_STATE *SstSaveState +) +{ + EFI_SMI_CPU_SAVE_STATE *SmmSave = (EFI_SMI_CPU_SAVE_STATE*) SmmBase; + + SmmSave->EFLAGS = SstSaveState->EFLAGS; + SmmSave->EIP = SstSaveState->EIP; + SmmSave->EDI = SstSaveState->EDI; + SmmSave->ESI = SstSaveState->ESI; + SmmSave->EBP = SstSaveState->EBP; + SmmSave->ESP = SstSaveState->ESP; + SmmSave->EBX = SstSaveState->EBX; + SmmSave->EDX = SstSaveState->EDX; + SmmSave->ECX = SstSaveState->ECX; + SmmSave->EAX = SstSaveState->EAX; + SmmSave->AutoHALTRestart = SstSaveState->AutoHALTRestart; + SmmSave->IORestart = SstSaveState->IORestart; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPU_GetSaveState +// +// Description: +// This routine is the generic routine used to copy the CPU specific SMM +// save state to standard save state. +// +// Input: +// SmmBase Pointer to CPU SMM save state. +// SstSaveState Pointer to copied SMM save state +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CPU_GetSaveState +( + UINT8 *SmmBase, + EFI_SMI_CPU_SAVE_STATE *SstSaveState +) +{ + UINT32 SmmRevision = *(UINT32*)(SmmBase + 0xfefc); + + //Porting Required. PERFORM CPU SPECIFIC save state handling + if (SmmRevision >= 0x30006) { + CPU_GetSaveStateId30006(SmmBase, SstSaveState, SmmRevision); + } else { + UINTN Index; + //Copy save state area. + for (Index = 0; + Index < (sizeof(EFI_SMI_CPU_SAVE_STATE) / sizeof(UINT32)); + Index ++) { + *( ((UINT32 *)SstSaveState) + Index) + = *( (UINT32 *)(SmmBase + 0xfe00) + Index); + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPU_RestoreSaveState +// +// Description: +// This routine is the generic routine used to copy the standard +// SMM save state from CPU specific save state. This routine +// should make sure it does not change read only areas +// +// Input: +// SmmBase Pointer to CPU SMM save state. +// SstSaveState Pointer to copied SMM save state +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CPU_RestoreSaveState +( + UINT8 *SmmBase, + EFI_SMI_CPU_SAVE_STATE *SstSaveState +) +{ + UINT32 SmmRevision = *(UINT32*)(SmmBase + 0xfefc); + + //Porting Required. PERFORM CPU SPECIFIC save state handling + if (SmmRevision >= 0x30006) { + CPU_RestoreSaveStateId30006(SmmBase, SstSaveState, SmmRevision); + } else { + CPU_RestoreDefaultSaveState(SmmBase + 0xfe00, SstSaveState); + } +} + +typedef struct { + UINT16 SaveStateOffset; + UINT16 SaveStateWidth; + UINT16 FrameworkOffset; + UINT16 FrameworkWidth; +} INTEL_X64_FORMAT; + +INTEL_X64_FORMAT gIntelX64Format[] = { + //Treat special case - EFI_SMM_SAVE_STATE_REGISTER_GDTBASE = 4 + //Treat special case - EFI_SMM_SAVE_STATE_REGISTER_IDTBASE = 5 + //Treat special case - EFI_SMM_SAVE_STATE_REGISTER_LDTBASE = 6 + //Treat special case - EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7 No Save State + //Treat special case - EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8 No Save State + //Treat special case - EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9 No Save State + //Treat special case - EFI_SMM_SAVE_STATE_REGISTER_LDTINFO = 10 No Save State + 0xffa8, 2, 0x01a8, 2, //EFI_SMM_SAVE_STATE_REGISTER_ES = 20 + 0xffac, 2, 0x01ac, 2, //EFI_SMM_SAVE_STATE_REGISTER_CS = 21 + 0xffb0, 2, 0x01b0, 2, //EFI_SMM_SAVE_STATE_REGISTER_SS = 22 + 0xffb4, 2, 0x01b4, 2, //EFI_SMM_SAVE_STATE_REGISTER_DS = 23 + 0xffb8, 2, 0x01b8, 2, //EFI_SMM_SAVE_STATE_REGISTER_FS = 24 + 0xffbc, 2, 0x01bc, 2, //EFI_SMM_SAVE_STATE_REGISTER_GS = 25 + 0xffc0, 2, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26 + 0xffc4, 2, 0x01c4, 2, //EFI_SMM_SAVE_STATE_REGISTER_TR_SEL = 27 + 0xffc8, 8, 0x01c8, 4, //EFI_SMM_SAVE_STATE_REGISTER_DR7 = 28 + 0xffd0, 8, 0x01fc, 4, //EFI_SMM_SAVE_STATE_REGISTER_DR6 = 29 + 0xff54, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R8 = 30 + 0xff4c, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R9 = 31 + 0xff44, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R10 = 32 + 0xff3c, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R11 = 33 + 0xff34, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R12 = 34 + 0xff2c, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R13 = 35 + 0xff24, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R14 = 36 + 0xff1c, 8, 0xffff, 0xff, //EFI_SMM_SAVE_STATE_REGISTER_R15 = 37 + 0xff5c, 8, 0x01d0, 4, //EFI_SMM_SAVE_STATE_REGISTER_RAX = 38 + 0xff74, 8, 0x01dc, 4, //EFI_SMM_SAVE_STATE_REGISTER_RBX = 39 + 0xff64, 8, 0x01d4, 4, //EFI_SMM_SAVE_STATE_REGISTER_RCX = 40 + 0xff6c, 8, 0x01d8, 4, //EFI_SMM_SAVE_STATE_REGISTER_RDX = 41 + 0xff64, 8, 0x01e0, 4, //EFI_SMM_SAVE_STATE_REGISTER_RSP = 42 + 0xff84, 8, 0x01e4, 4, //EFI_SMM_SAVE_STATE_REGISTER_RBP = 43 + 0xff8c, 8, 0x01e8, 4, //EFI_SMM_SAVE_STATE_REGISTER_RSI = 44 + 0xff94, 8, 0x01ec, 4, //EFI_SMM_SAVE_STATE_REGISTER_RDI = 45 + 0xffd8, 8, 0x01f0, 4, //EFI_SMM_SAVE_STATE_REGISTER_RIP = 46 + 0xffe8, 8, 0x01f4, 4, //EFI_SMM_SAVE_STATE_REGISTER_RFLAGS = 51 + 0xfff8, 8, 0x01fc, 4, //EFI_SMM_SAVE_STATE_REGISTER_CR0 = 52 + 0xfff0, 8, 0x01f8, 4, //EFI_SMM_SAVE_STATE_REGISTER_CR3 = 53 + 0xfe40, 8, 0x00f0, 4, //EFI_SMM_SAVE_STATE_REGISTER_CR4 = 54 + + //Supported in XMM Save/restore function + //EFI_SMM_SAVE_STATE_REGISTER_FCW = 256 + //EFI_SMM_SAVE_STATE_REGISTER_FSW = 257 + //EFI_SMM_SAVE_STATE_REGISTER_FTW = 258 + //EFI_SMM_SAVE_STATE_REGISTER_OPCODE = 259 + //EFI_SMM_SAVE_STATE_REGISTER_FP_EIP = 260 + //EFI_SMM_SAVE_STATE_REGISTER_FP_CS = 261 + //EFI_SMM_SAVE_STATE_REGISTER_DATAOFFSET = 262 + //EFI_SMM_SAVE_STATE_REGISTER_FP_DS = 263 + //EFI_SMM_SAVE_STATE_REGISTER_MM0 = 264 + //EFI_SMM_SAVE_STATE_REGISTER_MM1 = 265 + //EFI_SMM_SAVE_STATE_REGISTER_MM2 = 266 + //EFI_SMM_SAVE_STATE_REGISTER_MM3 = 267 + //EFI_SMM_SAVE_STATE_REGISTER_MM4 = 268 + //EFI_SMM_SAVE_STATE_REGISTER_MM5 = 269 + //EFI_SMM_SAVE_STATE_REGISTER_MM6 = 270 + //EFI_SMM_SAVE_STATE_REGISTER_MM7 = 271 + //EFI_SMM_SAVE_STATE_REGISTER_XMM0 = 272 + //EFI_SMM_SAVE_STATE_REGISTER_XMM1 = 273 + //EFI_SMM_SAVE_STATE_REGISTER_XMM2 = 274 + //EFI_SMM_SAVE_STATE_REGISTER_XMM3 = 275 + //EFI_SMM_SAVE_STATE_REGISTER_XMM4 = 276 + //EFI_SMM_SAVE_STATE_REGISTER_XMM5 = 277 + //EFI_SMM_SAVE_STATE_REGISTER_XMM6 = 278 + //EFI_SMM_SAVE_STATE_REGISTER_XMM7 = 279 + //EFI_SMM_SAVE_STATE_REGISTER_XMM8 = 280 + //EFI_SMM_SAVE_STATE_REGISTER_XMM9 = 281 + //EFI_SMM_SAVE_STATE_REGISTER_XMM10 = 282 + //EFI_SMM_SAVE_STATE_REGISTER_XMM11 = 283 + //EFI_SMM_SAVE_STATE_REGISTER_XMM12 = 284 + //EFI_SMM_SAVE_STATE_REGISTER_XMM13 = 285 + //EFI_SMM_SAVE_STATE_REGISTER_XMM14 = 286 + //EFI_SMM_SAVE_STATE_REGISTER_XMM15 = 287 + // + // Pseudo-Registers + // + //EFI_SMM_SAVE_STATE_REGISTER_IO = 512 + //EFI_SMM_SAVE_STATE_REGISTER_LMA = 513 +}; + +typedef enum { + CPULIB_SMM_SAVE_STATE_IO_WIDTH_UINT8 = 0, + CPULIB_SMM_SAVE_STATE_IO_WIDTH_UINT16 = 1, + CPULIB_SMM_SAVE_STATE_IO_WIDTH_UINT32 = 2, + CPULIB_SMM_SAVE_STATE_IO_WIDTH_UINT64 = 3 +} CPULIB_SMM_SAVE_STATE_IO_WIDTH; + +typedef enum { + CPULIB_SMM_SAVE_STATE_IO_TYPE_INPUT = 1, + CPULIB_SMM_SAVE_STATE_IO_TYPE_OUTPUT = 2, + CPULIB_SMM_SAVE_STATE_IO_TYPE_STRING = 4, + CPULIB_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX = 8 +} CPULIB_SMM_SAVE_STATE_IO_TYPE; + +typedef struct { + UINT64 IoData; + UINT16 IoPort; + CPULIB_SMM_SAVE_STATE_IO_WIDTH IoWidth; + CPULIB_SMM_SAVE_STATE_IO_TYPE IoType; +} CPULIB_SMM_SAVE_STATE_IO_INFO; + +UINT8 IOTypeToEMSSIT[] = { + CPULIB_SMM_SAVE_STATE_IO_TYPE_OUTPUT, + CPULIB_SMM_SAVE_STATE_IO_TYPE_INPUT, + CPULIB_SMM_SAVE_STATE_IO_TYPE_STRING, + CPULIB_SMM_SAVE_STATE_IO_TYPE_STRING, + 0, + 0, + CPULIB_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, + CPULIB_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, + CPULIB_SMM_SAVE_STATE_IO_TYPE_OUTPUT, + CPULIB_SMM_SAVE_STATE_IO_TYPE_INPUT +}; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_SmmReadSaveState +// +// Description: Read SMM Save state from combination of SMM save state and copy. +// If frame copy exists, use its data instead from actual save state. +// A different function gets information for floating point and XMM. +// +// Input: +// IN UINT8 *SmmBase - SmmBase of CPU to read Save State. +// IN UINT8 *SstSaveState - SMM Save state copy for Framework. +// IN BOOLEAN UseSstSaveState - True if Save state copy exists. +// IN UINT8 Width - Width in Bytes of register. +// IN UINT32 Register - Register Token in PI SMM. +// OUT VOID *Buffer - Read register into this buffer. +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CPULib_SmmReadSaveState( + IN UINT8 *SmmBase, + IN UINT8 *SstSaveState, + IN BOOLEAN UseSstSaveState, + IN UINT8 Width, + IN UINT32 Register, + OUT VOID *Buffer +) +{ + UINT32 Index = 0xffffffff; + UINTN Offset; + + if (Register >= 20 && Register <= 46) Index = Register - 20; + if (Register >= 51 && Register <= 54) Index = Register - 20 - (51-47); + + if (Index != 0xffffffff) { + if (Width > gIntelX64Format[Index].SaveStateWidth) return EFI_INVALID_PARAMETER; + switch(Width) { + case 1: + //Use SMM framework buffer if available, because copy may be updated by Framework driver, and copy will overwrite actual save state at end. + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(UINT8*)Buffer = *(SstSaveState + gIntelX64Format[Index].FrameworkOffset); + else *(UINT8*)Buffer = *(SmmBase + gIntelX64Format[Index].SaveStateOffset); + return EFI_SUCCESS; + case 2: + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(UINT16*)Buffer = *(UINT16*)(SstSaveState + gIntelX64Format[Index].FrameworkOffset); + else *(UINT16*)Buffer = *(UINT16*)(SmmBase + gIntelX64Format[Index].SaveStateOffset); + return EFI_SUCCESS; + case 4: + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(UINT32*)Buffer = *(UINT32*)(SstSaveState + gIntelX64Format[Index].FrameworkOffset); + else *(UINT32*)Buffer = *(UINT32*)(SmmBase + gIntelX64Format[Index].SaveStateOffset); + return EFI_SUCCESS; + case 8: + *(UINT64*)Buffer = *(UINT64*)(SmmBase + gIntelX64Format[Index].SaveStateOffset); + //Use copy if available, because copy may be updated by Framework driver, and copy will overwrite actual save state at end. Copy doesn't support upper bits. + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(UINT32*)Buffer = *(UINT32*)(SstSaveState + gIntelX64Format[Index].FrameworkOffset); + return EFI_SUCCESS; + } + } + if (Register == 4) { //GDT + if (Width != 4 && Width != 8) return EFI_INVALID_PARAMETER; + if (Width == 8) *((UINT32*)Buffer + 1) = *(UINT32*)(SmmBase + 0xffd0); + //Use copy for lower 32-bits + if (UseSstSaveState) *(UINT32*)Buffer = *(UINT32*)(SstSaveState + 0x188); + return EFI_SUCCESS; + } + if (Register == 5) { //IDT + if (Width != 4 && Width != 8) return EFI_INVALID_PARAMETER; + if (Width == 8) *((UINT32*)Buffer + 1) = *(UINT32*)(SmmBase + 0xfdd8); + //Use copy for lower 32-bits + if (UseSstSaveState) *(UINT32*)Buffer = *(UINT32*)(SstSaveState + 0x194); + return EFI_SUCCESS; + } + if (Register == 6) { //LDT + if (Width != 4 && Width != 8) return EFI_INVALID_PARAMETER; + if (Width == 8) *((UINT32*)Buffer + 1) = *(UINT32*)(SmmBase + 0xfdd4); + //Use copy for lower 32-bits + if (UseSstSaveState) *(UINT32*)Buffer = *(UINT32*)(SstSaveState + 0x1c0); + return EFI_SUCCESS; + } + + if (Register == 513) { + UINT16 Efer; + if (Width != 1) return EFI_INVALID_PARAMETER; + Efer = *(UINT16*)(SmmBase + 0xffe0); + *(UINT8*)Buffer = (Efer & BIT10) == BIT10 ? 64 : 32; + return EFI_SUCCESS; + } + + if (Register == 512) { + UINT32 IoMisc = *(UINT32*)(SmmBase + 0xffa4); + UINT8 Width = 0; + + if (!(IoMisc & 1)) return EFI_NOT_FOUND; + + switch((IoMisc >> 1) & 7) { + case 1: Width = 0; break; + case 2: Width = 1; break; + case 3: Width = 2; break; + default: return EFI_NOT_FOUND; + }; + + //Get the I/O address. + switch ((IoMisc >> 4) & 0xF) { + case 0: + case 1: + case 8: + case 9: + Offset = 0xff5c; //Reg RAX has the value + break; + case 2: + case 3: + case 6: + case 7: + Offset = 0xff9c; //IO_MEM_ADDRESS has the value + break; + default: + return EFI_NOT_FOUND; + } + + ((CPULIB_SMM_SAVE_STATE_IO_INFO*)Buffer)->IoPort = (UINT16)(IoMisc >> 16); + ((CPULIB_SMM_SAVE_STATE_IO_INFO*)Buffer)->IoWidth = Width; + ((CPULIB_SMM_SAVE_STATE_IO_INFO*)Buffer)->IoType = IOTypeToEMSSIT[(IoMisc >> 4) & 0xf]; + + switch (Width) { + case 0: + ((CPULIB_SMM_SAVE_STATE_IO_INFO*)Buffer)->IoData = *(UINT8 *)(SmmBase + Offset); + break; + case 1: + ((CPULIB_SMM_SAVE_STATE_IO_INFO*)Buffer)->IoData = *(UINT16 *)(SmmBase + Offset); + break; + case 2: + ((CPULIB_SMM_SAVE_STATE_IO_INFO*)Buffer)->IoData = *(UINT32 *)(SmmBase + Offset); + break; + default: + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; //Register not supported. +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuLib_SmmReadSaveStateFxSave +// +// Description: Read SMM Save state for floating point and XMM. +// +// Input: +// IN UINT8 *FxSave - FxSave buffer. +// IN UINT8 Width - Width in Bytes of register. +// IN UINT32 Register - Register Token in PI SMM. +// OUT VOID *Buffer - Read register into this buffer. +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CpuLib_SmmReadSaveStateFxSave( + IN UINT8 *FxSave, + IN UINT8 Width, + IN UINT32 Register, + OUT VOID *Buffer +) +{ + if (Register == 256) { //FCW + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)Buffer = *(UINT16*)FxSave; + return EFI_SUCCESS; + } + if (Register == 257) { //FSW + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)Buffer = *(UINT16*)(FxSave + 2); + return EFI_SUCCESS; + } + if (Register == 258) { //FTW + if (Width != 1) return EFI_INVALID_PARAMETER; + *(UINT8*)Buffer = *(UINT8*)(FxSave + 4); + return EFI_SUCCESS; + } + if (Register == 259) { //FOP + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)Buffer = *(UINT16*)(FxSave + 6); + return EFI_SUCCESS; + } + + if (Register == 260) { //FPU IP + if (Width == 4) { + MemCpy(Buffer, FxSave + 8, 4); + return EFI_SUCCESS; + } +#if x64_BUILD + if (Width == 8) { + MemCpy(Buffer, FxSave + 8, 8); + return EFI_SUCCESS; + } +#endif + return EFI_INVALID_PARAMETER; + } + +#if x64_BUILD == 0 + if (Register == 261) { //CS + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)Buffer = *(UINT16*)(FxSave + 12); + } +#endif + + if (Register == 262) { //FPU DP (DataOffset) + if (Width == 4) { + MemCpy(Buffer, FxSave + 16, 4); + return EFI_SUCCESS; + } +#if x64_BUILD + if (Width == 8) { + MemCpy(Buffer, FxSave + 16, 8); + return EFI_SUCCESS; + } +#endif + return EFI_INVALID_PARAMETER; + } + +#if x64_BUILD == 0 + if (Register == 263) { //DS + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)Buffer = *(UINT16*)(FxSave + 20); + } +#endif + + if (Register >= 264 && Register <= 271) { //MM0 - MM7 + if (Width != 10) return EFI_INVALID_PARAMETER; + MemCpy(Buffer, FxSave + 32 + 16 * (Register - 264), 10); + return EFI_SUCCESS; + } + if (Register >= 272 && Register <= 287) { //XMM0 - XMM15 + if (Width != 16) return EFI_INVALID_PARAMETER; + MemCpy(Buffer, FxSave + 160 + 16 * (Register - 272), 16); + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CPULib_SmmWriteSaveState +// +// Description: Write SMM Save state from combination of SMM save state and copy. +// If frame copy exists, use its data instead from actual save state. +// A different function gets information for floating point and XMM. +// +// Input: +// IN UINT8 *SmmBase - SmmBase of CPU to read Save State. +// IN UINT8 *SstSaveState - SMM Save state copy for Framework. +// IN BOOLEAN UseSstSaveState - True if Save state copy exists. +// IN UINT8 Width - Width in Bytes of register. +// IN UINT32 Register - Register Token in PI SMM. +// IN VOID *Buffer - Write register into this buffer. +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CPULib_SmmWriteSaveState( + IN OUT UINT8 *SmmBase, + IN OUT UINT8 *SstSaveState, + IN BOOLEAN UseSstSaveState, + IN UINT8 Width, + IN UINT32 Register, + IN VOID *Buffer +) +{ + UINT32 Index = 0xffffffff; + + if (Register >= 20 && Register <= 46) Index = Register - 20; + if (Register >= 51 && Register <= 54) Index = Register - 20 - (51-47); //No tokens assigned 47-50. + + if (Index != 0xffffffff) { + if (Width > gIntelX64Format[Index].SaveStateWidth) return EFI_INVALID_PARAMETER; + switch(Width) { + case 1: + *(SmmBase + gIntelX64Format[Index].SaveStateOffset) = *(UINT8*)Buffer; + //Copy to save state buffer for SMM framework. + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(SstSaveState + gIntelX64Format[Index].FrameworkOffset) = *(UINT8*)Buffer; + return EFI_SUCCESS; + case 2: + *(UINT16*)(SmmBase + gIntelX64Format[Index].SaveStateOffset) = *(UINT16*)Buffer; + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(UINT16*)(SstSaveState + gIntelX64Format[Index].FrameworkOffset) = *(UINT16*)Buffer; + return EFI_SUCCESS; + case 4: + *(UINT32*)(SmmBase + gIntelX64Format[Index].SaveStateOffset) = *(UINT32*)Buffer; + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(UINT32*)(SstSaveState + gIntelX64Format[Index].FrameworkOffset) = *(UINT32*)Buffer; + return EFI_SUCCESS; + case 8: + *(UINT64*)(SmmBase + gIntelX64Format[Index].SaveStateOffset) = *(UINT64*)Buffer; + if (UseSstSaveState && gIntelX64Format[Index].FrameworkWidth != 0xff) *(UINT32*)(SstSaveState + gIntelX64Format[Index].FrameworkOffset) = *(UINT32*)Buffer; + return EFI_SUCCESS; + } + } + if (Register == 4) { //GDT + if (Width != 4 && Width != 8) return EFI_INVALID_PARAMETER; + if (Width == 8) *(UINT32*)(SmmBase + 0xffd0) = *((UINT32*)Buffer + 1); + *(UINT32*)(SmmBase + 0xfe8c) = *(UINT32*)Buffer; + //Copy to framework buffer for lower 32-bits + if (UseSstSaveState) *(UINT32*)(SstSaveState + 0x188) = *(UINT32*)Buffer; + return EFI_SUCCESS; + } + if (Register == 5) { //IDT + if (Width != 4 && Width != 8) return EFI_INVALID_PARAMETER; + if (Width == 8) *(UINT32*)(SmmBase + 0xfdd8) = *((UINT32*)Buffer + 1); + *(UINT32*)(SmmBase + 0xfe94) = *(UINT32*)Buffer; + if (UseSstSaveState) *(UINT32*)(SstSaveState + 0x194) = *(UINT32*)Buffer; + return EFI_SUCCESS; + } + if (Register == 6) { //LDT + if (Width != 4 && Width != 8) return EFI_INVALID_PARAMETER; + if (Width == 8) *(UINT32*)(SmmBase + 0xfdd4) = *((UINT32*)Buffer + 1); + *(UINT32*)(SmmBase + 0xfe9c) = *(UINT32*)Buffer; + if (UseSstSaveState) *(UINT32*)(SstSaveState + 0x1c0) = *(UINT32*)Buffer; + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuLib_SmmWriteSaveStateFxSave +// +// Description: Write SMM Save state for floating point and XMM. +// +// Input: +// IN UINT8 *FxSave - FxSave buffer. +// IN UINT8 Width - Width in Bytes of register. +// IN UINT32 Register - Register Token in PI SMM. +// IN VOID *Buffer - Write register into this buffer. +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CpuLib_SmmWriteSaveStateFxSave( + IN UINT8 *FxSave, + IN UINT8 Width, + IN UINT32 Register, + IN VOID *Buffer +) +{ + if (Register == 256) { //FCW + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)FxSave = *(UINT16*)Buffer; + return EFI_SUCCESS; + } + if (Register == 257) { //FSW + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)(FxSave + 2) = *(UINT16*)Buffer; + return EFI_SUCCESS; + } + if (Register == 258) { //FTW + if (Width != 1) return EFI_INVALID_PARAMETER; + *(UINT8*)(FxSave + 4) = *(UINT8*)Buffer; + return EFI_SUCCESS; + } + if (Register == 259) { //FOP + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)(FxSave + 6) = *(UINT16*)Buffer; + return EFI_SUCCESS; + } + + if (Register == 260) { //FPU IP + if (Width == 4) { + MemCpy(FxSave + 8, Buffer, 4); + return EFI_SUCCESS; + } +#if x64_BUILD + if (Width == 8) { + MemCpy(FxSave + 8, Buffer, 8); + return EFI_SUCCESS; + } +#endif + return EFI_INVALID_PARAMETER; + } + +#if x64_BUILD == 0 + if (Register == 261) { //CS + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)(FxSave + 12) = *(UINT16*)Buffer; + } +#endif + + if (Register == 262) { //FPU DP (DataOffset) + if (Width == 4) { + MemCpy(FxSave + 16, Buffer, 4); + return EFI_SUCCESS; + } +#if x64_BUILD + if (Width == 8) { + MemCpy(FxSave + 16, Buffer, 8); + return EFI_SUCCESS; + } +#endif + return EFI_INVALID_PARAMETER; + } + +#if x64_BUILD == 0 + if (Register == 263) { //DS + if (Width != 2) return EFI_INVALID_PARAMETER; + *(UINT16*)(FxSave + 20) = *(UINT16*)Buffer ; + } +#endif + + if (Register >= 264 && Register <= 271) { //MM0 - MM7 + if (Width != 10) return EFI_INVALID_PARAMETER; + MemCpy(FxSave + 32 + 16 * (Register - 264), Buffer, 10); + return EFI_SUCCESS; + } + if (Register >= 272 && Register <= 287) { //XMM0 - XMM15 + if (Width != 16) return EFI_INVALID_PARAMETER; + MemCpy(FxSave + 160 + 16 * (Register - 272), Buffer, 16); + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; +} + +static UINT8 CpuIedSig[] = {'I','N','T','E','L',' ','R','S','V','D'}; + +VOID CPU_SmmMemoryInit(IN SMM_HOB *SmmHob) +{ + UINT8 *IedStart; + UINT32 IedSize; + + if (!SmmHob->IedStart) return; + + IedStart = (UINT8*)SmmHob->IedStart; + IedSize = SmmHob->IedSize; + + MemCpy(IedStart, CpuIedSig, sizeof(CpuIedSig)); + *(UINT32*)(IedStart + 10) = IedSize; + + *(UINT16*)(IedStart + 14) = 0; //Reserved + *(UINT64*)(IedStart + 16) = 0; //Trace memory for Nehalem-EX. + + MemSet(IedStart + 24, 24, 0); //Reserved +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsSwSmiTrigger +// +// Description: This routine checks to see if the cpu caused an software smi. +// +// Input: +// UINT8 *SmmBase +// UINT16 SwSmiPort +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsSwSmiTrigger(UINT8 *SmmBase, UINT16 SwSmiPort) +{ + UINT32 IO_MISC_INFO = *(UINT32*)(SmmBase + 0xffa4); + if (!(IO_MISC_INFO & 1)) return FALSE; //For valid data, this should be 1. + return (*((UINT16*)&IO_MISC_INFO + 1) == SwSmiPort); //[31:16] +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + + diff --git a/Core/CPU/CpuDxe.c b/Core/CPU/CpuDxe.c new file mode 100644 index 0000000..9bd4f52 --- /dev/null +++ b/Core/CPU/CpuDxe.c @@ -0,0 +1,2096 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxe.c 21 6/11/15 10:33p Crystallee $ +// +// $Revision: 21 $ +// +// $Date: 6/11/15 10:33p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxe.c $ +// +// 21 6/11/15 10:33p Crystallee +// [TAG] EIP207854 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Txt test fail with TCG2 module +// [RootCause] Tokne TCG_SUPPORT was removed. +// [Solution] Add TCG2Support token. +// +// 20 5/24/15 11:36p Davidhsieh +// [TAG] EIP215675 +// [Category] New Feature +// [Description] Smm Access Check feautre support +// [Files] Cpu.sdl, CpuDxe.c, CpuSpSmi.sdl, CpuSpsmi.c +// +// 19 8/28/13 6:00a Crystallee +// [TAG] EIP134339 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] [Sharkbay]Build error after update Haswell Cpu module +// [RootCause] If token TCG_SUPPORT is disabled, TpmSupport setup data +// will not define, then cause built error. +// [Solution] Add token TCG_SUPPORT condition when use TpmSupport setup +// data. +// +// 18 7/23/13 7:45a Crystallee +// [TAG] EIP128089 +// [Category] Improvement +// [Description] TXT will be disabled and grayed out in Setup when TPM +// Support is disabled. +// +// 17 3/20/13 2:49a Crystallee +// [TAG] EIP118478 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] AES-NI setup item disappear after set ASN-NI to disable. +// [RootCause] We determine AES support from the ASE support bit in +// CPUID function 1, but it will change with AES MSR. +// [Solution] Determine AES support before CPU RC DXE initialize. +// +// 16 2/27/13 5:00a Crystallee +// [TAG] EIP115822 +// [Category] Improvement +// [Description] Add SMBIOS type7 information for L4 cache if CPU +// supported +// And create a token to control this. +// +// 15 2/22/13 2:07a Crystallee +// [TAG] EIP112238 +// [Category] Improvement +// [Description] Refer Intel BIOS and provide setup items for Intel +// Haswell RC policy. +// +// 14 12/18/12 7:09a Davidhsieh +// [TAG] EIP93180 +// [Category] Improvement +// [Description] Do not create timer callback to clear +// direction flag, clear direction flag operation is in interrupt entry. +// +// 13 11/23/12 4:19a Davidhsieh +// [TAG] None +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Ctdp setup item is not displayed in setup menu +// [RootCause] The cTDPAvailable value is not initialzied +// [Solution] Initial cTDPAvailable value +// +// 12 11/08/12 6:18a Davidhsieh +// [TAG] EIP105401 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] CpuSignature and FeatureFlags of MPS table are incorrect +// [RootCause] Cpu Signature and FeatureFlags in CpuInfo are +// not initialized +// [Solution] Initialize Cpu Signature and FeatureFlags in +// CpuInfo +// +// 11 11/07/12 4:36a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] L4 Cache support improve +// +// 10 10/17/12 2:20a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Setup items CTDP BIOS, C8, C9 and C10 created +// +// 9 10/17/12 1:58a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] L4 cache support +// +// 8 9/26/12 10:53a Davidhsieh +// [TAG] None +// [Description] Add CPU APIC ID data variable for S3 resume +// +// 7 7/10/12 2:48a Davidhsieh +// [TAG] EIP93180 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] The "Event Kernel-Power 137" error event log shows while +// resumed from HS3/S3 in Windows8 (not-UEFI boot mode) +// [RootCause] The save MTRRs action is too early, the saved value is +// differnet from the value in OS +// [Solution] Move the MTRR save action to AMI_LEGACYBOOT event +// +// 6 5/20/12 11:38p Davidhsieh +// [TAG] EIP89382 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] System hangs when booting to UEFI Red Hat Linux OS with +// Network cable plugged in +// [RootCause] Red Hat Linux OS sets ¡§Direction Flag¡¨ and clears it +// immediately after few instructions. But before it has been cleared, +// Timer interrupt has been generated and MemSet () has function has been +// called inside UEFINetworkStack Timer callback handler. As the +// "Direction flag" is set ¡§MemSet¡¨ function stores data in reverse +// direction which results in data corruption. +// [Solution] Timer Callback function has been created with Higher +// priority level (TPL_NOTIFY + 14) and "direction flag" has been cleared +// inside the callback function. +// +// 5 5/17/12 9:34p Davidhsieh +// [TAG] EIP89591 +// [Category] Improvement +// [Description] Make the CPU wakup buffer locatioin depends on token +// PMM_EBDA_LOMEM_SIZE +// +// 4 3/20/12 3:22a Davidhsieh +// Create SMBIOS type4 and type7 in AMI CPU module part +// +// 3 3/16/12 3:11a Davidhsieh +// Setup items create for CPU RC policy +// +// 2 2/23/12 2:06a Davidhsieh +// [TAG] EIP72056 +// [Category] Improvement +// [Description] Change EFI_MP_PROC_CONTEXT to follow Intel CPU driver +// +// 1 2/07/12 3:58a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuDxe.c +// +// Description: +// Installs CPU Architectural Protocol. +// processor interrupt vector table. The CPU Architectural +// Protocol enables/disables/get state of interrupts, set +// memory range cache type, and installs/uninstalls +// interrupt handlers. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <token.h> +#include <AmiCspLib.h> +#include <Protocol\AmiCpuInfo.h> +#include <Protocol\DxeSmmReadyToLock.h> +#include "CpuDxe.h" +#include "PlatformCpuLib.h" + +#ifdef CSM_SUPPORT +#include <Protocol\LegacyBiosExt.h> +EFI_GUID gAmiLegacyBootProtocolGuid = EFI_AMI_LEGACYBOOT_PROTOCOL_GUID; +#endif + +#if AMI_PEI_DEBUG_SUPPORT +#include "PeiDbgDxeCpuLib.h" + +#define AMI_DEBUGGER_CPU_PROTOCOL_GUID \ + { 0xab21acc3, 0xba33, 0xee2c, 0x66, 0xbc, 0x12, 0x56, 0x77, 0x11, 0x1a, 0xb2 } + +typedef struct _AMI_DEBUGGER_CPU_PROTOCOL AMI_DEBUGGER_CPU_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *DEBUGGER_GET_APTIO_INT_HANDLER) ( + IN OUT UINT32* InterruptHandlerHaltAddr + ); + +typedef +EFI_STATUS +(EFIAPI *DEBUGGER_FIXUP_PEI_EXCEPTION_HANDLER) ( + IN IDTEntry_T* IdtEntry, + IN UINT32 i + ); + +typedef +EFI_STATUS +(EFIAPI *DEBUGGER_SETUP_EXCEPTION_HANDLER) (VOID); + +typedef +EFI_STATUS +(EFIAPI *DEBUGGER_IS_DEBUGGER_IRQ_HANDLER) ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + +typedef struct _AMI_DEBUGGER_CPU_PROTOCOL { + DEBUGGER_GET_APTIO_INT_HANDLER DebuggerGetAptioIntHandler; + DEBUGGER_FIXUP_PEI_EXCEPTION_HANDLER DebuggerFixUpPEIExceptionHandlers; + DEBUGGER_SETUP_EXCEPTION_HANDLER DebuggerSetupExceptionHandler; + DEBUGGER_IS_DEBUGGER_IRQ_HANDLER DebuggerIsDebuggerIrqHadler; +}; + + +#endif + +#define DELAY_CALCULATE_CPU_PERIOD 200 //uS + +#if CPU_MODULE_CREATE_SMBIOS_TABLES == 1 +VOID CpuSmbios(); +#endif + +#define AMI_BEFORE_CPU_RC_PROTOCOL_GUID \ + { 0x1d26adc3, 0xb011, 0xee2c, 0x21, 0x77, 0x89, 0xbb, 0xaa, 0xcc, 0x33, 0x92 } + +// Add EFI_MP_PROC_CONTEXT_FROM_RC relavant structures +typedef struct { + UINT32 ApicID; + BOOLEAN Enabled; + EFI_CPU_DESIGNATION Designation; + EFI_MP_HEALTH Health; + UINTN PackageNumber; + UINTN NumberOfCores; + UINTN NumberOfThreads; + UINT64 ProcessorPALCompatibilityFlags; + UINT64 ProcessorTestMask; +} EFI_MP_PROC_CONTEXT_FROM_RC; + +UINT32 *FindPtrToPrivCpuInfoPkg( + IN UINT32 Package +); + +EFI_GUID gHobListGuid = HOB_LIST_GUID; +EFI_GUID gEfiMpServicesProtocolGuid = EFI_MP_SERVICES_PROTOCOL_GUID; +EFI_GUID gAmiCpuinfoHobGuid = AMI_CPUINFO_HOB_GUID; +EFI_GUID gAmiCpuInfoProtocolGuid = AMI_CPU_INFO_PROTOCOL_GUID; +EFI_GUID gAmiCpuInfo2ProtocolGuid = AMI_CPU_INFO_2_PROTOCOL_GUID; +EFI_GUID gAmiBeforeCpuRcProtocolGuid = AMI_BEFORE_CPU_RC_PROTOCOL_GUID; +EFI_GUID gMpCpuApicIdDataGuid = MP_CPU_APIC_ID_DATA_GUID; +#if AMI_PEI_DEBUG_SUPPORT +EFI_GUID gAmiDebuggerCpuProtocolGuid = AMI_DEBUGGER_CPU_PROTOCOL_GUID; +#endif +EFI_MP_SERVICES_PROTOCOL *gEfiMpServicesProtocol; +EFI_MP_PROC_CONTEXT_FROM_RC *gEfiMpProcContext; + +UINTN gNumOfCpus; +UINTN gMaximumNumberOfCPUs; +UINTN gNumberOfEnabledCPUs; +UINTN gRendezvousIntNumber; +UINTN gRendezvousProcLength; + +UINT32 gNumOfCpuCores; +UINT32 gNumOfThreads; + +UINT32 gRegEax, gRegEbx, gRegEcx, gRegEdx; + +EFI_EVENT gAmiMpEvent; +VOID *gAmiMpEventRegistration = 0; + +EFI_EVENT gSmmFeaEnEvent; +VOID *gSmmFeaEnReg = 0; + +static VOID *gAcpiData; +static UINT32 gAcpiDataNumEntries; + +static CHAR8 gProcObjPath = '\0'; + +CPUINFO_HOB *gCpuInfoHob; +AMI_CPU_INFO *gAmiCpuInfo; +VOID *gSetupHandle; +CPU_FEATURES gCpuFeatures; +EFI_PHYSICAL_ADDRESS gTempBuffer; +BOOLEAN IsFreeMemBelow1MB; + +VOID CreatePrivateAmiCpuInfo2(); +UINT32 * GetPtrToPrivateAmiCpuInfo2Entry( + IN UINT32 Package, + IN UINT32 Core, + IN UINT32 Thread +); + +#if AMI_PEI_DEBUG_SUPPORT +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: InterruptHandlerHalt +// +// Description: Default CPU Exception. Halts CPU. +// +// Input: +// IN EFI_EXCEPTION_TYPE Exception +// IN EFI_SYSTEM_CONTEXT Context +// +// Output: +// VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID InterruptHandlerHalt(EFI_EXCEPTION_TYPE Exception,EFI_SYSTEM_CONTEXT Context) +{ + ERROR_CODE(EFI_SOFTWARE_IA32_EXCEPTION | (UINT32)Exception, EFI_ERROR_MAJOR); + checkpoint((UINT8)Exception); + TRACE((TRACE_DXE_CPU,"ERROR: CPU Exception %X\n",Exception)); + EFI_DEADLOOP(); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: DebuggerGetAptioInterruptHandlerHalt +// +// Description: +// +// Input: +// +// +// +// Output: +// VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DebuggerGetAptioInterruptHandlerHalt( + IN OUT UINT32* InterruptHandlerHaltAddr +) +{ + + *InterruptHandlerHaltAddr = (UINT32)InterruptHandlerHalt; + TRACE((TRACE_DXE_CPU,"InterruptHandlerHalt = %X\n",InterruptHandlerHalt)); + return EFI_SUCCESS; + +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: DebuggerIsItPEIDebugIRQHandlerToHookup +// +// Description: +// +// Input: +// +// +// +// Output: +// VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DebuggerFixUpPEIDebuggerExceptionHandlers( + IN IDTEntry_T* IdtEntry, + IN UINT32 i +) +{ + + FixUpPEIDebuggerExceptionHandlers((IDTEntry_T*)IdtEntry,i); + return EFI_SUCCESS; + +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: DebuggerSetupPEIDebuggerExceptionHandlers +// +// Description: +// +// Input: +// +// +// Output: +// +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DebuggerSetupPEIDebuggerExceptionHandlers(VOID) +{ + + SetupPEIDebuggerExceptionHandlers( ); + return EFI_SUCCESS; + +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: DebuggerIsItPEIDebugIRQHandlerToHookup +// +// Description: +// +// Input: +// +// +// +// Output: +// VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DebuggerIsItPEIDebugIRQHandlerToHookup( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler) +{ + + IsItPEIDebugIRQHandlerToHookup(InterruptType,InterruptHandler); + return EFI_SUCCESS; + +} +#endif +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CalculateTimerPeriod +// +// Description: Calculate CPU time period. +// +// Input: VOID +// +// Output: +// UINT64 Timer Period +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT64 CalculateTimerPeriod() +{ + UINT64 Timer1; + UINT64 Timer2; + + EFI_TPL OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL); + + Timer1 = ReadRtdsc(); + + pBS->Stall(DELAY_CALCULATE_CPU_PERIOD); + + Timer2 = ReadRtdsc(); + + pBS->RestoreTPL(OldTpl); + + return Div64(DELAY_CALCULATE_CPU_PERIOD * (UINT64)1000000000, (UINT32)(Timer2-Timer1),NULL); //50us * 10E15 femtosec; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetCpuInfo +// +// Description: Protocol function to get Cpu Info. +// +// Input: +// IN AMI_CPU_INFO_PROTOCOL *This +// IN UINTN Cpu +// OUT AMI_CPU_INFO **Info +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetCpuInfo( + IN AMI_CPU_INFO_PROTOCOL *This, + IN UINTN Cpu, + OUT AMI_CPU_INFO **Info +) +{ + if (Cpu >= gNumOfCpus) return EFI_INVALID_PARAMETER; + *Info = &gAmiCpuInfo[Cpu]; + return EFI_SUCCESS; +} + +AMI_CPU_INFO_PROTOCOL gAmiCpuInfoProtocol = {GetCpuInfo}; + +static CACHE_DESCRIPTOR_INFO gZeroCacheDesc = {0, 0, 0, 0, 0}; + +typedef struct { + UINT32 NumCores; //Number of cores in Package. + UINT32 NumEntries; //Each cache descriptor should have same number of entries, max of 4. + AMI_CPU_INFO_2_CACHE_DESCR PkgCacheDesc[4]; //Total of the cores + AMI_CPU_INFO_2_CACHE_DESCR CoreCacheDesc[4]; //Internal implementation assumes symmetry among cores. + //If this every changes, internal implementation will be updated. +} PKG_CACHE_DESCR; + +static PKG_CACHE_DESCR *gPkgCacheDesc; //Array of Package Cache Descriptions. + + +typedef struct { + UINT32 CacheType:5; + UINT32 CacheLevel:3; + UINT32 NotUsed:24; +} CPUID4_EAX_CACHE_INFO; + +typedef struct { + UINT32 LineSize:12; + UINT32 Partitions:10; + UINT32 Ways:10; +} CPUID4_EBX_CACHE_INFO; + +#define MAX_NUM_CACHE_DESC 8 + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: FindPtrToPrivCpuInfoPkg +// +// Description: Pointer to internal Package information. +// +// Input: +// IN UINT32 PkgPtr -- Internal package information. +// +// Output: UINT32 * -- Internal Core information. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 *FindPtrToPrivCpuInfoPkg( + IN UINT32 Package +) +{ + UINT32 *p = (UINT32*)(gPrivateAmiCpuInfo2 + 1); + UINT32 i; + + if (Package >= *p) return (UINT32*)-1; //Package does not exist. + p++; //now p = Num cores of package 0. + + //Skip entries for previous packages. + for (i = 0; i < Package; ++i) { + UINT32 NumCores = *p++; //p = now number of threads + UINT32 j; + for (j = 0; j < NumCores; ++j) { + UINT32 NumThreads = *p++; + p += NumThreads * PRIVATE_INFO_NUM_OF_CPU_DATA; + } + } + return p; +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: FindPtrToPrivCpuInfoCore +// +// Description: Pointer to internal Core information. +// +// Input: +// IN UINT32* PkgPtr -- Internal package information. +// IN UINT32 Core +// +// Output: UINT32 * -- Internal Core information. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 *FindPtrToPrivCpuInfoCore( + IN UINT32 *PkgPtr, + IN UINT32 Core +) +{ + UINT32 *p = PkgPtr; + UINT32 NumCores = *p++; + UINT32 i; + if (Core >= NumCores) return (UINT32*)-1; //Core does not exist. + + //Skip previous cores. + for (i = 0; i < Core; ++i) { + UINT32 NumThreads = *p++; + p += NumThreads * PRIVATE_INFO_NUM_OF_CPU_DATA; + } + return p; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: FindPtrToPrivCpuInfoThread +// +// Description: Pointer to internal Core information. +// +// Input: +// IN UINT32* CorePtr -- Internal core information. +// IN UINT32 Thread +// +// Output: UINT32 * -- Internal thread information. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 *FindPtrToPrivCpuInfoThread( + IN UINT32 *CorePtr, + IN UINT32 Thread +) +{ + UINT32 *p = CorePtr; + UINT32 NumThreads = *p++; + if (Thread >= NumThreads) return (UINT32*)-1; //Thread does not exist. + p += Thread * PRIVATE_INFO_NUM_OF_CPU_DATA; + return p; +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetBoardSocketNumber +// +// Description: Get socket number from Apic ID. +// +// Input: +// IN UINT32 ApicId +// +// Output: UINT32 - Physical Socket Id +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 GetBoardSocketNumber(IN UINT32 ApicId) +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT8 MaxThreadsPackage; + + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + + MaxThreadsPackage = (UINT8)(RegEbx >> 16); + + return ApicId / MaxThreadsPackage; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetNumPackages +// +// Description: Get the number of packages populated and sockets. +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This +// OUT UINT32 *NumPopulatedPackages +// OUT UINT32 *NumBoardSockets OPTIONAL +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetNumPackages( + IN AMI_CPU_INFO_2_PROTOCOL *This, + OUT UINT32 *NumPopulatedPackages, + OUT UINT32 *NumBoardSockets OPTIONAL +) +{ + //First entry after protocol functions is number of discovered packages. + /*UINT32 *p = (UINT32*)(gPrivateAmiCpuInfo2 + 1); + + *NumPopulatedPackages = *p; + //NUMBER_CPU_SOCKETS must be ported if more than 1 socket. + ASSERT(*NumPopulatedPackages <= NUMBER_CPU_SOCKETS); + if (NumBoardSockets) { + *NumBoardSockets = NUMBER_CPU_SOCKETS; + + //In case of porting error, Board sockets can never be less than Populated packages. + if (*NumPopulatedPackages > *NumBoardSockets) *NumBoardSockets = *NumPopulatedPackages; + }*/ + + if(NumPopulatedPackages == NULL) + return EFI_INVALID_PARAMETER; + + *NumPopulatedPackages = 1; + + if (NumBoardSockets) + *NumBoardSockets = 1; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetNumCoresThreads +// +// Description: Get the number of Cores +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This, +// IN UINT32 Package +// OUT UINT32 *NumEnabledCores +// OUT UINT32 *NumEnabledThreads - This value is total for package. +// OUT UINT32 *NumDisabledCores OPTIONAL -- Flag must be set in Protocol. +// OUT UINT32 *NumEnabledThreads OPTIONAL -- Flag must be set in Protocol. +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetNumCoresThreads( + IN AMI_CPU_INFO_2_PROTOCOL *This, + IN UINT32 Package, + OUT UINT32 *NumEnabledCores, + OUT UINT32 *NumEnabledThreads, + OUT UINT32 *NumDisabledCores OPTIONAL, + OUT UINT32 *NumDisabledThreads OPTIONAL +) +{ + UINT32 *p = FindPtrToPrivCpuInfoPkg(Package); + UINT32 TotNumCores; + UINT32 TotNumThreads = 0; + UINT32 i; + + if (NumEnabledCores == NULL || NumEnabledThreads == NULL) + return EFI_INVALID_PARAMETER; + + if (p == (UINT32*) -1) return EFI_INVALID_PARAMETER; + + //After package is number of cores. + TotNumCores = *p++; + for (i = 0; i < TotNumCores; ++i) { + UINT32 NumThreads = *p++; //After core is Number of Threads + TotNumThreads += NumThreads; + p += NumThreads * PRIVATE_INFO_NUM_OF_CPU_DATA; //APIC ID and CPU NUM; + } + + *NumEnabledCores = TotNumCores; + *NumEnabledThreads = TotNumThreads; + + if (NumDisabledCores) *NumDisabledCores = 0; //Flag not set in Protocol. + if (NumDisabledThreads) *NumDisabledThreads = 0; //Flag not set in Protocol.*/ + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetNumThreads +// +// Description: Get the number of Threads +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This +// IN UINT32 Package +// IN UINT32 Core +// OUT UINT32 *NumEnabledThreads +// OUT UINT32 *NumDisabledThreads OPTIONAL -- Flag must be set if valid +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetNumThreads( + IN AMI_CPU_INFO_2_PROTOCOL *This, + IN UINT32 Package, + IN UINT32 Core, + OUT UINT32 *NumEnabledThreads, + OUT UINT32 *NumDisabledThreads OPTIONAL +) +{ + UINT32 *p = FindPtrToPrivCpuInfoPkg(Package); + + if (NumEnabledThreads == NULL) return EFI_INVALID_PARAMETER; + + if (p == (UINT32*) -1) return EFI_INVALID_PARAMETER; + + p = FindPtrToPrivCpuInfoCore(p, Core); + if (p == (UINT32*) -1) return EFI_INVALID_PARAMETER; + + *NumEnabledThreads = *p; + if (NumDisabledThreads) *NumDisabledThreads = 0; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetSbsp +// +// Description: Get SBSP +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This +// OUT UINT32 *Package +// OUT UINT32 *Core +// OUT UINT32 *Thread +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetSbsp( + IN AMI_CPU_INFO_2_PROTOCOL *This, + OUT UINT32 *Package, + OUT UINT32 *Core, + OUT UINT32 *Thread +) +{ + //Desktop system, it must be package0, core0, thread0 + if (Package == NULL || Core == NULL || Thread == NULL) + return EFI_INVALID_PARAMETER; + + *Package = 0; + *Core = 0; + *Thread = 0; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetApicInfo +// +// Description: Get Apic Number and Version +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This +// IN UINT32 Package +// IN UINT32 Core +// IN UINT32 Thread +// OUT UINT32 *ApicId +// OUT UINT32 *ApicVer OPTIONAL +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetApicInfo( + IN AMI_CPU_INFO_2_PROTOCOL *This, + IN UINT32 Package, + IN UINT32 Core, + IN UINT32 Thread, + OUT UINT32 *ApicId, + OUT UINT32 *ApicVer OPTIONAL +) +{ + UINT32 *p = GetPtrToPrivateAmiCpuInfo2Entry( + Package, Core, Thread); + UINT32 CpuNum; + + if (ApicId == NULL) return EFI_INVALID_PARAMETER; + + if (p == (UINT32*) -1) return EFI_INVALID_PARAMETER; + + //p points to 32-bit APIC ID and 32-bit CPU Num for internal structures. + + *ApicId = *p++; + + if (ApicVer) { + CpuNum = *p; + *ApicVer = (UINT8)MemRead32((UINT32*)(UINTN)(LOCAL_APIC_BASE + APIC_VERSION_REGISTER)); + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetAcpiInfo +// +// Description: Get Cpu ACPI information. +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This +// OUT VOID **AcpiData - ACPI Data +// OUT UINT32 *NumEntries - Number of Entries in data. +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetAcpiInfo( + IN AMI_CPU_INFO_2_PROTOCOL *This, + OUT VOID **AcpiData, + OUT UINT32 *NumEntries +) +{ + if (AcpiData == NULL || NumEntries == NULL) + return EFI_INVALID_PARAMETER; + + *AcpiData = gAcpiData; + *NumEntries = gAcpiDataNumEntries; + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetPackageCacheDescr +// +// Description: Get the package Cache Information +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This +// IN UINT32 Package - Socket number. Intenal socket number (continous) +// OUT AMI_CPU_INFO_2_CACHE_DESCR **Description - Updates pointer to pointer with pointer to Cache information. +// OUT UINT32 *NumEntries - Number of AMI_CPU_INFO_2_CACHE_DESCR Entries. +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetPackageCacheDescr( + IN AMI_CPU_INFO_2_PROTOCOL *This, + IN UINT32 Package, + OUT AMI_CPU_INFO_2_CACHE_DESCR **Description, + OUT UINT32 *NumEntries +) +{ + PKG_CACHE_DESCR *PkgCacheDesc; + + if (Package >= NumberOfCpuSocketsPopulated()) return EFI_INVALID_PARAMETER; + + if (Description == NULL || NumEntries == NULL) + return EFI_INVALID_PARAMETER; + + PkgCacheDesc = &gPkgCacheDesc[Package]; + *Description = &PkgCacheDesc->PkgCacheDesc[0]; + *NumEntries = PkgCacheDesc->NumEntries; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetCoreCacheDescr +// +// Description: Get the Core Cache Information +// +// Input: +// IN AMI_CPU_INFO_2_PROTOCOL *This +// IN UINT32 Package - Socket number. Internal socket number (continous) +// IN UINT32 Core - Core number. Internal core number (continous) +// OUT AMI_CPU_INFO_2_CACHE_DESCR **Description - Updates pointer to pointer with pointer to Cache information. +// OUT UINT32 *NumEntries - Number of AMI_CPU_INFO_2_CACHE_DESCR Entries. +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetCoreCacheDescr( + IN AMI_CPU_INFO_2_PROTOCOL *This, + IN UINT32 Package, + IN UINT32 Core, + OUT AMI_CPU_INFO_2_CACHE_DESCR **Description, + OUT UINT32 *NumEntries +) +{ + PKG_CACHE_DESCR *PkgCacheDesc; + + if (Package >= NumberOfCpuSocketsPopulated()) return EFI_INVALID_PARAMETER; + + if (Description == NULL || NumEntries == NULL) + return EFI_INVALID_PARAMETER; + + PkgCacheDesc = &gPkgCacheDesc[Package]; + + if (Core >= PkgCacheDesc->NumCores) return EFI_INVALID_PARAMETER; + + *Description = &PkgCacheDesc->CoreCacheDesc[0]; + *NumEntries = PkgCacheDesc->NumEntries; + return EFI_SUCCESS; +} + +PRIVATE_AMI_CPU_INFO_2_PROTOCOL PrivateAmiCpuInfo2Init = { + { + 1, //ProtocolVer + 0, //Flags + GetNumPackages, + GetNumCoresThreads, + GetNumThreads, + GetSbsp, + GetApicInfo, + GetAcpiInfo, + GetPackageCacheDescr, + GetCoreCacheDescr + } + //Additional information will allocated. +}; + +PRIVATE_AMI_CPU_INFO_2_PROTOCOL *gPrivateAmiCpuInfo2; + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SizeOfPrivateAmiCpuInfo2 +// +// Description: Size of Private Ami Cpu Info 2 structure to be allocated. +// +// Input: VOID +// +// Output: UINT32 -- Size +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 SizeOfPrivateAmiCpuInfo2() +{ + //See PRIVATE_AMI_CPU_INFO_2_PROTOCOL defintion for comments on internal CPU information. + + UINT32 Size = sizeof(AMI_CPU_INFO_2_PROTOCOL); + UINT32 NumSockets = 1; + UINT32 CpuNum = 0; + UINT32 j; + + Size += sizeof(UINT32); //Number of populated sockets entry. + Size += sizeof(UINT32); //Number of cores for socket; + for (j = 0; j < gNumOfCpuCores; ++j) { + Size += sizeof(UINT32); //Number of thread per core. + Size += gNumOfThreads * sizeof(UINT32) * PRIVATE_INFO_NUM_OF_CPU_DATA; //APIC ID and CPU NUM; + CpuNum += gNumOfThreads; + ASSERT(CpuNum <= gNumOfCpus); + } + return Size; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: FillPrivateAmiCpuInfo2 +// +// Description: Fill CPU information in Private Ami Cpu Info structure. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID FillPrivateAmiCpuInfo2() +{ + //See PRIVATE_AMI_CPU_INFO_2_PROTOCOL defintion for comments on internal CPU information. + + UINT32 *p = (UINT32*)(gPrivateAmiCpuInfo2 + 1); + UINT32 NumSockets = 1; + UINT32 CpuNum = 0; + UINT32 i; + UINT32 j; + UINT32 k; + + *gPrivateAmiCpuInfo2 = PrivateAmiCpuInfo2Init; + *p++ = NumSockets; + for (i = 0; i < NumSockets; ++i) { + *p++ = gNumOfCpuCores; + for (j = 0; j < gNumOfCpuCores; ++j) { + *p++ = gNumOfThreads; + for (k = 0; k < gNumOfThreads; ++k) { + *p++ = gEfiMpProcContext[CpuNum].ApicID; + *p++ = CpuNum; + ++CpuNum; + ASSERT(CpuNum <= gNumOfCpus); + } + } + } +} + + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetPtrToPrivateAmiCpuInfo2Entry +// +// Description: Get pointer to APIC/Cpu Num +// +// Input: +// IN UINT32 Package +// IN UINT32 Core +// IN UINT32 Thread +// +// Output: UINT32 * +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 * GetPtrToPrivateAmiCpuInfo2Entry( + IN UINT32 Package, + IN UINT32 Core, + IN UINT32 Thread +) +{ + UINT32 *p; + + p = FindPtrToPrivCpuInfoPkg(Package); + if (p == (UINT32*) -1) return (UINT32*)-1; //Package does not exist. + + p = FindPtrToPrivCpuInfoCore(p, Core); + if (p == (UINT32*) -1) return (UINT32*)-1; //Core does not exist. + + p = FindPtrToPrivCpuInfoThread(p, Thread); + return p; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetCpuPkgCoreThrdByNum +// +// Description: Get CPU Package/Core/Thread by CPU Number. Number sequencial to APIC ID. +// +// Input: +// IN UINT32 CpuNum +// OUT UINT32 *Package +// OUT UINT32 *Core +// OUT UINT32 *Thread +// +// Output: BOOLEAN -- If found, return TRUE. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN GetCpuPkgCoreThrdByNum( + IN UINT32 CpuNum, + OUT UINT32 *Package, + OUT UINT32 *Core, + OUT UINT32 *Thread +) +{ + UINT32 *p = (UINT32*)(gPrivateAmiCpuInfo2 + 1); + UINT32 NumPkgs = *p++; + UINT32 Pkg; + + for (Pkg = 0; Pkg < NumPkgs; ++Pkg) { + UINT32 NumCores = *p++; + UINT32 Cor; + for (Cor = 0; Cor < NumCores; ++Cor) { + UINT32 NumThrds = *p++; + UINT32 Thrd; + for (Thrd = 0; Thrd < NumThrds; ++Thrd) { + ++p; //Skip ApicId; + if (*p++ == CpuNum) { + *Package = Pkg; + *Core = Cor; + *Thread = Thrd; + return TRUE; + } + } + } + } + return FALSE; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: FillAcpiData +// +// Description: Fill ACPI Data structure +// +// Input: +// IN ACPI_PROCESSOR_INFO *AcpiProcData +// IN UINT32 Package +// IN UINT32 Core +// IN UINT32 Thread +// IN BOOLEAN Bsp +// +// Output: BOOLEAN -- If filled, return TRUE. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN FillAcpiData( + OUT ACPI_PROCESSOR_INFO *AcpiProcData, + IN UINT32 Package, + IN UINT32 Core, + IN UINT32 Thread, + IN BOOLEAN Bsp +) +{ + UINT32 ApicId; + UINT32 CpuNum; + UINT32 CpuSignature, CpuIdEBX, CpuIdECX, FeatureFlags; + + static UINT32 ProcId = 1; + + UINT32 *ptr = GetPtrToPrivateAmiCpuInfo2Entry(Package, Core, Thread); + if (ptr == (UINT32*) -1) return FALSE; + //ptr points to 32-bit APIC ID and 32-bit CPU Num for internal structures. + + ApicId = *ptr++; + CpuNum = *ptr; + CPULib_CpuID(1, &CpuSignature, &CpuIdEBX, &CpuIdECX, &FeatureFlags); + + AcpiProcData->Type = ACPI_PROCESSOR_INFO_TYPE; //0 + AcpiProcData->Length = sizeof(ACPI_PROCESSOR_INFO); + AcpiProcData->Enable = 1; + AcpiProcData->Bsp = Bsp; + AcpiProcData->Package = Package; + AcpiProcData->Core = Core; + AcpiProcData->Thread = Thread; + AcpiProcData->ApicId = ApicId; //LAPIC number for processor. + //AcpiProcData->ApicVer = gCpuInfoHob->Cpuinfo[CpuNum].ApicVer; + AcpiProcData->ApicVer = (UINT8)MemRead32((UINT32*)(UINTN)(LOCAL_APIC_BASE + APIC_VERSION_REGISTER)); + AcpiProcData->CpuSignature = CpuSignature; + AcpiProcData->FeatureFlags = FeatureFlags & (BIT0 | BIT7 | BIT8 | BIT9); + AcpiProcData->ProcId = ProcId; //ASL processor object ID. + //AcpiProcData->ProcObjPath = (EFI_PHYSICAL_ADDRESS)(UINTN)&gProcObjPath; //ASL processor object ID. + AcpiProcData->LocalApicType = FALSE; //All processors will either be xAPIC or x2APIC Mode not mixed. + ++ProcId; + return TRUE; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: AddLocalApicCoreEntries +// +// Description: Create Private Ami Cpu Info2 Acpi Data. +// +// Input: +// IN UINT32 Package - Processor package +// IN UINT32 Thread - Processor thread (usually either 0 or 1 for HT) +// +// Output: BOOLEAN - TRUE if any entries added. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN AddLocalApicCoreEntries( + IN UINT32 Package, + IN UINT32 Thread, + IN BOOLEAN Bsp, + IN UINT32 BspCore +){ + UINT32 NumEnabledCores; + UINT32 NumEnabledThreads; + UINT32 Core; + BOOLEAN ValidEntry; + AMI_CPU_INFO_2_PROTOCOL *AmiCpu2Info = (AMI_CPU_INFO_2_PROTOCOL*)gPrivateAmiCpuInfo2; + ACPI_PROCESSOR_INFO *AcpiProcData = (ACPI_PROCESSOR_INFO *)gAcpiData; + static UINT32 Entry = 0; + + AmiCpu2Info->GetNumCoresThreads(AmiCpu2Info, Package, &NumEnabledCores, &NumEnabledThreads, NULL, NULL); + NumEnabledThreads = NumEnabledThreads / NumEnabledCores; + + if (Thread >= NumEnabledThreads) return FALSE; //Different packages could have different numbers of threads; + + ValidEntry = FillAcpiData( + &AcpiProcData[Entry], + Package, + BspCore, + Thread, + Bsp && Thread == 0 + ); + if (ValidEntry) ++Entry; + + for (Core = 0; Core < NumEnabledCores; ++Core) { + if (Core == BspCore) continue; + ValidEntry = FillAcpiData( + &AcpiProcData[Entry], + Package, + Core, + Thread, + FALSE + ); + if (ValidEntry) ++Entry; + } + + return TRUE; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CreateAcpiData +// +// Description: Create Private Ami Cpu Info2 Acpi Data. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CreateAcpiData() +{ + EFI_STATUS Status; + UINT32 Package; + UINT32 Thread; + UINT32 BspPackage; + UINT32 BspCore; + UINT32 BspThread; + UINT32 MaxPackages; + BOOLEAN ProcessedEntries; + AMI_CPU_INFO_2_PROTOCOL *AmiCpu2Info = (AMI_CPU_INFO_2_PROTOCOL*)gPrivateAmiCpuInfo2; + + gAcpiDataNumEntries = (UINT32)gNumOfCpus; + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(ACPI_PROCESSOR_INFO) * gNumOfCpus, &gAcpiData); + ASSERT_EFI_ERROR(Status); + + Status = AmiCpu2Info->GetSbsp( + AmiCpu2Info, + &BspPackage, + &BspCore, + &BspThread + ); + ASSERT_EFI_ERROR(Status); + + Status = AmiCpu2Info->GetNumPackages(AmiCpu2Info, &MaxPackages, NULL); + ASSERT_EFI_ERROR(Status); + Thread = 0; //Thread count for a core. + + do { //Thread + ProcessedEntries = FALSE; + + //Bsp is always first entry. + if (AddLocalApicCoreEntries(BspPackage, Thread, TRUE, BspCore)) + ProcessedEntries = TRUE; + + for (Package = 0; Package < MaxPackages; ++Package) { + if (Package == BspPackage) continue; + if (AddLocalApicCoreEntries(Package, Thread, FALSE, BspCore)) + ProcessedEntries = TRUE; + } + ++Thread; + } while (ProcessedEntries); //No more threads +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetCacheSharedThreads +// +// Description: Return number of shared threads for a Information. +// +// Input: IN UINT8 Level - Cache level +// +// Output: UINT8 - Number of shared threads. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 GetCacheSharedThreads(IN UINT8 Level) +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT32 i = 0; + + for(;;) { + RegEcx = i; + CPULib_CpuID(4, &RegEax, &RegEbx, &RegEcx, &RegEdx); + if ((RegEax & 0x1f) == 0) break; + if (((RegEax >> 5) & 7) == Level) return 1 + ((RegEax >> 14)& 0xfff); + ++i; + } + return 0; +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CreateCacheData +// +// Description: Get Cache information. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CreateCacheData() +{ + AMI_CPU_INFO_2_PROTOCOL *AmiCpu2Info = (AMI_CPU_INFO_2_PROTOCOL*)gPrivateAmiCpuInfo2; + UINT32 NumPackages; + UINT32 Package; + UINT32 CpuNum; + EFI_STATUS Status; + + BOOLEAN IsLxSharedByPackage[5]; + + //Assume between CPUs on the board, similar cache sharing. Only like CPUs can power the board. + IsLxSharedByPackage[1] = GetCacheSharedThreads(1) > 2 ? TRUE: FALSE; + IsLxSharedByPackage[2] = GetCacheSharedThreads(2) > 2 ? TRUE: FALSE; + IsLxSharedByPackage[3] = GetCacheSharedThreads(3) > 2 ? TRUE: FALSE; + IsLxSharedByPackage[4] = GetCacheSharedThreads(4) > 2 ? TRUE: FALSE; + + Status = AmiCpu2Info->GetNumPackages(AmiCpu2Info, &NumPackages, NULL); + ASSERT_EFI_ERROR(Status); + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(PKG_CACHE_DESCR) * NumPackages, &gPkgCacheDesc); + ASSERT_EFI_ERROR(Status); + + MemSet(gPkgCacheDesc, sizeof(PKG_CACHE_DESCR) * NumPackages, 0); + + //Assume symmetry between the cores in a package. This never likely to change. + for(Package = 0, CpuNum = 0; CpuNum < gNumOfCpus; ++Package) { + AMI_CPU_INFO *AmiCpuInfo = &gAmiCpuInfo[CpuNum]; + PKG_CACHE_DESCR *PkgDesc = &gPkgCacheDesc[Package]; + CACHE_DESCRIPTOR_INFO *CacheInfo = AmiCpuInfo->CacheInfo; + UINT32 NumCores = AmiCpuInfo->NumCores; + UINT32 Entry = 0; + + ASSERT (Package < NumPackages); + + PkgDesc->NumCores = NumCores; + + while(CacheInfo->Desc != 0) { + AMI_CPU_INFO_2_CACHE_DESCR *PkgCacheDesc = &PkgDesc->PkgCacheDesc[Entry]; + AMI_CPU_INFO_2_CACHE_DESCR *CoreCacheDesc = &PkgDesc->CoreCacheDesc[Entry]; + + ASSERT(Entry < MAX_NUM_CACHE_DESC); + ASSERT(CacheInfo->Level < 5); + + CoreCacheDesc->LengthDesc = sizeof(AMI_CPU_INFO_2_CACHE_DESCR); + CoreCacheDesc->Level = CacheInfo->Level; + CoreCacheDesc->Type = CacheInfo->Type; + CoreCacheDesc->Size = CacheInfo->Size; + CoreCacheDesc->Associativity = CacheInfo->Associativity; + CoreCacheDesc->Shared = IsLxSharedByPackage[CacheInfo->Level] + 1; + + if (CoreCacheDesc->Type == 3) { + CoreCacheDesc->Type = 2; //Translate type from AMI CPU INFO 1 to AMI CPU INFO 2. + } + + MemCpy(PkgCacheDesc, CoreCacheDesc, sizeof(AMI_CPU_INFO_2_CACHE_DESCR)); + + PkgCacheDesc->Size *= !IsLxSharedByPackage[CacheInfo->Level] ? NumCores : 1; + + ++Entry; + ++CacheInfo; + } + CpuNum += NumCores * (AmiCpuInfo->NumHts ? 2 : 1) ; + PkgDesc->NumEntries = Entry; + } +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CreatePrivateAmiCpuInfo2 +// +// Description: Create Private Ami Cpu Info2 structure. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CreatePrivateAmiCpuInfo2() +{ + EFI_STATUS Status; + + + Status = pBS->AllocatePool( + EfiBootServicesData, + SizeOfPrivateAmiCpuInfo2(), + &gPrivateAmiCpuInfo2 + ); + ASSERT_EFI_ERROR(Status); + + FillPrivateAmiCpuInfo2(); + + CreateAcpiData(); + + CreateCacheData(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FillCacheDesc +// +// Description: Update cache information with CPUID 4. +// +// Input: +// CACHE_DESCRIPTOR_INFO * CacheInfo - Array to be filled of cache info structures. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID FillCacheDesc(CACHE_DESCRIPTOR_INFO * CacheInfo) +{ + CPUID4_EAX_CACHE_INFO EaxInfo; + CPUID4_EBX_CACHE_INFO EbxInfo; + UINT32 RegEcx; + UINT32 RegEdx; + UINT32 CacheCount; + + for (CacheCount = 0; CacheCount < (MAX_NUM_CACHE_DESC - 1); ++CacheCount) { + RegEcx = CacheCount; + CPULib_CpuID(4, (UINT32*)&EaxInfo, (UINT32*)&EbxInfo, &RegEcx, &RegEdx); + if (EaxInfo.CacheType == 0) break; //No more cache. + + CacheInfo[CacheCount].Desc = 0xff; //Unused. + CacheInfo[CacheCount].Level = EaxInfo.CacheLevel; + switch (EaxInfo.CacheType) { + case 1: CacheInfo[CacheCount].Type = 0; break; + case 2: CacheInfo[CacheCount].Type = 1; break; + case 3: CacheInfo[CacheCount].Type = 3; break; + } + + CacheInfo[CacheCount].Size = + (EbxInfo.Ways + 1) * (EbxInfo.Partitions + 1) * (EbxInfo.LineSize + 1) * (RegEcx + 1) / + 1024; + CacheInfo[CacheCount].Associativity = EbxInfo.Ways + 1; + } + CacheInfo[CacheCount] = gZeroCacheDesc; +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CreatePrivateAmiCpuInfo1 +// +// Description: Create Private Ami Cpu Info1 structure. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CreatePrivateAmiCpuInfo1() +{ + EFI_STATUS Status; + AMI_CPU_INFO *AmiCpuInfo; + UINT64 MicroCodeVersion; + UINT32 CpuSignature; + UINT32 i; + UINT32 Bclk; + UINT32 RegEAX, RegEBX, RegECX, RegEDX; + UINT32 FeatureEcx, FeatureEdx; + UINT32 ExtFeatureEdx; + CHAR8 *BrandString; + CHAR8 *BrandString1; + UINT64 TimerPeriod; + UINT8 *pos1; + BOOLEAN Ht0 = IsHt0(); //True, if not hyper-threaded CPU. + //AMI_CPU_INFO *AmiCpuInfo = &gAmiCpuInfo[Cpu]; + + + //Allocate memory for AMI_CPU_INFO. This will be filled by CPU initialization. + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(AMI_CPU_INFO) * gNumOfCpus, + &gAmiCpuInfo + ); + ASSERT_EFI_ERROR(Status); + + //Get Cpu Signature + CpuSignature = GetCpuSignature(); + + //Use 100 for bclk for Sandy Bridge and Ivy Bridge + Bclk = 100; + + //Allocate memory for Brand string + Status = pBS->AllocatePool(EfiBootServicesData, 49, &BrandString); + ASSERT_EFI_ERROR(Status); + BrandString1 = BrandString; + //Get Brand string + CPULib_CpuID(0x80000002, &RegEAX, &RegEBX, &RegECX, &RegEDX); + *(UINT32*)BrandString = RegEAX; BrandString +=4; + *(UINT32*)BrandString = RegEBX; BrandString +=4; + *(UINT32*)BrandString = RegECX; BrandString +=4; + *(UINT32*)BrandString = RegEDX; BrandString +=4; + + CPULib_CpuID(0x80000003, &RegEAX, &RegEBX, &RegECX, &RegEDX); + *(UINT32*)BrandString = RegEAX; BrandString +=4; + *(UINT32*)BrandString = RegEBX; BrandString +=4; + *(UINT32*)BrandString = RegECX; BrandString +=4; + *(UINT32*)BrandString = RegEDX; BrandString +=4; + + CPULib_CpuID(0x80000004, &RegEAX, &RegEBX, &RegECX, &RegEDX); + *(UINT32*)BrandString = RegEAX; BrandString +=4; + *(UINT32*)BrandString = RegEBX; BrandString +=4; + *(UINT32*)BrandString = RegECX; BrandString +=4; + *(UINT32*)BrandString = RegEDX; BrandString +=4; + *BrandString = '\0'; + + BrandString = BrandString1; + + //Using CPUID to get related feature + CPULib_CpuID(1, &RegEAX, &RegEBX, &FeatureEcx, &FeatureEdx); + CPULib_CpuID(0x80000001, &RegEAX, &RegEBX, &RegECX, &ExtFeatureEdx); + + //Get loaded Microcode version, MSR 0x8b [EDX] = Microcode version + MicroCodeVersion = ReadMsr(0x8b); + MicroCodeVersion = *((UINT32*)&MicroCodeVersion + 1); //ignore upper 32-bits. + + TimerPeriod = CalculateTimerPeriod(); //10^-15 s. + + for(i = 0; i < gNumOfCpus; i++ ) + { + + AmiCpuInfo = &gAmiCpuInfo[i]; + + + Status = pBS->AllocatePool(EfiBootServicesData, MAX_NUM_CACHE_DESC * sizeof(CACHE_DESCRIPTOR_INFO), &AmiCpuInfo->CacheInfo); + ASSERT_EFI_ERROR(Status); + + FillCacheDesc(AmiCpuInfo->CacheInfo); //Get Cache Information. + //Remove leading spaces. After removing leading spaces, the Brand String can not be + //freed. However, it should never be freed. + + AmiCpuInfo->BrandString = BrandString; + + while (*AmiCpuInfo->BrandString == ' ') ++AmiCpuInfo->BrandString; + + //Remove extra spaces in middle. + pos1 = AmiCpuInfo->BrandString; + + for(;;) { + UINT8 *pos2; + UINT8 *pos3; + while (*pos1 != ' ' && *pos1 != '\0') ++pos1; //Find next space. + if (*pos1 == '\0') break; //If found terminator, break. + if (*++pos1 != ' ') continue; //If not second space, continue scanning. + pos2 = pos1; //Found 2 spaces. + while(*++pos2 == ' '); //Skip spaces. + pos3 = pos1; + while(*pos2 != '\0') *pos3++ = *pos2++; //copy string + *pos3++ = '\0'; //Add terminator. + } + + AmiCpuInfo->Version = CpuSignature; + AmiCpuInfo->X64Supported = (ExtFeatureEdx >> 29) & 1; + AmiCpuInfo->Ht0 = Ht0; + AmiCpuInfo->Features = Shl64(FeatureEcx, 32) + FeatureEdx; + AmiCpuInfo->NumCores = gNumOfCpuCores; + AmiCpuInfo->NumHts = IsHtEnabled() * 2; //Either 2 or 0. + AmiCpuInfo->FSBFreq = Bclk; + AmiCpuInfo->Voltage = 0; //Voltage is variable, and no information os available. + AmiCpuInfo->MicroCodeVers = (UINT32)MicroCodeVersion; + AmiCpuInfo->IntendedFreq = ((UINT32)ReadMsr(0x198) >> 8) * Bclk; + AmiCpuInfo->ActualFreq = 1000000000/(UINT32)TimerPeriod; + } + +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GlobalDataInitialize +// +// Description: Cpu Dxe Entrypoint. +// +// Input: +// IN EFI_HANDLE ImageHandle -- Handle assigned to this driver. +// IN EFI_SYSTEM_TABLE *SystemTable -- Efi System table. +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GlobalDataInitialize(VOID) +{ + + EFI_STATUS Status; + UINT64 MsrData = ReadMsr(MSR_CORE_THREAD_COUNT); + EFI_MP_PROC_CONTEXT_FROM_RC *ptr; + UINT32 i; + UINTN BufferSize; + + gNumOfCpuCores = ((UINT32)(MsrData >> 16 & 0xff)); + //Locate MP services protocol provided by CPU RC + Status = pBS->LocateProtocol(&gEfiMpServicesProtocolGuid, NULL, &gEfiMpServicesProtocol); + ASSERT_EFI_ERROR(Status); + + if (!EFI_ERROR(Status)){ + //Get number of Cpus on system + gEfiMpServicesProtocol->GetGeneralMPInfo( + gEfiMpServicesProtocol, + &gNumOfCpus, + &gMaximumNumberOfCPUs, + &gNumberOfEnabledCPUs, + &gRendezvousIntNumber, + &gRendezvousProcLength + ); + + }else{ + return Status; + } + + gNumOfThreads = (UINT32)(gNumOfCpus / gNumOfCpuCores); + //TRACE((-1, "Cpu MP service cpus = %x cores %x threads %x\n", gNumOfCpus, gNumOfCpuCores, gNumOfThreads)); + + //Get MP processor context of each CPU + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_MP_PROC_CONTEXT_FROM_RC) * gNumOfCpus, + &gEfiMpProcContext + ); + + ptr = gEfiMpProcContext; + BufferSize = sizeof(EFI_MP_PROC_CONTEXT_FROM_RC); + for(i = 0; i < gNumOfCpus; i++ , ptr++) + { + gEfiMpServicesProtocol->GetProcessorContext( + gEfiMpServicesProtocol, + i, + &BufferSize, + ptr + ); + } + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PrepareToBoot +// +// Description: Handler executed before OS. +// +// Input: +// IN EFI_EVENT Event +// IN VOID *Context +// +// Output: +// VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID PrepareToBoot(IN EFI_EVENT Event, IN VOID *Context) +{ + //Trigger SWSMI to save CPU fixed & varible MTRRs + IoWrite8(SW_SMI_IO_ADDRESS, SW_SMI_SAVE_MSR); + +} +#if CPU_SETUP_SET_BOOT_RATIO +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuSetBootRatio +// +// Description: Adjust CPU boot ratio base on setup item +// +// Input: +// None +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CpuSetBootRatio(VOID) +{ + + UINT8 MaxRatio = Shr64(ReadMsr(MSR_PLATFORM_INFO),8) & 0xff; + UINT8 MinRatio = Shr64(ReadMsr(MSR_PLATFORM_INFO),40) & 0xff; + UINT8 DesireRatio = (UINT8)GetPlatformCpuBootRatio(gSetupHandle); + + if (DesireRatio == 0 || DesireRatio == 0xff) + return; + + if (DesireRatio < MinRatio || DesireRatio > MaxRatio) + DesireRatio = MaxRatio; + + ReadWriteMsr(MSR_IA32_MISC_ENABLE, BIT16, (UINT64)-1); + WriteMsr(0x199, DesireRatio << 8); + + +} +#endif +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: AmiCpuMpServiceCallback +// +// Description: Cpu Dxe Entrypoint. +// +// Input: +// IN EFI_EVENT Event -- +// IN VOID * Context -- +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID AmiCpuMpServiceCallback(IN EFI_EVENT Event, IN VOID *Context) +{ + EFI_STATUS Status; + EFI_HANDLE Handle=0; + EFI_EVENT BootEvent; + VOID *FirstHob; + UINT32 CpuSignature = GetCpuSignature(); + UINT32 CpuSigNoVer = CpuSignature & 0xfffffff0; + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT8 CpuVer = CpuSignature & 0xf; + BOOLEAN X2ApicEnabled = CPULib_IsLocalX2ApicEnabled(); + UINT32 NumSocketsPop = NumberOfCpuSocketsPopulated(); + UINT32 i; + BOOLEAN IsSandyBridge = (CpuSigNoVer == SANDY_BRIDGE || CpuSigNoVer == JAKETOWN); + BOOLEAN IsIvyBridge = (CpuSigNoVer == IVY_BRIDGE); + VOID *pRegistration = NULL; + MP_CPU_APICID_DATA MpCpuApicIdData; + UINT8 *TpmBaseAddr = (UINT8*)0xfed40000; + + + //MSR 0xCE[28] Programmable Ratio Limits for Turbo Mode Supported + BOOLEAN IsXeCoreRatioLimitSupport = ReadMsr(MSR_PLATFORM_INFO) & 0x10000000 ? 1:0; + //MSR 0xCE[29] Programmable Ratio Limits for Turbo Mode Supported + BOOLEAN IsPwrLimitConfigSupport = ReadMsr(MSR_PLATFORM_INFO) & 0x20000000 ? 1:0; + //MSR 0xCE[30] Programmable TCC Acivation Offset Supported + BOOLEAN IsTccAcitveOffsetSupport = ReadMsr(MSR_PLATFORM_INFO) & 0x40000000 ? 1:0; + //MSR 0xCE[33:34] Programmable TCC Acivation Offset Supported + BOOLEAN IsCtdpSupport = Shr64(ReadMsr(MSR_PLATFORM_INFO), 33) & 0x3 ? 1:0; + //InitAmiLib(ImageHandle,SystemTable); + + PROGRESS_CODE(DXE_CPU_INIT); + + //Free the memory + if (IsFreeMemBelow1MB) + pBS->FreePages(gTempBuffer, EFI_SIZE_TO_PAGES(PMM_EBDA_LOMEM_SIZE) - 1); + + //Init global data for later usage + Status = GlobalDataInitialize(); + + //Create AMI private CpuInfo1 and CpuInfo2 for AMI other module usage + CreatePrivateAmiCpuInfo1(); + CreatePrivateAmiCpuInfo2(); + + Status = pBS->InstallProtocolInterface( + &TheImageHandle, + &gAmiCpuInfo2ProtocolGuid, + EFI_NATIVE_INTERFACE, + gPrivateAmiCpuInfo2 + ); + + Status = pBS->InstallProtocolInterface( + &TheImageHandle, + &gAmiCpuInfoProtocolGuid, + EFI_NATIVE_INTERFACE, + &gAmiCpuInfoProtocol + ); + + // Get CPU feature & set SetupCpuFeatures variable to hide unsupported setup items + DxeInitPlatformCpuLib(pBS, pRS, &gSetupHandle); + + FirstHob = GetEfiConfigurationTable(pST,&gHobListGuid); + if (!FirstHob) return; + + //Fill CpuInfoHob + gCpuInfoHob = (CPUINFO_HOB*)FirstHob; + + //Find CpuInfo Hob & Update it + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION,&gCpuInfoHob))) { + if (guidcmp(&gCpuInfoHob->EfiHobGuidType.Name,&gAmiCpuinfoHobGuid) == 0) break; + } + if (EFI_ERROR(Status)) return; + + for (i = 0; i < gNumOfCpuCores; ++i) { + gCpuInfoHob->Cpuinfo[i].ApicId = gEfiMpProcContext[i].ApicID; + } + + MpCpuApicIdData.NumberOfCpu = (UINT8)gNumOfCpus; + for (i = 0; i < gNumOfCpus; ++i) { + MpCpuApicIdData.ApicId[i] = (UINT8)(gEfiMpProcContext[i].ApicID); + } + Status = pRS->SetVariable( + L"CPUS3APICID", + &gMpCpuApicIdDataGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(MP_CPU_APICID_DATA), + &MpCpuApicIdData ); + + + gCpuFeatures = gCpuInfoHob->CpuFeatures; + + //Init setup feature data +#if TCG_SUPPORT || TCG2Support + PlatformCpuSmxSupport(gSetupHandle, IsSmxSupported(&gCpuFeatures)); +#else + PlatformCpuSmxSupport(gSetupHandle, FALSE); +#endif + PlatformCpuXdSupport(gSetupHandle, isXDSupported(&gCpuFeatures)); + PlatformCpuLimitCpuidSupport(gSetupHandle, isLimitCpuidSupported()); + PlatformCpuVtSupport(gSetupHandle, IsVmxSupported(&gCpuFeatures)); + PlatformCpuHtSupport(gSetupHandle, NumSupportedThreadsPerCore() > 1); + PlatformCpuMultiCoreSupport(gSetupHandle, NumSupportedCpuCores() > 1); + PlatformCpuMultiSocketSupport(gSetupHandle, NUMBER_CPU_SOCKETS > 1); + PlatformCpuMultiSocketPopulated(gSetupHandle, NumberOfCpuSocketsPopulated() > 1); + PlatformCpuSocketSetPopulated(gSetupHandle, 0, TRUE); + PlatformCpuTccActiveOffsetSupport(gSetupHandle, IsTccAcitveOffsetSupport); + PlatformCpuXeCoreRatioLimitSupport(gSetupHandle, IsXeCoreRatioLimitSupport); + //All CPU should support Current Limit Programming + PlatformCpuCurrentLimitSupport(gSetupHandle, TRUE); + PlatformCpuPwrLimitConfigSupport(gSetupHandle, IsPwrLimitConfigSupport); + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + PlatformCpuEistSupport(gSetupHandle, !!(RegEcx & (1 << 7))); + PlatformCpuAesSupport(gSetupHandle, !!(gRegEcx & (1 << 25))); + PlatformCpuPkgCStateDemotionSupport(gSetupHandle, (RegEax > 0x0306C1)); + PlatformCpuTurboModeSupport(gSetupHandle, isTurboModeSupported()); + CPULib_CpuID(5, &RegEax, &RegEbx, &RegEcx, &RegEdx); + PlatformCpuC3Support(gSetupHandle, !!(RegEdx & C3_SUB_STATES_MASK)); + PlatformCpuC6Support(gSetupHandle, !!(RegEdx & C6_SUB_STATES_MASK)); + PlatformCpuC7Support(gSetupHandle, !!(RegEdx & C7_SUB_STATES_MASK)); + PlatformCpuC8Support(gSetupHandle, !!(RegEdx & C8_SUB_STATES_MASK)); + PlatformCpuC9Support(gSetupHandle, !!(RegEdx & C9_SUB_STATES_MASK)); + PlatformCpuC10Support(gSetupHandle, !!(RegEdx & C10_SUB_STATES_MASK)); + PlatformCpuCtdpSupport(gSetupHandle, IsCtdpSupport); + PlatformTpmDevicePresent(gSetupHandle, (*TpmBaseAddr != 0xff)); + + Status = DxePlatformCpuSaveSupportedData(pRS); + ASSERT_EFI_ERROR(Status); + +#if CPU_SETUP_SET_BOOT_RATIO + CpuSetBootRatio(); +#endif + +#if CPU_MODULE_CREATE_SMBIOS_TABLES == 1 + CpuSmbios(); +#endif + + Status = pBS->CreateEvent( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + PrepareToBoot, + (VOID*)TRUE, + &BootEvent + ); + ASSERT_EFI_ERROR(Status); + +#ifdef CSM_SUPPORT + + Status = RegisterProtocolCallback( + &gAmiLegacyBootProtocolGuid, + PrepareToBoot, + NULL, + &BootEvent, + &pRegistration ); + +#endif + + CpuDxeMiscFuncs(); + + return; + +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: AmiCpuSmmFeatureEnCallbacks +// +// Description: Callback for trigger SMI to enable Cpu SMM feature in SMM +// +// Input: +// IN EFI_EVENT Event -- +// IN VOID * Context -- +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID AmiCpuSmmFeatureEnCallbacks(IN EFI_EVENT Event, IN VOID *Context) +{ + +#ifdef SW_SMI_ENABLE_SMM_FEATURE + pBS->CloseEvent(Event); +#if SMM_ACCESS_CHECK_ENABLE + IoWrite8(SW_SMI_IO_ADDRESS, SW_SMI_ENABLE_SMM_FEATURE); +#endif +#endif + +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: DxeInitializeCpu +// +// Description: Cpu Dxe Entrypoint. +// +// Input: +// IN EFI_HANDLE ImageHandle -- Handle assigned to this driver. +// IN EFI_SYSTEM_TABLE *SystemTable -- Efi System table. +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DxeInitializeCpu( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + AMI_BEFORE_CPU_RC_PROTOCOL *AmiBeforeCpuRcProtocol; + +#if AMI_PEI_DEBUG_SUPPORT + AMI_DEBUGGER_CPU_PROTOCOL *AmiDebuggerCpuProtocol; +#endif + + InitAmiLib(ImageHandle,SystemTable); + + // Get CPU support feature before CPU RC DXE initialize + CPULib_CpuID(1, &gRegEax, &gRegEbx, &gRegEcx, &gRegEdx); + + Status = RegisterProtocolCallback( + &gEfiMpServicesProtocolGuid, + AmiCpuMpServiceCallback, + NULL, + &gAmiMpEvent, + &gAmiMpEventRegistration + ); + + Status = RegisterProtocolCallback( + &gEfiDxeSmmReadyToLockProtocolGuid, + AmiCpuSmmFeatureEnCallbacks, + NULL, + &gSmmFeaEnEvent, + &gSmmFeaEnReg + ); + ASSERT_EFI_ERROR(Status); + + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof(AMI_BEFORE_CPU_RC_PROTOCOL), + (VOID**)&AmiBeforeCpuRcProtocol ); + + + Status = pBS->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gAmiBeforeCpuRcProtocolGuid, AmiBeforeCpuRcProtocol, + NULL ); +#if AMI_PEI_DEBUG_SUPPORT + + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof(AMI_DEBUGGER_CPU_PROTOCOL), + (VOID**)&AmiDebuggerCpuProtocol ); + + AmiDebuggerCpuProtocol->DebuggerGetAptioIntHandler = DebuggerGetAptioInterruptHandlerHalt; + AmiDebuggerCpuProtocol->DebuggerFixUpPEIExceptionHandlers = DebuggerFixUpPEIDebuggerExceptionHandlers; + AmiDebuggerCpuProtocol->DebuggerSetupExceptionHandler = DebuggerSetupPEIDebuggerExceptionHandlers; + AmiDebuggerCpuProtocol->DebuggerIsDebuggerIrqHadler = DebuggerIsItPEIDebugIRQHandlerToHookup; + + Status = pBS->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gAmiDebuggerCpuProtocolGuid, AmiDebuggerCpuProtocol, + NULL ); +#endif + + gTempBuffer = 0xA0000 - PMM_EBDA_LOMEM_SIZE; + IsFreeMemBelow1MB = FALSE; + Status = pBS->AllocatePages ( + AllocateAddress, + EfiBootServicesData, + EFI_SIZE_TO_PAGES(PMM_EBDA_LOMEM_SIZE) - 1, + &gTempBuffer + ); + + if (!EFI_ERROR(Status)) + IsFreeMemBelow1MB = TRUE; + + return EFI_SUCCESS; + +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + diff --git a/Core/CPU/CpuDxe.dxs b/Core/CPU/CpuDxe.dxs new file mode 100644 index 0000000..e6d6ced --- /dev/null +++ b/Core/CPU/CpuDxe.dxs @@ -0,0 +1,57 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxe.dxs 1 2/07/12 3:58a Davidhsieh $ +// +// $Revision: 1 $ +// +// $Date: 2/07/12 3:58a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxe.dxs $ +// +// 1 2/07/12 3:58a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CPUDXE.dxs +// +// Description: Dependency expression for Cpu Dxe. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +DEPENDENCY_START + TRUE +DEPENDENCY_END + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/CpuDxe.h b/Core/CPU/CpuDxe.h new file mode 100644 index 0000000..aeb5015 --- /dev/null +++ b/Core/CPU/CpuDxe.h @@ -0,0 +1,158 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxe.h 2 1/14/13 1:54a Crystallee $ +// +// $Revision: 2 $ +// +// $Date: 1/14/13 1:54a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxe.h $ +// +// 2 1/14/13 1:54a Crystallee +// [TAG] EIP111199 +// [Category] Improvement +// [Description] Provide variable data which constains number of P +// states support. +// +// 1 2/07/12 3:58a Davidhsieh +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuDxe.h +// +// Description: Cpu Dxe header file. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef __CPU_DXE_H__ +#define __CPU_DXE_H__ + +#include <AmiHobs.h> +#include <Protocol\Cpu.h> +#include <Protocol\MpService\MpService.h> +#include <Protocol\AmiCpuInfo2.h> +#include "Cpu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Define structures used and referenced in this file +typedef struct{ + UINT16 NumberOfPStates; +} P_STATES_DATA; + +typedef struct{ + UINT32 MemAddress, MemLength; +} system_memory_struc; + +EFI_STATUS EfiCpuFlushDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType); + +EFI_STATUS EfiCpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes); + +extern EFI_MP_SERVICES_PROTOCOL *gEfiMpServicesProtocol; + +//APIC ID +//CPU NUM +#define PRIVATE_INFO_NUM_OF_CPU_DATA 2 + +typedef struct { + AMI_CPU_INFO_2_PROTOCOL AmiCpuInfo2; +//??? Determine max structure size of UINT32s + // UINT32 # of populated Sockets 0 + // --------------------- + // --------------------- + // ---Socket #0--- + // UINT32 # of Cores + // ---Core #0--- + // UINT32 # of Threads + // ---Thread #0--- + // UINT32 APIC ID + // UINT32 CPU Num + // ---Thread #1--- + // UINT32 APIC ID + // UINT32 CPU Num + // ---Core #1--- + // .... + // --------------------- + // --------------------- + // ---Socket #1--- + // UINT32 # of Cores + // ---Core # 0--- + // UINT32 # of Threads + // ---Thread #0--- + // .... +} PRIVATE_AMI_CPU_INFO_2_PROTOCOL; + +extern PRIVATE_AMI_CPU_INFO_2_PROTOCOL *gPrivateAmiCpuInfo2; + +typedef struct _AMI_BEFORE_CPU_RC_PROTOCOL AMI_BEFORE_CPU_RC_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *PLATFORM_CPU_DXE_POLICY_OVERWRITE) ( + IN AMI_BEFORE_CPU_RC_PROTOCOL *This + + ); + +typedef struct _AMI_BEFORE_CPU_RC_PROTOCOL { + PLATFORM_CPU_DXE_POLICY_OVERWRITE PlatformCpuDxePolicyOverwrite; +}; + +VOID CpuDxeMiscFuncs(VOID); + +#if PERF_TUNE_SUPPORT == 1 + +EFI_STATUS IntelXtuFillCpuDataCallBack( + IN EFI_EVENT Event, + IN VOID *Context +); + +#endif + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/CpuDxeFuncs.c b/Core/CPU/CpuDxeFuncs.c new file mode 100644 index 0000000..dea230d --- /dev/null +++ b/Core/CPU/CpuDxeFuncs.c @@ -0,0 +1,1101 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxeFuncs.c 10 5/06/14 12:03a Hsingyingchung $ +// +// $Revision: 10 $ +// +// $Date: 5/06/14 12:03a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuDxeFuncs.c $ +// +// 10 5/06/14 12:03a Hsingyingchung +// [TAG] EIP167029 +// [Category] Improvement +// [Description] 1. keep the original attribute of "Setup" variable when +// use SetVariable(). +// 2. remove the runtime attribute of variables that no access requirement +// in runtime. +// +// 9 6/03/13 12:12a Hsingyingchung +// [TAG] None +// [Category] Improvement +// [Description] +// 1. Change PLL defatul value to LCPLL +// 2. Modify IA core ratio minimun value. Use "max non turbo ratio(MSR +// CEh)" instead of "power on turbo default value". +// 3. Remove write MSR 620h due to RC have implemented (EIP123446). +// +// 8 4/07/13 11:58p Hsingyingchung +// [TAG] None +// [Category] Improvement +// [Description] Keep ring ratio default value in ACPI table when one +// core ratio has changed. +// +// 7 3/05/13 1:10a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Use OcSetupData for EIST and Turbo status when +// PerformanceTunning enable +// +// 6 2/07/13 4:08a Hsingyingchung +// [TAG] EIP112631 +// [Category] Improvement +// [Description] +// Add: +// 1. Support IA core and Ring voltage offset negative in OC mailbox. +// 2. Add Filter PLL function, please change +// "HASWELL_PERFTUNE_CPU_FILTER_PLL_SUPPORT" token if need to use this +// function. +// +// Fixed: +// 1. TDP Time Window is now programmed to 8 seconds by default. +// 2. When cold reset, re-enabling FIVR faults and SVID control. +// 3. Assign max ring ratio in msr 0x620 with ring ratio max value +// support. +// +// 5 1/14/13 1:54a Crystallee +// [TAG] EIP111199 +// [Category] Improvement +// [Description] Provide variable data which constains number of P +// states support. +// +// 4 12/20/12 10:25a Hsingyingchung +// +// 3 12/20/12 10:21a Hsingyingchung +// [TAG] EIP108128 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] "Max non-turbo ratio" can't show in BIOS setup when first +// boot after flashing BIOS +// [RootCause] Doesn't initialize max non-turbo ratio value when first +// boot after flashing BIOS. +// [Solution] Add initialize code for max non-turbo ratio. +// +// 2 11/23/12 2:09a Hsingyingchung +// [TAG] EIP99095 +// [Category] Improvement +// [Description] Update by XTU 4.X +// +// 1 2/07/12 3:58a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuDxeFuncs.c +// +// Description: +// Installs CPU Architectural Protocol. +// processor interrupt vector table. The CPU Architectural +// Protocol enables/disables/get state of interrupts, set +// memory range cache type, and installs/uninstalls +// interrupt handlers. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <Setup.h> +#include <token.h> +#include <AmiCspLib.h> +#include <Protocol\AmiCpuInfo.h> +#include "CpuDxe.h" + +extern EFI_SYSTEM_TABLE *pST; +extern EFI_BOOT_SERVICES *pBS; +extern EFI_RUNTIME_SERVICES *pRS; + +extern EFI_GUID gHobListGuid; + +#if PERF_TUNE_SUPPORT == 1 +#include <Protocol\PerfTuneProtocol.h> +#include "Board\EM\PerfTune\PerfTuneCpuSetup.h" + +static EFI_GUID gAmiInternalFactoryTdcTdpHobGuid = AMI_INTERNAL_FACTORY_TDC_TDP_HOB_GUID; +static EFI_GUID gAmiCpuRatioLimitHobGuid = AMI_INTERNAL_CPU_RATIO_LIMIT; + +AMI_INTERNAL_FACTORY_TDC_TDP_HOB *gTdcTdpHob = NULL; +CPU_RATIO_LIMIT_DATA *gCpuRatioLimitData = NULL; + +OVERCLOCKING_CONFIG_DATA *gOcConfigData; +EFI_GUID InternalWdtGuid = PERF_TUNE_WDT_PROTOCOL_GUID; + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#define EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID \ + { \ + 0xd71db106, 0xe32d, 0x4225, 0xbf, 0xf4, 0xde, 0x6d, 0x77, 0x87, 0x17, 0x61 \ + } + +#else +#define EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID \ + { \ + 0xd71db106, 0xe32d, 0x4225, \ + { \ + 0xbf, 0xf4, 0xde, 0x6d, 0x77, 0x87, 0x17, 0x61 \ + } \ + } +#endif +EFI_GUID gPowerMgmtInitDoneProtocolGuid = EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID; +EFI_GUID gSetupGuid = SETUP_GUID; + +#define DXE_PLATFORM_ME_POLICY_GUID \ + { 0x69bf9e8a, 0x4ad6, 0x9a28, 0x87, 0xf3, 0x09, 0xa0, 0x71, 0x29, 0x2a, 0x00} +EFI_GUID gDxePlatformMePolicyGuid = DXE_PLATFORM_ME_POLICY_GUID; + +#define ME_INFO_SETUP_GUID \ + { 0x78259433, 0x7B6D, 0x4DB3, 0x9A, 0xE8, 0x36, 0xC4, 0xC2, 0xC3, 0xA1, 0x7D} +EFI_GUID gMeSetupInfoGuid = ME_INFO_SETUP_GUID; + +#define AMI_CPU_INTERNAL_ME_FW_VERSION_GUID \ + { 0x9b875aac, 0x36ec, 0x4550, 0xa4, 0xae, 0x86, 0xc8, 0x4e, 0x96, 0x76, 0x7e} +EFI_GUID gAmiCpuMEFwVerGuid = AMI_CPU_INTERNAL_ME_FW_VERSION_GUID; +typedef struct{ + UINT8 MeFirmwareInfo; + UINT32 MeMajor; + UINT32 MeMinor; + UINT32 MeHotFix; + UINT32 MeBuildNo; +} ME_INFO_SETUP_DATA; + +BIOS_SETTING_DATA *gBiosSettingData; +#endif + +#ifndef FVID_MAX_STATES +#define FVID_MAX_STATES 16 +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NumberOfPStatesSupport +// +// Description: Provide variable data which constains number of P states support +// +// Input: VOID +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID NumberOfPStatesSupport(VOID) +{ + EFI_STATUS Status; + EFI_GUID gSetupGuid = SETUP_GUID; +#if PERF_TUNE_SUPPORT == 1 + UINTN SetupDataSize = sizeof(OC_SETUP_DATA); + OC_SETUP_DATA SetupData; +#else + UINTN SetupDataSize = sizeof(SETUP_DATA); + SETUP_DATA SetupData; +#endif + P_STATES_DATA PStatesData; + UINT16 mMaxBusRatio; + UINT16 mMinBusRatio; + UINT16 BusRatioRange; + UINT64 MsrPlatformInfo; + +#if PERF_TUNE_SUPPORT == 1 + Status = pRS->GetVariable(L"OcSetupData",&gSetupGuid, NULL, &SetupDataSize, &SetupData); +#else + Status = pRS->GetVariable(L"Setup",&gSetupGuid, NULL, &SetupDataSize, &SetupData); +#endif + if(EFI_ERROR(Status)) { + TRACE((-1,"Get Setup variable fail!!\n")); + return; + } + + if (!EFI_ERROR(Status)) { + if (!SetupData.EIST) { + PStatesData.NumberOfPStates = 0; + } + else { + MsrPlatformInfo = ReadMsr(0xce); + mMaxBusRatio = (UINT16)(Shr64(MsrPlatformInfo, 8) & 0xff); + mMinBusRatio = (UINT16)(Shr64(MsrPlatformInfo, 40) & 0xff); + BusRatioRange = mMaxBusRatio - mMinBusRatio; + + PStatesData.NumberOfPStates = ((BusRatioRange + 1) < FVID_MAX_STATES ? (BusRatioRange + 1) : FVID_MAX_STATES); + + if (SetupData.TurboMode & isTurboModeSupported()) { + if (PStatesData.NumberOfPStates == FVID_MAX_STATES) + PStatesData.NumberOfPStates--; + } + } + + Status = pRS->SetVariable( + L"NumOfPState", + &gSetupGuid, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof(P_STATES_DATA), + &PStatesData + ); + if(EFI_ERROR(Status)) { + TRACE((-1,"Set number of P states variable fail!!\n")); + } + } +} + +#if PERF_TUNE_SUPPORT == 1 + + + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: FillXtuGaciData +// +// Description: Fill CPU information for xtu 3.0 specification +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS FillXtuGaciData( + IN PERF_TUNE_ASL_PROTOCOL *PerfTuneAslProtocol +) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + UINT8 *Buffer = NULL; + UINT8 *ptr = NULL; + UINTN Len = 0; + UINT64 PlatformInfo = ReadMsr(MSR_PLATFORM_INFO); + UINT16 Bins = Shr64(ReadMsr(MSR_FLEX_RATIO),17) & 0x7; //overclocking bins supported + UINT16 MNTR = gBiosSettingData->ProcessorMul; + + //----------------------------CPU Ratio GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA CpuMulGaciData = {BIOS_PROC_MULT_IMPLEMENTATION, 0x0, 0, 0, 0, 0, 0, 0, 0}; + + //----------------------------CPU TDC GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA CpuTdcGaciData = {BIOS_TDC_VALUE_IMPLEMENTATION, 4096, 3, 0, 0, 0, 4095, 0, 511875}; + + //----------------------------CPU TDP GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA CpuTdpGaciData = {BIOS_TDP_VALUE_IMPLEMENTATION, 4096, 3, 0, 0, 0, 4095, 0, 511875}; + + //-------------------TOTAL DESIGN POWER LOCK SWITCH DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA ExtTDPSwGaciData= {BIOS_EXTENDED_TDP_ENABLE_IMPLEMENTATION, 0x2, 0, 0, 0, 0, 1, 0, 1}; + + //----------------------------CPU Core Ratio Limit GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA Cpu1CoreRatioLimGaci = {BIOS_1_CORE_RATIO_IMPLEMENTATION, 0x1, 0, 0, 0, 0, 0, 0, 0}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA Cpu2CoreRatioLimGaci = {BIOS_2_CORE_RATIO_IMPLEMENTATION, 0x1, 0, 0, 0, 0, 0, 0, 0}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA Cpu3CoreRatioLimGaci = {BIOS_3_CORE_RATIO_IMPLEMENTATION, 0x1, 0, 0, 0, 0, 0, 0, 0}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA Cpu4CoreRatioLimGaci = {BIOS_4_CORE_RATIO_IMPLEMENTATION, 0x1, 0, 0, 0, 0, 0, 0, 0}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA Cpu5CoreRatioLimGaci = {BIOS_5_CORE_RATIO_IMPLEMENTATION, 0x1, 0, 0, 0, 0, 0, 0, 0}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA Cpu6CoreRatioLimGaci = {BIOS_6_CORE_RATIO_IMPLEMENTATION, 0x1, 0, 0, 0, 0, 0, 0, 0}; + + //----------------------------CPU Turbo Mode GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA TurboModeGaciData = {BIOS_TURBO_ENABLE_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; + + //----------------------------CPU Max Turbo Mode Cpu Voltage GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA TMCpuVoltGaci = {BIOS_MAX_TURBO_MODE_CPU_VOLTAGE_IMPLEMENTATION, 256, 5, 0, 0, 0, 255, 0, 99609375}; + + //----------------------------CPU EIST GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA EistGaciData = {BIOS_EIST_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; + + //----------------------------CPU TDP Related GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA ShortTDPSwGaciData= {BIOS_SHORT_TDP_ENABLE_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; + + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA ShortTdpGaci = {BIOS_SHORT_TDP_IMPLEMENTATION, 513, 0, 0, 0, 0, 512, 0, 512}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + //static GACI_DATA ExtTdpGaci = {BIOS_EXTENDED_TDP_IMPLEMENTATION, 4096, 3, 0, 0, 0, 4095, 0, 511875}; + static GACI_DATA ExtTdpGaci = {BIOS_EXTENDED_TDP_IMPLEMENTATION, 513, 0, 0, 0, 0, 512, 0, 512}; + + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA ExtTdpTimeGaci = {BIOS_EXTENDED_TIME_WINDOW_IMPLEMENTATION, 0xFFFF, 0, 0, 1, 0, 0, 0, 0}; + + //----------------------------IA CORE CURRENT MAX-------------------------- + // GACI_DATA DevNameGaciData { ControlID, NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA IACoreAmpGaci = {BIOS_PACKAGE_CURRENT_LIMIT_IMPLEMENTATION, 8192, 3, 0, 0, 0, 8191, 0, 1023875}; + + //----------------------------IGFX CORE CURRENT MAX-------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + //static GACI_DATA iGFXCoreAmpGaci = {BIOS_IGFX_CORE_CURRENT_MAX_IMPLEMENTATION, 8192, 3, 0, 0, 0, 8191, 0, 1023875}; + + + //----------------------------INTERNAL PLL Overvoltage Enable-------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA iPLLOvGaci = {BIOS_CPU_PLL_VOLTAGE_UNLOCK_ENABLE_IMPLEMENTATION, 0x2, 0, 0, 0, 0, 1, 0, 1}; + + //----------------------------Overclocking Lock GACI DATA---------------------------- + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA OverclockingGaciData = {BIOS_OVERCLOCKING_ENABLE_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; + + //----------------------------Overclocking Related GACI DATA---------------------------- + //IA core + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA CPUVoltOverrideGaci = {BIOS_CPU_VOLTAGE_IMPLEMENTATION, 2001, 3, 0, 0, 0, 2000, 0, 2000}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA CPUVoltModeGaci = {BIOS_IA_CORE_VOLTAGE_MODE_IMPLEMENTATION, 2, 0, 0, 0, 0, 1, 0, 1}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA CPUVoltOffsetGaci = {BIOS_CPU_VOLTAGE_OFFSET_IMPLEMENTATION, 2001, 0, 0, 1000, 0, 2000, 0xFFFFFc18, 1000}; + + //RING + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA RINGRatioGaci = { BIOS_RING_RATIO_IMPLEMENTATION, 1, 0, 0, 0, 0, 0, 0, 0}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA RINGVoltOverrideGaci = {BIOS_RING_VOLTAGE_OVERRIDE_IMPLEMENTATION, 2001, 3, 0, 0, 0, 2000, 0, 2000}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA RINGVoltModeGaci = {BIOS_RING_VOLTAGE_MODE_IMPLEMENTATION, 2, 0, 0, 0, 0, 1, 0, 1}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA RINGVoltOffsetGaci = {BIOS_RING_VOLTAGE_OFFSET_IMPLEMENTATION, 2001, 0, 0, 1000, 0, 2000, 0xFFFFFc18, 1000}; + + //SVID and FIVR + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA SVIDControlGaci = {BIOS_DYNAMIC_SVID_CONTROL_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA SVIDVoltOverrideGaci = {BIOS_SVID_VOLTAGE_OVERRIDE_IMPLEMENTATION, 2501, 3, 0, 0, 0, 2500, 0, 2500}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA FivrFaultsGaciData = {BIOS_FIVR_FAULTS_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; + // GACI_DATA DevNameGaciData { ControlID,NumberOfValues,Precision,Flags,DefaultDataValue,MinDataValue,MaxDataValue,MinDisplayValue,MaxDisplayValue} + static GACI_DATA FivrEfficiencyGaciData = {BIOS_FIVR_EFFICIENCY_MANAGEMENT_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; + +#if HASWELL_PERFTUNE_CPU_FILTER_PLL_SUPPORT == 1 + //Filter PLL Frequency + static GACI_DATA FilterPLLGaciData = {BIOS_FILTER_PLL_FREQUENCY_IMPLEMENTATION, 0x2, 0, 0, 1, 0, 1, 0, 1}; +#endif + + TRACE((-1, "XTU Fill XTU Cpu Gaci data\n")); + + //--1. CPU ratio GACI DATA-------------------------------------------- + //CpuMulGaciData.MinDataValue = (UINT16)(Shr64(PlatformInfo, 40) & 0xFF); + //CpuMulGaciData.MaxDataValue = (UINT16)(Shr64(PlatformInfo, 8) & 0xFF); + + //CpuMulGaciData.MinDisplayValue = (UINT16)(Shr64(PlatformInfo, 40) & 0xFF); + //CpuMulGaciData.MaxDisplayValue = (UINT16)(Shr64(PlatformInfo, 8) & 0xFF); + + //CpuMulGaciData.NumberOfValues = CpuMulGaciData.MaxDataValue - CpuMulGaciData.MinDataValue + 1; + //CpuMulGaciData.DefaultDataValue = (UINT16)(Shr64(PlatformInfo, 8) & 0xFF); + + //Len = sizeof(GACI_DATA); + //Buffer = MallocZ(Len); + //if(!Buffer) return EFI_OUT_OF_RESOURCES; + + //MemCpy(Buffer, &CpuMulGaciData, sizeof(CpuMulGaciData)); + //Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + //pBS->FreePool(Buffer); + CpuMulGaciData.MinDataValue = (UINT16)(Shr64(PlatformInfo, 40) & 0xFF); + CpuMulGaciData.MaxDataValue = (UINT16)gCpuRatioLimitData->MaxNonTurboRatio; + CpuMulGaciData.MinDisplayValue = (UINT16)(Shr64(PlatformInfo, 40) & 0xFF); + CpuMulGaciData.MaxDisplayValue = (UINT16)gCpuRatioLimitData->MaxNonTurboRatio; + CpuMulGaciData.NumberOfValues = CpuMulGaciData.MaxDataValue - CpuMulGaciData.MinDataValue + 1; + CpuMulGaciData.DefaultDataValue = (UINT16)gCpuRatioLimitData->MaxNonTurboRatio; + Len = sizeof(GACI_DATA); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &CpuMulGaciData, sizeof(CpuMulGaciData)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + + //--2. CPU TDC GACI DATA-------------------------------------------- + CpuTdcGaciData.DefaultDataValue = (UINT16)(gTdcTdpHob->Tdc); + Len = sizeof(GACI_DATA); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &CpuTdcGaciData, Len); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + + //--3. CPU TDP GACI DATA-------------------------------------------- + CpuTdpGaciData.DefaultDataValue = (UINT16)(gTdcTdpHob->Tdp); + Len = sizeof(GACI_DATA); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &CpuTdpGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //--4. TOTAL DESIGN POWER LOCK SWITCH DATA---------------------------- + Len = sizeof(GACI_DATA); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &ExtTDPSwGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //--5. CPU Cores ratio limit GACI DATA-------------------------------------------- + Cpu1CoreRatioLimGaci.MinDataValue = MNTR; + Cpu1CoreRatioLimGaci.MinDisplayValue = MNTR; + + MemCpy(&(Cpu2CoreRatioLimGaci.NumberOfValues), &(Cpu1CoreRatioLimGaci.NumberOfValues), sizeof(GACI_DATA) - sizeof(UINT32)); + MemCpy(&(Cpu3CoreRatioLimGaci.NumberOfValues), &(Cpu1CoreRatioLimGaci.NumberOfValues), sizeof(GACI_DATA) - sizeof(UINT32)); + MemCpy(&(Cpu4CoreRatioLimGaci.NumberOfValues), &(Cpu1CoreRatioLimGaci.NumberOfValues), sizeof(GACI_DATA) - sizeof(UINT32)); + MemCpy(&(Cpu5CoreRatioLimGaci.NumberOfValues), &(Cpu1CoreRatioLimGaci.NumberOfValues), sizeof(GACI_DATA) - sizeof(UINT32)); + MemCpy(&(Cpu6CoreRatioLimGaci.NumberOfValues), &(Cpu1CoreRatioLimGaci.NumberOfValues), sizeof(GACI_DATA) - sizeof(UINT32)); + + Cpu1CoreRatioLimGaci.MaxDataValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->OneCoreRatioLimit + (UINT16)Bins; + Cpu1CoreRatioLimGaci.MaxDisplayValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->OneCoreRatioLimit + (UINT16)Bins; + Cpu1CoreRatioLimGaci.NumberOfValues = Cpu1CoreRatioLimGaci.MaxDataValue - Cpu1CoreRatioLimGaci.MinDataValue + 1; + + Cpu2CoreRatioLimGaci.MaxDataValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->TwoCoreRatioLimit + (UINT16)Bins; + Cpu2CoreRatioLimGaci.MaxDisplayValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->TwoCoreRatioLimit + (UINT16)Bins; + Cpu2CoreRatioLimGaci.NumberOfValues = Cpu2CoreRatioLimGaci.MaxDataValue - Cpu2CoreRatioLimGaci.MinDataValue + 1; + + Cpu3CoreRatioLimGaci.MaxDataValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->ThreeCoreRatioLimit + (UINT16)Bins; + Cpu3CoreRatioLimGaci.MaxDisplayValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->ThreeCoreRatioLimit + (UINT16)Bins; + Cpu3CoreRatioLimGaci.NumberOfValues = Cpu3CoreRatioLimGaci.MaxDataValue - Cpu3CoreRatioLimGaci.MinDataValue + 1; + + Cpu4CoreRatioLimGaci.MaxDataValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->FourCoreRatioLimit + (UINT16)Bins; + Cpu4CoreRatioLimGaci.MaxDisplayValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->FourCoreRatioLimit + (UINT16)Bins; + Cpu4CoreRatioLimGaci.NumberOfValues = Cpu4CoreRatioLimGaci.MaxDataValue - Cpu4CoreRatioLimGaci.MinDataValue + 1; + + Cpu5CoreRatioLimGaci.MaxDataValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->FiveCoreRatioLimit + (UINT16)Bins; + Cpu5CoreRatioLimGaci.MaxDisplayValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->FiveCoreRatioLimit + (UINT16)Bins; + Cpu5CoreRatioLimGaci.NumberOfValues = Cpu5CoreRatioLimGaci.MaxDataValue - Cpu5CoreRatioLimGaci.MinDataValue + 1; + + Cpu6CoreRatioLimGaci.MaxDataValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->SixCoreRatioLimit + (UINT16)Bins; + Cpu6CoreRatioLimGaci.MaxDisplayValue = (Bins == 0x7)? 80 : (UINT16)gTdcTdpHob->SixCoreRatioLimit + (UINT16)Bins; + Cpu6CoreRatioLimGaci.NumberOfValues = Cpu6CoreRatioLimGaci.MaxDataValue - Cpu6CoreRatioLimGaci.MinDataValue + 1; + + gTdcTdpHob->OneCoreRatioMax = Cpu1CoreRatioLimGaci.MaxDataValue; + gTdcTdpHob->TwoCoreRatioMax = Cpu2CoreRatioLimGaci.MaxDataValue; + gTdcTdpHob->ThreeCoreRatioMax = Cpu3CoreRatioLimGaci.MaxDataValue; + gTdcTdpHob->FourCoreRatioMax = Cpu4CoreRatioLimGaci.MaxDataValue; + gTdcTdpHob->FiveCoreRatioMax = Cpu5CoreRatioLimGaci.MaxDataValue; + gTdcTdpHob->SixCoreRatioMax = Cpu6CoreRatioLimGaci.MaxDataValue; + + + Cpu1CoreRatioLimGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->OneCoreRatioLimit); + Cpu2CoreRatioLimGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->TwoCoreRatioLimit); + Cpu3CoreRatioLimGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->ThreeCoreRatioLimit); + Cpu4CoreRatioLimGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->FourCoreRatioLimit); + Cpu5CoreRatioLimGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->FiveCoreRatioLimit); + Cpu6CoreRatioLimGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->SixCoreRatioLimit); + + Len = sizeof(GACI_DATA); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &Cpu1CoreRatioLimGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if (MNTR > gBiosSettingData->CoreRatioLimit1) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, MNTR); + + MemCpy(Buffer, &Cpu2CoreRatioLimGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if (MNTR > gBiosSettingData->CoreRatioLimit2) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, MNTR); + + MemCpy(Buffer, &Cpu3CoreRatioLimGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if (MNTR > gBiosSettingData->CoreRatioLimit3) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, MNTR); + + MemCpy(Buffer, &Cpu4CoreRatioLimGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if (MNTR > gBiosSettingData->CoreRatioLimit4) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, MNTR); + + MemCpy(Buffer, &Cpu5CoreRatioLimGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if (MNTR > gBiosSettingData->CoreRatioLimit5) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, MNTR); + + MemCpy(Buffer, &Cpu6CoreRatioLimGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if (MNTR > gBiosSettingData->CoreRatioLimit6) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, MNTR); + + pBS->FreePool(Buffer); + pBS->FreePool(gBiosSettingData); + + //--6. Turbo Mode GACI DATA-------------------------------------------- + Len = sizeof(TurboModeGaciData); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &TurboModeGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //--7. Max Turbo Mode CPU Voltage------------------------------------- + Len = sizeof(TMCpuVoltGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &TMCpuVoltGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //--8. CPU EIST GACI DATA------------------------------------- + Len = sizeof(EistGaciData); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &EistGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //--9. ShortTdpGaci------------------------------------------ + //ShortTdpGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->Tdc); + ShortTdpGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->Tdc / 8 ); + Len = sizeof(ShortTdpGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &ShortTdpGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //-- ShortTDPSwGaci------------------------------------------ + Len = sizeof(ShortTDPSwGaciData); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &ShortTDPSwGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //--10.ExtTdpGaci------------------------------------------ + //ExtTdpGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->Tdp); + ExtTdpGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->Tdp / 8 ); + Len = sizeof(ExtTdpGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &ExtTdpGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //-- ExtTdpTimeGaci------------------------------------------ + ExtTdpTimeGaci.DefaultDataValue = 8; // For desktop, default is 8. + Len = sizeof(ExtTdpTimeGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &ExtTdpTimeGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + + //11.IA CORE CRUUENT MAX---------------------------------------------------- + IACoreAmpGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->IaCoreCurrentMax); + Len = sizeof(IACoreAmpGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &IACoreAmpGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //12.iGFX CORE CURRENT MAX-------------------------------------------------- + //iGFXCoreAmpGaci.DefaultDataValue = (UINT16)(gTdcTdpHob->IGfxCoreCurrentMax); + //Len = sizeof(iGFXCoreAmpGaci); + //Buffer = MallocZ(Len); + //if(!Buffer) return EFI_OUT_OF_RESOURCES; + + //MemCpy(Buffer, &iGFXCoreAmpGaci, sizeof(GACI_DATA)); + //Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + //pBS->FreePool(Buffer); + + + //13.INTERNAL PLL OVERVOLTAGE ENABLE--------------------------- + Len = sizeof(iPLLOvGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &iPLLOvGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //--14. Overclocking Enable GACI DATA------------------------------------- + Len = sizeof(OverclockingGaciData); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + + MemCpy(Buffer, &OverclockingGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + //--15. Overclocking Feature GACI DATA------------------------------------- +//IA core + //CPU voltage override + Len = sizeof(CPUVoltOverrideGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &CPUVoltOverrideGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //IA core voltage mode + Len = sizeof(CPUVoltModeGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &CPUVoltModeGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //Dynamic CPU Voltage Offset + Len = sizeof(CPUVoltOffsetGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &CPUVoltOffsetGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + +//CLR/RING + //Ring Ratio + RINGRatioGaci.MaxDataValue = (UINT16)gOcConfigData->OCCap[RING].MaxOcRatioLimit; + RINGRatioGaci.MaxDisplayValue = (UINT16)gOcConfigData->OCCap[RING].MaxOcRatioLimit; + RINGRatioGaci.NumberOfValues = RINGRatioGaci.MaxDataValue - RINGRatioGaci.MinDataValue + 1; + RINGRatioGaci.DefaultDataValue = (UINT16)gTdcTdpHob->OneCoreRatioLimit; + Len = sizeof(RINGRatioGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &RINGRatioGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //Ring Voltage Override + Len = sizeof(RINGVoltOverrideGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &RINGVoltOverrideGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //Ring Voltage Mode + Len = sizeof(RINGVoltModeGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &RINGVoltModeGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //Ring Voltage Offset + Len = sizeof(RINGVoltOffsetGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &RINGVoltOffsetGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + +//SVID and FIVR + //SVID Voltage Override + Len = sizeof(SVIDVoltOverrideGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &SVIDVoltOverrideGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + //SVID Control Enable/Disable + Len = sizeof(SVIDControlGaci); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &SVIDControlGaci, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if(gOcConfigData->IsPowerCycle) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, (UINT16)1); // Re-Enable SVID Control if cold boot + pBS->FreePool(Buffer); + + //FIVR FAULTS DISABLE + Len = sizeof(FivrFaultsGaciData); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &FivrFaultsGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + if(gOcConfigData->IsPowerCycle) + Status = PerfTuneAslProtocol->SyncHwValue(Buffer, (UINT16)1); // Re-Enable FIVR FAULTS if cold boot + pBS->FreePool(Buffer); + + //FIVR EFFICIENCY DISABLE + Len = sizeof(FivrEfficiencyGaciData); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &FivrEfficiencyGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); + + pBS->FreePool(gCpuRatioLimitData); + +#if HASWELL_PERFTUNE_CPU_FILTER_PLL_SUPPORT == 1 + //Filter PLL + Len = sizeof(FilterPLLGaciData); + Buffer = MallocZ(Len); + if(!Buffer) return EFI_OUT_OF_RESOURCES; + MemCpy(Buffer, &FilterPLLGaciData, sizeof(GACI_DATA)); + Status = PerfTuneAslProtocol->SetGaciData(Buffer, Len); + pBS->FreePool(Buffer); +#endif + + return EFI_SUCCESS; + +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: IntelXtuFillCpuDataCallBack +// +// Description: Callback function for Intel XTU data init +// +// Input: +// IN EFI_EVENT Event +// IN VOID *Context +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS IntelXtuFillCpuDataCallBack( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + EFI_GUID PerfTuneAslProtocolGuid = PERF_TUNE_ASL_PROTOCOL_GUID; + PERF_TUNE_ASL_PROTOCOL *PerfTuneAslProtocol = NULL; + + TRACE((-1, "XTU Fill Cpu Data Callback\n")); + + Status = pBS->LocateProtocol(&PerfTuneAslProtocolGuid, NULL, &PerfTuneAslProtocol); + if(!EFI_ERROR(Status)) + FillXtuGaciData(PerfTuneAslProtocol); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CpuPllOverVoltageProgress +// +// Description: CPU pll over voltage initialize code in DXE phase +// +// Input: +// IN EFI_EVENT Event +// IN VOID *Context +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CpuPllOverVoltageProgress( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_GUID AmiPllOvFlagHobGuid = AMI_PLL_OVER_VOTAGE_FLAG_HOB_GUID; + EFI_GUID AmiPllOvFlagDataGuid = AmiPllOvFlagHobGuid; + EFI_GUID gHobListGuid = HOB_LIST_GUID; + PLL_OV_FLAG_DATA_HOB *PllOvFlagDataHob; + UINT64 CoreRatioLimits = ReadMsr(0x1ad); + EFI_STATUS Status = EFI_NOT_STARTED; + VOID *FirstHob; + PERF_TUNE_WDT_PROTOCOL *InternalWdtProtocol; + + TRACE((-1,"CpuPllOverVoltageProgress Start\n")); + + // Get Hob List + FirstHob = GetEfiConfigurationTable(pST, &gHobListGuid); + if (!FirstHob) return EFI_NOT_READY; + + PllOvFlagDataHob = (PLL_OV_FLAG_DATA_HOB*)FirstHob; + + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION,&PllOvFlagDataHob))) { + if (guidcmp(&PllOvFlagDataHob->EfiHobGuidType.Name,&AmiPllOvFlagHobGuid) == 0) break; + } + if (EFI_ERROR(Status)) return EFI_NOT_FOUND; + + Status = EFI_ALREADY_STARTED; + + if((PllOvFlagDataHob->PllOvData.PLLOvFlag == 0x1) && (CoreRatioLimits = 0x060606)) + { + //Delay for 1.5 ms + pBS->Stall(150); + + PllOvFlagDataHob->PllOvData.PLLOvFlag = 0x2; + + //write back original Core Ratio Limits. + WriteMsr(0x1ad, PllOvFlagDataHob->PllOvData.OriTurboRatio); + + Status = pRS->SetVariable( + L"PLLOvFlag", + &AmiPllOvFlagDataGuid, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof(PLL_OV_FLAG_DATA), + &PllOvFlagDataHob->PllOvData + ); + + ASSERT_EFI_ERROR(Status); + + Status = pBS->LocateProtocol(&InternalWdtGuid, NULL, &InternalWdtProtocol); + if(!EFI_ERROR(Status)) + { + TRACE((-1,"Internal PLL Over Voltage Reset Requirement.\n")); + //reset + InternalWdtProtocol->AllowKnownReset(); + IoWrite8 (0xCF9,0x02); + IoWrite8 (0xCF9,0x06); + EFI_DEADLOOP(); + } + }else if(PllOvFlagDataHob->PllOvData.PLLOvFlag== 0x2) { + //Clear Flag to Zero + PllOvFlagDataHob->PllOvData.PLLOvFlag = 0x0; + Status = pRS->SetVariable( + L"PLLOvFlag", + &AmiPllOvFlagDataGuid, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof(PLL_OV_FLAG_DATA), + &PllOvFlagDataHob->PllOvData + ); + ASSERT_EFI_ERROR(Status); + + TRACE((-1,"Clear Pll Overvoltage Flag %r.\n",Status)); + } + + TRACE((-1,"CpuPllOverVoltageProgress End\n")); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SaveMEFWVersion +// +// Description: CPU pll over voltage initialize code in DXE phase +// +// Input: +// IN EFI_EVENT Event +// IN VOID *Context +// +// Output: EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SaveMEFWVersion( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_STATUS Status; + ME_INFO_SETUP_DATA MeInfoSetupData; + UINTN DataSize = sizeof(ME_INFO_SETUP_DATA); + + TRACE((-1,"SaveMEFWVersion start!!\n")); + + pBS->CloseEvent( Event); + Status = pRS->GetVariable( + L"MeInfoSetup", + &gMeSetupInfoGuid, + NULL, + &DataSize, + &MeInfoSetupData + ); + if(EFI_ERROR(Status)){ + TRACE((-1,"Get ME firmware version fail!!\n")); + return Status; + } + + Status = pRS->SetVariable( + L"MEFWVersion", + &gAmiCpuMEFwVerGuid, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof(ME_INFO_SETUP_DATA), + &MeInfoSetupData + ); + if(EFI_ERROR(Status)){ + TRACE((-1,"Set ME firmware version fail!!\n")); + return Status; + } + + TRACE((-1,"SaveMEFWVersion end!!\n")); + + return Status; +} +#endif +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuDxeMiscFuncs +// +// Description: +// +// Input: +// None +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CpuDxeMiscFuncs(VOID) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + +#if PERF_TUNE_SUPPORT == 1 + { + + EFI_GUID PerfTuneAslProtocolGuid = PERF_TUNE_ASL_PROTOCOL_GUID; + EFI_EVENT IntelXtuCpuCallbackEvt; + VOID *IntelXtuCpuCallbackReg; + VOID *FirstHob; + EFI_EVENT PllOvCallbackEvt; + VOID *PllOvCallbackReg; + EFI_EVENT MEFWCallbackEvt; + VOID *MEFWCallbackReg; + EFI_GUID gAmiPerfTuneDataHobGuid = AMI_PERF_TUNE_DATA_HOB_GUID; + EFI_GUID gAmiOcConfigHobGuid = AMI_OVERCLOCK_CONFIG_HOB_GUID; + UINTN DataSize; + OVERCLOCKING_CONFIG_HOB *OcConfigHob = NULL; + CPU_RATIO_LIMIT_HOB *CpuRatioLimitHob = NULL; + UINT32 Attributes = 0; + + FirstHob = GetEfiConfigurationTable(pST, &gHobListGuid); + + //If First boot or CPU change is detected, record new MaxNonTurboRatio. + CpuRatioLimitHob = (CPU_RATIO_LIMIT_HOB*)FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &CpuRatioLimitHob))) { + if (guidcmp(&CpuRatioLimitHob->EfiHobGuidType.Name, &gAmiCpuRatioLimitHobGuid) == 0){ + if(CpuRatioLimitHob->IsChangeCpu){ + Status = pRS->SetVariable( + L"CpuRatioLimit", + &gAmiCpuRatioLimitHobGuid, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof(CPU_RATIO_LIMIT_DATA), + &CpuRatioLimitHob->CpuRatioLimitData ); + ASSERT_EFI_ERROR(Status); + } + break; + } + } + + // get TdcTdpHob. + gTdcTdpHob = (AMI_INTERNAL_FACTORY_TDC_TDP_HOB*)FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &gTdcTdpHob))) { + if (guidcmp(&gTdcTdpHob->EfiHobGuidType.Name, &gAmiInternalFactoryTdcTdpHobGuid) == 0){ + + Status = RegisterProtocolCallback( + &PerfTuneAslProtocolGuid, + IntelXtuFillCpuDataCallBack, + NULL, + &IntelXtuCpuCallbackEvt, + &IntelXtuCpuCallbackReg + ); + + ASSERT_EFI_ERROR(Status); + break; + } + } + if(!EFI_ERROR(Status)){ + // get overclocking config HOB + OcConfigHob = (OVERCLOCKING_CONFIG_HOB*)FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &OcConfigHob))) { + if (guidcmp(&OcConfigHob->EfiHobGuidType.Name, &gAmiOcConfigHobGuid) == 0){ + break; + } + } + gOcConfigData = NULL; + if(!EFI_ERROR(Status)) + gOcConfigData = &OcConfigHob->OverclockData; + else + ASSERT_EFI_ERROR(Status); + + // get Cpu ratio limit default value. + DataSize = sizeof(CPU_RATIO_LIMIT_DATA); + Status = pBS->AllocatePool(EfiBootServicesData, DataSize, &gCpuRatioLimitData); + Status = pRS->GetVariable( + L"CpuRatioLimit", + &gAmiCpuRatioLimitHobGuid, + NULL, + &DataSize, + gCpuRatioLimitData ); + ASSERT_EFI_ERROR(Status); + + // Restores default value when Cpu change or watch dog timeout. + if( gOcConfigData->IsCpuRunDefault ){ + SETUP_DATA *SetupData; + DataSize = sizeof(SETUP_DATA); + Status = pBS->AllocatePool(EfiBootServicesData, DataSize, &SetupData); + Status = pRS->GetVariable( + L"Setup", + &gSetupGuid, + &Attributes, + &DataSize, + SetupData + ); + ASSERT_EFI_ERROR(Status); + + SetupData->LcSbSelect = 0; + SetupData->PackageCurrentLock = 0; + + Status = pRS->SetVariable( + L"Setup", + &gSetupGuid, + Attributes, + sizeof(SETUP_DATA), + SetupData + ); + ASSERT_EFI_ERROR(Status); + pBS->FreePool(SetupData); + } + + // get current setting data of XTU + DataSize = sizeof(BIOS_SETTING_DATA); + Status = pBS->AllocatePool(EfiBootServicesData, DataSize, &gBiosSettingData); + Status = pRS->GetVariable( + L"OcCurrent", + &gSetupGuid, + NULL, + &DataSize, + gBiosSettingData); + } + + Status = RegisterProtocolCallback( + &InternalWdtGuid, + CpuPllOverVoltageProgress, + NULL, + &PllOvCallbackEvt, + &PllOvCallbackReg ); + ASSERT_EFI_ERROR(Status); + + Status = RegisterProtocolCallback( + &gDxePlatformMePolicyGuid, + SaveMEFWVersion, + NULL, + &MEFWCallbackEvt, + &MEFWCallbackReg); + ASSERT_EFI_ERROR(Status); + } +#endif + + NumberOfPStatesSupport(); + + return; +} diff --git a/Core/CPU/CpuPei.c b/Core/CPU/CpuPei.c new file mode 100644 index 0000000..901171b --- /dev/null +++ b/Core/CPU/CpuPei.c @@ -0,0 +1,936 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.c 9 8/05/14 2:21a Crystallee $ +// +// $Revision: 9 $ +// +// $Date: 8/05/14 2:21a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.c $ +// +// 9 8/05/14 2:21a Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] For backward compatible, add old MTRR setting method +// back. Change new MTRR setting method to Policy2. +// +// 8 7/16/14 4:12a Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] Add WbMemMap and UcMemMap vectors size to prevent +// accessing out of bound. +// +// 7 7/08/14 3:35a Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] Add all the possible methods to describing memory in +// MTRRS. +// [Files] CpuPei.c, CpuPei.h, CpuPeiFuncs.c +// +// 6 6/25/14 2:15a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Add APIC version information in CpuInfoHob +// +// 5 6/13/14 2:22a Davidhsieh +// [TAG] EIP173454 +// [Category] Improvement +// [Description] Add TSEG address and size in CpuInfoHob +// +// 4 9/05/12 1:40a Davidhsieh +// Rename PEI_IFFS_TRANSITION_START_PPI_GUID to +// PEI_RAPID_START_TRANSITION_START_PPI_GUID +// +// 3 3/16/12 3:11a Davidhsieh +// Setup items create for CPU RC policy +// +// 2 3/09/12 2:13a Davidhsieh +// Create BIST data +// +// 1 2/07/12 3:58a Davidhsieh +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// Name: CpuPei.c +// +// Description: +// This file is the main CPU PEI component file. This component utilizes +// CPU I/O & PCI CFG PPI to publish early CPU Init PPI which can be used +// by NB PEI to load itself. Also this file contains a CPU init routine +// to be executed in permanent memory present environment. This is handled +// by issuing a notifyPPI on permanent memory PPI. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "cpu.h" +#include "AmiCspLibInc.h" +#include <AmiPeiLib.h> +#include <core\PeiHob.h> +#include <token.h> +#include <Ppi\ReadOnlyVariable.h> +#include "CpuPei.h" + +#define EFI_HT_BIST_HOB_GUID \ + { \ + 0xbe644001, 0xe7d4, 0x48b1, 0xb0, 0x96, 0x8b, 0xa0, 0x47, 0xbc, 0x7a, 0xe7 \ + } + +typedef struct _CPU_BIST_HOB { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Name; + UINT32 ApicId; + UINT32 BIST; +} CPU_BIST_HOB; + +// Setup GUID variables for installing, locating and notifying PPIs +EFI_GUID gPeiCachePpiGuid = PEI_CACHE_PPI_GUID; +EFI_GUID gEfiPeiEndOfPeiPhasePpiGuid = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID; +EFI_GUID gAmiCpuinfoHobGuid = AMI_CPUINFO_HOB_GUID; +EFI_GUID gEfiPeiReadOnlyVariablePpiGuid = EFI_PEI_READ_ONLY_VARIABLE_PPI_GUID; +EFI_GUID gAmiInternaluCodeHobGuid = AMI_INTERNAL_UCODE_HOB_GUID; +EFI_GUID gSmmHobGuid = SMM_HOB_GUID; +EFI_GUID gPeiRapidStartTransitionStartPpiGuid = PEI_RAPID_START_TRANSITION_START_PPI_GUID; +//EFI_GUID gCacheInstallGuid = EFI_CACHE_INSTALL_PPI_GUID; +EFI_GUID gAmiStatusCodeCpuBistDataGuid = AMI_STATUS_CODE_CPU_BIST_DATA_GUID; +EFI_GUID gEfiHtBistHobGuid = EFI_HT_BIST_HOB_GUID; + +EFI_STATUS NotifyAtPeiEnd ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi +); + +EFI_PEI_NOTIFY_DESCRIPTOR CpuNotifyDescs = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiEndOfPeiPhasePpiGuid, + NotifyAtPeiEnd +}; + +/*EFI_PEI_PPI_DESCRIPTOR CacheInstallPpi[] = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gCacheInstallGuid, + NULL +};*/ + +EFI_PEI_PPI_DESCRIPTOR IffsTransitionStartPpiDescriptor = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), \ + &gPeiRapidStartTransitionStartPpiGuid, + NULL +}; + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: ReportBistStatusCodes +// +// Description: Report the BIST Status Code. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ReportBistStatusCodes(IN EFI_PEI_SERVICES **PeiServices, IN CPUINFO_HOB *CpuInfoHob, IN UINT32 NumCpus) +{ + UINT32 i; + AMI_STATUS_CODE_CPU_BIST_DATA BistData; + + BistData.DataHeader.HeaderSize = sizeof(EFI_STATUS_CODE_DATA); + BistData.DataHeader.Size = sizeof(UINT32); + MemCpy(&BistData.DataHeader.Type, &gAmiStatusCodeCpuBistDataGuid, sizeof(EFI_GUID)); + + for (i = 0; i < NumCpus; ++i) { + if (CpuInfoHob->Cpuinfo[i].BIST != 0) { + PEI_TRACE((-1, PeiServices, "CpuInfo[%x].BIST = %x \n", i, CpuInfoHob->Cpuinfo[i].BIST)); + BistData.Bist = CpuInfoHob->Cpuinfo[i].BIST; + + (*PeiServices)->ReportStatusCode( + PeiServices, + EFI_ERROR_CODE| EFI_ERROR_MAJOR, + PEI_CPU_SELF_TEST_FAILED, + CpuInfoHob->Cpuinfo[i].ApicId, + NULL, + (EFI_STATUS_CODE_DATA*)&BistData + ); + } + } +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CreateCpuHobWithDefaults +// +// Description: Create CPU Hob and fill in default data. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// IN UINT8 NumCpus +// +// Output: +// CPUINFO_HOB * +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +CPUINFO_HOB * CreateCpuHobWithDefaults(EFI_PEI_SERVICES **PeiServices, UINT8 NumCpus) +{ + CPUINFO_HOB *CpuinfoHob; + EFI_STATUS Status; + UINT32 RegEax; + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; + UINT8 i; + VOID *FirstHob; + CPU_BIST_HOB *SecBistHob; + + //Create hob for storing Cpu Data + Status = (**PeiServices).CreateHob(PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + //NOTE: sizeof(CPUINFO_HOB) already includes size of one CPUINFO structure + sizeof(CPUINFO_HOB) + (NumCpus - 1) * sizeof(CPUINFO), + &CpuinfoHob + ); + ASSERT_PEI_ERROR(PeiServices, Status); + + CpuinfoHob->EfiHobGuidType.Name = gAmiCpuinfoHobGuid; + CpuinfoHob->CpuCount = NumCpus; + CpuinfoHob->NodeCount = NUMBER_CPU_SOCKETS; + CpuinfoHob->CacheLineSize = 64; + + CpuinfoHob->TsegAddress = NBGetTsegBase(); + CpuinfoHob->TsegSize = TSEG_SIZE; + + + for(i = 0; i < NumCpus; ++i) { + CpuinfoHob->Cpuinfo[i].Valid = FALSE; + CpuinfoHob->Cpuinfo[i].Disabled = FALSE; + CpuinfoHob->Cpuinfo[i].BIST = 0; + CpuinfoHob->Cpuinfo[i].ApicVer = (UINT8)MemRead32((UINT32*)(UINTN)(LOCAL_APIC_BASE + APIC_VERSION_REGISTER)); + } +//Save BSP features to CpuinfoHob + CPULib_CpuID(0x01, &RegEax, &RegEbx, &RegEcx, &RegEdx); + CpuinfoHob->CpuFeatures.FeatureEcx = RegEcx; + CpuinfoHob->CpuFeatures.FeatureEdx = RegEdx; + + CPULib_CpuID(0x80000001, &RegEax, &RegEbx, &RegEcx, &RegEdx); + CpuinfoHob->CpuFeatures.ExtFeatureEax = RegEax; + CpuinfoHob->CpuFeatures.ExtFeatureEbx = RegEbx; + CpuinfoHob->CpuFeatures.ExtFeatureEcx = RegEcx; + CpuinfoHob->CpuFeatures.ExtFeatureEdx = RegEdx; + + (*PeiServices)->GetHobList(PeiServices, &FirstHob); + if (!FirstHob) ASSERT_PEI_ERROR(PeiServices, EFI_NOT_FOUND); + + (VOID*)SecBistHob = FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &SecBistHob))) { + if (guidcmp(&((EFI_HOB_GUID_TYPE*)SecBistHob)->Name, &gEfiHtBistHobGuid) == 0) { + break; + } + } + + if (!EFI_ERROR(Status)) { + CpuinfoHob->Cpuinfo[SecBistHob->ApicId].BIST = SecBistHob->BIST; + } + + return CpuinfoHob; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: UpdateOrCreateCpuHob +// +// Description: Finds or Create Cpu Hob and initialize it. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// +// Output: +// VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID UpdateOrCreateCpuHob(EFI_PEI_SERVICES **PeiServices) +{ + VOID *FirstHob; + EFI_HOB_CPU *CpuHob; + UINT32 RegEax; + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; + EFI_STATUS Status; + + (*PeiServices)->GetHobList(PeiServices, &FirstHob); + if (!FirstHob) ASSERT_PEI_ERROR(PeiServices, EFI_NOT_FOUND); + + CpuHob = (EFI_HOB_CPU*) FirstHob; + Status = FindNextHobByType(EFI_HOB_TYPE_CPU, &CpuHob); + if (EFI_ERROR(Status)) { + Status = (**PeiServices).CreateHob(PeiServices, + EFI_HOB_TYPE_CPU, + sizeof(CpuHob), + &CpuHob + ); + ASSERT_PEI_ERROR(PeiServices, Status); + + CpuHob->SizeOfMemorySpace = 0xff; + MemSet(CpuHob->Reserved, 6, 0); + } + + CPULib_CpuID(0x80000008, &RegEax, &RegEbx, &RegEcx, &RegEdx); + RegEax &= 0xff; + if (RegEax < CpuHob->SizeOfMemorySpace) CpuHob->SizeOfMemorySpace = RegEax; + CpuHob->SizeOfIoSpace = 16; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: NotifyAtPeiEnd +// +// Description: According to resource descriptor HOBs to config system cache. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor +// IN VOID *Ppi +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NotifyAtPeiEnd ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi +) +{ + EFI_STATUS Status; + PEI_CACHE_PPI *CachePpi; + UINT64 MaxMemoryLength; + EFI_BOOT_MODE BootMode; + +#if MTRR_POLICY == 1 + EFI_PEI_HOB_POINTERS Hob; + UINT64 Above4GMemoryLength = 0; + MEMORY_MAP WbMemMap[12]; //Memory map of wb regions. + MEMORY_MAP UcMemMap[12]; //Memory map of uc regions. + UINTN i; +#endif + // + //Get bootmode + // + Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode); + PEI_TRACE((-1, PeiServices, "CPUPEI Get boot mode in end of PEI\n")); + + if (BootMode == BOOT_ON_S3_RESUME){ + PEI_TRACE((-1, PeiServices, "CPUPEI boot mode is S3 in end of PEI\n")); + //Trigger SWSMI to save CPU fixed & varible MTRRs + IoWrite8(SW_SMI_IO_ADDRESS, SW_SMI_RESTORE_MSR); + IoWrite8(SW_SMI_IO_ADDRESS, SW_SMI_S3_RESTORE_MSR_FROM_SDL); + }else{ + // + // Load Cache PPI + // + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gPeiCachePpiGuid, + 0, + NULL, + &CachePpi + ) ; + ASSERT_PEI_ERROR (PeiServices, Status); +#if MTRR_POLICY == 1 + //if MTRR_POLICY = 1, init MTRR above4G here + Above4GMemoryLength = 0; + (*PeiServices)->GetHobList(PeiServices, &Hob.Raw); + //Get above 4G memory length + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) || + ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) + ) { + if (Hob.ResourceDescriptor->PhysicalStart >= SIZE_4G + && Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + Above4GMemoryLength += (Hob.ResourceDescriptor->ResourceLength); + } + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + // + // Program the MTRR for above 4G memory range if it exist + // or just disable cache flash range + // + if (Above4GMemoryLength > 0) { + Status = InitMtrrPolicy1(PeiServices, WbMemMap, UcMemMap, Above4GMemoryLength); + if(EFI_ERROR(Status)) + Status = InitMtrrPolicy2(PeiServices, WbMemMap, UcMemMap, Above4GMemoryLength); + + //If cache map init successful, start program MTRR + if(!EFI_ERROR(Status)){ + CachePpi->ResetCache( + PeiServices, + CachePpi); + //WB region start first + for(i = 0; i < 10 ;i++){ + CachePpi->SetCache( + PeiServices, + CachePpi, + WbMemMap[i].Base, + WbMemMap[i].Len, + EfiCacheTypeWriteBack); + if(WbMemMap[i + 1].Len == 0) break; + } + //UC region start + if(UcMemMap[0].Len != 0){ + for(i = 0; i < 10 ;i++){ + CachePpi->SetCache( + PeiServices, + CachePpi, + UcMemMap[i].Base, + UcMemMap[i].Len, + EfiCacheTypeUncacheable); + if(UcMemMap[i + 1].Len == 0) break; + } + } + // + // Programm fix MTRRs WB from 0 to A0000 + // + CachePpi->SetCache( + PeiServices, + CachePpi, + 0, + 640*1024, + EfiCacheTypeWriteBack ); + } else{ //Get MTRR setting fail, still need disable cache flash range + MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE); + if (MaxMemoryLength < FLASH_SIZE) { + MaxMemoryLength = Shl64 (MaxMemoryLength, 1); + } + PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength))); + Status = CachePpi->SetCache ( + PeiServices, + CachePpi, + (SIZE_4G - MaxMemoryLength), + MaxMemoryLength, + EfiCacheTypeUncacheable + ); + + if (Status) PEI_TRACE((-1, PeiServices, "Disabling Flash Area Cache Error!!\n")); + } + } else{ // if (Above4GMemoryLength > 0) + MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE); + if (MaxMemoryLength < FLASH_SIZE) { + MaxMemoryLength = Shl64 (MaxMemoryLength, 1); + } + PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength))); + Status = CachePpi->SetCache ( + PeiServices, + CachePpi, + (SIZE_4G - MaxMemoryLength), + MaxMemoryLength, + EfiCacheTypeUncacheable + ); + + if (Status) PEI_TRACE((-1, PeiServices, "Disabling Flash Area Cache Error!!\n")); + } + // + //Disable NEM, Update MTRR setting from MTRR buffer + // + CachePpi->ActivateCache (PeiServices, CachePpi); +#else + // + // MTRR for above 4G memory range is already done at this point, + // only disable cache flash range is required + // + + MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE); + if (MaxMemoryLength < FLASH_SIZE) { + MaxMemoryLength = Shl64 (MaxMemoryLength, 1); + } + + PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength))); + Status = CachePpi->SetCache ( + PeiServices, + CachePpi, + (SIZE_4G - MaxMemoryLength), + MaxMemoryLength, + EfiCacheTypeUncacheable ); + + if (Status) PEI_TRACE((-1, PeiServices, "Disabling Flash Area Cache Error!!\n")); + + // + //Disable NEM, Update MTRR setting from MTRR buffer + // + CachePpi->ActivateCache (PeiServices, CachePpi); +#endif + } + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: SetupCache +// +// Description: According to resource descriptor HOBs to config system cache. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// IN EFI_BOOT_MODE BootMode +// +// Output: +// VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SetupCache ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_BOOT_MODE BootMode) +{ + EFI_STATUS Status; + PEI_CACHE_PPI *CachePpi; + UINT64 MemoryLength; + UINT64 MemoryLengthUc; + UINT64 MaxMemoryLength; + UINT64 CurrentBaseAddress; + UINT64 Above4GMemoryLength; + UINT64 PowerTwo; + UINT64 PowerTwoEnd; + UINT8 MtrrCount = 0; +#if MTRR_POLICY == 0 + EFI_PEI_HOB_POINTERS Hob; +#endif + // + // Load Cache PPI + // + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gPeiCachePpiGuid, + 0, + NULL, + &CachePpi + ) ; + ASSERT_PEI_ERROR (PeiServices, Status); + + // + // Clear the CAR Settings + // + CachePpi->ResetCache( + PeiServices, + CachePpi + ); + + + // + // Parse the HOB list and determine the amount of memory installed + // The first 1MB will be set until overridden by the CSM. + // The above 4G memory length will be calculated separately. + // + + MemoryLength = SIZE_1M; + Above4GMemoryLength = 0; + + MemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + PEI_TRACE((-1, PeiServices, "Memory Length below 4G= %lx.\n", MemoryLength)); + + // + // Record the current address + // + CurrentBaseAddress = 0; + // + // Set WB loop first + // + + for (PowerTwo = SIZE_2G, PowerTwoEnd = SIZE_64M; PowerTwo >= PowerTwoEnd; PowerTwo = Shr64 (PowerTwo, 1)) { + if (MemoryLength >= PowerTwo && MtrrCount < 8) { + PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", PowerTwo, CurrentBaseAddress)); + CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, PowerTwo, EfiCacheTypeWriteBack); + MtrrCount++; + CurrentBaseAddress += PowerTwo; + MemoryLength -= PowerTwo; + } + } + // + // Get Max Address for WB/UC + // + if (MemoryLength == GetPowerOfTwo64 (MemoryLength)) { + MaxMemoryLength = MemoryLength; + } else { + MaxMemoryLength = GetPowerOfTwo64 (Shl64 (MemoryLength, 1)); + } + // + // Set the MAX memory range as WB + // + if (MaxMemoryLength != 0 && MtrrCount < 8) { + PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", MaxMemoryLength, CurrentBaseAddress)); + CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, MaxMemoryLength, EfiCacheTypeWriteBack); + MtrrCount++; + } + // + // Start Setting UC here + // + while (MaxMemoryLength != MemoryLength) { + if (MtrrCount == 8) break; + MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); + PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx.\n", MemoryLengthUc, CurrentBaseAddress + MaxMemoryLength - MemoryLengthUc)); + CachePpi->SetCache ( + PeiServices, + CachePpi, + CurrentBaseAddress + MaxMemoryLength - MemoryLengthUc, + MemoryLengthUc, + EfiCacheTypeUncacheable + ); + MtrrCount++; + MaxMemoryLength -= MemoryLengthUc; + } + +#if MTRR_POLICY == 0 + // + // Program the MTRR for above 4G memory range + // if MTRR_POLICY = 1, program the MTRR for above 4G memory range at end of PEI + // + if (BootMode != BOOT_ON_S3_RESUME){ + (*PeiServices)->GetHobList(PeiServices, &Hob.Raw); + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) || + ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) + ) { + // + // Calculate the memory above 4G + // + if (Hob.ResourceDescriptor->PhysicalStart >= SIZE_4G + && Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + Above4GMemoryLength += (Hob.ResourceDescriptor->ResourceLength); + } + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + } + PEI_TRACE((-1, PeiServices, "Memory Length Above 4G= %lx.\n", Above4GMemoryLength)); + if (Above4GMemoryLength > 0) { + CurrentBaseAddress = SIZE_4G; + while (Above4GMemoryLength >= SIZE_4G) { + if (MtrrCount == 10) break; + PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", SIZE_4G, CurrentBaseAddress)); + CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, SIZE_4G, EfiCacheTypeWriteBack); + MtrrCount++; + Above4GMemoryLength -= SIZE_4G; + CurrentBaseAddress += SIZE_4G; + } + // + // Set WB loop first + // + for (PowerTwo = SIZE_2G, PowerTwoEnd = SIZE_256M; PowerTwo >= PowerTwoEnd; PowerTwo = Shr64 (PowerTwo, 1)) { + if (MtrrCount == 10) break; + if (Above4GMemoryLength >= PowerTwo) { + PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", PowerTwo, CurrentBaseAddress)); + CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, PowerTwo, EfiCacheTypeWriteBack); + MtrrCount++; + CurrentBaseAddress += PowerTwo; + Above4GMemoryLength -= PowerTwo; + } + } + // + // Get Max Address for WB/UC + // + if (Above4GMemoryLength == GetPowerOfTwo64 (Above4GMemoryLength)) { + MaxMemoryLength = Above4GMemoryLength; + } else { + MaxMemoryLength = GetPowerOfTwo64 (Shl64(Above4GMemoryLength, 1)); + } + // + // Set the MAX memory range as WB + // + if (MaxMemoryLength != 0 && MtrrCount < 10) { + //PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", MaxMemoryLength, CurrentBaseAddress)); + CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, MaxMemoryLength, EfiCacheTypeWriteBack); + MtrrCount++; + } + // + // Start Setting UC here + // + while (MaxMemoryLength != Above4GMemoryLength) { + if (MtrrCount == 10) break; + MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - Above4GMemoryLength); + if (MtrrCount == 9 && (MaxMemoryLength - Above4GMemoryLength) != MemoryLengthUc) { + MemoryLengthUc = Shl64 (MemoryLengthUc, 1); + } + PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx.\n", MemoryLengthUc, CurrentBaseAddress + MaxMemoryLength - MemoryLengthUc)); + CachePpi->SetCache ( + PeiServices, + CachePpi, + (CurrentBaseAddress+ MaxMemoryLength - MemoryLengthUc), + MemoryLengthUc, + EfiCacheTypeUncacheable + ); + MtrrCount++; + MaxMemoryLength -= MemoryLengthUc; + } + } +#endif + // + // Programm fix MTRRs WB from 0 to A0000 + // + PEI_TRACE((-1, PeiServices, "WB Memory Length = %08x at %09x.\n", 640*1024, 0)); + CachePpi->SetCache( + PeiServices, + CachePpi, + 0, + 640*1024, + EfiCacheTypeWriteBack + ); + +#if PEI_CACHE_FLASH_ENABLED + // + // Cache Flash Area + // + MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE); + if (MaxMemoryLength < FLASH_SIZE) { + MaxMemoryLength = Shl64 (MaxMemoryLength, 1); + } + + PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength))); + Status = CachePpi->SetCache ( + PeiServices, + CachePpi, + (SIZE_4G - MaxMemoryLength), + MaxMemoryLength, + EfiCacheTypeWriteProtected + ); + + if (Status) PEI_TRACE((-1, PeiServices, "Flash Area Caching Error!!\n")); +#endif + // + //Disable NEM, Update MTRR setting from MTRR buffer + // + CachePpi->ActivateCache (PeiServices, CachePpi); + + //Call back to disable caching flash at end of PEI. + (*PeiServices)->NotifyPpi( + PeiServices, + &CpuNotifyDescs + ); + // + // Install EFI_CACHE_INSTALL_PPI_GUID to indicate memory and CPU cache are initialzed. + // + /*Status = (*PeiServices)->InstallPpi ( + PeiServices, + CacheInstallPpi); + ASSERT_PEI_ERROR(PeiServices, Status);*/ +} +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: CpuPeiEntry +// +// Description: AMI CPU PEI driver entry +// +// Input: +// IN EFI_FFS_FILE_HEADER *FfsHeader +// IN EFI_PEI_SERVICES **PeiServices +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CpuPeiEntry( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariable; + EFI_BOOT_MODE BootMode; + EFI_STATUS Status; + CPUINFO_HOB *CpuinfoHob; + UINT32 NumCpus; + BOOLEAN X2ApicEnabled = FALSE; + BOOLEAN Serialize = FALSE; + UINT32 CpuSignature = GetCpuSignature(); + UINT32 CpuSigNoVer = CpuSignature & 0xfffffff0; + VOID *MicrocodeAddr = NULL; + UINT32 MicrocodeSize = 0; + EFI_PHYSICAL_ADDRESS MicrocodeBuffer; + AMI_INTERNAL_UCODE_HOB *uCodeHob; + UINT32 Tseg = (UINT32)NBGetTsegBase(); + SMM_HOB *SmmHob; + UINT32 SmmBspBase; + UINT32 SmmCpuBase; + UINT32 SmmBase; + UINT32 LargestSmmBase; + UINT32 MaxCpusBeforeOverlap; + UINT32 BeforeOverlapCount; + UINT32 NextUnoverlapSmmBase; + UINT32 i; + + PEI_PROGRESS_CODE(PeiServices, PEI_CPU_INIT); + + Status = (*PeiServices)->LocatePpi( + PeiServices, &gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, &ReadOnlyVariable + ); + ASSERT_PEI_ERROR(PeiServices, Status); + + Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode); + ASSERT_PEI_ERROR(PeiServices, Status); + + SetupCache(PeiServices, BootMode); + UpdateOrCreateCpuHob(PeiServices); + + Status = (*PeiServices)->InstallPpi( PeiServices, \ + &IffsTransitionStartPpiDescriptor); + + //After initialized, APs are in holding loop until halted. + NumCpus = (UINT32)((UINT8)ReadMsr(MSR_CORE_THREAD_COUNT)); + + PEI_TRACE((-1, PeiServices, "Cpu Pei - number of Cpus %x\n",NumCpus )); + CpuinfoHob = CreateCpuHobWithDefaults(PeiServices, NumCpus); + + CpuinfoHob->BspNo = 0; + + ReportBistStatusCodes(PeiServices, CpuinfoHob, NumCpus); + //Create Smm Hob + Status = (*PeiServices)->CreateHob( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(SMM_HOB)+ (NumCpus - 1) * sizeof(VOID*), + &SmmHob + ); + ASSERT_PEI_ERROR(PeiServices, Status); + MemCpy(&SmmHob->EfiHobGuidType.Name, &gSmmHobGuid, sizeof(EFI_GUID)); + + SmmHob->Tseg = Tseg; + SmmHob->TsegLength = TSEG_SIZE; + PEI_ASSERT(PeiServices, (SmmHob->Tseg & 0x7fffff)==0); //Must be 8MB boundary. + PEI_ASSERT(PeiServices, TSEG_SIZE >= 0x800000); //Must be >= 8MB. + + SmmHob->IedStart = Tseg + TSEG_SIZE - IED_SIZE; + SmmHob->IedSize = IED_SIZE; + + SmmHob->NumCpus = NumCpus; + SmmHob->Bsp = 0; + + SmmBspBase = (UINTN)Tseg - 0x8000; //Get bottom of TSEG - 0x8000 + SmmBase = SmmBspBase + MAX_SMM_SAVE_STATE_SIZE; + + MaxCpusBeforeOverlap = 0x8000 / MAX_SMM_SAVE_STATE_SIZE - 1; + BeforeOverlapCount = 0; + NextUnoverlapSmmBase = (UINTN)Tseg - 0x8000 + 0x10000 - 2 * MAX_SMM_SAVE_STATE_SIZE; + LargestSmmBase = 0; + + for (i = 0; i < NumCpus; ++i) + { + if (i == SmmHob->Bsp) + { + SmmCpuBase = SmmBspBase; + if (SmmCpuBase >= ((UINTN)Tseg - 0x8000)) ++BeforeOverlapCount; //Only increment count if BSP in TSEG. + } + else + { + SmmCpuBase = SmmBase; + ++BeforeOverlapCount; + if (BeforeOverlapCount < MaxCpusBeforeOverlap) + { + SmmBase += MAX_SMM_SAVE_STATE_SIZE; + } + else + { + SmmBase = NextUnoverlapSmmBase; + NextUnoverlapSmmBase += 0x10000 - 2 * MAX_SMM_SAVE_STATE_SIZE; + BeforeOverlapCount = 0; + } + } + + SmmHob->SmmBase[i] = SmmCpuBase; + + if (SmmCpuBase > LargestSmmBase) LargestSmmBase = SmmCpuBase; + } + + if (LargestSmmBase < 0xC0000) + SmmHob->ManagedMemStart = Tseg; + else + SmmHob->ManagedMemStart = LargestSmmBase + 0x10000; //+ 0x10000 = end of save state. + + SmmHob->ManagedMemSize = Tseg + TSEG_SIZE - SmmHob->ManagedMemStart; + SmmHob->ManagedMemSize -= SmmHob->IedSize; + + PEI_TRACE((-1, PeiServices, "TSEG Base %x\n", SmmHob->Tseg)); + PEI_TRACE((-1, PeiServices, "TSEG Size %x\n", SmmHob->TsegLength)); + PEI_TRACE((-1, PeiServices, "ManagedMemStart %x\n", SmmHob->ManagedMemStart)); + + if (BootMode != BOOT_ON_S3_RESUME){ + //Copy CPU microcode from ROM to RAM, when flash ragne is still cached + //and create hob to record the microcode address + //Create CPU microcode HOB + MicrocodeAddr = CPULib_FindMicrocode(); + + if(MicrocodeAddr != NULL){ + PEI_TRACE((-1, PeiServices, "Cpu uCode ID - %x\n",((MICROCODE_HEADER*)MicrocodeAddr)->CpuSignature )); + MicrocodeSize = ((MICROCODE_HEADER*)MicrocodeAddr)->TotalSize; + + Status = (*PeiServices)->AllocatePages ( + PeiServices, + EfiBootServicesData, + EFI_SIZE_TO_PAGES (MicrocodeSize), + &MicrocodeBuffer ); + if(!EFI_ERROR(Status)){ + // Copy Microcode from ROM to RAM + (*PeiServices)->CopyMem ( + (VOID*)MicrocodeBuffer, + (VOID*)MicrocodeAddr, + (UINTN)MicrocodeSize ); + + Status = (*PeiServices)->CreateHob( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(AMI_INTERNAL_UCODE_HOB), + &uCodeHob ); + if (!EFI_ERROR(Status)){ + MemCpy(&uCodeHob->EfiHobGuidType.Name, &gAmiInternaluCodeHobGuid, sizeof(EFI_GUID)); + uCodeHob->uCodeAddr = (UINT32)MicrocodeBuffer; + } + } + } + } + + CpuPeiMiscFuncs(PeiServices, ReadOnlyVariable, BootMode); + + return EFI_SUCCESS; + +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + diff --git a/Core/CPU/CpuPei.dxs b/Core/CPU/CpuPei.dxs new file mode 100644 index 0000000..ba054a4 --- /dev/null +++ b/Core/CPU/CpuPei.dxs @@ -0,0 +1,65 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.dxs 1 2/07/12 3:58a Davidhsieh $ +// +// $Revision: 1 $ +// +// $Date: 2/07/12 3:58a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.dxs $ +// +// 1 2/07/12 3:58a Davidhsieh +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// Name: CPUPEI.dxs +// +// Description: Dependency expression for CPU PEI component. +// Currently it is dependent on the CPU IO & PCI CFG PPI. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <pei.h> +#include <ppi\CpuIo.h> +#include <ppi\PciCfg.h> +#include <Ppi\ReadOnlyVariable.h> + +DEPENDENCY_START + EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI AND + EFI_PEI_MASTER_BOOT_MODE_PEIM_PPI AND + EFI_PEI_CPU_IO_PPI_INSTALLED_GUID AND + EFI_PEI_PCI_CFG_PPI_INSTALLED_GUID AND + EFI_PEI_READ_ONLY_VARIABLE_PPI_GUID +DEPENDENCY_END + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/CpuPei.h b/Core/CPU/CpuPei.h new file mode 100644 index 0000000..b004293 --- /dev/null +++ b/Core/CPU/CpuPei.h @@ -0,0 +1,206 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.h 4 8/05/14 2:21a Crystallee $ +// +// $Revision: 4 $ +// +// $Date: 8/05/14 2:21a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.h $ +// +// 4 8/05/14 2:21a Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] For backward compatible, add old MTRR setting method +// back. Change new MTRR setting method to Policy2. +// +// 3 7/08/14 3:35a Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] Add all the possible methods to describing memory in +// MTRRS. +// [Files] CpuPei.c, CpuPei.h, CpuPeiFuncs.c +// +// 2 9/05/12 1:40a Davidhsieh +// Rename PEI_IFFS_TRANSITION_START_PPI_GUID to +// PEI_RAPID_START_TRANSITION_START_PPI_GUID +// +// 1 2/07/12 3:58a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuPei.h +// +// Description: Cpu PEI header file. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef __CPU_PEI_H__ +#define __CPU_PEI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define IED_SIZE 0x400000 +#define VariableMtrrCount 10 + +#define SIZE_1M 0x100000 +#define SIZE_64M 0x4000000 +#define SIZE_128M 0x8000000 +#define SIZE_256M 0x10000000 +#define SIZE_512M 0x20000000 +#define SIZE_1G 0x40000000 +#define SIZE_2G 0x80000000 +#define SIZE_4G 0x100000000 +#define SIZE_8G 0x200000000 +#define SIZE_16G 0x400000000 + +//Chagned in IvyBridge RC 0.8 +//#define PEI_CACHE_PPI_GUID \ +// {0xc153205a, 0xe898, 0x4c24, 0x86, 0x89, 0xa4, 0xb4, 0xbc, 0xc5, 0xc8, 0xa2} +#define PEI_CACHE_PPI_GUID \ + {0x9be4bc2, 0x790e, 0x4dea, 0x8b, 0xdc, 0x38, 0x5, 0x16, 0x98, 0x39, 0x44} + +#define AMI_INTERNAL_UCODE_HOB_GUID \ + {0x94567c6f, 0xf7a9, 0x4229, 0x13, 0x30, 0xfe, 0x11, 0xcc, 0xab, 0x3a, 0x11} + +#define PEI_RAPID_START_TRANSITION_START_PPI_GUID \ + { \ + 0xde8f2878, 0x36d5, 0x498e, 0xba, 0x59, 0x16, 0x8c, 0x26, 0x47, 0xb3, 0x35 \ + } + +typedef struct { + EFI_HOB_GUID_TYPE EfiHobGuidType; + UINT32 uCodeAddr; +} AMI_INTERNAL_UCODE_HOB; + +typedef enum _EFI_MEMORY_CACHE_TYPE +{ + EfiCacheTypeUncacheable = 0, + EfiCacheTypeWriteCombining= 1, + EfiCacheTypeReserved2 = 2, + EfiCacheTypeReserved3 = 3, + EfiCacheTypeWriteThrough = 4, + EfiCacheTypeWriteProtected= 5, + EfiCacheTypeWriteBack = 6, + EfiCacheTypeMaximumType = 7 +} EFI_MEMORY_CACHE_TYPE; + + +typedef struct _PEI_CACHE_PPI PEI_CACHE_PPI; + +// +// ******************************************************* +// PEI_SET_CACHE_PPI +// ******************************************************* +// +typedef +EFI_STATUS +(EFIAPI *PEI_SET_CACHE_PPI) ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CACHE_PPI * This, + IN EFI_PHYSICAL_ADDRESS MemoryAddress, + IN UINT64 MemoryLength, + IN EFI_MEMORY_CACHE_TYPE MemoryCacheType + ); + +// +// ******************************************************* +// PEI_RESET_CACHE_PPI +// ******************************************************* +// +typedef +EFI_STATUS +(EFIAPI *PEI_RESET_CACHE_PPI) ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CACHE_PPI * This + ); + +// +// ******************************************************* +// PEI_ACTIVATE_CACHE_PPI +// ******************************************************* +// +typedef +EFI_STATUS +(EFIAPI *PEI_ACTIVATE_CACHE_PPI) ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CACHE_PPI * This + ); + +// +// ******************************************************* +// PEI_CACHE_PPI +// ******************************************************* +// +typedef struct _PEI_CACHE_PPI { + PEI_SET_CACHE_PPI SetCache; + PEI_RESET_CACHE_PPI ResetCache; + PEI_ACTIVATE_CACHE_PPI ActivateCache; +} PEI_CACHE_PPI; + +typedef struct { + UINT64 Base; + UINT64 Len; +} MEMORY_MAP; + +EFI_STATUS InitMtrrPolicy1 ( + IN EFI_PEI_SERVICES **PeiServices, + IN MEMORY_MAP *WbMap, + IN MEMORY_MAP *UcMap, + IN UINT64 Above4GMemoryLength +); + +EFI_STATUS InitMtrrPolicy2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN MEMORY_MAP *WbMap, + IN MEMORY_MAP *UcMap, + IN UINT64 Above4GMemoryLength +); + +VOID CpuPeiMiscFuncs ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariablePpi, + IN EFI_BOOT_MODE BootMode +); + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/CpuPeiBeforeMem.c b/Core/CPU/CpuPeiBeforeMem.c new file mode 100644 index 0000000..9647874 --- /dev/null +++ b/Core/CPU/CpuPeiBeforeMem.c @@ -0,0 +1,1268 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPeiBeforeMem.c 8 10/16/13 4:03a Crystallee $ +// +// $Revision: 8 $ +// +// $Date: 10/16/13 4:03a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPeiBeforeMem.c $ +// +// 8 10/16/13 4:03a Crystallee +// [TAG] EIP138897 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Locate BIST ppi will fail after disable CAR. +// [RootCause] All SEC PPIs must be reinstalled outside of SEC, +// otherwise they will be lost when CAR is no longer used. +// [Solution] Reinstall BIST PPI outside of SEC. +// +// 7 6/03/13 12:04a Hsingyingchung +// [TAG] None +// [Category] Improvement +// [Description] +// 1. Fix PLL setting is invalid once PEG/DMI ratio is 1:1. +// 2. Modify IA core ratio minimun value. Use "max non turbo ratio(MSR +// CEh)" instead of "power on turbo default value". +// +// 6 4/08/13 12:04a Hsingyingchung +// [TAG] None +// [Category] Improvement +// [Description] Limit CPU boot performance at Non-Turbo speed when add +// XTU. +// +// 5 2/07/13 4:13a Hsingyingchung +// [TAG] EIP112631 +// [Category] Improvement +// [Description] Add: +// 1. Support IA core and Ring voltage offset negative in OC mailbox. +// 2. Add Filter PLL function, please change +// "HASWELL_PERFTUNE_CPU_FILTER_PLL_SUPPORT" token if need to use this +// function. +// +// Fixed: +// 1. TDP Time Window is now programmed to 8 seconds by default. +// 2. When cold reset, re-enabling FIVR faults and SVID control. +// 3. Initialize OC mailbox for each boot. +// +// 4 12/20/12 10:15a Hsingyingchung +// [TAG] EIP108128 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] "Max non-turbo ratio" can't show in BIOS setup when first +// boot after flashing BIOS +// [RootCause] Doesn't initialize max non-turbo ratio value when first +// boot after flashing BIOS. +// [Solution] Add initialize code for max non-turbo ratio. +// +// 3 12/20/12 9:58a Hsingyingchung +// [TAG] EIP107712 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Change core ratio limit is not effective for oc cpu. +// [RootCause] The IA core max ratio in mailbox is not same as active +// one core ratio limit in MSR 0x1AD +// [Solution] Update the IA core max ratio in mailbox according to +// active one core ratio limit in XTU setting data +// +// 2 11/23/12 2:09a Hsingyingchung +// [TAG] EIP99095 +// [Category] Improvement +// [Description] Update by XTU 4.X +// +// 1 2/07/12 3:58a Davidhsieh +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// Name: CpuPeiBeforeMem.c +// +// Description: This file is the main contains Cpu code that must execute +// before memory. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <Pei.h> +#include <AmiPeiLib.h> +#include "CPU.h" +#include "AmiCspLibInc.h" +#include "token.h" +#include <Ppi\AmiEarlyBistPpi.h> + +#if PERF_TUNE_SUPPORT == 1 + #include <Ppi\PerfTunePpi.h> + #include <PerfTune.h> + #include "Ppi\CpuPlatformPolicy\CpuPlatformPolicy.h" + #include <Setup.h> + #include <PPI\Stall.h> + #include "Board\EM\PerfTune\PerfTuneCpuSetup.h" + typedef struct{ + UINT8 MeFirmwareInfo; + UINT32 MeMajor; + UINT32 MeMinor; + UINT32 MeHotFix; + UINT32 MeBuildNo; + } ME_INFO_SETUP_DATA; +#define AMI_CPU_INTERNAL_ME_FW_VERSION_GUID \ + {0x9b875aac, 0x36ec, 0x4550, 0xa4, 0xae, 0x86, 0xc8, 0x4e, 0x96, 0x76, 0x7e} +EFI_GUID gAmiCpuMEFwVerGuid = AMI_CPU_INTERNAL_ME_FW_VERSION_GUID; +#endif + + +#if PERF_TUNE_SUPPORT == 1 + +static EFI_GUID gPeiCpuPlatformPolicyGuid = PEI_CPU_PLATFORM_POLICY_PPI_GUID; +static EFI_GUID gPerfTunePpiGuid = PERF_TUNE_PPI_GUID; +static EFI_GUID gWdtPpiGuid = PERF_TUNE_WDT_PPI_GUID; +static EFI_GUID gAmiOcConfigHobGuid = AMI_OVERCLOCK_CONFIG_HOB_GUID; +static EFI_GUID gAmiCpuRatioLimitHobGuid = AMI_INTERNAL_CPU_RATIO_LIMIT; + +EFI_STATUS CpuPeiPolicyNotify( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *NullPpi +); + +// PPI that are notified +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiCpuPlatformPolicyGuid, + CpuPeiPolicyNotify + } +}; + +#if HASWELL_PERFTUNE_CPU_FILTER_PLL_SUPPORT == 1 +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PLLFilterFunction +// +// Description: Filter PLL setting High(3.2GHz) or lower(1.6GHz) +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// BIOS_SETTING_DATA *SettingData +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PLLFilterFunction ( + IN EFI_PEI_SERVICES **PeiServices, + IN BIOS_SETTING_DATA *SettingData +) +{ + UINT8 GpioSel; + UINT8 GpRstSel; + UINT32 RcbaAddress; + UINT8 PmCFG2; + PERF_TUNE_WDT_PPI *WdtPpi; + + // + // Set GPIO_USE_SEL[8] to `0' + // + GpioSel = READ_IO8(GPIO_BASE_ADDRESS + GP_IOREG_USE_SEL); // 0x00 + GpioSel = GpioSel & 0x7F; + WriteIo8 ((GPIO_BASE_ADDRESS + GP_IOREG_USE_SEL), GpioSel); + + // + // Set GP_RST_SEL[8] is `1' + // + GpRstSel = READ_IO8 (GPIO_BASE_ADDRESS + GP_IOREG_GP_RST_SEL1); // 0x60 + GpRstSel |= BIT8; + WriteIo8 ((GPIO_BASE_ADDRESS + GP_IOREG_GP_RST_SEL1), GpRstSel); + + // + // + // Set PCH_RCRB_PM_CFG 0x3318 bit 5 + RcbaAddress = (READ_PCI32 (00, 0x1F, 0x0, 0xF0)) & 0xFFFFF000; + PmCFG2 = READ_MEM8 (RcbaAddress + 0x3318); + if (SettingData->FilterPLLFrequency){ + PmCFG2 |= BIT5; //Bit5 set 1 + }else{ + PmCFG2 &= 0xDF; //Bit5 set 0 + } + WRITE_MEM8 (RcbaAddress + 0x3318, PmCFG2); + + + // + // Issue a CF9h with a power cycle + // + //Let WDT know this is a normal reset. + (*PeiServices)->LocatePpi( + PeiServices, + &gWdtPpiGuid, + 0, + NULL, + &WdtPpi + ); + WdtPpi->AllowKnowReset(PeiServices); + IoWrite8 (0xCF9,0x0e); + EFI_DEADLOOP(); + + return EFI_SUCCESS; + +} +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: OverrideNonTurboRatio +// +// Description: Override CPU NonTurbo Ratio Maximum value +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// UINT8 ProcessorMul +// CPU_CONFIG_PPI *CpuConfig +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS OverrideNonTurboRatio( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 ProcessorMul, + IN CPU_CONFIG_PPI *CpuConfig +) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_GUID PeiReadOnlyVariable2PpiGuid = EFI_PEI_READ_ONLY_VARIABLE2_PPI_GUID; + EFI_GUID gAmiCpuRatioLimitHobGuid = AMI_INTERNAL_CPU_RATIO_LIMIT; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2; + CPU_RATIO_LIMIT_DATA CpuRatioLimitData; + UINTN VarSize = sizeof(CPU_RATIO_LIMIT_DATA); + + PEI_TRACE((-1, PeiServices, "OverrideNonTurboRatio start!!\n")); + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &PeiReadOnlyVariable2PpiGuid, + 0, + NULL, + &ReadOnlyVariable2 + ); + if(EFI_ERROR(Status))return Status; + + Status = ReadOnlyVariable2->GetVariable( + ReadOnlyVariable2, + L"CpuRatioLimit", + &gAmiCpuRatioLimitHobGuid, + NULL, + &VarSize, + &CpuRatioLimitData + ); + if(EFI_ERROR(Status))return Status; + + //check if cpuratio in PurfTuneCPUSetup is not default Max Non Turbo Ratio. + if((UINT8)(ProcessorMul & 0xFF) != ((CpuRatioLimitData.MaxNonTurboRatio) & 0xFF)){ + CpuConfig->CpuRatioOverride = CPU_FEATURE_ENABLE; + CpuConfig->CpuRatio = (UINT8)(ProcessorMul & 0xFF); + } + + PEI_TRACE((-1, PeiServices, "OverrideNonTurboRatio end!!\n")); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PEGDMIRatio +// +// Description: Modify PEG/DMI Ratio for CPU +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// BIOS_SETTING_DATA *SettingData +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PEGDMIRatio( + IN EFI_PEI_SERVICES **PeiServices, + IN BIOS_SETTING_DATA *SettingData +) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 PciAddress, PciRegData; + UINT64 PCIEPLLRatio, MsrData; + EFI_BOOT_MODE BootMode = (EFI_BOOT_MODE)-1; + UINT8 Ratio = 0xFF; + EFI_GUID PeiReadOnlyVariable2PpiGuid = EFI_PEI_READ_ONLY_VARIABLE2_PPI_GUID; + EFI_GUID SetupGuid = SETUP_GUID; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2; + UINTN VarSize = sizeof(SETUP_DATA); + SETUP_DATA SetupData; + PERF_TUNE_WDT_PPI *WdtPpi; + ME_INFO_SETUP_DATA mMeInfoSetupData; + UINTN MeVarSize = sizeof(ME_INFO_SETUP_DATA); + + PEI_TRACE((-1, PeiServices, "Change PEGDMIRatio start!!\n")); + + //is SBPLL desired + //MSR 0x61E , bit2: SBPLL(1) or LCPLL(0). + Status = (*PeiServices)->LocatePpi( + PeiServices, + &PeiReadOnlyVariable2PpiGuid, + 0, + NULL, + &ReadOnlyVariable2 + ); + if(EFI_ERROR(Status))return Status; + Status = ReadOnlyVariable2->GetVariable( + ReadOnlyVariable2, + L"Setup", + &SetupGuid, + NULL, + &VarSize, + &SetupData + ); + if(EFI_ERROR(Status)){ + PEI_TRACE((-1, PeiServices, " Get SetupData fail!!\n")); + return Status; + } + MsrData = ReadMsr(0x61E); + PEI_TRACE((-1, PeiServices, "SetupData.LcSbSelect: %x !!\n",SetupData.LcSbSelect)); + MsrData = (SetupData.LcSbSelect)? MsrData | BIT2 : (MsrData & ~(BIT2)); + WriteMsr(0x61E,MsrData); + + //read ICC PEG/DMI ratio setting + PciAddress = (0x1) << 31 | ((0x0) << 16) | ((0x16) << 11) | ((0x0) << 8) | 0x60; + IoWrite32(0x0cf8,PciAddress); + PciRegData = IoRead32(0x0cfc); + + //B0:D22:F0, FWstatus3[2:0] + //000b = 5/5, 1 - Used when BCLK at 100MHz + //001b = 5/4, 1.25 - Used when BCLK around 125MHz + //010b = 5/3, 1.66 - Used when BCLK around 166MHz + //011b = 5/2, 2.5 - Used when BCLK around 250MHz + //100b~111b = Reserved + switch(SettingData->PEGDMIRatio){ + case 100: Ratio = 0x0; break; + case 125: Ratio = 0x1; break; + case 167: Ratio = 0x2; break; + case 250: Ratio = 0x3; break; + } + if((PciRegData & 0x3) == (ReadMsr(0x61E)& 0x3) || (PciRegData & 0x3) != Ratio){ + PEI_TRACE((-1, PeiServices, "Change PEGDMIRatio suspend!!\n")); + return EFI_UNSUPPORTED; + } + + //read CMOS and check if need to set bootmode = BOOT_ON_S3_RESUME + IoWrite8(0x70,0x50); + PEI_TRACE((-1, PeiServices, "S3 resume request: %x\n",IoRead8(0x71))); + if(IoRead8(0x71) == 0xA5){ + (*PeiServices)->SetBootMode(PeiServices, BOOT_ON_S3_RESUME); //restore BootMode after set BCLK over ratio and generate warm reset. + IoWrite8(0x71,0x5A); //clear scratch + } + + PCIEPLLRatio = ReadMsr(0x61E) & ~(BIT0 | BIT1 | BIT3); //clear PCIE_Ratio & Long_Reset bit + + //PCIE_Ratio bit + MsrData = 0; + switch(Ratio){ + case 0x0: MsrData = 0; break; + case 0x1: MsrData = 0 | BIT0; break; + case 0x2: MsrData = 0 | BIT1; break; + case 0x3: MsrData = 0 | BIT0 | BIT1; break; + } + //long reset bit + MsrData |= BIT3; + + PCIEPLLRatio |= MsrData; + WriteMsr(0x61E,PCIEPLLRatio); + + //Record current BootMode for restore after warm reset + (*PeiServices)->GetBootMode(PeiServices, &BootMode); + if (BootMode == BOOT_ON_S3_RESUME) + IoWrite8(0x71,0xA5); + PEI_TRACE((-1, PeiServices, "S3scratchpad value: %x\n",IoRead8(0x71))); + + //Is Memory in Self refresh?(B0:D31:F0, REG:0xa2) + PciAddress = (0x1) << 31 | ((0x0) << 16) | ((0x1f) << 11) | ((0x0) << 8) | 0xa0; + IoWrite32(0x0cf8,PciAddress); + PciRegData = IoRead32(0x0cfc); + PEI_TRACE((-1, PeiServices, "Read GEN_PMCON2 value: %x\n",PciRegData)); + if(!((PciRegData >> 16) & BIT5)){ //is memory in self-refresh + //clear GEN_PMCON2 bit7(DRAM Initialization Bit) + IoWrite32(0x0cfc,PciRegData & ~(BIT7 << 16)); + } + + //Need to send ICC message to enable Ramp when ME Firmware build no. is above 1221. + Status = ReadOnlyVariable2->GetVariable( + ReadOnlyVariable2, + L"MEFWVersion", + &gAmiCpuMEFwVerGuid, + NULL, + &MeVarSize, + &mMeInfoSetupData + ); + if(!EFI_ERROR(Status)){ + PEI_TRACE((-1, PeiServices, "ME FW Build No %d\n",mMeInfoSetupData.MeBuildNo)); + if(mMeInfoSetupData.MeBuildNo >= 1221){ + //Write a value of 0x60000001 to PCI 0:22:0 offset 0x4C. + PciAddress = (0x1) << 31 | ((0x0) << 16) | ((0x16) << 11) | ((0x0) << 8) | 0x4c; + IoWrite32(0x0cf8,PciAddress); + //Bits 31:28 - Message Type: + // 0x06 - ICC BIOS Message + //Bit 0 - BCLK Ramp Enable + // 0x01 - BCLK Ramp Enable + IoWrite32(0x0cfc,0x60000001); + + //Wait for FW ACK by reading FWStatus PCI 0:22:0 offset 0x40 for ICC FW ACK + //type and success status. + PciAddress = (0x1) << 31 | ((0x0) << 16) | ((0x16) << 11) | ((0x0) << 8) | 0x40; + IoWrite32(0x0cf8,PciAddress); + //Bits 31:28 - Message Type: + // 0x06 - ICC BIOS Message + //Bits 27:25 - ICC BIOS Ack Data + // 0 - ICC Success + // 1 - ICC BIOS Request Failed + while((Shr64(IoRead32(0x0cfc),25) & 0x7) != 0){} //wait for BCLK Ramp Enable success + } + } + else + PEI_TRACE((-1, PeiServices, "Get Me Fw Version fail!!\n")); + + //warm reset + PEI_TRACE((-1, PeiServices, "Warmreset!!\n")); + //Let WDT know this is a normal reset. + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gWdtPpiGuid, + 0, + NULL, + &WdtPpi + ); + WdtPpi->AllowKnowReset(PeiServices); + IoWrite8 (0xCF9,0x06); + EFI_DEADLOOP(); + + PEI_TRACE((-1, PeiServices, "Change PEGDMIRatio end!!\n")); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: EnablePLLOverVoltage +// +// Description: Enable PLL over voltage for CPU +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// UINT8 NumOfCpuCore +// UINT16 *pCoreRatioData +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS EnablePLLOverVoltage( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 NumOfCpuCore, + IN UINT16 *pCoreRatioData + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_GUID gAmiPllOvFlagHobGuid = AMI_PLL_OVER_VOTAGE_FLAG_HOB_GUID; + EFI_GUID gPeiReadOnlyVariable2PpiGuid = EFI_PEI_READ_ONLY_VARIABLE2_PPI_GUID; + EFI_GUID gAmiPllOvFlagDataGuid = gAmiPllOvFlagHobGuid; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2; + UINTN VarSize = sizeof(PLL_OV_FLAG_DATA); + PLL_OV_FLAG_DATA_HOB *PllOvFlagHob; + UINT16 i; + UINT8 *OriRatioLimit; + + PEI_TRACE((-1, PeiServices, "EnablePLLOverVoltage Start\n")); + Status = (*PeiServices)->CreateHob(PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(PLL_OV_FLAG_DATA_HOB), + &PllOvFlagHob); + if (EFI_ERROR(Status))return Status; + + PllOvFlagHob->EfiHobGuidType.Name = gAmiPllOvFlagHobGuid; + OriRatioLimit = (UINT8*)&PllOvFlagHob->PllOvData.OriTurboRatio; + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + &ReadOnlyVariable2 + ); + if(EFI_ERROR(Status))return Status; + + Status = ReadOnlyVariable2->GetVariable( + ReadOnlyVariable2, + L"PLLOvFlag", + &gAmiPllOvFlagDataGuid, + NULL, + &VarSize, + &PllOvFlagHob->PllOvData + ); + + if(!(EFI_ERROR(Status)) && (PllOvFlagHob->PllOvData.PLLOvFlag== 0x2)) return EFI_ALREADY_STARTED; + + for(i = 0; i < sizeof(UINT64); i++){ + if( i < NumOfCpuCore) + OriRatioLimit[i] = (UINT8)pCoreRatioData[i]; + else + OriRatioLimit[i] = 0x00; + + if( i < 3) + pCoreRatioData[i] = 0x06; + else + pCoreRatioData[i] = 0x00; + } + + PllOvFlagHob->PllOvData.PLLOvFlag = 0x1; + WriteMsr(MSR_TURBO_RATIO_LIMIT,0x60606); + + PEI_TRACE((-1, PeiServices, "EnablePLLOverVoltage End\n")); + + return EFI_SUCCESS; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CollectOcConfig +// +// Description: Collect Overclocking Config data from MSR 0x150. +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// OVERCLOCKING_CONFIG_HOB *OverclockConfig +// +// Output: +// VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CollectOcConfig( + EFI_PEI_SERVICES **PeiServices, + OVERCLOCKING_CONFIG_DATA *OverclockConfig +){ + EFI_STATUS Status; + UINT64 MsrData; + UINT8 i; + PERF_TUNE_PPI *PerfTunePpi; + PERF_TUNE_WDT_PPI *WdtPpi; + + PEI_TRACE((-1, PeiServices, "Collect Overclocking config data(MSR 0x150) Start\n")); + + OverclockConfig->OcSupport = 0; + OverclockConfig->IsPowerCycle = IsPowerCycle(); + OverclockConfig->IsCpuRunDefault = TRUE; + + //collect CPU overclocking config data + for(i=0;i<DOMAIN_MAX_NUM;++i){ + //1. Overclocking Capability + MsrData = 0; + Status = GetOcCapability(i, &MsrData); + if(!EFI_ERROR(Status)){ + OverclockConfig->OCCap[i].MaxOcRatioLimit = (UINT8)MsrData; + OverclockConfig->OCCap[i].RatioOcSupported = (MsrData & BIT8)?1:0; + OverclockConfig->OCCap[i].VoltageOverridesSupported = (MsrData & BIT9)?1:0; + OverclockConfig->OCCap[i].VoltageOffsetSupported = (MsrData & BIT10)?1:0; + if (!OverclockConfig->OcSupport) + OverclockConfig->OcSupport = OverclockConfig->OCCap[i].RatioOcSupported || + OverclockConfig->OCCap[i].VoltageOverridesSupported|| + OverclockConfig->OCCap[i].VoltageOffsetSupported ; + } + else{ + PEI_TRACE((-1, PeiServices, "Domain %x GetOcCapability fail [0x%x]\n",i,Shr64(MsrData,32) & 0xFF)); + } + + //2. Overclocking Voltage/Frequency + MsrData = 0; + Status = GetVoltFreq(i, &MsrData); + if(!EFI_ERROR(Status)){ + OverclockConfig->VFDef[i].MaxOcRatio = (UINT8)MsrData; + OverclockConfig->VFDef[i].VoltageTargetMode = (UINT8)(Shr64(MsrData,20) & 0x1); + OverclockConfig->VFDef[i].VoltageTarget = (UINT16)(Shr64(MsrData,8) & 0xFFF); + OverclockConfig->VFDef[i].VoltageOffset = (INT16)(Shr64(MsrData,21) & 0x7FF); + } + else{ + PEI_TRACE((-1, PeiServices, "Domain %x GetVoltFreq fail [0x%x]\n",i,Shr64(MsrData,32) & 0xFF)); + } + } + //3. SVID Config + MsrData = 0; + Status = GetSVIDConfig(&MsrData); + if(!EFI_ERROR(Status)){ + OverclockConfig->SvidDisable = (MsrData & BIT31)?1:0; + OverclockConfig->SvidVoltageOverride = (UINT16)(MsrData & 0xFFF); + } + else{ + PEI_TRACE((-1, PeiServices, "GetSVIDConfig fail [0x%x]\n",Shr64(MsrData,32) & 0xFF)); + } + + //4. Misc Global Config + MsrData = 0; + Status = GetFIVRConfig(&MsrData); + if(!EFI_ERROR(Status)){ + OverclockConfig->FivrFaultsDisable = (MsrData & BIT0)?1:0; + OverclockConfig->FivrEfficiencyDisable = (MsrData & BIT1)?1:0; + } + else{ + PEI_TRACE((-1, PeiServices, "GetMiscConfig fail [0x%x]\n",Shr64(MsrData,32) & 0xFF)); + } + + PEI_TRACE((-1, PeiServices, "Collect Overclocking config data(MSR 0x150) end\n")); + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gPerfTunePpiGuid, + 0, + NULL, + &PerfTunePpi + ); + if(EFI_ERROR(Status)) return; + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gWdtPpiGuid, + 0, + NULL, + &WdtPpi + ); + if(EFI_ERROR(Status)) return; + + if ( !(PerfTunePpi->IsChangeCpu(PeiServices) && PerfTunePpi->IsRunDefault(PeiServices)) && !(WdtPpi->QueryTimeOut(PeiServices))){ + OverclockConfig->IsCpuRunDefault = FALSE; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitOcMailbox +// +// Description: Initialize Overclocking Config data. +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// OVERCLOCKING_CONFIG_PPI *OverclockingConfig +// +// Output: +// VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS InitOcMailbox( + IN EFI_PEI_SERVICES **PeiServices, + IN OVERCLOCKING_CONFIG_PPI *OverclockingConfig +){ + EFI_STATUS Status = EFI_SUCCESS; + VOID *FirstHob; + OVERCLOCKING_CONFIG_HOB *OverclockConfigHob; + OVERCLOCKING_CONFIG_DATA *OverclockData; + + PEI_TRACE((-1, PeiServices, "InitOcMailbox start!!\n")); + + Status = (*PeiServices)->GetHobList(PeiServices, &FirstHob); + ASSERT_PEI_ERROR(PeiServices, Status); + OverclockConfigHob = (OVERCLOCKING_CONFIG_HOB*) FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &OverclockConfigHob))) { + if (guidcmp(&((EFI_HOB_GUID_TYPE*)OverclockConfigHob)->Name, &gAmiOcConfigHobGuid) == 0) { + break; + } + } + if(EFI_ERROR(Status)){ + PEI_TRACE((-1, PeiServices, "Get OC config HOB fail!!\n")); + return Status; + } + OverclockData = &OverclockConfigHob->OverclockData; + + // + // Initialize Overclocking Data + // + if(OverclockData->OCCap[IA].RatioOcSupported){ + OverclockingConfig->CoreMaxOcTurboRatio = ReadMsr(0x1AD) & 0xFF; + } + + if(OverclockData->OCCap[RING].RatioOcSupported){ + OverclockingConfig->ClrMaxOcTurboRatio = ReadMsr(0x1AD) & 0xFF; // read core one max ratio limit + } + + OverclockingConfig->SvidEnable = 1; // 1: Enable + OverclockingConfig->FivrFaultsEnable = 1; // 1: Enable + OverclockingConfig->FivrEfficiencyEnable = 1; // 1: Enable + + OverclockingConfig->OcSupport = 1; // 0: Disable, 1: Enable + + PEI_TRACE((-1, PeiServices, "InitOcMailbox End!!\n")); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: OverlockingConfigUpdate +// +// Description: Update Overclocking Config data. +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// BIOS_SETTING_DATA *SettingData +// OVERCLOCKING_CONFIG_PPI *OverclockingConfig +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS OverlockingConfigUpdate( + IN EFI_PEI_SERVICES **PeiServices, + IN BIOS_SETTING_DATA *SettingData, + IN OVERCLOCKING_CONFIG_PPI *OverclockingConfig +){ + EFI_STATUS Status = EFI_SUCCESS; + VOID *FirstHob; + OVERCLOCKING_CONFIG_HOB *OverclockConfigHob; + OVERCLOCKING_CONFIG_DATA *OverclockData; + + PEI_TRACE((-1, PeiServices, "OverlockingConfigUpdate start!!\n")); + + Status = (*PeiServices)->GetHobList(PeiServices, &FirstHob); + ASSERT_PEI_ERROR(PeiServices, Status); + OverclockConfigHob = (OVERCLOCKING_CONFIG_HOB*) FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &OverclockConfigHob))) { + if (guidcmp(&((EFI_HOB_GUID_TYPE*)OverclockConfigHob)->Name, &gAmiOcConfigHobGuid) == 0) { + break; + } + } + if(EFI_ERROR(Status)){ + PEI_TRACE((-1, PeiServices, "Get OC config HOB fail!!\n")); + return Status; + } + OverclockData = &OverclockConfigHob->OverclockData; + + + //Overwrite OverclockingConfig data in Intel reference code + if(OverclockData->OcSupport){ + //IA core + // Core Max overclocking turbo ratio + if(OverclockData->OCCap[IA].RatioOcSupported){ + OverclockingConfig->CoreMaxOcTurboRatio = (SettingData->CoreRatioLimit1)?SettingData->CoreRatioLimit1:ReadMsr(0x1AD) & 0xFF; + if (SettingData->CoreRatioLimit1 < SettingData->ProcessorMul ) + OverclockingConfig->CoreMaxOcTurboRatio = SettingData->ProcessorMul; + } + + if(OverclockData->OCCap[IA].VoltageOverridesSupported){ + // Voltage Mode, 0: Adaptive, 1: Override(Static) + OverclockingConfig->CoreVoltageMode = (UINT8)SettingData->IACoreVoltageMode; + + if(SettingData->IACoreVoltageMode == 0x1){ + // Override(Static) mode + OverclockingConfig->CoreVoltageOverride = SettingData->CPUVoltage; + if(SettingData->CPUVoltage == 0xFFFF) + OverclockingConfig->CoreVoltageOverride = 0; + OverclockingConfig->CoreExtraTurboVoltage = 0; + } + else{ + // Adaptive mode + OverclockingConfig->CoreExtraTurboVoltage = SettingData->CPUVoltage; + if(SettingData->CPUVoltage == 0xFFFF) + OverclockingConfig->CoreExtraTurboVoltage = 0; + OverclockingConfig->CoreVoltageOverride = 0; + } + } + + if(OverclockData->OCCap[IA].VoltageOffsetSupported){ + if (SettingData->DynamicCPUVoltage >=0 && \ + SettingData->DynamicCPUVoltage <= 999){ + OverclockingConfig->CoreVoltageOffset = ~(1000 - SettingData->DynamicCPUVoltage) + 1; + }else if (SettingData->DynamicCPUVoltage >=1000 && \ + SettingData->DynamicCPUVoltage <= 1998){ + OverclockingConfig->CoreVoltageOffset = SettingData->DynamicCPUVoltage - 1000; + } + + } + + //RING + // Ring Max overclocking turbo ratio + if(OverclockData->OCCap[RING].RatioOcSupported){ + if(SettingData->RingRatio){ + OverclockingConfig->ClrMaxOcTurboRatio = SettingData->RingRatio; + } + else{ + // first boot + OverclockingConfig->ClrMaxOcTurboRatio = ReadMsr(0x1AD) & 0xFF; // read core one max ratio limit + } + } + + if(OverclockData->OCCap[RING].VoltageOverridesSupported){ + // Voltage Mode, 0: Adaptive, 1: Override(Static) + OverclockingConfig->ClrVoltageMode = (UINT8)SettingData->RingVoltageMode; + + if(SettingData->RingVoltageMode == 0x1){ + // Override(Static) mode + OverclockingConfig->ClrVoltageOverride = SettingData->RingVoltageOverride; + if(SettingData->RingVoltageOverride == 0xFFFF) + OverclockingConfig->ClrVoltageOverride = 0; + OverclockingConfig->ClrExtraTurboVoltage = 0; + } + else{ + // Adaptive mode + OverclockingConfig->ClrExtraTurboVoltage = SettingData->RingVoltageOverride; + if(SettingData->RingVoltageOverride == 0xFFFF) + OverclockingConfig->ClrExtraTurboVoltage = 0; + OverclockingConfig->ClrVoltageOverride = 0; + } + } + + if(OverclockData->OCCap[RING].VoltageOffsetSupported){ + if (SettingData->RingVoltageOffset >=0 && \ + SettingData->RingVoltageOffset <= 999){ + OverclockingConfig->ClrVoltageOffset = ~(1000 - SettingData->RingVoltageOffset) + 1; + }else if (SettingData->RingVoltageOffset >=1000 && \ + SettingData->RingVoltageOffset <= 1998){ + OverclockingConfig->ClrVoltageOffset = SettingData->RingVoltageOffset - 1000; + } + } + + //SVID and FIVR + if(SettingData->DynamicSVIDControl != 0xFFFF) + OverclockingConfig->SvidEnable = (UINT8)(SettingData->DynamicSVIDControl); // 0: Disable, 1: Enable + if(OverclockData->IsPowerCycle) + OverclockingConfig->SvidEnable = 1; // When cold boot, reset to the default value '1'. + if(SettingData->DynamicSVIDControl != 0xFFFF && SettingData->SVIDVoltageOverride != 0xFFFF) + OverclockingConfig->SvidVoltageOverride = (SettingData->DynamicSVIDControl)? SettingData->SVIDVoltageOverride : 0; // External VR voltage override + + if(SettingData->FIVRFaults != 0xFFFF) + OverclockingConfig->FivrFaultsEnable = (UINT8)(SettingData->FIVRFaults); // 0: Disable, 1: Enable + if(OverclockData->IsPowerCycle) + OverclockingConfig->FivrFaultsEnable = 1; // When cold boot, reset to the default value '1'. + if(SettingData->FIVREfficiencyManagenment != 0xFFFF) + OverclockingConfig->FivrEfficiencyEnable = (UINT8)(SettingData->FIVREfficiencyManagenment); // 0: Disable, 1: Enable + + //Enable orDisable Reference code execute Cpu Overclocking Initialize(CpuOcInit). + OverclockingConfig->OcSupport = 1; // 0: Disable, 1: Enable + OverclockingConfig->BitReserved = 0; + } + PEI_TRACE((-1, PeiServices, "OverlockingConfigUpdate end!!\n")); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuPeiPolicyOverWrite +// +// Description: This function over writes the CPU PEI RC policy +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CpuPeiPolicyOverWrite ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + + //UINT8 MaxNonTurboRatio; + //UINT8 NumBinsSupport; + UINT8 CpuCores = NumCpuCores(); + UINT16 i; + UINT16 Xtu_CoreRatioArray[6]; + UINT32 CpuSignature = GetCpuSignature(); + UINT32 CpuSigNoVer = CpuSignature & 0xfffffff0; + //UINT64 MsrData; + + EFI_STATUS Status; + PEI_CPU_PLATFORM_POLICY_PPI *PeiCpuPolicyPpi; + //PPI_CPU_POWER_FEATURE_CONFIG *PeiCpuPowerFeatureConfig; + POWER_MGMT_CONFIG_PPI *PeiCpuPowerFeatureConfig; + PERF_TUNE_PPI *PerfTunePpi; + //PERF_TUNE_WDT_PPI *WdtPpi; + BIOS_SETTING_DATA SettingData; + OVERCLOCKING_CONFIG_HOB *OverclockConfigHob; + OVERCLOCKING_CONFIG_DATA *OverclockData; + CPU_RATIO_LIMIT_HOB *CpuRatioLimitHob; + CPU_RATIO_LIMIT_DATA *CpuRatioLimitData; + EFI_GUID PeiReadOnlyVariable2PpiGuid = EFI_PEI_READ_ONLY_VARIABLE2_PPI_GUID; + EFI_GUID SetupGuid = SETUP_GUID; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2; + SETUP_DATA SetupData; + UINTN VarSize = sizeof(SETUP_DATA); + + PEI_TRACE((-1, PeiServices, "Start CPU PEI RC policy overwrite\n")); + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &PeiReadOnlyVariable2PpiGuid, + 0, + NULL, + &ReadOnlyVariable2 + ); + if(EFI_ERROR(Status)) return; + Status = ReadOnlyVariable2->GetVariable( + ReadOnlyVariable2, + L"Setup", + &SetupGuid, + NULL, + &VarSize, + &SetupData + ); + if(EFI_ERROR(Status)) return; + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gPeiCpuPlatformPolicyGuid, + 0, + NULL, + &PeiCpuPolicyPpi + ); + if(EFI_ERROR(Status)) return; + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gPerfTunePpiGuid, + 0, + NULL, + &PerfTunePpi + ); + if(EFI_ERROR(Status)) return; + PEI_TRACE((-1, PeiServices, "Perfmorance tunning PPI located\n")); + + // collect OcMailbox data + Status = (*PeiServices)->CreateHob(PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(OVERCLOCKING_CONFIG_HOB), + &OverclockConfigHob); + if (EFI_ERROR(Status)){ + PEI_TRACE((-1, PeiServices, "Create OverclockConfigHob fail\n")); + return; + } + OverclockConfigHob->EfiHobGuidType.Name = gAmiOcConfigHobGuid; + OverclockData = &OverclockConfigHob->OverclockData; + CollectOcConfig(PeiServices,OverclockData); + InitOcMailbox(PeiServices,PeiCpuPolicyPpi->OverclockingConfig); + + if(PerfTunePpi->IsChangeCpu(PeiServices)){ + Status = (*PeiServices)->CreateHob(PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(CPU_RATIO_LIMIT_HOB), + &CpuRatioLimitHob); + if (EFI_ERROR(Status)){ + PEI_TRACE((-1, PeiServices, "Create NonTurboRatioMax HOB fail\n")); + return; + } + CpuRatioLimitHob->EfiHobGuidType.Name = gAmiCpuRatioLimitHobGuid; + CpuRatioLimitData = &CpuRatioLimitHob->CpuRatioLimitData; + CpuRatioLimitData->MaxNonTurboRatio = (UINT8)(Shr64(ReadMsr(0x0ce), 8) & 0xFF); + CpuRatioLimitHob->IsChangeCpu = PerfTunePpi->IsChangeCpu(PeiServices); + } + /* + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gWdtPpiGuid, + 0, + NULL, + &WdtPpi + ); + if(EFI_ERROR(Status)) return; + PEI_TRACE((-1, PeiServices, "watch dogger timer PPI located\n")); + */ + Status = PerfTunePpi->GetSettingData( + PeiServices, + &SettingData + ); + + if(EFI_ERROR(Status)) return; + PEI_TRACE((-1, PeiServices, "Got Perfmorance tunning setting data\n")); + + if(!((PerfTunePpi->IsChangeCpu(PeiServices) && PerfTunePpi->IsRunDefault(PeiServices)))){ + //if(!(WdtPpi->QueryTimeOut(PeiServices))){ + + PEI_TRACE((-1, PeiServices, "ReConfig XE policy from XTU\n")); + //PeiCpuPowerFeatureConfig = PeiCpuPolicyPpi->PpiCpuPowerFeatureConfig; + PeiCpuPowerFeatureConfig = PeiCpuPolicyPpi->PowerMgmtConfig; + //PeiCpuPowerFeatureConfig->PrimaryPlaneCurrentLimit = (SettingData.IACoreCurrentMax & 0x1fff); + PeiCpuPowerFeatureConfig->VrCurrentLimit = (SettingData.PackageCurrentLimit & 0x1fff); + //PeiCpuPowerFeatureConfig->SecondaryPlaneCurrentLimit = (SettingData.IGFXCoreCurrentMax & 0x1fff); + PeiCpuPowerFeatureConfig->VrCurrentLimitLock = (!OverclockData->IsCpuRunDefault)? SetupData.PackageCurrentLock : CPU_FEATURE_DISABLE ; + // CPU boot with Maximum Non-Turbo speed. + PeiCpuPowerFeatureConfig->BootInLfm = CPU_FEATURE_DISABLE; + + if (isXECoreRatioLimitSupported()) + { + PEI_TRACE((-1, PeiServices, "XE part CPU found\n")); + + PeiCpuPowerFeatureConfig->Xe = CPU_FEATURE_ENABLE; + Xtu_CoreRatioArray[0] = SettingData.CoreRatioLimit1; + Xtu_CoreRatioArray[1] = SettingData.CoreRatioLimit2; + Xtu_CoreRatioArray[2] = SettingData.CoreRatioLimit3; + Xtu_CoreRatioArray[3] = SettingData.CoreRatioLimit4; + Xtu_CoreRatioArray[4] = SettingData.CoreRatioLimit5; + Xtu_CoreRatioArray[5] = SettingData.CoreRatioLimit6; + + for(i = 0; i < CpuCores; ++i) + if(SettingData.ProcessorMul > Xtu_CoreRatioArray[i]) + Xtu_CoreRatioArray[i] = SettingData.ProcessorMul; + + /*Force Runtime Turbo not suuport now + if (CpuSigNoVer == SANDY_BRIDGE && SettingData.RuntimeTurboEanble) + { + PEI_TRACE((-1, PeiServices, "SnadyBridge Runtime Turbo ratio change\n")); + MsrData = ReadMsr(MSR_FLEX_RATIO); + NumBinsSupport = (UINT8)((UINT32)MsrData >> 17) & 0x7; + + //Read Max_Non turbo ratio. + MsrData = ReadMsr(MSR_PLATFORM_INFO); + MaxNonTurboRatio = ((UINT32) MsrData >> MAX_NON_TURBO_RATIO_OFFSET) & MAX_NON_TURBO_RATIO_MASK; + + MsrData = ReadMsr(MSR_TURBO_RATIO_LIMIT); + for(i = 0; i < CpuCores; i++) + { + if((NumBinsSupport > 0)&&(NumBinsSupport < 7)) + { + PeiCpuPowerFeatureConfig->RatioLimit[i] = MsrData & 0xff + NumBinsSupport; + } else { + PeiCpuPowerFeatureConfig->RatioLimit[i] = 0x39; + } + MsrData = Shr64(MsrData, 8); + } + + } else {*/ + PEI_TRACE((-1, PeiServices, "CPU core ratio limit change\n")); + for(i = 0; i < CpuCores; i++){ + PeiCpuPowerFeatureConfig->RatioLimit[i] = (UINT8)(Xtu_CoreRatioArray[i]); + PEI_TRACE((-1, PeiServices, "XTU for %x core ratio limit = %x \n", (i + 1, Xtu_CoreRatioArray[i]))); + } + //} + + //PeiCpuPowerFeatureConfig->OverClockExtraVoltage = SettingData.MaxTurboModeCPUVoltage; + + // Change Cpu Max Non-Tubro Ratio + if(SettingData.ProcessorMul != 0xFFFF){ + Status = OverrideNonTurboRatio(PeiServices,SettingData.ProcessorMul,PeiCpuPolicyPpi->CpuConfig); + } + } + +#if HASWELL_PERFTUNE_CPU_FILTER_PLL_SUPPORT == 1 + if(SettingData.FilterPLLFrequency != 0xFFFF){ + UINT32 RcbaAdd; + UINT8 PmCFG; + + RcbaAdd = (READ_PCI32 (00, 0x1F, 0x0, 0xF0)) & 0xFFFFF000; + PmCFG = READ_MEM8 (RcbaAdd + 0x3318); + if ( SettingData.FilterPLLFrequency != ( (PmCFG & BIT5) >> 5)){ + PLLFilterFunction(PeiServices,&SettingData); + } + } +#endif + + // Change PEG/DMI Ratio + if(SettingData.PEGDMIRatio != 0xFFFF){ + if(isBCLKRatioSuuported()){ + PEGDMIRatio(PeiServices,&SettingData); + } + } + // Enable PLL Over Voltage feature + if(SettingData.CpuPllVoltageUnlockEnable == 0x1){ + Status = EnablePLLOverVoltage(PeiServices,CpuCores,(UINT16*)Xtu_CoreRatioArray); + } + + // Updata OC config data in CpuOcInit.c + Status = OverlockingConfigUpdate(PeiServices,&SettingData,PeiCpuPolicyPpi->OverclockingConfig); + } +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuPeiPolicyNotify +// +// Description: CPU PEI pollicy PPI notify function +// +// Input: +// EFI_PEI_SERVICES **PeiServices +// EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor +// VOID *NullPpi +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CpuPeiPolicyNotify( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *NullPpi +) +{ + CpuPeiPolicyOverWrite(PeiServices); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuPeiXtuInitBeforeMem +// +// Description: CPU XTU init code in PEI phase +// +// Input: +// IN EFI_FFS_FILE_HEADER *FfsHeader, +// IN EFI_PEI_SERVICES **PeiServices +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CpuPeiXtuInitBeforeMem( + IN EFI_PEI_SERVICES **PeiServices +) +{ + + EFI_STATUS Status; + PEI_CPU_PLATFORM_POLICY_PPI *PeiCpuPolicyPpi; + + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiCpuPlatformPolicyGuid, 0, NULL, &PeiCpuPolicyPpi); + if (Status == EFI_SUCCESS) { + CpuPeiPolicyOverWrite(PeiServices); + } else { + Status = (*PeiServices)->NotifyPpi(PeiServices, mNotifyList); + } + + return Status; + +} +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ReinstallSecPpis +// +// Description: +// Reinstall PPIs from stack because stack will be lost when cache-as-ram is turned off. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +//Sec Core Descriptors on stack will be lost when cache-as-ram is turned off. +VOID ReinstallSecPpis(IN EFI_PEI_SERVICES **PeiServices) +{ + EFI_STATUS Status; + EFI_GUID gAmiEarlyBistGuid = AMI_EARLY_BIST_PPI_GUID; + + AMI_EARLY_BIST_PPI *OldAmiBistPpi; + AMI_EARLY_BIST_PPI *NewAmiBistPpi; + + EFI_PEI_PPI_DESCRIPTOR *OldPpiDesc; + EFI_PEI_PPI_DESCRIPTOR *NewPpiDesc; + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gAmiEarlyBistGuid, + 0,&OldPpiDesc, + &OldAmiBistPpi + ); + if (!EFI_ERROR(Status)) { + + //Create new PPI in allocated memory because the location in stack from Sec Core + //will not be available after memory. + Status = (*PeiServices)->AllocatePool(PeiServices, + sizeof(AMI_EARLY_BIST_PPI) + (OldAmiBistPpi->NumBists - 1) * sizeof(CPU_BIST), + &NewAmiBistPpi + ); + ASSERT_PEI_ERROR(PeiServices, Status); + MemCpy( + NewAmiBistPpi, + OldAmiBistPpi, + sizeof(AMI_EARLY_BIST_PPI) + (OldAmiBistPpi->NumBists - 1) * sizeof(CPU_BIST) + ); + + //Create new Descriptor + Status = (*PeiServices)->AllocatePool(PeiServices, + sizeof(EFI_PEI_PPI_DESCRIPTOR), + &NewPpiDesc + ); + ASSERT_PEI_ERROR(PeiServices, Status); + MemCpy(NewPpiDesc, OldPpiDesc, sizeof(EFI_PEI_PPI_DESCRIPTOR)); + NewPpiDesc->Ppi = NewAmiBistPpi; + + (*PeiServices)->ReInstallPpi( + PeiServices, + (EFI_PEI_PPI_DESCRIPTOR*)OldPpiDesc, + (EFI_PEI_PPI_DESCRIPTOR*)NewPpiDesc + ); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuPeiBeforeMemEntry +// +// Description: CPU PEI functions before memory ready +// +// Input: +// IN EFI_FFS_FILE_HEADER *FfsHeader, +// IN EFI_PEI_SERVICES **PeiServices +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CpuPeiBeforeMemEntry( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ +#if PERF_TUNE_SUPPORT == 1 + EFI_STATUS Status; + Status = CpuPeiXtuInitBeforeMem(PeiServices); +#endif + + ReinstallSecPpis(PeiServices); + + return EFI_SUCCESS; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + diff --git a/Core/CPU/CpuPeiFuncs.c b/Core/CPU/CpuPeiFuncs.c new file mode 100644 index 0000000..c5bb238 --- /dev/null +++ b/Core/CPU/CpuPeiFuncs.c @@ -0,0 +1,1378 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPeiFuncs.c 10 8/06/14 11:57p Crystallee $ +// +// $Revision: 10 $ +// +// $Date: 8/06/14 11:57p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPeiFuncs.c $ +// +// 10 8/06/14 11:57p Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] Add special case for saving MTRRs. +// +// 9 8/05/14 2:21a Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] For backward compatible, add old MTRR setting method +// back. Change new MTRR setting method to Policy2. +// +// 8 7/08/14 3:35a Crystallee +// [TAG] EIPNone +// [Category] Improvement +// [Description] Add all the possible methods to describing memory in +// MTRRS. +// [Files] CpuPei.c, CpuPei.h, CpuPeiFuncs.c +// +// 7 6/03/13 2:37a Hsingyingchung +// [TAG] EIP123835 +// [Category] Spec Update +// [Severity] Important +// [Description] SBY Performance Tuning Guid rev. 1.1 update. +// +// 6 2/07/13 3:59a Hsingyingchung +// [TAG] EIP112631 +// [Category] Improvement +// [Description] add PEI/DMI ratio control item. +// +// 5 12/20/12 10:09a Hsingyingchung +// [TAG] EIP +// [Category] Improvement +// [Description] Remove mailbox item limit. Because mailbox item is not +// be effected by turbo mode support or not. +// +// 4 11/23/12 2:10a Hsingyingchung +// [TAG] EIP99095 +// [Category] Improvement +// [Description] Update by XTU 4.X +// +// 3 10/25/12 4:01a Davidhsieh +// Add ReadOnlyVariable.h file include +// +// 2 3/09/12 2:14a Davidhsieh +// Use all variable MTRRs +// +// 1 2/07/12 3:58a Davidhsieh +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// Name: CpuPeiFuncs.c +// +// Description: +// This file is the main CPU PEI component file. This file provides +// misc functions for CPU PEI drvier usage. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "cpu.h" +#include "AmiCspLibInc.h" +#include <AmiPeiLib.h> +#include <core\PeiHob.h> +#include <token.h> +#include <Ppi\ReadOnlyVariable.h> +#include "CpuPei.h" +#include "Setup.h" + +#if PERF_TUNE_SUPPORT == 1 + #include <Ppi\PerfTunePpi.h> + #include <PerfTune.h> + + //TODO: Update library and remove private structure. + typedef struct { + SETUP_DATA *SetupData; + } PRIVATE_CPU_SETUP_LIB; + + EFI_GUID gAmiDddtPreFlagHobGuid = AMI_DDDT_PRESENT_FLAG_HOB_GUID; + EFI_GUID gAmiOcConfigHobGuid = AMI_OVERCLOCK_CONFIG_HOB_GUID; +#endif + +#if MTRR_POLICY == 1 +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: InitMtrrPolicy1 +// +// Description: Config system cache. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// IN PEI_CACHE_PPI *CachePpi +// IN UINT64 Above4GMemoryLength +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InitMtrrPolicy1 ( + IN EFI_PEI_SERVICES **PeiServices, + IN MEMORY_MAP *WbMap, + IN MEMORY_MAP *UcMap, + IN UINT64 Above4GMemoryLength +) +{ + + UINT64 TotalAbove4GMemoryLength = Above4GMemoryLength + SIZE_4G; + UINT64 RemainMemoryLength = TotalAbove4GMemoryLength - GetPowerOfTwo64(TotalAbove4GMemoryLength); + UINT64 Below4GMemoryLength; + UINT64 MemoryLengthUc; + UINT64 CurrentBaseAddress; + UINT64 PowerTwo; + UINTN i, WbCount = 0, UcCount = 0; + UINT8 MtrrCount = 0; + UINT8 NumOfOne = 0; + + CurrentBaseAddress = 0; + + for(i = 0; i < 10; i++){ + WbMap[i].Len = 0; + UcMap[i].Len = 0; + } + + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = GetPowerOfTwo64(TotalAbove4GMemoryLength); + WbCount++; + MtrrCount++; + + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + + // + // UC memory length below 4GB = 4GB - total memory length below 4GB + // + MemoryLengthUc = SIZE_4G - Below4GMemoryLength; + CurrentBaseAddress = SIZE_4G - GetPowerOfTwo64 (MemoryLengthUc); + + for (PowerTwo = GetPowerOfTwo64 (MemoryLengthUc); + CurrentBaseAddress >= Below4GMemoryLength; PowerTwo = GetPowerOfTwo64 (MemoryLengthUc)) { + + //PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %08lx.\n", PowerTwo, CurrentBaseAddress)); + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = PowerTwo; + MemoryLengthUc -= PowerTwo; + CurrentBaseAddress -= GetPowerOfTwo64 (MemoryLengthUc); + UcCount++; + MtrrCount++; + if (MtrrCount > VariableMtrrCount) return EFI_OUT_OF_RESOURCES; + } + + // + // Calculate how many MTRRs needs if only use WB type + // + for (i = 0; i < 32; i++) { + if (Shr64(RemainMemoryLength, i) & 0x1 ) + NumOfOne++; + } + + //PEI_TRACE((-1, PeiServices, "Remain above 4G Memory Length = %08lx number of one = %x.\n", RemainMemoryLength, NumOfOne)); + + if (NumOfOne + MtrrCount < VariableMtrrCount){ //Use WB range is enough + + CurrentBaseAddress = GetPowerOfTwo64(TotalAbove4GMemoryLength); + while(RemainMemoryLength) + { + PowerTwo = GetPowerOfTwo64 (RemainMemoryLength); + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = PowerTwo; + WbCount++; + CurrentBaseAddress += (UINT64)PowerTwo; + RemainMemoryLength -= (UINT64)PowerTwo; + MtrrCount++; + if (MtrrCount > VariableMtrrCount) return EFI_OUT_OF_RESOURCES; + } + } else{ + // + // Use UC to overwrite WB memory + // + if ((RemainMemoryLength - GetPowerOfTwo64(RemainMemoryLength)) < SIZE_2G) + { + WbMap[WbCount].Base = GetPowerOfTwo64(TotalAbove4GMemoryLength); + WbMap[WbCount].Len = GetPowerOfTwo64(RemainMemoryLength); + RemainMemoryLength -= WbMap[WbCount].Len; + WbCount++; + MtrrCount++; + WbMap[WbCount].Base = WbMap[WbCount - 1].Base + WbMap[WbCount - 1].Len; + WbMap[WbCount].Len = GetPowerOfTwo64(Shl64(RemainMemoryLength,1)); + + MemoryLengthUc = WbMap[WbCount].Len - RemainMemoryLength; + CurrentBaseAddress = (WbMap[WbCount].Base + WbMap[WbCount].Len) - GetPowerOfTwo64(MemoryLengthUc); + if ((WbMap[WbCount].Len + WbMap[WbCount - 1].Len) == GetPowerOfTwo64(WbMap[WbCount].Len + WbMap[WbCount - 1].Len)) + { + WbMap[WbCount - 1].Len += WbMap[WbCount].Len; + WbMap[WbCount].Base = 0; + WbMap[WbCount].Len = 0; + } else { + WbCount++; + MtrrCount++; + } + + } else{ + WbMap[WbCount].Base = GetPowerOfTwo64(TotalAbove4GMemoryLength); + WbMap[WbCount].Len = GetPowerOfTwo64(Shl64(RemainMemoryLength,1)); + if (WbMap[WbCount - 1].Len == WbMap[WbCount].Base){ + // special case to save mtrr + WbMap[WbCount - 1].Len += WbMap[WbCount].Len; + WbMap[WbCount].Base = 0; + WbMap[WbCount].Len = 0; + WbCount--; + MtrrCount--; + } + + MemoryLengthUc = (WbMap[WbCount].Base + WbMap[WbCount].Len) - TotalAbove4GMemoryLength; + CurrentBaseAddress = (WbMap[WbCount].Base + WbMap[WbCount].Len) - GetPowerOfTwo64(MemoryLengthUc); + WbCount++; + MtrrCount++; + } + //PEI_TRACE((-1, PeiServices, "Above 4G UC Memory Length = %08lx base start at %08lx.\n", MemoryLengthUc, CurrentBaseAddress)); + for (PowerTwo = GetPowerOfTwo64 (MemoryLengthUc); + CurrentBaseAddress >= TotalAbove4GMemoryLength; PowerTwo = GetPowerOfTwo64 (MemoryLengthUc)) { + + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = PowerTwo; + MemoryLengthUc -= PowerTwo; + CurrentBaseAddress -= GetPowerOfTwo64 (MemoryLengthUc); + UcCount++; + MtrrCount++; + if (MtrrCount > VariableMtrrCount) return EFI_OUT_OF_RESOURCES; + } + } + + PEI_TRACE((-1, PeiServices, "Set MTRR policy1 success. MtrrCount = %d\n", MtrrCount)); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: NumOfOne +// +// Description: Count how many of ones in the binary value. +// +// Input: +// IN UINT64 InputValue - Needed count value. +// +// Output: +// UINT8 - Number of one. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 NumOfOne( + IN UINT64 InputValue) +{ + UINT8 i, j; + + for (i = 0, j = 0; i < 40; i++) { + if (Shr64(InputValue, i) & 0x1 ) + j++; + if (Shr64(InputValue, i) == 0) + break; + } + return j; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: InitMtrrPolicy2 +// +// Description: Config system cache. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// IN PEI_CACHE_PPI *CachePpi +// IN UINT64 Above4GMemoryLength +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InitMtrrPolicy2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN MEMORY_MAP *WbMap, + IN MEMORY_MAP *UcMap, + IN UINT64 Above4GMemoryLength +) +{ + UINT64 TotalMemoryLength = Above4GMemoryLength + SIZE_4G; + UINT64 RemainMemoryLength; + UINT64 Below4GMemoryLength; + UINTN i; + UINT8 WbMtrrCountBelow4G1 = 0; + UINT8 WbMtrrCountBelow4G2 = 0; + UINT8 UcMtrrCountBelow4G1 = 0; + UINT8 UcMtrrCountBelow4G2 = 0; + UINT8 WbMtrrCountAbove4G1 = 0; + UINT8 WbMtrrCountAbove4G2 = 0; + UINT8 UcMtrrCountAbove4G1 = 0; + UINT8 UcMtrrCountAbove4G2 = 0; + UINT8 UcMtrrCountAbove4G3 = 0; + UINT8 UcMtrrCountAbove4G4 = 0; + UINT8 MtrrCountRemainMemory1 = 0; + UINT8 MtrrCountRemainMemory2 = 0; + UINT8 MtrrCountRemainMemory3 = 0; + UINT64 MemoryLength; + UINT8 PolicyOneMtrrCount = 0; + UINT8 PolicyTwoMtrrCount = 0; + UINT8 PolicyThreeMtrrCount = 0; + UINT8 PolicyFourMtrrCount = 0; + UINT8 PolicyFiveMtrrCount = 0; + UINT8 PolicySixMtrrCount = 0; + BOOLEAN WbSpecialCase1 = 0; + BOOLEAN WbSpecialCase2 = 0; + + for(i = 0; i < 10; i++){ + WbMap[i].Len = 0; + UcMap[i].Len = 0; + } + + //First, we calculate how many MTRR we need in different situation. + //1. Calculating MTRR when only use wb type in below 4G memory + //There are two size of Below4GMemoryLength. One is NBGetTsegBase() + TSEG_SIZE, the other is NBGetTsegBase(). + //Therefore we have two calculating method to calculate wb MTRR below 4G memory. + //A.When Below4GMemoryLength is NBGetTsegBase() + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + WbMtrrCountBelow4G1 = NumOfOne(Below4GMemoryLength); + + //B.When Below4GMemoryLength is NBGetTsegBase() + TSEG_SIZE + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + WbMtrrCountBelow4G2 = NumOfOne(Below4GMemoryLength); + + //2. Calculating MTRR when use wb type from 0 to 4G, then use uc type to overwrite 4G to Below4GMemoryLength. + //There are two size of Below4GMemoryLength. One is NBGetTsegBase() + TSEG_SIZE, the other is NBGetTsegBase(). + //Therefore we have two calculating method to calculate uc MTRR below 4G memory. + //A.When Below4GMemoryLength is NBGetTsegBase() + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + UcMtrrCountBelow4G1 = NumOfOne(((UINT64)SIZE_4G - Below4GMemoryLength)); + + //B.When Below4GMemoryLength is NBGetTsegBase() + TSEG_SIZE + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + UcMtrrCountBelow4G2 = NumOfOne(((UINT64)SIZE_4G - Below4GMemoryLength)); + + //3. Calculating MTRR when Memory above 4G is larger then 4G. + //A.If it's larger then 4G, memory above 4G should minus SIZE_4G and MTRR count should add 1. + //Next, if remain memory above 4G still larger than SIZE_8G, remain memory minus SIZE_8G and MTRR count should add 1. + //Next, if remain memory above 4G still larger than SIZE_16G, remain memory minus SIZE_16G and MTRR count should add 1. And so on. + RemainMemoryLength = Above4GMemoryLength; + MemoryLength = SIZE_4G; + for (MtrrCountRemainMemory1 = 0; RemainMemoryLength >= MemoryLength; MemoryLength = Shl64(MemoryLength, 1)) { + MtrrCountRemainMemory1++; + RemainMemoryLength -= MemoryLength; + } + + //B.Calculating MTRR when use wb type till remain memory is smaller then 2G + MemoryLength = GetPowerOfTwo64(RemainMemoryLength); + for (MtrrCountRemainMemory2 = 0; RemainMemoryLength >= SIZE_2G;) { + MemoryLength = GetPowerOfTwo64(RemainMemoryLength); + MtrrCountRemainMemory2++; + RemainMemoryLength -= MemoryLength; + } + + //C.Calculating MTRR when only use wb type in remain memory + WbMtrrCountAbove4G1 = NumOfOne(RemainMemoryLength) + MtrrCountRemainMemory2; + + //Special case for saving MTRR. If wb setting can combine with previous wb setting. This case only occur in Policy two. + if ((MtrrCountRemainMemory2 != 0) && (Shl64(GetPowerOfTwo64 (RemainMemoryLength), 1) == MemoryLength)) + WbSpecialCase1 = 0; + else + WbSpecialCase1 = 1; + + //D.Calculating MTRR when use uc type to overwrite wb type. + RemainMemoryLength = (Shl64(GetPowerOfTwo64 (RemainMemoryLength), 1)) - RemainMemoryLength; + UcMtrrCountAbove4G2 = NumOfOne(RemainMemoryLength); + + //4. Calculating MTRR when use uc type to overwrite wb type above 4G memory, there are two calculating methods. + //A.Set wb type from 4G to shl(PowerOfTwo64(TotalMemoryLength),1), + //then use uc to overwrite overflow wb memory. + RemainMemoryLength = TotalMemoryLength - Shl64(SIZE_4G , MtrrCountRemainMemory1); + RemainMemoryLength = (Shl64(GetPowerOfTwo64 (RemainMemoryLength), 1)) - RemainMemoryLength; + UcMtrrCountAbove4G1 = NumOfOne(RemainMemoryLength); + + //B.Set wb type from 0 to shl(PowerOfTwo64(TotalMemoryLength), 1), + //then use uc to overwrite overflow wb memory. + RemainMemoryLength = (Shl64(GetPowerOfTwo64 (TotalMemoryLength), 1)) - TotalMemoryLength; + UcMtrrCountAbove4G3 = NumOfOne(RemainMemoryLength); + + //5. Calculating MTRR when (TotalMemoryLength) minus PowerOfTwo64(TotalMemoryLength) is larger then 2G. + //A. Calculating MTRR when use wb type till remain memory is smaller then 2G + RemainMemoryLength = TotalMemoryLength - GetPowerOfTwo64(TotalMemoryLength); + MemoryLength = GetPowerOfTwo64(RemainMemoryLength); + for (MtrrCountRemainMemory3 = 0; RemainMemoryLength >= SIZE_2G;) { + MemoryLength = GetPowerOfTwo64(RemainMemoryLength); + MtrrCountRemainMemory3++; + RemainMemoryLength -= MemoryLength; + } + //B.Calculating MTRR when use wb type in Remain memory + WbMtrrCountAbove4G2 = NumOfOne(RemainMemoryLength) + MtrrCountRemainMemory3; + + //Special case for saving MTRR. If wb setting can combine with previous wb setting. This case only occur in Policy five. + if ((MtrrCountRemainMemory3 != 0) && (Shl64(GetPowerOfTwo64 (RemainMemoryLength), 1) == MemoryLength)) + WbSpecialCase2 = 0; + else + WbSpecialCase2 = 1; + + //C.Calculating MTRR when use uc type to overwrite wb type. + RemainMemoryLength = (Shl64(GetPowerOfTwo64 (RemainMemoryLength), 1)) - RemainMemoryLength; + UcMtrrCountAbove4G4 = NumOfOne(RemainMemoryLength); + + //Second, Calculating MTRR for each setting MTRR policy. + //Policy 1:Only use wb type from 0 to Below4GMemoryLength, and 4G to TotalMemoryLength. + // + // _______ TotalMemoryLength + // |Wb Set | + // |-------| 4G + // |Uc Ori | + // |-------| Below4GMemoryLength + // |Wb Set | + // |_______| 0 + //Chose which Below4GMemoryLength((NBGetTsegBase() + TSEG_SIZE) or NBGetTsegBase()) is better for below 4G memory MTRR setting. + if (WbMtrrCountBelow4G1 < WbMtrrCountBelow4G2) + PolicyOneMtrrCount = WbMtrrCountBelow4G1 + WbMtrrCountAbove4G1 + MtrrCountRemainMemory1; + else + PolicyOneMtrrCount = WbMtrrCountBelow4G2 + WbMtrrCountAbove4G1 + MtrrCountRemainMemory1; + + //Policy 2:First, Use wb type from 0 to Below4GMemoryLength. Use wb type from 4G to 8G, 8G to 16G, and so on. + // Second, if remain memory larger then 2G , use wb type till remain memory samller then 2G. last, set wb type to shl(RemainMemory, 1). + // Third, use uc type from shl(RemainMemory, 1) to TotalMemoryLength. + // first Second third + // |-------| |-------| shl(RemainMemory, 1) + // | | |Uc Set | + // |Wb Set | |_______| TotalMemoryLength + // |-------| 4G |-------| 4G + // |Uc Ori | |Same | + // |-------| Below4GMemoryLength |as | + // |Wb Set | |first | + // |_______| 0 |_______| 0 + //Chose which Below4GMemoryLength((NBGetTsegBase() + TSEG_SIZE) or NBGetTsegBase()) is better for below 4G memory MTRR setting. + if (WbMtrrCountBelow4G1 < WbMtrrCountBelow4G2) + PolicyTwoMtrrCount = WbMtrrCountBelow4G1 + MtrrCountRemainMemory1 + MtrrCountRemainMemory2 + WbSpecialCase1 + UcMtrrCountAbove4G2; + else + PolicyTwoMtrrCount = WbMtrrCountBelow4G2 + MtrrCountRemainMemory1 + MtrrCountRemainMemory2 + WbSpecialCase1 + UcMtrrCountAbove4G2; + + //Policy 3: First, Use wb type from 0 to Below4GMemoryLength. Use wb type from 4G to 8G, 8G to 16G, and so on. + // Second, set wb type to shl(RemainMemory, 1). + // Third, use uc type form shl(RemainMemory, 1) to TotalMemoryLength; + // first Second third + // |-------| shl(PowerOfTwo64(TotalMemoryLength), 1) |-------| shl(PowerOfTwo64(TotalMemoryLength), 1) + // | | |Uc Set | + // |Wb Set | |_______| TotalMemoryLength + // |-------| 4G |-------| 4G + // |Uc Ori | |Same | + // |-------| Below4GMemoryLength |as | + // |Wb Set | |first | + // |_______| 0 |_______| 0 + //Chose which Below4GMemoryLength((NBGetTsegBase() + TSEG_SIZE) or NBGetTsegBase()) is better for below 4G memory MTRR setting. + if (WbMtrrCountBelow4G1 < WbMtrrCountBelow4G2) + PolicyThreeMtrrCount = WbMtrrCountBelow4G1 + MtrrCountRemainMemory1 + 1 + UcMtrrCountAbove4G1; + else + PolicyThreeMtrrCount = WbMtrrCountBelow4G2 + MtrrCountRemainMemory1 + 1 + UcMtrrCountAbove4G1; + + //Policy 4: First, use wb type from 0 to PowerOfTwo64(TotalMemoryLength). + // Second, use uc type from 4G to Below4GMemoryLength. + // Third, use wb type from PowerOfTwo64(TotalMemoryLength) to TotalMemoryLength. + // first second and third + // |--------| PowerOfTwo64(TotalMemoryLength) _______ TotalMemoryLength + // | | |Wb Set | + // |Wb Set | |-------| PowerOfTwo64(TotalMemoryLength) + // |ALL | | | + // | | |-------| 4G + // | | |Uc Set | + // | | |-------| Below4GMemoryLength + // |________| 0 |_______| 0 + //Chose which Below4GMemoryLength is better for below 4G memory MTRR setting. + if (UcMtrrCountBelow4G1 < UcMtrrCountBelow4G2) + PolicyFourMtrrCount = 1 + UcMtrrCountBelow4G1 + WbMtrrCountAbove4G2; + else + PolicyFourMtrrCount = 1 + UcMtrrCountBelow4G2 + WbMtrrCountAbove4G2; + + //Policy 5: First, use wb type from 0 to PowerOfTwo64(TotalMemoryLength). + // Second, use uc type from 4G to Below4GMemoryLength. + // Third, remain memory will be (TotalMemoryLength - PowerOfTwo64(TotalMemoryLength)) use wb type\ + // from PowerOfTwo64(TotalMemoryLength) to shl(RemainMemory, 1). + // Four, use uc type from shl(RemainMemory, 1) to TotalMemoryLength. + // first second and third Four + // |--------| PowerOfTwo64(TotalMemoryLength) ------- shl(RemainMemory, 1) ------- shl(RemainMemory, 1) + // | | |_______| TotalMemoryLength |Uc Set | + // |Wb Set | |Wb Set | |_______| TotalMemoryLength + // |ALL | |-------| PowerOfTwo64(TotalMemoryLength) | | + // | | |-------| 4G |Same | + // | | |Uc Set | |as | + // | | |-------| Below4GMemoryLength |before | + // |________| 0 |_______| 0 |_______| 0 + //Chose which Below4GMemoryLength is better for below 4G memory MTRR setting. + if (UcMtrrCountBelow4G1 < UcMtrrCountBelow4G2) + PolicyFiveMtrrCount = 1 + UcMtrrCountBelow4G1 + MtrrCountRemainMemory3 + WbSpecialCase2 + UcMtrrCountAbove4G4; + else + PolicyFiveMtrrCount = 1 + UcMtrrCountBelow4G2 + MtrrCountRemainMemory3 + WbSpecialCase2 + UcMtrrCountAbove4G4; + + //Policy 6:First, use wb type to shl(PowerOfTwo64(TotalMemoryLength), 1). + // Second, use uc type from 4G to Below4GMemoryLength and + // Uc type from shl(PowerOfTwo64(TotalMemoryLength), 1) to TotalMemoryLength. + // first second + // |--------| shl(PowerOfTwo64(TotalMemoryLength), 1) |-------| shl(PowerOfTwo64(TotalMemoryLength), 1) + // | | |Uc Set | + // |Wb Set | |_______| TotalMemoryLength + // |ALL | | | + // | | |-------| 4G + // | | |Uc Set | + // | | |-------| Below4GMemoryLength + // |________| 0 |_______| 0 + //Chose which Below4GMemoryLength is better for below 4G memory MTRR setting. + if (UcMtrrCountBelow4G1 < UcMtrrCountBelow4G2) + PolicySixMtrrCount = 1 + UcMtrrCountBelow4G1 + UcMtrrCountAbove4G3; + else + PolicySixMtrrCount = 1 + UcMtrrCountBelow4G2 + UcMtrrCountAbove4G3; + +// PEI_TRACE((-1, PeiServices, "WbMtrrCountBelow4G1 = %d, WbMtrrCountBelow4G2 = %d.\n", WbMtrrCountBelow4G1, WbMtrrCountBelow4G2)); +// PEI_TRACE((-1, PeiServices, "UcMtrrCountBelow4G1 = %d, UcMtrrCountBelow4G2 = %d.\n", UcMtrrCountBelow4G1, UcMtrrCountBelow4G2)); +// PEI_TRACE((-1, PeiServices, "WbMtrrCountAbove4G1 = %d, WbMtrrCountAbove4G2= %d, UcMtrrCountAbove4G1 = %d.\n", WbMtrrCountAbove4G1, WbMtrrCountAbove4G2, UcMtrrCountAbove4G1)); +// PEI_TRACE((-1, PeiServices, "UcMtrrCountAbove4G2 = %d, UcMtrrCountAbove4G3 = %d, UcMtrrCountAbove4G4= %d.\n", UcMtrrCountAbove4G2, UcMtrrCountAbove4G3, UcMtrrCountAbove4G4)); +// PEI_TRACE((-1, PeiServices, "WbSpecialCase1 = %d, WbSpecialCase2 = %d.\n", WbSpecialCase1, WbSpecialCase2)); +// PEI_TRACE((-1, PeiServices, "MtrrCountRemainMemory1 = %d, MtrrCountRemainMemory2 = %d, MtrrCountRemainMemory3 = %d.\n", MtrrCountRemainMemory1, MtrrCountRemainMemory2, MtrrCountRemainMemory3)); +// PEI_TRACE((-1, PeiServices, "PolicyOneMtrrCount = %d, PolicyTwoMtrrCount = %d, PolicyThreeMtrrCount = %d.\n", PolicyOneMtrrCount, PolicyTwoMtrrCount, PolicyThreeMtrrCount)); +// PEI_TRACE((-1, PeiServices, "PolicyFourMtrrCount = %d, PolicyFiveMtrrCount = %d, PolicySixMtrrCount = %d.\n", PolicyFourMtrrCount, PolicyFiveMtrrCount, PolicySixMtrrCount)); +// PEI_TRACE((-1, PeiServices, "TsegBase = 0x%8lX, Above4GMemoryLength = 0x%8lX.\n", (UINT64)NBGetTsegBase(), Above4GMemoryLength)); + + //Policy one + if (PolicyOneMtrrCount <= VariableMtrrCount) { + EFI_STATUS Status = EFI_SUCCESS; + UINT64 CurrentBaseAddress = 0; + UINT8 MtrrCount = 0; + UINT8 WbCount = 0; + + //1.Chose which Below4GMemoryLength is better + if (WbMtrrCountBelow4G1 < WbMtrrCountBelow4G2) + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + else + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + //2.Use wb type from 0 to Below4GMemoryLength + RemainMemoryLength = Below4GMemoryLength; + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + + //3.When memory above 4G is larger then 4G, set a wb type MTRR from 4G to 8G. + //Next, if remain memory above 4G still larger than 8G, set a wb type MTRR from 8G to 16G. And so on. + if (Status == EFI_SUCCESS) { + RemainMemoryLength = Above4GMemoryLength; + CurrentBaseAddress = SIZE_4G; + for (MemoryLength = SIZE_4G; RemainMemoryLength >= MemoryLength; MemoryLength = Shl64(MemoryLength, 1)) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + + //4.Next, set RemainMemoryLength to wb type. + if (Status == EFI_SUCCESS) { + for (MemoryLength = GetPowerOfTwo64(RemainMemoryLength); RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + } + + if (Status == EFI_SUCCESS) { + PEI_TRACE((-1, PeiServices, "Set MTRR policy one success. MtrrCount = %d\n", MtrrCount)); + return EFI_SUCCESS; + } + } + + //Initialize, just in case + if ((WbMap[0].Len != 0) || (UcMap[0].Len != 0)) { + for(i = 0; i < 10; i++){ + WbMap[i].Len = 0; + UcMap[i].Len = 0; + } + } + + //Policy Two + if (PolicyTwoMtrrCount <= VariableMtrrCount) { + EFI_STATUS Status = EFI_SUCCESS; + UINT64 CurrentBaseAddress = 0; + UINT8 MtrrCount = 0; + UINT8 WbCount = 0; + UINT8 UcCount = 0; + + //1.Chose which Below4GMemoryLength is better + if (WbMtrrCountBelow4G1 < WbMtrrCountBelow4G2) + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + else + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + //2.Use wb type from 0 to Below4GMemoryLength + RemainMemoryLength = Below4GMemoryLength; + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + + //3.When memory above 4G is larger then 4G, set a wb type MTRR from 4G to 8G. + //Next, if remain memory above 4G still larger than 8G, set a wb type MTRR from 8G to 16G. And so on. + if (Status == EFI_SUCCESS) { + RemainMemoryLength = Above4GMemoryLength; + CurrentBaseAddress = SIZE_4G; + for (MemoryLength = SIZE_4G; RemainMemoryLength >= MemoryLength; MemoryLength = Shl64(MemoryLength, 1)) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + + //4.Next, if remain memory larger than 2G, set wb type till remain memory smaller than 2G. + if (Status == EFI_SUCCESS) { + for (MemoryLength = GetPowerOfTwo64(RemainMemoryLength); RemainMemoryLength >= SIZE_2G; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + } + + //5. Set a wb type from CurrentBaseAddress to shl(PowerOfTwo64(RemainMemoryLength), 1) + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = Shl64(GetPowerOfTwo64(RemainMemoryLength), 1); + //Special case for saving MTRR. If wb setting can combine with previous wb setting. + if (((WbMap[WbCount - 1].Base + WbMap[WbCount - 1].Len) == WbMap[WbCount].Base) && + (GetPowerOfTwo64(WbMap[WbCount - 1].Base) > WbMap[WbCount - 1].Len) && + (WbMap[WbCount - 1].Len == WbMap[WbCount].Len)) { + WbMap[WbCount - 1].Len += WbMap[WbCount].Len; + WbMap[WbCount].Base = 0; + WbMap[WbCount].Len = 0; +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", WbMap[WbCount - 1].Len, WbMap[WbCount - 1].Base, MtrrCount - 1)); + } + else { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", WbMap[WbCount].Len, CurrentBaseAddress, MtrrCount)); + MtrrCount++; + WbCount++; + } + + CurrentBaseAddress += Shl64(GetPowerOfTwo64(RemainMemoryLength), 1); + + //6.Next, set uc type from Shl64(GetPowerOfTwo64(TotalMemoryLength), 1) to TotalMemoryLength, overwrite wb type. + RemainMemoryLength = Shl64(GetPowerOfTwo64(RemainMemoryLength), 1) - RemainMemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64(RemainMemoryLength); + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = MemoryLength; + MtrrCount++; + UcCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + } + } + + if (Status == EFI_SUCCESS) { + PEI_TRACE((-1, PeiServices, "Set MTRR policy two success. MtrrCount = %d\n", MtrrCount)); + return EFI_SUCCESS; + } + } + + //Initialize, just in case + if ((WbMap[0].Len != 0) || (UcMap[0].Len != 0)) { + for(i = 0; i < 10; i++){ + WbMap[i].Len = 0; + UcMap[i].Len = 0; + } + } + + //Policy Three + if (PolicyThreeMtrrCount <= VariableMtrrCount) { + EFI_STATUS Status = EFI_SUCCESS; + UINT64 CurrentBaseAddress = 0; + UINT8 MtrrCount = 0; + UINT8 WbCount = 0; + UINT8 UcCount = 0; + + //1.Chose which Below4GMemoryLength is better + if (WbMtrrCountBelow4G1 < WbMtrrCountBelow4G2) + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + else + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + //2.Use wb type from 0 to Below4GMemoryLength + RemainMemoryLength = Below4GMemoryLength; + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + + //3.When memory above 4G is larger then 4G, set a wb type MTRR from 4G to 8G. + //Next, if remain memory above 4G still larger than 8G, set a wb type MTRR from 8G to 16G. + if (Status == EFI_SUCCESS) { + RemainMemoryLength = Above4GMemoryLength; + CurrentBaseAddress = SIZE_4G; + for (MemoryLength = SIZE_4G; RemainMemoryLength >= MemoryLength; MemoryLength = Shl64(MemoryLength, 1)) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + CurrentBaseAddress += MemoryLength; + RemainMemoryLength -= MemoryLength; + } + } + + //4.Next, set wb type from 4G to Shl64(GetPowerOfTwo64(RemainMemoryLength), 1). + RemainMemoryLength = TotalMemoryLength - CurrentBaseAddress; + if (Status == EFI_SUCCESS) { + if (RemainMemoryLength > 0) { + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = Shl64(GetPowerOfTwo64(RemainMemoryLength), 1); +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", Shl64(GetPowerOfTwo64(RemainMemoryLength), 1), CurrentBaseAddress, MtrrCount)); + MtrrCount++; + WbCount++; + CurrentBaseAddress += Shl64(GetPowerOfTwo64(RemainMemoryLength), 1); + RemainMemoryLength = Shl64(GetPowerOfTwo64(RemainMemoryLength), 1) - RemainMemoryLength; + } + } + + //5.Next, set uc type from Shl64(GetPowerOfTwo64(RemainMemoryLength), 1) to RemainMemoryLength + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + for (MemoryLength = GetPowerOfTwo64(RemainMemoryLength); RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = MemoryLength; + MtrrCount++; + UcCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + } + } + + if (Status == EFI_SUCCESS) { + PEI_TRACE((-1, PeiServices, "Set MTRR policy three success. MtrrCount = %d\n", MtrrCount)); + return EFI_SUCCESS; + } + } + + //Initialize, just in case + if ((WbMap[0].Len != 0) || (UcMap[0].Len != 0)) { + for(i = 0; i < 10; i++){ + WbMap[i].Len = 0; + UcMap[i].Len = 0; + } + } + + //Policy Four + if (PolicyFourMtrrCount <= VariableMtrrCount) { + EFI_STATUS Status = EFI_SUCCESS; + UINT64 CurrentBaseAddress = 0; + UINT8 MtrrCount = 0; + UINT8 WbCount = 0; + UINT8 UcCount = 0; + + //1.Chose which Below4GMemoryLength is better + if (UcMtrrCountBelow4G1 < UcMtrrCountBelow4G2) + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + else + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + + RemainMemoryLength = TotalMemoryLength; + + //2.Set GetPowerOfTwo64(RemainMemoryLength) to wb type. + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = GetPowerOfTwo64(RemainMemoryLength); +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", GetPowerOfTwo64(RemainMemoryLength), CurrentBaseAddress, MtrrCount)); + MtrrCount++; + WbCount++; + CurrentBaseAddress += GetPowerOfTwo64(RemainMemoryLength); + RemainMemoryLength -= GetPowerOfTwo64(RemainMemoryLength); + + //3.Next, use wb type from CurrentBaseAddress to TotalMemoryLength. + for (MemoryLength = GetPowerOfTwo64(RemainMemoryLength); RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress += MemoryLength; + } + } + + //4.Next, use uc type from Below4GMemoryLength to 4G + if (Status == EFI_SUCCESS) { + RemainMemoryLength = SIZE_4G - Below4GMemoryLength; + CurrentBaseAddress = SIZE_4G - GetPowerOfTwo64 (RemainMemoryLength); + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = MemoryLength; + MtrrCount++; + UcCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + } + } + } + + if (Status == EFI_SUCCESS) { + PEI_TRACE((-1, PeiServices, "Set MTRR policy four success. MtrrCount = %d\n", MtrrCount)); + return EFI_SUCCESS; + } + } + + //Initialize, just in case + if ((WbMap[0].Len != 0) || (UcMap[0].Len != 0)) { + for(i = 0; i < 10; i++){ + WbMap[i].Len = 0; + UcMap[i].Len = 0; + } + } + + //Policy Five + if (PolicyFiveMtrrCount <= VariableMtrrCount) { + EFI_STATUS Status = EFI_SUCCESS; + UINT64 CurrentBaseAddress = 0; + UINT8 MtrrCount = 0; + UINT8 WbCount = 0; + UINT8 UcCount = 0; + + //1.Chose which Below4GMemoryLength is better + if (UcMtrrCountBelow4G1 < UcMtrrCountBelow4G2) + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + else + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + + RemainMemoryLength = TotalMemoryLength; + + //2.Set GetPowerOfTwo64(RemainMemoryLength) to wb type. + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = GetPowerOfTwo64(RemainMemoryLength); +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", GetPowerOfTwo64(RemainMemoryLength), CurrentBaseAddress, MtrrCount)); + MtrrCount++; + WbCount++; + CurrentBaseAddress += GetPowerOfTwo64(RemainMemoryLength); + RemainMemoryLength -= GetPowerOfTwo64(RemainMemoryLength); + + //3.Next, use wb type from CurrentBaseAddress till remain memory is smaller 2G. + for (MemoryLength = GetPowerOfTwo64(RemainMemoryLength); RemainMemoryLength >= SIZE_2G; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = MemoryLength; + MtrrCount++; + WbCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress += MemoryLength; + } + } + + //4. Set a wb type from CurrentBaseAddress to shl(PowerOfTwo64(RemainMemoryLength), 1) + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = Shl64(GetPowerOfTwo64(RemainMemoryLength), 1); + //Special case for saving MTRR. If wb setting can combine with previous wb setting. + if (((WbMap[WbCount - 1].Base + WbMap[WbCount - 1].Len) == WbMap[WbCount].Base) && + (GetPowerOfTwo64(WbMap[WbCount - 1].Base) > WbMap[WbCount - 1].Len) && + (WbMap[WbCount - 1].Len == WbMap[WbCount].Len)) { + WbMap[WbCount - 1].Len += WbMap[WbCount].Len; + WbMap[WbCount].Base = 0; + WbMap[WbCount].Len = 0; +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", WbMap[WbCount - 1].Len, WbMap[WbCount - 1].Base, MtrrCount - 1)); + } + else { +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", WbMap[WbCount].Len, CurrentBaseAddress, MtrrCount)); + MtrrCount++; + WbCount++; + } + CurrentBaseAddress += Shl64(GetPowerOfTwo64(RemainMemoryLength), 1); + + //5.Next, set uc type from Shl64(GetPowerOfTwo64(TotalMemoryLength), 1) to TotalMemoryLength, overwrite wb type. + RemainMemoryLength = Shl64(GetPowerOfTwo64(RemainMemoryLength), 1) - RemainMemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64(RemainMemoryLength); + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = MemoryLength; + MtrrCount++; + UcCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + } + } + + //6.Next, use uc type from Below4GMemoryLength to 4G + if (Status == EFI_SUCCESS) { + RemainMemoryLength = SIZE_4G - Below4GMemoryLength; + CurrentBaseAddress = SIZE_4G - GetPowerOfTwo64 (RemainMemoryLength); + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = MemoryLength; + MtrrCount++; + UcCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + } + } + } + + if (Status == EFI_SUCCESS) { + PEI_TRACE((-1, PeiServices, "Set MTRR policy five success. MtrrCount = %d\n", MtrrCount)); + return EFI_SUCCESS; + } + } + + //Initialize, just in case + if ((WbMap[0].Len != 0) || (UcMap[0].Len != 0)) { + for(i = 0; i < 10; i++){ + WbMap[i].Len = 0; + UcMap[i].Len = 0; + } + } + + //Policy Six + if (PolicySixMtrrCount <= VariableMtrrCount) { + EFI_STATUS Status = EFI_SUCCESS; + UINT64 CurrentBaseAddress = 0; + UINT8 MtrrCount = 0; + UINT8 WbCount = 0; + UINT8 UcCount = 0; + + //1.Chose which Below4GMemoryLength is better for below 4G memory MTRR setting. + if (UcMtrrCountBelow4G1 < UcMtrrCountBelow4G2) + Below4GMemoryLength = (UINT64)NBGetTsegBase(); + else + Below4GMemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE; + + //2.Set wb type from 0 to Shl64(GetPowerOfTwo64(TotalMemoryLength), 1). + WbMap[WbCount].Base = CurrentBaseAddress; + WbMap[WbCount].Len = Shl64(GetPowerOfTwo64(TotalMemoryLength), 1); +// PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx. MtrrCount = %x\n", Shl64(GetPowerOfTwo64(TotalMemoryLength), 1), CurrentBaseAddress, MtrrCount)); + MtrrCount++; + WbCount++; + CurrentBaseAddress += Shl64(GetPowerOfTwo64(TotalMemoryLength), 1); + + //3.Next, set uc type from Shl64(GetPowerOfTwo64(TotalMemoryLength), 1) to TotalMemoryLength. + RemainMemoryLength = Shl64(GetPowerOfTwo64(TotalMemoryLength), 1) - TotalMemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64(RemainMemoryLength); + for (MemoryLength = GetPowerOfTwo64(RemainMemoryLength); RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = MemoryLength; + MtrrCount++; + UcCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + } + } + + //4.Next, use uc type from Below4GMemoryLength to 4G + if (Status == EFI_SUCCESS) { + RemainMemoryLength = SIZE_4G - Below4GMemoryLength; + CurrentBaseAddress = SIZE_4G - GetPowerOfTwo64 (RemainMemoryLength); + for (MemoryLength = SIZE_2G; RemainMemoryLength > 0; MemoryLength = GetPowerOfTwo64(RemainMemoryLength)) { + if (RemainMemoryLength >= MemoryLength) { +// PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx. MtrrCount = %x\n", MemoryLength, CurrentBaseAddress, MtrrCount)); + if (MtrrCount >= VariableMtrrCount) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + UcMap[UcCount].Base = CurrentBaseAddress; + UcMap[UcCount].Len = MemoryLength; + MtrrCount++; + UcCount++; + RemainMemoryLength -= MemoryLength; + CurrentBaseAddress -= GetPowerOfTwo64 (RemainMemoryLength); + } + } + } + + if (Status == EFI_SUCCESS) { + PEI_TRACE((-1, PeiServices, "Set MTRR policy six success. MtrrCount = %d\n", MtrrCount)); + return EFI_SUCCESS; + } + } + PEI_TRACE((-1, PeiServices, "Set MTRR status = EFI_OUT_OF_RESOURCES\n")); + return EFI_OUT_OF_RESOURCES; +} +#endif + +#if PERF_TUNE_SUPPORT == 1 +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: CpuPeiIntelXtuDataInit +// +// Description: +// Interl XTU utility data initialize in PEI phase +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// IN EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariablePpi +// IN EFI_BOOT_MODE BootMode +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CpuPeiIntelXtuDataInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariablePpi, + IN EFI_BOOT_MODE BootMode +) +{ + EFI_STATUS Status; + BIOS_SETTING_DATA SettingData; + EFI_GUID PerfTunePpiGuid = PERF_TUNE_PPI_GUID; + EFI_GUID WdtPpiGuid = PERF_TUNE_WDT_PPI_GUID; + PERF_TUNE_PPI *PerfTunePpi; + PERF_TUNE_WDT_PPI *WdtPpi; + DDDT_PRESENT_FLAG_HOB *DddtPreFlagHob; + VOID *FirstHob; + UINT32 CpuSignature = GetCpuSignature(); + UINT32 CpuSigNoVer = CpuSignature & 0xfffffff0; + UINT8 i; + UINT8 CpuCores = NumCpuCores(); + UINT8 NumOcBins = 0; + UINT8 CpuImptype[] = {BIOS_1_CORE_RATIO_IMPLEMENTATION,\ + BIOS_2_CORE_RATIO_IMPLEMENTATION,\ + BIOS_3_CORE_RATIO_IMPLEMENTATION,\ + BIOS_4_CORE_RATIO_IMPLEMENTATION,\ + BIOS_5_CORE_RATIO_IMPLEMENTATION,\ + BIOS_6_CORE_RATIO_IMPLEMENTATION }; + + OVERCLOCKING_CONFIG_HOB *OverclockConfigHob; + OVERCLOCKING_CONFIG_DATA *OverclockData; + + if (CpuSigNoVer != IVY_BRIDGE) + NumOcBins = (UINT8)((UINT32)(ReadMsr(MSR_FLEX_RATIO)) >> 17) & 0x7; + + Status = (*PeiServices)->GetHobList(PeiServices, &FirstHob); + ASSERT_PEI_ERROR(PeiServices, Status); + + DddtPreFlagHob = (DDDT_PRESENT_FLAG_HOB*) FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &DddtPreFlagHob))) { + if (guidcmp(&((EFI_HOB_GUID_TYPE*)DddtPreFlagHob)->Name, &gAmiDddtPreFlagHobGuid) == 0) { + break; + } + } + + if(!EFI_ERROR(Status)){ + //iGfx Core Current Max Dddt Flag set to 1 or 0 + //if((DddtPreFlagHob->PresentFlag[BIOS_GRAPHICS_TURBO_RATIO_LIMIT_IMPLEMENTATION] == 0)||\ + // (DddtPreFlagHob->PresentFlag[BIOS_GRAPHICS_CORE_VOLTAGE_IMPLEMENTATION] == 0)) + // DddtPreFlagHob->PresentFlag[BIOS_IGFX_CORE_CURRENT_MAX_IMPLEMENTATION] = 0; + //else + // DddtPreFlagHob->PresentFlag[BIOS_IGFX_CORE_CURRENT_MAX_IMPLEMENTATION] = 1; + DddtPreFlagHob->PresentFlag[BIOS_IGFX_CORE_CURRENT_MAX_IMPLEMENTATION] = 0; //disable IGFX current MAX + + //if Cpu is partial unlock or full unlock then turbo Core ratio dddt should not build. + PEI_TRACE((-1, PeiServices, "CPU PEI XTU data init CpuCores = %x\n", CpuCores)); + for (i = 0; i < sizeof(CpuImptype); i++){ + if(CpuCores < (i + 1)){ + DddtPreFlagHob->PresentFlag[CpuImptype[i]] = 0; + } + } + + //Force Runtime Turbo disable + if (NumOcBins) + DddtPreFlagHob->PresentFlag[BIOS_RUNTIME_TURBO_ENABLE_IMPLEMENTATION] = 1; + else + DddtPreFlagHob->PresentFlag[BIOS_RUNTIME_TURBO_ENABLE_IMPLEMENTATION] = 0; + + //Overclocking Core Ratio Limit disable + if (!isXECoreRatioLimitSupported()){ + DddtPreFlagHob->PresentFlag[BIOS_1_CORE_RATIO_IMPLEMENTATION] = 0;//One-core Flag + DddtPreFlagHob->PresentFlag[BIOS_2_CORE_RATIO_IMPLEMENTATION] = 0;//Two-core Flag + DddtPreFlagHob->PresentFlag[BIOS_3_CORE_RATIO_IMPLEMENTATION] = 0;//Three-core Flag + DddtPreFlagHob->PresentFlag[BIOS_4_CORE_RATIO_IMPLEMENTATION] = 0;//Four-core Flag + DddtPreFlagHob->PresentFlag[BIOS_5_CORE_RATIO_IMPLEMENTATION] = 0;//Five-core Flag + DddtPreFlagHob->PresentFlag[BIOS_6_CORE_RATIO_IMPLEMENTATION] = 0;//Six-core Flag + } + + //Package Power Limit disable + // Skus that support Config TDP are not able to change power limit(MSR 0x610) in real time. + if (!isXETdcTdpLimitSupported() || (Shr64(ReadMsr(MSR_PLATFORM_INFO), 32) & (BIT1 | BIT2)) ){ + DddtPreFlagHob->PresentFlag[BIOS_SHORT_TDP_IMPLEMENTATION] = 0; //Short TDP Flag + DddtPreFlagHob->PresentFlag[BIOS_EXTENDED_TDP_IMPLEMENTATION] = 0; //Extended TDP Flag + DddtPreFlagHob->PresentFlag[BIOS_SHORT_TDP_ENABLE_IMPLEMENTATION] = 0; //Short TDP Enable Flag + DddtPreFlagHob->PresentFlag[BIOS_EXTENDED_TDP_ENABLE_IMPLEMENTATION] = 0; //Package TDP Enable Flag + DddtPreFlagHob->PresentFlag[BIOS_EXTENDED_TIME_WINDOW_IMPLEMENTATION] = 0; //Package TDP Time Window Flag + } + DddtPreFlagHob->PresentFlag[BIOS_RUNTIME_TURBO_OVERRIDE_IMPLEMENTATION] = 0; + DddtPreFlagHob->PresentFlag[BIOS_MAX_TURBO_MODE_CPU_VOLTAGE_IMPLEMENTATION] = 0; + + //if cpu not support turbo mode, disable TDP, TDC, extend tdp, short tdp and all core ratio DDD table creation. + if(!isTurboModeSupported()){ + DddtPreFlagHob->PresentFlag[BIOS_TURBO_ENABLE_IMPLEMENTATION] = 0; //Turbo Eanble Flag + DddtPreFlagHob->PresentFlag[BIOS_TDC_VALUE_IMPLEMENTATION] = 0; //TDC Flag + DddtPreFlagHob->PresentFlag[BIOS_TDP_VALUE_IMPLEMENTATION] = 0; //TDP Flag + DddtPreFlagHob->PresentFlag[BIOS_1_CORE_RATIO_IMPLEMENTATION] = 0; //One-core Flag + DddtPreFlagHob->PresentFlag[BIOS_2_CORE_RATIO_IMPLEMENTATION] = 0; //Two-core Flag + DddtPreFlagHob->PresentFlag[BIOS_3_CORE_RATIO_IMPLEMENTATION] = 0; //Three-core Flag + DddtPreFlagHob->PresentFlag[BIOS_4_CORE_RATIO_IMPLEMENTATION] = 0; //Four-core Flag + DddtPreFlagHob->PresentFlag[BIOS_5_CORE_RATIO_IMPLEMENTATION] = 0; //Five-core Flag + DddtPreFlagHob->PresentFlag[BIOS_6_CORE_RATIO_IMPLEMENTATION] = 0; //Six-core Flag + DddtPreFlagHob->PresentFlag[BIOS_SHORT_TDP_IMPLEMENTATION] = 0; //Short TDP Flag + DddtPreFlagHob->PresentFlag[BIOS_EXTENDED_TDP_IMPLEMENTATION] = 0; //Extended TDP Flag + DddtPreFlagHob->PresentFlag[BIOS_SHORT_TDP_ENABLE_IMPLEMENTATION] = 0; //Short TDP Enable Flag + DddtPreFlagHob->PresentFlag[BIOS_RUNTIME_TURBO_OVERRIDE_IMPLEMENTATION] = 0; //Runtime Turbo Overwride Flag + DddtPreFlagHob->PresentFlag[BIOS_CPU_PLL_VOLTAGE_UNLOCK_ENABLE_IMPLEMENTATION] = 0; //Internal PLL overvoltage Enable Flag + DddtPreFlagHob->PresentFlag[BIOS_EXTENDED_TDP_ENABLE_IMPLEMENTATION] = 0; //Package TDP Enable Flag + DddtPreFlagHob->PresentFlag[BIOS_EXTENDED_TIME_WINDOW_IMPLEMENTATION] = 0; //Package TDP Time Window Flag + /* + DddtPreFlagHob->PresentFlag[BIOS_OVERCLOCKING_ENABLE_IMPLEMENTATION] = 0; //Overclocking Lock Flag + DddtPreFlagHob->PresentFlag[BIOS_CPU_VOLTAGE_IMPLEMENTATION] = 0; //Malibox: CPU Voltage Target Flag + DddtPreFlagHob->PresentFlag[BIOS_IA_CORE_VOLTAGE_MODE_IMPLEMENTATION] = 0; //Malibox: CPU Voltage Mode Flag + DddtPreFlagHob->PresentFlag[BIOS_CPU_VOLTAGE_OFFSET_IMPLEMENTATION] = 0; //Malibox: CPU Voltage Offset Flag + DddtPreFlagHob->PresentFlag[BIOS_RING_RATIO_IMPLEMENTATION] = 0; //Malibox: RING Ratio Flag + DddtPreFlagHob->PresentFlag[BIOS_RING_VOLTAGE_OVERRIDE_IMPLEMENTATION] = 0; //Malibox: RING Voltage Target Flag + DddtPreFlagHob->PresentFlag[BIOS_RING_VOLTAGE_MODE_IMPLEMENTATION] = 0; //Malibox: RING Voltage Mode Flag + DddtPreFlagHob->PresentFlag[BIOS_RING_VOLTAGE_OFFSET_IMPLEMENTATION] = 0; //Malibox: RING Voltage Offset Flag + DddtPreFlagHob->PresentFlag[BIOS_DYNAMIC_SVID_CONTROL_IMPLEMENTATION] = 0; //Malibox: SVID Control Flag + DddtPreFlagHob->PresentFlag[BIOS_SVID_VOLTAGE_OVERRIDE_IMPLEMENTATION] = 0; //Malibox: SVID Voltage Target Flag + DddtPreFlagHob->PresentFlag[BIOS_FIVR_FAULTS_IMPLEMENTATION] = 0; //Malibox: FIVR Faults Flag + DddtPreFlagHob->PresentFlag[BIOS_FIVR_EFFICIENCY_MANAGEMENT_IMPLEMENTATION] = 0; //Malibox: FIVR Efficiency Management Flag + */ + } + + if(!(isFullUnlockCpuSuuported())){ + DddtPreFlagHob->PresentFlag[BIOS_CPU_PLL_VOLTAGE_UNLOCK_ENABLE_IMPLEMENTATION] = 0; //Internal PLL overvoltage Enable Flag + } + + if(!(isBCLKRatioSuuported())){ + DddtPreFlagHob->PresentFlag[BIOS_PEG_DMI_RATIO_IMPLEMENTATION] = 0; // PEG/DMI ratio Enable Flag + } + + DddtPreFlagHob->PresentFlag[BIOS_TDC_VALUE_IMPLEMENTATION] = 0; //TDC Flag + DddtPreFlagHob->PresentFlag[BIOS_TDP_VALUE_IMPLEMENTATION] = 0; //TDP Flag + + OverclockConfigHob = (OVERCLOCKING_CONFIG_HOB*) FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &OverclockConfigHob))) { + if (guidcmp(&((EFI_HOB_GUID_TYPE*)OverclockConfigHob)->Name, &gAmiOcConfigHobGuid) == 0) { + break; + } + } + if(!EFI_ERROR(Status)){ + OverclockData = &OverclockConfigHob->OverclockData; + //Mailbox item + //IA core + if(!OverclockData->OCCap[IA].VoltageOverridesSupported){ + DddtPreFlagHob->PresentFlag[BIOS_IA_CORE_VOLTAGE_MODE_IMPLEMENTATION] = 0; + DddtPreFlagHob->PresentFlag[BIOS_CPU_VOLTAGE_IMPLEMENTATION] = 0; + } + if(!OverclockData->OCCap[IA].VoltageOffsetSupported) + DddtPreFlagHob->PresentFlag[BIOS_CPU_VOLTAGE_OFFSET_IMPLEMENTATION] = 0; + //RING + if(!OverclockData->OCCap[RING].RatioOcSupported) + DddtPreFlagHob->PresentFlag[BIOS_RING_RATIO_IMPLEMENTATION] = 0; + if(!OverclockData->OCCap[RING].VoltageOverridesSupported){ + DddtPreFlagHob->PresentFlag[BIOS_RING_VOLTAGE_MODE_IMPLEMENTATION] = 0; + DddtPreFlagHob->PresentFlag[BIOS_RING_VOLTAGE_OVERRIDE_IMPLEMENTATION] = 0; + } + if(!OverclockData->OCCap[RING].VoltageOffsetSupported) + DddtPreFlagHob->PresentFlag[BIOS_RING_VOLTAGE_OFFSET_IMPLEMENTATION] = 0; + } + } + + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &PerfTunePpiGuid, + 0, + NULL, + &PerfTunePpi + ); + if(EFI_ERROR(Status)) return Status; + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &WdtPpiGuid, + 0, + NULL, + &WdtPpi + ); + if(EFI_ERROR(Status)) return Status; + + Status = PerfTunePpi->GetSettingData(PeiServices, &SettingData); + if(EFI_ERROR(Status)) return Status; + + if(SettingData.RuntimeTurboEanble == 1 && NumOcBins != 0) + DddtPreFlagHob->PresentFlag[BIOS_RUNTIME_TURBO_OVERRIDE_IMPLEMENTATION] = 1; + else + DddtPreFlagHob->PresentFlag[BIOS_RUNTIME_TURBO_OVERRIDE_IMPLEMENTATION] = 0; + + return Status; + +} +#endif + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// Procedure: CpuPeiMiscFuncs +// +// Description: +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// IN EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariablePpi +// IN EFI_BOOT_MODE BootMode +// +// Output: +// EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CpuPeiMiscFuncs ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariablePpi, + IN EFI_BOOT_MODE BootMode +) +{ + +#if PERF_TUNE_SUPPORT == 1 + EFI_STATUS Status; + + Status = CpuPeiIntelXtuDataInit(PeiServices, ReadOnlyVariablePpi, BootMode); +#endif + + return; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + diff --git a/Core/CPU/CpuSmbios.c b/Core/CPU/CpuSmbios.c new file mode 100644 index 0000000..aa0c42a --- /dev/null +++ b/Core/CPU/CpuSmbios.c @@ -0,0 +1,734 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuSmbios.c 6 6/16/14 4:52a Davidhsieh $ +// +// $Revision: 6 $ +// +// $Date: 6/16/14 4:52a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuSmbios.c $ +// +// 6 6/16/14 4:52a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Support the cache size which bigger than 0x8000MB +// [Files] AmiCpuInfo.h, CpuSmbios.c +// +// 5 8/14/13 4:53a Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Smbios CpuMaxSpeed value is from Cpu when token +// SMBIOS_TYPE_4_MAX_SPEED is zero +// +// 4 2/27/13 5:00a Crystallee +// [TAG] EIP115822 +// [Category] Improvement +// [Description] Add SMBIOS type7 information for L4 cache if CPU +// supported +// And create a token to control this. +// +// 3 3/21/12 4:33a Davidhsieh +// +// 2 3/20/12 3:23a Davidhsieh +// Create SMBIOS type4 and type7 in AMI CPU module part +// +// 1 2/07/12 3:58a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuSmbios.c +// +// Description: +// Installs TYPE 4 and TYPE 7 SMBIOS tables. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + + +#include <Efi.h> +#include <AmiLib.h> +#include <Protocol\SmBios.h> +#include <Protocol\AmiCpuInfo.h> +#include <Protocol\AmiCpuInfo2.h> +#include <AmiCspLibInc.h> +#include <Token.h> +#include "Cpu.h" +#include "CpuDxe.h" + +extern AMI_CPU_INFO_PROTOCOL gAmiCpuInfoProtocol; +extern PRIVATE_AMI_CPU_INFO_2_PROTOCOL *gPrivateAmiCpuInfo2; +AMI_CPU_INFO *gGetCpuInfo = NULL; +EFI_SMBIOS_PROTOCOL *gSmbiosProtocol; + +UINT32 GetCpuNumByPkgCoreThrd( + IN UINT32 Package, + IN UINT32 Core, + IN UINT32 Thread +); + +UINT32 gType4Instance = 1; +UINT32 gType7Instance = 1; + +EFI_GUID gEfiSmbiosProtocolGuid = EFI_SMBIOS_PROTOCOL_GUID; + +EFI_EVENT gSmbiosEvent; +VOID *gSmbiosRegistration = 0; + +UINT32 GetBoardSocketNumber(IN UINT32 ApicId); +UINT8 GetCacheSharedThreads(IN UINT8 Level); + +CACHE_DESCRIPTOR_INFO *gCacheDescInfo; +UINT8 gCacheTypeTable[] = {4, 3, 0, 5}; +UINT8 gAssociativityTable[] = {2, 6 ,4 ,1 ,5 ,1 ,1 ,1 ,7 ,1 ,1 ,1 ,9 ,1 ,1, 1, 8, 1, 1, 1, 0xe, + 1, 1, 1, 0xa, 1, 1, 1, 1, 1, 1, 1, 0xb +}; + +typedef struct { + UINT32 Size; + UINT8 Type; + UINT8 Assoc; +} CACHE_INFO; + +#if !CPU_CACHE_L4_DISPLAY_IN_SMBIOS +CACHE_INFO gCacheInfo[3]; //[0] = L1, [1] = L2, [2] = L3 +#else +CACHE_INFO gCacheInfo[4]; //[0] = L1, [1] = L2, [2] = L3, [3] = L4 +#endif + +#define SMBIOS_CACHE_ECC_PARITY 4 +#define SMBIOS_CACHE_ECC_SINGLE_BIT 5 + +#define SMBIOS_MAX_NUM_SOCKETS 8 + +CHAR8 *gSocketDesgination[8] = { + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_0), + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_1), + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_2), + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_3), + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_4), + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_5), + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_6), + CONVERT_TO_STRING(SMBIOS_TYPE_4_SOCKET_DESIGINTATION_SOCKET_7) +}; + + +typedef struct { + //Private Data + UINT8 *StrBuf; + INT32 StrBufSize; + INT32 StrBufAvail; + UINT8 Tok; +} SMBIOS_TABLE_STR_BUFFER; + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: EstablishStringBuffer +// +// Description: Initialize string buffer variables +// +// Input: +// IN VOID *Buffer - Buffer address +// IN UINT32 Size - Buffer Size +// OUT SMBIOS_TABLE_STR_BUFFER **StrBuffer - String Buffer structure +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID EstablishStringBuffer( + IN VOID *Buffer, + IN UINT32 Size, + OUT SMBIOS_TABLE_STR_BUFFER **StrBuffer +) +{ + EFI_STATUS Status; + SMBIOS_TABLE_STR_BUFFER *Buf; + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(SMBIOS_TABLE_STR_BUFFER), &Buf); + ASSERT_EFI_ERROR(Status); + + Buf->StrBuf = Buffer; + Buf->StrBufSize = Size; + Buf->StrBufAvail = Size; + Buf->Tok = 0; + + *StrBuffer = Buf; + +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: AddStrGetTok +// +// Description: Add string to buffer and return token value. +// +// Input: +// IN SMBIOS_TABLE_STR_BUFFER *StrBuffer - String Buffer structure +// IN UINT8 *Str - Pointer to string. +// +// Output: UINT8 - token of string +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 AddStrGetTok( + IN SMBIOS_TABLE_STR_BUFFER *StrBuffer, + IN UINT8 *Str +) +{ + INT32 Len = (INT32)Strlen(Str); + + if (Len == 0) return 0; //No string + + //For string buffer, 2 bytes at end reserved for double 0, so that is why + //gStrBufAvail - 2 + if (Len > (StrBuffer->StrBufAvail - 2)) return 0; //Not enough space left. + + Strcpy(StrBuffer->StrBuf, Str); + StrBuffer->StrBuf += Len + 1; + StrBuffer->StrBufAvail -= Len + 1; + ++StrBuffer->Tok; + return StrBuffer->Tok; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetBufferSizeUsed +// +// Description: Get amount storage space used by strings. +// +// Input: +// IN SMBIOS_TABLE_STR_BUFFER *StrBuffer - String Buffer structure +// +// Output: UINT32 - Size needed for strings. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 GetBufferSizeUsed(IN SMBIOS_TABLE_STR_BUFFER *StrBuffer) +{ + return StrBuffer->StrBufSize - StrBuffer->StrBufAvail; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: RemoveStringBuffer +// +// Description: Remove String Buffer structure. +// +// Input: +// IN SMBIOS_TABLE_STR_BUFFER *StrBuffer - String Buffer structure +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID RemoveStringBuffer(IN SMBIOS_TABLE_STR_BUFFER *StrBuffer) +{ + pBS->FreePool(StrBuffer); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: GetMaxSpeedFromBrandString +// +// Description: Get the max speed from the brand string. +// +// Input: +// IN CHAR8 *CpuBrandString - Pointer to CPU brand string. +// +// Output: UINT32 - frequency found in MHz. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 GetMaxSpeedFromBrandString(IN CHAR8 *CpuBrandString) +{ + UINT32 i; + UINT8 CharCount; + BOOLEAN TransToMHz = FALSE; + BOOLEAN FreqStringFound = FALSE; + CHAR8 FrequencyString[] = "0000"; + + while (*CpuBrandString != 0) { + if (*CpuBrandString == 'G' && *(CpuBrandString + 1) == 'H' && *(CpuBrandString + 2) == 'z') { + FreqStringFound = TRUE; + TransToMHz = TRUE; + break; + } else if (*CpuBrandString == 'M' && *(CpuBrandString+1) == 'H' && *(CpuBrandString + 2) == 'z') { + FreqStringFound = TRUE; + break; + } else ++CpuBrandString; + } + + --CpuBrandString; //first numeric char + + //search numeric char + CharCount = 0; + for(i = 0 ; i < 4; ++i) { + if (*CpuBrandString >= '0' && *CpuBrandString <= '9') { + --CpuBrandString; + ++CharCount; + } else if (*CpuBrandString == '.') { + --CpuBrandString; + ++CharCount; + } else break; + } + + ++CpuBrandString; //first numeric char + + if (FreqStringFound && CharCount > 0) { + for(i = 0; i < CharCount; ++i) { + if (TransToMHz && *CpuBrandString == '.') CpuBrandString++; + + FrequencyString[i] = *CpuBrandString; + ++CpuBrandString; + } + if (TransToMHz) FrequencyString[3] = '0'; + } else FreqStringFound = FALSE; + + return FreqStringFound ? Atoi(FrequencyString) : 0; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CollectCacheInfo +// +// Description: Store cache information in variables. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CollectCacheInfo() +{ + INT32 i; + UINT8 Type; + UINT8 Assoc; + UINT32 NumCores = NumSupportedCpuCores(); + + MemSet(gCacheInfo, sizeof(gCacheInfo), 0); + + gCacheDescInfo = gGetCpuInfo->CacheInfo; + for(i = 0; gCacheDescInfo[i].Desc; ++i) { // End of descriptors, Desc = 0. + UINT8 Level = gGetCpuInfo->CacheInfo[i].Level; + switch(Level) { +#if !CPU_CACHE_L4_DISPLAY_IN_SMBIOS + case 1: case 2: case 3: +#else + case 1: case 2: case 3: case 4: +#endif + Type = gCacheTypeTable[gCacheDescInfo[i].Type]; + + if (gCacheDescInfo[i].Associativity < sizeof(gAssociativityTable)/sizeof(UINT8)) + Assoc = gAssociativityTable[gCacheDescInfo[i].Associativity]; + else Assoc = 1; + + //If multiple caches of same level, add sizes. + gCacheInfo[Level - 1].Size += gCacheDescInfo[i].Size; + + //If multiple caches of same level have different types report as other. + if (gCacheInfo[Level - 1].Type == 0) gCacheInfo[Level - 1].Type = Type; + else if (gCacheInfo[Level - 1].Type != Type) gCacheInfo[Level - 1].Type = 1; + + if (gCacheInfo[Level - 1].Assoc == 0) gCacheInfo[Level - 1].Assoc = Assoc; + else if (gCacheInfo[Level - 1].Assoc != Assoc) gCacheInfo[Level - 1].Assoc = 1; + } + } + + if (GetCacheSharedThreads(1) <= 2) gCacheInfo[0].Size *= NumCores; + if (GetCacheSharedThreads(2) <= 2) gCacheInfo[1].Size *= NumCores; + if (GetCacheSharedThreads(3) <= 2) gCacheInfo[2].Size *= NumCores; +#if CPU_CACHE_L4_DISPLAY_IN_SMBIOS + if (GetCacheSharedThreads(4) <= 2) gCacheInfo[3].Size *= NumCores; +#endif +} + +#define TYPE7_STRING_BUFFER_SIZE 100 +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CreateSmbiosTable7 +// +// Description: Create SMBIOS Table 7 +// +// Input: IN UINT8 CacheLevel (L1, L2, L3) +// +// Output: UINT16 - Handle for table. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 CreateSmbiosTable7(IN UINT8 CacheLevel) +{ + SMBIOS_CACHE_INFO *CacheInfo; + UINT16 Handle; + EFI_STATUS Status; + UINT32 Type7ActStrBufSize; + SMBIOS_TABLE_STR_BUFFER *StrBuffer; + + if (gCacheInfo[CacheLevel-1].Size == 0) return 0xffff; + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(SMBIOS_CACHE_INFO) + TYPE7_STRING_BUFFER_SIZE, &CacheInfo); + ASSERT_EFI_ERROR(Status); + + EstablishStringBuffer((UINT8*)CacheInfo + sizeof(SMBIOS_CACHE_INFO), TYPE7_STRING_BUFFER_SIZE, &StrBuffer); + + Handle = gSmbiosProtocol->SmbiosGetFreeHandle(); + + CacheInfo->StructureType.Type = 7; + CacheInfo->StructureType.Length = 0x13; + CacheInfo->StructureType.Handle = Handle; + CacheInfo->SocketDesignation = 0; + + if(gCacheInfo[CacheLevel-1].Size > 0x07FFF){ + CacheInfo->MaxCacheSize = 0x8000 | (gCacheInfo[CacheLevel-1].Size / 64); + CacheInfo->InstalledSize = 0x8000 | (gCacheInfo[CacheLevel-1].Size / 64); + } else { + CacheInfo->MaxCacheSize = gCacheInfo[CacheLevel-1].Size; + CacheInfo->InstalledSize = gCacheInfo[CacheLevel-1].Size; + } + + CacheInfo->SystemCacheType = gCacheInfo[CacheLevel-1].Type; + CacheInfo->Associativity = gCacheInfo[CacheLevel-1].Assoc; + + switch (CacheLevel) { + case 1: + CacheInfo->CacheConfig = 0x180; +#ifdef SMBIOS_TYPE_7_L1_SOCKET_DESIGNATION + CacheInfo->SocketDesignation = AddStrGetTok(StrBuffer, CONVERT_TO_STRING(SMBIOS_TYPE_7_L1_SOCKET_DESIGNATION)); +#endif + break; + case 2: + CacheInfo->CacheConfig = 0x181; +#ifdef SMBIOS_TYPE_7_L2_SOCKET_DESIGNATION + CacheInfo->SocketDesignation = AddStrGetTok(StrBuffer, CONVERT_TO_STRING(SMBIOS_TYPE_7_L2_SOCKET_DESIGNATION)); +#endif + break; + case 3: + CacheInfo->CacheConfig = 0x182; +#ifdef SMBIOS_TYPE_7_L3_SOCKET_DESIGNATION + CacheInfo->SocketDesignation = AddStrGetTok(StrBuffer, CONVERT_TO_STRING(SMBIOS_TYPE_7_L3_SOCKET_DESIGNATION)); +#endif + break; +#if CPU_CACHE_L4_DISPLAY_IN_SMBIOS + case 4: + CacheInfo->CacheConfig = 0x183; +#ifdef SMBIOS_TYPE_7_L4_SOCKET_DESIGNATION + CacheInfo->SocketDesignation = AddStrGetTok(StrBuffer, CONVERT_TO_STRING(SMBIOS_TYPE_7_L4_SOCKET_DESIGNATION)); +#endif + break; +#endif + } + + CacheInfo->SupportSRAM = 2; + CacheInfo->CurrentSRAM = 2; + CacheInfo->CacheSpeed = 0; + CacheInfo->ErrorCorrectionType = 0x05; //ECC + Type7ActStrBufSize = GetBufferSizeUsed(StrBuffer); + + if (Type7ActStrBufSize == 0) { + *(UINT16*)(CacheInfo + 1) = 0; //Double NULL. + } else { + *((UINT8*)(CacheInfo + 1) + Type7ActStrBufSize) = 0; //End structure of NULL. + } + + Status = gSmbiosProtocol->SmbiosAddStrucByHandle( + Handle, + (VOID*)CacheInfo, + (UINT16)(sizeof(SMBIOS_CACHE_INFO) + (Type7ActStrBufSize == 0 ? 2 : Type7ActStrBufSize + 1)) + ); + + pBS->FreePool(CacheInfo); + RemoveStringBuffer(StrBuffer); + + return !EFI_ERROR(Status) ? Handle : 0xffff; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: AutodetectFamily +// +// Description: Return family type from Brand String. +// +// Input: IN CHAR8 *BrandString +// +// Output: UINT8 - Family +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 AutodetectFamily(IN CHAR8 *BrandString) +{ + CHAR8 *p = BrandString; + + while(*p) { + if (MemCmp(p, "Xeon", 4) == 0) return 0xb3; + if (MemCmp(p, "i7", 2) == 0) return 0xc6; + if (MemCmp(p, "i5", 2) == 0) return 0xcd; + if (MemCmp(p, "i3", 2) == 0) return 0xce; + if (MemCmp(p, "Pentiu", 6) == 0) return 0x0b; + if (MemCmp(p, "Celero", 6) == 0) return 0x0f; + ++p; + } + + return 0xcd; //default as i5 family +} + +#define TYPE4_STRING_BUFFER_SIZE 200 + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CreateSmbiosTable4 +// +// Description: Create SMBIOS Table 4 +// +// Input: IN UINT32 PhysSocket +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CreateSmbiosTable4(IN UINT32 PhysSocket) +{ + SMBIOS_PROCESSOR_INFO * ProcInfo; + EFI_STATUS Status; + UINT32 ActStrBufSize; + UINT32 MaxFreqBrandStr; + SMBIOS_TABLE_STR_BUFFER *StrBuffer; + SMBIOS_STRUCTURE_HEADER *Hdr; + UINT16 Size; + BOOLEAN HandleExists = FALSE; + + Status = pBS->AllocatePool( + EfiBootServicesData, sizeof(SMBIOS_PROCESSOR_INFO) + TYPE4_STRING_BUFFER_SIZE, &ProcInfo + ); + + EstablishStringBuffer((UINT8*)ProcInfo + sizeof(SMBIOS_PROCESSOR_INFO), TYPE4_STRING_BUFFER_SIZE, &StrBuffer); + + ProcInfo->StructureType.Type = 4; + ProcInfo->StructureType.Length = 0x2a; + ProcInfo->StructureType.Handle = 0xffff; //To be updated by SMBIOS driver. + + if (PhysSocket >= SMBIOS_MAX_NUM_SOCKETS) ProcInfo->SocketDesignation = 0; + else ProcInfo->SocketDesignation = AddStrGetTok(StrBuffer, gSocketDesgination[PhysSocket]); + + ProcInfo->ProcessotType = 3; //Central processor + + if (SMBIOS_TYPE_4_PROC_FAMILY != 0) ProcInfo->Family = SMBIOS_TYPE_4_PROC_FAMILY; + else ProcInfo->Family = AutodetectFamily(gGetCpuInfo->BrandString); + + ProcInfo->ProcessorManufacturer = AddStrGetTok(StrBuffer, "Intel"); + + ProcInfo->ProcessorID_1 = (UINT32)(gGetCpuInfo->Version); + ProcInfo->ProcessorID_2 = (UINT32)(gGetCpuInfo->Features); + ProcInfo->ProcessorVersion = AddStrGetTok(StrBuffer, gGetCpuInfo->BrandString); + ProcInfo->Voltage = (UINT8)(12) + BIT7; // 1.2 volts + //ProcInfo->Voltage = BIT7; // 1.2 volts + ProcInfo->MaxSpeed = SMBIOS_TYPE_4_MAX_SPEED; + + MaxFreqBrandStr = GetMaxSpeedFromBrandString(gGetCpuInfo->BrandString); + if (MaxFreqBrandStr) ProcInfo->CurrentSpeed = MaxFreqBrandStr; + else ProcInfo->CurrentSpeed = gGetCpuInfo->IntendedFreq; + +#if !SMBIOS_TYPE_4_MAX_SPEED + ProcInfo->MaxSpeed = ProcInfo->CurrentSpeed; +#endif + ProcInfo->ExtClockFreq = (UINT16)(gGetCpuInfo->FSBFreq); + ProcInfo->Status = 0x41; //Populated and enabled. + ProcInfo->Upgrade = SMBIOS_TYPE_4_PROC_UPGRADE; + ProcInfo->SerialNumber = 0; + +#ifdef SMBIOS_TYPE_4_ASSET_TAG + ProcInfo->AssetTag = AddStrGetTok(StrBuffer, CONVERT_TO_STRING(SMBIOS_TYPE_4_ASSET_TAG)); +#else + ProcInfo->AssetTag = 0; +#endif +#ifdef SMBIOS_TYPE_4_PART_NUMBER + ProcInfo->PartNumber = AddStrGetTok(StrBuffer, CONVERT_TO_STRING(SMBIOS_TYPE_4_PART_NUMBER)); +#else + ProcInfo->PartNumber = 0; +#endif + ProcInfo->CoreCount = NumSupportedCpuCores(); //This must be the same across sockets. + ProcInfo->CoreEnabled = gGetCpuInfo->NumCores; + ProcInfo->ThreadCount = NumSupportedCpuCores() * NumSupportedThreadsPerCore(); //This must be the same across sockets. + ProcInfo->ProcessorChar = 4; //X64 Support + ProcInfo->Family2 = ProcInfo->Family; + + ActStrBufSize = GetBufferSizeUsed(StrBuffer); + if (ActStrBufSize == 0) { + *(UINT16*)(ProcInfo + 1) = 0; //Double NULL. + } else { + *((UINT8*)(ProcInfo + 1) + ActStrBufSize) = 0; //End structure of NULL. + } + + Status = gSmbiosProtocol->SmbiosAddStructure( + (VOID*)ProcInfo, + (UINT16)(sizeof(SMBIOS_PROCESSOR_INFO) + (ActStrBufSize == 0 ? 2 : ActStrBufSize + 1)) + ); + + ASSERT_EFI_ERROR(Status); + + Status = gSmbiosProtocol->SmbiosReadStrucByType(4, 1, (UINT8**)&Hdr, &Size); + ProcInfo->StructureType.Handle = Hdr->Handle; + ProcInfo->L1CacheHandle = CreateSmbiosTable7(1); + ProcInfo->L2CacheHandle = CreateSmbiosTable7(2); + ProcInfo->L3CacheHandle = CreateSmbiosTable7(3); +#if CPU_CACHE_L4_DISPLAY_IN_SMBIOS + CreateSmbiosTable7(4); +#endif + Status = gSmbiosProtocol->SmbiosWriteStructure( + ProcInfo->StructureType.Handle, + (VOID*)ProcInfo, + (UINT16)(sizeof(SMBIOS_PROCESSOR_INFO) + (ActStrBufSize == 0 ? 2 : ActStrBufSize + 1)) + ); + + pBS->FreePool(ProcInfo); + RemoveStringBuffer(StrBuffer); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CreateCpuSmbiosTables +// +// Description: Create CPU SMBIOS Tables 4 and 7. +// +// Input: +// IN EFI_EVENT Event - Not used +// IN VOID *Context - Note Used +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CreateCpuSmbiosTables(IN EFI_EVENT Event, IN VOID *Context) +{ + EFI_STATUS Status; + UINT8 i; + UINT32 NumSocketsPop = NumberOfCpuSocketsPopulated(); + UINT32 SocketPopBitmap = 0; + SMBIOS_STRUCTURE_HEADER *Hdr; + UINT16 Size; + UINT32 Cpu; + + ASSERT(NUMBER_CPU_SOCKETS <= SMBIOS_MAX_NUM_SOCKETS); + + Status = pBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, &gSmbiosProtocol); + if (EFI_ERROR(Status)) return; //First call, error, because protocol not installed yet. + +//Delete existing CPU SBIOS structures type 4 and type 7. + while (!EFI_ERROR(gSmbiosProtocol->SmbiosReadStrucByType(4, 1, (UINT8**)&Hdr, &Size))) { + gSmbiosProtocol->SmbiosDeleteStructure(Hdr->Handle); + pBS->FreePool(Hdr); + } + + while (!EFI_ERROR(gSmbiosProtocol->SmbiosReadStrucByType(7, 1, (UINT8**)&Hdr, &Size))) { + gSmbiosProtocol->SmbiosDeleteStructure(Hdr->Handle); + pBS->FreePool(Hdr); + } + +//Add CPU SMBIOS structures for populated sockets. + Cpu = 0; + for (i = 0; i < NumSocketsPop; ++i) { + UINT32 ApicId; + UINT32 PhysSocket; + + Status = gAmiCpuInfoProtocol.GetCpuInfo(&gAmiCpuInfoProtocol, Cpu, &gGetCpuInfo); + ASSERT_EFI_ERROR(Status); + + CollectCacheInfo(); //For one thread. + + Status = ((AMI_CPU_INFO_2_PROTOCOL*)gPrivateAmiCpuInfo2)->GetApicInfo( + (AMI_CPU_INFO_2_PROTOCOL*)gPrivateAmiCpuInfo2, i, 0, 0, &ApicId, NULL + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) ApicId = 0; + PhysSocket = GetBoardSocketNumber(ApicId); + + CreateSmbiosTable4(PhysSocket); + if (PhysSocket < SMBIOS_MAX_NUM_SOCKETS) SocketPopBitmap |= 1 << PhysSocket; + + //Update Cpu from gGetCpuInfo + Cpu += gGetCpuInfo->NumCores * (gGetCpuInfo->NumHts == 0 ? 1 : 2); + } +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CpuSmbios +// +// Description: Create CPU SMBIOS Tables. Installs notification on SMBIOS handlers. +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CpuSmbios() +{ + EFI_STATUS Status; + + Status = RegisterProtocolCallback( + &gEfiSmbiosProtocolGuid, + CreateCpuSmbiosTables, + NULL, + &gSmbiosEvent, + &gSmbiosRegistration + ); + ASSERT_EFI_ERROR(Status); + + CreateCpuSmbiosTables(gSmbiosEvent, NULL); +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/CpuSpSmi.DXS b/Core/CPU/CpuSpSmi.DXS new file mode 100644 index 0000000..9362072 --- /dev/null +++ b/Core/CPU/CpuSpSmi.DXS @@ -0,0 +1,59 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.DXS 1 2/07/12 4:00a Davidhsieh $ +// +// $Revision: 1 $ +// +// $Date: 2/07/12 4:00a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.DXS $ +// +// 1 2/07/12 4:00a Davidhsieh +// +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuSpSmi.DXS +// +// Description: Dependency file for the CpuSp SMI +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "CpuSpSmi.h" + +DEPENDENCY_START + EFI_SMM_SW_DISPATCH_PROTOCOL_GUID +DEPENDENCY_END + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CPU/CpuSpSmi.c b/Core/CPU/CpuSpSmi.c new file mode 100644 index 0000000..bd4469d --- /dev/null +++ b/Core/CPU/CpuSpSmi.c @@ -0,0 +1,568 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.c 8 5/24/15 11:37p Davidhsieh $ +// +// $Revision: 8 $ +// +// $Date: 5/24/15 11:37p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.c $ +// +// 8 5/24/15 11:37p Davidhsieh +// [TAG] EIP215675 +// [Category] New Feature +// [Description] Smm Access Check feautre support +// [Files] Cpu.sdl, CpuDxe.c, CpuSpSmi.sdl, CpuSpsmi.c +// +// 7 10/08/13 3:10a Crystallee +// [TAG] EIP137873 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] CPU Security Configuration(MSR 4E0[0]) will be changed +// after S3 resume +// [RootCause] Didn't restore the Cpu MSR 4e0 while S3 resume. +// [Solution] Restore the Cpu MSR 0x4E0 while S3 resume. +// +// 6 1/24/13 10:45p Davidhsieh +// [TAG] EIP112381 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] TBoot S3 resume fail +// [RootCause] MSR 0x2e7 is not restored +// [Solution] Save and restore MSR 0x2e7 for S3 +// +// 5 12/18/12 9:23p Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Check CPU before lock SMM_FEATURE_CONTROL MSR +// +// 4 12/09/12 10:35p Davidhsieh +// [TAG] None +// [Category] Improvement +// [Description] Lock SMM_FEATURE_CONTROL MSR +// +// 3 10/04/12 9:20a Davidhsieh +// Change the procedure of configuring MTRR +// +// 2 7/10/12 2:51a Davidhsieh +// [TAG] EIP93180 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] The "Event Kernel-Power 137" error event log shows while +// resumed from S3 +// [RootCause] The fixed and variable Mtrrs of BSP are not restored +// [Solution] Restore BPS's mtrss +// +// 1 2/07/12 4:00a Davidhsieh +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: CpuSpSmi.C +// +// Description: Provide functions to CPU specific SMI +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "CpuSpSmi.h" + +UINT64 ReadMsr (UINT32 Msr); +VOID WriteMsr(UINT32 Msr, UINT64 Value); + +UINTN MpMtrrSynchUpEntry (VOID); +VOID MpMtrrSynchUpExit (UINTN Cr4); + +EFI_GUID SwDispatchProtocolGuid = EFI_SMM_SW_DISPATCH_PROTOCOL_GUID; + +EFI_SMM_SYSTEM_TABLE *mSmst; +EFI_SMM_BASE_PROTOCOL *pSmmBase; +EFI_SMM_SW_DISPATCH_PROTOCOL *gSwDispatch; + +// +// MSR table for S3 resume +// +EFI_MSR_VALUES mFixedMtrrValues[] = { + { MTRR_FIX_64K_00000, 0 }, + { MTRR_FIX_16K_80000, 0 }, + { MTRR_FIX_16K_A0000, 0 }, + { MTRR_FIX_4K_C0000, 0 }, + { MTRR_FIX_4K_C8000, 0 }, + { MTRR_FIX_4K_D0000, 0 }, + { MTRR_FIX_4K_D8000, 0 }, + { MTRR_FIX_4K_E0000, 0 }, + { MTRR_FIX_4K_E8000, 0 }, + { MTRR_FIX_4K_F0000, 0 }, + { MTRR_FIX_4K_F8000, 0 }, + { 0, 0 } +}; + +EFI_MSR_VALUES mVariableMtrrValues[] = { + { MTRR_PHYS_BASE_0, 0 }, + { MTRR_PHYS_MASK_0, 0 }, + { MTRR_PHYS_BASE_1, 0 }, + { MTRR_PHYS_MASK_1, 0 }, + { MTRR_PHYS_BASE_2, 0 }, + { MTRR_PHYS_MASK_2, 0 }, + { MTRR_PHYS_BASE_3, 0 }, + { MTRR_PHYS_MASK_3, 0 }, + { MTRR_PHYS_BASE_4, 0 }, + { MTRR_PHYS_MASK_4, 0 }, + { MTRR_PHYS_BASE_5, 0 }, + { MTRR_PHYS_MASK_5, 0 }, + { MTRR_PHYS_BASE_6, 0 }, + { MTRR_PHYS_MASK_6, 0 }, + { MTRR_PHYS_BASE_7, 0 }, + { MTRR_PHYS_MASK_7, 0 }, + { MTRR_PHYS_BASE_8, 0 }, + { MTRR_PHYS_MASK_8, 0 }, + { MTRR_PHYS_BASE_9, 0 }, + { MTRR_PHYS_MASK_9, 0 } +}; + +#define MiscMsrCount 1 + +EFI_MSR_VALUES mMiscMsrValues[] = { + { 0x2e7, 0 } +}; + +EFI_MSR_VALUES mSmmFeatureCtrl = { 0x4e0, 0}; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SaveCpuMsr +// +// Description: This function saves the CPU MSRs for S3 resume usage. +// +// Input: DispatchHandle Handle to the Dispatcher +// DispatchContext SW SMM dispatcher context +// +// Output: None +// +// Modified: +// +// Referrals: +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +SaveCpuMsr( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + UINT32 i; + + if (Shr64(ReadMsr(0x17d),57) & 0x03){ + if (!(ReadMsr(mSmmFeatureCtrl.Index) && 0x01)) + WriteMsr(mSmmFeatureCtrl.Index, ReadMsr(mSmmFeatureCtrl.Index) | 0x01); + mSmmFeatureCtrl.Value = ReadMsr(mSmmFeatureCtrl.Index); + } + + //Save Fixed MTRR + for(i=0; i < NUM_OF_FIXED_MTRRS; i++) + { + mFixedMtrrValues[i].Value = ReadMsr(mFixedMtrrValues[i].Index); + } + + //Save variable MTRR + for (i = 0; i < ((UINT8)(ReadMsr(MSR_IA32_MTRR_CAP) & VCNT_MASK)); i++) + { + mVariableMtrrValues[i * 2].Value = ReadMsr(mVariableMtrrValues[i * 2].Index); + mVariableMtrrValues[i * 2 + 1].Value = ReadMsr(mVariableMtrrValues[i * 2 + 1].Index); + } + + mMiscMsrValues[0].Value = ReadMsr(mMiscMsrValues[0].Index); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RestoreMsrOnCpu +// +// Description: This function restores the CPU MSRs during S3 resume. +// +// Input: None +// +// Output: None +// +// Modified: +// +// Referrals: +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +RestoreMsrOnCpu(IN VOID *data) +{ + UINT32 i; + UINTN Cr4; + + Cr4 = MpMtrrSynchUpEntry(); + + //Restore Fixed MTRR + for(i=0; i < NUM_OF_FIXED_MTRRS; i++) + { + WriteMsr(mFixedMtrrValues[i].Index, mFixedMtrrValues[i].Value ); + } + + //Restore variable MTRR + for (i = 0; i < ((UINT8)(ReadMsr(MSR_IA32_MTRR_CAP) & VCNT_MASK)); i++) + { + WriteMsr(mVariableMtrrValues[i * 2].Index, mVariableMtrrValues[i * 2].Value ); + WriteMsr(mVariableMtrrValues[i * 2 + 1].Index, mVariableMtrrValues[i * 2 + 1].Value ); + } + + MpMtrrSynchUpExit (Cr4); + + WriteMsr(mMiscMsrValues[0].Index, mMiscMsrValues[0].Value); + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RestoreCpuMsr +// +// Description: This function restores the CPU MSRs during S3 resume. +// +// Input: DispatchHandle Handle to the Dispatcher +// DispatchContext SW SMM dispatcher context +// +// Output: None +// +// Modified: +// +// Referrals: +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +RestoreCpuMsr( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + UINT32 i; + UINTN Cr4; + + if (Shr64(ReadMsr(0x17d),57) & 0x03){ + if (!(ReadMsr(mSmmFeatureCtrl.Index) && 0x01)){ + WriteMsr(mSmmFeatureCtrl.Index, (mSmmFeatureCtrl.Value & ~0x01)); + WriteMsr(mSmmFeatureCtrl.Index, ReadMsr(mSmmFeatureCtrl.Index) | 0x01); + } + } + + for (i = 0; i < pSmst->NumberOfCpus; ++i) { + pSmst->SmmStartupThisAp(RestoreMsrOnCpu, i, NULL); + } + + Cr4 = MpMtrrSynchUpEntry(); + RestoreMsrOnCpu(NULL); + MpMtrrSynchUpExit (Cr4); +} + +#define SMRAM_CPU_DATA_VARIABLE_GUID \ + { \ + 0x429501d9, 0xe447, 0x40f4, 0x86, 0x7b, 0x75, 0xc9, 0x3a, 0x1d, 0xb5, 0x4e \ + } + +#define SMRAM_CPU_DATA_VARIABLE L"SmramCpuDataVar" + +#define SMM_FROM_CPU_DRIVER_SAVE_INFO 0x81 + +EFI_GUID mSmramCpuDataVariableGuid = SMRAM_CPU_DATA_VARIABLE_GUID; +BOOLEAN mLocked = FALSE; + +/** + Dispatch function for a Software SMI handler. + + @param DispatchHandle The handle of this dispatch function. + @param DispatchContext The pointer to the dispatch function's context. + The SwSmiInputValue field is filled in + by the software dispatch driver prior to + invoking this dispatch function. + The dispatch function will only be called + for input values for which it is registered. + + @return None + +**/ +VOID +EFIAPI +SmramSaveInfoHandler ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +/** + +@brief + + Dispatch function for a Software SMI handler + + @param[in] DispatchHandle - The handle of this dispatch function. + @param[in] DispatchContext - The pointer to the dispatch function's context. + + +**/ +{ + EFI_STATUS Status; + UINT64 VarData[3]; + UINTN VarSize; + + if (!mLocked && IoRead8 (SW_SMI_IO_ADDRESS+1) == SMM_FROM_CPU_DRIVER_SAVE_INFO) { + VarSize = sizeof (VarData); + Status = pRS->GetVariable ( + SMRAM_CPU_DATA_VARIABLE, + &mSmramCpuDataVariableGuid, + NULL, + &VarSize, + VarData + ); + if (!EFI_ERROR (Status) && VarSize == sizeof (VarData)) { + MemCpy ( + (VOID *) (UINTN) (VarData[0]), + (VOID *) (UINTN) (VarData[1]), + (UINTN) (VarData[2]) + ); + } + + mLocked = TRUE; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuSmmFeatureEn +// +// Description: +// +// Input: DispatchHandle Handle to the Dispatcher +// DispatchContext SW SMM dispatcher context +// +// Output: None +// +// Modified: +// +// Referrals: +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CpuSmmFeatureEn( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + + UINT64 MsrData; + + if (Shr64(ReadMsr(0x17d),58) & 0x01){ + if (!(ReadMsr(0x4e0) && 0x01)){ + MsrData = ReadMsr(0x4e0); + MsrData |= 0x4; + WriteMsr(0x4e0, MsrData); + } + } +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InSmmFunction +// +// Description: Called from InstallSmiHandler +// +// Input: +// +// +// Output: None +// +// Modified: +// +// Referrals: +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS InSmmFunction( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + EFI_HANDLE Handle; + + EFI_SMM_SW_DISPATCH_CONTEXT Save_CPU_MSR = {SW_SMI_SAVE_MSR}; + EFI_SMM_SW_DISPATCH_CONTEXT Restore_CPU_MSR = {SW_SMI_RESTORE_MSR}; + EFI_SMM_SW_DISPATCH_CONTEXT CpuDriverSaveInfo = { SMM_FROM_SMBASE_DRIVER }; + EFI_SMM_SW_DISPATCH_CONTEXT CpuSmmFeatureEnable = {SW_SMI_ENABLE_SMM_FEATURE}; + + Status = pBS->LocateProtocol(&SwDispatchProtocolGuid,NULL,&gSwDispatch); + if (EFI_ERROR(Status)) { + ASSERT_EFI_ERROR(Status); + return Status; + } + + Status = gSwDispatch->Register( + gSwDispatch, + SaveCpuMsr, + &Save_CPU_MSR, + &Handle + ); + if (EFI_ERROR(Status)) { + ASSERT_EFI_ERROR(Status); + return Status; + } + + Status = gSwDispatch->Register( + gSwDispatch, + RestoreCpuMsr, + &Restore_CPU_MSR, + &Handle + ); + + if (EFI_ERROR(Status)) { + ASSERT_EFI_ERROR(Status); + return Status; + } + + Status = gSwDispatch->Register( + gSwDispatch, + SmramSaveInfoHandler, + &CpuDriverSaveInfo, + &Handle + ); + + if (EFI_ERROR(Status)) { + ASSERT_EFI_ERROR(Status); + return Status; + } + + Status = gSwDispatch->Register( + gSwDispatch, + CpuSmmFeatureEn, + &CpuSmmFeatureEnable, + &Handle + ); + + Status = pBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, NULL, &pSmmBase); + if (EFI_ERROR(Status)) { + return Status; + } + + /*Status = pBS->LocateProtocol (&gEfiSmmThunkProtocolGuid, NULL, &mSmmThunk); + if (EFI_ERROR(Status)) { + TRACE_IDESMM(((UINTN)TRACE_ALWAYS, "SMM Thunk Protocol not located.\n")); + } else { + TRACE_IDESMM(((UINTN)TRACE_ALWAYS, "SMM Thunk Protocol located.\n")); + }*/ + + pSmmBase->GetSmstLocation (pSmmBase, &mSmst); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NotInSmmFunction +// +// Description: If Not In Smm Function +// +// Input: +// +// +// Output: None +// +// Modified: +// +// Referrals: +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NotInSmmFunction( + ) +{ + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CpuSpSmiInit +// +// Description: Initializes CPU specific SMM Drivers. +// +// Input: +// +// Output: +// EFI_STATUS +// +// Modified: +// +// Referrals: +// +// Notes: +// Here is the control flow of this function: +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CpuSpSmiInit( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + //EFI_STATUS Status; + + InitAmiLib(ImageHandle,SystemTable); + + //Status = pBS->LocateProtocol(&SwDispatchProtocolGuid,NULL,&gSwDispatch); + //if (EFI_ERROR(Status)) return Status; +//InitSmmHandler + + // return InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NonSmmElinkFunctions); + + return InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NULL); + + +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + diff --git a/Core/CPU/CpuSpSmi.cif b/Core/CPU/CpuSpSmi.cif new file mode 100644 index 0000000..9f0e181 --- /dev/null +++ b/Core/CPU/CpuSpSmi.cif @@ -0,0 +1,12 @@ +<component> + name = "CpuSp SMI" + category = ModulePart + LocalRoot = "Core\CPU + RefName = "CpuSpSMI" +[files] +"CpuSpSmi.sdl" +"CpuSpSmi.mak" +"CpuSpSmi.h" +"CpuSpSmi.c" +"CpuSpSmi.DXS" +<endComponent> diff --git a/Core/CPU/CpuSpSmi.h b/Core/CPU/CpuSpSmi.h new file mode 100644 index 0000000..bb05202 --- /dev/null +++ b/Core/CPU/CpuSpSmi.h @@ -0,0 +1,118 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.h 1 2/07/12 4:00a Davidhsieh $ +// +// $Revision: 1 $ +// +// $Date: 2/07/12 4:00a $ +// +//********************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.h $ +// +// 1 2/07/12 4:00a Davidhsieh +// +//********************************************************************* + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: <CpuSpSmi.h> +// +// Description: This file contains the Includes, Definitions, typedefs, +// Variable and External Declarations, Structure and +// function prototypes needed for the CpuSpSMI Component +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef _CPUSPSMI_H_ +#define _CPUSPSMI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <AmiDxeLib.h> +#include <Protocol\SmmBase.h> +#include <Protocol\SmmSwDispatch.h> +#include <Protocol\DevicePath.h> +#include <Protocol\LoadedImage.h> +#include <Token.h> + +#define NUM_OF_FIXED_MTRRS 11 + +#define MSR_IA32_MTRR_CAP 0xFE + #define VCNT_MASK 0xFF + +#define MTRR_PHYS_BASE_0 0x200 +#define MTRR_PHYS_MASK_0 0x201 +#define MTRR_PHYS_BASE_1 0x202 +#define MTRR_PHYS_MASK_1 0x203 +#define MTRR_PHYS_BASE_2 0x204 +#define MTRR_PHYS_MASK_2 0x205 +#define MTRR_PHYS_BASE_3 0x206 +#define MTRR_PHYS_MASK_3 0x207 +#define MTRR_PHYS_BASE_4 0x208 +#define MTRR_PHYS_MASK_4 0x209 +#define MTRR_PHYS_BASE_5 0x20a +#define MTRR_PHYS_MASK_5 0x20b +#define MTRR_PHYS_BASE_6 0x20c +#define MTRR_PHYS_MASK_6 0x20d +#define MTRR_PHYS_BASE_7 0x20e +#define MTRR_PHYS_MASK_7 0x20f +#define MTRR_PHYS_BASE_8 0x210 +#define MTRR_PHYS_MASK_8 0x211 +#define MTRR_PHYS_BASE_9 0x212 +#define MTRR_PHYS_MASK_9 0x213 +#define MTRR_FIX_64K_00000 0x250 +#define MTRR_FIX_16K_80000 0x258 +#define MTRR_FIX_16K_A0000 0x259 +#define MTRR_FIX_4K_C0000 0x268 +#define MTRR_FIX_4K_C8000 0x269 +#define MTRR_FIX_4K_D0000 0x26a +#define MTRR_FIX_4K_D8000 0x26b +#define MTRR_FIX_4K_E0000 0x26c +#define MTRR_FIX_4K_E8000 0x26d +#define MTRR_FIX_4K_F0000 0x26e +#define MTRR_FIX_4K_F8000 0x26f + +typedef struct _EFI_MSR_VALUES { + UINT16 Index; + UINT64 Value; +} EFI_MSR_VALUES; + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif + +#endif // _IDESMM_H_ + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CPU/CpuSpSmi.mak b/Core/CPU/CpuSpSmi.mak new file mode 100644 index 0000000..e25e332 --- /dev/null +++ b/Core/CPU/CpuSpSmi.mak @@ -0,0 +1,65 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1987-2013, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.mak 1 2/07/12 4:00a Davidhsieh $ +# +# $Revision: 1 $ +# +# $Date: 2/07/12 4:00a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CpuSp SMI/CpuSpSmi.mak $ +# +# 1 2/07/12 4:00a Davidhsieh +# +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: CpuSpSmi.mak +# +# Description: Make file for the CpuSpSMI component +# +#<AMI_FHDR_END> +#********************************************************************** +all : CPUSPSMI + +CPUSPSMI : $(BUILD_DIR)\CpuSpSmi.mak CpuSpSmiBin + +$(BUILD_DIR)\CpuSpSmi.mak : $(CPUSPSMI_DIR)\$(@B).cif $(CPUSPSMI_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(CPUSPSMI_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +CpuSpSmiBin : $(AMIDXELIB) + @set INCLUDE=%%INCLUDE%% + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\CpuSpSmi.mak all\ + GUID=116e1acf-2533-4cc2-820a-bbc10a2aB07c\ + ENTRY_POINT=CpuSpSmiInit\ + TYPE=BS_DRIVER \ + COMPRESS=1\ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1987-2013, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/CpuSpSmi.sdl b/Core/CPU/CpuSpSmi.sdl new file mode 100644 index 0000000..be2e366 --- /dev/null +++ b/Core/CPU/CpuSpSmi.sdl @@ -0,0 +1,56 @@ +TOKEN + Name = "CPUSPSMI_SUPPORT" + Value = "1" + Help = "Main switch to enable IDESMM support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "SW_SMI_SAVE_MSR" + Value = "0x56" + TokenType = Integer + TargetEQU = Yes + TargetH = Yes +End + +TOKEN + Name = "SW_SMI_RESTORE_MSR" + Value = "0x57" + TokenType = Integer + TargetEQU = Yes + TargetH = Yes +End + +TOKEN + Name = "SW_SMI_ENABLE_SMM_FEATURE" + Value = "0x58" + TokenType = Integer + TargetEQU = Yes + TargetH = Yes +End + +TOKEN + Name = "SW_SMI_S3_RESTORE_MSR_FROM_SDL" + Value = "0x59" + TokenType = Integer + TargetEQU = Yes + TargetH = Yes +End + +PATH + Name = "CPUSPSMI_DIR" +End + +MODULE + Help = "Includes CpuSpSmi.mak to Project" + File = "CpuSpSmi.mak" +End + +ELINK + Name = "$(BUILD_DIR)\CpuSpSmi.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End
\ No newline at end of file diff --git a/Core/CPU/CpuTools.cif b/Core/CPU/CpuTools.cif new file mode 100644 index 0000000..1cafb1b --- /dev/null +++ b/Core/CPU/CpuTools.cif @@ -0,0 +1,10 @@ +<component> + name = "CpuTools" + category = ModulePart + LocalRoot = "Core\Cpu" + RefName = "CpuTools" +[files] +"CpuTools.sdl" +"SecFixup.exe" +"CreateSecFfs.exe" +<endComponent> diff --git a/Core/CPU/CpuTools.sdl b/Core/CPU/CpuTools.sdl new file mode 100644 index 0000000..b259ecf --- /dev/null +++ b/Core/CPU/CpuTools.sdl @@ -0,0 +1,13 @@ +TOKEN + Name = CpuTools_SUPPORT + Value = 1 + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes + Help = "Main switch to enable CpuTools support in Project" +End + +PATH + Name = "CPU_TOOLS_DIR" +End diff --git a/Core/CPU/CreateSecFfs.exe b/Core/CPU/CreateSecFfs.exe Binary files differnew file mode 100644 index 0000000..345c2e5 --- /dev/null +++ b/Core/CPU/CreateSecFfs.exe diff --git a/Core/CPU/IA32/AmiIa32Lib.cif b/Core/CPU/IA32/AmiIa32Lib.cif new file mode 100644 index 0000000..e86bed7 --- /dev/null +++ b/Core/CPU/IA32/AmiIa32Lib.cif @@ -0,0 +1,12 @@ +<component> + name = "AmiIa32Lib" + category = ModulePart + LocalRoot = "Core\CPU\IA32\" + RefName = "AmiIa32Lib" +[files] +"AmiIa32Lib.sdl" +"AmiIa32Lib.mak" +"IA32CLib.c" +"IA32AsmLib\EnableLongMode.asm" +"IA32AsmLib\EnableMachineCheck.asm" +<endComponent> diff --git a/Core/CPU/IA32/AmiIa32Lib.mak b/Core/CPU/IA32/AmiIa32Lib.mak new file mode 100644 index 0000000..304209c --- /dev/null +++ b/Core/CPU/IA32/AmiIa32Lib.mak @@ -0,0 +1,67 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/Modules/IA32Core/AmiIa32Lib.mak 1 10/13/06 8:36p Felixp $ +# +# $Revision: 1 $ +# +# $Date: 10/13/06 8:36p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/Modules/IA32Core/AmiIa32Lib.mak $ +# +# 1 10/13/06 8:36p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: AmiIa32Lib.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +AmiIa32Lib : $(BUILD_DIR)\AmiIa32Lib.mak AmiIa32LibBin + +$(BUILD_DIR)\AmiIa32Lib.mak : $(AmiIa32Lib_DIR)\$(@B).cif $(AmiIa32Lib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(AmiIa32Lib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +!IF "$(PROCESSOR)"=="" || "$(PROCESSOR)"=="IA32" +AmiDxeLibBin : $(BUILD_DIR)\AmiIa32Lib.lib +AmiPeiLibBin : $(BUILD_DIR)\AmiIa32Lib.lib +$(BUILD_DIR)\AmiIa32Lib.lib : AmiIa32Lib +!ELSEIF "$(PROCESSOR)"=="x64" +AmiPeiLibBin : $(BUILD_DIR)\AmiIa32Lib.lib +$(BUILD_DIR)\AmiIa32Lib.lib : AmiIa32Lib +!ENDIF + +AmiIa32LibBin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\AmiIa32Lib.mak all\ + TYPE=PEI_LIBRARY +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/IA32/AmiIa32Lib.sdl b/Core/CPU/IA32/AmiIa32Lib.sdl new file mode 100644 index 0000000..8581f00 --- /dev/null +++ b/Core/CPU/IA32/AmiIa32Lib.sdl @@ -0,0 +1,19 @@ +TOKEN + Name = "AmiIa32Lib_SUPPORT" + Value = "1" + Help = "Main switch to enable AmiIa32Lib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "AmiIa32Lib_DIR" +End + +MODULE + Help = "Includes AmiIa32Lib.mak to Project" + File = "AmiIa32Lib.mak" +End + diff --git a/Core/CPU/IA32/FoundationIa32.cif b/Core/CPU/IA32/FoundationIa32.cif new file mode 100644 index 0000000..8f9a179 --- /dev/null +++ b/Core/CPU/IA32/FoundationIa32.cif @@ -0,0 +1,16 @@ +<component> + name = "FoundationIa32" + category = ModulePart + LocalRoot = "Core\CPU\IA32\" + RefName = "FoundationIa32" +[files] +"FoundationIa32.sdl" +"FoundationIa32.mak" +"efijump.h" +"PeCoffLoaderEx.c" +"PeCoffLoaderEx.h" +"Processor.c" +"ProcessorAsms.Asm" +"SwitchCoreStacks.asm" +"Processor.h" +<endComponent> diff --git a/Core/CPU/IA32/FoundationIa32.mak b/Core/CPU/IA32/FoundationIa32.mak new file mode 100644 index 0000000..93f45d4 --- /dev/null +++ b/Core/CPU/IA32/FoundationIa32.mak @@ -0,0 +1,69 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/EDK/IA32/FoundationIa32.mak 1 8/24/06 12:35p Felixp $ +# +# $Revision: 1 $ +# +# $Date: 8/24/06 12:35p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/EDK/IA32/FoundationIa32.mak $ +# +# 1 8/24/06 12:35p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: FoundationIa32.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +FoundationIa32 : $(BUILD_DIR)\FoundationIa32.mak FoundationIa32Bin + +$(BUILD_DIR)\FoundationIa32.mak : $(FoundationIa32_DIR)\$(@B).cif $(FoundationIa32_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(FoundationIa32_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +!IF "$(PROCESSOR)"=="" || "$(PROCESSOR)"=="IA32" +FoundationBin : $(BUILD_DIR)\FoundationIa32.lib +FoundationPeiBin : $(BUILD_DIR)\FoundationIa32.lib +$(BUILD_DIR)\FoundationIa32.lib : FoundationIa32 +!ELSEIF "$(PROCESSOR)"=="x64" +FoundationPeiBin : $(BUILD_DIR)\FoundationIa32.lib +$(BUILD_DIR)\FoundationIa32.lib : FoundationIa32 +!ENDIF + + +FoundationIa32Bin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\FoundationIa32.mak all\ + "CFLAGS=$(CFLAGS) /I$(Foundation_DIR)"\ + TYPE=PEI_LIBRARY +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/IA32/FoundationIa32.sdl b/Core/CPU/IA32/FoundationIa32.sdl new file mode 100644 index 0000000..67f7c70 --- /dev/null +++ b/Core/CPU/IA32/FoundationIa32.sdl @@ -0,0 +1,19 @@ +TOKEN + Name = "FoundationIa32_SUPPORT" + Value = "1" + Help = "Main switch to enable FoundationIa32 support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "FoundationIa32_DIR" +End + +MODULE + Help = "Includes FoundationIa32.mak to Project" + File = "FoundationIa32.mak" +End + diff --git a/Core/CPU/IA32/IA32AsmLib/EnableLongMode.asm b/Core/CPU/IA32/IA32AsmLib/EnableLongMode.asm new file mode 100644 index 0000000..14af3dd --- /dev/null +++ b/Core/CPU/IA32/IA32AsmLib/EnableLongMode.asm @@ -0,0 +1,143 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2012, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/IA32Core/IA32AsmLib/EnableLongMode.asm 2 8/06/12 2:43p Markw $ +; +; $Revision: 2 $ +; +; $Date: 8/06/12 2:43p $Log:$ +; +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.686p +.xmm +.model flat +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: EnableLongMode +; +; Description: +; VOID EnableLongMode(IN VOID *PageTable, IN VOID *Function, +; IN VOID *Parameter1, IN VOID *Parameter2) enables long mode then calls the +; provided function with the provided parameters. +; +; Input: +; IN VOID *PageTable +; Pointer to level 4 page map. +; +; IN VOID *Function +; Pointer to function to call. +; +; IN VOID *Parameter1 +; Parameter 1 for above function call. +; +; IN VOID *Parameter2 +; Parameter 2 for above function call. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +EnableLongMode proc C public PageTable:DWORD, Function:DWORD, Parameter1:DWORD, Parameter2:DWORD + mov eax, PageTable + mov cr3, eax ;Set CR3 to first page directory pointer table + + mov eax, cr4 + or ax, 620h ;Enable PAE and XMM in case it was turned off. + mov cr4, eax + + ;Enable long mode in msr register. Doesn't actually enter long mode yet. + mov ecx, 0c0000080h + rdmsr + bts eax, 8 + wrmsr + + ;Enable paging + mov eax, cr0 + bts eax, 31 + mov cr0, eax ;Now in long mode compatiblity. + jmp @f +@@: + + ;jmp far segment:offset + db 67h, 0eah + dd offset long_mode_64 + dw 38h ;SYS_CODE64_SEL +long_mode_64: + ;in 64-bit long mode + + db 48h + xor eax, eax ;xor rax, rax + db 48h + xor ebx, ebx ;xor rbx, rbx + db 48h + xor ecx, ecx ;xor rcx, rcx + db 48h + xor edx, edx ;xor rdx, rdx + + mov ecx, Parameter1 + mov edx, Parameter2 + mov ebx, Function + + mov ax, 30h ;SYS_DATA64_SEL + mov ds, ax + mov es, ax + mov ss, ax + + push 37fh + fldcw word ptr [esp] ;Uses rsp. Set FP control word according UEFI + db 48h + add esp, 8 ;add rsp, 8 + + + mov eax, 0fffffff0h + db 48h + and esp, eax ;rsp must be on a 16 byte boundary. C compiler expects that. + call ebx ;call rbx + ret +EnableLongMode endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2012, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* diff --git a/Core/CPU/IA32/IA32AsmLib/EnableMachineCheck.asm b/Core/CPU/IA32/IA32AsmLib/EnableMachineCheck.asm new file mode 100644 index 0000000..8b3cd2a --- /dev/null +++ b/Core/CPU/IA32/IA32AsmLib/EnableMachineCheck.asm @@ -0,0 +1,78 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/IA32Core/IA32AsmLib/EnableMachineCheck.asm 1 10/01/10 4:56p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 4:56p $Log:$ +; +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.686p +.xmm +.model flat +.code + +;************************************************************************* +; +; Name: EnableMachineCheck +; +; Description: +; VOID EnableMachineCheck(VOID) sets the Machine Check Exception bit in CR4, +; which enables machine check interrupts to occur. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;************************************************************************* +_EnableMachineCheck proc + mov eax, cr4 + or eax, 1 SHL 6 + mov cr4, eax + ret +_EnableMachineCheck endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* diff --git a/Core/CPU/IA32/IA32CLib.c b/Core/CPU/IA32/IA32CLib.c new file mode 100644 index 0000000..4cf579c --- /dev/null +++ b/Core/CPU/IA32/IA32CLib.c @@ -0,0 +1,1959 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Modules/IA32Core/IA32CLib.c 14 11/11/11 3:39p Artems $ +// +// $Revision: 14 $ +// +// $Date: 11/11/11 3:39p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Modules/IA32Core/IA32CLib.c $ +// +// 14 11/11/11 3:39p Artems +// Bug fix: Verify pointer is not NULL when return value +// +// 13 10/18/11 11:47a Yakovlevs +// [TAG] EIP71694 +// [Category] Bug Fix +// [Symptom] Option ROM is corrupted when copied from device on Rosecity +// Core 4.6.5.1. +// [RootCause] MemCpy was updated to use 8 bytes at a time. +// PCI ROM BAR was not able to handle this type of request. +// [Solution] Introducesd MemCpy32 functiom. +// [Files] AmiLib.h; AmiX64Lib.cif; IA32CLib.c +// MemCpy32.asm - added +// +// 12 10/01/10 4:57p Felixp +// Most of the functions from IA32AsmLib.asm moved here +// +// 11 11/25/09 1:55p Felixp +// +// 10 11/24/09 5:24p Oleksiyy +// EIP 27605: Added ACPI 4.0 support. InitLongMode function modified. +// +// 9 11/05/09 5:03p Oleksiyy +// EIP 27821 Support for 64 bit operations in IoRead and IoWrite added. +// +// 8 7/10/09 9:26a Felixp +// Function headers are added +// +// 7 4/17/08 2:30p Markw +// Update InitLongMode to create pages above 32-bits. +// +// 6 3/24/08 2:18p Markw +// Added support for pages tables above 4GB. Currently, disabled. +// +// 5 3/18/08 2:41p Markw +// Update page table for first 2MB to have 4k pages. This is so cache +// attributes will not be different in a page. +// +// 4 4/25/07 5:36p Felixp +// InitLongMode and EnableLongMode routines extended so support calling of +// the x64 routine with 2 parameters +// +// 3 12/28/06 6:21p Felixp +// VC8 32-bit compiler support added +// +// 2 10/09/06 10:09a Felixp +// Clean up +// +// 1 8/24/06 12:54p Felixp +// +//************************************************************************* +//<AMI_FHDR_START> +// +// Name: IA32CLib.c +// +// Description: +// Generic CPU library functions for the IA32 architecture. See function +// definitions in the x64 library; most IA32 functions have been removed +// from help builder output to fix a name collision issue. +// +//<AMI_FHDR_END> +//************************************************************************* +#include <PEI.h> +#include <AmiLib.h> +#include <Hob.h> + +//************************************************************************* +// Math +//************************************************************************* + +//************************************************************************* +// +// Name: Shr64 +// +// Description: +// UINT64 Shr64(IN UINT64 Value, IN UINT8 Shift) shifts the 64-bit Value +// right the provided number of bits, Shift. +// +// Input: +// IN UINT64 Value +// The value to be shifted. +// +// IN UINT8 Shift +// The number of bits to shift right. +// +// Output: +// UINT64 Value shifted right Shift number of bits. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 Shr64( + IN UINT64 Value, + IN UINT8 Shift + ) +{ + _asm { + mov edx, dword ptr Value[4] + mov eax, dword ptr Value + mov cl, Shift + + cmp cl, 64 + jb less_64 + xor eax, eax + xor edx, edx + jmp exit +less_64: + cmp cl, 32 //Shift is 32 modulo + jb less_32 + + mov eax, edx + xor edx, edx +less_32: + shrd eax, edx, cl + shr edx, cl +exit: + } +} + +//************************************************************************* +// +// Name: Shl64 +// +// Description: +// UINT64 Shl64(IN UINT64 Value, IN UINT8 Shift) shifts the 64-bit Value +// left the provided number of bits, Shift. +// +// Input: +// IN UINT64 Value +// The value to be shifted left. +// +// IN UINT8 Shift +// The number of bits to shift. +// +// Output: +// UINT64 Value shifted left Shift number of bits. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 Shl64( + IN UINT64 Value, + IN UINT8 Shift + ) +{ + _asm { + mov edx, dword ptr Value[4] + mov eax, dword ptr Value + mov cl, Shift + + cmp cl, 64 + jb less_64 + xor eax, eax + xor edx, edx + jmp exit +less_64: + cmp cl, 32 //Shift is 32 modulo + jb less_32 + + mov edx, eax + xor eax, eax +less_32: + shld edx, eax, cl + shl eax, cl +exit: + } +} + +//************************************************************************* +// +// Name: Div64 +// +// Description: +// UINT64 Div64(IN UINT64 Dividend, IN UINTN Divisor, +// OUT UINTN *Remainder OPTIONAL) divides a 64-bit number, Dividend, by the +// Divisor, which can be up to 31-bits. +// +// Input: +// IN UINT64 Dividend +// The 64-bit number to be divided. +// +// IN UINT Divisor +// The number to divide Dividend by; may not exceed 31-bits in size. +// +// OUT UINTN *Remainder OPTIONAL +// The remainder of the division. Provide NULL if undesired; otherwise user +// is responsible for handling the necessary memory resources. +// +// Output: +// UINT64 result of dividing Dividend by Divisor. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 Div64 ( + IN UINT64 Dividend, + IN UINTN Divisor, //Can only be 31 bits. + OUT UINTN *Remainder OPTIONAL + ) +{ + UINT64 Result; + UINT32 Rem; + _asm + { + mov eax, dword ptr Dividend[0] + mov edx, dword ptr Dividend[4] + mov esi, Divisor + xor edi, edi ; Remainder + mov ecx, 64 ; 64 bits +Div64_loop: + shl eax, 1 ;Shift dividend left. This clears bit 0. + rcl edx, 1 + rcl edi, 1 ;Shift remainder left. Bit 0 = previous dividend bit 63. + + cmp edi, esi ; If Rem >= Divisor, don't adjust + cmc ; else adjust dividend and subtract divisor. + sbb ebx, ebx ; if Rem >= Divisor, ebx = 0, else ebx = -1. + sub eax, ebx ; if adjust, bit 0 of dividend = 1 + and ebx, esi ; if adjust, ebx = Divisor, else ebx = 0. + sub edi, ebx ; if adjust, subtract divisor from remainder. + loop Div64_loop + + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + mov Rem, edi + } + + if (Remainder) *Remainder = Rem; + + return Result; +} +//************************************************************************* +// +// Name: Mul64 +// +// Description: +// UINT64 Mul64(IN UINT64 Value64, IN UINTN Value32) multiplies a 64-bit +// number by a 32-bit number and returns the 64-bit result. +// +// Input: +// IN UINTN64 Value64 +// The 64-bit number to multiply by. +// +// IN UINTN Value32 +// The 32-bit number to multiply by. +// +// Output: +// UINT64 result of multiplying Value64 by Value32. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 Mul64( + IN UINT64 Value64, + IN UINTN Value32 + ) +{ + UINT64 Result; + + _asm { + mov eax, dword ptr Value64[0] + mul Value32 + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + mov eax, dword ptr Value64[4] + mul Value32 + add dword ptr Result[4], eax + } + + return Result; +} + +//************************************************************************* +// Memory Operations +//************************************************************************* + +//************************************************************************* +// +// Name: MemCpy +// +// Description: +// VOID MemCpy(OUT VOID *pDestination, IN VOID *pSource, IN UINTN Count) +// copies Count bytes of memory from Source to Destination. +// +// Input: +// OUT VOID *pDestination +// Memory address where data shall be copied. User is responsible for +// allocating the necessary memory resources. +// +// IN VOID *pSource +// Memory address from where data shall be copied. +// +// IN UINTN Count +// Number of bytes to copy from pSource. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// This function checks for overlapping of source and destination and +// selects copy direction that prevents memory corruption. +// +//************************************************************************* +VOID MemCpy(VOID* pDestination, VOID* pSource, UINTN Count) +{ + _asm{ +// esi, edi, ebx are saved/restores in compiler prolog/epilog code + pushf + mov esi, pSource + mov edi, pDestination + mov ecx, Count + mov dl, 0 + mov eax, esi + sub eax, edi + jnb CopyForward + lea ebx, [esi+ecx] + neg eax + cmp ebx, edi + jb CopyForward + mov esi, ebx + lea edi, [edi+ecx] + mov dl, 1 + std +CopyForward: + cmp ecx, 4 + jb m8 + cmp eax, 4 + jb m8 + mov eax, esi + mov ebx, edi + and eax, 3 + and ebx, 3 + test dl, dl + jz skip1 + dec esi + dec edi +skip1: + cmp eax, ebx + jne m32 + test eax, eax + jz m32 + test dl, dl + jnz skip_nz1 + neg eax + add eax, 4 +skip_nz1: + xchg eax, ecx + sub eax, ecx + rep movsb + mov ecx, eax +m32: + test dl, dl + jz skip2 + sub esi, 3 + sub edi, 3 +skip2: + mov eax, ecx + shr ecx, 2 + rep movsd + and eax, 3 + jz end + test dl, dl + jz skip3 + add esi, 4 + add edi, 4 +skip3: + mov ecx, eax +m8: + test dl, dl + jz skip4 + dec esi + dec edi +skip4: + rep movsb +end: + popf +// esi, edi, ebx are saved/restores in compiler prolog/epilog code + } +} + +VOID MemCpy32(VOID* pDestination, VOID* pSource, UINTN Count){ + MemCpy(pDestination, pSource, Count); +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: memcpy +// +// Description: +// VOID memcpy(OUT VOID *pDestination, IN VOID *pSource, IN UINTN Count) is +// a wrapper for MemCpy, which copies Count bytes of memory from Source to +// Destination. +// +// Input: +// OUT VOID *pDestination +// Memory address where data shall be copied. User is responsible for +// allocating the necessary memory resources. +// +// IN VOID *pSource +// Memory address from where data shall be copied. +// +// IN UINTN Count +// Number of bytes to copy from pSource. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// MemCpy +// +// Notes: +// MemCpy checks for overlapping of source and destination and selects copy +// direction that prevents memory corruption. +// +//<AMI_PHDR_END> +//************************************************************************* +VOID memcpy(VOID* pDestination, VOID* pSource, UINTN Count) +{ + MemCpy(pDestination,pSource,Count); +} + +//************************************************************************* +// +// Name: MemSet +// +// Description: +// VOID MemSet(IN VOID *pBuffer, IN UINTN Count, IN UINT8 Value) fills Count +// bytes of memory in pBuffer with Value. +// +// Input: +// IN VOID *pBuffer +// The starting location in memory where to begin filling. +// +// IN UINTN Count +// The number of bytes to fill with Value. +// +// IN UINT8 Value +// The value to fill memory with starting at pBuffer. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID MemSet(VOID* pBuffer, UINTN Count, UINT8 Value) +{ + _asm{ +// edi, ebx are saved/restores in compiler prolog/epilog code + // fill EAX with the Value so that we can perform DWORD operatins + mov al,Value + mov ah, al + mov bx,ax + shl eax,16 + mov ax,bx + mov edi, pBuffer + // if Counter is less then 4, jump to byte copy + mov ecx, Count + cmp ecx, 4 + jb CopyByte + // check if the Buffer is 4-bytes aligned + mov edx,edi + and edx, 3 + // if the Buffer is 4-bytes aligned, jump to DWORD copy + jz CopyDword + // Buffer is not 4-bytes aligned + // Calculate 4-(Buffer%4), which is a number of bytes we have to copy before + // Buffer will reach 4-bytes boundary, and perform byte copy + neg edx + add edx, 4 + xchg ecx, edx + sub edx, ecx + rep stosb + mov ecx, edx +CopyDword: + // perform DWORD copy + mov edx, ecx + shr ecx, 2 + rep stosd + // copy the remainder + and edx,3 + mov ecx, edx +CopyByte: + rep stosb + /// +// edi, ebx are saved/restores in compiler prolog/epilog code + } +} + +//************************************************************************* +// +// Name: memset +// +// Description: +// VOID memset(IN VOID *pBuffer, IN UINT8 Value, IN UINTN Count) is a +// wrapper for MemSet which fills Count bytes of memory in pBuffer with +// Value. +// +// Input: +// IN VOID *pBuffer +// The starting location in memory where to begin filling. +// +// IN UINT8 Value +// The value to fill memory with starting at pBuffer. +// +// IN UINTN Count +// The number of bytes to fill with Value. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID memset(VOID* pBuffer, UINTN Value, UINTN Count) +{ + MemSet(pBuffer,Count,(UINT8)Value); +} +//************************************************************************* +// Debug routines +//************************************************************************* + +//************************************************************************* +// +// Name: checkpoint +// +// Description: +// VOID checkpoint(IN UINT8 c) writes the value c to port 0x80. +// +// Input: +// IN UINT8 c +// The value/checkpoint to write to 0x80. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// This routine should only be used if the PROGRESS_CODE or +// PEI_PROGRESS_CODE macros are unavailable. +// +//************************************************************************* +VOID checkpoint(UINT8 c){ + _asm{ + mov al, c + out 0x80,al + } +} + +//************************************************************************* +// +// Name: GetCpuTimer +// +// Description: +// UINT64 GetCpuTimer() returns the value of the CPU timer. +// +// Input: +// None. +// +// Output: +// UINT64 value of the CPU timer. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 GetCpuTimer(){_asm rdtsc} + +//************************************************************************* +// I/O Operations +//************************************************************************* + +//************************************************************************* +// +// Name: IoRead8 +// +// Description: +// UINT8 IoRead8(IN UINT16 Port) reads the 8-bit value stored at the I/O +// port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to read 8-bits from. +// +// Output: +// UINT8 value stored at I/O Port. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT8 IoRead8(UINT16 Port) +{ + _asm { + mov dx, Port + in al, dx + } +} + +//************************************************************************* +// +// Name: IoWrite8 +// +// Description: +// VOID IoWrite8(IN UINT16 Port, IN UINT8 Value) writes the 8-bit Value to +// the I/O port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to write 8-bits to. +// +// IN UINT8 Value +// 8-bits to write to the I/O Port. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +void IoWrite8(UINT16 Port,UINT8 Value) +{ + _asm { + mov dx, Port + mov al, Value + out dx, al + } +} + +//************************************************************************* +// +// Name: IoRead16 +// +// Description: +// UINT16 IoRead16(IN UINT16 Port) reads the 16-bit value stored at the I/O +// port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to read 16-bits from. +// +// Output: +// UINT16 value stored at I/O Port. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT16 IoRead16(UINT16 Port) +{ + _asm { + mov dx, Port + in ax, dx + } +} + +//************************************************************************* +// +// Name: IoWrite16 +// +// Description: +// VOID IoWrite16(IN UINT16 Port, IN UINT16 Value) writes the 16-bit Value +// to the I/O port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to write 16-bits to. +// +// IN UINT16 Value +// 16-bits to write to the I/O Port. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +void IoWrite16(UINT16 Port,UINT16 Value) +{ + _asm { + mov dx, Port + mov ax, Value + out dx, ax + } +} + +//************************************************************************* +// +// Name: IoRead32 +// +// Description: +// UINT32 IoRead32(IN UINT16 Port) reads the 32-bit value stored at the I/O +// port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to read 32-bits from. +// +// Output: +// UINT32 value stored at I/O Port. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT32 IoRead32(UINT16 Port) +{ + _asm { + mov dx, Port + in eax, dx + } +} + +//************************************************************************* +// +// Name: IoWrite32 +// +// Description: +// VOID IoWrite32(IN UINT16 Port, IN UINT32 Value) writes the 32-bit Value +// to the I/O port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to write 32-bits to. +// +// IN UINT32 Value +// 32-bits to write to the I/O Port. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +void IoWrite32(UINT16 Port,UINT32 Value) +{ + _asm { + mov dx, Port + mov eax, Value + out dx, eax + } +} + +//************************************************************************* +// +// Name: IoRead64 +// +// Description: +// UINT32 IoRead64(IN UINT16 Port) reads the 64-bit value stored at the I/O +// port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to read 64-bits from. +// +// Output: +// UINT64 value stored at I/O Port. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 IoRead64(UINT16 Port) +{ + + UINT64 Result; + UINT64 *Buffer = &Result; + + _asm { + xor edx, edx + mov dx, Port + mov esi, Buffer + in eax, dx + mov dword ptr[esi],eax + add esi, 4 + add dx, 4 + in eax, dx + mov dword ptr[esi],eax + } + return Result; +} + +//************************************************************************* +// +// Name: IoWrite64 +// +// Description: +// VOID IoWrite64(IN UINT16 Port, IN UINT64 Value) writes the 64-bit Value +// to the I/O port defined by Port. +// +// Input: +// IN UINT16 Port +// I/O port to write 64-bits to. +// +// IN UINT64 Value +// 64-bits to write to the I/O Port. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +void IoWrite64(UINT16 Port, UINT64 Value) +{ +// UINT32 Lo=(UINT32)Value, Hi=(UINT32)Shr64(Value,32); + + VOID* Buffer=&Value; + + + _asm { + xor edx, edx + mov dx, Port + mov esi, Buffer + mov eax, dword ptr[esi] + out dx, eax + add esi, 4 + add dx, 4 + mov eax, dword ptr[esi] + out dx, eax + } + + + +} + +VOID EnableLongMode(VOID *PageTable, VOID *Function, VOID *Parameter1, VOID *Parameter2); + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: InitLongModeExt +// +// Description: +// VOID InitLongMode(IN EFI_PEI_SERVICES **PeiServices, IN VOID *Function, +// IN VOID *Parameter1, IN VOID *Parameter2) initializes memory page mapping, +// enables long mode and jumps to a provided function. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to the PEI Services table. +// +// IN VOID *Function +// Pointer to a function for EnableLongMode to call. +// +// IN VOID *Parameter1 +// First parameter to provide the Function to be called. +// +// IN VOID *Parameter2 +// Second parameter to provide the Function to be called. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// FindNextHobByType +// EFI_ERROR +// GetPageTableNumPages +// FillPageTable +// EnableLongMode +// +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +VOID InitLongModeExt( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Function, + IN VOID *Parameter1, + IN VOID *Parameter2, + IN UINT8 NumMemBits +) +{ + EFI_PHYSICAL_ADDRESS PageTable; + UINT32 NumPages; + EFI_STATUS Status; +//TODO: In AllocatePages below, change EfiACPIMemoryNVS to EfiBootServicesData. +//TODO: It is left as EfiACPIMemoryNVS until future projects can be updated to +//TODO: a later CPU module. Future CPU modules will allocate EfiACPIMemoryNVS +//TODO: for only 32-bits. + + NumPages = GetPageTableNumPages(NumMemBits); + + Status = (*PeiServices)->AllocatePages( + PeiServices, + EfiACPIMemoryNVS, + NumPages, + &PageTable + ); + //ASSERT_PEI_ERROR(PeiServices,Status); + + FillPageTable(NumMemBits, (VOID*)PageTable); + + EnableLongMode((VOID*)PageTable, Function, Parameter1, Parameter2); +} +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: InitLongMode +// +// Description: +// VOID InitLongMode(IN EFI_PEI_SERVICES **PeiServices, IN VOID *Function, +// IN VOID *Parameter1, IN VOID *Parameter2) initializes memory page mapping, +// enables long mode and jumps to a provided function. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to the PEI Services table. +// +// IN VOID *Function +// Pointer to a function for EnableLongMode to call. +// +// IN VOID *Parameter1 +// First parameter to provide the Function to be called. +// +// IN VOID *Parameter2 +// Second parameter to provide the Function to be called. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// FindNextHobByType +// EFI_ERROR +// GetPageTableNumPages +// FillPageTable +// EnableLongMode +// +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +VOID InitLongMode( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Function, + IN VOID *Parameter1, + IN VOID *Parameter2 +) +{ + + + UINT8 NumMemBits = 32; + EFI_HOB_CPU *CpuHob; + VOID *FirstHob; + EFI_STATUS Status; + + (*PeiServices)->GetHobList(PeiServices, &FirstHob); + //if (!FirstHob) ASSERT_PEI_ERROR(PeiServices, EFI_NOT_FOUND); + + CpuHob = (EFI_HOB_CPU*) FirstHob; + Status = FindNextHobByType(EFI_HOB_TYPE_CPU, &CpuHob); + + //If error during release mode, The memory cache size will be 32-bits. + //During debug mode, an assert will happen to alert that the CPU HOB is + //not produced, so that all memory will not be paged. + //ASSERT_PEI_ERROR(PeiServices, Status); + + //Find APIC ID Hob. + if (!EFI_ERROR(Status)) { + NumMemBits = CpuHob->SizeOfMemorySpace; + } + + InitLongModeExt (PeiServices, Function, Parameter1, Parameter2, NumMemBits); +} + +//************************************************************************* +// +// Name: GetPowerOfTwo64 +// +// Description: +// UINT64 GetPowerOfTwo64(IN UINT64 Input) returns the highest bit set in +// the provided UINT64 Input. Equivalent to 1 << log2(x). +// +// Input: +// IN UINT64 Input +// The 64-bit value to check for its highest bit. +// +// Output: +// UINT64 value of the highest bit; if Input is 0, returns 0. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 GetPowerOfTwo64( + IN UINT64 Input +) +{ + UINT64 Result = 0; + + if (Input > 0xffffffff) { + _asm { + bsr eax, dword ptr Input[4] + bts dword ptr Result[4], eax + } + } else { + _asm { + bsr eax, dword ptr Input[0] + bts dword ptr Result[0], eax + } + } + return Result; +} + +//************************************************************************* +// +// Name: ReadMsr +// +// Description: +// UINT64 ReadMsr(IN UINT32 Msr) reads the CPU MSR index defined by Msr and +// returns the value. +// +// Input: +// IN UINT32 Msr +// 32-bit MSR index to be read. +// +// Output: +// UINT64 MSR value at MSR index, Msr. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 ReadMsr(IN UINT32 Msr){ + _asm{ + mov ecx, Msr ;MSR register + rdmsr + } +} + +//************************************************************************* +// +// Name: WriteMsr +// +// Description: +// VOID WriteMsr(IN UINT32 Msr, IN UINT64 Value) writes the Value to the +// supplied MSR index, Msr. +// +// Input: +// IN UINT32 Msr +// 32-bit MSR index to be written to. +// +// IN UINT64 Value +// Value to be written to MSR index. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID WriteMsr(IN UINT32 Msr, IN UINT64 Value){ + _asm{ + mov ecx, Msr ;MSR register + mov edx, dword ptr Value[4] ;Upper 32 bit MSR Value + mov eax, dword ptr Value[0] ;Lower 32 bit MSR Value + wrmsr + } +} +//************************************************************************* +// +// Name: CPULib_CpuID +// +// Description: +// VOID CPULib_CpuID(IN UINT32 CpuIDIndex, IN OUT UINT32 *pRegEAX, +// IN OUT UINT32 *pRegEBX, IN OUT UINT32 *pRegECX, IN OUT UINT32 *pRegEDX) +// issues the CPUID instruction with the index provided and returns the +// register values. +// +// Input: +// IN UINT32 CpuIDIndex +// 32-bit CPUID index. +// +// IN OUT UINT32 *pRegEAX +// Pointer to UINT32 for EAX return value. +// +// IN OUT UINT32 *pRegEBX +// Pointer to UINT32 for EBX return value. +// +// IN OUT UINT32 *pRegECX +// Pointer to UINT32 for ECX return value. +// +// IN OUT UINT32 *pRegEDX +// Pointer to UINT32 for EDX return value. +// +// Output: +// IN OUT UINT32 *pRegEAX +// Value of EAX after CPUID instruction. +// +// IN OUT UINT32 *pRegEBX +// Value of EBX after CPUID instruction. +// +// IN OUT UINT32 *pRegECX +// Value of ECX after CPUID instruction. +// +// IN OUT UINT32 *pRegEDX +// Value of EDX after CPUID instruction. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_CpuID( + IN UINT32 CpuIDIndex, + IN OUT UINT32 *pRegEAX, + IN OUT UINT32 *pRegEBX, + IN OUT UINT32 *pRegECX, + IN OUT UINT32 *pRegEDX) +{ + _asm{ + push ebx + push ecx + push edx + push esi + mov esi, pRegECX + mov ecx, [esi] + mov eax, CpuIDIndex + cpuid + mov esi, pRegEAX + or esi, esi + jz skip1 + mov [esi], eax +skip1: + mov esi, pRegEBX + or esi, esi + jz skip2 + mov [esi], ebx +skip2: + mov esi, pRegECX + or esi, esi + jz skip3 + mov [esi], ecx +skip3: + mov esi, pRegEDX + or esi, esi + jz skip4 + mov [esi], edx +skip4: + pop esi + pop edx + pop ecx + pop ebx + } +} + +//************************************************************************* +// +// Name: DisableCacheInCR0 +// +// Description: +// VOID DisableCacheInCR0(VOID) disables the CPU cache using the CR0 register. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID DisableCacheInCR0(VOID){ + _asm{ + wbinvd + mov eax, cr0 + or eax, 060000000h ;SET CD, NW + mov cr0, eax + wbinvd ;Invalidate cache + } +} + +//************************************************************************* +// +// Name: EnableCacheInCR0 +// +// Description: +// VOID EnableCacheInCR0(VOID) enables the CPU cache using the CR0 register. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID EnableCacheInCR0(VOID){ + _asm{ + // Enable cache + mov eax, cr0 + and eax, 09fffffffh ;SET CD, NW + mov cr0, eax + wbinvd + } +} +//************************************************************************* +// +// Name: ReadCr3 +// +// Description: +// UINTN ReadCr3(VOID) reads the register CR3 and returns its value. +// +// Input: +// VOID. +// +// Output: +// Returns UINTN value stored in the CR3 register. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINTN ReadCr3(VOID){ + _asm{ + mov eax, cr3 + } +} +//************************************************************************* +// +// Name: WriteCr3 +// +// Description: +// VOID WriteCr3(IN UINTN CR3) writes the provided value to the CR3 register. +// +// Input: +// IN UINTN CR3 +// Value to be written to the CR3 register. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID WriteCr3(IN UINTN CR3){ + _asm{ + mov eax, CR3 + mov cr3, eax + } +} +//************************************************************************* +// +// Name: CPULib_EnableInterrupt +// +// Description: +// VOID CPULib_EnableInterrupt(VOID) enables interrupts on the CPU. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_EnableInterrupt(VOID){ + _asm{ + // Enable Interrupt + sti + } +} + +//************************************************************************* +// +// Name: CPULib_DisableInterrupt +// +// Description: +// VOID CPULib_DisableInterrupt() disables interrupts on the CPU. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_DisableInterrupt(){ + _asm{ + // Disable Interrupt + cli + } +} + +//************************************************************************* +// +// Name: CPULib_GetInterruptState +// +// Description: +// BOOLEAN CPULib_GetInterruptState(VOID)returns the current CPU interrupt +// state. +// +// Input: +// VOID. +// +// Output: +// Returns FALSE if interrupts are disabled; otherwise TRUE. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +BOOLEAN CPULib_GetInterruptState(VOID){ + _asm{ + xor bl, bl + pushfd ; push flags onto stack. + pop eax ; eax = flags. + bt eax,9 ; IF (bit 9) if set, set carry flag. + ; Interrupts are allowed if IF is set. + adc bl, 0 ; BL = IF = CF. + + mov al, bl ; Return value + } +} + +//************************************************************************* +// +// Name: GetCsSegment +// +// Description: +// UINT16 GetCsSegment(VOID) retreives the value of the CS register. +// +// Input: +// VOID. +// +// Output: +// Returns UINT16 value of CS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT16 GetCsSegment(VOID){ + _asm{ + mov ax, cs + } +} + +//************************************************************************* +// +// Name: ReadRtdsc +// +// Description: +// UINT64 ReadRtdsc(VOID) retrieves the time stamp counter. +// +// Input: +// VOID. +// +// Output: +// Returns UINT64 value of the time stamp counter. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT64 ReadRtdsc(VOID){ + _asm{ + rdtsc + } +} + +//************************************************************************* +// +// Name: WaitForever +// +// Description: +// VOID WaitForever(VOID) performs an infinite loop which does nothing. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID WaitForever(VOID){ + _asm{ + bbb: + jmp bbb + } +} + +//************************************************************************* +// +// Name: HltCpu +// +// Description: +// VOID HltCpu(VOID) halts the CPU. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID HltCpu(VOID){ + _asm{ + bbb: + cli + hlt + jmp bbb + } +} + +//************************************************************************* +// +// Name: CPULib_Pause +// +// Description: +// VOID CPULib_Pause(VOID) performs the pause assembly instruction. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_Pause(VOID){ + _asm{ + pause + } +} + +//************************************************************************* +// +// Name: WaitForSemaphore +// +// Description: +// VOID WaitForSemaphore(IN volatile UINT8 *Semaphore) waits for the +// semaphore to become available; once available, it claims the semaphore and +// returns. +// +// Input: +// IN volatile UINT8 *Semaphore +// Pointer to the desired semaphore. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID WaitForSemaphore(IN volatile UINT8 *Semaphore){ + _asm{ + push ebx + mov al, 1 + mov ebx, Semaphore + bbb: + xchg al, [ebx] + or al, al + pause + jnz bbb + pop ebx + } +} + +//************************************************************************* +// +// Name: WaitUntilZero8 +// +// Description: +// VOID WaitUntilZero8(IN volatile UINT8 *Value) waits until the byte stored +// at Value becomes 0, then continues. +// +// Input: +// IN volatile UINT8 *Value +// Address of the byte value to be monitored. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID WaitUntilZero8(IN volatile UINT8 *Value){ + _asm{ + push ebx + mov ebx, Value + bbb: + mov al, [ebx] + or al, al + pause + jnz bbb + pop ebx + } +} + +//************************************************************************* +// +// Name: WaitUntilZero32 +// +// Description: +// VOID WaitUntilZero32(IN volatile UINT32 *Value) waits until the UINT32 +// value stored at the Value address becomes 0, then continues. +// +// Input: +// IN volatile UINT32 *Value +// Address of the UINT32 value to be monitored. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID WaitUntilZero32(IN volatile UINT32 *Value) { + _asm{ + push ebx + mov ebx, Value + bbb: + mov eax, [ebx] + or eax, eax + pause + jnz bbb + pop ebx + } +} + +//************************************************************************* +// +// Name: CPULib_LockByteInc +// +// Description: +// VOID CPULib_LockByteInc(IN UINT8 *ptr) locks the next byte after the +// address pointed to by ptr. +// +// Input: +// IN UINT8 *ptr// Address to the byte which preceeds the desired byte to be locked. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_LockByteInc(IN UINT8 *xptr){ + _asm{ + mov eax, xptr + lock inc byte ptr [eax] + } +} + +//************************************************************************* +// +// Name: CPULib_LockByteDec +// +// Description: +// VOID CPULib_LockByteDec(IN UINT8 *ptr) locks the preceeding byte before +// the address pointed to by ptr. +// +// Input: +// IN UINT8 *ptr +// Address to the byte which follows the desired byte to be locked. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_LockByteDec(IN UINT8 *xptr) { + _asm{ + mov eax, xptr + lock dec byte ptr [eax] + } +} + +//************************************************************************* +// +// Name: CPULib_LoadGdt +// +// Description: +// VOID CPULib_LoadGdt(IN VOID *ptr) loads the GDT at the location pointed to +// by ptr. +// +// Input: +// IN VOID *ptr +// Address of the GDT to be loaded. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_LoadGdt(IN VOID *xptr) { + _asm{ + mov eax, xptr + lgdt fword ptr [eax] + } +} + +//************************************************************************* +// +// Name: CPULib_SaveGdt +// +// Description: +// VOID CPULib_SaveGdt(IN VOID *ptr) stores the loaded GDT at the location +// provided by ptr. +// +// Input: +// IN VOID *ptr +// Address to save the GDT. User is responsible for allocating the necessary +// memory resources. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_SaveGdt(IN VOID *xptr) { + _asm{ + mov eax, xptr + sgdt fword ptr [eax] + } +} + +//************************************************************************* +// +// Name: CPULib_LoadIdt +// +// Description: +// VOID CPULib_LoadIdt(IN VOID *ptr) loads the IDT at the location provided +// by ptr. +// +// Input: +// IN VOID *ptr +// Address of the IDT to be loaded. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_LoadIdt(IN VOID *xptr) { + _asm{ + mov eax, xptr + lidt fword ptr [eax] + } +} + +//************************************************************************* +// +// Name: CPULib_SaveIdt +// +// Description: +// VOID CPULib_SaveIdt(IN VOID *ptr) stores the loaded IDT at the location +// provided by ptr. +// +// Input: +// IN VOID *ptr +// Address to save the IDT. User is responsible for allocating the necessary +// memory resources. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID CPULib_SaveIdt(IN VOID *xptr) { + _asm{ + mov eax, xptr + sidt fword ptr [eax] + } +} + +//************************************************************************* +// +// Name: MemRead32 +// +// Description: +// UINT32 MemRead32(IN UINT32 *Address) reads and returns the 32-bit value +// stored at the user provided address. +// +// Input: +// IN UINT32 *Address +// Address to read 32-bits from. +// +// Output: +// UINT32 value stored at Address. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +UINT32 MemRead32(IN UINT32 *Address) { + _asm{ + push esi + mov esi, Address ;esi = address + mov eax, [esi] + pop esi + } +} + +//************************************************************************* +// +// Name: MemReadWrite32 +// +// Description: +// VOID MemReadWrite32(IN UINT32 *Address, IN UINT32 Value, IN UINT32 Mask) +// reads the 32-bit value stored at Address, ANDs it with Mask, ORs the result +// with Value, then writes the result back to Address. +// +// Input: +// IN UINT32 *Address +// Address which shall be read from and subsequently written to. +// +// IN UINT32 Value +// Value to be ORed with the value stored at Address after it has been ANDed +// with the provided Mask. +// +// IN UINT32 Mask +// Mask to be ANDed with the original value stored at Address. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//************************************************************************* +VOID MemReadWrite32( + IN UINT32 *Address, + IN UINT32 Value, + IN UINT32 Mask) +{ + _asm{ + push esi + mov esi, Address ;esi = address + mov eax, [esi] + and eax, Mask ;Mask + or eax, Value ;Value + mov [esi], eax + pop esi + } +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/IA32/IA32Core.cif b/Core/CPU/IA32/IA32Core.cif new file mode 100644 index 0000000..352c150 --- /dev/null +++ b/Core/CPU/IA32/IA32Core.cif @@ -0,0 +1,9 @@ +<component> + name = "IA32 Core" + category = ModulePart + LocalRoot = "Core\CPU\IA32\" + RefName = "IA32Core" +[files] +"IA32Core.sdl" +"IA32rules.mak" +<endComponent> diff --git a/Core/CPU/IA32/IA32Core.sdl b/Core/CPU/IA32/IA32Core.sdl new file mode 100644 index 0000000..98f179a --- /dev/null +++ b/Core/CPU/IA32/IA32Core.sdl @@ -0,0 +1,33 @@ +TOKEN + Name = "IA32Core_SUPPORT" + Value = "1" + Help = "Main switch to enable IA32 support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "AFLAGSIA32" + Value = "/coff" + TokenType = Expression + TargetMAK = Yes +End + +PATH + Name = "IA32Core_DIR" +End + +ELINK + Name = "IA32" + Parent = "PROCESSOR" + InvokeOrder = AfterParent +End + +ELINK + Name = "$(IA32Core_DIR)\IA32rules.mak" + Parent = "PROCESSOR_RULES" + InvokeOrder = AfterParent +End + diff --git a/Core/CPU/IA32/IA32rules.mak b/Core/CPU/IA32/IA32rules.mak new file mode 100644 index 0000000..8f58110 --- /dev/null +++ b/Core/CPU/IA32/IA32rules.mak @@ -0,0 +1,62 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/BIN/Core/Modules/IA32Core/IA32rules.mak 2 12/28/06 6:22p Felixp $ +# +# $Revision: 2 $ +# +# $Date: 12/28/06 6:22p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Core/Modules/IA32Core/IA32rules.mak $ +# +# 2 12/28/06 6:22p Felixp +# VC8 32-bit compiler support added +# +# 1 10/13/06 8:30p Felixp +# +# 1 8/24/06 12:54p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: IA32rules.mak +# +# Description: Defines IA32-specific build rules. +# This file is included into the template makefile rules.mak +# +#<AMI_FHDR_END> +#********************************************************************** +!IF "$(TOOLS)"=="vc8" +EXTRA_CFLAGS=$(EXTRA_CFLAGS) /GS- +!ENDIF + +EXTRA_CFLAGS=$(EXTRA_CFLAGS) $(CFLAGSIA32) +EXTRA_LFLAGS=$(EXTRA_LFLAGS) $(LFLAGSIA32) +EXTRA_AFLAGS=$(EXTRA_AFLAGS) $(AFLAGSIA32) +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/IA32/PeCoffLoaderEx.c b/Core/CPU/IA32/PeCoffLoaderEx.c new file mode 100644 index 0000000..3e08c1c --- /dev/null +++ b/Core/CPU/IA32/PeCoffLoaderEx.c @@ -0,0 +1,93 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + IA-32 Specific relocation fixups + +Revision History + +--*/ + +#include "Tiano.h" +#include "EfiImage.h" + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - relocate unsupported + +--*/ +{ + return EFI_UNSUPPORTED; +} + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +{ + if ((Machine == EFI_IMAGE_MACHINE_IA32) || (Machine == EFI_IMAGE_MACHINE_X64) || + (Machine == EFI_IMAGE_MACHINE_EBC)) { + return TRUE; + } + + return FALSE; +} + diff --git a/Core/CPU/IA32/PeCoffLoaderEx.h b/Core/CPU/IA32/PeCoffLoaderEx.h new file mode 100644 index 0000000..a83282d --- /dev/null +++ b/Core/CPU/IA32/PeCoffLoaderEx.h @@ -0,0 +1,85 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PeCoffLoaderEx.h + +Abstract: + + IA-32 Specific relocation fixups + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - relocate unsupported + +--*/ +; + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +; + +#endif diff --git a/Core/CPU/IA32/Processor.c b/Core/CPU/IA32/Processor.c new file mode 100644 index 0000000..fcdd4bf --- /dev/null +++ b/Core/CPU/IA32/Processor.c @@ -0,0 +1,140 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +// +// Prototypes +// +EFI_STATUS +EFIAPI +TransferControlSetJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +TransferControlLongJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +// +// Table declarations +// +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + TransferControlSetJump, + TransferControlLongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + FlushInstructionCacheFlush +}; + + +EFI_STATUS +InstallEfiPeiTransferControl ( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed. + +--*/ +{ + *This = &mTransferControl; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed + +--*/ +{ + *This = &mFlushInstructionCache; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + In the case of IA32, this flushing is not necessary and is thus not implemented. + +Arguments: + + This - Pointer to CPU Architectural Protocol interface + Start - Start adddress in memory to flush + Length - Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/Core/CPU/IA32/Processor.h b/Core/CPU/IA32/Processor.h new file mode 100644 index 0000000..0084d4a --- /dev/null +++ b/Core/CPU/IA32/Processor.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + Processor.h + +Abstract: + This file contains the IA-32 processor specific definitions + +--*/ + +#ifndef _PROCESSOR_H_ +#define _PROCESSOR_H_ + +#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE) + +#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE) + +#endif
\ No newline at end of file diff --git a/Core/CPU/IA32/ProcessorAsms.Asm b/Core/CPU/IA32/ProcessorAsms.Asm new file mode 100644 index 0000000..86f4606 --- /dev/null +++ b/Core/CPU/IA32/ProcessorAsms.Asm @@ -0,0 +1,223 @@ +; +; Copyright (c) 2004, Intel Corporation +; All rights reserved. This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; ProcessorAsms.Asm +; +; Abstract: +; This is separated from processor.c to allow this functions to be built with /O1 +; +; Notes: +; - Masm uses "This", "ebx", etc as a directive. +; - H2INC is still not embedded in our build process so I translated the struc manually. +; - Unreferenced variables/arguments (This, NewBsp, NewStack) were causing compile errors and +; did not know of "pragma" mechanism in MASM and I did not want to reduce the warning level. +; Instead, I did a dummy referenced. +; + + .686P + .MMX + .MODEL SMALL + .CODE + +EFI_SUCCESS equ 0 +EFI_WARN_RETURN_FROM_LONG_JUMP equ 5 + +; +; Generated by h2inc run manually +; +_EFI_JUMP_BUFFER STRUCT 2t +_ebx DWORD ? +_esi DWORD ? +_edi DWORD ? +_ebp DWORD ? +_esp DWORD ? +_eip DWORD ? +_EFI_JUMP_BUFFER ENDS + +EFI_JUMP_BUFFER TYPEDEF _EFI_JUMP_BUFFER + +TransferControlSetJump PROTO C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + +TransferControlLongJump PROTO C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + +SwitchStacks PROTO C \ + EntryPoint:PTR DWORD, \ + Parameter:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + +SwitchIplStacks PROTO C \ + EntryPoint:PTR DWORD, \ + Parameter1:DWORD, \ + Parameter2:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + +; +;Routine Description: +; +; This routine implements the IA32 variant of the SetJump call. Its +; responsibility is to store system state information for a possible +; subsequent LongJump. +; +;Arguments: +; +; Pointer to CPU context save buffer. +; +;Returns: +; +; EFI_SUCCESS +; +TransferControlSetJump PROC C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + + mov eax, _This + mov ecx, Jump + mov (EFI_JUMP_BUFFER PTR [ecx])._ebx, ebx + mov (EFI_JUMP_BUFFER PTR [ecx])._esi, esi + mov (EFI_JUMP_BUFFER PTR [ecx])._edi, edi + mov eax, [ebp] + mov (EFI_JUMP_BUFFER PTR [ecx])._ebp, eax + lea eax, [ebp+4] + mov (EFI_JUMP_BUFFER PTR [ecx])._esp, eax + mov eax, [ebp+4] + mov (EFI_JUMP_BUFFER PTR [ecx])._eip, eax + mov eax, EFI_SUCCESS + + ret + +TransferControlSetJump ENDP + +; +; Routine Description: +; +; This routine implements the IA32 variant of the LongJump call. Its +; responsibility is restore the system state to the Context Buffer and +; pass control back. +; +; Arguments: +; +; Pointer to CPU context save buffer. +; +; Returns: +; +; EFI_WARN_RETURN_FROM_LONG_JUMP +; + +TransferControlLongJump PROC C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + + push ebx + push esi + push edi + + mov eax, _This + ; set return from SetJump to EFI_WARN_RETURN_FROM_LONG_JUMP + mov eax, EFI_WARN_RETURN_FROM_LONG_JUMP + mov ecx, Jump + mov ebx, (EFI_JUMP_BUFFER PTR [ecx])._ebx + mov esi, (EFI_JUMP_BUFFER PTR [ecx])._esi + mov edi, (EFI_JUMP_BUFFER PTR [ecx])._edi + mov ebp, (EFI_JUMP_BUFFER PTR [ecx])._ebp + mov esp, (EFI_JUMP_BUFFER PTR [ecx])._esp + add esp, 4 ;pop the eip + jmp DWORD PTR (EFI_JUMP_BUFFER PTR [ecx])._eip + mov eax, EFI_WARN_RETURN_FROM_LONG_JUMP + + pop edi + pop esi + pop ebx + ret + +TransferControlLongJump ENDP + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter +; Parameter - Parameter to pass in +; NewStack - New Location of the stack +; NewBsp - New BSP +; +; Returns: +; +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchStacks PROC C \ + EntryPoint:PTR DWORD, \ + Parameter:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + + push ebx + mov eax, NewBsp + mov ebx, Parameter + mov ecx, EntryPoint + mov eax, NewStack + mov esp, eax + push ebx + push 0 + jmp ecx + + pop ebx + ret + +SwitchStacks ENDP + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter +; Parameter1/Parameter2 - Parameter to pass in +; NewStack - New Location of the stack +; NewBsp - New BSP +; +; Returns: +; +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchIplStacks PROC C \ + EntryPoint:PTR DWORD, \ + Parameter1:DWORD, \ + Parameter2:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + + push ebx + mov eax, NewBsp + mov ebx, Parameter1 + mov edx, Parameter2 + mov ecx, EntryPoint + mov eax, NewStack + mov esp, eax + + push edx + push ebx + call ecx + + pop ebx + ret + +SwitchIplStacks ENDP + + END + diff --git a/Core/CPU/IA32/SwitchCoreStacks.asm b/Core/CPU/IA32/SwitchCoreStacks.asm new file mode 100644 index 0000000..dbb664d --- /dev/null +++ b/Core/CPU/IA32/SwitchCoreStacks.asm @@ -0,0 +1,104 @@ + TITLE SwitchCoreStacks.asm: Core stack switching routine + +;------------------------------------------------------------------------------ +;Copyright (c) 2004, Intel Corporation +;All rights reserved. This program and the accompanying materials +;are licensed and made available under the terms and conditions of the BSD License +;which accompanies this distribution. The full text of the license may be found at +;http://opensource.org/licenses/bsd-license.php +; +;THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +;WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;Module Name: +; +; SwitchCoreStacks.asm +; +;Abstract: +; +; Core stack switching routine, invoked when real system memory is +; discovered and installed. +; +;------------------------------------------------------------------------------ + + .686P + .XMM + .MODEL SMALL + .CODE + + +include token.equ + +AsmWriteMm7 PROTO C + +AsmWriteMm7 PROC C +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm7 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ + movq mm7, [esp + 4] + ret +AsmWriteMm7 ENDP + +IF MKF_PI_SPECIFICATION_VERSION GE 00010000h +SwitchCoreStacks PROTO C EntryPoint: DWORD, Parameter1: DWORD, Parameter2: DWORD, Parameter3: DWORD, NewStack: DWORD + +SwitchCoreStacks PROC C EntryPoint: DWORD, Parameter1: DWORD, Parameter2: DWORD, Parameter3: DWORD, NewStack: DWORD +ELSE +SwitchCoreStacks PROTO C EntryPoint: DWORD, Parameter1: DWORD, Parameter2: DWORD, NewStack: DWORD + +SwitchCoreStacks PROC C EntryPoint: DWORD, Parameter1: DWORD, Parameter2: DWORD, NewStack: DWORD +ENDIF + +;------------------------------------------------------------------------------ +; VOID +; SwitchCoreStacks ( +; IN VOID *EntryPoint, +; IN UINTN Parameter1, +; IN UINTN Parameter2, +; IN UINTN Parameter3, +; IN VOID *NewStack +; ) +; +; Routine Description: +; +; Routine for PEI switching stacks. +; +; Arguments: +; +; EntryPoint - Entry point with new stack. +; Parameter1 - First parameter for entry point. +; Parameter2 - Second parameter for entry point. +; Parameter3 - Third parameter for entry point. +; NewStack - Pointer to new stack. +; +; Returns: +; +; None +; +;---------------------------------------------------- + + mov ebx, Parameter1 + mov edx, Parameter2 +IF MKF_PI_SPECIFICATION_VERSION GE 00010000h + mov eax, Parameter3 +ENDIF + mov ecx, EntryPoint + mov esp, NewStack + + ; First push Parameter3, and then Parameter2 ,at last Parameter1. +IF MKF_PI_SPECIFICATION_VERSION GE 00010000h + push eax +ENDIF + push edx + push ebx + call ecx + + ret + +SwitchCoreStacks ENDP + +END diff --git a/Core/CPU/IA32/efijump.h b/Core/CPU/IA32/efijump.h new file mode 100644 index 0000000..d676f88 --- /dev/null +++ b/Core/CPU/IA32/efijump.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiJump.h + +Abstract: + + This is the Setjump/Longjump pair for an IA32 processor. + +--*/ + +#ifndef _EFI_JUMP_H_ +#define _EFI_JUMP_H_ + +typedef struct { + UINT32 ebx; + UINT32 esi; + UINT32 edi; + UINT32 ebp; + UINT32 esp; + UINT32 eip; +} EFI_JUMP_BUFFER; + +#endif diff --git a/Core/CPU/IPF/FoundationIPF.cif b/Core/CPU/IPF/FoundationIPF.cif new file mode 100644 index 0000000..c6f8c63 --- /dev/null +++ b/Core/CPU/IPF/FoundationIPF.cif @@ -0,0 +1,24 @@ +<component> + name = "FoundationIPF" + category = ModulePart + LocalRoot = "Core\CPU\IPF\" + RefName = "FoundationIPF" +[files] +"FoundationIPF.sdl" +"FoundationIPF.mak" +"SwitchStack.s" +"asm.h" +"efijump.h" +"ia_64gen.h" +"PeCoffLoaderEx.c" +"PeCoffLoaderEx.h" +"PerformancePrimitives.s" +"pioflush.s" +"processor.c" +"setjmp.s" +"Processor.h" +"SwitchToCacheMode.c" +"IpfCpuCore.s" +"IpfCpuCore.i" + +<endComponent> diff --git a/Core/CPU/IPF/FoundationIPF.mak b/Core/CPU/IPF/FoundationIPF.mak new file mode 100644 index 0000000..ad13ce2 --- /dev/null +++ b/Core/CPU/IPF/FoundationIPF.mak @@ -0,0 +1,66 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/EDK/IPF/FoundationIPF.mak 1 8/24/06 12:37p Felixp $ +# +# $Revision: 1 $ +# +# $Date: 8/24/06 12:37p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/EDK/IPF/FoundationIPF.mak $ +# +# 1 8/24/06 12:37p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: FoundationIPF.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +FoundationIPF : $(BUILD_DIR)\FoundationIPF.mak FoundationIPFBin + +$(BUILD_DIR)\FoundationIPF.mak : $(FoundationIPF_DIR)\$(@B).cif $(FoundationIPF_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(FoundationIPF_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +!IF "$(PROCESSOR)"=="IPF" +FoundationBin : $(BUILD_DIR)\FoundationIPF.lib +FoundationPeiBin : $(BUILD_DIR)\FoundationIPF.lib +$(BUILD_DIR)\FoundationIPF.lib : FoundationIPF +!ENDIF + + +FoundationIPFBin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\FoundationIPF.mak all\ + "CFLAGS=$(CFLAGS) /I$(Foundation_DIR)"\ + TYPE=LIBRARY +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/IPF/FoundationIPF.sdl b/Core/CPU/IPF/FoundationIPF.sdl new file mode 100644 index 0000000..32db6cc --- /dev/null +++ b/Core/CPU/IPF/FoundationIPF.sdl @@ -0,0 +1,19 @@ +TOKEN + Name = "FoundationIPF_SUPPORT" + Value = "1" + Help = "Main switch to enable FoundationIPF support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "FoundationIPF_DIR" +End + +MODULE + Help = "Includes FoundationIPF.mak to Project" + File = "FoundationIPF.mak" +End + diff --git a/Core/CPU/IPF/IpfCpuCore.i b/Core/CPU/IPF/IpfCpuCore.i new file mode 100644 index 0000000..d0c6fa2 --- /dev/null +++ b/Core/CPU/IPF/IpfCpuCore.i @@ -0,0 +1,93 @@ +//++ +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// IpfCpuCore.i +// +// Abstract: +// IPF CPU definitions +// +//-- + +#ifndef _IPF_CPU_CORE_ +#define _IPF_CPU_CORE_ + +#define PEI_BSP_STORE_SIZE 0x4000 +#define ResetFn 0x00 +#define MachineCheckFn 0x01 +#define InitFn 0x02 +#define RecoveryFn 0x03 +#define GuardBand 0x10 + +// +// Define hardware RSE Configuration Register +// + +// +// RS Configuration (RSC) bit field positions +// +#define RSC_MODE 0 +#define RSC_PL 2 +#define RSC_BE 4 +// +// RSC bits 5-15 reserved +// +#define RSC_MBZ0 5 +#define RSC_MBZ0_V 0x3ff +#define RSC_LOADRS 16 +#define RSC_LOADRS_LEN 14 +// +// RSC bits 30-63 reserved +// +#define RSC_MBZ1 30 +#define RSC_MBZ1_V 0x3ffffffffULL + +// +// RSC modes +// + +// +// Lazy +// +#define RSC_MODE_LY (0x0) +// +// Store intensive +// +#define RSC_MODE_SI (0x1) +// +// Load intensive +// +#define RSC_MODE_LI (0x2) +// +// Eager +// +#define RSC_MODE_EA (0x3) + +// +// RSC Endian bit values +// +#define RSC_BE_LITTLE 0 +#define RSC_BE_BIG 1 + +// +// RSC while in kernel: enabled, little endian, pl = 0, eager mode +// +#define RSC_KERNEL ((RSC_MODE_EA<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) +// +// Lazy RSC in kernel: enabled, little endian, pl = 0, lazy mode +// +#define RSC_KERNEL_LAZ ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) +// +// RSE disabled: disabled, pl = 0, little endian, eager mode +// +#define RSC_KERNEL_DISABLED ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) + +#endif diff --git a/Core/CPU/IPF/IpfCpuCore.s b/Core/CPU/IPF/IpfCpuCore.s new file mode 100644 index 0000000..d3b7c62 --- /dev/null +++ b/Core/CPU/IPF/IpfCpuCore.s @@ -0,0 +1,196 @@ +//++ +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// IpfCpuCore.s +// +// Abstract: +// IPF Specific assembly routines +// +//-- + +.file "IpfCpuCore.s" + +#include "IpfMacro.i" +#include "IpfCpuCore.i" + +//---------------------------------------------------------------------------------- +// This module supports terminating CAR (Cache As RAM) stage. It copies all the +// CAR data into real RAM and then makes a stack switch. + +// EFI_STATUS +// SwitchCoreStacks ( +// IN VOID *EntryPoint, +// IN UINTN CopySize, +// IN VOID *OldBase, +// IN VOID *NewBase +// IN UINTN NewSP, OPTIONAL +// IN UINTN NewBSP OPTIONAL +// ) +// EFI_STATUS +// SwitchCoreStacks ( +// IN VOID *EntryPointForContinuationFunction, +// IN UINTN StartupDescriptor, +// IN VOID PEICorePointer, +// IN UINTN NewSP +// ) +//---------------------------------------------------------------------------------- +PROCEDURE_ENTRY (SwitchCoreStacks) + + NESTED_SETUP (4,2,0,0) + + // first save all stack registers in GPRs. + mov r13 = in0;; // this is a pointer to the PLABEL of the continuation function. + ld8 r16 = [r13],8;; // r16 = address of continuation function from the PLABEL + ld8 gp = [r13];; // gp = gp of continuation function from the PLABEL + mov b1 = r16;; + + // save the parameters in r5, r6. these 2 seemed to be preserved across PAL calls + mov r5 = in1;; // this is the parameter1 to pass to the continuation function + mov r6 = in2;; // this is the parameter2 to pass to the continuation function + dep r6=0,r6,63,1;; // zero the bit 63. + + mov r8 = in3;; // new stack pointer. + + // r8 has the sp, this is 128K stack size, from this we will reserve 16K for the bspstore + movl r15 = PEI_BSP_STORE_SIZE;; + sub r8 = r8, r15;; + add r15 = (GuardBand),r8;; // some little buffer, now r15 will be our bspstore + + // save the bspstore value to r4, save sp value to r7 + mov r4 = r15 + mov r7 = r8 + mov r16 = r8;; // will be the new sp in uncache mode + + + alloc r11=0,0,0,0;; // Set 0-size frame + flushrs;; + + mov r21 = RSC_KERNEL_DISABLED;; // for rse disable + mov ar.rsc = r21;; // turn off RSE + + add sp = r0, r16 // transfer to the EFI stack + mov ar.bspstore = r15 // switch to EFI BSP + invala // change of ar.bspstore needs invala. + + mov r19 = RSC_KERNEL_LAZ;; // RSC enabled, Lazy mode + mov ar.rsc = r19;; // turn rse on, in kernel mode + +//----------------------------------------------------------------------------------- +// Save here the meaningful stuff for next few lines and then make the PAL call. +// Make PAL call to terminate the CAR status. + // AVL: do this only for recovery check call... + + mov r28=ar.k3;; + dep r2 = r28,r0,0,8;; // Extract Function bits from GR20. + cmp.eq p6,p7 = RecoveryFn,r2;; // Is it Recovery check + (p7) br.sptk.few DoneCARTermination; // if not, don't terminate car.. + +TerminateCAR:: + + mov r28 = ip;; + add r28 = (DoneCARTerminationPALCall - TerminateCAR),r28;; + mov b0 = r28 + + mov r8 = ar.k5;; + mov b6 = r8 + mov r28 = 0x208 + + mov r29 = r0 + mov r30 = r0 + mov r31 = r0 + mov r8 = r0;; + br.sptk.few b6;; // Call PAL-A call. + +DoneCARTerminationPALCall:: + +// don't check error in soft sdv, it is always returning -1 for this call for some reason +#if SOFT_SDV +#else +ReturnToPEIMain:: + cmp.eq p6,p7 = r8,r0;; + // + // dead loop if the PAL call failed, we have the CAR on but the stack is now pointing to memory + // + (p7) br.sptk.few ReturnToPEIMain;; + // + // PAL call successed,now the stack are in memory so come into cache mode + // instead of uncache mode + // + + alloc r11=0,0,0,0;; // Set 0-size frame + flushrs;; + + mov r21 = RSC_KERNEL_DISABLED;; // for rse disable + mov ar.rsc = r21;; // turn off RSE + + dep r6 = 0,r6,63,1 // zero the bit 63 + dep r7 = 0,r7,63,1 // zero the bit 63 + dep r4 = 0,r4,63,1;; // zero the bit 63 + add sp = r0, r7 // transfer to the EFI stack in cache mode + mov ar.bspstore = r4 // switch to EFI BSP + invala // change of ar.bspstore needs invala. + + mov r19 = RSC_KERNEL_LAZ;; // RSC enabled, Lazy mode + mov ar.rsc = r19;; // turn rse on, in kernel mode + +#endif + +DoneCARTermination:: + + // allocate a stack frame: + alloc r11=0,2,2,0 ;; // alloc outs going to ensuing DXE IPL service + // on the new stack + mov out0 = r5;; + mov out1 = r6;; + + mov r16 = b1;; + mov b6 = r16;; + br.call.sptk.few b0=b6;; // Call the continuation function + + NESTED_RETURN + +PROCEDURE_EXIT(SwitchCoreStacks) +//----------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------- +//++ +// GetHandOffStatus +// +// This routine is called by all processors simultaneously, to get some hand-off +// status that has been captured by IPF dispatcher and recorded in kernel registers. +// +// Arguments : +// +// On Entry : None. +// +// Return Value: Lid, R20Status. +// +//-- +//---------------------------------------------------------------------------------- +PROCEDURE_ENTRY (GetHandOffStatus) + + NESTED_SETUP (0,2+0,0,0) + + mov r8 = ar.k6 // Health Status (Self test params) + mov r9 = ar.k4 // LID bits + mov r10 = ar.k3;; // SAL_E entry state + #if (PI_SPECIFICATION_VERSION < 0x00010000) + mov r11 = ar.k7 // Return address to PAL + #else + mov r11 = ar.k1 // Return address to PAL + #endif + + NESTED_RETURN +PROCEDURE_EXIT (GetHandOffStatus) +//---------------------------------------------------------------------------------- + + diff --git a/Core/CPU/IPF/PeCoffLoaderEx.c b/Core/CPU/IPF/PeCoffLoaderEx.c new file mode 100644 index 0000000..60018ed --- /dev/null +++ b/Core/CPU/IPF/PeCoffLoaderEx.c @@ -0,0 +1,268 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#include "TianoCommon.h" +#include "EfiImage.h" + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \ + Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos) + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \ + *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \ + ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos) + +#define IMM64_IMM7B_INST_WORD_X 3 +#define IMM64_IMM7B_SIZE_X 7 +#define IMM64_IMM7B_INST_WORD_POS_X 4 +#define IMM64_IMM7B_VAL_POS_X 0 + +#define IMM64_IMM9D_INST_WORD_X 3 +#define IMM64_IMM9D_SIZE_X 9 +#define IMM64_IMM9D_INST_WORD_POS_X 18 +#define IMM64_IMM9D_VAL_POS_X 7 + +#define IMM64_IMM5C_INST_WORD_X 3 +#define IMM64_IMM5C_SIZE_X 5 +#define IMM64_IMM5C_INST_WORD_POS_X 13 +#define IMM64_IMM5C_VAL_POS_X 16 + +#define IMM64_IC_INST_WORD_X 3 +#define IMM64_IC_SIZE_X 1 +#define IMM64_IC_INST_WORD_POS_X 12 +#define IMM64_IC_VAL_POS_X 21 + +#define IMM64_IMM41a_INST_WORD_X 1 +#define IMM64_IMM41a_SIZE_X 10 +#define IMM64_IMM41a_INST_WORD_POS_X 14 +#define IMM64_IMM41a_VAL_POS_X 22 + +#define IMM64_IMM41b_INST_WORD_X 1 +#define IMM64_IMM41b_SIZE_X 8 +#define IMM64_IMM41b_INST_WORD_POS_X 24 +#define IMM64_IMM41b_VAL_POS_X 32 + +#define IMM64_IMM41c_INST_WORD_X 2 +#define IMM64_IMM41c_SIZE_X 23 +#define IMM64_IMM41c_INST_WORD_POS_X 0 +#define IMM64_IMM41c_VAL_POS_X 40 + +#define IMM64_SIGN_INST_WORD_X 3 +#define IMM64_SIGN_SIZE_X 1 +#define IMM64_SIGN_INST_WORD_POS_X 27 +#define IMM64_SIGN_VAL_POS_X 63 + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +{ + UINT64 *F64; + UINT64 FixupVal; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_IA64_IMM64: + + // + // Align it to bundle address before fixing up the + // 64-bit immediate value of the movl instruction. + // + + Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); + FixupVal = (UINT64)0; + + // + // Extract the lower 32 bits of IMM64 from bundle + // + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X, + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + // + // Update 64-bit address + // + FixupVal += Adjust; + + // + // Insert IMM64 into bundle + // + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X), + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X), + IMM64_IMM41b_SIZE_X, + IMM64_IMM41b_INST_WORD_POS_X, + IMM64_IMM41b_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X), + IMM64_IMM41c_SIZE_X, + IMM64_IMM41c_INST_WORD_POS_X, + IMM64_IMM41c_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), + IMM64_SIGN_SIZE_X, + IMM64_SIGN_INST_WORD_POS_X, + IMM64_SIGN_VAL_POS_X + ); + + F64 = (UINT64 *) Fixup; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IPF, EBC, + images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +{ + if ((Machine == EFI_IMAGE_MACHINE_IA64) || (Machine == EFI_IMAGE_MACHINE_EBC)) { + return TRUE; + } + + return FALSE; +} diff --git a/Core/CPU/IPF/PeCoffLoaderEx.h b/Core/CPU/IPF/PeCoffLoaderEx.h new file mode 100644 index 0000000..fc14551 --- /dev/null +++ b/Core/CPU/IPF/PeCoffLoaderEx.h @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PeCoffLoaderEx.h + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +; + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IPF, EBC, + images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +; + +#endif diff --git a/Core/CPU/IPF/PerformancePrimitives.s b/Core/CPU/IPF/PerformancePrimitives.s new file mode 100644 index 0000000..5aeb886 --- /dev/null +++ b/Core/CPU/IPF/PerformancePrimitives.s @@ -0,0 +1,61 @@ +//++ +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// PerformancePrimitives.s +// +// Abstract: +// +// +// Revision History: +// +//-- + +.file "PerformancePrimitives.s" + +#include "IpfMacro.i" + +//----------------------------------------------------------------------------- +//++ +// GetTimerValue +// +// Implementation of CPU-based time service +// +// On Entry : +// EFI_STATUS +// GetTimerValue ( +// OUT UINT64 *TimerValue +// ) +// +// Return Value: +// r8 = Status +// r9 = 0 +// r10 = 0 +// r11 = 0 +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY (GetTimerValue) + + NESTED_SETUP (1,8,0,0) + mov r8 = ar.itc;; + st8 [r32]= r8 + mov r8 = r0 + mov r9 = r0 + mov r10 = r0 + mov r11 = r0 + NESTED_RETURN + +PROCEDURE_EXIT (GetTimerValue) +//--------------------------------------------------------------------------- + diff --git a/Core/CPU/IPF/Processor.h b/Core/CPU/IPF/Processor.h new file mode 100644 index 0000000..8e49d37 --- /dev/null +++ b/Core/CPU/IPF/Processor.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + Processor.h + +Abstract: + This file contains the Ipf processor specific definitions + +--*/ + +#ifndef _PROCESSOR_H_ +#define _PROCESSOR_H_ + +#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE * 2) + +#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE * 2) + +#endif
\ No newline at end of file diff --git a/Core/CPU/IPF/SwitchStack.s b/Core/CPU/IPF/SwitchStack.s new file mode 100644 index 0000000..5de7e18 --- /dev/null +++ b/Core/CPU/IPF/SwitchStack.s @@ -0,0 +1,122 @@ +//++ +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// SwitchStack.s +// +// Abstract: +// +// Contains an implementation of a stack switch for the Itanium-based architecture. +// +// +// +// Revision History: +// +//-- + + .file "SwitchStack.s" + +#include <asm.h> +#include <ia_64gen.h> + +// Define hardware RSE Configuration Register +// +// RS Configuration (RSC) bit field positions + +#define RSC_MODE 0 +#define RSC_PL 2 +#define RSC_BE 4 +// RSC bits 5-15 reserved +#define RSC_MBZ0 5 +#define RSC_MBZ0_V 0x3ff +#define RSC_LOADRS 16 +#define RSC_LOADRS_LEN 14 +// RSC bits 30-63 reserved +#define RSC_MBZ1 30 +#define RSC_MBZ1_V 0x3ffffffffULL + +// RSC modes +// Lazy +#define RSC_MODE_LY (0x0) +// Store intensive +#define RSC_MODE_SI (0x1) +// Load intensive +#define RSC_MODE_LI (0x2) +// Eager +#define RSC_MODE_EA (0x3) + +// RSC Endian bit values +#define RSC_BE_LITTLE 0 +#define RSC_BE_BIG 1 + +// RSC while in kernel: enabled, little endian, pl = 0, eager mode +#define RSC_KERNEL ((RSC_MODE_EA<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) +// Lazy RSC in kernel: enabled, little endian, pl = 0, lazy mode +#define RSC_KERNEL_LAZ ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) +// RSE disabled: disabled, pl = 0, little endian, eager mode +#define RSC_KERNEL_DISABLED ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) + + +//VOID +//SwitchStacks ( +// VOID *ContinuationFunction, +// UINTN Parameter, +// UINTN NewTopOfStack, +// UINTN NewBSPStore OPTIONAL +//) +///*++ +// +//Input Arguments +// +// ContinuationFunction - This is a pointer to the PLABEL of the function that should be called once the +// new stack has been created. +// Parameter - The parameter to pass to the continuation function +// NewTopOfStack - This is the new top of the memory stack for ensuing code. This is mandatory and +// should be non-zero +// NewBSPStore - This is the new BSP store for the ensuing code. It is optional on IA-32 and mandatory on Itanium-based platform. +// +//--*/ + +PROCEDURE_ENTRY(SwitchStacks) + + mov r16 = -0x10;; + and r16 = r34, r16;; // get new stack value in R16, 0 the last nibble. + mov r15 = r35;; // Get new BspStore into R15 + mov r13 = r32;; // this is a pointer to the PLABEL of the continuation function. + mov r17 = r33;; // this is the parameter to pass to the continuation function + + alloc r11=0,0,0,0 // Set 0-size frame + ;; + flushrs;; + + mov r21 = RSC_KERNEL_DISABLED // for rse disable + ;; + mov ar.rsc = r21 // turn off RSE + + add sp = r0, r16;; // transfer to the EFI stack + mov ar.bspstore = r15 // switch to EFI BSP + invala // change of ar.bspstore needs invala. + + mov r18 = RSC_KERNEL_LAZ // RSC enabled, Lazy mode + ;; + mov ar.rsc = r18 // turn rse on, in kernel mode + ;; + alloc r11=0,0,1,0;; // alloc 0 outs going to ensuing DXE IPL service + mov out0 = r17 + ld8 r16 = [r13],8;; // r16 = address of continuation function from the PLABEL + ld8 gp = [r13] // gp = gp of continuation function from the PLABEL + mov b6 = r16 + ;; + br.call.sptk.few b0=b6;; // Call the continuation function + ;; +PROCEDURE_EXIT(SwitchStacks) + + diff --git a/Core/CPU/IPF/SwitchToCacheMode.c b/Core/CPU/IPF/SwitchToCacheMode.c new file mode 100644 index 0000000..9f938d4 --- /dev/null +++ b/Core/CPU/IPF/SwitchToCacheMode.c @@ -0,0 +1,77 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + SwitchToCacheMode.c + +Abstract: + + Ipf CAR specific function used to switch to cache mode for the later memory access + +Revision History + +--*/ +#include "Tiano.h" +#include "PeiCore.h" +#include "IpfCpuCore.i" + +extern +SAL_RETURN_REGS +GetHandOffStatus ( + VOID + ); + +VOID +SwitchToCacheMode ( + IN PEI_CORE_INSTANCE *CoreData + ) +/*++ + +Routine Description: + + Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR. + +Arguments: + + CoreData - The PEI core Private Data + +Returns: + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *Phit; + + if (CoreData == NULL) { + // + // the first call with CoreData as NULL. + // + return; + } + + if ((GetHandOffStatus().r10 & 0xFF) == RecoveryFn) { + CoreData->StackBase = CoreData->StackBase & CACHE_MODE_ADDRESS_MASK; + CoreData->HobList.Raw = (UINT8 *)((UINTN)CoreData->HobList.Raw & CACHE_MODE_ADDRESS_MASK); + + // + // Change the PHIT pointer value to cache mode + // + Phit = CoreData->HobList.HandoffInformationTable; + + Phit->EfiMemoryTop = Phit->EfiMemoryTop & CACHE_MODE_ADDRESS_MASK; + Phit->EfiFreeMemoryTop = Phit->EfiFreeMemoryTop & CACHE_MODE_ADDRESS_MASK; + Phit->EfiMemoryBottom = Phit->EfiMemoryBottom & CACHE_MODE_ADDRESS_MASK; + Phit->EfiFreeMemoryBottom = Phit->EfiFreeMemoryBottom & CACHE_MODE_ADDRESS_MASK; + Phit->EfiEndOfHobList = Phit->EfiEndOfHobList & CACHE_MODE_ADDRESS_MASK; + } + + return; +}
\ No newline at end of file diff --git a/Core/CPU/IPF/asm.h b/Core/CPU/IPF/asm.h new file mode 100644 index 0000000..2db93d6 --- /dev/null +++ b/Core/CPU/IPF/asm.h @@ -0,0 +1,35 @@ +// +// +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// asm.h +// +// Abstract: +// +// This module contains generic macros for an assembly writer. +// +// +// Revision History +// +#ifndef _ASM_H +#define _ASM_H + +#define TRUE 1 +#define FALSE 0 +#define PROCEDURE_ENTRY(name) .##text; \ + .##type name, @function; \ + .##proc name; \ + name:: + +#define PROCEDURE_EXIT(name) .##endp name + +#endif // _ASM_H diff --git a/Core/CPU/IPF/efijump.h b/Core/CPU/IPF/efijump.h new file mode 100644 index 0000000..4a078ce --- /dev/null +++ b/Core/CPU/IPF/efijump.h @@ -0,0 +1,112 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiJump.h + +Abstract: + + This is the Setjump/Longjump pair for an IA32 processor. + +--*/ + +#ifndef _EFI_JUMP_H_ +#define _EFI_JUMP_H_ + +#include EFI_GUID_DEFINITION (PeiTransferControl) + +// +// NOTE:Set/LongJump needs to have this buffer start +// at 16 byte boundary. Either fix the structure +// which call this buffer or fix inside SetJump/LongJump +// Choosing 1K buffer storage for now +// +typedef struct { + CHAR8 Buffer[1024]; +} EFI_JUMP_BUFFER; + +EFI_STATUS +SetJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ) +/*++ + +Routine Description: + + SetJump stores the current register set in the area pointed to +by "save". It returns zero. Subsequent calls to "LongJump" will +restore the registers and return non-zero to the same location. + On entry, r32 contains the pointer to the jmp_buffer + +Arguments: + + This - Calling context + Jump - Jump buffer + +Returns: + + Status code + +--*/ +; + +EFI_STATUS +LongJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ) +/*++ + +Routine Description: + + LongJump initializes the register set to the values saved by a +previous 'SetJump' and jumps to the return location saved by that +'SetJump'. This has the effect of unwinding the stack and returning +for a second time to the 'SetJump'. + +Arguments: + + This - Calling context + Jump - Jump buffer + +Returns: + + Status code + +--*/ +; + +VOID +RtPioICacheFlush ( + IN VOID *StartAddress, + IN UINTN SizeInBytes + ) +/*++ + +Routine Description: + + Flushing the CPU instruction cache. + +Arguments: + + StartAddress - Start address to flush + SizeInBytes - Length in bytes to flush + +Returns: + + None + +--*/ +; + +#endif diff --git a/Core/CPU/IPF/ia_64gen.h b/Core/CPU/IPF/ia_64gen.h new file mode 100644 index 0000000..8e8d1a5 --- /dev/null +++ b/Core/CPU/IPF/ia_64gen.h @@ -0,0 +1,214 @@ +// +// +// +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//Module Name: ia_64gen.h +// +// +//Abstract: +// +// +// +// +//Revision History +// +// +#ifndef _IA64GEN_H +#define _IA64GEN_H + +#define TT_UNAT 0 +#define C_PSR 0 +#define J_UNAT 0 +#define T_TYPE 0 +#define T_IPSR 0x8 +#define T_ISR 0x10 +#define T_IIP 0x18 +#define T_IFA 0x20 +#define T_IIPA 0x28 +#define T_IFS 0x30 +#define T_IIM 0x38 +#define T_RSC 0x40 +#define T_BSP 0x48 +#define T_BSPSTORE 0x50 +#define T_RNAT 0x58 +#define T_PFS 0x60 +#define T_KBSPSTORE 0x68 +#define T_UNAT 0x70 +#define T_CCV 0x78 +#define T_DCR 0x80 +#define T_PREDS 0x88 +#define T_NATS 0x90 +#define T_R1 0x98 +#define T_GP 0x98 +#define T_R2 0xa0 +#define T_R3 0xa8 +#define T_R4 0xb0 +#define T_R5 0xb8 +#define T_R6 0xc0 +#define T_R7 0xc8 +#define T_R8 0xd0 +#define T_R9 0xd8 +#define T_R10 0xe0 +#define T_R11 0xe8 +#define T_R12 0xf0 +#define T_SP 0xf0 +#define T_R13 0xf8 +#define T_R14 0x100 +#define T_R15 0x108 +#define T_R16 0x110 +#define T_R17 0x118 +#define T_R18 0x120 +#define T_R19 0x128 +#define T_R20 0x130 +#define T_R21 0x138 +#define T_R22 0x140 +#define T_R23 0x148 +#define T_R24 0x150 +#define T_R25 0x158 +#define T_R26 0x160 +#define T_R27 0x168 +#define T_R28 0x170 +#define T_R29 0x178 +#define T_R30 0x180 +#define T_R31 0x188 +#define T_F2 0x1f0 +#define T_F3 0x200 +#define T_F4 0x210 +#define T_F5 0x220 +#define T_F6 0x230 +#define T_F7 0x240 +#define T_F8 0x250 +#define T_F9 0x260 +#define T_F10 0x270 +#define T_F11 0x280 +#define T_F12 0x290 +#define T_F13 0x2a0 +#define T_F14 0x2b0 +#define T_F15 0x2c0 +#define T_F16 0x2d0 +#define T_F17 0x2e0 +#define T_F18 0x2f0 +#define T_F19 0x300 +#define T_F20 0x310 +#define T_F21 0x320 +#define T_F22 0x330 +#define T_F23 0x340 +#define T_F24 0x350 +#define T_F25 0x360 +#define T_F26 0x370 +#define T_F27 0x380 +#define T_F28 0x390 +#define T_F29 0x3a0 +#define T_F30 0x3b0 +#define T_F31 0x3c0 +#define T_FPSR 0x1e0 +#define T_B0 0x190 +#define T_B1 0x198 +#define T_B2 0x1a0 +#define T_B3 0x1a8 +#define T_B4 0x1b0 +#define T_B5 0x1b8 +#define T_B6 0x1c0 +#define T_B7 0x1c8 +#define T_EC 0x1d0 +#define T_LC 0x1d8 +#define J_NATS 0x8 +#define J_PFS 0x10 +#define J_BSP 0x18 +#define J_RNAT 0x20 +#define J_PREDS 0x28 +#define J_LC 0x30 +#define J_R4 0x38 +#define J_R5 0x40 +#define J_R6 0x48 +#define J_R7 0x50 +#define J_SP 0x58 +#define J_F2 0x60 +#define J_F3 0x70 +#define J_F4 0x80 +#define J_F5 0x90 +#define J_F16 0xa0 +#define J_F17 0xb0 +#define J_F18 0xc0 +#define J_F19 0xd0 +#define J_F20 0xe0 +#define J_F21 0xf0 +#define J_F22 0x100 +#define J_F23 0x110 +#define J_F24 0x120 +#define J_F25 0x130 +#define J_F26 0x140 +#define J_F27 0x150 +#define J_F28 0x160 +#define J_F29 0x170 +#define J_F30 0x180 +#define J_F31 0x190 +#define J_FPSR 0x1a0 +#define J_B0 0x1a8 +#define J_B1 0x1b0 +#define J_B2 0x1b8 +#define J_B3 0x1c0 +#define J_B4 0x1c8 +#define J_B5 0x1d0 +#define TRAP_FRAME_LENGTH 0x3d0 +#define C_UNAT 0x28 +#define C_NATS 0x30 +#define C_PFS 0x8 +#define C_BSPSTORE 0x10 +#define C_RNAT 0x18 +#define C_RSC 0x20 +#define C_PREDS 0x38 +#define C_LC 0x40 +#define C_DCR 0x48 +#define C_R1 0x50 +#define C_GP 0x50 +#define C_R4 0x58 +#define C_R5 0x60 +#define C_R6 0x68 +#define C_R7 0x70 +#define C_SP 0x78 +#define C_R13 0x80 +#define C_F2 0x90 +#define C_F3 0xa0 +#define C_F4 0xb0 +#define C_F5 0xc0 +#define C_F16 0xd0 +#define C_F17 0xe0 +#define C_F18 0xf0 +#define C_F19 0x100 +#define C_F20 0x110 +#define C_F21 0x120 +#define C_F22 0x130 +#define C_F23 0x140 +#define C_F24 0x150 +#define C_F25 0x160 +#define C_F26 0x170 +#define C_F27 0x180 +#define C_F28 0x190 +#define C_F29 0x1a0 +#define C_F30 0x1b0 +#define C_F31 0x1c0 +#define C_FPSR 0x1d0 +#define C_B0 0x1d8 +#define C_B1 0x1e0 +#define C_B2 0x1e8 +#define C_B3 0x1f0 +#define C_B4 0x1f8 +#define C_B5 0x200 +#define TT_R2 0x8 +#define TT_R3 0x10 +#define TT_R8 0x18 +#define TT_R9 0x20 +#define TT_R10 0x28 +#define TT_R11 0x30 +#define TT_R14 0x38 + +#endif _IA64GEN_H diff --git a/Core/CPU/IPF/pioflush.s b/Core/CPU/IPF/pioflush.s new file mode 100644 index 0000000..0f0d760 --- /dev/null +++ b/Core/CPU/IPF/pioflush.s @@ -0,0 +1,106 @@ +//++ +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// pioflush.s +// +// Abstract: +// +// +// Revision History: +// +//-- + + .file "pioflush.c" + .radix D + .section .text, "ax", "progbits" + .align 32 + .section .pdata, "a", "progbits" + .align 4 + .section .xdata, "a", "progbits" + .align 8 + .section .data, "wa", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .bss, "wa", "nobits" + .align 16 + .section .tls$, "was", "progbits" + .align 16 + .section .sdata, "was", "progbits" + .align 16 + .section .sbss, "was", "nobits" + .align 16 + .section .srdata, "as", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .rtcode, "ax", "progbits" + .align 32 + .type RtPioICacheFlush# ,@function + .global RtPioICacheFlush# +// Function compile flags: /Ogsy + .section .rtcode + +// Begin code for function: RtPioICacheFlush: + .proc RtPioICacheFlush# + .align 32 +RtPioICacheFlush: +// File e:\tmp\pioflush.c + { .mii //R-Addr: 0X00 + alloc r3=2, 0, 0, 0 //11, 00000002H + cmp4.leu p0,p6=32, r33;; //15, 00000020H + (p6) mov r33=32;; //16, 00000020H + } + { .mii //R-Addr: 0X010 + nop.m 0 + zxt4 r29=r33;; //21 + dep.z r30=r29, 0, 5;; //21, 00000005H + } + { .mii //R-Addr: 0X020 + cmp4.eq p0,p7=r0, r30 //21 + shr.u r28=r29, 5;; //19, 00000005H + (p7) adds r28=1, r28;; //22, 00000001H + } + { .mii //R-Addr: 0X030 + nop.m 0 + shl r27=r28, 5;; //25, 00000005H + zxt4 r26=r27;; //25 + } + { .mfb //R-Addr: 0X040 + add r31=r26, r32 //25 + nop.f 0 + nop.b 0 + } +$L143: + { .mii //R-Addr: 0X050 + fc r32 //27 + adds r32=32, r32;; //28, 00000020H + cmp.ltu p14,p15=r32, r31 //29 + } + { .mfb //R-Addr: 0X060 + nop.m 0 + nop.f 0 + (p14) br.cond.dptk.few $L143#;; //29, 880000/120000 + } + { .mmi + sync.i;; + srlz.i + nop.i 0;; + } + { .mfb //R-Addr: 0X070 + nop.m 0 + nop.f 0 + br.ret.sptk.few b0;; //31 + } +// End code for function: + .endp RtPioICacheFlush# +// END diff --git a/Core/CPU/IPF/processor.c b/Core/CPU/IPF/processor.c new file mode 100644 index 0000000..9740948 --- /dev/null +++ b/Core/CPU/IPF/processor.c @@ -0,0 +1,118 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include "PeiHob.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +EFI_STATUS +WinNtFlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + SetJump, + LongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + WinNtFlushInstructionCacheFlush +}; + +EFI_STATUS +InstallEfiPeiTransferControl ( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed. + +--*/ +{ + *This = &mTransferControl; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed + +--*/ +{ + *This = &mFlushInstructionCache; + return EFI_SUCCESS; +} + +EFI_STATUS +WinNtFlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + +Arguments: + + This - Pointer to CPU Architectural Protocol interface + Start - Start adddress in memory to flush + Length - Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + RtPioICacheFlush ((UINT8 *) Start, (UINTN) Length); + return EFI_SUCCESS; +} diff --git a/Core/CPU/IPF/setjmp.s b/Core/CPU/IPF/setjmp.s new file mode 100644 index 0000000..ee27ca7 --- /dev/null +++ b/Core/CPU/IPF/setjmp.s @@ -0,0 +1,325 @@ +//++ +// Copyright (c) 2004, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// setjmp.s +// +// Abstract: +// +// Contains an implementation of setjmp and longjmp for the +// Itanium-based architecture. +// +// +// +// Revision History: +// +//-- + + .file "setjmp.s" + +#include <asm.h> +#include <ia_64gen.h> + +// int SetJump(struct jmp_buffer save) +// +// Setup a non-local goto. +// +// Description: +// +// SetJump stores the current register set in the area pointed to +// by "save". It returns zero. Subsequent calls to "LongJump" will +// restore the registers and return non-zero to the same location. +// +// On entry, r32 contains the pointer to the jmp_buffer +// + +PROCEDURE_ENTRY(SetJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + add r10 = J_PREDS, r32 // skip Unats & pfs save area + add r11 = J_BSP, r32 + // + // save immediate context + // + mov r2 = ar.bsp // save backing store pointer + mov r3 = pr // save predicates + ;; + // + // save user Unat register + // + mov r16 = ar.lc // save loop count register + mov r14 = ar.unat // save user Unat register + + st8 [r10] = r3, J_LC-J_PREDS + st8 [r11] = r2, J_R4-J_BSP + ;; + st8 [r10] = r16, J_R5-J_LC + st8 [r32] = r14, J_NATS // Note: Unat at the + // beginning of the save area + mov r15 = ar.pfs + ;; + // + // save preserved general registers & NaT's + // + st8.spill [r11] = r4, J_R6-J_R4 + ;; + st8.spill [r10] = r5, J_R7-J_R5 + ;; + st8.spill [r11] = r6, J_SP-J_R6 + ;; + st8.spill [r10] = r7, J_F3-J_R7 + ;; + st8.spill [r11] = sp, J_F2-J_SP + ;; + // + // save spilled Unat and pfs registers + // + mov r2 = ar.unat // save Unat register after spill + ;; + st8 [r32] = r2, J_PFS-J_NATS // save unat for spilled regs + ;; + st8 [r32] = r15 // save pfs + // + // save floating registers + // + stf.spill [r11] = f2, J_F4-J_F2 + stf.spill [r10] = f3, J_F5-J_F3 + ;; + stf.spill [r11] = f4, J_F16-J_F4 + stf.spill [r10] = f5, J_F17-J_F5 + ;; + stf.spill [r11] = f16, J_F18-J_F16 + stf.spill [r10] = f17, J_F19-J_F17 + ;; + stf.spill [r11] = f18, J_F20-J_F18 + stf.spill [r10] = f19, J_F21-J_F19 + ;; + stf.spill [r11] = f20, J_F22-J_F20 + stf.spill [r10] = f21, J_F23-J_F21 + ;; + stf.spill [r11] = f22, J_F24-J_F22 + stf.spill [r10] = f23, J_F25-J_F23 + ;; + stf.spill [r11] = f24, J_F26-J_F24 + stf.spill [r10] = f25, J_F27-J_F25 + ;; + stf.spill [r11] = f26, J_F28-J_F26 + stf.spill [r10] = f27, J_F29-J_F27 + ;; + stf.spill [r11] = f28, J_F30-J_F28 + stf.spill [r10] = f29, J_F31-J_F29 + ;; + stf.spill [r11] = f30, J_FPSR-J_F30 + stf.spill [r10] = f31, J_B0-J_F31 // size of f31 + fpsr + // + // save FPSR register & branch registers + // + mov r2 = ar.fpsr // save fpsr register + mov r3 = b0 + ;; + st8 [r11] = r2, J_B1-J_FPSR + st8 [r10] = r3, J_B2-J_B0 + mov r2 = b1 + mov r3 = b2 + ;; + st8 [r11] = r2, J_B3-J_B1 + st8 [r10] = r3, J_B4-J_B2 + mov r2 = b3 + mov r3 = b4 + ;; + st8 [r11] = r2, J_B5-J_B3 + st8 [r10] = r3 + mov r2 = b5 + ;; + st8 [r11] = r2 + ;; + // + // return + // + mov r8 = r0 // return 0 from setjmp + mov ar.unat = r14 // restore unat + br.ret.sptk b0 + +PROCEDURE_EXIT(SetJump) + + +// +// void LongJump(struct jmp_buffer *) +// +// Perform a non-local goto. +// +// Description: +// +// LongJump initializes the register set to the values saved by a +// previous 'SetJump' and jumps to the return location saved by that +// 'SetJump'. This has the effect of unwinding the stack and returning +// for a second time to the 'SetJump'. +// + +PROCEDURE_ENTRY(LongJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + // + // caching the return value as we do invala in the end + // +/// mov r8 = r33 // return value + mov r8 = 1 // For now return hard coded 1 + + // + // get immediate context + // + mov r14 = ar.rsc // get user RSC conf + add r10 = J_PFS, r32 // get address of pfs + add r11 = J_NATS, r32 + ;; + ld8 r15 = [r10], J_BSP-J_PFS // get pfs + ld8 r2 = [r11], J_LC-J_NATS // get unat for spilled regs + ;; + mov ar.unat = r2 + ;; + ld8 r16 = [r10], J_PREDS-J_BSP // get backing store pointer + mov ar.rsc = r0 // put RSE in enforced lazy + mov ar.pfs = r15 + ;; + + // + // while returning from longjmp the BSPSTORE and BSP needs to be + // same and discard all the registers allocated after we did + // setjmp. Also, we need to generate the RNAT register since we + // did not flushed the RSE on setjmp. + // + mov r17 = ar.bspstore // get current BSPSTORE + ;; + cmp.ltu p6,p7 = r17, r16 // is it less than BSP of +(p6) br.spnt.few .flush_rse + mov r19 = ar.rnat // get current RNAT + ;; + loadrs // invalidate dirty regs + br.sptk.many .restore_rnat // restore RNAT + +.flush_rse: + flushrs + ;; + mov r19 = ar.rnat // get current RNAT + mov r17 = r16 // current BSPSTORE + ;; +.restore_rnat: + // + // check if RNAT is saved between saved BSP and curr BSPSTORE + // + dep r18 = 1,r16,3,6 // get RNAT address + ;; + cmp.ltu p8,p9 = r18, r17 // RNAT saved on RSE + ;; +(p8) ld8 r19 = [r18] // get RNAT from RSE + ;; + mov ar.bspstore = r16 // set new BSPSTORE + ;; + mov ar.rnat = r19 // restore RNAT + mov ar.rsc = r14 // restore RSC conf + + + ld8 r3 = [r11], J_R4-J_LC // get lc register + ld8 r2 = [r10], J_R5-J_PREDS // get predicates + ;; + mov pr = r2, -1 + mov ar.lc = r3 + // + // restore preserved general registers & NaT's + // + ld8.fill r4 = [r11], J_R6-J_R4 + ;; + ld8.fill r5 = [r10], J_R7-J_R5 + ld8.fill r6 = [r11], J_SP-J_R6 + ;; + ld8.fill r7 = [r10], J_F2-J_R7 + ld8.fill sp = [r11], J_F3-J_SP + ;; + // + // restore floating registers + // + ldf.fill f2 = [r10], J_F4-J_F2 + ldf.fill f3 = [r11], J_F5-J_F3 + ;; + ldf.fill f4 = [r10], J_F16-J_F4 + ldf.fill f5 = [r11], J_F17-J_F5 + ;; + ldf.fill f16 = [r10], J_F18-J_F16 + ldf.fill f17 = [r11], J_F19-J_F17 + ;; + ldf.fill f18 = [r10], J_F20-J_F18 + ldf.fill f19 = [r11], J_F21-J_F19 + ;; + ldf.fill f20 = [r10], J_F22-J_F20 + ldf.fill f21 = [r11], J_F23-J_F21 + ;; + ldf.fill f22 = [r10], J_F24-J_F22 + ldf.fill f23 = [r11], J_F25-J_F23 + ;; + ldf.fill f24 = [r10], J_F26-J_F24 + ldf.fill f25 = [r11], J_F27-J_F25 + ;; + ldf.fill f26 = [r10], J_F28-J_F26 + ldf.fill f27 = [r11], J_F29-J_F27 + ;; + ldf.fill f28 = [r10], J_F30-J_F28 + ldf.fill f29 = [r11], J_F31-J_F29 + ;; + ldf.fill f30 = [r10], J_FPSR-J_F30 + ldf.fill f31 = [r11], J_B0-J_F31 ;; + + // + // restore branch registers and fpsr + // + ld8 r16 = [r10], J_B1-J_FPSR // get fpsr + ld8 r17 = [r11], J_B2-J_B0 // get return pointer + ;; + mov ar.fpsr = r16 + mov b0 = r17 + ld8 r2 = [r10], J_B3-J_B1 + ld8 r3 = [r11], J_B4-J_B2 + ;; + mov b1 = r2 + mov b2 = r3 + ld8 r2 = [r10], J_B5-J_B3 + ld8 r3 = [r11] + ;; + mov b3 = r2 + mov b4 = r3 + ld8 r2 = [r10] + ld8 r21 = [r32] // get user unat + ;; + mov b5 = r2 + mov ar.unat = r21 + + // + // invalidate ALAT + // + invala ;; + + br.ret.sptk b0 +PROCEDURE_EXIT(LongJump) + + diff --git a/Core/CPU/MBIOSMAC.MAC b/Core/CPU/MBIOSMAC.MAC new file mode 100644 index 0000000..5fe3105 --- /dev/null +++ b/Core/CPU/MBIOSMAC.MAC @@ -0,0 +1,512 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1987-2013, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;*****************************************************************; +; $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MBIOSMAC.MAC 1 2/07/12 3:58a Davidhsieh $ +; +; $Revision: 1 $ +; +; $Date: 2/07/12 3:58a $ +;*****************************************************************; +;*****************************************************************; +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MBIOSMAC.MAC $ +; +; 1 2/07/12 3:58a Davidhsieh +; +; +;*****************************************************************; + +;<AMI_FHDR_START> +;---------------------------------------------------------------------------- +; +; Name: MBIOSMAC.MAC +; +; Description: Assembly Macros +; +;---------------------------------------------------------------------------- +;<AMI_FHDR_END> + + +ifndef _mbiosmac_mac_ +_mbiosmac_mac_ equ 1 +.xlist + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEXTERN_NEAR +; +; Description: External Near macro +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEXTERN_NEAR MACRO LabelName + + EXTERN LabelName:NEAR ; Define the label as a NEAR EXTERN. + +ENDM + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEXTERN_NEAR32 +; +; Description: External Near 32 Macro +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEXTERN_NEAR32 MACRO LabelName + + EXTERN LabelName:NEAR32 ; Define the label as a NEAR EXTERN. + +ENDM + + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEXTERN_FAR +; +; Description: External Far macro +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEXTERN_FAR MACRO LabelName + + EXTERN LabelName:FAR ; Define the label as a FAR EXTERN. + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mSTART_PROC_NEAR +; +; Description: Start Near procedure macro. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mSTART_PROC_NEAR MACRO LabelName + +LabelName PROC NEAR PUBLIC + +ENDM + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mSTART_PROC_NEAR32 +; +; Description: Start Near 32-bit procedure macro. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mSTART_PROC_NEAR32 MACRO LabelName + +LabelName PROC NEAR32 PUBLIC + +ENDM + + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_CALL_PROC_NEAR +; +; Description: Call near macro. +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_CALL_PROC_NEAR MACRO LabelID, LabelName + + call LabelName + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_JMP_PROC_NEAR +; +; Description: Jump Near Macro. Provide a return label to jump to. +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_JMP_PROC_NEAR MACRO LabelID, LabelName + + jmp LabelName + PUBLIC LabelName&End +LabelName&End:: + +ENDM + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_JMP_PROC_NEAR32 +; +; Description: Jump near 32-bit macro. Provide a return label to jump to. +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_JMP_PROC_NEAR32 MACRO LabelID, LabelName + + jmp LabelName + PUBLIC LabelName&End +LabelName&End:: + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEND_PROC_NEAR +; +; Description: End near procedure macro. Last in a group. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEND_PROC_NEAR MACRO LabelName + + ret +LabelName ENDP + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEND_PROC_WITH_JMP_NEAR +; +; Description: End of procedure and jump near macro. Last procedure in a group. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEND_PROC_WITH_JMP_NEAR MACRO LabelName + + EXTERN LabelName&End:NEAR + jmp LabelName&End +LabelName ENDP + +ENDM + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEND_PROC_WITH_JMP_NEAR32 +; +; Description: Jump Near 32-bit macro. Last macro in a group. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEND_PROC_WITH_JMP_NEAR32 MACRO LabelName + + EXTERN LabelName&End:NEAR32 + jmp LabelName&End +LabelName ENDP + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mSTART_PROC_FAR +; +; Description: Far procedure macro. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mSTART_PROC_FAR MACRO LabelName + +LabelName PROC FAR PUBLIC + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_CALL_PROC_FAR +; +; Description: Call far macro. +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_CALL_PROC_FAR MACRO LabelID, LabelName + + call LabelName + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_JMP_PROC_FAR +; +; Description: jmp far macro with return label to jump back to. +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_JMP_PROC_FAR MACRO LabelID, LabelName + + jmp LabelName + PUBLIC LabelName&End +LabelName&End:: + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEND_PROC_FAR +; +; Description: Ret procedure macro. Last in a group. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEND_PROC_FAR MACRO LabelName + + ret +LabelName ENDP + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEND_PROC_WITH_JMP_FAR +; +; Description: End procedure macro. Last in agroup. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEND_PROC_WITH_JMP_FAR MACRO LabelName + + EXTERN LabelName&End:FAR + jmp LabelName&End +LabelName ENDP + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mSTART_TBL +; +; Description: Start table macro. +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mSTART_TBL MACRO LabelName + + PUBLIC LabelName +LabelName LABEL BYTE + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_TBL_ENTRY_NEAR +; +; Description: Start table enty macro. +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_TBL_ENTRY_NEAR MACRO LabelID, LabelName + + stTblEntryNEAR <LabelName> + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_ID_AND_TBL_ENTRY_NEAR +; +; Description: Start ID Table Entry macro. +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_ID_AND_TBL_ENTRY_NEAR MACRO LabelID, LabelName + + stIDAndTblEntryNEAR <LabelID, LabelName> + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_TBL_ENTRY_FAR +; +; Description: +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_TBL_ENTRY_FAR MACRO LabelID, LabelName + + stTblEntryFAR <LabelName> + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mBODY_ID_AND_TBL_ENTRY_FAR +; +; Description: +; +; Input: +; LabelID +; LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mBODY_ID_AND_TBL_ENTRY_FAR MACRO LabelID, LabelName + + stIDAndTblEntryFAR <LabelID, LabelName> + +ENDM + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Name: mEND_TBL +; +; Description: +; +; Input: LabelName +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +mEND_TBL MACRO LabelName + + PUBLIC LabelName&End +LabelName&End LABEL BYTE + +ENDM + +.list + +endif ;_mbiosmac_mac_ + +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1987-2013, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* diff --git a/Core/CPU/MicrocodeUpdate/FwhFvb.c b/Core/CPU/MicrocodeUpdate/FwhFvb.c new file mode 100644 index 0000000..9450272 --- /dev/null +++ b/Core/CPU/MicrocodeUpdate/FwhFvb.c @@ -0,0 +1,140 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//**************************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/FwhFvb.c 1 2/07/12 3:59a Davidhsieh $ +// +// $Revision: 1 $ +// +// $Date: 2/07/12 3:59a $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/FwhFvb.c $ +// +// 1 2/07/12 3:59a Davidhsieh +// +//**************************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: FwhFvb.c +// +// Description: +// This file contains code for flash update used by the MicrocodeUpdate module. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <Efi.h> +#include "Flash.h" +#include "Token.h" + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FwhFvbErase +// +// Description: This function erases a block of NVRAM. +// +// Input: Address - Address of the block to erase +// +// Output: Return Status based on errors that occurred while erasing. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS FwhErase( + IN UINTN Address, + IN UINTN NumberOfBytes +) +{ + UINTN FlashBlockStart = BLOCK(Address); + UINTN FlashBlockEnd = BLOCK(Address + NumberOfBytes - 1); + UINTN FlashBlock; + BOOLEAN bStatus; + + FlashDeviceWriteEnable(); + + for (FlashBlock = FlashBlockStart; FlashBlock <= FlashBlockEnd; FlashBlock += FLASH_BLOCK_SIZE) { + FlashBlockWriteEnable((UINT8*)FlashBlock); + bStatus = FlashEraseBlock((UINT8*)FlashBlock); + FlashBlockWriteDisable((UINT8*)FlashBlock); + if (!bStatus) break; + } + + FlashDeviceWriteDisable(); + + return bStatus ? EFI_SUCCESS : EFI_DEVICE_ERROR; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FwhWrite +// +// Description: This function writes a block of NVRAM. +// +// Input: Address - Address of the block to write. +// Buffer - Pointer to a buffer containing data to write. +// NumberOfBytes - The number of bytes to write +// +// Output: Return Status based on errors that occurred while writing. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FwhWrite( + IN UINT8 *Buffer, + IN UINTN Address, + IN UINTN NumberOfBytes +) +{ + BOOLEAN bStatus; + UINTN FlashBlockStart = BLOCK(Address); + UINTN FlashBlockEnd = BLOCK(Address + NumberOfBytes - 1); + UINTN FlashBlock; + + FlashDeviceWriteEnable(); + + for (FlashBlock = FlashBlockStart; FlashBlock <= FlashBlockEnd; FlashBlock += FLASH_BLOCK_SIZE) { + FlashBlockWriteEnable((UINT8*)FlashBlock); + } + + + bStatus = FlashProgram((UINT8*)Address, Buffer, (UINT32)NumberOfBytes); + + + for (FlashBlock = FlashBlockStart; FlashBlock <= FlashBlockEnd; FlashBlock += FLASH_BLOCK_SIZE) { + FlashBlockWriteDisable((UINT8*)FlashBlock); + } + + FlashDeviceWriteDisable(); + + return bStatus ? EFI_SUCCESS : EFI_DEVICE_ERROR; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.c b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.c new file mode 100644 index 0000000..bc3b696 --- /dev/null +++ b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.c @@ -0,0 +1,1164 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//**************************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.c 4 4/14/15 2:48a Crystallee $ +// +// $Revision: 4 $ +// +// $Date: 4/14/15 2:48a $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.c $ +// +// 4 4/14/15 2:48a Crystallee +// +// 3 5/15/14 2:32a Crystallee +// [TAG] EIP169079 +// [Category] Improvement +// [Description] Security Enhancement for SMIHandler in Microcode update +// SWSMI. +// +// 2 10/28/12 11:23p Davidhsieh +// [TAG] EIP104874 +// [Category] Improvement +// [Description] Add signature check before search microcode ffs +// +// 1 2/07/12 3:59a Davidhsieh +// +// +//**************************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: MicrocodeUpdate.c +// +// Description: Microcode Update SMI handler. +// This file contains code for processing Interrupt 15 function +// D042h, and for registering the callback that does the processing. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <Protocol\SmmBase.h> +#include <Protocol\SmmSwDispatch.h> +#include <token.h> +#include <AmiDxeLib.h> +#include <Ffs.h> +#include <AmiCspLibInc.h> +#include "MicrocodeUpdate.h" +#include <AmiSmm.h> +#include <AmiHobs.h> + +#ifndef INT15_D042_SWSMI +#define INT15_D042_SWSMI 0x44 +#endif + +#pragma optimize("", off) + +EFI_GUID gMcodeFfsguid = + {0x17088572, 0x377F, 0x44ef, 0x8F,0x4E,0xB0,0x9F,0xFF,0x46,0xA0,0x70}; + +EFI_GUID gSwSmiCpuTriggerGuid = SW_SMI_CPU_TRIGGER_GUID; + +#if MICROCODE_SPLIT_BB_UPDATE +UINT8 *gMcodeFlashStartFixed = 0; +UINT32 gMcodeFlashSizeFixed = 0; +#endif + +UINT8 *gMcodeFlashStartUpdate = 0; +UINT32 gMcodeFlashSizeUpdate = 0; + +typedef enum { + MCODE_BLK_EMPTY = 0, + MCODE_BLK_START, + MCODE_BLK_CONT +} MCODE_BLK_TYPE; + +typedef struct { + UINT8 *Addr; + UINT32 Size; //0 if less than 64k + MCODE_BLK_TYPE Type; +} MCODE_BLK_MAP; + +UINT16 gNumMcodeBlks = 0; +UINT16 gFirstEmptyBlk = 0xffff; +MCODE_BLK_MAP *gMcodeBlkMap = NULL; + +UINT32 gCpuSignature; +UINT8 gCpuFlag; +UINT32 gUcRevision; + +SMM_HOB gSmmHob; + +#define MAX_MICROCODE_UPDATE_FUNCTIONS 4 +VOID(*MicrocodeUpdate[4])(SMI_UC_DWORD_REGS *) = { + PresenceTest, WriteUpdateData, UpdateControl, ReadUpdateData +}; + +#define MICROCODE_SIZE(Hdr) \ + (((MICROCODE_HEADER*)(Hdr))->TotalSize ? ((MICROCODE_HEADER*)Hdr)->TotalSize : 2048) + +#if PACK_MICROCODE +#define MICROCODE_ALIGN_SIZE(Hdr) \ + ((MICROCODE_SIZE(Hdr) + 16 - 1) & ~(16 - 1)) +#else +#define MICROCODE_ALIGN_SIZE(Hdr) \ + ((MICROCODE_SIZE(Hdr) + MICROCODE_BLOCK_SIZE - 1) & ~(MICROCODE_BLOCK_SIZE - 1)) +#endif + +#if PACK_MICROCODE +#define MICROCODE_BLOCKS(Hdr) \ + ((((MICROCODE_SIZE(Hdr) + MICROCODE_BLOCK_SIZE - 1) & ~(MICROCODE_BLOCK_SIZE - 1)))/MICROCODE_BLOCK_SIZE) +#else + #define MICROCODE_BLOCKS(Hdr) (MICROCODE_ALIGN_SIZE(Hdr)/MICROCODE_BLOCK_SIZE) +#endif + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CheckAddressRange +// +// Description: Check address range to avoid TSEG area. +// +// Input: +// Address - starting address +// Range - length of the area +// +// Output: +// EFI_SUCCESS - Access granted +// EFI_ACCESS_DENIED - Access denied! +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CheckAddressRange( IN UINT8 *Address, IN UINTN Range ) +{ + // Check the size and range + if ( ((EFI_PHYSICAL_ADDRESS)Address >= gSmmHob.Tseg) && + ((EFI_PHYSICAL_ADDRESS)Address <= (gSmmHob.Tseg + gSmmHob.TsegLength)) ) + return EFI_ACCESS_DENIED; + + if ( (((EFI_PHYSICAL_ADDRESS)Address + Range) >= gSmmHob.Tseg) && + (((EFI_PHYSICAL_ADDRESS)Address + Range) <= (gSmmHob.Tseg + gSmmHob.TsegLength)) ) + return EFI_ACCESS_DENIED; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsValidHeader +// +// Description: Check if the header is valid. +// +// Input: MICROCODE_HEADER *uHeader -- Address of Microcode Header. +// +// Output: BOOLEAN -- TRUE if microcode header is valid. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN IsValidHeader(MICROCODE_HEADER *uHeader) +{ + if (uHeader->HeaderVersion != UC_HEADER_VERSION) return FALSE; + if (uHeader->LoaderRevison != UC_LOADER_REVISION) return FALSE; + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsValidChecksum +// +// Description: Validate the checksum. +// +// Input: +// VOID *Microcode - Address of Microcode Header. +// UINT32 Size - Microcode Size. +// +// Output: BOOLEAN -- TRUE if checksum is valid. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN IsValidChecksum(VOID *Mcode, UINT32 Size) +{ + UINT32 NumDwords = Size >> 2; + UINT32 *p32 = (UINT32*)Mcode; + UINT32 Checksum = 0; + UINT32 i; + + for(i = 0; i < NumDwords; ++i) Checksum += p32[i]; //Checksum is the summation dwords. + + return Checksum == 0 ? TRUE : FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetInstalledMicrocodeRevision +// +// Description: Get the installed microcode revision on the cpu. +// +// Input: VOID +// +// Output: UINT32 - Revision of microcode currently installed on CPU. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 GetInstalledMicrocodeRevision() +{ + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + + //Clear IA32_BIOS_SIGN_ID of microcode loaded. + WriteMsr(0x8b, 0); //IA32_BIOS_SIGN_ID + + //Reading CPU ID 1, updates the MSR to the microcode revision. + CPULib_CpuID(1, &RegEax, &RegEbx, &RegEcx, &RegEdx); + return (UINT32) Shr64(ReadMsr(0x8b), 32); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CountBlks +// +// Description: Count blocks taken by microcode in FFS. +// +// Input: +// IN UINT8 *McodeStart - Start of microcode in FFS. +// IN UINT32 McodeSize - Size of microcode and empty space in FFS. +// IN BOOLEAN CountEmpty - TRUE if calculate blocks for empty space. +// +// Output: UINT16 - Number of blocks needed. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 CountBlks(IN UINT8 *McodeStart, IN UINT32 McodeSize, IN BOOLEAN CountEmpty) +{ + UINT8 *p = McodeStart; + UINT8 *EndOfMcode = p + McodeSize; + UINT16 TotBlks = 0; + + while(p < EndOfMcode) { + if (*(UINT32*)p != 0xffffffff && *(UINT32*)p != 0) { + TotBlks += MICROCODE_BLOCKS(p); + p += MICROCODE_ALIGN_SIZE(p); + } else if (CountEmpty) { + TotBlks += (UINT16)((EndOfMcode - p) / MICROCODE_BLOCK_SIZE); + break; + } + else break; + } + + return TotBlks; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FillMicrocodeBlkMap +// +// Description: Update gMcodeBlkMap with data for microcode. +// +// Input: +// IN OUT *BlkStart - On Input: Start update with this block. Output: Next call use this value. +// IN UINT8 *McodeStart - Start of microcode in FFS. +// IN UINT32 McodeSize - Size of microcode and empty space in FFS. +// IN BOOLEAN CountEmpty - TRUE if update blocks for empty space. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID FillMicrocodeBlkMap(IN OUT UINT16 *BlkStart, IN UINT8 *McodeStart, IN UINT32 McodeSize, IN BOOLEAN CountEmpty) +{ + UINT8 *p = McodeStart; + UINT8 *EndOfMcode = p + McodeSize; + UINT16 BlkIndex = *BlkStart; + + while(p < EndOfMcode) { + if (*(UINT32*)p != 0xffffffff && *(UINT32*)p != 0) { + UINT16 NumBlks = MICROCODE_BLOCKS(p); + UINT32 McodeSize = MICROCODE_SIZE(p); +#if PACK_MICROCODE == 0 + UINT32 PackDiff = MICROCODE_ALIGN_SIZE(p) - McodeSize; +#endif + + gMcodeBlkMap[BlkIndex].Addr = p; + gMcodeBlkMap[BlkIndex].Size = MICROCODE_BLOCK_SIZE; + gMcodeBlkMap[BlkIndex].Type = MCODE_BLK_START; + if (NumBlks <= 1 && McodeSize < MICROCODE_BLOCK_SIZE) { + gMcodeBlkMap[BlkIndex].Size = McodeSize; + } + p += gMcodeBlkMap[BlkIndex].Size; + McodeSize -= gMcodeBlkMap[BlkIndex].Size; + ++BlkIndex; + while(--NumBlks) { + gMcodeBlkMap[BlkIndex].Addr = p; + gMcodeBlkMap[BlkIndex].Size = MICROCODE_BLOCK_SIZE; + gMcodeBlkMap[BlkIndex].Type = MCODE_BLK_CONT; + if (NumBlks == 1 && McodeSize < MICROCODE_BLOCK_SIZE) { + gMcodeBlkMap[BlkIndex].Size = McodeSize; + } + p += gMcodeBlkMap[BlkIndex].Size; + McodeSize -= gMcodeBlkMap[BlkIndex].Size; + ++BlkIndex; + } +#if PACK_MICROCODE == 0 + p += PackDiff; +#endif + } else if (CountEmpty) { + gFirstEmptyBlk = BlkIndex; + while (BlkIndex < gNumMcodeBlks) { + gMcodeBlkMap[BlkIndex].Addr = p; + gMcodeBlkMap[BlkIndex].Size = MICROCODE_BLOCK_SIZE; + gMcodeBlkMap[BlkIndex].Type = MCODE_BLK_EMPTY; + BlkIndex++; + } + break; + } else break; + } + *BlkStart = BlkIndex; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitMcodeBlkMap +// +// Description: Initialize gMcodeBlkMap and related globals for all microcode FFS. +// +// Input: VOID +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID InitMcodeBlkMap() +{ + UINT16 BlkStart = 0; + + if (gMcodeBlkMap != NULL) pSmst->SmmFreePool(gMcodeBlkMap); + gNumMcodeBlks = 0; +#if MICROCODE_SPLIT_BB_UPDATE + gNumMcodeBlks += CountBlks(gMcodeFlashStartFixed, gMcodeFlashSizeFixed, FALSE); +#endif + gNumMcodeBlks += CountBlks(gMcodeFlashStartUpdate, gMcodeFlashSizeUpdate, TRUE); + + pSmst->SmmAllocatePool(0, gNumMcodeBlks * sizeof(MCODE_BLK_MAP), &gMcodeBlkMap); + + gFirstEmptyBlk = 0xffff; +#if MICROCODE_SPLIT_BB_UPDATE + FillMicrocodeBlkMap(&BlkStart, gMcodeFlashStartFixed, gMcodeFlashSizeFixed, FALSE); +#endif + FillMicrocodeBlkMap(&BlkStart, gMcodeFlashStartUpdate, gMcodeFlashSizeUpdate, TRUE); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindMicrocodeFfs +// +// Description: Find Micorode FFS in FV. +// +// Input: IN EFI_FIRMWARE_VOLUME_HEADER *FvHdr - Firmware volume to search +// +// Output: UINT8 * - Return FFS. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 *FindMicrocodeFfs(IN EFI_FIRMWARE_VOLUME_HEADER *FvHdr) +{ + UINT8 *FvPtr = (UINT8*)FvHdr + FvHdr->HeaderLength; + UINT8 *EndOfFv = (UINT8*)FvHdr + FvHdr->FvLength; + + //Check for corrupt firmware volume. + if (FvHdr->Signature != 'HVF_') return NULL; + //Search the FV_MAIN firmware volume for the microcode file. + while (FvPtr < EndOfFv && *FvPtr != -1) { + if (guidcmp(&gMcodeFfsguid, &((EFI_FFS_FILE_HEADER*)FvPtr)->Name)==0) + return FvPtr; + + FvPtr += *(UINT32*)&((EFI_FFS_FILE_HEADER*)FvPtr)->Size & 0xffffff; + FvPtr = (UINT8*)(((UINTN)FvPtr + 7) & ~7); //8 byte alignment + } + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitMicrocodeVariables +// +// Description: Initialize global variables used by the driver. +// +// Input: VOID +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN InitMicrocodeVariables() +{ + UINT8 *FfsPtr; + UINT32 McodeFfsSize; + UINT64 MsrValue; + UINT32 RegEbx, RegEcx, RegEdx; +#if MICROCODE_SPLIT_BB_UPDATE + UINT16 MPDTLengthFixed; +#endif + UINT16 MPDTLengthUpdate; + +#if MICROCODE_SPLIT_BB_UPDATE + FfsPtr = FindMicrocodeFfs((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)FV_MICROCODE_BASE); + if (FfsPtr == NULL) return FALSE; + + gMcodeFlashStartFixed = FfsPtr + sizeof(EFI_FFS_FILE_HEADER); + McodeFfsSize = ((*(UINT32*)((EFI_FFS_FILE_HEADER*)FfsPtr)->Size) & 0xffffff); +#if MPDTable_CREATED + MPDTLengthFixed = *(UINT16*)(FfsPtr + McodeFfsSize - 2); //Last 2 bytes is table size. +#else + MPDTLengthFixed = 0; +#endif + gMcodeFlashSizeFixed = McodeFfsSize - sizeof(EFI_FFS_FILE_HEADER) - MPDTLengthFixed; +#endif + +#if MICROCODE_SPLIT_BB_UPDATE + FfsPtr = FindMicrocodeFfs((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)FV_MICROCODE_UPDATE_BASE); +#else + FfsPtr = FindMicrocodeFfs((EFI_FIRMWARE_VOLUME_HEADER*)(UINTN)FV_MICROCODE_BASE); +#endif + if (FfsPtr == NULL) return FALSE; + + gMcodeFlashStartUpdate = FfsPtr + sizeof(EFI_FFS_FILE_HEADER); + McodeFfsSize = ((*(UINT32*)((EFI_FFS_FILE_HEADER*)FfsPtr)->Size) & 0xffffff); +#if MPDTable_CREATED + MPDTLengthUpdate = *(UINT16*)(FfsPtr + McodeFfsSize - 2); //Last 2 bytes is table size. +#else + MPDTLengthUpdate = 0; +#endif + gMcodeFlashSizeUpdate = McodeFfsSize - sizeof(EFI_FFS_FILE_HEADER) - MPDTLengthUpdate; + + InitMcodeBlkMap(); + + //Clear revision value. CPUID of 1 will update this revision value. + WriteMsr(0x8b, 0); //IA32_BIOS_SIGN_ID + + CPULib_CpuID(1, &gCpuSignature, &RegEbx, &RegEcx, &RegEdx); + gCpuSignature &= 0x00ffffff; + MsrValue = ReadMsr(0x17); + gCpuFlag = (UINT8)(Shr64(MsrValue, 50) & 7); //Get the CPU flags. + gUcRevision = (UINT32) Shr64(ReadMsr(0x8b), 32); //Get the current microcode revision loaded. + + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindMicrocodeOfStepping +// +// Description: Search the microcode in the firmware for the cpu signature +// or earlier steping. +// +// Input: +// UINT8 *Mcode - Address of Mcode Header. +// UINT8 *End - Mcode End. +// UINT32 CpuSignature - Signature of CPU to find. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID *FindMicrocodeOfStepping(UINT8 *Mcode, UINT8 *End, UINT32 CpuSignature) +{ + UINT8 *ptr; + for(ptr = Mcode; ptr < End; ptr += MICROCODE_ALIGN_SIZE(ptr)) { + MICROCODE_HEADER* uC = (MICROCODE_HEADER*)ptr; + + if (*(UINT32*)ptr == 0xffffffff || *(UINT32*)ptr == 0) return 0; + if (uC->CpuSignature == CpuSignature) return ptr; + + if (uC->TotalSize > (uC->DataSize + 48)) { //Extended signature count. + MICROCODE_EXT_PROC_SIG_TABLE *SigTable = (MICROCODE_EXT_PROC_SIG_TABLE*)(ptr + uC->DataSize + 48); + UINT32 ExtSigCount = SigTable->Count; + UINT8 i; + + for (i = 0; i < ExtSigCount; ++i) { + if (SigTable->ProcSig[i].CpuSignature == CpuSignature) return ptr; + } + } + } + return 0; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: LoadMicrocode +// +// Description: Load the microcode onto the CPU. +// +// Input: +// VOID *Mcode - Address of Microcode Header. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID LoadMicrocode(IN VOID *Mcode) +{ + WriteMsr(0x79, (UINT64)(UINTN)Mcode + 48); //IA32_BIOS_UPDT_TRIG +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: LoadMicrocodeEachCpu +// +// Description: Load the microcode on each CPU. +// +// Input: EFI_SMI_CPU_SAVE_STATE *CpuSaveState +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID LoadMicrocodeEachCpu(IN VOID *Mcode) +{ + UINT8 i; + //In for loop, BSP CPU will return error and continue for all APs. + for (i = 0; i < pSmst->NumberOfCpus; ++i) { + pSmst->SmmStartupThisAp(LoadMicrocode, i, Mcode); + } + LoadMicrocode(Mcode); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PresenceTest +// +// Description: Execute the presence test function for int 15h. +// +// Input: SMI_UC_DWORD_REGS *Regs +// +// Output: VOID +// +// Notes: +// +// Input: +// AX - D042h +// BL - 00h i.e., PRESCENCE_TEST +// +// Output: +// CF NC - All return values are valid +// CY - Failure, AH contains status. +// +// AH Return code +// AL Additional OEM information +// EBX Part one of the signature 'INTE'. +// ECX Part two of the signature 'LPEP'. +// EDX Version number of the BIOS update loader +// SI Number of update blocks system can record in NVRAM (1 based). +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID PresenceTest(SMI_UC_DWORD_REGS *Regs) +{ + Regs->EBX = 'INTE'; //Part 1 of the Signature + Regs->ECX = 'LPEP'; //Part 2 of the Signature. + Regs->EDX = UC_LOADER_VERSION; + + *(UINT16*)&Regs->ESI = gNumMcodeBlks; //Number of blocks. +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UpdateControl +// +// Description: Execute the update control for int 15h. +// +// Input: SMI_UC_DWORD_REGS *Regs +// +// Output: VOID +// +// Notes: +// Input: +// AX - D042h +// BL - 02h i.e., UPDATE_CONTROL +// BH - Task +// 1 - Enable the update loading at initialization time. +// 2 - Determine the current state of the update control without changing its status. +// +// Output: +// AH Return code +// AL Additional OEM information +// BL Update status Disable or Enable. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID UpdateControl(SMI_UC_DWORD_REGS *Regs) +{ + + //This is checking for a task of 0 or > 2. This is not in the specification, but in Intel code. + if ((Regs->EBX & 0xff00) == 0 || (Regs->EBX & 0x0ff00) > 0x200) { //Check BH + // Indicate we cannot determinate the Enable/Disable status via CMOS + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_READ_FAILURE; + } + + Regs->EBX = (Regs->EBX & 0xffffff00) | UC_INT15_ENABLE; // Always enabled. +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ReadUpdateData +// +// Description: Read microcode using int15h. +// +// Input: SMI_UC_DWORD_REGS *Regs +// +// Output: VOID +// +// Notes: +// +// Input: +// AX - D042h +// BL - 03h i.e., READ_UPDATE_DATA +// ES:DI - Real Mode Pointer to the Intel Update structure. +// SS:SP - Stack pointer (32K minimum) +// SI - Update number, the index number of the update block to be read. +// This number is zero based and must be less than the update +// count returned from the prescence test function. +// +// Output: +// AH Return code +// AL Additional OEM information +// BL Update status Disable or Enable. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ReadUpdateData(SMI_UC_DWORD_REGS *Regs) +{ + EFI_STATUS Status; + UINT16 Index = (UINT16)Regs->ESI; + UINT8 *UpdateBuffer; + MICROCODE_HEADER *Header; + + if (Index >= gNumMcodeBlks) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_UPDATE_NUM_INVALID; + return; + } + + if (gMcodeBlkMap[Index].Type == MCODE_BLK_CONT) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_NOT_EMPTY; + return; + } + + UpdateBuffer = (UINT8*)(UINTN)(((UINT16)Regs->ES << 4) + (UINT16)Regs->EDI); + + Status = CheckAddressRange (UpdateBuffer, MICROCODE_BLOCK_SIZE); + if(EFI_ERROR(Status)) return; + + if (gMcodeBlkMap[Index].Type == MCODE_BLK_EMPTY) { + MemSet(UpdateBuffer, MICROCODE_BLOCK_SIZE, 0xff); + return; + } + + Header = (MICROCODE_HEADER *)gMcodeBlkMap[Index].Addr; + + MemCpy(UpdateBuffer, Header, MICROCODE_SIZE(Header)); +} + + +/////////////////////////////////////////////////////////////////////////////////// + +static UINT8 *gFlashBlk; //Pointer to current flash block to write. +static UINT8 *gFlashBuffer; //Pointer to beginning of buffer. +static UINT8 *gFlashBufferPos; //Pointer to current posisiton. +static UINT32 gFlashBufferUsed; //Number of bytes used in the buffer. + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FlushBufferToFlash +// +// Description: Helper function to write the buffer to the flash and reset the buffer. +// +// Input: VOID +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID FlushBufferToFlash() +{ + FwhErase((UINTN)gFlashBlk, FLASH_BLOCK_SIZE); + FwhWrite(gFlashBuffer, (UINTN)gFlashBlk, FLASH_BLOCK_SIZE); + gFlashBlk += FLASH_BLOCK_SIZE; + gFlashBufferPos = gFlashBuffer; + gFlashBufferUsed = 0; + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitializeFlashBuffer +// +// Description: Initialize the flash buffer before using. +// +// Input: +// IN UINT8* FirstFlashBlk - Address of first block to flash. +// IN UINT8* FlashBuffer - Flash Buffer. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID InitializeFlashBuffer(IN UINT8* FirstFlashBlk, IN UINT8 *FlashBuffer) +{ + gFlashBlk = FirstFlashBlk; + gFlashBuffer = FlashBuffer; + gFlashBufferPos = gFlashBuffer; + gFlashBufferUsed = 0; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CopyToFlashBuffer +// +// Description: Copy data to the buffer. When the buffer is full, write to the flash, +// and continues to copy data. +// +// Input: +// IN UINT8 Data - Start of data to write. +// IN UINT32 Size - Amount to Write. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CopyToFlashBuffer(IN UINT8 *Data, IN UINT32 Size) +{ + while (Size) { + if (gFlashBufferUsed + Size <= FLASH_BLOCK_SIZE) { + MemCpy(gFlashBufferPos, Data, Size); + + gFlashBufferPos += Size; + gFlashBufferUsed += Size; + + if (gFlashBufferUsed == FLASH_BLOCK_SIZE) FlushBufferToFlash(); + return; + } + + MemCpy(gFlashBufferPos, Data, FLASH_BLOCK_SIZE - gFlashBufferUsed); + Data += FLASH_BLOCK_SIZE - gFlashBufferUsed; + Size -= FLASH_BLOCK_SIZE - gFlashBufferUsed; + FlushBufferToFlash(); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: WriteValueToFlashBuffer +// +// Description: Fill part of the buffer with a value. When the buffer is full, write to the flash, +// and continue to update the beginning of the buffer with a value. +// +// Input: +// IN UINT8 Value - Value to write. +// IN UINT32 Size - Amount to Write. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteValueToFlashBuffer(IN UINT8 Value, IN UINT32 Size) +{ + + while (Size) { + if (gFlashBufferUsed + Size <= FLASH_BLOCK_SIZE) { + MemSet(gFlashBufferPos, Size, Value); + + gFlashBufferPos += Size; + gFlashBufferUsed += Size; + + if (gFlashBufferUsed == FLASH_BLOCK_SIZE) FlushBufferToFlash(); + return; + } + + MemSet(gFlashBufferPos, FLASH_BLOCK_SIZE - gFlashBufferUsed, Value); + Size -= FLASH_BLOCK_SIZE - gFlashBufferUsed; + FlushBufferToFlash(); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FillBufferAndFlush +// +// Description: Fill the rest of the buffer of a size of the flash block, then update the flash. +// +// Input: IN UINT8 *Data - Pointer to starting of data to write to the flash. +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID FillFlashBufferAndFlush(IN UINT8 *Data) +{ + if (gFlashBufferUsed != 0) { + MemCpy(gFlashBufferPos, Data, FLASH_BLOCK_SIZE - gFlashBufferUsed); + FwhErase((UINTN)gFlashBlk, FLASH_BLOCK_SIZE); + FwhWrite(gFlashBuffer, (UINTN)gFlashBlk, FLASH_BLOCK_SIZE); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SMI_UC_DWORD_REGS +// +// Description: Write microcode to flash and load microcode into each CPU. +// +// Input: EFI_SMI_CPU_SAVE_STATE *Regs +// +// Output: VOID +// +// Input: +// AX - D042h +// BL - 01h i.e., WRITE_UPDATE_DATA +// ES:DI - Real Mode Pointer to the Intel Update structure. +// CX - Scratch Pad1 (Real Mode Scratch segment 64K in length) +// DX - Scratch Pad2 (Real Mode Scratch segment 64K in length) +// SI - Scratch Pad3 (Real Mode Scratch segment 64K in length) +// SS:SP - Stack pointer (32K minimum) +// +// Output: +// CF NC - All return values are valid +// CY - Failure, AH contains status. +// +// AH Return code +// AL Additional OEM information +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteUpdateData(SMI_UC_DWORD_REGS *Regs) +{ + EFI_STATUS Status; + UINT8 *NewMcode = (UINT8*)(UINTN)((Regs->ES << 4) + (Regs->EDI & 0xFFFF)); + MICROCODE_HEADER *Header = (MICROCODE_HEADER*)NewMcode; + INT32 NewMcodeAlignSize = MICROCODE_ALIGN_SIZE(NewMcode); + INT32 NewMcodeSize = MICROCODE_SIZE(NewMcode); + BOOLEAN Compact = FALSE; + + UINT8 *OldMcode; + INT32 OldMcodeAlignSize; + UINT8 *BlkStart; + UINT8 *McodeUpdateStart; + UINT8 *Buffer; + + Status = CheckAddressRange(NewMcode, NewMcodeAlignSize); + if(EFI_ERROR(Status)) return; + + if (!IsValidHeader(Header)) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_INVALID_HEADER; + return; + } + + if (!IsValidChecksum(NewMcode, NewMcodeSize)) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_INVALID_HEADER_CS; + return; + } + + //Only update if microcode is for the installed CPU. + if (Header->CpuSignature != gCpuSignature || !(Header->Flags & (1<<gCpuFlag))) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_CPU_NOT_PRESENT; + return; + } + + //Only update a different revision. + if (Header->UpdateRevision == gUcRevision) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_INVALID_REVISION; + return; + } + + //If no microcode installed, then the revision is 0. + if (gUcRevision != 0) { //Quick check. + if(FindMicrocodeOfStepping(gMcodeFlashStartUpdate, + gMcodeFlashStartUpdate + gMcodeFlashSizeUpdate, + gCpuSignature + ) != NULL) { + Compact = TRUE; //Remove old version. + } + } + if (gFirstEmptyBlk == 0xffff || NewMcodeAlignSize > + (gMcodeFlashStartUpdate + gMcodeFlashSizeUpdate - gMcodeBlkMap[gFirstEmptyBlk].Addr) + ) Compact = TRUE; //Volume is full. + + if (!Compact) { + //Append blocks. + UINT8 *pEmptyBlk = gMcodeBlkMap[gFirstEmptyBlk].Addr; + LoadMicrocodeEachCpu(NewMcode); //Install new microcode. + + //Check to see if new microcode is installed. + if (Header->UpdateRevision != GetInstalledMicrocodeRevision()) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_SECURITY_FAILURE; + return; + } + + FwhWrite(NewMcode, (UINTN)pEmptyBlk, NewMcodeSize); //Currently ignoring status + + InitMcodeBlkMap(); + return; + } + + //***Compact Flash Part*** + + //Currently restrict FLASH_BLOCK_SIZE to 64k or smaller + if (FLASH_BLOCK_SIZE > 64 * 1024) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_NOT_IMPLEMENTED; + } + + //Set up Buffer. + Buffer = (UINT8*)(UINTN)((UINT16)Regs->ECX << 4); + + Status = CheckAddressRange(Buffer, FLASH_BLOCK_SIZE); + if(EFI_ERROR(Status)) return; + + //Find existing microcode of same revision. + McodeUpdateStart = gFirstEmptyBlk == 0xffff ? + gMcodeFlashStartUpdate + gMcodeFlashSizeUpdate : gMcodeBlkMap[gFirstEmptyBlk].Addr; + + OldMcode = FindMicrocodeOfStepping( + gMcodeFlashStartUpdate, + McodeUpdateStart, + gCpuSignature + ); + + //Old Microcode not available to remove? + if (!OldMcode) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_STORAGE_FULL; + return; + } + OldMcodeAlignSize = MICROCODE_ALIGN_SIZE(OldMcode);; + + //Check to see if space big enough for new microcode. + if ((gMcodeFlashStartUpdate + gMcodeFlashSizeUpdate - McodeUpdateStart + OldMcodeAlignSize) < NewMcodeAlignSize) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_STORAGE_FULL; + return; + } + + //Load new microcode, if can't load exit. + LoadMicrocodeEachCpu(NewMcode); //Install new microcode. + if (Header->UpdateRevision != GetInstalledMicrocodeRevision()) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_SECURITY_FAILURE; + return; + } + + //Start compacting at block with Old Microcode to remove. + BlkStart = (UINT8*)((UINTN)OldMcode & ~(FLASH_BLOCK_SIZE - 1)); //Must start at block boundary. + + //Note: When Buffer is full, it will flush to flash. + InitializeFlashBuffer(BlkStart, Buffer); + CopyToFlashBuffer(BlkStart, (UINT32)(OldMcode - BlkStart)); //Copy before old microcode. + + CopyToFlashBuffer(OldMcode + OldMcodeAlignSize, (UINT32)(McodeUpdateStart - (OldMcode + OldMcodeAlignSize))); //Copy after old microcode. + + CopyToFlashBuffer(NewMcode, NewMcodeSize); //Copy new microcode. + + WriteValueToFlashBuffer(0xff, NewMcodeAlignSize - NewMcodeSize); //Fill block space after microcode. + + if (NewMcodeAlignSize < OldMcodeAlignSize) { + WriteValueToFlashBuffer(0xff, OldMcodeAlignSize - NewMcodeAlignSize); //Write 0xff over reclaimed space. Polarity? + } else { + McodeUpdateStart += NewMcodeAlignSize - OldMcodeAlignSize; + } + FillFlashBufferAndFlush(McodeUpdateStart); + + InitMcodeBlkMap(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MicrocodeUpdateCallback +// +// Description: This notification function is called when an SMM Mode +// is invoked through SMI. This may happen during RT, +// so it must be RT safe. +// Interrupt 15h, function D042h is processed here. +// +// Input: DispatchHandle - EFI Handle +// DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT +// +// Output: Status code returned to function D042h caller. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID MicrocodeUpdateCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + EFI_STATUS Status; + SMI_UC_DWORD_REGS *Regs; + SW_SMI_CPU_TRIGGER *SwSmiCpuTrigger; + UINTN Cpu = pSmst->CurrentlyExecutingCpu - 1; + UINT8 Function; + UINTN i; + + for (i = 0; i < pSmst->NumberOfTableEntries; ++i) { + if (guidcmp(&pSmst->SmmConfigurationTable[i].VendorGuid,&gSwSmiCpuTriggerGuid) == 0) { + break; + } + } + + //If found table, check for the CPU that caused the software Smi. + if (i != pSmst->NumberOfTableEntries) { + SwSmiCpuTrigger = pSmst->SmmConfigurationTable[i].VendorTable; + Cpu = SwSmiCpuTrigger->Cpu; + } + Regs = (SMI_UC_DWORD_REGS*)(UINTN)(pSmst->CpuSaveState[Cpu].Ia32SaveState.ESI); + + Status = CheckAddressRange((UINT8*)Regs, sizeof(SMI_UC_DWORD_REGS)); + if(EFI_ERROR(Status)) return; + + if ((UINT16)Regs->EAX != 0xD042) return; + + Function = (UINT8)Regs->EBX; //BL + + //Initialize return as successful. + Regs->EFLAGS &= ~CARRY_FLAG; + Regs->EAX &= 0xffff0000; + + if (Function >= MAX_MICROCODE_UPDATE_FUNCTIONS) { + Regs->EFLAGS |= CARRY_FLAG; + *(UINT16*)&Regs->EAX = UC_NOT_IMPLEMENTED; + return; + } + + MicrocodeUpdate[Function](Regs); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InSmmFunction +// +// Description: This function is called from the InitSmmHandler if driver is in SMM. +// +// Input: ImageHandle - Pointer to the loaded image protocol for this driver +// SystemTable - Pointer to the EFI System Table +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InSmmFunction(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_SMM_SW_DISPATCH_PROTOCOL *pSwDispatch; + EFI_SMM_SW_DISPATCH_CONTEXT SwContext; + EFI_STATUS Status; + EFI_HANDLE Handle; + SMM_HOB *SmmHob; + EFI_GUID SmmHobGuid = SMM_HOB_GUID; + EFI_GUID HobListGuid = HOB_LIST_GUID; + + BOOLEAN IsInit = InitMicrocodeVariables(); + if (!IsInit) return EFI_UNSUPPORTED; + + Status = pBS->LocateProtocol(&gEfiSmmSwDispatchProtocolGuid, NULL, &pSwDispatch); + ASSERT_EFI_ERROR(Status); + + SmmHob = (SMM_HOB*)GetEfiConfigurationTable(pST, &HobListGuid); + if (SmmHob == NULL) return EFI_NOT_FOUND; + + Status = FindNextHobByGuid(&SmmHobGuid,(VOID**)&SmmHob); + if (EFI_ERROR(Status)) return Status; + + gSmmHob = *SmmHob; + + SwContext.SwSmiInputValue = INT15_D042_SWSMI; + + Status = pSwDispatch->Register(pSwDispatch, MicrocodeUpdateCallback, &SwContext, &Handle); + ASSERT_EFI_ERROR(Status); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitializeMicrocodeSmm +// +// Description: This function registers the INT15 D042 SW SMI handler +// This is the driver entry pOoint. +// +// Input: ImageHandle - Pointer to the loaded image protocol for this driver +// SystemTable - Pointer to the EFI System Table +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InitializeMicrocodeSmm( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + InitAmiLib(ImageHandle, SystemTable); + return InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NULL); +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.cif b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.cif new file mode 100644 index 0000000..8a965ea --- /dev/null +++ b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.cif @@ -0,0 +1,13 @@ +<component> + name = "MicrocodeUpdate" + category = ModulePart + LocalRoot = "Core\CPU\MicrocodeUpdate\" + RefName = "MicrocodeUpdate" +[files] +"MicrocodeUpdate.sdl" +"MicrocodeUpdate.mak" +"MicrocodeUpdate.c" +"MicrocodeUpdate.h" +"MicrocodeUpdate.dxs" +"FwhFvb.c" +<endComponent> diff --git a/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.dxs b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.dxs new file mode 100644 index 0000000..f6a5ffa --- /dev/null +++ b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.dxs @@ -0,0 +1,48 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.dxs 1 2/07/12 3:59a Davidhsieh $ +// +// $Revision: 1 $ +// +// $Date: 2/07/12 3:59a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.dxs $ +// +// 1 2/07/12 3:59a Davidhsieh +// +//********************************************************************** + +#include <Protocol\SmmSwDispatch.h> + +DEPENDENCY_START + EFI_SMM_SW_DISPATCH_PROTOCOL_GUID +DEPENDENCY_END + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.h b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.h new file mode 100644 index 0000000..73b5dea --- /dev/null +++ b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.h @@ -0,0 +1,133 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//**************************************************************************** +// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.h 1 2/07/12 3:59a Davidhsieh $ +// +// $Revision: 1 $ +// +// $Date: 2/07/12 3:59a $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.h $ +// +// 1 2/07/12 3:59a Davidhsieh +// +// +//**************************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: MicrocodeUpdate.h +// +// Description: Header file for Microcode Update SMI handler. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef _MICROCODE_UPDATE_H_ +#define _MICROCODE_UPDATE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//#define SIG_PART_ONE 0x0494e5445 // 'INTE' +//#define SIG_PART_TWO 0x04c504550 // 'LPEP' + + +#define CARRY_FLAG 1 + +#define UC_LOADER_VERSION 1 + +#define UC_HEADER_VERSION 1 +#define UC_LOADER_REVISION 1 + +#define UC_INT15_ENABLE 0x01 + +#define UC_PRESCENCE_TEST 0 +#define UC_WRITE_UPDATE_DATA 1 +#define UC_UPDATE_CONTROL 2 +#define UC_READ_UPDATE_DATA 3 + +#define UC_SUCCESS 0x0000 +#define UC_NOT_IMPLEMENTED 0x8600 +#define UC_ERASE_FAILURE 0x9000 +#define UC_WRITE_FAILURE 0x9100 +#define UC_READ_FAILURE 0x9200 +#define UC_STORAGE_FULL 0x9300 +#define UC_CPU_NOT_PRESENT 0x9400 +#define UC_INVALID_HEADER 0x9500 +#define UC_INVALID_HEADER_CS 0x9600 +#define UC_SECURITY_FAILURE 0x9700 +#define UC_INVALID_REVISION 0x9800 +#define UC_UPDATE_NUM_INVALID 0x9900 +#define UC_NOT_EMPTY 0x9a00 + +typedef struct { + UINT32 EAX; + UINT32 EBX; + UINT32 ECX; + UINT32 EDX; + UINT32 ESI; + UINT32 EDI; + UINT32 EFLAGS; + UINT16 ES; + UINT16 CS; + UINT16 SS; + UINT16 DS; + UINT16 FS; + UINT16 GS; + UINT32 EBP; +} SMI_UC_DWORD_REGS; + +VOID PresenceTest(SMI_UC_DWORD_REGS *Regs); +VOID WriteUpdateData(SMI_UC_DWORD_REGS *Regs); +VOID UpdateControl(SMI_UC_DWORD_REGS *Regs); +VOID ReadUpdateData(SMI_UC_DWORD_REGS *Regs); + +EFI_STATUS FwhErase( + IN UINTN Address, + IN UINTN NumberOfBytes +); + +EFI_STATUS FwhWrite( + IN UINT8 *Buffer, + IN UINTN Address, + IN UINTN NumberOfBytes +); + + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1987-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.mak b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.mak new file mode 100644 index 0000000..160baf9 --- /dev/null +++ b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.mak @@ -0,0 +1,58 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1987-2013, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************// +# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.mak 1 2/07/12 3:59a Davidhsieh $ +# +# $Revision: 1 $ +# +# $Date: 2/07/12 3:59a $ +#************************************************************************// +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MicrocodeUpdate/MicrocodeUpdate.mak $ +# +# 1 2/07/12 3:59a Davidhsieh +# +#************************************************************************// + +all : MicrocodeUpdate + +MicrocodeUpdate: $(BUILD_DIR)\MicrocodeUpdate.mak MicrocodeUpdateBin + +$(BUILD_DIR)\MicrocodeUpdate.mak : $(MICROCODEUPDATE_PATH)\MicrocodeUpdate.cif $(MICROCODEUPDATE_PATH)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(MICROCODEUPDATE_PATH)\MicrocodeUpdate.cif $(CIF2MAK_DEFAULTS) + +MicrocodeUpdateBin : $(AMIDXELIB) $(FLASHLIB) $(AMICSPLib) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\MicrocodeUpdate.mak all\ + GUID=F3331DE6-4A55-44e4-B767-7453F7A1A021\ + ENTRY_POINT=InitializeMicrocodeSmm\ + TYPE=BS_DRIVER \ + COMPRESS=1 + + +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1987-2013, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.sdl b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.sdl new file mode 100644 index 0000000..2acaf0d --- /dev/null +++ b/Core/CPU/MicrocodeUpdate/MicrocodeUpdate.sdl @@ -0,0 +1,32 @@ +TOKEN + Name = "MicrocodeUpdate_SUPPORT" + Value = "1" + Help = "Main switch to enable Microcode Update support in Project" + TokenType = Boolean + TargetMAK = Yes + Master = Yes + Token = "Microcode_SUPPORT" "=" "1" + Token = "CSM_SUPPORT" "=" "1" +End + +PATH + Name = "MICROCODEUPDATE_PATH" +End + +MODULE + Help = "Includes MicorcodeUpdate.mak to Project" + File = "MicrocodeUpdate.mak" +End + +ELINK + Name = "$(BUILD_DIR)\MicrocodeUpdate.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End + +ELINK + Name = " " + Parent = "$(BUILD_DIR)\MicrocodeUpdate.ffs" + Token = "AMI_DEBUGGER_SUPPORT" "=" "1" + InvokeOrder = ReplaceParent +End diff --git a/Core/CPU/ResetVector.asm b/Core/CPU/ResetVector.asm new file mode 100644 index 0000000..dd134ad --- /dev/null +++ b/Core/CPU/ResetVector.asm @@ -0,0 +1,99 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1987-2013, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;********************************************************************** +; $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/ResetVector.asm 3 6/15/12 3:27a Davidhsieh $ +; +; $Revision: 3 $ +; +; $Date: 6/15/12 3:27a $ +;********************************************************************** +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/ResetVector.asm $ +; +; 3 6/15/12 3:27a Davidhsieh +; [TAG] None +; [Category] New Feature +; [Description] For FIT module support +; +; 2 3/16/12 3:11a Davidhsieh +; Setup items create for CPU RC policy +; +; 1 2/07/12 3:58a Davidhsieh +; +;********************************************************************** + +;<AMI_FHDR_START> +;---------------------------------------------------------------------------- +; +; Name: ResetVector.asm +; +; Description: +; Reset Vector. Fixup will update code to jump to EntryPoint of Startup32.asm. +; +;---------------------------------------------------------------------------- +;<AMI_FHDR_END> + +.586P +.XMM +.model tiny + +include token.equ + +RESET_SEG SEGMENT PARA PUBLIC 'CODE' USE16 + org 0 ;offset 0xFFFFFFC0h +ifndef MKF_INTEL_FIT_TABLE_ADDRESS + dd 0EEEEEEEEh + dd 0EEEEEEEEh +else + dd MKF_INTEL_FIT_TABLE_ADDRESS ;Reserve + dd 0h +endif + org 10h ;offset 0xFFFFFFD0h + mov di, "AP" ;Actual AP startup (SIPI) is hardcoded to jump here. + jmp ApStartup + + org 20h ;offset 0xFFFFFFE0 + dd 87654321h ;Fixed up by tool to point to PEI CORE Entry. + + org 30h ;offset 0xFFFFFFF0 + nop ;Place holder to maintain byte sequence for build tool fix-ups. + nop ;Place holder to maintain byte sequence for build tool fix-ups. +ApStartup: + ; Use machine code directly in case of the assembler optimization + ; SEC entry point relatvie address will be fixed up by some build tool. + ; + db 0e9h ;jmp Rel16 + dw -3 ;SecFixup utility changes to point to flat32.asm Entry Point. + + org 3ch ;offset 0xFFFFFFFC + dd 012345678h ;Fixed up by GenFvImage to Boot Firmware Volume Base. +RESET_SEG ENDS +END + +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1987-2013, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + diff --git a/Core/CPU/SecFixup.exe b/Core/CPU/SecFixup.exe Binary files differnew file mode 100644 index 0000000..950343c --- /dev/null +++ b/Core/CPU/SecFixup.exe diff --git a/Core/CPU/Startup32.asm b/Core/CPU/Startup32.asm new file mode 100644 index 0000000..9728a39 --- /dev/null +++ b/Core/CPU/Startup32.asm @@ -0,0 +1,618 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1987-2013, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;********************************************************************** +; $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/Startup32.asm 3 11/28/12 1:11a Davidhsieh $ +; +; $Revision: 3 $ +; +; $Date: 11/28/12 1:11a $ +;********************************************************************** +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/Startup32.asm $ +; +; 3 11/28/12 1:11a Davidhsieh +; [TAG] EIP107763 +; [Category] Bug Fix +; [Severity] Important +; [Symptom] UEFI SCT 2.3.1 Floating Point ABI Test fail +; [RootCause] According to UEFI 2.3.1 errata C, Floating-point control +; word must be initialized to 0x037F +; [Solution] Use 0x37f for Floating-point control word +; +; 2 3/09/12 2:13a Davidhsieh +; Create BIST data +; +; 1 2/07/12 3:58a Davidhsieh +; +;********************************************************************** + +;<AMI_FHDR_START> +;---------------------------------------------------------------------------- +; +; Name: StartUp32.asm +; +; Description: Switch CPU to protected mode, INIT CAR and setup stack. +; +;---------------------------------------------------------------------------- +;<AMI_FHDR_END> + +.586P +.XMM +.model small + +include token.equ +include cpu.equ + +ifndef MKF_PI_SPECIFICATION_VERSION +MKF_PI_SPECIFICATION_VERSION EQU 0 +endif + +ifndef MKF_CSM_SUPPORT +MKF_CSM_SUPPORT EQU 0 +endif + +ifndef MKF_MPDTable_CREATED +MKF_MPDTable_CREATED EQU 0 +endif + +ifndef MKF_PACK_MICROCODE +MKF_PACK_MICROCODE EQU 0 +endif + +ifndef MKF_MICROCODE_SPLIT_BB_UPDATE +MKF_MICROCODE_SPLIT_BB_UPDATE EQU 0 +endif + +PhysMask equ (NOT (MKF_CAR_TOTAL_SIZE - 1)) ;8k stack + +WriteBack equ 6 +ValidMask equ 1 SHL 11 + +IA32_MISC_ENABLE EQU 1A0h +FAST_STRING_ENABLE_BIT EQU 01h + +MTRR_PHYS_BASE_0 EQU 0200h +MTRR_PHYS_MASK_0 EQU 0201h +MTRR_PHYS_BASE_1 EQU 0202h +MTRR_PHYS_MASK_1 EQU 0203h +MTRR_PHYS_BASE_2 EQU 0204h +MTRR_PHYS_MASK_2 EQU 0205h +MTRR_PHYS_BASE_3 EQU 0206h +MTRR_PHYS_MASK_3 EQU 0207h +MTRR_PHYS_BASE_4 EQU 0208h +MTRR_PHYS_MASK_4 EQU 0209h +MTRR_PHYS_BASE_5 EQU 020Ah +MTRR_PHYS_MASK_5 EQU 020Bh +MTRR_PHYS_BASE_6 EQU 020Ch +MTRR_PHYS_MASK_6 EQU 020Dh +MTRR_PHYS_BASE_7 EQU 020Eh +MTRR_PHYS_MASK_7 EQU 020Fh +MTRR_FIX_64K_00000 EQU 0250h +MTRR_FIX_16K_80000 EQU 0258h +MTRR_FIX_16K_A0000 EQU 0259h +MTRR_FIX_4K_C0000 EQU 0268h +MTRR_FIX_4K_C8000 EQU 0269h +MTRR_FIX_4K_D0000 EQU 026Ah +MTRR_FIX_4K_D8000 EQU 026Bh +MTRR_FIX_4K_E0000 EQU 026Ch +MTRR_FIX_4K_E8000 EQU 026Dh +MTRR_FIX_4K_F0000 EQU 026Eh +MTRR_FIX_4K_F8000 EQU 026Fh +MTRR_DEF_TYPE EQU 02FFh + +EFI_PEI_PPI_DESCRIPTOR_PPI EQU 00000010h +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST EQU 80000000h + +FV_LENGTH EQU (16 + 16) +FV_SIGNATURE EQU (FV_LENGTH + 8) +FV_HDR_LENGTH EQU (FV_SIGNATURE + 4 + 4) + +FFS_LENGTH EQU (16 + 2 + 1 + 1) +FFS_HDR_LENGTH EQU (FFS_LENGTH + 3 + 1) + +uCODE_CPU_SIGNATURE EQU 12 +uCODE_CPU_FLAGS EQU 24 +uCODE_DATA_SIZE EQU 28 +uCODE_TOTAL_SIZE EQU 32 + +; Externs +EXTERN SECCoreAtPowerOn:NEAR32 +PUBLIC SECCoreAtPowerOnEnd + +;STARTUP_SEG SEGMENT USE32 +;---------------------------------------------------------------------------- +; STARTUP_SEG S E G M E N T STARTS +;---------------------------------------------------------------------------- +STARTUP_SEG SEGMENT PARA PUBLIC 'CODE' USE32 + +MICOCODE_FFS_GUID label dword + dd 17088572h + dw 377Fh + dw 44efh + db 8Fh,4Eh,0B0h,9Fh,0FFh,46h,0A0h,70h + +AMI_BIST_GUID label dword + dd 0A7E2CE72h + dw 0DC32h + dw 04BC0h + db 9Eh, 35h, 0FEh, 0B3h, 0Ah, 0E5h, 0CCh, 47h + +SEC_CORE_PPI_DESC STRUCT + BIST_FLAGS dd ? + BIST_GUID dd ? + BIST_PPI dd ? +SEC_CORE_PPI_DESC ends + + +SecCorePpiDesc SEC_CORE_PPI_DESC < \ + EFI_PEI_PPI_DESCRIPTOR_PPI + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, \ + offset AMI_BIST_GUID, \ + 0 \ +> + + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; Procedure: FindMicrocode +; +; Description: This routine searches the file volume for a microcode update +; and returns the address if found. +; +; Input: None +; +; Output: eax = Pointer to microcode. 0 if not found. +; +; Notes: +; This routine can not use stack. It can be called from rom or ram. +; If called from rom, a hard coded stack must be exist in rom. +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +IF MKF_Microcode_SUPPORT +public FindMicrocode +extern FindMicrocodeEnd:NEAR32 +FindMicrocode proc +IF MKF_MICROCODE_SPLIT_BB_UPDATE + mov ebx, MKF_FV_MICROCODE_UPDATE_BASE +FindMicrocodeFv: +ELSE + mov ebx, MKF_FV_MICROCODE_BASE +ENDIF + cmp dword ptr [ebx + FV_SIGNATURE], 'HVF_' + jne Microcode_Not_Found ;Corrupt FV? + + mov edx, ebx + mov eax, [ebx + FV_HDR_LENGTH] + and eax, 0ffffh ;Get 16 bit FV header length + add ebx, eax ;ebx = start of FFS + jc Microcode_Not_Found ;Corrupt FV? + add edx, [edx + FV_LENGTH] + jz @f ;zf if Boot Block + jc Microcode_Not_Found ;Corrupt FV? +@@: + dec edx ;edx = End of FFS +;---Find File --- +;ebx = Start of FFS +;edx = End of FFS +Get_Next_File: + cmp dword ptr [ebx], -1 ;Is in end of files, but not firmware volume. + je File_not_found + mov ecx, 4 + mov esi, ebx + mov edi, offset MICOCODE_FFS_GUID + ;compare file guid + repe cmpsd + je Found_File +;---get next file-- + ;get file length and add to ebx + mov eax, [ebx + FFS_LENGTH] + and eax, 0ffffffh ;eax = File length (24 bits) + add ebx, eax ;next file + ;align file + add ebx, 7 + jc Microcode_Not_Found ;Check for wrap-around if bad data. + and ebx, not 7 + + cmp ebx, edx ;Is end of firmware volume? + jb Get_Next_file +File_not_found: + jmp Microcode_Not_Found +;---Found File--- +Found_File: +;ebx = Start of Microcode FFS +;edx = End of FFS + 1 + +;---Search micocode for match.--- + mov edi, ebx + + mov eax, [ebx + FFS_LENGTH] + and eax, 0ffffffh ;eax = File length (24 bits) + add edi, eax ;edi = end of file + jc Microcode_Not_Found ;Check for wrap-around if bad data. + +IF MKF_MPDTable_CREATED + movzx eax, word ptr [edi-2] ;eax = MPDT length + sub edi, eax ;edi = end of microcodes. +ENDIF + + add ebx, FFS_HDR_LENGTH + jc Microcode_Not_Found ;Check for wrap-around if bad data. + + mov esi, ebx + + mov eax, 1 + cpuid + mov ebx, eax ;ebx = CPU signature + + mov ecx, 17h + rdmsr ;read CPUS flags + + shr edx, 18 + and dl, 7 ;dl = CPU FLAG + mov cl, dl + mov dl, 1 + shl dl, cl ;dl = bit set for CPU flag + + xchg ebx, esi ;ebx = ptr, esi = signature +Next_Microcode: + cmp ebx, edi ;Check to see if microcode at end of FFS File. + jae Microcode_Not_Found + + cmp dword ptr [ebx], 1 ;Check if correct header revision + jne Microcode_Not_Found + + mov ecx, 2048 ;total size if data size in field = 0. + cmp dword ptr [ebx + uCODE_DATA_SIZE], 0 + jz @f + mov ecx, [ebx + uCODE_TOTAL_SIZE] ;Get total size. +@@: + + cmp esi, [ebx + uCODE_CPU_SIGNATURE] + jne Check_Ext_Sig + + mov eax, ebx ;Store uC addr in eax, so if jnz succeeds. + test dl, [ebx + uCODE_CPU_FLAGS] ;uC flags match? + jnz Exit_Find_Microcode + +Check_Ext_Sig: + mov ebp, [ebx + uCODE_TOTAL_SIZE] ;Get total size. + mov eax, [ebx + uCODE_DATA_SIZE] ;Get Data Size + add eax, 48 + cmp ebp, eax + jbe Find_Next_Microcode ;No extended signature. + + mov ecx, [ebx + eax] ;Get extended signature. + cmp ecx, 20 + jae Microcode_Not_Found ;Corrupt? + lea ebp, [ebx + eax + 20] ;First Proc Signature. + +@@: + cmp [ebp], esi ;Check Signature + jne Next_Ext_Sig + + mov eax, ebx + test dl, [ebp + 4] ;Check processor flags + jnz Exit_Find_Microcode +Next_Ext_Sig: + add ebp, 12 + loop @b + mov ecx, [ebx + uCODE_TOTAL_SIZE] ;Get total size. +Find_Next_Microcode: + ;align to next block size +IF MKF_PACK_MICROCODE + add ecx, 15 + and ecx, 0fffffff0h +ELSE + add ecx, MKF_MICROCODE_BLOCK_SIZE - 1 + and ecx, NOT (MKF_MICROCODE_BLOCK_SIZE - 1) +ENDIF + add ebx, ecx + jc Microcode_Not_Found ;Overflow - bad data. + jmp Next_Microcode + +Microcode_Not_Found: +IF MKF_MICROCODE_SPLIT_BB_UPDATE + cmp ebx, MKF_FV_MICROCODE_BASE + jae @f + mov ebx, MKF_FV_MICROCODE_BASE + jmp FindMicrocodeFv +@@: +ENDIF + xor eax, eax +Exit_Find_Microcode: + jmp FindMicrocodeEnd +FindMicrocode endp + +ENDIF ;MKF_Microcode_SUPPORT + +;<AMI_PHDR_START> +;---------------------------------------------------------------------------- +; +; Procedure: CPU_START +; +; Description: Switch CPU to protected mode, INIT CAR and setup stack. +; +; Input: None +; +; Output: None +; +;---------------------------------------------------------------------------- +;<AMI_PHDR_END> + +public _CPU_START +_CPU_START: + ;---16 bit in 32 bit assembler-- + ;---Some 16-bit and 32-bit assmebly is the same, others are not.--- + ;---Need to use some machine code.--- + + fninit ;Clear any pending Floating point exceptions + movd mm0, eax ;Save BIST state in MM0 + + cli + +if MKF_CSM_SUPPORT EQ -1 + db 0B8h, 00h, 0F0h ;mov ax, 0F000h + db 8Eh, 0D8h ;mov ds, ax + db 0BEh, 0F0h, 0FFh ;mov si, 0FFF0h + db 80h, 3Ch, 0EAh ;cmp BYTE PTR [si], 0EAh ; Is it warm reset ? + jne NotWarmReset ; If not. + + db 0EAh ;DB 0EAh ; Far jump to F000:E05B (legacy BIOS warm reset entry) + dw 0E05Bh ;DW 0E05Bh + dw 0F000h ;DW 0F000h +NotWarmReset: +endif + + ;Switch to protected mode + ;lgdt fword ptr cs:[GdtDescriptor] ;Relative to 4G. +; db 66h,2eh,0fh,1,16h +; dw offset GdtDescriptor ;<-------Problem------< + + db 66h + mov ebx, offset GdtDescriptor + ;lgdt fword ptr cs:[bx] + db 66h, 2eh,0fh,1,17h + + mov eax, cr0 + or al, 1 ;Set PE bit + mov cr0, eax ;Turn on Protected Mode + + ;In 16 bit protected mode + + cld + db 0b8h ;mov ax, DATA_SEL + dw DATA_SEL + db 8eh, 0d8h ;mov ds, ax + db 8eh, 0c0h ;mov es, ax + db 8eh, 0d0h ;mov ss, ax + db 8eh, 0e0h ;mov fs, ax + db 8eh, 0e8h ;mov gs, ax + + ;set cs segment + ;jmp 10:CHANGE_CS + db 66h, 0eah + dd CHANGE_CS ;Relative to 4G. + dw CODE_SEL +CHANGE_CS: + ;---If Limit CPU ID enabled because of soft reset, disable. + mov ecx, 01a0h + rdmsr + btr eax, 22 ;Reset bit + jnc @f ;If already reset, don't write to 1a0. + wrmsr +@@: + ;---Change APIC Address--- + mov ecx, MSR_XAPIC_BASE ; Enable local APIC + rdmsr + and edx, NOT 0fh ;Mask local APIC address + and eax, NOT 0fffff000h ;Mask local APIC address + or eax, MKF_LOCAL_APIC_BASE + wrmsr + +;-------------------------------------------------------------------- + + ;In CR4, set OSFXSR bit 9 and OSXMMEXCPT bit 10 + mov eax, cr4 + or ax, 1 SHL 9 + 1 SHL 10 + mov cr4, eax + +;--------------------------------------------- +;--------------------------------------------- +;--------------------------------------------- + +; Invoke the SECCore Init hook for other components to hook functions +; This also executes referece code. + jmp SECCoreAtPowerOn +SECCoreAtPowerOnEnd:: + + ; This stores the BIST for SBSP. + ; The PBSPs BIST is stored in MM0. The value will preserved across INIT-SIPI and captured + ; in CPU PEI. + movd eax, mm0 + pushd eax ;Bist0 + + ;Get Apic ID + mov eax, MKF_LOCAL_APIC_BASE + 20h + mov ebx, [eax] + shr ebx, 24 + pushd ebx ;ApicId0 + pushd 1 ;Num BISTS + + mov ebx, esp ;points to AMI_BIST_PPI_STRUCT + + sub esp, size SEC_CORE_PPI_DESC + mov esi, offset SecCorePpiDesc + mov edi, esp + mov ecx, size SEC_CORE_PPI_DESC / 4 + rep movsd + + mov (SEC_CORE_PPI_DESC PTR [esp]).BIST_PPI, ebx + mov ebx, esp + +IFDEF EFIx64 + pushd 37fh +ELSE + pushd 27fh +ENDIF + fldcw word ptr [esp] ;Set FP control word according UEFI + add esp, 4 + + ; Pass NEM address into the PEI Core + push MKF_CAR_BASE_ADDRESS + + ; Dispatch table + push ebx + +IF MKF_PI_SPECIFICATION_VERSION GE 00010000h + ; Initialize EFI_SEC_PEI_HAND_OFF data structure in CAR + mov ebx, MKF_CAR_BASE_ADDRESS + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).DataSize, sizeof EFI_SEC_PEI_HAND_OFF + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).Reserved1, 0 + + ; Report the Boot Firmware Volume that PEI should search for PEIMS (FV_BB) + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).BootFirmwareVolumeBase, MKF_FV_BB_BASE + + ; Report the Size of the Boot Firmware Volume, in Bytes + mov eax, MKF_FV_BB_BASE + 32 + mov eax, [eax] + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).BootFirmwareVolumeSize, eax + + ; Report the start the CAR Base address and size (based on SDL tokens) + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).TemporaryRamBase, MKF_CAR_BASE_ADDRESS + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).TemporaryRamSize, MKF_CAR_TOTAL_SIZE + + ; Report the starting address of the CAR that PEI Core can use + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).PeiTemporaryRamBase, MKF_CAR_BASE_ADDRESS + sizeof EFI_SEC_PEI_HAND_OFF + EFI_PEI_SERVICES_DOUBLE_POINTER_SIZE + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).PeiTemporaryRamSize, MKF_CAR_TOTAL_SIZE - sizeof EFI_SEC_PEI_HAND_OFF - EFI_PEI_SERVICES_DOUBLE_POINTER_SIZE + + ; Report the start of the stack and its size (should point into top of CAR region) + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).StackBase, MKF_CAR_BASE_ADDRESS + MKF_CAR_TOTAL_SIZE + mov (EFI_SEC_PEI_HAND_OFF ptr [ebx]).StackSize, MKF_CAR_TOTAL_SIZE + + ; In CAR, reserve 8 bytes space before IDT Base Address for a pointer to a pointer + ; of the PEI Services Table (EFI_PEI_SERVICES**) which will be initialized in PEI + + ; IDT Base Address = MKF_CAR_BASE_ADDRESS + sizeof EFI_SEC_PEI_HAND_OFF + EFI_PEI_SERVICES_DOUBLE_POINTER_SIZE + ; IDT Size is 0 because it will be initalized in PEI. Here, it is only + ; used to reserved 8 bytes space for (EFI_PEI_SERVICES**) + sub esp, sizeof IDTR32 + mov (IDTR32 ptr [esp]).BaseAddress, MKF_CAR_BASE_ADDRESS + sizeof EFI_SEC_PEI_HAND_OFF + EFI_PEI_SERVICES_DOUBLE_POINTER_SIZE + mov (IDTR32 ptr [esp]).Limit, 0 + lidt FWORD PTR [esp] + add esp, sizeof IDTR32 + + ; Push a pointer to the the EFI_PEI_PPI_DESCRIPTOR AMI_PI_TODO: + ;push 0 + + ; Push a pointer to the EFI_SEC_PEI_HAND_OFF data structure onto the stack + push MKF_CAR_BASE_ADDRESS + +ELSE + ; Pass stack size into the PEI Core + push MKF_CAR_TOTAL_SIZE + + ; Pass BFV into the PEI Core + push DWORD PTR ds:[0FFFFFFFCh] +ENDIF + + ;mov edi, 0FFFFFFE0h + call DWORD PTR ds:[0FFFFFFE0h] +;---Does not return--- + +align 16 +MTRR_TABLE label byte + dw MTRR_DEF_TYPE + dw MTRR_PHYS_BASE_0, MTRR_PHYS_MASK_0 + dw MTRR_PHYS_BASE_1, MTRR_PHYS_MASK_1 + dw MTRR_PHYS_BASE_2, MTRR_PHYS_MASK_2 + dw MTRR_PHYS_BASE_3, MTRR_PHYS_MASK_3 + dw MTRR_PHYS_BASE_4, MTRR_PHYS_MASK_4 + dw MTRR_PHYS_BASE_5, MTRR_PHYS_MASK_5 + dw MTRR_PHYS_BASE_6, MTRR_PHYS_MASK_6 + dw MTRR_PHYS_BASE_7, MTRR_PHYS_MASK_7 + dw MTRR_FIX_64K_00000 + dw MTRR_FIX_16K_80000 + dw MTRR_FIX_16K_A0000 + dw MTRR_FIX_4K_C0000, MTRR_FIX_4K_C8000 + dw MTRR_FIX_4K_D0000, MTRR_FIX_4K_D8000 + dw MTRR_FIX_4K_E0000, MTRR_FIX_4K_E8000 + dw MTRR_FIX_4K_F0000, MTRR_FIX_4K_F8000 +MTRR_TABLE_END label byte + +;---------------------------------------------- +align 16 +GDT_BASE: +NULL_SEL equ $-GDT_BASE ;NULL Selector 0 + dd 0, 0 + +DATA_SEL equ $-GDT_BASE ; Selector 8, Data 0-ffffffff 32 bit + dd 0000ffffh + dd 00cf9300h + +CODE_SEL equ $-GDT_BASE ; Selector 10h, CODE 0-ffffffff 32 bit + dd 0000ffffh + dd 00cf9b00h + +; We only need this because Intel DebugSupport driver +; (RegisterPeriodicCallback function) assumes that selector 0x20 is valid +; The funciton sets 0x20 as a code selector in IDT +; +; To switch to 16 bit, Selectors SYS16_CODE_SEL and SYS16_DATA_SEL are used. +; +; System data segment descriptor +; +SYS_DATA_SEL equ $ - GDT_BASE ; Selector [0x18] + dd 0000FFFFh ;0 - f_ffff + dd 00cf9300h ;data, expand-up, notwritable, 32-bit + +; System code segment descriptor +SYS_CODE_SEL equ $ - GDT_BASE ; Selector [0x20] + dd 0000FFFFh ;0 - f_ffff + dd 00cf9b00h ;data, expand-up, writable, 32-bit +SPARE3_SEL equ $-GDT_BASE ; Selector [0x28] + dd 0, 0 +SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30] + dd 0000FFFFh + dd 00cf9300h +SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38] + dd 0000FFFFh + dd 00af9b00h +SPARE4_SEL equ $-GDT_BASE ; Selector [0x40] + dd 0, 0 +GDT_SIZE equ $-GDT_BASE ;Size of Descriptor Table + +GdtDescriptor: + dw GDT_SIZE - 1 ; GDT limit + dd offset GDT_BASE ; GDT base Relative to 4G. + +STARTUP_SEG ENDS + +end + +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1987-2013, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* diff --git a/Core/CPU/x64/AmiX64Lib.cif b/Core/CPU/x64/AmiX64Lib.cif new file mode 100644 index 0000000..5070b67 --- /dev/null +++ b/Core/CPU/x64/AmiX64Lib.cif @@ -0,0 +1,52 @@ +<component> + name = "AmiX64Lib" + category = ModulePart + LocalRoot = "Core\CPU\x64\" + RefName = "AmiX64Lib" +[files] +"AmiX64Lib.sdl" +"AmiX64Lib.mak" +"x64CLib.c" +"x64AsmLib\checkpoint.asm" +"x64AsmLib\CPULib_CpuID.asm" +"x64AsmLib\CPULib_DisableInterrupt.asm" +"x64AsmLib\CPULib_EnableInterrupt.asm" +"x64AsmLib\CPULib_GetInterruptState.asm" +"x64AsmLib\CPULIB_GetPageTable.asm" +"x64AsmLib\CPULib_LoadGdt.asm" +"x64AsmLib\CPULib_LoadIdt.asm" +"x64AsmLib\CPULib_LockByteDec.asm" +"x64AsmLib\CPULib_LockByteInc.asm" +"x64AsmLib\CPULib_Pause.asm" +"x64AsmLib\CPULib_SaveGdt.asm" +"x64AsmLib\CPULib_SaveIdt.asm" +"x64AsmLib\DisableCacheInCR0.asm" +"x64AsmLib\EnableCacheInCR0.asm" +"x64AsmLib\EnableMachineCheck.asm" +"x64AsmLib\GetCpuTimer.asm" +"x64AsmLib\GetCsSegment.asm" +"x64AsmLib\GetPowerOfTwo64.asm" +"x64AsmLib\HltCpu.asm" +"x64AsmLib\IoRead16.asm" +"x64AsmLib\IoRead32.asm" +"x64AsmLib\IoRead64.asm" +"x64AsmLib\IoRead8.asm" +"x64AsmLib\IoWrite16.asm" +"x64AsmLib\IoWrite32.asm" +"x64AsmLib\IoWrite64.asm" +"x64AsmLib\IoWrite8.asm" +"x64AsmLib\MemCpy.asm" +"x64AsmLib\MemRead32.asm" +"x64AsmLib\MemReadWrite32.asm" +"x64AsmLib\MemSet.asm" +"x64AsmLib\ReadCr3.asm" +"x64AsmLib\ReadMsr.asm" +"x64AsmLib\ReadRtdsc.asm" +"x64AsmLib\WaitForever.asm" +"x64AsmLib\WaitForSemaphore.asm" +"x64AsmLib\WaitUntilZero32.asm" +"x64AsmLib\WaitUntilZero8.asm" +"x64AsmLib\WriteCr3.asm" +"x64AsmLib\WriteMsr.asm" +"x64AsmLib\MemCpy32.asm" +<endComponent> diff --git a/Core/CPU/x64/AmiX64Lib.mak b/Core/CPU/x64/AmiX64Lib.mak new file mode 100644 index 0000000..e2cd482 --- /dev/null +++ b/Core/CPU/x64/AmiX64Lib.mak @@ -0,0 +1,63 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/Modules/x64Core/AmiX64Lib.mak 1 10/13/06 8:37p Felixp $ +# +# $Revision: 1 $ +# +# $Date: 10/13/06 8:37p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/Modules/x64Core/AmiX64Lib.mak $ +# +# 1 10/13/06 8:37p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: AmiX64Lib.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +AmiX64Lib : $(BUILD_DIR)\AmiX64Lib.mak AmiX64LibBin + +$(BUILD_DIR)\AmiX64Lib.mak : $(AmiX64Lib_DIR)\$(@B).cif $(AmiX64Lib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(AmiX64Lib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +!IF "$(PROCESSOR)"=="x64" +AmiDxeLibBin : $(BUILD_DIR)\AmiX64Lib.lib +$(BUILD_DIR)\AmiX64Lib.lib : AmiX64Lib +!ENDIF + +AmiX64LibBin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\AmiX64Lib.mak all\ + TYPE=LIBRARY +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/x64/AmiX64Lib.sdl b/Core/CPU/x64/AmiX64Lib.sdl new file mode 100644 index 0000000..79b7e36 --- /dev/null +++ b/Core/CPU/x64/AmiX64Lib.sdl @@ -0,0 +1,19 @@ +TOKEN + Name = "AmiX64Lib_SUPPORT" + Value = "1" + Help = "Main switch to enable AmiX64Lib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "AmiX64Lib_DIR" +End + +MODULE + Help = "Includes AmiX64Lib.mak to Project" + File = "AmiX64Lib.mak" +End + diff --git a/Core/CPU/x64/EfiJump.h b/Core/CPU/x64/EfiJump.h new file mode 100644 index 0000000..61f371f --- /dev/null +++ b/Core/CPU/x64/EfiJump.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiJump.h + +Abstract: + + This is the Setjump/Longjump pair for an x64 processor. + +--*/ + +#ifndef _EFI_JUMP_H_ +#define _EFI_JUMP_H_ + +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + UINT64 Rdi; + UINT64 Rsi; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; + UINT32 MxCsr; + UINT8 XmmBuffer[160]; // XMM6-XMM15 +} EFI_JUMP_BUFFER; + +#endif diff --git a/Core/CPU/x64/Foundationx64.cif b/Core/CPU/x64/Foundationx64.cif new file mode 100644 index 0000000..cb10e7a --- /dev/null +++ b/Core/CPU/x64/Foundationx64.cif @@ -0,0 +1,15 @@ +<component> + name = "Foundationx64" + category = ModulePart + LocalRoot = "Core\CPU\x64\" + RefName = "Foundationx64" +[files] +"Foundationx64.sdl" +"Foundationx64.mak" +"ProcessorAsms.Asm" +"EfiJump.h" +"PeCoffLoaderEx.c" +"PeCoffLoaderEx.h" +"Processor.c" +"Processor.h" +<endComponent> diff --git a/Core/CPU/x64/Foundationx64.mak b/Core/CPU/x64/Foundationx64.mak new file mode 100644 index 0000000..488e672 --- /dev/null +++ b/Core/CPU/x64/Foundationx64.mak @@ -0,0 +1,65 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/EDK/x64/Foundationx64.mak 1 8/24/06 12:36p Felixp $ +# +# $Revision: 1 $ +# +# $Date: 8/24/06 12:36p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/EDK/x64/Foundationx64.mak $ +# +# 1 8/24/06 12:36p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: Foundationx64.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +Foundationx64 : $(BUILD_DIR)\Foundationx64.mak Foundationx64Bin + +$(BUILD_DIR)\Foundationx64.mak : $(Foundationx64_DIR)\$(@B).cif $(Foundationx64_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(Foundationx64_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +!IF "$(PROCESSOR)"=="x64" +FoundationBin : $(BUILD_DIR)\Foundationx64.lib +$(BUILD_DIR)\Foundationx64.lib : Foundationx64 +!ENDIF + + +Foundationx64Bin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\Foundationx64.mak all\ + "CFLAGS=$(CFLAGS) /I$(Foundation_DIR)"\ + TYPE=LIBRARY +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/x64/Foundationx64.sdl b/Core/CPU/x64/Foundationx64.sdl new file mode 100644 index 0000000..bb61c1a --- /dev/null +++ b/Core/CPU/x64/Foundationx64.sdl @@ -0,0 +1,19 @@ +TOKEN + Name = "Foundationx64_SUPPORT" + Value = "1" + Help = "Main switch to enable Foundationx64 support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "Foundationx64_DIR" +End + +MODULE + Help = "Includes Foundationx64.mak to Project" + File = "Foundationx64.mak" +End + diff --git a/Core/CPU/x64/MiscLib/Misc.asm b/Core/CPU/x64/MiscLib/Misc.asm new file mode 100644 index 0000000..facdd89 --- /dev/null +++ b/Core/CPU/x64/MiscLib/Misc.asm @@ -0,0 +1,124 @@ +;********************************************************************** +;********************************************************************** +;** ** +;** (C)Copyright 1985-2010, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;********************************************************************** +;********************************************************************** + +;********************************************************************** +; $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MiscX64Lib/Misc.asm 2 10/04/12 9:17a Davidhsieh $ +; +; $Revision: 2 $ +; +; $Date: 10/04/12 9:17a $ +;********************************************************************** +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MiscX64Lib/Misc.asm $ +; +; 2 10/04/12 9:17a Davidhsieh +; Add MpMtrrSynchUpEntry and MpMtrrSynchUpExit procedures +; +; 1 5/15/12 5:41a Davidhsieh +; +; 1 5/08/12 6:02a Dukeyeh +; [TAG] EIP89382 +; [Category] Improvement +; [Description] clear direction flag inside Timer callback function. +; [Files] MiscX64Lib.cif +; Misc.asm +; MiscX64Lib.sdl +; MiscX64Lib.mak +; +; 6 1/13/10 2:13p Felixp +; +;********************************************************************** +;<AMI_FHDR_START> +; +; Name: Misc +; +; Description: +; +;<AMI_FHDR_END> +;********************************************************************** + +.code + +ClearDirectionFlag Proc + cld + ret +ClearDirectionFlag endp + +MpMtrrSynchUpEntry PROC PUBLIC + ; + ; Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29) + ; + mov rax, cr0 + and rax, 0DFFFFFFFh + or rax, 040000000h + mov cr0, rax + ; + ; Flush cache + ; + wbinvd + ; + ; Clear PGE flag Bit 7 + ; + mov rax, cr4 + mov rdx, rax + and rax, 0FFFFFF7Fh + mov cr4, rax + ; + ; Flush all TLBs + ; + mov rax, cr3 + mov cr3, rax + + mov rax, rdx + + ret + +MpMtrrSynchUpEntry ENDP + +MpMtrrSynchUpExit PROC PUBLIC + ; + ; Flush all TLBs the second time + ; + mov rax, cr3 + mov cr3, rax + ; + ; Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29) + ; + mov rax, cr0 + and rax, 09FFFFFFFh + mov cr0, rax + ; + ; Set PGE Flag in CR4 if set + ; + mov cr4, rcx + ret + +MpMtrrSynchUpExit ENDP + +END + +;********************************************************************** +;********************************************************************** +;** ** +;** (C)Copyright 1985-2010, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;********************************************************************** +;**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/x64/MiscLib/MiscX64Lib.cif b/Core/CPU/x64/MiscLib/MiscX64Lib.cif new file mode 100644 index 0000000..c05edf2 --- /dev/null +++ b/Core/CPU/x64/MiscLib/MiscX64Lib.cif @@ -0,0 +1,10 @@ +<component> + name = "MiscX64Lib" + category = ModulePart + LocalRoot = "Core\CPU\x64\MiscLib" + RefName = "MiscX64Lib" +[files] +"Misc.asm" +"MiscX64Lib.sdl" +"MiscX64Lib.mak" +<endComponent> diff --git a/Core/CPU/x64/MiscLib/MiscX64Lib.mak b/Core/CPU/x64/MiscLib/MiscX64Lib.mak new file mode 100644 index 0000000..61e7446 --- /dev/null +++ b/Core/CPU/x64/MiscLib/MiscX64Lib.mak @@ -0,0 +1,74 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MiscX64Lib/MiscX64Lib.mak 1 5/15/12 5:41a Davidhsieh $ +# +# $Revision: 1 $ +# +# $Date: 5/15/12 5:41a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/MiscX64Lib/MiscX64Lib.mak $ +# +# 1 5/15/12 5:41a Davidhsieh +# +# 1 5/08/12 6:02a Dukeyeh +# [TAG] EIP89382 +# [Category] Improvement +# [Description] clear direction flag inside Timer callback function. +# [Files] MiscX64Lib.cif +# Misc.asm +# MiscX64Lib.sdl +# MiscX64Lib.mak +# +# 1 10/13/06 8:37p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: MiscX64Lib.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +MiscX64Lib : $(BUILD_DIR)\MiscX64Lib.mak MiscX64LibBin + +$(BUILD_DIR)\MiscX64Lib.mak : $(MiscX64Lib_DIR)\$(@B).cif $(MiscX64Lib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(MiscX64Lib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +!IF "$(PROCESSOR)"=="x64" +AmiDxeLibBin : $(BUILD_DIR)\MiscX64Lib.lib +$(BUILD_DIR)\MiscX64Lib.lib : MiscX64Lib +!ENDIF + +MiscX64LibBin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\MiscX64Lib.mak all\ + TYPE=LIBRARY +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CPU/x64/MiscLib/MiscX64Lib.sdl b/Core/CPU/x64/MiscLib/MiscX64Lib.sdl new file mode 100644 index 0000000..a9c676e --- /dev/null +++ b/Core/CPU/x64/MiscLib/MiscX64Lib.sdl @@ -0,0 +1,19 @@ +TOKEN + Name = "MiscX64Lib_SUPPORT" + Value = "1" + Help = "Main switch to enable MiscX64Lib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "MiscX64Lib_DIR" +End + +MODULE + Help = "Includes MiscX64Lib.mak to Project" + File = "MiscX64Lib.mak" +End + diff --git a/Core/CPU/x64/PeCoffLoaderEx.c b/Core/CPU/x64/PeCoffLoaderEx.c new file mode 100644 index 0000000..ff216a7 --- /dev/null +++ b/Core/CPU/x64/PeCoffLoaderEx.c @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + x64 Specific relocation fixups + +Revision History + +--*/ + +#include "Tiano.h" +#include "EfiImage.h" + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + Performs an x64 specific relocation fixup + +Arguments: + Reloc - Pointer to the relocation record + Fixup - Pointer to the address to fix up + FixupData - Pointer to a buffer to log the fixups + Adjust - The offset to adjust the fixup + +Returns: + EFI_UNSUPPORTED - relocate unsupported + +--*/ +{ + return EFI_UNSUPPORTED; +} + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +{ + if ((Machine == EFI_IMAGE_MACHINE_IA32) || (Machine == EFI_IMAGE_MACHINE_X64) || + (Machine == EFI_IMAGE_MACHINE_EBC)) { + return TRUE; + } + + return FALSE; +} diff --git a/Core/CPU/x64/PeCoffLoaderEx.h b/Core/CPU/x64/PeCoffLoaderEx.h new file mode 100644 index 0000000..a3f78e0 --- /dev/null +++ b/Core/CPU/x64/PeCoffLoaderEx.h @@ -0,0 +1,85 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PeCoffLoaderEx.h + +Abstract: + + x64 Specific relocation fixups + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an x64 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - relocate unsupported + +--*/ +; + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +; + +#endif diff --git a/Core/CPU/x64/Processor.c b/Core/CPU/x64/Processor.c new file mode 100644 index 0000000..21a1649 --- /dev/null +++ b/Core/CPU/x64/Processor.c @@ -0,0 +1,146 @@ +/*++ + +Copyright 2005 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +// +// Prototypes +// +EFI_STATUS +EFIAPI +TransferControlSetJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +TransferControlLongJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +// +// Table declarations +// +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + TransferControlSetJump, + TransferControlLongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + FlushInstructionCacheFlush +}; + + +EFI_STATUS +EFIAPI +InstallEfiPeiTransferControl( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + This - Pointer to transfer control mechanism. + +--*/ +{ + *This = &mTransferControl; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + This - Pointer to flush instruction cache mechanism. + +--*/ +{ + *This = &mFlushInstructionCache; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + In the case of IA32, this flushing is not necessary and is thus not implemented. + +Arguments: + + Pointer to CPU Architectural Protocol interface + Start adddress in memory to flush + Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} + diff --git a/Core/CPU/x64/Processor.h b/Core/CPU/x64/Processor.h new file mode 100644 index 0000000..cdf2992 --- /dev/null +++ b/Core/CPU/x64/Processor.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + Processor.h + +Abstract: + This file contains the x64 processor specific definitions + +--*/ + +#ifndef _PROCESSOR_H_ +#define _PROCESSOR_H_ + +#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE) + +#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE) + +#endif diff --git a/Core/CPU/x64/ProcessorAsms.Asm b/Core/CPU/x64/ProcessorAsms.Asm new file mode 100644 index 0000000..ebd8b03 --- /dev/null +++ b/Core/CPU/x64/ProcessorAsms.Asm @@ -0,0 +1,186 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2005 - 2007, Intel Corporation +; All rights reserved. This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; ProcessorAsms.Asm +; +; Abstract: +; This is separated from processor.c to allow this functions to be built with /O1 +; +; +;------------------------------------------------------------------------------ + +text SEGMENT + + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter // rcx +; Parameter - Parameter to pass in // rdx +; NewStack - New Location of the stack // r8 +; NewBsp - New BSP // r9 - not used +; +; Returns: +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchStacks PROC PUBLIC + + ; Adjust stack for + ; 1) leave 4 registers space + ; 2) let it 16 bytes aligned after call + sub r8, 20h + and r8w, 0fff0h ; do not assume 16 bytes aligned + + mov rsp, r8 ; rsp = NewStack + mov r10, rcx ; save EntryPoint + mov rcx, rdx ; Arg1 = Parameter + call r10 ; r10 = copy of EntryPoint + ; + ; no ret as we have a new stack and we jumped to the new location + ; + ret + +SwitchStacks ENDP + + +EFI_SUCCESS equ 0 +EFI_WARN_RETURN_FROM_LONG_JUMP equ 5 + +; +; Generated by h2inc run manually +; +_EFI_JUMP_BUFFER STRUCT 2t +_rbx QWORD ? +_rsp QWORD ? +_rbp QWORD ? +_rdi QWORD ? +_rsi QWORD ? +_r10 QWORD ? +_r11 QWORD ? +_r12 QWORD ? +_r13 QWORD ? +_r14 QWORD ? +_r15 QWORD ? +_rip QWORD ? +_MxCsr DWORD ? +_XmmBuffer DB 160 DUP (?) +_EFI_JUMP_BUFFER ENDS + +EFI_JUMP_BUFFER TYPEDEF _EFI_JUMP_BUFFER + + +; +;Routine Description: +; +; This routine implements the x64 variant of the SetJump call. Its +; responsibility is to store system state information for a possible +; subsequent LongJump. +; +;Arguments: +; +; Pointer to CPU context save buffer. +; +;Returns: +; +; EFI_SUCCESS +; +; EFI_STATUS +; EFIAPI +; TransferControlLongJump ( +; IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, +; IN EFI_JUMP_BUFFER *Jump +; ); +; +; rcx - *This +; rdx - JumpBuffer +; +PUBLIC TransferControlSetJump +TransferControlSetJump PROC + mov (EFI_JUMP_BUFFER PTR [rdx])._rbx, rbx + mov (EFI_JUMP_BUFFER PTR [rdx])._rsp, rsp + mov (EFI_JUMP_BUFFER PTR [rdx])._rbp, rbp + mov (EFI_JUMP_BUFFER PTR [rdx])._rdi, rdi + mov (EFI_JUMP_BUFFER PTR [rdx])._rsi, rsi + mov (EFI_JUMP_BUFFER PTR [rdx])._r10, r10 + mov (EFI_JUMP_BUFFER PTR [rdx])._r11, r11 + mov (EFI_JUMP_BUFFER PTR [rdx])._r12, r12 + mov (EFI_JUMP_BUFFER PTR [rdx])._r13, r13 + mov (EFI_JUMP_BUFFER PTR [rdx])._r14, r14 + mov (EFI_JUMP_BUFFER PTR [rdx])._r15, r15 + ; save non-volatile fp registers + stmxcsr (EFI_JUMP_BUFFER PTR [rdx])._MxCsr + lea rax, (EFI_JUMP_BUFFER PTR [rdx])._XmmBuffer + movdqu [rax], xmm6 + movdqu [rax + 10h], xmm7 + movdqu [rax + 20h], xmm8 + movdqu [rax + 30h], xmm9 + movdqu [rax + 40h], xmm10 + movdqu [rax + 50h], xmm11 + movdqu [rax + 60h], xmm12 + movdqu [rax + 70h], xmm13 + movdqu [rax + 80h], xmm14 + movdqu [rax + 90h], xmm15 + mov rax, QWORD PTR [rsp+0] + mov (EFI_JUMP_BUFFER PTR [rdx])._rip, rax + mov rax, EFI_SUCCESS + ret + +TransferControlSetJump ENDP + +; +; EFI_STATUS +; EFIAPI +; TransferControlLongJump ( +; IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, // rcx +; IN EFI_JUMP_BUFFER *Jump // rdx +; ); +; +; +PUBLIC TransferControlLongJump +TransferControlLongJump PROC + ; load non-volatile fp registers + ldmxcsr (EFI_JUMP_BUFFER PTR [rdx])._MxCsr + lea rax, (EFI_JUMP_BUFFER PTR [rdx])._XmmBuffer + movdqu xmm6, [rax] + movdqu xmm7, [rax + 10h] + movdqu xmm8, [rax + 20h] + movdqu xmm9, [rax + 30h] + movdqu xmm10, [rax + 40h] + movdqu xmm11, [rax + 50h] + movdqu xmm12, [rax + 60h] + movdqu xmm13, [rax + 70h] + movdqu xmm14, [rax + 80h] + movdqu xmm15, [rax + 90h] + ; set return from SetJump to EFI_WARN_RETURN_FROM_LONG_JUMP + mov rax, EFI_WARN_RETURN_FROM_LONG_JUMP + mov rbx, (EFI_JUMP_BUFFER PTR [rdx])._rbx + mov rsp, (EFI_JUMP_BUFFER PTR [rdx])._rsp + mov rbp, (EFI_JUMP_BUFFER PTR [rdx])._rbp + mov rdi, (EFI_JUMP_BUFFER PTR [rdx])._rdi + mov rsi, (EFI_JUMP_BUFFER PTR [rdx])._rsi + mov r10, (EFI_JUMP_BUFFER PTR [rdx])._r10 + mov r11, (EFI_JUMP_BUFFER PTR [rdx])._r11 + mov r12, (EFI_JUMP_BUFFER PTR [rdx])._r12 + mov r13, (EFI_JUMP_BUFFER PTR [rdx])._r13 + mov r14, (EFI_JUMP_BUFFER PTR [rdx])._r14 + mov r15, (EFI_JUMP_BUFFER PTR [rdx])._r15 + add rsp, 8 ;pop the eip + jmp QWORD PTR (EFI_JUMP_BUFFER PTR [rdx])._rip + ; set return from SetJump to EFI_WARN_RETURN_FROM_LONG_JUMP + mov rax, EFI_WARN_RETURN_FROM_LONG_JUMP + ret +TransferControlLongJump ENDP + +text ENDS +END diff --git a/Core/CPU/x64/x64AsmLib/CPULIB_GetPageTable.asm b/Core/CPU/x64/x64AsmLib/CPULIB_GetPageTable.asm new file mode 100644 index 0000000..973357f --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULIB_GetPageTable.asm @@ -0,0 +1,80 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULIB_GetPageTable.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULIB_GetPageTable.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULIB_GetPageTable +; +; Description: +; VOID* CPULIB_GetPageTable() retrieves the address of the page table. +; +; Input: +; VOID. +; +; Output: +; VOID* address of the page table. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULIB_GetPageTable proc + mov rax, cr3 + ret +CPULIB_GetPageTable endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_CpuID.asm b/Core/CPU/x64/x64AsmLib/CPULib_CpuID.asm new file mode 100644 index 0000000..53719f2 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_CpuID.asm @@ -0,0 +1,130 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_CpuID.asm 2 11/11/11 3:40p Artems $ +; +; $Revision: 2 $ +; +; $Date: 11/11/11 3:40p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_CpuID.asm $ +; +; 2 11/11/11 3:40p Artems +; Bug fix: Verify pointer is not NULL, when return value +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_CpuID +; +; Description: +; VOID CPULib_CpuID(IN UINT32 CpuIDIndex, IN UINT32 *pRegEAX, +; IN UINT32 *pRegEBX, IN UINT32 *pRegECX, IN UINT32 *pRegEDX) issues the +; CPUID instruction with the index provided and returns the register values. +; +; Input: +; IN UINT32 CpuIDIndex +; 32-bit CPUID index. +; +; IN UINT32 *pRegEAX +; Value of EAX after CPUID instruction. +; +; IN UINT32 *pRegEBX +; Value of EBX after CPUID instruction. +; +; IN UINT32 *pRegECX +; Value of ECX after CPUID instruction. +; +; IN UINT32 *pRegEDX +; Value of EDX after CPUID instruction. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_CpuID proc +;rcx = CpuIDIndex +;rdx = pRegEax +;r8 = pRegEBX +;r9 = pRegECX +;[rsp + 8] = pRegEDX:DWORD + + push rbx + mov r11, [rsp + 30h] ;pRegEDX + mov r10, r9 ;pRegECX + mov r9, r8 ;pRegEBX + mov r8, rdx ;pRegEAX + + mov eax, ecx + mov ecx, [r10] + cpuid + + or r8, r8 + jz skip1 + mov [r8], eax +skip1: + or r9, r9 + jz skip2 + mov [r9], ebx +skip2: + or r10, r10 + jz skip3 + mov [r10], ecx +skip3: + or r11, r11 + jz skip4 + mov [r11], edx +skip4: + pop rbx + ret +CPULib_CpuID endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_DisableInterrupt.asm b/Core/CPU/x64/x64AsmLib/CPULib_DisableInterrupt.asm new file mode 100644 index 0000000..6c63f8a --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_DisableInterrupt.asm @@ -0,0 +1,81 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_DisableInterrupt.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_DisableInterrupt.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_DisableInterrupt +; +; Description: +; VOID CPULib_DisableInterrupt() disables interrupts on the CPU. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_DisableInterrupt PROC PUBLIC +; Disable Interrupt + cli + ret +CPULib_DisableInterrupt ENDP + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_EnableInterrupt.asm b/Core/CPU/x64/x64AsmLib/CPULib_EnableInterrupt.asm new file mode 100644 index 0000000..bc43c62 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_EnableInterrupt.asm @@ -0,0 +1,81 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_EnableInterrupt.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_EnableInterrupt.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_EnableInterrupt +; +; Description: +; VOID CPULib_EnableInterrupt() enables interrupts on the CPU. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_EnableInterrupt PROC PUBLIC +; Enable Interrupt + sti + ret +CPULib_EnableInterrupt ENDP + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_GetInterruptState.asm b/Core/CPU/x64/x64AsmLib/CPULib_GetInterruptState.asm new file mode 100644 index 0000000..436cba7 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_GetInterruptState.asm @@ -0,0 +1,87 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_GetInterruptState.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_GetInterruptState.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_GetInterruptState +; +; Description: +; BOOLEAN CPULib_GetInterruptState()returns the current CPU interrupt state. +; +; Input: +; VOID. +; +; Output: +; FALSE if interrupts are disabled; otherwise TRUE. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_GetInterruptState PROC PUBLIC + xor cl, cl + pushf ; push flags onto stack. + pop ax ; eax = flags. + bt ax, 9 ; IF (bit 9) if set, set carry flag. + ; Interrupts are allowed if IF is set. + adc cl, 0 ; CL = IF = CF. + + mov al, cl ; Return value + ret +CPULib_GetInterruptState ENDP + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_LoadGdt.asm b/Core/CPU/x64/x64AsmLib/CPULib_LoadGdt.asm new file mode 100644 index 0000000..1fc3c23 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_LoadGdt.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LoadGdt.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LoadGdt.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_LoadGdt +; +; Description: +; VOID CPULib_LoadGdt(IN VOID *ptr) loads the GDT at the location pointed to +; by ptr. +; +; Input: +; IN VOID *ptr +; Address of the GDT to be loaded. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_LoadGdt proc + lgdt fword ptr [rcx] + ret +CPULib_LoadGdt endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_LoadIdt.asm b/Core/CPU/x64/x64AsmLib/CPULib_LoadIdt.asm new file mode 100644 index 0000000..3c4afc8 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_LoadIdt.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LoadIdt.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LoadIdt.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_LoadIdt +; +; Description: +; VOID CPULib_LoadIdt(IN VOID *ptr) loads the IDT at the location provided +; by ptr. +; +; Input: +; IN VOID *ptr +; Address of the IDT to be loaded. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_LoadIdt proc + lidt fword ptr [rcx] + ret +CPULib_LoadIdt endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_LockByteDec.asm b/Core/CPU/x64/x64AsmLib/CPULib_LockByteDec.asm new file mode 100644 index 0000000..433bd1b --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_LockByteDec.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LockByteDec.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LockByteDec.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_LockByteDec +; +; Description: +; VOID CPULib_LockByteDec(IN UINT8 *ptr) locks the preceeding byte before +; the address pointed to by ptr. +; +; Input: +; IN UINT8 *ptr +; Address to the byte which follows the desired byte to be locked. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_LockByteDec proc + lock dec byte ptr [rcx] + ret +CPULib_LockByteDec endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_LockByteInc.asm b/Core/CPU/x64/x64AsmLib/CPULib_LockByteInc.asm new file mode 100644 index 0000000..83addc8 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_LockByteInc.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LockByteInc.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_LockByteInc.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_LockByteInc +; +; Description: +; VOID CPULib_LockByteInc(IN UINT8 *ptr) locks the next byte after the +; address pointed to by ptr. +; +; Input: +; IN UINT8 *ptr +; Address to the byte which preceeds the desired byte to be locked. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_LockByteInc proc + lock inc byte ptr [rcx] + ret +CPULib_LockByteInc endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_Pause.asm b/Core/CPU/x64/x64AsmLib/CPULib_Pause.asm new file mode 100644 index 0000000..c7d2574 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_Pause.asm @@ -0,0 +1,80 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_Pause.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_Pause.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_Pause +; +; Description: +; VOID CPULib_Pause() performs the pause assembly instruction. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_Pause Proc + pause + ret +CPULib_Pause endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_SaveGdt.asm b/Core/CPU/x64/x64AsmLib/CPULib_SaveGdt.asm new file mode 100644 index 0000000..28258cf --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_SaveGdt.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_SaveGdt.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_SaveGdt.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_SaveGdt +; +; Description: +; VOID CPULib_SaveGdt(IN VOID *ptr) stores the loaded GDT at the location +; provided by ptr. +; +; Input: +; IN VOID *ptr +; Address to save the GDT. User is responsible for allocating the necessary +; memory resources. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_SaveGdt proc + sgdt fword ptr [rcx] + ret +CPULib_SaveGdt endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/CPULib_SaveIdt.asm b/Core/CPU/x64/x64AsmLib/CPULib_SaveIdt.asm new file mode 100644 index 0000000..046b7f6 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/CPULib_SaveIdt.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_SaveIdt.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/CPULib_SaveIdt.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: CPULib_SaveIdt +; +; Description: +; VOID CPULib_SaveIdt(IN VOID *ptr) stores the loaded IDT at the location +; provided by ptr. +; +; Input: +; IN VOID *ptr +; Address to save the IDT. User is responsible for allocating the necessary +; memory resources. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +CPULib_SaveIdt proc + sidt fword ptr [rcx] + ret +CPULib_SaveIdt endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/DisableCacheInCR0.asm b/Core/CPU/x64/x64AsmLib/DisableCacheInCR0.asm new file mode 100644 index 0000000..c03cd1f --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/DisableCacheInCR0.asm @@ -0,0 +1,84 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/DisableCacheInCR0.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/DisableCacheInCR0.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: DisableCacheInCR0 +; +; Description: +; VOID DisableCacheInCR0() disables the CPU cache using the CR0 register. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +DisableCacheInCR0 PROC PUBLIC + wbinvd + mov rax, cr0 + or eax, 060000000h ;SET CD, NW + mov cr0, rax + wbinvd ;Invalidate cache + ret +DisableCacheInCR0 ENDP + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/EnableCacheInCR0.asm b/Core/CPU/x64/x64AsmLib/EnableCacheInCR0.asm new file mode 100644 index 0000000..7633a1f --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/EnableCacheInCR0.asm @@ -0,0 +1,84 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/EnableCacheInCR0.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/EnableCacheInCR0.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: EnableCacheInCR0 +; +; Description: +; VOID EnableCacheInCR0() enables the CPU cache using the CR0 register. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +EnableCacheInCR0 PROC PUBLIC +; Enable cache + mov rax, cr0 + and eax, 09fffffffh ;SET CD, NW + mov cr0, rax + wbinvd + ret +EnableCacheInCR0 ENDP + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/EnableMachineCheck.asm b/Core/CPU/x64/x64AsmLib/EnableMachineCheck.asm new file mode 100644 index 0000000..b220afd --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/EnableMachineCheck.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/EnableMachineCheck.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/EnableMachineCheck.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: EnableMachineCheck +; +; Description: +; VOID EnableMachineCheck() sets the Machine Check Exception bit in CR4, +; which enables machine check interrupts to occur. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +EnableMachineCheck proc + mov rax, cr4 + or eax, 1 SHL 6 + mov cr4, rax + ret +EnableMachineCheck endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/GetCpuTimer.asm b/Core/CPU/x64/x64AsmLib/GetCpuTimer.asm new file mode 100644 index 0000000..f606744 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/GetCpuTimer.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/GetCpuTimer.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/GetCpuTimer.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: GetCpuTimer +; +; Description: +; UINT64 GetCpuTimer() returns the value of the CPU timer. +; +; Input: +; None. +; +; Output: +; UINT64 value of the CPU timer. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +GetCpuTimer proc + rdtsc + shl rdx,32 + or rax, rdx + ret +GetCpuTimer endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/GetCsSegment.asm b/Core/CPU/x64/x64AsmLib/GetCsSegment.asm new file mode 100644 index 0000000..02138c3 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/GetCsSegment.asm @@ -0,0 +1,79 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/GetCsSegment.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/GetCsSegment.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: GetCsSegment +; +; Description: +; UINT16 GetCsSegment() retreives the value of the CS register. +; +; Input: +; VOID. +; +; Output: +; UINT16 value of CS. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +GetCsSegment proc + mov ax, cs + ret +GetCsSegment endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/GetPowerOfTwo64.asm b/Core/CPU/x64/x64AsmLib/GetPowerOfTwo64.asm new file mode 100644 index 0000000..9cebe72 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/GetPowerOfTwo64.asm @@ -0,0 +1,84 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/GetPowerOfTwo64.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/GetPowerOfTwo64.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: GetPowerOfTwo64 +; +; Description: +; UINT64 GetPowerOfTwo64(IN UINT64 Input) returns the highest bit set in +; the provided UINT64 Input. Equivalent to 1 << log2(x). +; +; Input: +; IN UINT64 Input +; The 64-bit value to check for its highest bit. +; +; Output: +; UINT64 value of the highest bit; if Input is 0, returns 0. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +GetPowerOfTwo64 proc + bsr rdx, rcx + xor rax, rax + bts rax, rdx + ret +GetPowerOfTwo64 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/HltCpu.asm b/Core/CPU/x64/x64AsmLib/HltCpu.asm new file mode 100644 index 0000000..a8c8a6e --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/HltCpu.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/HltCpu.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/HltCpu.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: HltCpu +; +; Description: +; VOID HltCpu() halts the CPU. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +HltCpu Proc +@@: + cli + hlt + jmp @b + ret +HltCpu endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoRead16.asm b/Core/CPU/x64/x64AsmLib/IoRead16.asm new file mode 100644 index 0000000..3403a34 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoRead16.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead16.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead16.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoRead16 +; +; Description: +; UINT16 IoRead16(IN UINT16 Port) reads the 16-bit value stored at the I/O +; port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to read 16-bits from. +; +; Output: +; UINT16 value stored at I/O Port. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoRead16 proc + mov dx, cx + in ax, dx + ret +IoRead16 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoRead32.asm b/Core/CPU/x64/x64AsmLib/IoRead32.asm new file mode 100644 index 0000000..510a01f --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoRead32.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead32.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead32.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoRead32 +; +; Description: +; UINT32 IoRead32(IN UINT16 Port) reads the 32-bit value stored at the I/O +; port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to read 32-bits from. +; +; Output: +; UINT32 value stored at I/O Port. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoRead32 proc + mov dx, cx + in eax, dx + ret +IoRead32 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoRead64.asm b/Core/CPU/x64/x64AsmLib/IoRead64.asm new file mode 100644 index 0000000..ff1da50 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoRead64.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead64.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead64.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoRead64 +; +; Description: +; UINT32 IoRead64(IN UINT16 Port) reads the 64-bit value stored at the I/O +; port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to read 64-bits from. +; +; Output: +; UINT64 value stored at I/O Port. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoRead64 proc + mov dx, cx + in rax, dx + ret +IoRead64 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoRead8.asm b/Core/CPU/x64/x64AsmLib/IoRead8.asm new file mode 100644 index 0000000..3dfd1fd --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoRead8.asm @@ -0,0 +1,83 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead8.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoRead8.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoRead8 +; +; Description: +; UINT8 IoRead8(IN UINT16 Port) reads the 8-bit value stored at the I/O +; port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to read 8-bits from. +; +; Output: +; UINT8 value stored at I/O Port. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoRead8 proc + mov dx, cx + in al, dx + ret +IoRead8 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoWrite16.asm b/Core/CPU/x64/x64AsmLib/IoWrite16.asm new file mode 100644 index 0000000..2616d1a --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoWrite16.asm @@ -0,0 +1,87 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite16.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite16.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoWrite16 +; +; Description: +; VOID IoWrite16(IN UINT16 Port, IN UINT16 Value) writes the 16-bit Value +; to the I/O port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to write 16-bits to. +; +; IN UINT16 Value +; 16-bits to write to the I/O Port. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoWrite16 proc + mov ax, dx + mov dx, cx + out dx, ax + ret +IoWrite16 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoWrite32.asm b/Core/CPU/x64/x64AsmLib/IoWrite32.asm new file mode 100644 index 0000000..98096d7 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoWrite32.asm @@ -0,0 +1,87 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite32.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite32.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoWrite32 +; +; Description: +; VOID IoWrite32(IN UINT16 Port, IN UINT32 Value) writes the 32-bit Value +; to the I/O port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to write 32-bits to. +; +; IN UINT32 Value +; 32-bits to write to the I/O Port. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoWrite32 proc + mov eax, edx + mov dx, cx + out dx, eax + ret +IoWrite32 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoWrite64.asm b/Core/CPU/x64/x64AsmLib/IoWrite64.asm new file mode 100644 index 0000000..c38c832 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoWrite64.asm @@ -0,0 +1,87 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite64.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite64.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoWrite64 +; +; Description: +; VOID IoWrite64(IN UINT16 Port, IN UINT64 Value) writes the 64-bit Value +; to the I/O port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to write 64-bits to. +; +; IN UINT64 Value +; 64-bits to write to the I/O Port. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoWrite64 proc + mov rax, rdx + mov dx, cx + out dx, rax + ret +IoWrite64 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/IoWrite8.asm b/Core/CPU/x64/x64AsmLib/IoWrite8.asm new file mode 100644 index 0000000..4bd5119 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/IoWrite8.asm @@ -0,0 +1,87 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite8.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/IoWrite8.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: IoWrite8 +; +; Description: +; VOID IoWrite8(IN UINT16 Port, IN UINT8 Value) writes the 8-bit Value to +; the I/O port defined by Port. +; +; Input: +; IN UINT16 Port +; I/O port to write 8-bits to. +; +; IN UINT8 Value +; 8-bits to write to the I/O Port. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +IoWrite8 proc + mov al, dl + mov dx, cx + out dx, al + ret +IoWrite8 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/MemCpy.asm b/Core/CPU/x64/x64AsmLib/MemCpy.asm new file mode 100644 index 0000000..a671ec8 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/MemCpy.asm @@ -0,0 +1,178 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemCpy.asm 2 3/09/11 1:58p Felixp $ +; +; $Revision: 2 $ +; +; $Date: 3/09/11 1:58p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemCpy.asm $ +; +; 2 3/09/11 1:58p Felixp +; MemCpy is updated to copy 8 bytes at a time (used to be 4) +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: MemCpy +; +; Description: +; VOID MemCpy(OUT VOID *pDestination, IN VOID *pSource, IN UINTN Count) +; copies Count bytes of memory from Source to Destination. +; +; Input: +; OUT VOID *pDestination +; Memory address where data shall be copied. User is responsible for +; allocating the necessary memory resources. +; +; IN VOID *pSource +; Memory address from where data shall be copied. +; +; IN UINTN Count +; Number of bytes to copy from pSource. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; This function checks for overlapping of source and destination and +; selects copy direction that prevents memory corruption. +; +;<AMI_PHDR_END> +;************************************************************************* +public memcpy +memcpy: +MemCpy proc + push rdi + push rsi + push rbx + pushf + mov rsi, rdx ; pSource + mov rdi, rcx ; pDestination + mov rcx, r8 ; Count + mov dl, 0 + ; if pSource > pDestination CopyForward + mov rax, rsi + sub rax, rdi ; rax = pSource-pDestination + jnb CopyForward; if pSource-pDestination > 0 CopyForward + ; if pSource+Count < pDestination then CopyForward + lea rbx, [rsi+rcx] ; rbx = pSource + Count + neg rax ; rax = pDestination - pSource + cmp rbx, rdi + jb CopyForward ; if (pSource + Count < pDestination ) CopyForward + ; Copy Backward + mov rsi, rbx; rsi = pSource + Count + lea rdi, [rdi+rcx]; rdi = pDestination + Count + mov dl, 1; Flag to indicate that we are copying backward + std; set direction flag to copy backward +CopyForward: + cmp rcx, 8 ; if (Counter<8) copy byte by byte + jb m8 + cmp rax, 8 ; if (pDestination - pSource < 8) copy byte by byte + jb m8 + ; if pSource and pDestination are not 8 byte aligned + ; Calculate 8-(Buffer%8), which is a number of bytes we have to copy to align the buffer + ; if this number if the same for source and destinations + ; copy several bytes to align them + ; otherwise proceed to QWORD copy + mov rax, rsi + mov rbx, rdi + and rax, 7 + and rbx, 7 + test dl, dl + jz skip1 + dec rsi + dec rdi +skip1: + cmp rax, rbx + jne m64 + test rax, rax + jz m64 + test dl, dl + jnz skip_nz1 + neg rax + add rax, 8 +skip_nz1: + xchg rax, rcx + sub rax, rcx + rep movsb + mov rcx, rax +m64: + test dl, dl + jz skip2 + sub rsi, 7 + sub rdi, 7 +skip2: + mov rax, rcx + shr rcx, 3 + rep movsq + and rax, 7 + jz MemCpuEnd + test dl, dl + jz skip3 + add rsi, 8 + add rdi, 8 +skip3: + mov rcx, rax +m8: + test dl, dl + jz skip4 + dec rsi + dec rdi +skip4: + rep movsb +MemCpuEnd: + popf + pop rbx + pop rsi + pop rdi + ret +MemCpy endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/MemCpy32.asm b/Core/CPU/x64/x64AsmLib/MemCpy32.asm new file mode 100644 index 0000000..a5886b3 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/MemCpy32.asm @@ -0,0 +1,178 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemCpy32.asm 1 10/17/11 1:03p Yakovlevs $ +; +; $Revision: 1 $ +; +; $Date: 10/17/11 1:03p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemCpy32.asm $ +; +; 1 10/17/11 1:03p Yakovlevs +; [TAG] EIP71694 +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: MemCpy32 +; +; Description: +; VOID MemCpy32(OUT VOID *pDestination, IN VOID *pSource, IN UINTN Count) +; copies Count bytes of memory from Source to Destination. +; +; Input: +; OUT VOID *pDestination +; Memory address where data shall be copied. User is responsible for +; allocating the necessary memory resources. +; +; IN VOID *pSource +; Memory address from where data shall be copied. +; +; IN UINTN Count +; Number of bytes to copy from pSource. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; This function checks for overlapping of source and destination and +; selects copy direction that prevents memory corruption. +; +;<AMI_PHDR_END> +;************************************************************************* +public memcpy32 +memcpy32: +MemCpy32 proc + push rdi + push rsi + push rbx + pushf + mov rsi, rdx ; pSource + mov rdi, rcx ; pDestination + mov rcx, r8 ; Count + mov dl, 0 + ; if pSource > pDestination CopyForward + mov rax, rsi + sub rax, rdi ; rax = pSource-pDestination + jnb CopyForward; if pSource-pDestination > 0 CopyForward + ; if pSource+Count < pDestination then CopyForward + lea rbx, [rsi+rcx] ; rbx = pSource + Count + neg rax ; rax = pDestination - pSource + cmp rbx, rdi + jb CopyForward ; if (pSource + Count < pDestination ) CopyForward + ; Copy Backward + mov rsi, rbx; rsi = pSource + Count + lea rdi, [rdi+rcx]; rdi = pDestination + Count + mov dl, 1; Flag to indicate that we are copying backward + std; set direction flag to copy backward +CopyForward: + cmp rcx, 4 ; if (Counter<4) copy byte by byte + jb m8 + cmp rax, 4 ; if (pDestination - pSource < 4) copy byte by byte + jb m8 + ; if pSource and pDestination are not 4 byte aligned + ; Calculate 4-(Buffer%4), which is a number of bytes we have to copy to align the buffer + ; if this number if the same for source and destinations + ; copy several bytes to align them + ; otherwise proceed to DWORD copy + mov rax, rsi + mov rbx, rdi + and rax, 3 + and rbx, 3 + test dl, dl + jz skip1 + dec rsi + dec rdi +skip1: + cmp rax, rbx + jne m32 + test rax, rax + jz m32 + test dl, dl + jnz skip_nz1 + neg rax + add rax, 4 +skip_nz1: + xchg rax, rcx + sub rax, rcx + rep movsb + mov rcx, rax +m32: + test dl, dl + jz skip2 + sub rsi, 3 + sub rdi, 3 +skip2: + mov rax, rcx + shr rcx, 2 + rep movsd + and rax, 3 + jz MemCpuEnd + test dl, dl + jz skip3 + add rsi, 4 + add rdi, 4 +skip3: + mov rcx, rax +m8: + test dl, dl + jz skip4 + dec rsi + dec rdi +skip4: + rep movsb +MemCpuEnd: + popf + pop rbx + pop rsi + pop rdi + ret +MemCpy32 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/MemRead32.asm b/Core/CPU/x64/x64AsmLib/MemRead32.asm new file mode 100644 index 0000000..3f79a06 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/MemRead32.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemRead32.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemRead32.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: MemRead32 +; +; Description: +; UINT32 MemRead32(IN UINT32 *Address) reads and returns the 32-bit value +; stored at the user provided address. +; +; Input: +; IN UINT32 *Address +; Address to read 32-bits from. +; +; Output: +; UINT32 value stored at Address. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +MemRead32 proc + mov eax, [rcx] + ret +MemRead32 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/MemReadWrite32.asm b/Core/CPU/x64/x64AsmLib/MemReadWrite32.asm new file mode 100644 index 0000000..a9ab5ba --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/MemReadWrite32.asm @@ -0,0 +1,93 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemReadWrite32.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemReadWrite32.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: MemReadWrite32 +; +; Description: +; VOID MemReadWrite32(IN UINT32 *Address, IN UINT32 Value, IN UINT32 Mask) +; reads the 32-bit value stored at Address, ANDs it with Mask, ORs the result +; with Value, then writes the result back to Address. +; +; Input: +; IN UINT32 *Address +; Address which shall be read from and subsequently written to. +; +; IN UINT32 Value +; Value to be ORed with the value stored at Address after it has been ANDed +; with the provided Mask. +; +; IN UINT32 Mask +; Mask to be ANDed with the original value stored at Address. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +MemReadWrite32 proc + mov eax, [rcx] + and eax, r8D ;Mask + or eax, edx ;Value + mov [rcx], eax + ret +MemReadWrite32 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/MemSet.asm b/Core/CPU/x64/x64AsmLib/MemSet.asm new file mode 100644 index 0000000..246b985 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/MemSet.asm @@ -0,0 +1,127 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemSet.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/MemSet.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: MemSet +; +; Description: +; VOID MemSet(IN VOID *pBuffer, IN UINTN Count, IN UINT8 Value) fills Count +; bytes of memory in pBuffer with Value. +; +; Input: +; IN VOID *pBuffer +; The starting location in memory where to begin filling. +; +; IN UINTN Count +; The number of bytes to fill with Value. +; +; IN UINT8 Value +; The value to fill memory with starting at pBuffer. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +MemSet proc + push rdi + push rbx + mov rdi, rcx ; rdi = pBuffer + mov rcx, rdx ; rcx = Count + mov rax, r8 ; al = Value + ; fill EAX with the Value so that we can perform DWORD operatins + mov ah, al + mov bx,ax + shl rax,16 + mov ax,bx + ; if Counter is less then 4, jump to byte copy + cmp rcx, 4 + jb CopyByte + ; check if the Buffer is 4-bytes aligned + mov rdx,rdi + and rdx, 3 + ; if the Buffer is 4-bytes aligned, jump to DWORD copy + jz CopyDword + ; Buffer is not 4-bytes aligned + ; Calculate 4-(Buffer%4), which is a number of bytes we have to copy before + ; Buffer will reach 4-bytes boundary, and perform byte copy + neg rdx + add rdx, 4 + xchg rcx, rdx + sub rdx, rcx + rep stosb + mov rcx, rdx +CopyDword: + ; perform DWORD copy + mov rdx, rcx + shr rcx, 2 + rep stosd + ; copy the remainder + and rdx,3 + mov rcx, rdx +CopyByte: + rep stosb + ;;; + pop rbx + pop rdi + ret +MemSet endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/ReadCr3.asm b/Core/CPU/x64/x64AsmLib/ReadCr3.asm new file mode 100644 index 0000000..ad90c20 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/ReadCr3.asm @@ -0,0 +1,79 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/ReadCr3.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/ReadCr3.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: ReadCr3 +; +; Description: +; UINTN ReadCr3() reads the register CR3 and returns its value. +; +; Input: +; +; Output: +; UINTN value stored in the CR3 register. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +ReadCr3 PROC PUBLIC + mov rax, cr3 + ret +ReadCr3 ENDP + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/ReadMsr.asm b/Core/CPU/x64/x64AsmLib/ReadMsr.asm new file mode 100644 index 0000000..3fbeff6 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/ReadMsr.asm @@ -0,0 +1,85 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/ReadMsr.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/ReadMsr.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: ReadMsr +; +; Description: +; UINT64 ReadMsr(UINT32 Msr) reads the CPU MSR index defined by Msr and +; returns the value. +; +; Input: +; IN UINT32 Msr +; 32-bit MSR index to be read. +; +; Output: +; UINT64 MSR value at MSR index, Msr. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +ReadMsr Proc ;(UINT32 Msr) + rdmsr ;rcx = MSR + and rax, 0ffffffffh + shl rdx, 32 + or rax, rdx ;rax = (rdx << 32) | eax + ret +ReadMsr endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/ReadRtdsc.asm b/Core/CPU/x64/x64AsmLib/ReadRtdsc.asm new file mode 100644 index 0000000..078964c --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/ReadRtdsc.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/ReadRtdsc.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/ReadRtdsc.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: ReadRtdsc +; +; Description: +; UINT64 ReadRtdsc() retrieves the time stamp counter. +; +; Input: +; VOID. +; +; Output: +; UINT64 value of the time stamp counter. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +ReadRtdsc Proc + rdtsc + shl rdx,32 + or rax, rdx + ret +ReadRtdsc endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/WaitForSemaphore.asm b/Core/CPU/x64/x64AsmLib/WaitForSemaphore.asm new file mode 100644 index 0000000..a5efa82 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/WaitForSemaphore.asm @@ -0,0 +1,88 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitForSemaphore.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitForSemaphore.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: WaitForSemaphore +; +; Description: +; VOID WaitForSemaphore(IN volatile UINT8 *Semaphore) waits for the +; semaphore to become available; once available, it claims the semaphore and +; returns. +; +; Input: +; IN volatile UINT8 *Semaphore +; Pointer to the desired semaphore. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +WaitForSemaphore Proc + mov al, 1 +@@: + xchg al, [rcx] + or al, al + pause + jnz @b + ret +WaitForSemaphore endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/WaitForever.asm b/Core/CPU/x64/x64AsmLib/WaitForever.asm new file mode 100644 index 0000000..c010643 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/WaitForever.asm @@ -0,0 +1,82 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitForever.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitForever.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: WaitForever +; +; Description: +; VOID WaitForever() performs an infinite loop which does nothing. +; +; Input: +; VOID. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +WaitForever Proc +@@: + Pause + jmp @b + ret +WaitForever endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/WaitUntilZero32.asm b/Core/CPU/x64/x64AsmLib/WaitUntilZero32.asm new file mode 100644 index 0000000..cdda323 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/WaitUntilZero32.asm @@ -0,0 +1,86 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitUntilZero32.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitUntilZero32.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: WaitUntilZero32 +; +; Description: +; VOID WaitUntilZero32(IN volatile UINT32 *Value) waits until the UINT32 +; value stored at the Value address becomes 0, then continues. +; +; Input: +; IN volatile UINT32 *Value +; Address of the UINT32 value to be monitored. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +WaitUntilZero32 Proc +@@: + mov eax, [rcx] + or eax, eax + pause + jnz @b + ret +WaitUntilZero32 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/WaitUntilZero8.asm b/Core/CPU/x64/x64AsmLib/WaitUntilZero8.asm new file mode 100644 index 0000000..b2c5f4d --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/WaitUntilZero8.asm @@ -0,0 +1,86 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitUntilZero8.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WaitUntilZero8.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: WaitUntilZero8 +; +; Description: +; VOID WaitUntilZero8(IN volatile UINT8 *Value) waits until the byte stored +; at Value becomes 0, then continues. +; +; Input: +; IN volatile UINT8 *Value +; Address of the byte value to be monitored. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +WaitUntilZero8 Proc +@@: + mov al, [rcx] + or al, al + pause + jnz @b + ret +WaitUntilZero8 endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/WriteCr3.asm b/Core/CPU/x64/x64AsmLib/WriteCr3.asm new file mode 100644 index 0000000..d028b07 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/WriteCr3.asm @@ -0,0 +1,81 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WriteCr3.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WriteCr3.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: WriteCr3 +; +; Description: +; VOID WriteCr3(IN UINTN CR3) writes the provided value to the CR3 register. +; +; Input: +; IN UINTN CR3 +; Value to be written to the CR3 register. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +WriteCr3 PROC PUBLIC + mov cr3, rcx + ret +WriteCr3 ENDP + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/WriteMsr.asm b/Core/CPU/x64/x64AsmLib/WriteMsr.asm new file mode 100644 index 0000000..b181a5b --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/WriteMsr.asm @@ -0,0 +1,89 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WriteMsr.asm 1 10/01/10 5:08p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:08p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/WriteMsr.asm $ +; +; 1 10/01/10 5:08p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: WriteMsr +; +; Description: +; VOID WriteMsr(IN UINT32 Msr, IN UINT64 Value) writes the Value to the +; supplied MSR index, Msr. +; +; Input: +; IN UINT32 Msr +; 32-bit MSR index to be written to. +; +; IN UINT64 Value +; Value to be written to MSR index. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; +;<AMI_PHDR_END> +;************************************************************************* +WriteMsr proc + ;rcx = MSR + mov rax, rdx ;rax = rdx = Value + and rax, 0ffffffffh ;Lower 32 bit MSR Value + shr rdx, 32 ;Upper 32 bit MSR Value + wrmsr + ret +WriteMsr endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64AsmLib/checkpoint.asm b/Core/CPU/x64/x64AsmLib/checkpoint.asm new file mode 100644 index 0000000..38edb52 --- /dev/null +++ b/Core/CPU/x64/x64AsmLib/checkpoint.asm @@ -0,0 +1,84 @@ +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* +;************************************************************************* + +;************************************************************************* +; $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/checkpoint.asm 1 10/01/10 5:07p Felixp $ +; +; $Revision: 1 $ +; +; $Date: 10/01/10 5:07p $ +;************************************************************************* +; Revision History +; ---------------- +; $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64AsmLib/checkpoint.asm $ +; +; 1 10/01/10 5:07p Felixp +; +; 1 8/24/06 12:57p Felixp +; +;************************************************************************* +;<AMI_FHDR_START> +; +; Name: +; +; Description: +; +;<AMI_FHDR_END> +;************************************************************************* +.code + +;************************************************************************* +;<AMI_PHDR_START> +; +; Name: checkpoint +; +; Description: +; VOID checkpoint(IN UINT8 c) writes the value c to port 0x80. +; +; Input: +; IN UINT8 c +; The value/checkpoint to write to 0x80. +; +; Output: +; VOID. +; +; Modified: +; +; Referrals: +; +; Notes: +; This routine should only be used if the PROGRESS_CODE or +; PEI_PROGRESS_CODE macros are unavailable. +; +;<AMI_PHDR_END> +;************************************************************************* +checkpoint proc + mov al, cl + out 80h,al + ret +checkpoint endp + +END +;************************************************************************* +;************************************************************************* +;** ** +;** (C)Copyright 1985-2009, American Megatrends, Inc. ** +;** ** +;** All Rights Reserved. ** +;** ** +;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +;** ** +;** Phone: (770)-246-8600 ** +;** ** +;************************************************************************* diff --git a/Core/CPU/x64/x64CLib.c b/Core/CPU/x64/x64CLib.c new file mode 100644 index 0000000..ad96411 --- /dev/null +++ b/Core/CPU/x64/x64CLib.c @@ -0,0 +1,328 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Modules/x64Core/x64CLib.c 4 7/10/09 9:30a Felixp $ +// +// $Revision: 4 $ +// +// $Date: 7/10/09 9:30a $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Modules/x64Core/x64CLib.c $ +// +// 4 7/10/09 9:30a Felixp +// Function headers are added. +// +// 3 10/09/06 10:11a Felixp +// MemCpy/MemSet replaced with assembler routines +// +// 2 8/25/06 10:52a Felixp +// memcpy, memset functions updated with the volotile qualifier to +// restrain compiler optimization. +// +// 1 8/24/06 12:57p Felixp +// +//************************************************************************* +//<AMI_FHDR_START> +// +// Name: x64CLib.c +// +// Description: +// Generic CPU library functions for the x64 architecture. +// +//<AMI_FHDR_END> +//************************************************************************* + +#include <efi.h> + +//************************************************************************* +// Math +//************************************************************************* + +//************************************************************************* +//<AMI_GHDR_START> +// +// Name: Math_64_Bit_Functions +// +// Description: +// Math functions involving 64-bit input parameters designed to be usable on +// both 32-bit and 64-bit platforms. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib Shr64 Shift 64-bit value right. +// AmiLib Shl64 Shift 64-bit value left. +// AmiLib Div64 Divide 64-bit value by a 31-bit value. +// AmiLib Mul64 Multiply 64-bit value by a 32-bit value. +// AmiLib GetPowerOfTwo64 Determine the highest set bit in a 64-bit value. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +//<AMI_GHDR_END> +//************************************************************************* + +//************************************************************************* +//<AMI_GHDR_START> +// +// Name: CPU_Functions +// +// Description: +// CPU related functions defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// None CPULib_CpuID Perform the cpuid assembly instruction. +// None CPULib_DisableInterrupt Disable interrupts. +// None CPULib_EnableInterrupt Enable interrupts. +// None CPULib_GetInterruptState Get current interrupt state (enabled or disabled). +// None CPULIB_GetPageTable Retrieve address of the page table. +// None CPULib_LoadGdt Load GDT. +// None CPULib_LoadIdt Load IDT. +// None CPULib_LockByteDec Lock preceeding byte. +// None CPULib_LockByteInc Lock following byte. +// None CPULib_Pause Pause CPU. +// None CPULib_SaveGdt Save GDT at provided location. +// None CPULib_SaveIdt Save IDT at provided location. +// None DisableCacheInCR0 Disable CPU cache using CR0. +// None EnableCacheInCR0 Enable CPU cache using CR0. +// None EnableMachineCheck Enable machine check exception bit in CR4. +// AmiLib GetCpuTimer Retrieve the CPU timer's value. +// None GetCsSegment Retrieve the code segment. +// None HltCpu Halt the CPU. +// None WaitForever Perform infinite loop. +// None WaitForSemaphore Wait for semaphore to become available. then take control. +// None WaitUntilZero32 Wait until a 32-bit memory region becomes zero. +// None WaitUntilZero8 Wait until an 8-bit meomry region becomes zero. +// None WriteMsr Write a value to a MSR. +// None ReadMsr Read value from a MSR. +// AmiLib WriteCr3 Write a value to CR3. +// AmiLib ReadCr3 Read value from CR3. +// None ReadRtdsc Retrieve the time stamp counter. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +//<AMI_GHDR_END> +//************************************************************************* + + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: Shr64 +// +// Description: +// UINT64 Shr64(IN UINT64 Value, IN UINT8 Shift) shifts the 64-bit Value +// right the provided number of bits, Shift. +// +// Input: +// IN UINT64 Value +// The value to be shifted. +// +// IN UINT8 Shift +// The number of bits to shift right. +// +// Output: +// UINT64 Value shifted right Shift number of bits. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +UINT64 Shr64( + IN UINT64 Value, + IN UINT8 Shift + ) +{ + return Value>>Shift; +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: Shl64 +// +// Description: +// UINT64 Shl64(IN UINT64 Value, IN UINT8 Shift) shifts the 64-bit Value +// left the provided number of bits, Shift. +// +// Input: +// IN UINT64 Value +// The value to be shifted left. +// +// IN UINT8 Shift +// The number of bits to shift. +// +// Output: +// UINT64 Value shifted left Shift number of bits. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +UINT64 Shl64( + IN UINT64 Value, + IN UINT8 Shift + ) +{ + return Value<<Shift; +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: Div64 +// +// Description: +// UINT64 Div64(IN UINT64 Dividend, IN UINTN Divisor, +// OUT UINTN *Remainder OPTIONAL) divides a 64-bit number, Dividend, by the +// Divisor, which can be up to 31-bits. +// +// Input: +// IN UINT64 Dividend +// The 64-bit number to be divided. +// +// IN UINT Divisor +// The number to divide Dividend by; may not exceed 31-bits in size. +// +// OUT UINTN *Remainder OPTIONAL +// The remainder of the division. Provide NULL if undesired; otherwise user +// is responsible for handling the necessary memory resources. +// +// Output: +// UINT64 result of dividing Dividend by Divisor. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +UINT64 Div64 ( + IN UINT64 Dividend, + IN UINTN Divisor, //Can only be 31 bits. + OUT UINTN *Remainder OPTIONAL + ) +{ + UINT64 Result = Dividend/Divisor; + if (Remainder) *Remainder=Dividend%Divisor; + return Result; +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: Mul64 +// +// Description: +// UINT64 Mul64(IN UINT64 Value64, IN UINTN Value32) multiplies a 64-bit +// number by a 32-bit number and returns the 64-bit result. +// +// Input: +// IN UINTN64 Value64 +// The 64-bit number to multiply by. +// +// IN UINTN Value32 +// The 32-bit number to multiply by. +// +// Output: +// UINT64 result of multiplying Value64 by Value32. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +UINT64 Mul64( + IN UINT64 Value64, + IN UINTN Value32 + ) +{ + return Value64*Value32; +} + +//************************************************************************* +// Memory Operations +//************************************************************************* + +VOID MemSet(VOID* pBuffer, UINTN Count, UINT8 Value); + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: memset +// +// Description: +// VOID memset(IN VOID *pBuffer, IN UINT8 Value, IN UINTN Count) is a +// wrapper for MemSet which fills Count bytes of memory in pBuffer with +// Value. +// +// Input: +// IN VOID *pBuffer +// The starting location in memory where to begin filling. +// +// IN UINT8 Value +// The value to fill memory with starting at pBuffer. +// +// IN UINTN Count +// The number of bytes to fill with Value. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// MemSet +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +VOID memset(VOID* pBuffer, UINTN Value, UINTN Count) +{ + MemSet(pBuffer,Count,(UINT8)Value); +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CPU/x64/x64Core.cif b/Core/CPU/x64/x64Core.cif new file mode 100644 index 0000000..0d92f09 --- /dev/null +++ b/Core/CPU/x64/x64Core.cif @@ -0,0 +1,9 @@ +<component> + name = "x64 Core" + category = ModulePart + LocalRoot = "Core\CPU\x64\" + RefName = "x64Core" +[files] +"x64Core.sdl" +"x64rules.mak" +<endComponent> diff --git a/Core/CPU/x64/x64Core.sdl b/Core/CPU/x64/x64Core.sdl new file mode 100644 index 0000000..389aa0f --- /dev/null +++ b/Core/CPU/x64/x64Core.sdl @@ -0,0 +1,112 @@ +TOKEN + Name = "x64_BUILD" + Value = "0" + Help = "Main switch to enable x64 support in Project\DO REBUILD ALL AFTER CHANGING THIS SWITCH!!!" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "GLOBAL_DEFINES_x64" + Value = "/DEFIx64 /DEFIX64" + Help = "Global x64-specific macro definitions. Added to CFLAGSx64 and AFLAGSx64" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "CC" + Value = "$(SILENT)$(CCX64DIR)\CL" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "LINK" + Value = "$(SILENT)$(CCX64DIR)\LINK" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "LIBEXE" + Value = "$(SILENT)$(CCX64DIR)\LINK /LIB" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "CCPEI" + Value = "$(SILENT)$(CCX86DIR)\CL" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "LINKPEI" + Value = "$(SILENT)$(CCX86DIR)\LINK" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "LIBEXEPEI" + Value = "$(SILENT)$(CCX86DIR)\LINK /LIB" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "CFLAGSx64" + Value = "/GS- $(GLOBAL_DEFINES_x64)" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "ASMx64" + Value = "$(SILENT)$(CCX64DIR)\ML64" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "AFLAGSx64" + Value = "$(GLOBAL_DEFINES_x64) /Cp" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "LFLAGSx64" + Value = "/MACHINE:AMD64" + TokenType = Expression + TargetMAK = Yes +End + +TOKEN + Name = "CP" + Value = "$(SILENT)$(CCX64DIR)\CL /nologo /EP" + Help = "C preprocessor" + TokenType = Expression + TargetMAK = Yes +End + +PATH + Name = "x64Core_DIR" +End + +ELINK + Name = "x64" + Parent = "IA32" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(x64Core_DIR)\x64rules.mak" + Parent = "$(IA32Core_DIR)\IA32rules.mak" + InvokeOrder = ReplaceParent +End + diff --git a/Core/CPU/x64/x64rules.mak b/Core/CPU/x64/x64rules.mak new file mode 100644 index 0000000..ed1ab3c --- /dev/null +++ b/Core/CPU/x64/x64rules.mak @@ -0,0 +1,86 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/BIN/Core/Modules/x64Core/x64rules.mak 3 8/02/07 1:33a Felixp $ +# +# $Revision: 3 $ +# +# $Date: 8/02/07 1:33a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Core/Modules/x64Core/x64rules.mak $ +# +# 3 8/02/07 1:33a Felixp +# minor modification to use newly defined COMPONENT_BUILD_RULES macro +# defined in rules.mak +# +# 2 3/13/07 11:53a Felixp +# Global and CPU architecture specific macros are now passed +# to C preprocessor (used during DepEx and VFR compilation) +# +# 1 10/13/06 8:31p Felixp +# +# 3 9/05/06 6:03p Felixp +# define PROCESSOR is IA32 when building PEI components in x64 build. +# +# 2 8/25/06 11:12a Felixp +# +# 1 8/24/06 12:57p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: x64rules.mak +# +# Description: Defines x64-specific build rules. +# This file is included into the template makefile rules.mak +# +#<AMI_FHDR_END> +#********************************************************************** +!IF "$(COMPONENT_BUILD_RULES)"=="PEI" +# IA32 Build +CC = $(CCPEI) +LINK = $(LINKPEI) +LIBEXE=$(LIBEXEPEI) + +LIB_BUILD_DIR=$(BUILD_ROOT)\IA32 +!UNDEF PROCESSOR +PROCESSOR=IA32 +!INCLUDE $(IA32Core_DIR)\IA32rules.mak + +!ELSE +# x64 Build +ASM=$(ASMx64) + +EXTRA_CFLAGS=$(EXTRA_CFLAGS) $(CFLAGSx64) +EXTRA_LFLAGS=$(EXTRA_LFLAGS) $(LFLAGSx64) +EXTRA_AFLAGS=$(EXTRA_AFLAGS) $(AFLAGSx64) +EXTRA_AFLAGS16=$(EXTRA_AFLAGS16) $(GLOBAL_DEFINES_x64) +CPFLAGS=$(CPFLAGS) $(GLOBAL_DEFINES_x64) +!ENDIF +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file |