summaryrefslogtreecommitdiff
path: root/Core/EM/SMM/SmmInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/SMM/SmmInit.c')
-rw-r--r--Core/EM/SMM/SmmInit.c1319
1 files changed, 1319 insertions, 0 deletions
diff --git a/Core/EM/SMM/SmmInit.c b/Core/EM/SMM/SmmInit.c
new file mode 100644
index 0000000..fa0f699
--- /dev/null
+++ b/Core/EM/SMM/SmmInit.c
@@ -0,0 +1,1319 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/SMM/SmmInit.c 3 10/31/12 6:32a Wesleychen $
+//
+// $Revision: 3 $
+//
+// $Date: 10/31/12 6:32a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/SMM/SmmInit.c $
+//
+// 3 10/31/12 6:32a Wesleychen
+// Move 'DisableSmmCallbacks' event from BDS_CONNECT_DRIVERS_PROTOCOL_GUID
+// to BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID.
+//
+// 8 1/05/12 1:54p Markw
+// [TAG] EIP78457
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] If BSP is switch, SMM may not bring all CPUs into SMM if
+// not all CPUs are inside of SMM.
+// [RootCause] During CPU initialization, the sytem uses the actual BSP
+// instead of BSP from the SMM HOB.
+// This creates a inconsistentancy with the rest of the SMM numbering.
+// [Solution] Use SMM HOB BSP value.
+// [Files] SmmInit.c
+//
+// 7 10/03/11 2:51p Markw
+// Update StartupThisAP for PI 1.1.
+// File: SmmInit.c
+//
+// 6 6/22/11 11:55a Markw
+// Separate DxeSmmReadyToLock from Protocol\SmmReadyToLock.h.
+//
+//
+// 5 5/10/11 12:06p Markw
+// [TAG] EIP60051
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] With PI 1.1, BIOS may hang in DisableSmmCallbacks .
+// [RootCause] DisableSmmCallbacks calls SmmDispatcher. This must be
+// executed inside SMM.
+// [Solution] Call SmmDispatcher inside SMM.
+// [Files] SmmInit.c
+//
+// 4 4/12/11 3:00p Markw
+// [TAG] EIP57440
+// [Category] New Feature
+// [Description] PI Update allocated SMM BASE Protocol with boot
+// services data. Change it to runtime services data.
+// [Files] SmmInit.c
+//
+// 3 4/01/11 10:07a Markw
+// [TAG] EIP57440
+// [Category] New Feature
+// [Description] Add PI 1.1 SMM support for reading/writing floating
+// point/smm save state.
+//
+// [Files] CpuCspLib.h, CpuCspLib.c, SmmPiSmst.c, SmmPrivateShared.h,
+// SmmHdr.equ, SmmInit.c
+//
+// 2 3/04/11 3:32p Markw
+// Update headers.
+//
+// 1 2/07/11 3:34p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support.
+// Moved common initialization from SmmBase.c to SmmInit.c.
+// [Files] Smm.sdl, SmmPrivateShared.h, SmmDispatcher.mak,
+// SmmDispatcher.h, SmmDispatcher.c,
+// Smst.c, SmmPiSmst.c, SmmInit.c, SmmBase.c, SmmBase2.c,
+// SmmDriverDispatcher.c, Smm Framewwork Protocol files, SmmPi.h,
+// Smm Pi Protocol files, SmmPciRbio files
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmInit.c
+//
+// Description: Dispatch SMM Drivers
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//This include should be first.
+#include "SmmPrivateShared.h"
+#include <AmiDxeLib.h>
+#include "AmiCspLib.h"
+#include <AmiSmm.h>
+#include <AmiHobs.h>
+#if USE_FV2
+#include <Protocol\FirmwareVolume2.h>
+#else
+#include <Protocol\FirmwareVolume.h>
+#endif
+#include <Protocol\LoadPe32Image.h>
+#include <Protocol\MpService.h>
+#if SMM_THUNK_IN_CSM == 1
+#include <Protocol\LegacyBiosExt.h>
+#include <Protocol\LegacyBios.h>
+#endif
+
+#if SMM_USE_FRAMEWORK
+#include <Protocol\SmmBase.h>
+#endif
+
+#if SMM_USE_PI
+#include <Protocol\SmmBase2.h>
+#include <Protocol\SmmReadyToLock.h>
+#include <Protocol\DxeSmmReadyToLock.h>
+#endif
+
+
+#if SMM_USE_PI
+#include <Protocol\SmmAccess2.h>
+#include <Protocol\SmmControl2.h>
+#else
+#include <Protocol\SmmAccess.h>
+#include <Protocol\SmmControl.h>
+#endif
+
+#include <Token.h>
+
+// {3AA83745-9454-4f7a-A7C0-90DBD02FAB8E}
+#define BDS_CONNECT_DRIVERS_PROTOCOL_GUID \
+ { 0x3aa83745, 0x9454, 0x4f7a, { 0xa7, 0xc0, 0x90, 0xdb, 0xd0, 0x2f, 0xab, 0x8e } }
+#define BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID \
+ {0xdbc9fd21, 0xfad8, 0x45b0, 0x9e, 0x78, 0x27, 0x15, 0x88, 0x67, 0xcc, 0x93}
+
+CPUINFO_HOB *gCpuinfoHob;
+SMM_HOB *gSmmHob;
+EFI_HOB_CPU *gCpuHob;
+UINT32 gBspSmmBase;
+SMM_ENTRY_INIT_STRUCT *gSmmEntryData;
+SMM_BASE_PRIVATE_STRUCT *gBasePrivate;
+SMM_DISPATCHER_PRIVATE_STRUCT *gDispatcherPrivate;
+EFI_PE32_IMAGE_PROTOCOL *gPe32Image;
+EFI_MP_SERVICES_PROTOCOL *gMpServices;
+
+
+#if SMM_USE_FRAMEWORK
+EFI_SMM_SYSTEM_TABLE *gSmstTable;
+#endif
+
+#if SMM_USE_PI
+EFI_SMM_SYSTEM_TABLE2 *gSmstTable2;
+#endif
+
+#if SMM_USE_PI
+EFI_SMM_CONTROL2_PROTOCOL *gSmmControl;
+EFI_SMM_ACCESS2_PROTOCOL *gSmmAccess;
+#else
+EFI_SMM_CONTROL_PROTOCOL *gSmmControl;
+EFI_SMM_ACCESS_PROTOCOL *gSmmAccess;
+#endif
+
+
+#if SMM_THUNK_IN_CSM == 1
+EFI_LEGACY_BIOS_PROTOCOL *gLegacyBios;
+EFI_LEGACY_BIOS_EXT_PROTOCOL *gLegacyBiosExt;
+#endif
+
+EFI_HANDLE gThisImageHandle;
+
+EFI_GUID gHobListGuid = HOB_LIST_GUID;
+EFI_GUID gSmmHobGuid = SMM_HOB_GUID;
+EFI_GUID gCpuinfoHobGuid = AMI_CPUINFO_HOB_GUID;
+EFI_GUID gEfiPe32ImageProtocolGuid = PE32_IMAGE_PROTOCOL_GUID;
+EFI_GUID gEfiMpServicesProtocolGuid = EFI_MP_SERVICES_PROTOCOL_GUID;
+EFI_GUID gBdsConnectDriversProtocolGuid = BDS_CONNECT_DRIVERS_PROTOCOL_GUID;
+EFI_GUID gBdsAllDriversConnectedProtocolGuid = BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID;
+#if SMM_USE_PI
+EFI_GUID gEfiEventDxeDispatchGuid = EFI_EVENT_GROUP_DXE_DISPATCH;
+//EFI_GUID gEfiDxeSmmReadyToLockProtocolGuid = EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL_GUID;
+#endif
+
+#if USE_FV2
+EFI_GUID gEfiFVProtocolGuid = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID;
+#else
+EFI_GUID gEfiFVProtocolGuid = EFI_FIRMWARE_VOLUME_PROTOCOL_GUID;
+#endif
+
+#if SMM_THUNK_IN_CSM == 1
+EFI_GUID gEfiLegacyBiosProtocolGuid = EFI_LEGACY_BIOS_PROTOCOL_GUID;
+EFI_GUID gEfiLegacyBiosExtProtocolGuid = EFI_LEGACY_BIOS_EXT_PROTOCOL_GUID;
+#endif
+
+#if SMM_USE_FRAMEWORK
+extern EFI_SMM_BASE_PROTOCOL gEfiSmmBase;
+#endif
+
+#if SMM_USE_PI
+extern EFI_SMM_BASE2_PROTOCOL gEfiSmmBase2;
+#endif
+
+UINT32 gBspSmmBase;
+SMM_ENTRY_INIT_STRUCT *gSmmEntryData;
+UINTN gBsp;
+
+EFI_GUID SmmEntryGuid =
+ {0xD2596F82,0xF0E1,0x49fa,0x95,0xBC,0x62,0x01,0x2C,0x79,0x57,0x28};
+ //D2596F82-F0E1-49fa-95BC-62012C795728
+EFI_GUID gEfiSmmCoreDispatcherGuid =
+ {0x4A37320B,0x3FB3,0x4365,0x97,0x30,0x9e,0x89,0xC6,0x00,0x39,0x5D};
+ //4A37320B-3FB3-4365-9730-9E89C600395D
+
+VOID SmmDispatcher();
+VOID SetDisallowRegistering();
+VOID SmmDriverDispatchHandler();
+
+extern UINT32 InSmmFuncLength;
+extern UINT32 InSmmFuncOffset;
+
+EFI_STATUS EfiSmmInSmm(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ OUT BOOLEAN *InSmm
+);
+
+//
+// This is the structure contains default values in Boot Services memory.
+// This table will be updated and copied into Runtime memory.
+//
+SMM_BASE_PRIVATE_STRUCT gSmmBasePrivateStruct =
+{
+ 0, //*CallBackFunc
+ FALSE, //InSmm
+ FALSE //DisallowCallbacks
+ //Additional members not specified.
+};
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CallFuncInSmm
+//
+// Description: Call function in SMM. If not in SMM, generate SW SMI, otherwise
+// call the function.
+//
+// Input: IN func -- Pointer to function
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID CallFuncInSmm(IN VOID func())
+{
+ if (!*gBasePrivate->InSmm) {
+#if SMM_USE_PI
+ UINT8 CommandPort = SMMBASE_CALLBACK;
+#else
+ UINT8 ArgBuffer = SMMBASE_CALLBACK;
+ UINTN ArgBufferSize = 1;
+#endif
+ gBasePrivate->CallBackFunc = func;
+
+ //Generate SW SMI
+#if SMM_USE_PI
+ gSmmControl->Trigger(gSmmControl, &CommandPort, NULL, FALSE, 0);
+#else
+ gSmmControl->Trigger(gSmmControl, &ArgBuffer, &ArgBufferSize, FALSE, 0);
+#endif
+ //This is cleared inside of SMM.
+ } else {
+ func();
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindMatchingMtrr
+//
+// Description: Search MTRRs for a matching MTRR.
+//
+// Input:
+// IN UINT64 BASE
+// IN UINT64 Mask
+//
+// Output:
+// UINT32 -- MSR for matching MTTR.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+#if SMM_CACHE_SUPPORT == 1
+#ifndef NEHALEM_CPU_MODULE
+VOID InitSmmCacheData()
+{
+ UINT32 Msr;
+ UINT32 i;
+ UINT8 NumMtrrs = (UINT8)ReadMsr(0xfe); //MSR_IA32_MTRR_CAP
+ UINT32 RegEAX, RegEBX, RegECX, RegEDX;
+ UINT8 NumOfMemoryBits = 36;
+ UINT64 MemoryMask;
+
+ CPULib_CpuID(0x80000008, &RegEAX, &RegEBX, &RegECX, &RegEDX);
+ //Check if CPU supports this CPUID.
+ if (RegEAX != 0 && RegEAX != 0xffffffff)
+ NumOfMemoryBits = (UINT8)RegEAX & 0xff;
+
+ MemoryMask = Shl64(1, NumOfMemoryBits)- 1;
+
+ gDispatcherPrivate->SmrrEnable = FALSE;
+ gDispatcherPrivate->SmrrMsr = GetSmrrBaseMsr();
+ gDispatcherPrivate->TsegMsr = 0;
+ gDispatcherPrivate->TsegMsrBase = (UINT64)(UINTN)gSmmHob->Tseg;
+ gDispatcherPrivate->TsegMsrMask = (MemoryMask & (~(TSEG_SIZE - 1))) | (1 << 11);
+
+ //MSRs will not be found if there is not enough MSRs for caching SMM.
+
+ for(i = 0, Msr = 0x200; i < NumMtrrs; ++i, Msr+=2) { //MTRR_PHYS_BASE_0
+ if ((ReadMsr(Msr) & ~(UINT64)0xff) == gDispatcherPrivate->TsegMsrBase
+ && ReadMsr(Msr+1) == gDispatcherPrivate->TsegMsrMask
+ ) {
+ gDispatcherPrivate->TsegMsr = Msr;
+ }
+ }
+
+ if (CPULib_IsSmrrEnabled()) gDispatcherPrivate->SmrrEnable = TRUE;
+}
+#endif
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: LoadRealModeFile
+//
+// Description: Load a real mode file into a buffer.
+//
+// Input:
+// IN EFI_GUID *Guid
+// OUT VOID **Buffer
+// OUT UINTN *BufferSize
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS LoadRealModeFile(EFI_GUID *Guid, VOID **Buffer, UINTN *BufferSize)
+{
+#if USE_FV2
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+#else
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+#endif
+ UINT32 Authentication;
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN i;
+
+ *Buffer=0;
+ *BufferSize=0;
+
+ Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiFVProtocolGuid,NULL,&NumHandles,&HandleBuffer);
+ if (EFI_ERROR(Status)) return Status;
+
+ for (i = 0; i< NumHandles; ++i) {
+ Status = pBS->HandleProtocol(HandleBuffer[i],&guidFV,&Fv);
+ if (EFI_ERROR(Status)) continue;
+
+ Status = Fv->ReadSection(Fv,
+ Guid,
+ EFI_SECTION_RAW,
+ 0, //Instance
+ Buffer,
+ BufferSize,
+ &Authentication);
+
+ if (Status == EFI_SUCCESS) break;
+ }
+
+ pBS->FreePool(HandleBuffer);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EarlyAllocSmmMemory
+//
+// Description: Allocate SMM memory before SMM memory manager available.
+//
+// Input:
+// IN UINT32 Size -- Memory size
+//
+// Output: VOID * -- ptr to allocated memory.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID * EarlyAllocSmmMemory(IN UINT32 Size)
+{
+ UINT8 *AllocatedAddress;
+ UINT32 AdjSize;
+
+ AdjSize = (Size + 7) & ~7; //Minimum 8 bytes.
+ if (AdjSize > gBasePrivate->SmmAllocMemoryLength) return 0;
+
+ AllocatedAddress = (UINT8*)gBasePrivate->SmmAllocMemoryStart;
+ gBasePrivate->SmmAllocMemoryStart = AllocatedAddress + AdjSize;
+ gBasePrivate->SmmAllocMemoryLength -= AdjSize;
+
+ return AllocatedAddress;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EarlyAllocSmmMemoryAlign
+//
+// Description:
+// Allocate SMM memory before SMM memory manager available with specified alignment.
+// Memory address returned will be the next aligned address available and the free memory
+// before the aligned address can not be allocated.
+//
+// Input:
+// IN UINT32 Size -- Memory size.
+// IN UINT32 Align -- Alignment. Must be 2^n.
+//
+// Output: VOID * -- ptr to allocated memory.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID * EarlyAllocSmmMemoryAlign(IN UINT32 Size, IN UINT32 Align)
+{
+ UINT8* AllocatedAddress;
+ UINT8 *OrigAddress;
+ UINT32 AdjSize;
+
+ AdjSize = (Size + 7) & ~7; //Minimum 8 bytes.
+ if (AdjSize > gBasePrivate->SmmAllocMemoryLength) return 0;
+
+ OrigAddress = (UINT8*)gBasePrivate->SmmAllocMemoryStart;
+ AllocatedAddress = (UINT8*)(((UINT32)OrigAddress + (Align - 1)) & ~(Align - 1));
+
+ gBasePrivate->SmmAllocMemoryStart = AllocatedAddress + AdjSize;
+ gBasePrivate->SmmAllocMemoryLength -= (UINT32)(AllocatedAddress + AdjSize - OrigAddress);
+
+ return AllocatedAddress;
+}
+
+//SMM thunk either requires AB Segment of CSM.
+#if SMM_THUNK_NO_AB_SEG == 0 || SMM_THUNK_IN_CSM == 1
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CopySmmThunkAfterBspEntry
+//
+// Description:
+// Copy SMM Thunk to immediately after SMM BSP entry.
+//
+// Input:
+// IN VOID *SmmEntryBuffer -- pointer to SMM Entry file
+// IN UINTN SmmEntryBufferSize -- Size of SMM Entry file
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS CopySmmThunkAfterBspEntry (
+ IN VOID *SmmEntryBuffer,
+ IN UINTN SmmEntryBufferSize
+)
+{
+ UINT8 *SmmThunkStart = (UINT8*)gBspSmmBase + 0x8000 + gSmmEntryData->SmmThunkProcOffset;
+ UINT16 AdrFixup;
+ UINT16 SegFixup;
+
+ *(UINT32*)(gBspSmmBase + 0x8000 + gSmmEntryData->LCodeSelBaseOffset) += (UINT32)SmmThunkStart;
+ *(UINT32*)((UINT8*)SmmEntryBuffer + gSmmEntryData->LCodeSelBaseOffset) += (UINT32)SmmThunkStart;
+
+ MemCpy(SmmThunkStart,
+ (UINT8*)SmmEntryBuffer + gSmmEntryData->SmmThunkProcOffset,
+ gSmmEntryData->SmmThunkLength
+ );
+
+ gDispatcherPrivate->SmmThunkProc = (VOID(*)())SmmThunkStart;
+
+ gDispatcherPrivate->SmmThunkData = (SMM_THUNK_DATA*)
+ (((UINTN)SmmThunkStart + gSmmEntryData->SmmThunkLength + 16) & ~0xf);
+
+ ASSERT(((UINTN)gDispatcherPrivate->SmmThunkData & 0xf) == 0);
+
+ //Update Thunk to set Smm Thunk Data.
+ AdrFixup = *(UINT16*)(SmmThunkStart + 2);
+ SegFixup = *(UINT16*)(SmmThunkStart + 4);
+
+ *(UINT32*)(SmmThunkStart + AdrFixup) = (UINT32)gDispatcherPrivate->SmmThunkData;
+ *(UINT16*)(SmmThunkStart + SegFixup) = (UINT16)((UINT32)gDispatcherPrivate->SmmThunkData >> 4);
+
+ //Max 4k of stack.
+ //In this case, code, data, and stack in this 4k block.
+ //The ss=ds, and points to the end of the code,
+ // so code will have to be subtracted from the 4k top,
+ // so ss:sp = cs:1000h
+ gDispatcherPrivate->SmmThunkData->Below1MStack =
+ 0x1000
+ - gSmmEntryData->SmmEntrySize
+ - gSmmEntryData->SmmThunkLength
+ - 0xf; //Could be up to 15 bytes skipped for alignment purposes;
+ gDispatcherPrivate->SmmThunkData->Below1MStack &= ~1; //Align on word bounary;
+
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Limit = 0x3ff;
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Base = 0;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CopySmmThunkAtStartABSegment
+//
+// Description:
+// Copy SMM Thunk to start of AB Segment
+//
+// Input:
+// IN VOID *SmmEntryBuffer -- pointer to SMM Entry file
+// IN UINTN SmmEntryBufferSize -- Size of SMM Entry file
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS CopySmmThunkAtStartABSegment(
+ IN VOID *SmmEntryBuffer,
+ IN UINTN SmmEntryBufferSize
+)
+{
+ UINT8 *SmmThunkStart;
+ UINT16 AdrFixup;
+ UINT16 SegFixup;
+
+#if SMM_EXCLUDE_A000 != 1
+ SmmThunkStart = (UINT8*)0xa0000;
+#else
+ SmmThunkStart = (UINT8*)0xb0000;
+#endif
+
+ *(UINT32*)(gBspSmmBase + 0x8000 + gSmmEntryData->LCodeSelBaseOffset) += (UINT32)SmmThunkStart;
+
+//TODO: remove and share GDT between all CPUs. CPU0 is already copied. CPUx will copy this buffer later.
+ *(UINT32*)((UINT8*)SmmEntryBuffer + gSmmEntryData->LCodeSelBaseOffset) += (UINT32)SmmThunkStart;
+
+
+ MemCpy(SmmThunkStart,
+ (UINT8*)SmmEntryBuffer + gSmmEntryData->SmmThunkProcOffset,
+ gSmmEntryData->SmmThunkLength
+ );
+
+ gDispatcherPrivate->SmmThunkProc = (VOID(*)())SmmThunkStart;
+
+ //SmmThunkData must be aligned on 16 byte boundary.
+ gDispatcherPrivate->SmmThunkData = (SMM_THUNK_DATA*)
+ (((UINTN)SmmThunkStart + gSmmEntryData->SmmThunkLength + 16) & ~0xf);
+ ASSERT(((UINTN)gDispatcherPrivate->SmmThunkData & 0xf) == 0);
+
+ //Update Thunk to set Smm Thunk Data.
+ AdrFixup = *(UINT16*)(SmmThunkStart + 2);
+ SegFixup = *(UINT16*)(SmmThunkStart + 4);
+
+ *(UINT32*)(SmmThunkStart + AdrFixup) = (UINT32)gDispatcherPrivate->SmmThunkData;
+ *(UINT16*)(SmmThunkStart + SegFixup) = (UINT16)((UINT32)gDispatcherPrivate->SmmThunkData >> 4);
+
+ //Max 4k of stack.
+ //If in SMM, 1 block is reserved for stack and data.
+ gDispatcherPrivate->SmmThunkData->Below1MStack =
+ 0x1000
+ - gSmmEntryData->SmmThunkLength
+ - 0xf; //Could be up to 15 bytes skipped for alignment purposes;
+ gDispatcherPrivate->SmmThunkData->Below1MStack &= ~1; //Align on word boundary;
+
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Limit = 0x3ff;
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Base = 0;
+ return EFI_SUCCESS;
+}
+
+#if SMM_THUNK_IN_CSM == 1
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CopySmmThunkInCsmEBDA
+//
+// Description:
+// Copy SMM Thunk to CSM. Data will be in EBDA.
+//
+// Input:
+// IN VOID *SmmEntryBuffer -- pointer to SMM Entry file
+// IN UINTN SmmEntryBufferSize -- Size of SMM Entry file
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS CopySmmThunkInCsmEBDA (
+ VOID *SmmEntryBuffer,
+ UINTN SmmEntryBufferSize
+)
+{
+ UINT8 *SmmThunkStart;
+ UINT16 AdrFixup;
+ UINT16 SegFixup;
+ UINT32 EbdaStart;
+ EFI_STATUS Status;
+
+ //Initialize this with the pointer to the Buffer in memory.
+ //This will be update later to the newly allocated region.
+ SmmThunkStart = (UINT8*)SmmEntryBuffer + gSmmEntryData->SmmThunkProcOffset;
+
+ //In case this is 64-bits, initialize upper 32-bits to 0.
+ //Allocate Ebda, updates only the lower 32-bits.
+ gDispatcherPrivate->SmmThunkData = 0;
+
+ Status = gLegacyBiosExt->AllocateEbda(
+ gLegacyBiosExt,
+ 4,
+ (UINT32*)&gDispatcherPrivate->SmmThunkData,
+ &gDispatcherPrivate->EbdaStartOffset
+ );
+ if (EFI_ERROR(Status)) return Status;
+
+ EbdaStart = (*(UINT16*)(0x40e)) << 4;
+
+ //Max 4k of stack.
+ //If in SMM, 1 block is reserved for stack and data.
+ gDispatcherPrivate->SmmThunkData->Below1MStack = 0x1000;
+
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Limit = 0x3ff;
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Base = 0;
+
+ AdrFixup = *(UINT16*)(SmmThunkStart + 2);
+ SegFixup = *(UINT16*)(SmmThunkStart + 4);
+
+ *(UINT32*)(SmmThunkStart + AdrFixup) = (UINT32)gDispatcherPrivate->SmmThunkData - EbdaStart;
+ *(UINT16*)(SmmThunkStart + SegFixup) = (UINT16)(((UINT32)gDispatcherPrivate->SmmThunkData - EbdaStart) >> 4);
+
+ //Allocate CSM memory.
+ Status = gLegacyBios->GetLegacyRegion(
+ gLegacyBios,
+ gSmmEntryData->SmmThunkLength,
+ 0, //In e_0000 - f_ffff.
+ 1, //Byte alignment
+ &SmmThunkStart
+ );
+ if (EFI_ERROR(Status)) return Status;
+
+ *(UINT32*)(gBspSmmBase + 0x8000 + gSmmEntryData->LCodeSelBaseOffset) += (UINT32)SmmThunkStart;
+ *(UINT32*)((UINT8*)SmmEntryBuffer + gSmmEntryData->LCodeSelBaseOffset) += (UINT32)SmmThunkStart;
+
+ //Copy to CSM memory.
+ Status = gLegacyBios->CopyLegacyRegion(
+ gLegacyBios,
+ gSmmEntryData->SmmThunkLength,
+ SmmThunkStart,
+ (UINT8*)SmmEntryBuffer + gSmmEntryData->SmmThunkProcOffset
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ gDispatcherPrivate->SmmThunkProc = (VOID(*)())SmmThunkStart;
+
+ ASSERT(((UINTN)gDispatcherPrivate->SmmThunkData & 0xf) == 0);
+
+ //Max 4k of stack.
+ gDispatcherPrivate->SmmThunkData->Below1MStack = 0x1000;
+
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Limit = 0x3ff;
+ gDispatcherPrivate->SmmThunkData->LegacyIdtDesc.Base = 0;
+
+ return EFI_SUCCESS;
+}
+#endif
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: LoadAndInitDispatcherImages
+//
+// Description: Load and initialize dispatcher images.
+//
+// Input:
+// IN EFI_SYSTEM_TABLE SystemTable
+// IN UINT32 NumCpus
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID LoadAndInitDispatcherImages(
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINT32 NumCpus
+)
+{
+ EFI_STATUS Status;
+ VOID *SmmEntryBuffer;
+ UINTN SmmEntryBufferSize;
+ VOID *SmmBaseSaveBuffer;
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT32 AuthenticationStatus;
+ UINT8 *SmmBase;
+ UINT8 *ApStackTop;
+ UINT16 Bsp = gSmmHob->Bsp;
+ UINT32 i;
+ UINT32 TssBaseAddress;
+
+ SMM_ENTRY_INIT_STRUCT *SmmApEntryInit;
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+ EFI_HANDLE ImageHandle;
+
+ CPU_SmmMemoryInit(gSmmHob);
+
+ //
+ // Load BSP SMM real mode.
+ // This must be done before loading protected mode dispatcher
+ // because the entry point of the protected mode dispatcher
+ // initializes some of SMM real mode variables.
+ //
+
+ Status = LoadRealModeFile(&SmmEntryGuid, &SmmEntryBuffer, &SmmEntryBufferSize);
+ ASSERT_EFI_ERROR(Status);
+
+ SmmBase = (UINT8*)gBspSmmBase;
+ MemCpy(SmmBase+0x8000, SmmEntryBuffer, ((SMM_ENTRY_INIT_STRUCT*)((UINT8*)SmmEntryBuffer+4))->SmmEntrySize);
+
+ gSmmEntryData->CpuNo = 0;
+ gSmmEntryData->SmmEntryStart = (VOID*)(SmmBase + 0x8000);
+ gSmmEntryData->DispatcherPrivate = gDispatcherPrivate;
+
+ *(UINT32*)(SmmBase + 0x8000 + gSmmEntryData->GdtDescBaseOffset) += gBspSmmBase + 0x8000;
+
+ TssBaseAddress=*(UINT16*)(SmmBase + 0x8000 + gSmmEntryData->TssSelBaseOffset) + gBspSmmBase + 0x8000;
+ *(UINT16*)(SmmBase + 0x8000 + gSmmEntryData->TssSelBaseOffset) = TssBaseAddress;
+ *(UINT8*)(SmmBase + 0x8000 + gSmmEntryData->TssSelBaseOffset+2) = TssBaseAddress>>16;
+ *(UINT8*)(SmmBase + 0x8000 + gSmmEntryData->TssSelBaseOffset+5) = TssBaseAddress>>24;
+
+
+ gDispatcherPrivate->EbdaStartOffset = 0; //CopySmmThunkInCsmEBDA will update this.
+//SMM thunk either requires AB Segment of CSM.
+#if SMM_THUNK_NO_AB_SEG == 0 || SMM_THUNK_IN_CSM == 1
+#if SMM_THUNK_IN_CSM == 0
+ if (gBspSmmBase < 0x100000)
+ CopySmmThunkAfterBspEntry(SmmEntryBuffer, SmmEntryBufferSize);
+ else
+ CopySmmThunkAtStartABSegment(SmmEntryBuffer, SmmEntryBufferSize);
+#else
+ CopySmmThunkInCsmEBDA(SmmEntryBuffer, SmmEntryBufferSize);
+#endif
+#endif
+
+#ifdef EFIx64
+ //Setup pages for virtual memory after Stack.
+
+ //align page directories to 4k.
+ {
+ UINT8 *PageTable;
+ UINT32 NumAddrLines = gCpuHob->SizeOfMemorySpace;
+
+ if (NumAddrLines > SMM_PAGING_MAX_ADDRESS_LINES) NumAddrLines = SMM_PAGING_MAX_ADDRESS_LINES;
+
+ PageTable = EarlyAllocSmmMemoryAlign(GetPageTableNumPages(NumAddrLines) * 4096, 4096);
+ ASSERT(PageTable);
+ FillPageTable(NumAddrLines, PageTable);
+ gDispatcherPrivate->PageDirectories = PageTable;
+ }
+#endif
+
+ //
+ // Load and call entry of protected mode dispatcher.
+ // This must be done before AP real mode entry point because
+ // the protected mode init provides a pointer for the AP real mode
+ // to call after switching to protected mode.
+
+ Buffer = 0;
+ Status = FvReadPe32Image(
+ &gEfiSmmCoreDispatcherGuid,&Buffer,&BufferSize,
+ &AuthenticationStatus);
+ ASSERT_EFI_ERROR(Status);
+
+ gBasePrivate->Pe32DispatcherImage =
+ (VOID*)(((UINTN)gBasePrivate->SmmAllocMemoryStart + 4095) & ~4095);
+ gBasePrivate->Pe32DispatcherImageSize=EFI_SIZE_TO_PAGES(gSmmHob->ManagedMemSize);
+
+ Status=gPe32Image->LoadPeImage(
+ gPe32Image, gThisImageHandle,
+ NULL, //Either DevicePath or
+ Buffer, BufferSize, //Buffer. This will be zero if DevicePath.
+ (EFI_PHYSICAL_ADDRESS)gBasePrivate->Pe32DispatcherImage,
+ &gBasePrivate->Pe32DispatcherImageSize, &ImageHandle,
+ &EntryPoint, EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ gBasePrivate->Pe32DispatcherImageSize=EFI_PAGES_TO_SIZE(gBasePrivate->Pe32DispatcherImageSize);
+
+ pBS->FreePool(Buffer);
+//
+// Give control to protected mode dispatcher. The dispatcher is in SMM memory,
+// however, the CPU is NOT in SMM mode. Currently SMM space is open.
+//
+ if (!EFI_ERROR(Status)) {
+ TRACE((TRACE_ALWAYS,"SMM.SmmDispatcher.Entry(%lX)\n",EntryPoint));
+ Status = ((DISPATCHER_ENTRY_POINT)EntryPoint)(
+ ImageHandle,
+ SystemTable,
+ gBasePrivate,
+ gDispatcherPrivate,
+#if SMM_USE_FRAMEWORK
+ &gSmstTable,
+#else
+ NULL,
+#endif
+#if SMM_USE_PI
+ &gSmstTable2
+#else
+ NULL
+#endif
+ );
+ }
+ ASSERT_EFI_ERROR(Status);
+
+ gSmmEntryData->SmmStackTop = (VOID*)(gSmmHob->ManagedMemStart + BSP_SMM_STACK_SIZE);
+
+ //Copy ApCode to SMM region.
+
+ ApStackTop = gSmmEntryData->SmmStackTop + AP_SMM_STACK_SIZE;
+
+ for (i = 0; i < NumCpus; ++i) {
+ static UINT32 ApNum = 0; //BSP is given CPU #0, and APs 1,2...
+
+ if (i == Bsp) continue;
+ ++ApNum;
+ SmmBase = (VOID*)gSmmHob->SmmBase[i];
+ MemCpy(SmmBase + 0x8000, SmmEntryBuffer, SmmEntryBufferSize);
+ SmmApEntryInit = (SMM_ENTRY_INIT_STRUCT*) (SmmBase + 0x8004);
+ SmmApEntryInit->SmmEntryStart = SmmBase + 0x8000;
+ SmmApEntryInit->DispatcherEntry = gSmmEntryData->DispatcherEntry;
+ SmmApEntryInit->DispatcherPrivate = gDispatcherPrivate;
+ SmmApEntryInit->SmmStackTop = ApStackTop;
+ SmmApEntryInit->CpuNo = ApNum;
+
+ *(UINT32*)(SmmApEntryInit->GdtDescBaseOffset + SmmBase + 0x8000)
+ += (UINT32)SmmBase + 0x8000;
+
+ TssBaseAddress=(UINT32)((*(UINT16*)(SmmBase + 0x8000 + SmmApEntryInit->TssSelBaseOffset)) + (SmmBase + 0x8000));
+ *(UINT16*)(SmmBase + 0x8000 + SmmApEntryInit->TssSelBaseOffset) = TssBaseAddress;
+ *(UINT8*)(SmmBase + 0x8000 + SmmApEntryInit->TssSelBaseOffset+2) = (TssBaseAddress>>16);
+ *(UINT8*)(SmmBase + 0x8000 + SmmApEntryInit->TssSelBaseOffset+5) = (TssBaseAddress>>24);
+
+ ApStackTop += AP_SMM_STACK_SIZE;
+ }
+
+ pBS->FreePool(SmmEntryBuffer);
+
+ SmmBaseSaveBuffer = Malloc(SmmGetBaseSaveBufferSize());
+ ASSERT(SmmBaseSaveBuffer);
+
+ SmmSetupDefaultHandler(SmmBaseSaveBuffer, gSmmHob);
+
+ for (i = 0; i < gSmmHob->NumCpus; ++i) {
+ if (i == gBsp) {
+ SmmBaseChangeOnCpu((VOID*)gSmmHob->SmmBase[i]);
+ continue;
+ }
+
+ gMpServices->StartupThisAP(
+ gMpServices,
+ SmmBaseChangeOnCpu,
+ i, //Cpu
+ NULL,
+ 0,
+ (VOID*)gSmmHob->SmmBase[i]
+#if !(PI_SPECIFICATION_VERSION < 0x0001000A || BACKWARD_COMPATIBLE_MODE && defined(NO_PI_MP_SERVICES_SUPPORT))
+ , NULL
+#endif
+ );
+ }
+
+ SmmRemoveDefaultHandler(SmmBaseSaveBuffer);
+ pBS->FreePool(SmmBaseSaveBuffer);
+}
+
+VOID InitgBasePrivate()
+{
+ UINT32 NumCpus = gSmmHob->NumCpus;
+ gBasePrivate->SmmHob = gSmmHob;
+ gBasePrivate->CallBackFunc = 0;
+ gBasePrivate->SmmAllocMemoryStart =
+ (VOID*) (gSmmHob->ManagedMemStart + BSP_SMM_STACK_SIZE + AP_SMM_STACK_SIZE * (NumCpus - 1));
+ gBasePrivate->SmmAllocMemoryLength =
+ gSmmHob->ManagedMemSize - BSP_SMM_STACK_SIZE - AP_SMM_STACK_SIZE * (NumCpus - 1);
+}
+
+VOID InitgDispatcherPrivate()
+{
+ UINT8 i;
+ UINT32 SmmNum;
+ UINT32 NumCpus = gSmmHob->NumCpus;
+ UINT8 *XmmSaveBase;
+
+ gDispatcherPrivate = EarlyAllocSmmMemory(sizeof(*gDispatcherPrivate));
+ ASSERT(gDispatcherPrivate);
+
+ gDispatcherPrivate->NumCpus = NumCpus;
+ gDispatcherPrivate->NumCpusInSmm = 0;
+ gDispatcherPrivate->HandlerListHead = NULL;
+ gDispatcherPrivate->FloatingPointSave = FALSE;
+
+ //Allocate a XMM Save Restore on a 16-byte boundary
+ XmmSaveBase = EarlyAllocSmmMemoryAlign(NumCpus * 512, 16);
+ gDispatcherPrivate->SmmXmmSave = EarlyAllocSmmMemory(NumCpus * sizeof(VOID*));
+ for (i = 0; i < NumCpus; ++i) {
+ gDispatcherPrivate->SmmXmmSave[i] = XmmSaveBase;
+ XmmSaveBase += 512;
+ }
+
+ //Initialize SmmCpuInfo
+ gDispatcherPrivate->SmmCpuInfo = EarlyAllocSmmMemory(sizeof(SMM_CPU_INFO) * NumCpus);
+ ASSERT(gDispatcherPrivate->SmmCpuInfo);
+ MemSet(gDispatcherPrivate->SmmCpuInfo, sizeof(SMM_CPU_INFO) * NumCpus, 0);
+
+ gDispatcherPrivate->SmmCpuInfo[0].ApicId = gCpuinfoHob->Cpuinfo[gSmmHob->Bsp].ApicId;
+
+ SmmNum = 1;
+ for (i = 0; i < NumCpus; ++i) {
+ if (i == gSmmHob->Bsp) continue;
+ gDispatcherPrivate->SmmCpuInfo[SmmNum].ApicId = gCpuinfoHob->Cpuinfo[i].ApicId;
+ ++SmmNum;
+ }
+
+ //Initialize AP control for multi-threaded SMM.
+ gDispatcherPrivate->SmmApCpuControl = EarlyAllocSmmMemory(sizeof(SMM_AP_CPU_CONTROL) * NumCpus);
+ ASSERT(gDispatcherPrivate->SmmApCpuControl);
+ MemSet((VOID*)gDispatcherPrivate->SmmApCpuControl, sizeof(SMM_AP_CPU_CONTROL) * NumCpus, 0);
+
+ gDispatcherPrivate->SmmControl = gSmmControl;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CreateRuntimeInSmmFunction
+//
+// Description:
+// Create InSmm function in runtime.
+//
+// Input: VOID
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID *CreateRuntimeInSmmFunction()
+{
+ UINT8 *RuntimeInSmmFunc;
+ EFI_STATUS Status;
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesCode, InSmmFuncLength, &RuntimeInSmmFunc);
+ ASSERT_EFI_ERROR(Status);
+
+ MemCpy(RuntimeInSmmFunc, EfiSmmInSmm, InSmmFuncLength);
+
+ return RuntimeInSmmFunc;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: DisableSmmCallbacks
+//
+// Description:
+// This is signaled before booting or shell.
+// This makes the SMM Base protocol register/unregister unsupported.
+//
+// Input:
+// IN EFI_EVENT Event
+// IN VOID *Context
+//
+// Output:
+// VOID
+//
+//
+// NOTE: This routine could be called multiple times right before booting.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID DisableSmmCallbacks(IN EFI_EVENT Event, IN VOID *Context)
+{
+#if SMM_USE_PI
+ EFI_HANDLE Handle = NULL;
+#endif
+ //This should only run once, even if called by different events.
+ static BOOLEAN HasRun = FALSE;
+ if (HasRun) return;
+
+ pBS->CloseEvent(Event);
+
+ //If we are following PI1.1 model we should dispatch rest of SMM drivers whose DEPEX
+ //was not TRUE at the time of the first pass.
+#if SMM_USE_PI
+ CallFuncInSmm(SmmDispatcher);
+
+ pBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiDxeSmmReadyToLockProtocolGuid, NULL,
+ NULL
+ );
+#endif
+
+ CallFuncInSmm(SetDisallowRegistering);
+ HasRun = TRUE;
+}
+
+#if SMM_USE_PI
+VOID SmmIplGuidedEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context)
+{
+ CallFuncInSmm(SmmDriverDispatchHandler);
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: LocateProtocols
+//
+// Description:
+// Locate protocols needed for SMM Base.
+//
+// Input: VOID
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID LocateProtocols()
+{
+ EFI_STATUS Status;
+#if SMM_USE_PI
+ Status = pBS->LocateProtocol(&gEfiSmmAccess2ProtocolGuid, NULL, &gSmmAccess);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = pBS->LocateProtocol(&gEfiSmmControl2ProtocolGuid, NULL, &gSmmControl);
+ ASSERT_EFI_ERROR(Status);
+#else
+ Status = pBS->LocateProtocol(&gEfiSmmAccessProtocolGuid, NULL, &gSmmAccess);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = pBS->LocateProtocol(&gEfiSmmControlProtocolGuid, NULL, &gSmmControl);
+ ASSERT_EFI_ERROR(Status);
+#endif
+
+ Status = pBS->LocateProtocol(&gEfiPe32ImageProtocolGuid, NULL, &gPe32Image);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = pBS->LocateProtocol(&gEfiMpServicesProtocolGuid, NULL, &gMpServices);
+ ASSERT_EFI_ERROR(Status);
+
+#if SMM_THUNK_IN_CSM == 1
+ Status = pBS->LocateProtocol(&gEfiLegacyBiosProtocolGuid, NULL, &gLegacyBios);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = pBS->LocateProtocol(&gEfiLegacyBiosExtProtocolGuid, NULL, &gLegacyBiosExt);
+ ASSERT_EFI_ERROR(Status);
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: FindHobs
+//
+// Description: Locate the HOBs needed.
+//
+// Input: VOID
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS FindHobs()
+{
+ VOID *FirstHob;
+ EFI_STATUS Status;
+
+ //Parse hobs to get CPU Hob.
+ //Find first Hob
+ FirstHob = GetEfiConfigurationTable(pST,&gHobListGuid);
+ if (!FirstHob) {
+ TRACE((TRACE_ALWAYS, "SmmBase.Entry()Error:Unable to find CPUInfo HOB\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ //Find SMM Hob.
+ gSmmHob = (SMM_HOB*) FirstHob;
+ while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &gSmmHob))) {
+ if (guidcmp(&((EFI_HOB_GUID_TYPE*)gSmmHob)->Name, &gSmmHobGuid) == 0) {
+ break;
+ }
+ }
+ if (EFI_ERROR(Status)) return Status;
+
+ //Find Cpu Info Hob.
+ gCpuinfoHob = (CPUINFO_HOB*) FirstHob;
+ while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &gCpuinfoHob))) {
+ if (guidcmp(&((EFI_HOB_GUID_TYPE*)gCpuinfoHob)->Name, &gCpuinfoHobGuid) == 0) {
+ break;
+ }
+ }
+ if (EFI_ERROR(Status)) return Status;
+
+ gCpuHob = (EFI_HOB_CPU*)FirstHob;
+ Status = FindNextHobByType(EFI_HOB_TYPE_CPU, &gCpuHob);
+ if (EFI_ERROR(Status)) return Status;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SmmInitEntry
+//
+// Description: SMM Installer Entry Point.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmInitEntry(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+ EFI_EVENT BootEvent;
+ EFI_EVENT Event;
+ VOID *Registration;
+ VOID *RuntimeInSmmFunc;
+#if SMM_USE_FRAMEWORK
+ EFI_SMM_BASE_PROTOCOL *RuntimeSmmBase;
+#endif
+
+ InitAmiLib(ImageHandle,SystemTable);
+
+ gThisImageHandle = ImageHandle;
+
+ LocateProtocols();
+
+ Status = FindHobs();
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+
+ Status = gMpServices->WhoAmI(gMpServices, &gBsp);
+ ASSERT_EFI_ERROR(Status);
+
+ gBspSmmBase = gSmmHob->SmmBase[gSmmHob->Bsp];
+ gSmmEntryData = (SMM_ENTRY_INIT_STRUCT *) (gBspSmmBase + 0x8004);
+
+
+ // Allocate space in runtime services for gPrivate.
+ // This is needed because this pointer will be used by SMM during runtime.
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, sizeof(SMM_BASE_PRIVATE_STRUCT), &gBasePrivate);
+ ASSERT_EFI_ERROR(Status);
+
+ // Copy the private structure. This does not copy the pointer. It copies the entire structure.
+ *gBasePrivate = gSmmBasePrivateStruct; //Make available during runtime.
+
+ InitgBasePrivate();
+ RuntimeInSmmFunc = CreateRuntimeInSmmFunction();
+
+#if SMM_USE_FRAMEWORK
+ gEfiSmmBase.InSmm = (EFI_SMM_INSIDE_OUT)RuntimeInSmmFunc;
+#endif
+#if SMM_USE_PI
+ gEfiSmmBase2.InSmm = (EFI_SMM_INSIDE_OUT2)RuntimeInSmmFunc;
+#endif
+ gBasePrivate->InSmm = (UINT8*)RuntimeInSmmFunc + InSmmFuncOffset;
+
+ Status = gSmmAccess->Open(gSmmAccess
+#if SMM_USE_PI == 0
+ ,0
+#endif
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ InitgDispatcherPrivate();
+
+#if SMM_CACHE_SUPPORT == 1
+#ifndef NEHALEM_CPU_MODULE
+ InitSmmCacheData();
+#endif
+#endif
+
+ LoadAndInitDispatcherImages(pST, gSmmHob->NumCpus);
+
+ gSmmAccess->Close(gSmmAccess
+#if SMM_USE_PI == 0
+ , 0
+#endif
+ );
+
+ // locks SMM area so no one else can change it
+ gSmmAccess->Lock(gSmmAccess
+#if SMM_USE_PI == 0
+ , 0
+#endif
+ );
+
+ //For security reasons SMM should call from inside SMM to outside SMM before option ROMs are loaded.
+ //The following callback is registered to disable this. When this is disabled, no new SMM drivers
+ //can be registered.
+
+ //This call back is only available since core 4.6.3.5.
+ Status = RegisterProtocolCallback(
+ &gBdsAllDriversConnectedProtocolGuid,
+ DisableSmmCallbacks,
+ NULL,
+ &Event,
+ &Registration
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //In cases where core does not support a call back before option roms are executed.
+ //The calling outside of SMM will be disabled before shell or a OS is loaded.
+ Status = CreateReadyToBootEvent(
+ TPL_CALLBACK,
+ DisableSmmCallbacks,
+ NULL,
+ &BootEvent
+ );
+ ASSERT_EFI_ERROR(Status);
+
+#if SMM_USE_PI
+ //Setup Notification when BDS has finished 1st pass on loading drivers...
+ Status = pBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ SmmIplGuidedEventNotify,
+ NULL,
+ &gEfiEventDxeDispatchGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR(Status);
+
+#endif
+
+#if SMM_USE_FRAMEWORK
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, sizeof(EFI_SMM_BASE_PROTOCOL), &RuntimeSmmBase);
+ ASSERT_EFI_ERROR(Status);
+ *RuntimeSmmBase = gEfiSmmBase;
+#endif
+
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+#if SMM_USE_FRAMEWORK
+ &gEfiSmmBaseProtocolGuid, RuntimeSmmBase,
+#endif
+#if SMM_USE_PI
+ &gEfiSmmBase2ProtocolGuid, &gEfiSmmBase2,
+#endif
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************