summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c')
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c1112
1 files changed, 1112 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c
new file mode 100644
index 0000000..308329e
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c
@@ -0,0 +1,1112 @@
+/** @file
+ Cpu driver, which initializes CPU and implements CPU Architecture
+ Protocol as defined in Framework specification.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxeDbgr.h"
+#include "ProcessorData.h"
+#include "CacheData.h"
+#include "Exception.h"
+#include "PfatDefinitions.h"
+#include "BootGuardLibrary.h"
+#include "BootGuardRevocationLib.h"
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+EFI_GUID gAmiDebuggerCpuProtocolGuid = AMI_DEBUGGER_CPU_PROTOCOL_GUID;
+AMI_DEBUGGER_CPU_PROTOCOL *mAmiDebuggerCpuProtocol;
+VOID* AptioInterruptHandlerHalt;
+UINT32 AptioInterruptHandlerHalt1;
+VOID
+EFIAPI CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+#endif
+//<(AMI_CHG+)
+
+#define SAMPLE_TICK_COUNT 1000
+
+#endif
+
+extern UINT64 mValidMtrrAddressMask;
+extern UINT64 mValidMtrrBitsMask;
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+extern UINT8 CpuInitDxeStrings[];
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+EFI_HANDLE mDriverHandle;
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+#else
+EFI_HII_PROTOCOL *mHii;
+#endif
+EFI_SMM_BASE_PROTOCOL *mSmmBaseProtocol = NULL;
+VOID *mSmmBaseRegistration;
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu = NULL;
+EFI_HII_HANDLE mStringHandle;
+BOOLEAN mIsFlushingGCD = TRUE;
+UINT8 mSmmbaseSwSmiNumber;
+BOOLEAN mVariableMtrrChanged;
+BOOLEAN mFixedMtrrChanged;
+UINT64 mCpuFrequency = 0;
+
+EFI_EVENT gReadyToBootEvent;
+EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[0x100];
+BOOLEAN mInterruptState = FALSE;
+
+///
+/// The Cpu Architectural Protocol that this Driver produces
+///
+EFI_CPU_ARCH_PROTOCOL gCpu = {
+ FlushCpuDataCache,
+ EnableInterrupt,
+ DisableInterrupt,
+ CpuGetInterruptState,
+ Init,
+ RegisterInterruptHandler,
+ GetTimerValue,
+ SetMemoryAttributes,
+ 1, ///< NumberOfTimers
+ 4, ///< DmaBufferAlignment
+};
+
+/**
+ Decide if the CPU is executing in SMM mode
+
+ @retval TRUE - The CPU is executing in SMM mode
+ @retval FALSE - The CPU is not executing in SMM mode
+**/
+BOOLEAN
+ExecutionInSmm (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN InSmm;
+
+ if (mSmmBaseProtocol == NULL) {
+ return FALSE;
+ }
+
+ Status = mSmmBaseProtocol->InSmm (mSmmBaseProtocol, &InSmm);
+ ASSERT_EFI_ERROR (Status);
+ return InSmm;
+}
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param[in] This - Protocol instance structure
+ @param[in] Start - Physical address to start flushing from.
+ @param[in] Length - Number of bytes to flush. Round up to chipset
+ granularity.
+ @param[in] FlushType - Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS - If cache was flushed
+ @exception EFI_UNSUPPORTED - If flush type is not supported.
+ @retval EFI_DEVICE_ERROR - If requested range could not be flushed.
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ EfiInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Enables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ if (!ExecutionInSmm ()) {
+ CpuEnableInterrupt ();
+ }
+
+ mInterruptState = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Disables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ CpuDisableInterrupt ();
+
+ mInterruptState = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the state of interrupts.
+
+ @param[in] This - Protocol instance structure
+ @param[in] State - Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER - State is NULL.
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = mInterruptState;
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates an INIT to the CPU
+
+ @param[in] This - Protocol instance structure
+ @param[in] InitType - Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS - If CPU INIT occurred. This value should never be seen
+ @retval EFI_DEVICE_ERROR - If CPU INIT failed.
+ @exception EFI_UNSUPPORTED - Requested type of CPU INIT not supported.
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param[in] This - Protocol instance structure
+ @param[in] InterruptType - Defines which interrupt to hook.
+ IA-32 valid range is 0x00 through 0xFF
+ @param[in] InterruptHandler - A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ A null pointer is an error condition.
+
+ @retval EFI_SUCCESS - If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for
+ InterruptType was previously installed
+ @retval EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @exception EFI_UNSUPPORTED - The interrupt specified by InterruptType is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ EFI_STATUS Status;
+#endif
+//<(AMI_CHG+)
+
+ if (InterruptType < 0 || InterruptType > 0xff) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && mExternalVectorTable[InterruptType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && mExternalVectorTable[InterruptType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mExternalVectorTable[InterruptType] = InterruptHandler;
+
+//AMI_CHG>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ if ((UINT32) InterruptHandler == (UINT32)CommonExceptionHandler)
+ Status = mAmiDebuggerCpuProtocol->DebuggerIsDebuggerIrqHadler(InterruptType,AptioInterruptHandlerHalt);
+ else
+ Status = mAmiDebuggerCpuProtocol->DebuggerIsDebuggerIrqHadler(InterruptType,InterruptHandler);
+#endif
+//<AMI_CHG
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param[in] This - Protocol instance structure.
+ @param[in] TimerIndex - Specifies which CPU timer is requested.
+ @param[in] TimerValue - Pointer to the returned timer value.
+ @param[in] TimerPeriod - A pointer to the amount of time that passes in femtoseconds (10-15) for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned. The amount of time that has passed between two calls to
+ GetTimerValue() can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @exception EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+**/
+{
+ UINT64 Actual;
+
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = EfiReadTsc ();
+
+ if (TimerPeriod != NULL) {
+ GetActualFrequency (mMetronome, &Actual);
+ *TimerPeriod = DivU64x32 (1000000000, (UINT32) Actual);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set memory cacheability attributes for given range of memeory
+
+ @param[in] This - Protocol instance structure
+ @param[in] BaseAddress - Specifies the start address of the memory range
+ @param[in] Length - Specifies the length of the memory range
+ @param[in] Attributes - The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS - If the cacheability of that memory range is set successfully
+ @exception EFI_UNSUPPORTED - If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINT64 TempQword;
+ UINT32 MsrNum;
+ UINTN MtrrNumber;
+ BOOLEAN Positive;
+ BOOLEAN OverLap;
+#define SKIP_ALIGN_CHECK 0
+#if SKIP_ALIGN_CHECK
+ UINT32 Remainder;
+#endif
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ EFI_STATUS Status1;
+ UINT32 VariableMtrrLimit;
+
+ mFixedMtrrChanged = FALSE;
+ mVariableMtrrChanged = FALSE;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+
+ if (mIsFlushingGCD) {
+ return EFI_SUCCESS;
+ }
+
+ TempQword = 0;
+
+ ///
+ /// Check for invalid parameter
+ ///
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BaseAddress &~mValidMtrrAddressMask) != 0 || (Length &~mValidMtrrAddressMask) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (Attributes) {
+ case EFI_MEMORY_UC:
+ Attributes = CACHE_UNCACHEABLE;
+ break;
+
+ case EFI_MEMORY_WC:
+ Attributes = CACHE_WRITECOMBINING;
+ break;
+
+ case EFI_MEMORY_WT:
+ Attributes = CACHE_WRITETHROUGH;
+ break;
+
+ case EFI_MEMORY_WP:
+ Attributes = CACHE_WRITEPROTECTED;
+ break;
+
+ case EFI_MEMORY_WB:
+ Attributes = CACHE_WRITEBACK;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// Check if Fixed MTRR
+ ///
+ Status = EFI_SUCCESS;
+ while ((BaseAddress < (1 << 20)) && (Length > 0) && Status == EFI_SUCCESS) {
+ Status = CalculateFixedMtrr (Attributes, &BaseAddress, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (mFixedMtrrChanged) {
+ ProgramFixedMtrr ();
+ }
+
+ if (Length == 0) {
+ ///
+ /// Just Fixed MTRR. NO need to go through Variable MTRR
+ ///
+ goto Done;
+ }
+
+ ///
+ /// since mem below 1m will be override by fixed mtrr, we can set it to 0 to save mtrr.
+ ///
+ if (BaseAddress == 0x100000) {
+ BaseAddress = 0;
+ Length += 0x100000;
+ }
+
+ ///
+ /// Check memory base address alignment
+ ///
+#if SKIP_ALIGN_CHECK
+ DivU64x32Remainder (BaseAddress, (UINT32) Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder);
+ if (Remainder != 0) {
+ DivU64x32Remainder (BaseAddress, (UINT32) Power2MaxMemory (Length), &Remainder);
+ if (Remainder != 0) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ }
+#endif
+
+ ///
+ /// Check overlap
+ ///
+ GetMemoryAttribute ();
+ OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1);
+ if (OverLap) {
+ Status = CombineMemoryAttribute (Attributes, &BaseAddress, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ if (Length == 0) {
+ ///
+ /// combine successfully
+ ///
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ } else {
+ if (Attributes == CACHE_UNCACHEABLE) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ ///
+ /// Program Variable MTRRs
+ ///
+ if (mUsedMtrr >= VariableMtrrLimit) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ///
+ /// Find first unused MTRR
+ ///
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1); MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+
+ TempQword = Length;
+ if (TempQword == Power2MaxMemory (TempQword)) {
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ } else {
+ GetDirection (TempQword, &MtrrNumber, &Positive);
+ if ((mUsedMtrr + MtrrNumber) > VariableMtrrLimit) {
+ goto Done;
+ }
+ if (!Positive) {
+ Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += TempQword;
+ TempQword = Length - TempQword;
+ Attributes = CACHE_UNCACHEABLE;
+ }
+ do {
+ ///
+ /// Find unused MTRR
+ ///
+ for (; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1); MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+ Length = Power2MaxMemory (TempQword);
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += Length;
+ TempQword -= Length;
+ } while (TempQword);
+ }
+
+Done:
+ Status1 = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &MpService
+ );
+
+ if (!EFI_ERROR (Status1)) {
+ if (mVariableMtrrChanged || mFixedMtrrChanged) {
+ ///
+ /// PERF_START (NULL, L"CacheSync", NULL, 0);
+ ///
+ ReadMtrrRegisters ();
+ Status1 = MpService->StartupAllAPs (
+ MpService,
+ MpMtrrSynchUp,
+ FALSE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ ///
+ /// PERF_END (NULL, L"CacheSync", NULL, 0);
+ ///
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Initialize the SmmBase pointer when SmmBase protocol get installed
+
+ @param[in] Event - Event whose notification function is being invoked.
+ @param[in] Context - Pointer to the notification functions context, which is implementation dependent.
+**/
+VOID
+EFIAPI
+InitializeSmmBasePtr (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBaseProtocol);
+ if (EFI_ERROR (Status)) {
+ mSmmBaseProtocol = NULL;
+ }
+}
+
+/**
+ Call back function to publish Hii data
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+HiiCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+#else
+ EFI_HII_PACKAGES *PackageList;
+#endif
+ EFI_STATUS Status;
+
+ ///
+ /// Initialize strings to HII database
+ ///
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ &mHiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ ///
+ /// Create driver handle used by HII database
+ ///
+ Status = CreateHiiDriverHandle (&mDriverHandle);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ ///
+ /// Publish our HII data
+ ///
+ PackageList = PreparePackageList (1, &gProcessorProducerGuid, CpuInitDxeStrings);
+ if (PackageList == NULL) {
+ return;
+ }
+ Status = mHiiDatabase->NewPackageList (
+ mHiiDatabase,
+ PackageList,
+ mDriverHandle,
+ &mStringHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+#else
+ ///
+ /// There should only be one HII protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) &mHii
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ PackageList = PreparePackages (1, &gProcessorProducerGuid, CpuInitDxeStrings);
+ Status = mHii->NewPack (mHii, PackageList, &mStringHandle);
+ FreePool (PackageList);
+#endif
+}
+
+/**
+ Create SMBIOS Table type - FviSmbiosType, when ExitPmAuth event is signaled
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+ **/
+VOID
+InitializeFviDataCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ UINT32 uCodeRevision;
+
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ gBS->CloseEvent (Event);
+
+ if (mPlatformCpu->CpuConfig->FviReport) {
+ InitFviDataHubCbContext (
+ mPlatformCpu->CpuConfig->FviSmbiosType,
+ (UINT8) mCpuFviElements,
+ &mCpuFviVersionData
+ );
+
+ uCodeRevision = GetCpuUcodeRevision ();
+ mCpuFviElementsData[UCODE_VER].Element.Version.MajorVersion = (UINT8) ((uCodeRevision & 0xFF000000) >> 24);
+ mCpuFviElementsData[UCODE_VER].Element.Version.MinorVersion = (UINT8) ((uCodeRevision & 0x00FF0000) >> 16);
+ mCpuFviElementsData[UCODE_VER].Element.Version.Revision = (UINT8) ((uCodeRevision & 0x0000FF00) >> 8);
+ mCpuFviElementsData[UCODE_VER].Element.Version.BuildNum = (UINT16) (uCodeRevision & 0x000000FF);
+
+ CreateRcFviDatahub (&mCpuFviVersionData);
+ }
+ return;
+}
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param[in] ImageHandle - Image handle of the loaded driver
+ @param[in] SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR - cannot create the thread
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NewHandle1;
+ VOID *Registration;
+
+ ///
+ /// Initialize the Global Descriptor Table
+ ///
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ Status = gBS->LocateProtocol(
+ &gAmiDebuggerCpuProtocolGuid,
+ NULL,
+ &mAmiDebuggerCpuProtocol
+ );
+
+ if (!EFI_ERROR(Status)){
+ Status = mAmiDebuggerCpuProtocol->
+ DebuggerGetAptioIntHandler((VOID*)&AptioInterruptHandlerHalt1);
+
+ (UINT32)AptioInterruptHandlerHalt = AptioInterruptHandlerHalt1;
+
+ Status = mAmiDebuggerCpuProtocol->DebuggerSetupExceptionHandler();
+ }
+#endif
+
+ InitializeSelectors ();
+
+ ///
+ /// Initialize Exception Handlers
+ ///
+ InitializeException (&gCpu);
+
+ ///
+ /// Setup Cache attributes and Interrupt Tables
+ ///
+ PrepareMemory ();
+
+//<(AMI_CHG+)
+
+ ///
+ /// Install CPU Architectural Protocol
+ ///
+ NewHandle1 = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle1,
+ &gEfiCpuArchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gCpu
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Refresh memory space attributes according to MTRRs
+ ///
+ Status = RefreshGcdMemoryAttributes ();
+ mIsFlushingGCD = FALSE;
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Locate DxeCpuPlatformPolicy protocol instance and assign it to a global variable
+ ///
+ Status = gBS->LocateProtocol (&gDxeCpuPlatformPolicyProtocolGuid, NULL, (VOID **) &mPlatformCpu);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR,"Failed to locate DxeCpuPlatformPolicy Protocol\n"));
+ return Status;
+ }
+
+ //
+ // Dump Cpu platform policy
+ //
+ CpuDxePolicyDump();
+
+ ///
+ /// Initialize the global SmmBase SWSMI number
+ ///
+ mSmmbaseSwSmiNumber = mPlatformCpu->CpuConfig->SmmbaseSwSmiNumber;
+
+ ///
+ /// Load the microcode if needed
+ ///
+ Status = LoadAllMicrocodeUpdates ();
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+ EfiLibCreateProtocolNotifyEvent (
+ &gEfiHiiDatabaseProtocolGuid,
+ EFI_TPL_CALLBACK,
+ HiiCallback,
+ NULL,
+ &Registration
+ );
+#else
+ EfiLibCreateProtocolNotifyEvent (
+ &gEfiHiiProtocolGuid,
+ EFI_TPL_CALLBACK,
+ HiiCallback,
+ NULL,
+ &Registration
+ );
+#endif
+
+ ///
+ /// Create an SmmBase protocol call back event to initialize
+ /// Smm Base pointer, during SMM mode
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiSmmBaseProtocolGuid,
+ TPL_CALLBACK,
+ InitializeSmmBasePtr,
+ NULL,
+ &mSmmBaseRegistration
+ );
+
+ ///
+ /// Initialize MP Support if necessary
+ ///
+ Status = InitializeMpSupport ();
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR,"Failed to initialize MPs\n"));
+ }
+
+ ///
+ /// Create an ExitPmAuth protocol callback event to generate SMBIOS table - FviSmbiosType
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ InitializeFviDataCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Create an ExitPmAuth protocol callback event for PFAT.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ InitializePfatToolsIntCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Verify if Boot Guard is supported
+ ///
+ if (IsBootGuardSupported()){
+ ///
+ /// Identify if Revocation is requested by Boot Guard ACM
+ ///
+ if (AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & BIT7) {
+ ///
+ /// Create an ExitPmAuth protocol call back event if one or more of Boot Guard modules are revoked.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ TPL_CALLBACK,
+ BootGuardRevocationCallback,
+ NULL,
+ &Registration
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ @param[in] Metronome - Metronome protocol
+ @param[in] Frequency - Pointer to the CPU core frequency
+
+ @retval EFI_SUCCESS - If the frequency is returned successfully
+ @retval EFI_INVALID_PARAMETER - If the input parameter is wrong
+**/
+EFI_STATUS
+GetActualFrequency (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome,
+ OUT UINT64 *Frequency
+ )
+{
+ UINT64 BeginValue;
+ UINT64 EndValue;
+ UINT64 TotalValue;
+ UINT32 TickCount;
+ BOOLEAN InterruptState;
+ EFI_STATUS Status;
+
+ if (Metronome == NULL || Frequency == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mCpuFrequency == 0) {
+ ///
+ /// In order to calculate the actual CPU frequency, we keep track of the CPU Tsc value (which
+ /// increases by 1 for every cycle) for a know period of time. The Metronome is not accurate
+ /// for the 1st tick, so I choose to wait for 1000 ticks, thus the error can be control to be
+ /// lower than 1%.
+ ///
+ TickCount = SAMPLE_TICK_COUNT;
+ CpuGetInterruptState (&gCpu, &InterruptState);
+ if (InterruptState) {
+ DisableInterrupt (&gCpu);
+ }
+ ///
+ /// In DxeCis-0.91 specs.
+ /// Metronome->WaitForTick is possible for interrupt processing,
+ /// or exception processing to interrupt the execution of the WaitForTick() function.
+ /// Depending on the hardware source for the ticks, it is possible for a tick to be missed.
+ /// This function cannot guarantee that ticks will not be missed.
+ ///
+ while (TRUE) {
+ BeginValue = EfiReadTsc ();
+ Status = Metronome->WaitForTick (Metronome, TickCount);
+ EndValue = EfiReadTsc ();
+ if (!EFI_ERROR (Status)) {
+ TotalValue = EndValue - BeginValue;
+ break;
+ }
+ }
+
+ if (InterruptState) {
+ EnableInterrupt (&gCpu);
+ }
+
+ mCpuFrequency = MultU64x32 (TotalValue, 10);
+ mCpuFrequency = DivU64x32 (mCpuFrequency, Metronome->TickPeriod * TickCount);
+ }
+
+ *Frequency = mCpuFrequency;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Dump RC CPU and PPM platform policies
+**/
+VOID
+CpuDxePolicyDump (
+ VOID
+ )
+{
+#ifdef EFI_DEBUG
+ CPU_CONFIG *CpuConfig;
+ POWER_MGMT_CONFIG *PowerMgmtConfig;
+ SECURITY_CONFIG *SecurityConfig;
+
+ CpuConfig = mPlatformCpu->CpuConfig;
+ PowerMgmtConfig = mPlatformCpu->PowerMgmtConfig;
+ SecurityConfig = mPlatformCpu->SecurityConfig;
+ //
+ // Dump Cpu Platform policy
+ //
+ DEBUG ((EFI_D_INFO, "\n------------------------ DXE CpuPlatformPolicy Dump Begin -----------------\n"));
+ //
+ // Cpu config
+ //
+ DEBUG ((EFI_D_INFO, " CPU:: HtState : 0x%X \n", CpuConfig->HtState));
+ DEBUG ((EFI_D_INFO, " CPU:: LimitCpuidMaximumValue : 0x%X\n", CpuConfig->LimitCpuidMaximumValue));
+ DEBUG ((EFI_D_INFO, " CPU:: ExecuteDisableBit : 0x%X\n", CpuConfig->ExecuteDisableBit));
+ DEBUG ((EFI_D_INFO, " CPU:: VmxEnable : 0x%X\n", CpuConfig->VmxEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: SmxEnable : 0x%X\n", CpuConfig->SmxEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: MachineCheckEnable : 0x%X\n", CpuConfig->MachineCheckEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: MonitorMwaitEnable : 0x%X\n", CpuConfig->MonitorMwaitEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: XapicEnable : 0x%X\n", CpuConfig->XapicEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: IsColdReset : 0x%X\n", CpuConfig->IsColdReset));
+ DEBUG ((EFI_D_INFO, " CPU:: MlcStreamerPrefetcher : 0x%X\n", CpuConfig->MlcStreamerPrefetcher));
+ DEBUG ((EFI_D_INFO, " CPU:: EnableDts : 0x%X\n", CpuConfig->EnableDts));
+ DEBUG ((EFI_D_INFO, " CPU:: FviReport : 0x%X\n", CpuConfig->FviReport));
+ DEBUG ((EFI_D_INFO, " CPU:: AesEnable : 0x%X\n", CpuConfig->AesEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: DebugInterfaceEnable : 0x%X\n", CpuConfig->DebugInterfaceEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: DebugInterfaceLockEnable : 0x%X\n", CpuConfig->DebugInterfaceLockEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: ApIdleManner : 0x%X\n", CpuConfig->ApIdleManner));
+ DEBUG ((EFI_D_INFO, " CPU:: ApHandoffManner : 0x%X\n", CpuConfig->ApHandoffManner));
+ DEBUG ((EFI_D_INFO, " CPU:: BspSelection : 0x%X\n", CpuConfig->BspSelection));
+ DEBUG ((EFI_D_INFO, " CPU:: SmmbaseSwSmiNumber : 0x%X\n", CpuConfig->SmmbaseSwSmiNumber));
+ DEBUG ((EFI_D_INFO, " CPU:: FviSmbiosType; : 0x%X\n", CpuConfig->FviSmbiosType));
+ //
+ // SECURITY_CONFIG : TXT_FUNCTION_CONFIG
+ //
+ DEBUG ((EFI_D_INFO, " CPU:: SECURITY_CONFIG:TXT_FUNCTION_CONFIG : ResetAux : 0x%X\n", SecurityConfig->TxtFunctionConfig->ResetAux));
+ DEBUG ((EFI_D_INFO, "\n------------------------ DXE CpuPlatformPolicy Dump End -----------------\n"));
+#endif
+}
+
+/**
+ Initialize the global DataHub pointer
+
+ @param[in] DataHub - Pointer to the DataHub protocol as output
+
+ @retval EFI_SUCCESS - If the DataHub pointer is initialized successfully
+**/
+EFI_STATUS
+InitializeDataHubPtr (
+ OUT EFI_DATA_HUB_PROTOCOL **DataHub
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) DataHub);
+ return Status;
+}
+
+/**
+ Drop into SMM to register IOTRAP for pfat tools interface
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+InitializePfatToolsIntCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ PFAT_HOB *PfatHobPtr;
+ EFI_GUID PfatHobGuid = PFAT_HOB_GUID;
+
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ PfatHobPtr = GetFirstGuidHob (&PfatHobGuid);
+ if (PfatHobPtr != NULL) {
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) PfatHobPtr->PfatToolsIntIoTrapAdd;
+ ///
+ /// IOTRAP TO SMM
+ ///
+ IoRead8 (BaseAddress);
+ }
+ return;
+}
+
+/**
+ Register callback function for Boot Guard revocation flow.
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+BootGuardRevocationCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+
+ //
+ // Check whether this is real ExitPmAuth notification, or just a SignalEvent
+ //
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ BootGuardOemRevocationHook();
+
+ //
+ // Closed the event to avoid call twice
+ //
+ gBS->CloseEvent (Event);
+
+ return;
+}