diff options
Diffstat (limited to 'Core/CPU/CpuDxe.c')
-rw-r--r-- | Core/CPU/CpuDxe.c | 2096 |
1 files changed, 2096 insertions, 0 deletions
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 ** +//** ** +//************************************************************************* +//************************************************************************* + |