summaryrefslogtreecommitdiff
path: root/Core/EM/SMM
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/SMM
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/SMM')
-rw-r--r--Core/EM/SMM/SMM.cif19
-rw-r--r--Core/EM/SMM/SMM.sdl101
-rw-r--r--Core/EM/SMM/Smm.chmbin0 -> 123054 bytes
-rw-r--r--Core/EM/SMM/SmmBase.c911
-rw-r--r--Core/EM/SMM/SmmBase.cif15
-rw-r--r--Core/EM/SMM/SmmBase.dxs107
-rw-r--r--Core/EM/SMM/SmmBase.mak84
-rw-r--r--Core/EM/SMM/SmmBase.sdl25
-rw-r--r--Core/EM/SMM/SmmBase2.c102
-rw-r--r--Core/EM/SMM/SmmBaseAsm.asm139
-rw-r--r--Core/EM/SMM/SmmCommunicate.c462
-rw-r--r--Core/EM/SMM/SmmCommunicate.cif12
-rw-r--r--Core/EM/SMM/SmmCommunicate.dxs67
-rw-r--r--Core/EM/SMM/SmmCommunicate.mak91
-rw-r--r--Core/EM/SMM/SmmCommunicate.sdl44
-rw-r--r--Core/EM/SMM/SmmDispatcher.c1533
-rw-r--r--Core/EM/SMM/SmmDispatcher.cif17
-rw-r--r--Core/EM/SMM/SmmDispatcher.dxs59
-rw-r--r--Core/EM/SMM/SmmDispatcher.h253
-rw-r--r--Core/EM/SMM/SmmDispatcher.mak127
-rw-r--r--Core/EM/SMM/SmmDispatcher.sdl35
-rw-r--r--Core/EM/SMM/SmmDispatcherAsm.asm196
-rw-r--r--Core/EM/SMM/SmmDriverDispatcher.c1694
-rw-r--r--Core/EM/SMM/SmmDxeCommunicate.dxs69
-rw-r--r--Core/EM/SMM/SmmEntry.asm1041
-rw-r--r--Core/EM/SMM/SmmHdr.equ286
-rw-r--r--Core/EM/SMM/SmmInit.c1319
-rw-r--r--Core/EM/SMM/SmmMemoryManager.c962
-rw-r--r--Core/EM/SMM/SmmPiSmst.c1827
-rw-r--r--Core/EM/SMM/SmmPrivateShared.h392
-rw-r--r--Core/EM/SMM/Smst.c917
31 files changed, 12906 insertions, 0 deletions
diff --git a/Core/EM/SMM/SMM.cif b/Core/EM/SMM/SMM.cif
new file mode 100644
index 0000000..2a6a922
--- /dev/null
+++ b/Core/EM/SMM/SMM.cif
@@ -0,0 +1,19 @@
+<component>
+ name = "SMM"
+ category = eModule
+ LocalRoot = "Core\EM\SMM"
+ RefName = "SMM"
+[files]
+"SMM.sdl"
+"SmmPrivateShared.h"
+"SmmHdr.equ"
+"Smm.chm"
+[parts]
+"SmmDispatcher"
+"SmmBase"
+"SmmCommunicate"
+"SmmProtocols"
+"SmmPiIncludes"
+"SmmPiProtocols"
+"PowerButton"
+<endComponent>
diff --git a/Core/EM/SMM/SMM.sdl b/Core/EM/SMM/SMM.sdl
new file mode 100644
index 0000000..2923eaa
--- /dev/null
+++ b/Core/EM/SMM/SMM.sdl
@@ -0,0 +1,101 @@
+TOKEN
+ Name = "SMM_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable SMM support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "SMM_MAJOR_VER"
+ Value = "00"
+ Help = "SMM Major Version Number. Do not change"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "SMM_MINOR_VER"
+ Value = "0x46"
+ Help = "SMM Minor Version Number. Do not change"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "SMM_PAGING_MAX_ADDRESS_LINES"
+ Value = "32"
+ Help = "For x64, maximum number of address lines to page.\Each additional line doubles the page table size."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SMM_CACHE_SUPPORT"
+ Value = "1"
+ Help = "Enable/disable SMM Cache Support"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SMM_THUNK_NO_AB_SEG"
+ Value = "1"
+ Help = "Enable/disable using A & B segment for SMM Thunk.\Some CPUs don't provide support for SMM THUNK in A&B segment."
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SMM_THUNK_IN_CSM"
+ Value = "0"
+ Help = "Enable/disable SMM Thunk in CSM"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+ Token = "CSM_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "SMM_TIME_OUT_US"
+ Value = "1000"
+ Help = "uS Timeout waiting for BSP and APs to sync."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BSP_SMM_STACK_SIZE"
+ Value = "16384"
+ Help = "Must be 4k byte alligned."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "AP_SMM_STACK_SIZE"
+ Value = "16384"
+ Help = "Must be 4k byte alligned."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INTEL_MP_SW_SMI_PATCH"
+ Value = "0"
+ Help = "INTEL drivers always read Save State Copy 0.\When this is enabled, an AP generated sw smi will\appear as CPU 0.\Further, Save State Copies of other CPUs may be invalid."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
diff --git a/Core/EM/SMM/Smm.chm b/Core/EM/SMM/Smm.chm
new file mode 100644
index 0000000..dd76d80
--- /dev/null
+++ b/Core/EM/SMM/Smm.chm
Binary files differ
diff --git a/Core/EM/SMM/SmmBase.c b/Core/EM/SMM/SmmBase.c
new file mode 100644
index 0000000..219e405
--- /dev/null
+++ b/Core/EM/SMM/SmmBase.c
@@ -0,0 +1,911 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase.c 73 2/13/12 4:41p Markw $
+//
+// $Revision: 73 $
+//
+// $Date: 2/13/12 4:41p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase.c $
+//
+// 73 2/13/12 4:41p Markw
+// [TAG] EIP83005
+// [Category] Improvement
+// [Description] Some framework based SMM libraries expect a DXE image
+// handle on input. However, PI 1.1 SMM drivers expect a SMM handle on
+// input.
+// Update code to provide proper EFI_HANDLE when calling SMM functions.
+// [Files] SmmBase.c, SmmDriverDispatcher.c
+//
+// 72 8/25/11 10:29a Markw
+// [TAG] EIP64115
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] PI 1.1 - unable to install protocol on image handle.
+// [RootCause] Image handle is created by AMI code, but protocol handles
+// are created by Intel code.
+// [Solution] Create a new dummy handle from Intel's code and use that a
+// the image handle in the entry point.
+// [Files] SmmBase.c
+//
+// 71 2/07/11 3:35p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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
+//
+// 70 12/28/09 11:07a Markw
+// EIP #32378 - Use SDL token to determine how much memory to page to be
+// able to page above 4GB.
+//
+// 69 11/23/09 11:04a Markw
+// Add back SMM Communicate function. Smm runtime module needed this.
+//
+// 68 11/05/09 4:31p Markw
+// SMM Base functions pre-initalize Status to EFI_DEVICE_ERROR in case sw
+// smi doesn't happen.
+//
+// 67 10/13/09 3:42p Markw
+// EIP #27823 - Fix allocating SMM driver below 1MB if out of SMM memory.
+//
+// 66 8/11/09 11:47a Markw
+// Removed Legacy registration. This is removed from latest PI and not
+// used by projects.
+//
+// 65 8/05/09 2:59p Markw
+// When functions aren't available in BDS for SMM security, return proper
+// error of EFI_UNSUPPORTED.
+//
+// 64 7/17/09 4:19p Markw
+// Added back changes 60 and 61.
+//
+// 63 7/16/09 8:12p Markw
+// EIP #24284 - Correct order SmmCpuInfo structure. It's was ordered
+// incorrectly the same as CpuInfo. Thus, the wrong APIC ID could be used
+// when starting unstarted APs if the BSP was changed.
+//
+// 62 7/08/09 8:03p Markw
+// Update headers.
+//
+// 61 6/25/09 4:15p Markw
+// Move setting gDispatcherPrivate->SmrrEnable outside condition.
+//
+// 60 6/10/09 3:17p Markw
+// Remove extra freepool.
+//
+// 59 1/26/09 5:29p Markw
+// EIP 14800: Aptio 4.x SMI Code vulnerablity. Disable call back inside
+// SMM before BDS can launch option roms.
+//
+// 58 1/22/09 1:07p Markw
+// EIP #18671 (OPEN) Clear SW SMI status and set EOS inside SMM. Move
+// Clear from Base function.
+//
+// 57 12/24/08 10:55a Markw
+// EIP #18423: Adjust EBDA location as more EBDA data is allocated.
+//
+// 56 12/23/08 2:19p Markw
+// EIP #17900 Set up TSS. Borland C in DOS hangs otherwise.
+//
+// 55 11/21/08 5:02p Markw
+// Use 32-bit CPU Count.
+//
+// 54 10/06/08 6:27p Markw
+// Add generic Smm Memory libary hook.
+//
+// 53 9/26/08 4:51p Markw
+// InSmm is now a runtime function.
+//
+// 52 9/15/08 4:00p Markw
+// Initialize HandlerListHead and FloatingPointSave in Dispatcher Private
+// structure.
+//
+// 51 9/09/08 3:06p Markw
+// Align Dispatcher to 4k.
+//
+// 50 9/07/08 12:47a Markw
+// Separate SMM Private structure into inside SMM and outside SMM
+// structure.
+//
+// 49 8/27/08 9:07p Markw
+// Nehalem SMRR is not WB. Fix VIA not supporting cpuid 0x80000008.
+//
+// 47 6/10/08 6:46p Markw
+// Disable SMM Thunk if no A & B seg, and no CSM.
+//
+// 46 6/10/08 1:30p Markw
+// Update gdt for Smm Thunk for APs.
+//
+// 45 6/09/08 5:42p Markw
+// Provide support for any CPU to be BSP by providing APIC for each CPU
+// and allowing CPU 0 to have a structure for controlling as an Ap.
+//
+// 44 5/23/08 5:28p Markw
+// Undo change from previous revision to lock smm before os with AMI
+// debugger.
+//
+// 43 5/23/08 12:25p Markw
+// Disallow registering now disallows all callbacks.
+//
+// 42 4/04/08 6:23p Markw
+// Change SMM base here instead of CPU module.
+//
+// 41 3/18/08 4:59p Markw
+// Change 64-bit pages to have the first 2MB as 4k pages. This is so
+// different MTRR types will not overlap a page.
+//
+// 40 3/11/08 12:46p Markw
+//
+// 39 3/04/08 9:01a Markw
+// Updated EBDA allocation for SMM THUNK to use the changed protocol from
+// 4.5.3_CSM.6.43_56.
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmBase.c
+//
+// Description: Provide functions to register drivers with SMM,
+// determine if driver is in SMM Mode, register call backs,
+// provide callback buffer, return SMST table pointer,
+// and allocate memory.
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+//This include should be first.
+#include "SmmPrivateShared.h"
+
+#include <Protocol\LoadPe32Image.h>
+#include <Protocol\LoadedImage.h>
+#include <token.h>
+#include <Ffs.h>
+#include <AmiDxeLib.h>
+
+#if SMM_USE_FRAMEWORK
+#include <Smm.h>
+#include <Protocol\SmmBase.h>
+#endif
+
+#if SMM_USE_PI
+#include <SmmPi.h>
+#include <Protocol\SmmReadyToLock.h>
+#endif
+
+UINT8 gDisallowCallbacks = FALSE;
+BOOLEAN gRegisterForPi = FALSE;
+
+VOID SmmRegisterHandler();
+
+#if SMM_USE_FRAMEWORK
+VOID SmmUnregisterHandler();
+VOID SmmCommunicate();
+VOID SmmAllocatePool();
+VOID SmmFreePool();
+
+extern EFI_SMM_SYSTEM_TABLE *gSmstTable;
+#endif
+
+#if SMM_USE_PI
+extern EFI_SMM_SYSTEM_TABLE2 *gSmstTable2;
+#endif
+
+extern EFI_HANDLE gThisImageHandle;
+extern SMM_BASE_PRIVATE_STRUCT *gBasePrivate;
+extern EFI_PE32_IMAGE_PROTOCOL *gPe32Image;
+extern SMM_DISPATCHER_PRIVATE_STRUCT *gDispatcherPrivate;
+
+EFI_GUID gEfiLoadedImageProtocolGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+
+
+#if SMM_USE_PI
+//EFI_GUID gEfiSmmReadyToLockProtocolGuid = EFI_SMM_READY_TO_LOCK_PROTOCOL_GUID;
+EFI_GUID gSmmImageHandleDummyGuid = {0x33aa4ba3, 0x5439, 0x4658, 0x89, 0x51, 0xe2, 0xe7, 0xea, 0xf8, 0x1c, 0x49};
+#endif
+
+VOID CallFuncInSmm(IN VOID func());
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SetDisallowRegistering
+//
+// Description: Don't allow registering handlers from SMM.
+//
+// Input: VOID
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SetDisallowRegistering()
+{
+#if SMM_USE_PI
+ EFI_HANDLE Handle = NULL;
+#endif
+
+ //Dispatcher has a private variable, is set after this.
+ //Thus, once DisallowCallbacks is set, it can not be unset.
+ gBasePrivate->DisallowCallbacks = TRUE;
+ gDisallowCallbacks = TRUE;
+
+#if SMM_USE_PI
+ gSmstTable2->SmmInstallProtocolInterface(
+ &Handle,
+ &gEfiSmmReadyToLockProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmRegister
+//
+// Description: Register a driver with the SMM Handler.
+// * Loads SMM PE32 Driver into SMM memory and give control to the entry point.
+// * Or, loads SMM 16-bit driver into SMM memory. It is given control during SMM mode.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+// IN VOID *SourceBuffer OPTIONAL
+// IN UINTN SourceSize
+// OUT EFI_HANDLE *ImageHandle
+// IN BOOLEAN LegacyIA32Binary OPTIONAL
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Driver was registered.
+// * EFI_OUT_OF_RESOURCES - No additional resources to load handler.
+// * EFI_INVALID_PARAMETER - Invalid inputs.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmRegister(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle,
+ IN BOOLEAN LegacyIA32Binary OPTIONAL
+ )
+{
+
+ if (gDisallowCallbacks) return EFI_UNSUPPORTED;
+ if (LegacyIA32Binary) return EFI_UNSUPPORTED;
+
+ gBasePrivate->CallbackParameters.RegisterHandler.FilePath = FilePath;
+ gBasePrivate->CallbackParameters.RegisterHandler.SourceBuffer = SourceBuffer;
+ gBasePrivate->CallbackParameters.RegisterHandler.SourceSize = SourceSize;
+ gBasePrivate->CallbackParameters.RegisterHandler.ImageHandle = ImageHandle;
+ gBasePrivate->CallbackParameters.RegisterHandler.LegacyIA32Binary = FALSE;
+ gBasePrivate->CallbackStatus = EFI_DEVICE_ERROR; //Pre-init - SW SMI didn't happen.
+
+ CallFuncInSmm(SmmRegisterHandler);
+
+ return gBasePrivate->CallbackStatus;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SmmRegisterHandler
+//
+// Description: Does the actual work for EfiSmmRegisterHandler.
+//
+// Input: VOID
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+//Can Legacy and PE32 handle overlap?
+VOID SmmRegisterHandler()
+{
+ EFI_PHYSICAL_ADDRESS EntryPoint, DstBuffer;
+ UINTN NumberOfPages,RealNumberOfPages;
+ EFI_STATUS Status;
+ EFI_HANDLE NewImageHandle;
+ EFI_HANDLE SmmImageHandle;
+
+ //Pre-allocate plenty of pages for the SMM driver, so LoadPeImage will only decompress the driver once.
+ //If memory is not enough, the number of pages will returned and enough memory allocated,
+ // then LoadPeImage will decompress the driver again.
+ //Any extra pages will be freed and not wasted.
+#define DEFAULT_SMM_DRIVER_PAGES 16
+ NumberOfPages = DEFAULT_SMM_DRIVER_PAGES;
+#if SMM_USE_FRAMEWORK
+ Status = gSmstTable->SmmAllocatePages(
+#else
+ Status = gSmstTable2->SmmAllocatePages(
+#endif
+ AllocateAnyPages, 0, NumberOfPages, &DstBuffer
+ );
+ if (EFI_ERROR(Status)) {
+ //If allocation failed, so try the minimum of 1 page.
+ NumberOfPages = 1;
+#if SMM_USE_FRAMEWORK
+ Status = gSmstTable->SmmAllocatePages(
+#else
+ Status = gSmstTable2->SmmAllocatePages(
+#endif
+ AllocateAnyPages, 0, NumberOfPages, &DstBuffer
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ gBasePrivate->CallbackStatus = Status;
+ return;
+ }
+ }
+
+ //DstBuffer can't be 0, or LoadPeImage will allocate non-SMM memory.
+ RealNumberOfPages = NumberOfPages;
+ Status=gPe32Image->LoadPeImage(
+ gPe32Image, gThisImageHandle,
+ gBasePrivate->CallbackParameters.RegisterHandler.FilePath, //Either DevicePath or
+ gBasePrivate->CallbackParameters.RegisterHandler.SourceBuffer, //Buffer. This will be zero if DevicePath.
+ gBasePrivate->CallbackParameters.RegisterHandler.SourceSize,
+ DstBuffer, &RealNumberOfPages,
+ &NewImageHandle,
+ &EntryPoint, EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
+ );
+ //If Image has been loaded, let's free extra memory
+ if (!EFI_ERROR(Status) && RealNumberOfPages<NumberOfPages) {
+#if SMM_USE_FRAMEWORK
+ gSmstTable->SmmFreePages(
+#else
+ gSmstTable2->SmmFreePages(
+#endif
+ DstBuffer+EFI_PAGES_TO_SIZE(RealNumberOfPages),
+ NumberOfPages-RealNumberOfPages
+ );
+ //If it's not enough memory, let's allocate new chunk and try again.
+ } else if (Status==EFI_BUFFER_TOO_SMALL) {
+ //Free Old Buffer
+#if SMM_USE_FRAMEWORK
+ gSmstTable->SmmFreePages(
+#else
+ gSmstTable2->SmmFreePages(
+#endif
+ DstBuffer, NumberOfPages);
+ //Allocate New Buffer
+#if SMM_USE_FRAMEWORK
+ Status = gSmstTable->SmmAllocatePages(
+#else
+ Status = gSmstTable2->SmmAllocatePages(
+#endif
+ AllocateAnyPages, 0, RealNumberOfPages, &DstBuffer
+ );
+ if (!EFI_ERROR(Status))
+ Status=gPe32Image->LoadPeImage(
+ gPe32Image, gThisImageHandle,
+ gBasePrivate->CallbackParameters.RegisterHandler.FilePath, //Either DevicePath or
+ gBasePrivate->CallbackParameters.RegisterHandler.SourceBuffer, //Buffer. This will be zero if DevicePath.
+ gBasePrivate->CallbackParameters.RegisterHandler.SourceSize,
+ DstBuffer, &RealNumberOfPages,
+ &NewImageHandle,
+ &EntryPoint, EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
+ );
+ }
+ if (!EFI_ERROR(Status)) {
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ //EFI_IMAGE_ENTRY_POINT EntryPoint;
+
+ Status = pBS->HandleProtocol(NewImageHandle, &gEfiLoadedImageProtocolGuid, &LoadedImage);
+ ASSERT_EFI_ERROR(Status);
+
+ TRACE((TRACE_ALWAYS,"SMM."));
+#ifdef EFI_DEBUG
+{
+//Debug message: name/entry point of the module being started
+BOOLEAN GetImageName(EFI_HANDLE, CHAR8 *);
+VOID Trace(UINTN Level, CHAR8 *sFormat,...);
+CHAR8 sName[0x100];
+
+ GetImageName(NewImageHandle, sName);
+ TRACE((TRACE_ALWAYS, "%s.Entry(%X)\n", sName, EntryPoint));
+}
+#endif
+
+ SmmImageHandle = NewImageHandle;
+#if SMM_USE_PI
+ if (gRegisterForPi) {
+ //Create an Image Handle for SMM driver, so the handle can be used to install new handles on.
+ SmmImageHandle = NULL;
+ Status = gSmstTable2->SmmInstallProtocolInterface(
+ &SmmImageHandle,
+ &gSmmImageHandleDummyGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL //Dummy
+ );
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+
+ gBasePrivate->CallbackParameters.RegisterHandler.ImageHandle = SmmImageHandle;
+
+ Status = ((EFI_IMAGE_ENTRY_POINT)EntryPoint)(SmmImageHandle, pST);
+ if (EFI_ERROR(Status))
+#if SMM_USE_FRAMEWORK
+ gSmstTable->SmmFreePages(
+#else
+ gSmstTable2->SmmFreePages(
+#endif
+ DstBuffer, RealNumberOfPages
+ );
+ }
+ gBasePrivate->CallbackStatus = Status;
+}
+
+#if SMM_USE_FRAMEWORK
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmUnregister
+//
+// Description: Removes handler from being called in SMM.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN EFI_HANDLE ImageHandle
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Driver was unregistered.
+// * EFI_INVALID_PARAMETER - Image Handle doesn't exist.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmUnregister(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ if (gDisallowCallbacks) return EFI_UNSUPPORTED;
+
+ gBasePrivate->CallbackParameters.UnregisterHandler.ImageHandle = ImageHandle;
+ gBasePrivate->CallbackStatus = EFI_DEVICE_ERROR; //Pre-init - SW SMI didn't happen.
+
+ CallFuncInSmm(SmmUnregisterHandler);
+
+ return gBasePrivate->CallbackStatus;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SmmUnregisterHandler
+//
+// Description: Does the actual work for EfiSmmUnregisterHandler.
+//
+// Input: VOID
+//
+// Output:
+// VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmUnregisterHandler()
+{
+ gBasePrivate->CallbackStatus = EFI_UNSUPPORTED;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmCommunicate
+//
+// Description: Buffer location for EFI Call Back function.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN EFI_HANDLE ImageHandle
+// IN OUT VOID *CommunicationBuffer
+// IN OUT UINTN *SourceSize
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Buffer is set.
+// * EFI_INVALID_PARAMETER - Buffer is NULL
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmCommunicate(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+ if (gDisallowCallbacks) return EFI_UNSUPPORTED;
+
+ if (!CommunicationBuffer) return EFI_INVALID_PARAMETER;
+
+ gBasePrivate->CallbackParameters.Communicate.ImageHandle = ImageHandle;
+ gBasePrivate->CallbackParameters.Communicate.CommunicationBuffer = CommunicationBuffer;
+ gBasePrivate->CallbackParameters.Communicate.SourceSize = SourceSize;
+ gBasePrivate->CallbackStatus = EFI_DEVICE_ERROR; //Pre-init - SW SMI didn't happen.
+
+ CallFuncInSmm(SmmCommunicate);
+
+ return gBasePrivate->CallbackStatus;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SmmCommunicate
+//
+// Description: Does the actual work for EfiSmmCommunicate.
+//
+// Input: VOID
+//
+// Output:
+// VOID
+//
+// Notes:
+// A runtime driver will have to call this function again for a virtual address.
+// Currently, virtual address are not automatically fixed up.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmCommunicate()
+{
+// A runtime driver will have to call this function again for a virtual address.
+// Currently, virtual address are not automaically fixed up. Also, no runtime drivers are
+// using this.
+
+ HANDLER_LIST *Link;
+ for (Link = gDispatcherPrivate->HandlerListHead;Link; Link = Link->Link) {
+ if (Link->SmmImageHandle == gBasePrivate->CallbackParameters.Communicate.ImageHandle) {
+ Link->CommunicationBuffer = gBasePrivate->CallbackParameters.Communicate.CommunicationBuffer;
+ Link->SourceSize = gBasePrivate->CallbackParameters.Communicate.SourceSize;
+ gBasePrivate->CallbackStatus = EFI_SUCCESS;
+ return;
+ }
+ }
+ gBasePrivate->CallbackStatus = EFI_NOT_FOUND;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmCallBackService
+//
+// Description: Function for the SMM to call back.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN EFI_HANDLE SmmImageHandle
+// IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress
+// IN BOOLEAN MakeLast OPTIONAL
+// IN BOOLEAN FloatingPointSave OPTIONAL
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Call back function set for Handle.
+// * EFI_OUT_OF_RESOURCES - Not enough memory to add callback.
+// * EFI_UNSUPPORTED - Caller not in SMM.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmCallBackService(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN EFI_HANDLE SmmImageHandle,
+ IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress,
+ IN BOOLEAN MakeLast OPTIONAL,
+ IN BOOLEAN FloatingPointSave OPTIONAL
+ )
+{
+ HANDLER_LIST *Handler,*Link;
+
+ if (!*gBasePrivate->InSmm) return EFI_UNSUPPORTED;
+
+ if (gSmstTable->SmmAllocatePool(0,sizeof(HANDLER_LIST),&Handler) != EFI_SUCCESS)
+ return EFI_OUT_OF_RESOURCES;
+
+ Handler->EntryPoint = CallbackAddress;
+ Handler->SmmImageHandle = SmmImageHandle;
+ Handler->CommunicationBuffer = 0;
+ Handler->SourceSize = 0;
+ Handler->IsRoot = TRUE;
+ Handler->IsPi = FALSE;
+ Handler->Link = 0;
+
+ if (FloatingPointSave) gDispatcherPrivate->FloatingPointSave = TRUE;
+
+ //If very first add.
+ if (!gDispatcherPrivate->HandlerListHead) {
+ gDispatcherPrivate->HandlerListHead = Handler;
+ return EFI_SUCCESS;
+ }
+
+ //If not MakeLast, add to beginning of list.
+ if (!MakeLast) {
+ Handler->Link = gDispatcherPrivate->HandlerListHead;
+ gDispatcherPrivate->HandlerListHead = Handler;
+ return EFI_SUCCESS;
+ }
+
+ //Add to end of list.
+ for (Link = gDispatcherPrivate->HandlerListHead; Link->Link; Link = Link->Link); //Find end of list
+ Link->Link = Handler;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmAllocatePool
+//
+// Description: Allocate buffer from SMM Memory.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN EFI_MEMORY_TYPE PoolType
+// IN UINTN Size
+// OUT VOID **Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Allocation successful.
+// * EFI_OUT_OF_RESOURCES - Not enough space.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmAllocatePool(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ if (gDisallowCallbacks) return EFI_UNSUPPORTED;
+
+ gBasePrivate->CallbackParameters.AllocatePool.Size = Size;
+ gBasePrivate->CallbackParameters.AllocatePool.Buffer = Buffer;
+ gBasePrivate->CallbackStatus = EFI_DEVICE_ERROR; //Pre-init - SW SMI didn't happen.
+
+ CallFuncInSmm(SmmAllocatePool);
+
+ return gBasePrivate->CallbackStatus;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SmmAllocatePool
+//
+// Description: Does the actual work for EfiSmmAllocatePool.
+//
+// Input: VOID
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmAllocatePool()
+{
+ gBasePrivate->CallbackStatus = gSmstTable->SmmAllocatePool(
+ 0,
+ gBasePrivate->CallbackParameters.AllocatePool.Size,
+ gBasePrivate->CallbackParameters.AllocatePool.Buffer
+ );
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmFreePool
+//
+// Description: Free pool of memory.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Buffer freed
+// * EFI_INVALID_PARAMETER - Buffer invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmFreePool(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN VOID *Buffer
+ )
+{
+ if (gDisallowCallbacks) return EFI_UNSUPPORTED;
+
+ gBasePrivate->CallbackParameters.FreePool.Buffer = Buffer;
+ gBasePrivate->CallbackStatus = EFI_DEVICE_ERROR; //Pre-init - SW SMI didn't happen.
+
+ CallFuncInSmm(SmmFreePool);
+
+ return gBasePrivate->CallbackStatus;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SmmFreePool
+//
+// Description: Does the actual work for EfiSmmFreePool.
+//
+// Input: VOID
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmFreePool()
+{
+ gBasePrivate->CallbackStatus = gSmstTable->SmmFreePool(
+ gBasePrivate->CallbackParameters.FreePool.Buffer);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmGetSmstLocation
+//
+// Description: Returns a pointer to the Smst.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN OUT EFI_SMM_SYSTEM_TABLE **Smst
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - SMST address saved in *Smst.
+// * EFI_INVALID_PARAMETER - Smst = NULL.
+// * EFI_UNSUPPORTED - Not in SMM.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmGetSmstLocation(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN OUT EFI_SMM_SYSTEM_TABLE **Smst
+ )
+{
+ if (!*gBasePrivate->InSmm) return EFI_UNSUPPORTED;
+ if (Smst == NULL) return EFI_INVALID_PARAMETER;
+
+ *Smst = gSmstTable;
+ return EFI_SUCCESS;
+}
+
+EFI_SMM_BASE_PROTOCOL gEfiSmmBase = {
+ EfiSmmRegister,
+ EfiSmmUnregister,
+ EfiSmmCommunicate,
+ EfiSmmCallBackService,
+ NULL, //EfiSmmInSmm is runtime function. This will be updated.
+ EfiSmmAllocatePool,
+ EfiSmmFreePool,
+ EfiSmmGetSmstLocation,
+};
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmRegisterUnsupported
+//
+// Description:
+// The SMM Base Protocol function Register return unsupported after
+// BIOS is done executing.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+// IN VOID *SourceBuffer OPTIONAL,
+// IN UINTN SourceSize
+// OUT EFI_HANDLE *ImageHandle
+// IN BOOLEAN LegacyIA32Binary OPTIONAL
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmRegisterUnsupported(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle,
+ IN BOOLEAN LegacyIA32Binary OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmUnregisterUnsupported
+//
+// Description:
+// The SMM Base Protocol function UnRegister return unsupported after
+// BIOS is done executing.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN EFI_HANDLE ImageHandle
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EfiSmmUnregisterUnsupported(
+ IN EFI_SMM_BASE_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+#endif
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmBase.cif b/Core/EM/SMM/SmmBase.cif
new file mode 100644
index 0000000..79d6ba1
--- /dev/null
+++ b/Core/EM/SMM/SmmBase.cif
@@ -0,0 +1,15 @@
+<component>
+ name = "SmmBase"
+ category = ModulePart
+ LocalRoot = "Core\EM\SMM"
+ RefName = "SmmBase"
+[files]
+"SmmBase.sdl"
+"SmmBase.mak"
+"SmmInit.c"
+"SmmBase.c"
+"SmmBase2.c"
+"SmmDriverDispatcher.c"
+"SmmBase.dxs"
+"SmmBaseAsm.asm"
+<endComponent>
diff --git a/Core/EM/SMM/SmmBase.dxs b/Core/EM/SMM/SmmBase.dxs
new file mode 100644
index 0000000..b6bc561
--- /dev/null
+++ b/Core/EM/SMM/SmmBase.dxs
@@ -0,0 +1,107 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase.dxs 8 4/01/11 10:36a Markw $
+//
+// $Revision: 8 $
+//
+// $Date: 4/01/11 10:36a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase.dxs $
+//
+// 8 4/01/11 10:36a Markw
+// [TAG] EIP57440
+// [Category] New Feature
+// [Description] Update for PI 1.1
+// [Files] SmmBase.dxs
+//
+// 7 7/08/09 8:03p Markw
+// Update headers.
+//
+// 6 8/28/08 2:04p Markw
+//
+// 5 10/29/07 3:38p Markw
+//
+// 4 10/29/07 11:21a Markw
+// Smm Thunk:
+// * Code and data different segments.
+// * Code position independent.
+// * Switch for CSM for code and EBDA for data.
+//
+// 3 3/14/06 10:02a Felixp
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmBase.dxs
+//
+// Description: Dependency file for the SMM base driver
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <Token.h>
+#if PI_SPECIFICATION_VERSION >= 0x0001000a
+#include <Protocol\SmmAccess2.h>
+#include <Protocol\smmcontrol2.h>
+#else
+#include <Protocol\SmmAccess.h>
+#include <Protocol\smmcontrol.h>
+#endif
+#include <Protocol\FirmwareVolume.h >
+#include <Protocol\Variable.h>
+
+#if SMM_THUNK_IN_CSM == 1
+#include <Protocol\LegacyBiosExt.h>
+#include <Protocol\LegacyBios.h>
+#endif
+
+DEPENDENCY_START
+#if PI_SPECIFICATION_VERSION >= 0x0001000a
+ EFI_SMM_ACCESS2_PROTOCOL_GUID AND
+ EFI_SMM_CONTROL2_PROTOCOL_GUID AND
+#else
+ EFI_SMM_ACCESS_PROTOCOL_GUID AND
+ EFI_SMM_CONTROL_PROTOCOL_GUID AND
+#endif
+ EFI_FIRMWARE_VOLUME_PROTOCOL_GUID AND
+ EFI_VARIABLE_ARCH_PROTOCOL_GUID AND
+#if SMM_THUNK_IN_CSM == 0
+ EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID
+#else
+ EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID AND
+ EFI_LEGACY_BIOS_EXT_PROTOCOL_GUID AND
+ EFI_LEGACY_BIOS_PROTOCOL_GUID
+#endif
+DEPENDENCY_END
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmBase.mak b/Core/EM/SMM/SmmBase.mak
new file mode 100644
index 0000000..1d57955
--- /dev/null
+++ b/Core/EM/SMM/SmmBase.mak
@@ -0,0 +1,84 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase.mak 4 2/07/11 3:35p Markw $
+#
+# $Revision: 4 $
+#
+# $Date: 2/07/11 3:35p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase.mak $
+#
+# 4 2/07/11 3:35p Markw
+# [TAG] EIP53481
+# [Category] New Feature
+# [Description] Add PIWG 1.1 SMM support
+# [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
+#
+# 3 7/08/09 8:26p Markw
+# Updated headers.
+#
+# 2 12/02/05 11:48a Felixp
+#
+# 1 1/28/05 4:31p Sivagarn
+# SMM Base Component - Initial check in
+#
+#
+#**********************************************************************
+
+#<AMI_FHDR_START>
+#---------------------------------------------------------------------------
+#
+# Name: SmmBase.MAK
+#
+# Description: Make file for the SMM base code
+#
+#---------------------------------------------------------------------------
+#<AMI_FHDR_END>
+
+all : SmmBase
+
+SmmBase : $(BUILD_DIR)\SmmBase.mak SmmBaseBin
+
+$(BUILD_DIR)\SmmBase.mak : $(SMM_BASE_DIR)\SmmBase.cif $(SMM_BASE_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SMM_BASE_DIR)\SmmBase.cif $(CIF2MAK_DEFAULTS)
+
+SmmBaseBin : $(AMIDXELIB) $(AMICSPLib)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SmmBase.mak all\
+ GUID=D0632C90-AFD7-4492-B186-257C63143C61\
+ ENTRY_POINT=SmmInitEntry\
+ TYPE=BS_DRIVER \
+ COMPRESS=1
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/Core/EM/SMM/SmmBase.sdl b/Core/EM/SMM/SmmBase.sdl
new file mode 100644
index 0000000..449d117
--- /dev/null
+++ b/Core/EM/SMM/SmmBase.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = "SmmBase_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable SmmBase support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "SMM_BASE_DIR"
+End
+
+MODULE
+ Help = "Includes SmmBase.mak to Project"
+ File = "SmmBase.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SmmBase.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/SMM/SmmBase2.c b/Core/EM/SMM/SmmBase2.c
new file mode 100644
index 0000000..679b880
--- /dev/null
+++ b/Core/EM/SMM/SmmBase2.c
@@ -0,0 +1,102 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-20011 American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase2.c 1 2/07/11 3:35p Markw $
+//
+// $Revision: 1 $
+//
+// $Date: 2/07/11 3:35p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBase2.c $
+//
+// 1 2/07/11 3:35p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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: SmmBase2.c
+//
+// Description: SmmBase2 Protocol
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "SmmPrivateShared.h"
+#if SMM_USE_PI
+#include <SmmPi.h>
+#include <Protocol\SmmBase2.h>
+#include <AmiDxeLib.h>
+
+EFI_SMM_SYSTEM_TABLE2 *gSmstTable2;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EfiSmmGetSmstLocation2
+//
+// Description: Retruns a pointer to the Smst.
+//
+// Input:
+// IN EFI_SMM_BASE_PROTOCOL *This
+// IN OUT EFI_SMM_SYSTEM_TABLE **Smst
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - SMST address saved in *Smst.
+// * EFI_INVALID_PARAMETER - Smst = NULL.
+// * EFI_UNSUPPORTED - Not in SMM.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EfiSmmGetSmstLocation2(
+ IN CONST EFI_SMM_BASE2_PROTOCOL *This,
+ IN OUT EFI_SMM_SYSTEM_TABLE2 **Smst
+ )
+{
+ *Smst = gSmstTable2;
+ return EFI_SUCCESS;
+}
+
+EFI_SMM_BASE2_PROTOCOL gEfiSmmBase2 = {
+ NULL, //This will be updated dynamically.
+ EfiSmmGetSmstLocation2
+};
+#endif
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmBaseAsm.asm b/Core/EM/SMM/SmmBaseAsm.asm
new file mode 100644
index 0000000..cdaa37b
--- /dev/null
+++ b/Core/EM/SMM/SmmBaseAsm.asm
@@ -0,0 +1,139 @@
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2008, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;*************************************************************************
+;*************************************************************************
+
+;**********************************************************************
+; $Header: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBaseAsm.asm 2 7/14/09 12:16p Markw $
+;
+; $Revision: 2 $
+;
+; $Date: 7/14/09 12:16p $
+;**********************************************************************
+; Revision History
+; ----------------
+; $Log: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmBaseAsm.asm $
+;
+; 2 7/14/09 12:16p Markw
+; Update headers.
+;
+; 1 9/26/08 4:48p Markw
+;
+; 1 6/09/08 5:56p Markw
+; Assembly functions for Dispatcher.
+;
+;**********************************************************************
+
+;<AMI_FHDR_START>
+;----------------------------------------------------------------------------
+;
+; Name: SmmDispatcher.asm
+;
+; Description: File that contains assembly for Smm Dispatcher.
+;
+;----------------------------------------------------------------------------
+;<AMI_FHDR_END>
+
+IFDEF EFIx64
+.code
+include token.equ
+
+public EfiSmmInSmm
+
+public InSmmFuncOffset
+public InSmmFuncLength
+
+InSmmFuncOffset dd InSmmFixup - InSmmStart
+InSmmFuncLength dd InSmmEnd - InSmmStart
+
+;<AMI_PHDR_START>
+;----------------------------------------------------------------------------
+;
+; Procedure: InSmm
+;
+; Description: Updates if *InSmm if in SMM.
+;
+; Input:
+; IN EFI_SMM_BASE_PROTOCOL *This,
+; OUT BOOLEAN *InSmm
+;
+; Output: EFI_STATUS
+;
+; Modified: Nothing
+;
+;----------------------------------------------------------------------------
+;<AMI_PHDR_END>
+
+EfiSmmInSmm proc
+InSmmStart EQU $
+ or rdx, rdx
+ jnz @f
+ mov rax, 8000000000000002h
+ ret
+@@:
+ ;mov al, 0
+ db 0b0h
+InSmmFixup EQU $
+ db 0
+ mov [rdx], al
+ mov rax, 0
+ ret
+InSmmEnd EQU $
+EfiSmmInSmm endp
+
+ELSE ;32-bits
+.586p
+.model small
+.code
+
+public _InSmmFuncOffset
+public _InSmmFuncLength
+
+_InSmmFuncOffset dd InSmmFixup - InSmmStart
+_InSmmFuncLength dd InSmmEnd - InSmmStart
+
+_EfiSmmInSmm proc public
+InSmmStart EQU $
+ or dword ptr [esp + 8], 0
+ jnz @f
+ mov eax, 80000002h
+ ret
+@@:
+ ;mov al, 0
+ db 0b0h
+InSmmFixup EQU $
+ db 0
+ push ebx
+ mov ebx, [esp + 12]
+ mov [ebx], al
+ pop ebx
+ xor eax, eax
+ ret
+InSmmEnd EQU $
+_EfiSmmInSmm endp
+ENDIF
+
+end
+
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2008, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;*************************************************************************
+;*************************************************************************
diff --git a/Core/EM/SMM/SmmCommunicate.c b/Core/EM/SMM/SmmCommunicate.c
new file mode 100644
index 0000000..929118e
--- /dev/null
+++ b/Core/EM/SMM/SmmCommunicate.c
@@ -0,0 +1,462 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011 American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmCommunicate.c 5 3/22/12 11:38a Markw $
+//
+// $Revision: 5 $
+//
+// $Date: 3/22/12 11:38a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmCommunicate.c $
+//
+// 5 3/22/12 11:38a Markw
+// [TAG] EIP84198
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Using SMM Communication can cause OS to hang
+// [RootCause] SMM Communication Protocol’s Communicate API does not
+// function in UEFI OS after Exit boot services event because
+// ConvertPointer() did not convert SMM_COMMUNICATE_DATA *gCommunicateData
+// pointer from a Physical Memory Map Pointer to a Virtual Memory Map
+// Pointer. gCommunicateData is allocated in EfiACPIMemoryNVS.
+// [Solution] Allocate memory gCommunicateData as Runtime Services Data.
+// [Files] SmmCommunicate.c
+//
+// 4 10/03/11 3:56p Markw
+// Use tokens for SW SMI. Comment publishing ACPI table until ready.
+// Files: SmmCommunicate.sdl, SmmCommunicate.c
+//
+// 3 9/14/11 11:30a Markw
+// Add comment for pRS->GetVariable in CommunicateCallback, and in SMM
+// Communcate generating SW SMI.
+//
+// 2 9/12/11 9:58a Markw
+// [TAG] EIP64115
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] SmmCommuncate hangs in OS.
+// [RootCause] SMM Communciate not available in OS.
+// [Solution] Update SMM Communicate to work under OS by making it a
+// runtime driver and converting pointers to virtual points on
+// EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+//
+// [Files] SmmCommunicate.c, SmmCommunicate.mak
+//
+// 1 4/18/11 12:03p Markw
+// [TAG] EIP57440
+// [Category] New Feature
+// [Description] Add SMM PI 1.1 Communicate Support.
+// [Files] SmmCommunicate.cif
+// SmmCommunicate.sdl
+// SmmCommunicate.c
+// SmmCommunicate.dxs
+// SmmDxeCommunicate.dxs
+// SmmCommunicate.mak
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmCommunicate.c
+//
+// Description: Provide SMM Communicate Protocol
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <Efi.h>
+#include <Acpi.h>
+#include <AmiDxeLib.h>
+#include <SmmPi.h>
+#include <Protocol\SmmBase2.h>
+#include <Protocol\SmmCommunication.h>
+#include <Protocol\SmmSwDispatch2.h>
+#include <Protocol\AcpiSupport.h>
+#include <Protocol\AmiInternalSmmComm.h>
+#include <Token.h>
+
+typedef struct {
+ VOID *CommBuffer;
+ UINTN *CommSize;
+ EFI_STATUS Status;
+} SMM_COMMUNICATE_DATA;
+
+#define SMM_COMMUNICATE_DATA_VARIABLE L"SMM_COMMUNICATE_DATA"
+
+// {08F10CB6-3131-4919-9D70-5C8A17366EE8}
+#define SMM_COMMUNICATE_DATA_GUID \
+ {0x8f10cb6, 0x3131, 0x4919, 0x9d, 0x70, 0x5c, 0x8a, 0x17, 0x36, 0x6e, 0xe8}
+
+EFI_HANDLE gImageHandle;
+
+EFI_GUID gEfiSmmBase2ProtocolGuid = EFI_SMM_BASE2_PROTOCOL_GUID;
+EFI_GUID gEfiSmmCommunicationProtocolGuid = EFI_SMM_COMMUNICATION_PROTOCOL_GUID;
+EFI_GUID gAmiIntSmmCommProtocolGuid = AMI_INT_SMM_COMM_PROTOCOL_GUID;
+EFI_GUID gSmmCommunicateDataGuid = SMM_COMMUNICATE_DATA_GUID;
+EFI_GUID gEfiAcpiSupportGuid = EFI_ACPI_SUPPORT_GUID;
+
+
+EFI_SMM_BASE2_PROTOCOL *gSmmBase2;
+
+
+SMM_COMMUNICATE_DATA *gCommunicateData = NULL;
+
+/////////////////////SMM//////////////////
+EFI_GUID gEfiSmmSwDispatch2ProtocolGuid = EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID;
+
+EFI_SMM_SW_DISPATCH2_PROTOCOL *gSmmSw2;
+EFI_SMM_SYSTEM_TABLE2 *Smst2;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CommunicateCallBack
+//
+// Description: Sw SMI callback to call communicate functions.
+//
+// Input:
+// IN EFI_HANDLE DispatchHandle - Unused
+// IN CONST VOID *Context OPTIONAL - Unused
+// IN OUT VOID *CommBuffer OPTIONAL - Unused
+// IN OUT UINTN *CommBufferSize OPTIONAL - Unused
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS CommunicateCallBack(
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+)
+{
+ EFI_SMM_COMMUNICATE_HEADER *Header;
+ EFI_STATUS Status;
+
+ if (gCommunicateData == NULL) {
+ UINTN VariableSize = sizeof(EFI_SMM_COMMUNICATE_HEADER*);
+
+ //SMM_COMMUNICATE_DATA_VARIABLE variable is not available during
+ // SMM entry. When this variable is set in DXE before BDS,
+ // a SW SMI is executed, and gCommunicateData is initialized
+ // before SMM Communciate protocol is published.
+ Status = pRS->GetVariable(
+ SMM_COMMUNICATE_DATA_VARIABLE,
+ &gSmmCommunicateDataGuid,
+ NULL,
+ &VariableSize,
+ &gCommunicateData
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (!EFI_ERROR(Status)) gCommunicateData->Status = Status;
+ return EFI_SUCCESS;
+ }
+
+ if (gCommunicateData->CommBuffer == NULL) {
+ gCommunicateData->Status = EFI_INVALID_PARAMETER;
+ return EFI_SUCCESS;
+ }
+
+ gCommunicateData->Status = EFI_NOT_FOUND; //Default no handler found.
+
+ Header = (EFI_SMM_COMMUNICATE_HEADER*)(gCommunicateData->CommBuffer);
+ Status = Smst2->SmiManage(&Header->HeaderGuid, NULL, Header->Data, &Header->MessageLength);
+
+ //Default Status of SmiManage is EFI_INTERRUPT_PENDING. Thus, no handler found.
+ if (Status != EFI_INTERRUPT_PENDING) gCommunicateData->Status = EFI_SUCCESS;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitSmm
+//
+// Description: Initialize SMM part of SMM Communicate.
+//
+// Input: VOID
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InitSmm()
+{
+ EFI_STATUS Status;
+ EFI_SMM_SW_REGISTER_CONTEXT RegisterContext = {SMM_COMM_SW_SMI};
+ EFI_HANDLE ImageHandle = NULL;
+ EFI_HANDLE DispatchHandle;
+
+ Status = gSmmBase2->GetSmstLocation(gSmmBase2, &Smst2);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = Smst2->SmmLocateProtocol(&gEfiSmmSwDispatch2ProtocolGuid, NULL, &gSmmSw2);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = gSmmSw2->Register(
+ gSmmSw2,
+ CommunicateCallBack,
+ &RegisterContext,
+ &DispatchHandle
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+
+//Signal that Handler is ready
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+ &gAmiIntSmmCommProtocolGuid, NULL,
+ NULL
+ );
+
+ return Status;
+}
+
+
+/////////////////////ACPI//////////////////
+
+#pragma pack(push, 1)
+typedef struct {
+ ACPI_HDR Hdr;
+ EFI_GUID Identifier;
+ UINT16 DataOffset;
+ UINT32 SwSmi;
+ UINT64 BufferPtr;
+} ACPI_SMM_COMM_TABLE;
+#pragma pack(pop)
+
+ACPI_SMM_COMM_TABLE gAcpiSmmCommTable =
+{
+ 'UEFI',
+ sizeof(ACPI_SMM_COMM_TABLE),
+ 1, //Revision
+ 0, //Checksum
+ CONVERT_TO_STRING(T_ACPI_OEM_ID),
+ CONVERT_TO_STRING(T_ACPI_OEM_TBL_ID),
+ ACPI_OEM_REV,
+ 0, //Creator ID
+ 0, //Creator Revision,
+ EFI_SMM_COMMUNICATION_PROTOCOL_GUID,
+ EFI_FIELD_OFFSET(ACPI_SMM_COMM_TABLE, SwSmi),
+ SMM_COMM_SW_SMI,
+ 0
+};
+
+EFI_ACPI_SUPPORT_PROTOCOL *gAcpiSupport;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitAcpi
+//
+// Description: Initialize Acpi SMM Communicate part.
+//
+// Input: VOID
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InitAcpi()
+{
+//TODO: Proper support for ACPI SMM communicate will be in SMM label 45.
+#if 0
+ EFI_STATUS Status;
+ UINTN AcpiHandle = 0;
+
+ Status = pBS->LocateProtocol(&gEfiAcpiSupportGuid, NULL, &gAcpiSupport);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = gAcpiSupport->SetAcpiTable(
+ gAcpiSupport,
+ &gAcpiSmmCommTable,
+ TRUE,
+ EFI_ACPI_TABLE_VERSION_ALL,
+ &AcpiHandle
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+#endif
+
+ return EFI_SUCCESS;
+}
+
+/////////////////////DXE//////////////////
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmCommunicate
+//
+// Description: SmmCommunicate Protocol function. This will generate SW SMI.
+//
+// Input:
+// IN CONST EFI_SMM_COMMUNICATION_PROTOCOL *This,
+// IN OUT VOID *CommBuffer,
+// IN OUT UINTN *CommSize
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmCommunicate(
+ IN CONST EFI_SMM_COMMUNICATION_PROTOCOL *This,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize
+)
+{
+ gCommunicateData->CommBuffer = CommBuffer;
+ gCommunicateData->CommSize = CommSize;
+ gCommunicateData->Status = EFI_DEVICE_ERROR; //Pre-initialize status in case SMI doesn't happen.
+
+ //Execute SW SMI to initialize
+ IoWrite8(SW_SMI_IO_ADDRESS, SMM_COMM_SW_SMI);
+
+ return gCommunicateData->Status;
+}
+
+EFI_SMM_COMMUNICATION_PROTOCOL gEfiSmmCommunicationProtocol = {
+ SmmCommunicate
+};
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: VirtAddrChg
+//
+// Description: Change pointer of gCommunicateData to virtual address.
+//
+// Input:
+// IN EFI_EVENT Event
+// IN VOID *Context
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID VirtAddrChg(IN EFI_EVENT Event, IN VOID *Context)
+{
+ pRS->ConvertPointer(0, (VOID**)&gCommunicateData);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitDxe
+//
+// Description: Initialize DXE SMM Communicate part.
+//
+// Input: VOID
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InitDxe()
+{
+ EFI_STATUS Status;
+ EFI_EVENT VirtAddrChgEvt;
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, sizeof(SMM_COMMUNICATE_DATA), &gCommunicateData);
+ ASSERT_EFI_ERROR(Status);
+
+ //Pass gCommunicateData to SMM Dispatcher.
+ gCommunicateData->Status = EFI_DEVICE_ERROR; //Pre-initialize status in case SMI doesn't happen.
+
+ //Set Value
+ Status = pRS->SetVariable(
+ SMM_COMMUNICATE_DATA_VARIABLE,
+ &gSmmCommunicateDataGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(SMM_COMMUNICATE_DATA*),
+ &gCommunicateData
+ );
+
+ IoWrite8(SW_SMI_IO_ADDRESS, SMM_COMM_SW_SMI);
+
+ if (gCommunicateData->Status == EFI_DEVICE_ERROR) return EFI_DEVICE_ERROR;
+
+ InitAcpi();
+
+ Status = pBS->CreateEvent(
+ EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+ TPL_CALLBACK,
+ &VirtAddrChg,
+ NULL,
+ &VirtAddrChgEvt
+ );
+ ASSERT_EFI_ERROR(Status);
+
+
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &gImageHandle,
+ &gEfiSmmCommunicationProtocolGuid, &gEfiSmmCommunicationProtocol,
+ NULL
+ );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmCommunicateEntry
+//
+// Description: Smm Communciation entry point to initialize provide SMM Communicate Protocol.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle,
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmCommunicateEntry(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+ BOOLEAN InSmram;
+
+ InitAmiLib(ImageHandle,SystemTable);
+
+ gImageHandle = ImageHandle;
+
+ Status = pBS->LocateProtocol(&gEfiSmmBase2ProtocolGuid, NULL, &gSmmBase2);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = gSmmBase2->InSmm(gSmmBase2, &InSmram);
+ ASSERT_EFI_ERROR(Status);
+
+ if (InSmram) return InitSmm();
+ return InitDxe();
+}
diff --git a/Core/EM/SMM/SmmCommunicate.cif b/Core/EM/SMM/SmmCommunicate.cif
new file mode 100644
index 0000000..3d086cd
--- /dev/null
+++ b/Core/EM/SMM/SmmCommunicate.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "SmmCommunicate"
+ category = ModulePart
+ LocalRoot = "Core\EM\SMM\"
+ RefName = "SmmCommunicate"
+[files]
+"SmmCommunicate.sdl"
+"SmmCommunicate.c"
+"SmmCommunicate.dxs"
+"SmmDxeCommunicate.dxs"
+"SmmCommunicate.mak"
+<endComponent>
diff --git a/Core/EM/SMM/SmmCommunicate.dxs b/Core/EM/SMM/SmmCommunicate.dxs
new file mode 100644
index 0000000..4eb6b47
--- /dev/null
+++ b/Core/EM/SMM/SmmCommunicate.dxs
@@ -0,0 +1,67 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmCommunicate.dxs 1 4/18/11 12:03p Markw $
+//
+// $Revision: 1 $
+//
+// $Date: 4/18/11 12:03p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmCommunicate.dxs $
+//
+// 1 4/18/11 12:03p Markw
+// [TAG] EIP57440
+// [Category] New Feature
+// [Description] Add SMM PI 1.1 Communicate Support.
+// [Files] SmmCommunicate.cif
+// SmmCommunicate.sdl
+// SmmCommunicate.c
+// SmmCommunicate.dxs
+// SmmDxeCommunicate.dxs
+// SmmCommunicate.mak
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmCommunicate.dxs
+//
+// Description: Dependency file for the SMM Communicate driver
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <Protocol\SmmSwDispatch2.h>
+
+DEPENDENCY_START
+ EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID
+DEPENDENCY_END
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmCommunicate.mak b/Core/EM/SMM/SmmCommunicate.mak
new file mode 100644
index 0000000..b0b4918
--- /dev/null
+++ b/Core/EM/SMM/SmmCommunicate.mak
@@ -0,0 +1,91 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmCommunicate.mak 2 9/12/11 9:59a Markw $
+#
+# $Revision: 2 $
+#
+# $Date: 9/12/11 9:59a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmCommunicate.mak $
+#
+# 2 9/12/11 9:59a Markw
+# [TAG] EIP64115
+# [Category] Bug Fix
+# [Severity] Normal
+# [Symptom] SmmCommuncate hangs in OS.
+# [RootCause] SmmCommunicate not supported in OS.
+# [Solution] Update SMM Communicate to work under OS by making it a
+# runtime driver and converting pointers to virtual points on
+# EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+#
+# [Files] SmmCommunicate.c, SmmCommunicate.mak
+#
+# 1 4/18/11 12:03p Markw
+# [TAG] EIP57440
+# [Category] New Feature
+# [Description] Add SMM PI 1.1 Communicate Support.
+# [Files] SmmCommunicate.cif
+# SmmCommunicate.sdl
+# SmmCommunicate.c
+# SmmCommunicate.dxs
+# SmmDxeCommunicate.dxs
+# SmmCommunicate.mak
+#
+#**********************************************************************
+
+#<AMI_FHDR_START>
+#---------------------------------------------------------------------------
+#
+# Name: SmmCommunicate.mak
+#
+# Description: Make file for the SMM Communicate code
+#
+#---------------------------------------------------------------------------
+#<AMI_FHDR_END>
+
+all : SmmCommunicate
+SmmCommunicate : $(BUILD_DIR)\SmmCommunicate.mak SmmCommunicateBin
+
+$(BUILD_DIR)\SmmCommunicate.mak : $(SMM_COMMUNICATE_DIR)\SmmCommunicate.cif $(SMM_COMMUNICATE_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SMM_COMMUNICATE_DIR)\SmmCommunicate.cif $(CIF2MAK_DEFAULTS)
+
+SmmCommunicateBin : $(AMIDXELIB) $(AMICSPLib)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SmmCommunicate.mak all\
+ GUID=7E2D983F-F703-4a29-9761-77B51F5354ED\
+ ENTRY_POINT=SmmCommunicateEntry\
+ TYPE=DXESMM_DRIVER PE_TYPE=RT_DRIVER\
+ DEPEX1=$(SMM_COMMUNICATE_DIR)\SmmCommunicate.dxs \
+ DEPEX1_TYPE=EFI_SECTION_SMM_DEPEX \
+ DEPEX2=$(SMM_COMMUNICATE_DIR)\SmmDxeCommunicate.dxs \
+ DEPEX2_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/Core/EM/SMM/SmmCommunicate.sdl b/Core/EM/SMM/SmmCommunicate.sdl
new file mode 100644
index 0000000..7ac66cc
--- /dev/null
+++ b/Core/EM/SMM/SmmCommunicate.sdl
@@ -0,0 +1,44 @@
+TOKEN
+ Name = "SMM_COMMUNICATE_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable SmmBase support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Token = "PI_SPECIFICATION_VERSION" ">=" "0x1000A"
+End
+
+TOKEN
+ Name = "SMM_COMM_SW_SMI"
+ Value = "0xdd"
+ Help = "SMM Communicate function SW SMI. Do not change"
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "SMM_COMM_ACPI_SW_SMI"
+ Value = "0xde"
+ Help = "SMM Communicate ACPI SW SMI. Do not change"
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+End
+
+PATH
+ Name = "SMM_COMMUNICATE_DIR"
+End
+
+MODULE
+ Help = "Includes SmmCommunicate.mak to Project"
+ File = "SmmCommunicate.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SmmCommunicate.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/SMM/SmmDispatcher.c b/Core/EM/SMM/SmmDispatcher.c
new file mode 100644
index 0000000..c510cc7
--- /dev/null
+++ b/Core/EM/SMM/SmmDispatcher.c
@@ -0,0 +1,1533 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (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/SmmDispatcher.c 5 6/17/16 4:14a Chienhsieh $
+//
+// $Revision: 5 $
+//
+// $Date: 6/17/16 4:14a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/SMM/SmmDispatcher.c $
+//
+// 5 6/17/16 4:14a Chienhsieh
+// Roll back #if condition: "ENABLE_SEND_SMI_IPI_IN_SMM" as Rev.3
+//
+// 4 7/08/15 4:26a Chienhsieh
+//
+// 3 12/19/12 6:25a Wesleychen
+// Set a #if condition: "ENABLE_SEND_SMI_IPI_IN_SMM" to isolate send SMI
+// IPI in SMM for avoid system stay in an unstable state when numerous
+// SMI# are generated.
+//
+// 2 10/31/12 6:30a Wesleychen
+// Modify SMM InterruptManage function to execute Non-PI handler after PI
+// handler.
+//
+// 75 10/03/11 2:53p Markw
+// Add SMM Machine Check handler.
+// Files: SmmDispatcher.c, SmmDispatcherAsm.asm
+//
+// 74 9/28/11 4:52p Markw
+// [TAG] EIP71122
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] System may hang randomly in PI 1.1 mode.
+// [RootCause] PI 1.1 SMST was initialized using uninitialized gSmmBase.
+// [Solution] Initialize gSmmBase before initializing PI 1.1 SMST.
+// [Files] SmmDispatcher.c
+//
+// 73 6/01/11 3:09p Markw
+// [TAG] EIP61586
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] None
+// [RootCause] SMM security issue. Need ITP, specific board, and memory
+// to exploit.
+// SMM Dispatcher reads a pointer out of SMM. It uses this pointer to
+// access outside of SMM.
+// To exploit, the pointer would have to modified to write inside of SMM
+// to update code to allow SMM code to access the function call outside of
+// SMM.
+// Then, the exploit would have update a callback structure with an
+// address outside of SMM.
+// [Solution] Copy the pointer inside of SMM. Thus, a direct write
+// outside of SMM without reading a pointer outside of SMM first.
+// [Files] SmmDispatcher.c
+//
+// 72 4/15/11 4:39p Markw
+// [TAG] EIP57440
+// [Category] New Feature
+// [Description] PI 1.1 update of Manage function from previous
+// check-in.
+// [Files] SmmDispatcher.c
+//
+// 71 3/31/11 6:44p Markw
+// [TAG] EIP57440
+// [Category] Improvement
+// [Description] Separate Framework and PI 1.1 registered SMI source
+// handlers function return status checking.
+// [Files] SmmDispatcher.c
+//
+// 69 2/07/11 3:29p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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
+//
+// 67 10/13/10 1:15p Markw
+// Fix compiler warning form Timeout->EndValue = ((UINT32)EndValue) & ((1
+// << NUM_BITS_IN_ACPI_TIMER) - 1);
+//
+// 66 9/10/10 5:05p Markw
+// Typecase to UINT8 when comparing savestate eax with SW SMI number.
+//
+// 65 4/29/10 11:23a Markw
+// Added some additional asserts on allocating SMM memory during SMM
+// initialization.
+//
+// 64 4/27/10 7:28p Markw
+// EIP 37921 - Update timeout functions to fix boundary condition in
+// timeout.
+//
+// 63 3/02/10 1:49p Markw
+// Added functions/structures for Save/Restore CPU state in SMM.
+//
+// 62 2/25/10 5:24p Markw
+// Install AmiSmmInfo Protocol.
+//
+// 61 2/18/10 4:31p Markw
+// EIP 34991 - Update CPU detection of CPU that generated SW SMI. It is
+// possible that multiple SW SMI may be generated simutaneously.
+// The CPU reported as generated the SW SMI by SwSMiCpuTrigger will the
+// first CPU that matches SW_SMI_IO_ADDRESS not just the first CPU found
+// that generated a SW SMI.
+//
+// 60 11/23/09 11:27a Markw
+// Remove ASSERT when SBSP not in SMM.
+//
+// 59 11/23/09 10:59a Markw
+// Renamed TIMEOUT to SMM_TIMEOUT.
+//
+// 58 9/09/09 5:17p Markw
+// EIP #25506 - Use token for x2apic support.
+//
+// 57 8/05/09 3:03p Markw
+// EIP #24914 - Add early local x2APIC support.
+//
+// 56 7/08/09 8:04p Markw
+// Update headers.
+//
+// 55 5/12/09 7:22p Markw
+// Fix mismatch #if/#endif when updating AMI_DEBUGGER_SUPPORT.
+//
+// 54 5/12/09 7:04p Markw
+// EIP #22087 - When AMI Debugger enabled, save IDT for IDT
+// re-initialization in SmmEntry.asm.
+//
+// 53 1/22/09 1:03p Markw
+// EIP #18671 (OPEN) Clear SW SMI status and set EOS inside SMM. Also
+// check for private SW SMI as well as private function. Call Clear
+// function inside SMM.
+//
+// 52 12/24/08 10:54a Markw
+// EIP #18423: Adjust EBDA location as more EBDA data is allocated.
+//
+// 51 12/01/08 1:55p Markw
+//
+// 50 11/25/08 4:09p Markw
+// Remove TRACE. Hangs during runtime OS.
+//
+// 49 11/25/08 11:25a Markw
+// Reinitialize the InSmm variable.
+//
+// 48 11/24/08 7:13p Markw
+// Save/restore upper byte of Interrupt command register. Check if no IPI
+// pending before issuing interrupt.
+//
+// 47 11/21/08 4:59p Markw
+// SBSP if available dispatches. S3 reinitialization. User ACPI timer for
+// time.out.
+//
+// 46 11/12/08 4:57p Markw
+// Dynamically update the CurrentlyExecutingCpu in SMM SYSTEM TABLE.
+//
+// 45 10/03/08 9:45a Markw
+// Fix race condindition when sync APs with BSP. Under some conditions
+// some APs skip the SmmStartupAp control loop.
+//
+// 44 9/26/08 4:52p Markw
+// The Private InSmm is now a pointer.
+//
+// 43 9/09/08 3:06p Markw
+// Align Dispatcher to 4k.
+//
+// 42 9/07/08 12:44a Markw
+// Separate SMM Private structure into inside SMM and outside SMM
+// structure.
+//
+// 41 9/04/08 12:26a Markw
+// Always have timeout on AP. Check SMM IPI pending status.
+//
+// 40 8/28/08 3:54p Markw
+//
+// 39 8/28/08 3:52p Markw
+//
+// 38 8/12/08 5:58p Markw
+// Use SMM instance BSP, not not runtime BSP. Call dispatcher even for SMM
+// software SMIs.
+//
+// 37 6/10/08 6:45p Markw
+// Disable SMM Thunk, if SMM is in TSEG and no CSM.
+//
+// 36 6/09/08 5:51p Markw
+// Any CPU can be BSP now. Created a Common Entry. Start APs that have not
+// started yet.
+//
+// 35 5/23/08 11:19a Markw
+// Don't allow callbacks once the flag is set.
+//
+// 34 3/03/08 6:58p Markw
+// Add 32-bit registers to SMM 16-bit thunk.
+//
+// 33 11/21/07 1:06p Markw
+// Header updates.
+//
+// 32 11/21/07 12:56p Markw
+// Always install thunk protocol.
+//
+// 31 11/14/07 2:02p Markw
+// Added SMRR support and updated SMM Cache for non-SMRR.
+// Updated SMM interrupt handeling because of complier optimization bug.
+//
+// 30 10/29/07 3:38p Markw
+//
+// 29 10/29/07 10:58a Markw
+// Smm Thunk:
+// * Code and data different segments.
+// * Code position independent.
+// * Switch for CSM for code and EBDA for data.
+//
+// 28 10/24/07 12:02p Markw
+// SMM Thunk code position independent. Data in a separate segment than
+// code in Smm Thunk.
+// Combined BSP and AP SmmEntry.
+//
+// 27 9/10/07 1:39p Markw
+// Add Interrupt Handling in SMM.
+//
+// 26 7/25/07 2:11p Markw
+// Limit number of CPUs in SMM to maximum in case system shutsdown in SMM.
+//
+// 25 6/14/07 11:01a Markw
+// Comment change.
+//
+// 24 4/13/07 11:03a Markw
+// Update header.
+//
+// 23 3/27/07 11:42a Markw
+// Fix get SmmBases in dispatcher for APs if BSP is in TSEG.
+//
+// 22 3/14/07 5:58p Markw
+// Allow the BSP to service the SMI if APs time-out.
+//
+// 21 2/07/07 11:06a Markw
+// Add Smm Cpu State protocol.
+//
+// 20 1/30/07 11:58a Markw
+// Added code to exit if not all CPUs enter SMM.
+//
+// 19 1/11/07 12:29p Markw
+// Use switch to enable/disable legacy code during build.
+//
+// 18 1/10/07 5:29p Markw
+// Only install SMM Thunk if BSP entry below 1MB.
+//
+// 17 1/09/07 6:45p Markw
+// Remove dependencies on SMM_BSP_BASE. Use SMM Hob.
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmDispatcher.c
+//
+// Description: Contains the SMM dispatcher code for BSP & APs
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//This include should be first.
+#include "SmmPrivateShared.h"
+#include <Protocol\SmmThunk.h>
+#include <AmiSmm.h>
+#include <Protocol\SmmCpuState.h>
+#include <Protocol\AmiSmmInfo.h>
+#if SMM_USE_PI
+#include "SmmPi.h"
+#include <Protocol\SmmCpu.h>
+#include <Protocol\SmmControl2.h>
+#else
+#include <smm.h>
+#include <Protocol\SmmControl.h>
+#endif
+#include "AmiCspLib.h"
+
+//CPU APIC includes
+#define APIC_ALL_EXCLUDING_SELF (3 << 18)
+#define APIC_SIPI (6 << 8)
+#define APIC_INIT (5 << 8)
+#define APIC_SMI (2 << 8)
+#define APIC_DELIVERY_STATUS (1 << 12)
+#define APIC_LEVEL_ASSERT (1 << 14)
+#define APIC_LEVEL_DEASSERT (0 << 14)
+#define APIC_NO_SHORT_HAND (0 << 18)
+
+#define MSR_EXT_XAPIC_ICR 0x830
+
+EFI_GUID gEfiSmmThunkProtocolGuid = EFI_SMM_THUNK_PROTOCOL_GUID;
+EFI_GUID gSwSmiCpuTriggerGuid = SW_SMI_CPU_TRIGGER_GUID;
+EFI_GUID gEfiSmmCpuSaveStateProtocolGuid = EFI_SMM_CPU_SAVE_STATE_PROTOCOL_GUID;
+EFI_GUID gAmiSmmInfoProtcolGuid = AMI_SMM_INFO_PROTOCOL_GUID;
+#if SMM_USE_PI
+EFI_GUID gEfiCpuIo2ProtocolGuid = EFI_SMM_CPU_IO2_PROTOCOL_GUID;
+#endif
+
+UINT8 **gSmmBase;
+
+SMM_ENTRY_INIT_STRUCT *gSmmEntryData;
+SW_SMI_CPU_TRIGGER *gSwSmiCpuTrigger;
+EFI_SMM_CPU_SAVE_STATE_PROTOCOL gEfiSmmCpuSaveState;
+SMM_BASE_PRIVATE_STRUCT *gBasePrivate;
+SMM_DISPATCHER_PRIVATE_STRUCT *gDispatcherPrivate;
+volatile BOOLEAN gEntrySemaphore = FALSE;
+volatile BOOLEAN gUseSbsp;
+UINT32 gSbsp;
+volatile BOOLEAN gReleaseStartedCpus = FALSE;
+volatile UINT32 gNumCpusReady = 0;
+volatile BOOLEAN gAllCpusInSync = FALSE;
+volatile BOOLEAN gReadyForApsToExecute;
+volatile UINT8 gInitSemaphore = 0;
+BOOLEAN *gInSmm;
+
+
+#if SMM_USE_FRAMEWORK
+extern EFI_SMM_SYSTEM_TABLE gSmmSystemTable;
+#endif
+#if SMM_USE_PI
+extern EFI_SMM_SYSTEM_TABLE2 gSmmSystemTable2;
+extern EFI_SMM_CPU_PROTOCOL gEfiSmmCpuProtocol;
+#endif
+
+EFI_SMM_SAVE_RESTORE_FUNCTION SmmSaveRestoreFunctionTable[] = {
+ SmmSaveRestoreEnvironment
+ NULL
+};
+
+#if SMM_USE_PI
+EFI_SMM_ENTRY_CONTEXT gEfiSmmEntryContext; //For now, hardcode.
+UINTN gEfiSmmEntryContextSize = sizeof(EFI_SMM_ENTRY_CONTEXT);
+#endif
+
+void * Allocate(
+ IN VOID *Address OPTIONAL,
+ IN UINTN Size,
+ UINTN Alignment OPTIONAL
+);
+
+VOID InitializeMemoryManager(SMM_BASE_PRIVATE_STRUCT *Private);
+VOID InitializeSmmSystemTable();
+VOID InitializeSmmPiSystemTable();
+BOOLEAN IsSwSmiTrigger(UINT8 *SmmBase, UINT16 SwSmiPort);
+VOID StartAllCpus(SMM_ENTRY_INIT_STRUCT *SmmEntryInit);
+VOID HoldStartedCpus(SMM_ENTRY_INIT_STRUCT *SmmEntryInit);
+VOID SmmBspEntry(SMM_ENTRY_INIT_STRUCT *SmmEntryInit);
+VOID SmmApEntry(SMM_ENTRY_INIT_STRUCT *SmmEntryInit);
+UINT32 LockInc32(UINT32 *);
+VOID LockDec32(UINT32 *);
+VOID MachineCheckHandler();
+VOID InitCrc();
+
+EFI_STATUS InterruptManage(
+ IN CONST EFI_GUID *HandlerType,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+);
+
+typedef struct {
+ UINT32 OverFlow;
+ UINT32 EndValue;
+ UINT32 OldTimerValue;
+} SMM_TIMEOUT;
+
+EFI_STATUS StartTimeout(SMM_TIMEOUT *Timeout, UINT32 Time);
+EFI_STATUS HasItTimedOut(SMM_TIMEOUT *Timeout);
+
+BOOLEAN EfiSmmFarCall86Ex(
+ IN EFI_SMM_THUNK_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN SMM_THUNK_IA32_REGISTER_SET_EX *Regs,
+ IN VOID *Stack,
+ IN UINTN StackSize
+);
+
+//TODOx64: move it to a library header
+VOID CPULib_Pause();
+
+BOOLEAN Xchg8(IN OUT volatile UINT8 *, IN UINT8);
+
+//This typedef is the same as EFI_SMM_HANDLER_ENTRY_POINT2 in SmmPi.h.
+typedef EFI_STATUS (EFIAPI *SMM_HANDLER_ENTRY) (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+);
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CommonEntry
+//
+// Description: BSP and APs start here from SmmEntry.asm.
+//
+// Input:
+// IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID CommonEntry(IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit)
+{
+ //Two groups of CPUs where come through this function.
+ //1. The initial group all at once. They race for the semaphore.
+ // The winning CPU will try to start any other that has not been started.
+ //2. The CPUs that got started or stragglers after the time-out.
+ //
+ //The SMM Dispatcher will be run by the SBSP if it has been started.
+ //Otherwise, the winning CPU in #1 will run the Dispatcher.
+ //
+ //If SMM generates S3, flags will not be reset.
+
+ UINT32 CpuNo = SmmEntryInit->CpuNo;
+ volatile UINT8 IsNotFirstCpu = TRUE;
+ CPU_LIB_SMM_SAVE_RESTORE_DATA CpuSaveRestoreData;
+
+ CpuLib_SmmSaveCpuState(&CpuSaveRestoreData); //This not save state area.
+
+ //Use gSmmEntryData, so all CPUs use the same SmmInit.
+ //Re-initialize the variables on first entry and S3 resume.
+ if (gSmmEntryData->SmmInit) {
+ volatile UINT8 HoldCpus = 1;
+ HoldCpus = Xchg8(&gInitSemaphore, HoldCpus);
+ if (!HoldCpus) {
+ UINT8 i;
+ gDispatcherPrivate->NumCpusInSmm = 0;
+ gNumCpusReady = 0;
+ gAllCpusInSync = FALSE;
+ gEntrySemaphore = FALSE; //This be reset once, or all CPUs go into hold loop.
+
+ for(i = 0; i < gDispatcherPrivate->NumCpus; ++i) {
+ gDispatcherPrivate->SmmCpuInfo[i].InSmm = FALSE;
+ }
+
+ gSmmEntryData->SmmInit = 0; //This must be last; it releases the other CPUs.
+ } else {
+ while (gSmmEntryData->SmmInit) CPULib_Pause();
+ }
+ }
+
+ //InSmm must be before LockIn32, otherwise StartAllCpus fucntion could
+ //exit time-out loop, and InSmm would be false, so BSP would not execute
+ //dispatcher.
+ gDispatcherPrivate->SmmCpuInfo[CpuNo].InSmm = TRUE;
+
+ LockInc32(&gDispatcherPrivate->NumCpusInSmm);
+
+ if (gEntrySemaphore == 0) { //This if causes fewer memory exchanges.
+ IsNotFirstCpu = Xchg8(&gEntrySemaphore, IsNotFirstCpu);
+ }
+
+ if (!IsNotFirstCpu) { //This is the first CPU.
+ StartAllCpus(SmmEntryInit);
+ } else {
+ HoldStartedCpus(SmmEntryInit);
+ }
+
+ gDispatcherPrivate->SmmCpuInfo[CpuNo].InSmm = FALSE;
+
+ CpuLib_SmmRestoreCpuState(&CpuSaveRestoreData); //This not save state area.
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: StartAllCpus
+//
+// Description:
+// One random CPU enters here. Waits for CPUs to sync. If no sync, tries to
+// start CPUs that didn't enter SMM.
+//
+// Input:
+// IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID StartAllCpus(IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit)
+{
+ SMM_TIMEOUT Timeout;
+ UINT32 i;
+
+ //Wait until all APs and BSP are synced.
+ StartTimeout(&Timeout, SMM_TIME_OUT_US);
+
+ while(gDispatcherPrivate->NumCpusInSmm < gDispatcherPrivate->NumCpus
+ && !EFI_ERROR(HasItTimedOut(&Timeout))) CPULib_Pause();
+
+ //If not all CPUs get control in SMM, try to start other CPUs.
+ if (gDispatcherPrivate->NumCpusInSmm < gDispatcherPrivate->NumCpus) {
+ for (i = 0; i < gDispatcherPrivate->NumCpus; ++i) {
+ if (!gDispatcherPrivate->SmmCpuInfo[i].InSmm) {
+ UINT32 ApicId = gDispatcherPrivate->SmmCpuInfo[i].ApicId;
+#if LOCAL_X2APIC_SUPPORT
+ if (CPULib_IsLocalX2ApicEnabled()) {
+ while(ReadMsr(MSR_EXT_XAPIC_ICR) & APIC_DELIVERY_STATUS); //Wait until idle.
+ ReadWriteMsr(MSR_EXT_XAPIC_ICR,
+ Shl64(ApicId, 32) + APIC_NO_SHORT_HAND + APIC_LEVEL_ASSERT + APIC_SMI,
+ 0xfff32000);
+ } else {
+#endif
+#if ENABLE_SEND_SMI_IPI_IN_SMM
+ UINT32 SaveHighByte = *(UINT32*)(LOCAL_APIC_BASE + APIC_ICR_HIGH_REGISTER);
+ //Wait until IPI is Idle
+ while(
+ MemRead32((UINT32*)(LOCAL_APIC_BASE + APIC_ICR_LOW_REGISTER)) & APIC_DELIVERY_STATUS
+ );
+
+ //Send IPI to APIC ID.
+ MemReadWrite32(
+ (UINT32*)(LOCAL_APIC_BASE + APIC_ICR_HIGH_REGISTER),
+ ApicId << 24,
+ 0x00ffffff
+ );
+ MemReadWrite32(
+ (UINT32*)(LOCAL_APIC_BASE + APIC_ICR_LOW_REGISTER),
+ (0 << 18) + (1 << 14) + (2 << 8),
+ 0
+ );
+ //Restore high byte. Before SMI, BIOS, OS, etc may have
+ *(UINT32*)(LOCAL_APIC_BASE + APIC_ICR_HIGH_REGISTER) = SaveHighByte;
+#endif
+#if LOCAL_X2APIC_SUPPORT
+ }
+#endif
+ }
+ }
+
+ //If not all CPUs get control in SMM.
+ StartTimeout(&Timeout, SMM_TIME_OUT_US); //uS
+ while(gDispatcherPrivate->NumCpusInSmm < gDispatcherPrivate->NumCpus
+ && !EFI_ERROR(HasItTimedOut(&Timeout))) CPULib_Pause();
+ }
+
+ //Has SBSP been started.
+ gUseSbsp = gDispatcherPrivate->SmmCpuInfo[gSbsp].InSmm;
+
+ //The ASSERT below is to signal SBSP not in SMM when testing SMM.
+ //It is generally not an error when the ASSERT below is triggered. It is triggered when debugging, non-SMM errors, etc.
+ //The SMM Dispatcher is designed to process correctly if SBSP is not in SMM.
+ //DEBUG ASSERT(gUseSbsp);
+
+ gReleaseStartedCpus = TRUE;
+
+ if (gUseSbsp) {
+ if (SmmEntryInit->CpuNo == gSbsp) SmmBspEntry(SmmEntryInit);
+ else SmmApEntry(SmmEntryInit);
+ } else {
+ SmmBspEntry(SmmEntryInit); //BSP has not started, so use this as the BSP.
+ }
+
+ //reset flags before exiting.
+ gEntrySemaphore = FALSE;
+ gReleaseStartedCpus = FALSE; //This must be reset last because this releases APs to resume.
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: HoldStartedCpus
+//
+// Description:
+// Hold loop for CPU to sync. All but one CPU will enter here.
+//
+// Input:
+// IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID HoldStartedCpus(IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit)
+{
+ //Wait until trying to start all CPUs.
+ while(!gReleaseStartedCpus) CPULib_Pause();
+
+ //All CPUs have been started.
+ if (gUseSbsp) {
+ if (SmmEntryInit->CpuNo == gSbsp) SmmBspEntry(SmmEntryInit);
+ else SmmApEntry(SmmEntryInit);
+ } else {
+ SmmApEntry(SmmEntryInit);
+ }
+
+ //Wait until flags are reset by First CPU.
+ while (gReleaseStartedCpus) CPULib_Pause();
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmBspEntry
+//
+// Description: Call Smm call back or dispatch handlers.
+//
+// Input:
+// IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmBspEntry(IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit)
+{
+ static BOOLEAN DisallowCallbacks = FALSE;
+ UINT32 i;
+#if INTEL_MP_SW_SMI_PATCH == 1
+ EFI_SMM_CPU_SAVE_STATE *OrigCpuSaveState = 0;
+#endif
+ UINT32 CpuNo = SmmEntryInit->CpuNo;
+ BOOLEAN IsCallBackFunction = FALSE;
+
+#if SMM_USE_FRAMEWORK
+ gSmmSystemTable.CurrentlyExecutingCpu = CpuNo + 1;
+#endif
+ gDispatcherPrivate->SmmBspNumber = CpuNo;
+#if SMM_USE_PI
+ gEfiSmmEntryContext.CurrentlyExecutingCpu = CpuNo;
+ gSmmSystemTable2.CurrentlyExecutingCpu = CpuNo; //This 0-based, Framework is 1-based.
+#endif
+
+ //Copy save state area.
+#if SMM_USE_FRAMEWORK
+ CPU_GetSaveState(gSmmBase[CpuNo], &gSmmSystemTable.CpuSaveState[CpuNo].Ia32SaveState);
+#endif
+
+ //Indicates APs can execute function for a driver when released.
+ gReadyForApsToExecute = TRUE;
+
+ LockInc32((UINT32*)&gNumCpusReady);
+ while (gNumCpusReady < gDispatcherPrivate->NumCpusInSmm) CPULib_Pause();
+ gAllCpusInSync = TRUE;
+
+ //Make OEM Call to save state.
+ for (i = 0; SmmSaveRestoreFunctionTable[i] != NULL; ++i) SmmSaveRestoreFunctionTable[i](TRUE);
+
+ //Check if software smi, and the CPU that caused it.
+ gSwSmiCpuTrigger->Cpu = (UINTN)-1;
+
+ for(i = 0; i < gDispatcherPrivate->NumCpus; ++i) {
+ if (IsSwSmiTrigger(gSmmBase[i], SW_SMI_IO_ADDRESS)) {
+ UINT8 SwSmi = IoRead8(SW_SMI_IO_ADDRESS);
+#if SMM_USE_FRAMEWORK
+ if ( SwSmi == (UINT8)gSmmSystemTable.CpuSaveState[i].Ia32SaveState.EAX) {
+#else
+ UINT8 RegAl;
+ EFI_STATUS Status;
+ Status = gEfiSmmCpuProtocol.ReadSaveState(
+ &gEfiSmmCpuProtocol,
+ 1,
+ EFI_SMM_SAVE_STATE_REGISTER_RAX,
+ i,
+ &RegAl
+ );
+ if (EFI_ERROR(Status) || SwSmi == RegAl) { //Assume if error, then this is the correct CPU.
+#endif
+ gSwSmiCpuTrigger->Cpu = i;
+ break;
+ }
+ }
+ }
+
+//Intel only uses save state CpuSaveState[0] for software SMIs, event though it may
+//be generated by a AP. If INTEL_MP_SW_SMI_PATCH is enabled, it will temporarily,
+//set CpuSaveState[0] to the AP that generated SMI. However, this means CpuSaveState[x]
+//may be invalid.
+//
+//The PIWG should come up with a permanent solution.
+//
+#if INTEL_MP_SW_SMI_PATCH == 1
+ if ((INTN)gSwSmiCpuTrigger->Cpu > 0) {
+ OrigCpuSaveState = gSmmSystemTable.CpuSaveState;
+ gSmmSystemTable.CpuSaveState = &OrigCpuSaveState[gSwSmiCpuTrigger->Cpu];
+ gSwSmiCpuTrigger->Cpu = 0;
+ }
+#endif
+
+ if (gDispatcherPrivate->FloatingPointSave) {
+//The XMM is already before executing C because of possible optimizations.
+// _asm FXSAVE gSmmSystemTable.CpuOptionalFloatingPointState //Save Floating Point Context;
+ }
+
+ *gInSmm = TRUE; //SMM BASE protocol InSmm function returns this variable.
+ //This CallBackFunc is only called during boot services before shell.
+ if (!DisallowCallbacks) {
+ //Check both CallBackFunc and software smi.
+ //This is done in case asynchronous SMI occurs between setting up CallBackFunc and SW SMI.
+ IsCallBackFunction = gBasePrivate->CallBackFunc && IoRead8(SW_SMI_IO_ADDRESS) == SMMBASE_CALLBACK;
+
+ if (IsCallBackFunction) {
+ gBasePrivate->CallBackFunc();
+ gBasePrivate->CallBackFunc = 0;
+ if (gBasePrivate->DisallowCallbacks) DisallowCallbacks = TRUE;
+ }
+ }
+
+ gInitSemaphore = 0; //Clear this away from loop to be sure 2 CPUs don't do xchg.
+
+#if SMM_USE_PI
+ InterruptManage(NULL, NULL, &gEfiSmmEntryContext, &gEfiSmmEntryContextSize); //Execute root handlers
+#else
+ InterruptManage(NULL, NULL, NULL, NULL); //Execute root handlers
+#endif
+
+ *gInSmm = FALSE; //SMM BASE protocol InSmm function returns this variable.
+
+ if (gDispatcherPrivate->FloatingPointSave) {
+//The XMM is already before executing C because of possible optimizations.
+// _asm FXRSTOR gSmmSystemTable.CpuOptionalFloatingPointState //Restore Floating Point Context;
+ }
+
+ if (IsCallBackFunction) {
+ //This will clear the SW SMI Status. This is done last in case an incorrect
+ // implementation Clear, clears all statuses.
+ //
+ //This will not be called during runtime.
+#if SMM_USE_PI
+ ((EFI_SMM_CONTROL2_PROTOCOL*)gDispatcherPrivate->SmmControl)->Clear((EFI_SMM_CONTROL2_PROTOCOL*)gDispatcherPrivate->SmmControl, FALSE);
+#else
+ ((EFI_SMM_CONTROL_PROTOCOL*)gDispatcherPrivate->SmmControl)->Clear((EFI_SMM_CONTROL_PROTOCOL*)gDispatcherPrivate->SmmControl, FALSE);
+#endif
+ }
+
+//Restore CpuSaveState.
+#if INTEL_MP_SW_SMI_PATCH == 1
+ if(OrigCpuSaveState) gSmmSystemTable.CpuSaveState = OrigCpuSaveState;
+#endif
+
+ //Make OEM Call to restore state.
+ for (i = 0; SmmSaveRestoreFunctionTable[i] != NULL; ++i) SmmSaveRestoreFunctionTable[i](FALSE);
+
+#if SMM_USE_FRAMEWORK
+ //Copy save state area.
+ CPU_RestoreSaveState(gSmmBase[CpuNo], &gSmmSystemTable.CpuSaveState[CpuNo].Ia32SaveState);
+#endif
+
+ gReadyForApsToExecute = FALSE; //Used to indicate that BSP is exiting SMM mode.
+
+ LockDec32(&gDispatcherPrivate->NumCpusInSmm);
+ while(gDispatcherPrivate->NumCpusInSmm > 0) CPULib_Pause();
+
+ gNumCpusReady = 0; //Initialize count.
+ gAllCpusInSync = FALSE; //This must be set last. Releases CPUs from SmmApEntry.
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmApEntry
+//
+// Description: APs after switching to protected mode will jump here.
+//
+// Input:
+// IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmApEntry(IN SMM_ENTRY_INIT_STRUCT *SmmEntryInit)
+{
+ volatile SMM_AP_CPU_CONTROL *SmmApCpuControl = &gDispatcherPrivate->SmmApCpuControl[SmmEntryInit->CpuNo];
+ UINT32 CpuNo = SmmEntryInit->CpuNo;
+
+ //Copy save state area.
+#if SMM_USE_FRAMEWORK
+ CPU_GetSaveState(gSmmBase[CpuNo], &gSmmSystemTable.CpuSaveState[CpuNo].Ia32SaveState);
+#endif
+
+ LockInc32((UINT32*)&gNumCpusReady);
+ while(!gAllCpusInSync) CPULib_Pause();
+
+ while(gReadyForApsToExecute) {
+ if (SmmApCpuControl->Procedure) {
+ SmmApCpuControl->Procedure(SmmApCpuControl->ProcArguments);
+ SmmApCpuControl->Procedure = 0;
+ }
+ CPULib_Pause();
+ }
+
+#if SMM_USE_FRAMEWORK
+ CPU_RestoreSaveState(
+ (UINT8*)SmmEntryInit->SmmEntryStart - 0x8000,
+ &gSmmSystemTable.CpuSaveState[SmmEntryInit->CpuNo].Ia32SaveState
+ );
+#endif
+
+ LockDec32(&gDispatcherPrivate->NumCpusInSmm);
+
+ while(gAllCpusInSync) CPULib_Pause(); //Wait until BSP is ready.
+}
+
+
+//*******************************************************
+//EFI SMM Handler Return Code
+//*******************************************************
+#define EFI_HANDLER_SUCCESS 0x0000
+#define EFI_HANDLER_CRITICAL_EXIT 0x0001
+#define EFI_HANDLER_SOURCE_QUIESCED 0x0002
+#define EFI_HANDLER_SOURCE_PENDING 0x0003
+
+EFI_STATUS InterruptManage(
+ IN CONST EFI_GUID *HandlerType,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+)
+{
+ HANDLER_LIST *Link;
+#if SMM_USE_PI
+ EFI_STATUS Status = EFI_INTERRUPT_PENDING; //Default: Interrupt not handled.
+#else
+ EFI_STATUS Status = EFI_HANDLER_SUCCESS;
+#endif
+ EFI_STATUS HdlrStatus;
+
+ for (Link = gDispatcherPrivate->HandlerListHead; Link; Link = Link->Link) {
+ if (HandlerType == NULL) {
+ if (!Link->IsRoot) continue;
+ } else {
+ if (Link->IsRoot || (guidcmp((EFI_GUID*)HandlerType, &Link->HandlerType) != 0)) continue;
+ }
+
+#if SMM_USE_PI
+ if(Link->IsPi) {
+ HdlrStatus = ((SMM_HANDLER_ENTRY)Link->EntryPoint)(
+ Link->SmmImageHandle, Context, CommBuffer, CommBufferSize
+ );
+
+ //TODO: PI 1.1 spec SmiManage function EFI_SUCCESS description questionable.
+ //Review with PI work group.
+
+ switch(HdlrStatus) {
+ case EFI_WARN_INTERRUPT_SOURCE_PENDING:
+ break;
+ //TODO: Comment out for now because of build error related to core header files.
+ //case EFI_INTERRUPT_PENDING:
+ // return EFI_INTERRUPT_PENDING;
+ case EFI_WARN_INTERRUPT_SOURCE_QUIESCED:
+ Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED; //Change status to interrupt handled.
+ break;
+ case EFI_SUCCESS:
+ if (Link->IsRoot) {
+ Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED; //Change status to interrupt handled.
+ break; //Continue checking other root handlers.
+ }
+ return EFI_WARN_INTERRUPT_SOURCE_QUIESCED;
+ default:
+ break;
+ }
+ }
+#endif
+#if 0//SMM_USE_FRAMEWORK
+ if (!Link->IsPi) {
+ HdlrStatus = ((EFI_SMM_CALLBACK_ENTRY_POINT)Link->EntryPoint)(
+ Link->SmmImageHandle, Link->CommunicationBuffer, Link->SourceSize
+ );
+ switch(HdlrStatus) {
+ case EFI_HANDLER_CRITICAL_EXIT:
+ case EFI_HANDLER_SOURCE_QUIESCED:
+ return EFI_HANDLER_CRITICAL_EXIT;
+ case EFI_HANDLER_SUCCESS:
+ case EFI_HANDLER_SOURCE_PENDING:
+ default:
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ #endif
+ }
+#if SMM_USE_FRAMEWORK
+ if (HandlerType == NULL)
+ {
+ for (Link = gDispatcherPrivate->HandlerListHead; Link; Link = Link->Link)
+ {
+ if (!Link->IsRoot)
+ continue;
+
+ if (!Link->IsPi)
+ {
+ HdlrStatus = ((EFI_SMM_CALLBACK_ENTRY_POINT)Link->EntryPoint)(Link->SmmImageHandle, Link->CommunicationBuffer, Link->SourceSize);
+ switch(HdlrStatus)
+ {
+ case EFI_HANDLER_CRITICAL_EXIT:
+ case EFI_HANDLER_SOURCE_QUIESCED:
+ return EFI_HANDLER_CRITICAL_EXIT;
+ case EFI_HANDLER_SUCCESS:
+ case EFI_HANDLER_SOURCE_PENDING:
+ default:
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ return Status;
+}
+
+
+//SMM thunk either requires AB Segment of CSM.
+#if SMM_THUNK_NO_AB_SEG == 0 || SMM_THUNK_IN_CSM == 1
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EfiSmmFarCall86Ex
+//
+// Description:
+// Smm Thunk call. If no stack, this will push flags to simulate int call.
+//
+// Input:
+// IN EFI_SMM_THUNK_PROTOCOL *This,
+// IN UINT16 Segment -16-bit segment to call
+// IN UINT16 Offset -16-bit offset to call
+// IN SMM_THUNK_IA32_REGISTER_SET_EX *Regs -Preload registers before call
+// IN VOID *Stack -Stack before call optional
+// IN UINTN StackSize - if no stack, this should be zero.
+//
+// Output: BOOLEAN
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN EfiSmmFarCall86Ex(
+ IN EFI_SMM_THUNK_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN SMM_THUNK_IA32_REGISTER_SET_EX *Regs,
+ IN VOID *Stack,
+ IN UINTN StackSize
+)
+{
+ SMM_THUNK_DATA *SmmThunkData = gDispatcherPrivate->SmmThunkData;
+
+#if SMM_THUNK_IN_CSM == 1
+ if (gDispatcherPrivate->EbdaStartOffset) {
+ UINT32 CurrentEbda = (UINT32)(UINTN)(*(UINT16*)0x40e << 4);
+ SmmThunkData =(SMM_THUNK_DATA *) (CurrentEbda + gDispatcherPrivate->EbdaStartOffset);
+ }
+#endif
+
+ SmmThunkData->FarCall.Segment = Segment;
+ SmmThunkData->FarCall.Offset = Offset;
+
+ //Copy address for stack
+ if (Stack) {
+ SmmThunkData->Stack.Stack = (UINT32)Stack;
+ SmmThunkData->Stack.StackSize = (UINT32)StackSize;
+ } else SmmThunkData->Stack.StackSize = 0;
+
+ //Copy thunk registers.
+ SmmThunkData->Regs = *Regs;
+
+ gDispatcherPrivate->SmmThunkProc(); //Do Far call.
+
+ //Restore thunk registers.
+ *Regs = SmmThunkData->Regs;
+
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EfiSmmFarCall86
+//
+// Description:
+// Smm Thunk call. If no stack, this will push flags to simulate int call.
+//
+// Input:
+// IN EFI_SMM_THUNK_PROTOCOL *This,
+// IN UINT16 Segment -16-bit segment to call
+// IN UINT16 Offset -16-bit offset to call
+// IN SMM_THUNK_IA32_REGISTER_SET *Regs -Preload registers before call
+// IN VOID *Stack -Stack before call optional
+// IN UINTN StackSize - if no stack, this should be zero.
+//
+// Output: BOOLEAN
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN EfiSmmFarCall86(
+ IN EFI_SMM_THUNK_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN SMM_THUNK_IA32_REGISTER_SET *Regs,
+ IN VOID *Stack,
+ IN UINTN StackSize
+)
+{
+ SMM_THUNK_IA32_REGISTER_SET_EX RegsEx;
+ BOOLEAN RetValue;
+
+ RegsEx.X.AX = Regs->X.AX;
+ RegsEx.X.BX = Regs->X.BX;
+ RegsEx.X.CX = Regs->X.CX;
+ RegsEx.X.DX = Regs->X.DX;
+ RegsEx.X.SI = Regs->X.SI;
+ RegsEx.X.DI = Regs->X.DI;
+ RegsEx.X.Flags = Regs->X.Flags;
+ RegsEx.X.ES = Regs->X.ES;
+ RegsEx.X.CS = Regs->X.CS;
+ RegsEx.X.SS = Regs->X.SS;
+ RegsEx.X.DS = Regs->X.DS;
+ RegsEx.X.BP = Regs->X.BP;
+
+ RetValue = EfiSmmFarCall86Ex(
+ This,
+ Segment,
+ Offset,
+ &RegsEx,
+ Stack,
+ StackSize
+ );
+
+ Regs->X.AX = RegsEx.X.AX;
+ Regs->X.BX = RegsEx.X.BX;
+ Regs->X.CX = RegsEx.X.CX;
+ Regs->X.DX = RegsEx.X.DX;
+ Regs->X.SI = RegsEx.X.SI;
+ Regs->X.DI = RegsEx.X.DI;
+ Regs->X.Flags = RegsEx.X.Flags;
+ Regs->X.ES = RegsEx.X.ES;
+ Regs->X.CS = RegsEx.X.CS;
+ Regs->X.SS = RegsEx.X.SS;
+ Regs->X.DS = RegsEx.X.DS;
+ Regs->X.BP = RegsEx.X.BP;
+
+ return RetValue;
+}
+
+EFI_SMM_THUNK_PROTOCOL EfiSmmThunkProtocol = {EfiSmmFarCall86, EfiSmmFarCall86Ex};
+
+#endif
+
+#pragma pack (1)
+typedef struct {
+ UINT16 LoOffset;
+ UINT16 Segment;
+ UINT16 DescBits; //Will be set to 0x0f00 Present=1, DPL = 0, D = 1 (32bit)
+ UINT16 HiOffset;
+#ifdef EFIx64
+ UINT32 Hi32Offset;
+ UINT32 Rsv;
+#endif
+} INTR_GATE_DESC;
+
+typedef struct {
+ UINT8 MovAlOp;
+ UINT8 InterruptNum;
+ UINT8 JmpOp;
+ UINT8 RelOffset;
+} INT_ENTRY_POINT;
+
+INT_ENTRY_POINT gIntEntryTemplate = { //No global memory
+ 0xb0, //mov al, Int
+ 0, //Int
+ 0xeb, //jmp
+ 0xfe // to itself
+};
+
+typedef struct {
+ UINT8 PushEaxOp;
+ UINT8 MovAlOp;
+ UINT8 MovAlValue;
+ UINT8 OutAlOp;
+ UINT8 OutAlValue;
+ UINT8 PopEaxOp;
+#ifdef EFIx64
+ UINT8 Ext64Op;
+#endif
+ UINT8 IretValue;
+} EOI_TEMPLATE;
+
+EOI_TEMPLATE EoiTemplate = {
+ 0x50, //push eax/rax
+ 0xb0, 0x20, //mov al, 20h ;EOI
+ 0xe6, 0x20, //out 20h, al ;Sent Master EOI to interrupt controller.
+ 0x58, //pop eax/rax
+#ifdef EFIx64
+ 0x48, //Ext 64-bit Opcode.
+#endif
+ 0xcf //iret
+};
+
+#pragma pack()
+
+#define NUM_EXCEPTIONS 19
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitInterrupts
+//
+// Description:
+// Install Interrupt Handlers. Initialize the interrupt descriptors.
+//
+// Input: VOID
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InitInterrupts()
+{
+#if AMI_DEBUGGER_SUPPORT
+ CPULib_SaveIdt(&gDispatcherPrivate->Idt);
+ return;
+#else
+
+ UINT32 i;
+ UINT16 Segment;
+ INT_ENTRY_POINT *IntEntryPoint;
+ INTR_GATE_DESC *IntGateDescs;
+#ifdef EFIx64
+ UINT16 *DummyIrqHandler;
+#else
+ UINT8 *DummyIrqHandler;
+#endif
+
+ //Allocate memory for addresses of interrupt Handlers.
+ DummyIrqHandler = Allocate(0, sizeof(*DummyIrqHandler), 0);
+ ASSERT(DummyIrqHandler != NULL);
+
+#ifdef EFIx64
+ *DummyIrqHandler = 0xcf48; //IRET
+#else
+ *DummyIrqHandler = 0xcf;
+#endif
+
+ IntEntryPoint = Allocate(0, sizeof(INT_ENTRY_POINT) * NUM_EXCEPTIONS, 0);
+ ASSERT(IntEntryPoint != NULL);
+
+ //Initialize interrupt entry points using template.
+ for(i = 0; i < NUM_EXCEPTIONS; ++i) {
+ gIntEntryTemplate.InterruptNum = i;
+ IntEntryPoint[i] = gIntEntryTemplate;
+ }
+
+ //Alocate space for Interrupt Descriptor Table. 256 entries/8 bytes.
+ IntGateDescs = Allocate(0, 256 * sizeof(*IntGateDescs),0);
+ ASSERT(IntGateDescs != NULL);
+
+ Segment = GetCsSegment();
+
+ //Setup halts for exceptions.
+ for (i = 0 ; i < NUM_EXCEPTIONS; ++i) {
+ UINTN IntHndlrAddr = (UINTN)&IntEntryPoint[i];
+ if (i == 18) IntHndlrAddr = (UINTN)MachineCheckHandler;
+
+ IntGateDescs[i].LoOffset=(UINT16)IntHndlrAddr;
+ IntGateDescs[i].HiOffset=(UINT16)((UINT32)IntHndlrAddr >> 16);
+ IntGateDescs[i].Segment=Segment;
+ IntGateDescs[i].DescBits=0x8e00; //Present=1, DPL = 0, D = 1 (32bit)
+#ifdef EFIx64
+ IntGateDescs[i].Hi32Offset = 0;
+ IntGateDescs[i].Rsv = 0;
+#endif
+ }
+
+ //Initialize the rest for dummy irets except timer to be overwritten below.
+ for (; i < 256 ; ++i) {
+ IntGateDescs[i].LoOffset=(UINT16)DummyIrqHandler;
+ IntGateDescs[i].HiOffset=(UINT16)((UINT32)DummyIrqHandler >> 16);
+ IntGateDescs[i].Segment=Segment;
+ IntGateDescs[i].DescBits=0x8e00; //Present=1, DPL = 0, D = 1 (32bit)
+#ifdef EFIx64
+ IntGateDescs[i].Hi32Offset = 0;
+ IntGateDescs[i].Rsv = 0;
+#endif
+ }
+
+//Setup EOI for timer interrupt.
+ {
+ VOID *TimerEoi = Allocate(0, sizeof(EOI_TEMPLATE), 0);
+ ASSERT(TimerEoi != NULL);
+ MemCpy(TimerEoi, &EoiTemplate, sizeof(EOI_TEMPLATE));
+
+ IntGateDescs[MASTER_INTERRUPT_BASE].LoOffset=*(UINT16*)&TimerEoi;
+ IntGateDescs[MASTER_INTERRUPT_BASE].HiOffset=*(((UINT16*)&TimerEoi)+1);
+ }
+
+ gDispatcherPrivate->Idt.Base=(UINT32)(UINTN)IntGateDescs;
+#ifdef EFIx64
+ gDispatcherPrivate->Idt.Limit=16*256-1;
+#else
+ gDispatcherPrivate->Idt.Limit=8*256-1;
+#endif
+#endif
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: StartTimeout
+//
+// Description:
+// Initialize timeout for a specified about of time in uS.
+//
+// Input:
+// OUT SMM_TIMEOUT *Timeout
+// IN UINT32 Time
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS StartTimeout(OUT SMM_TIMEOUT *Timeout, IN UINT32 Time) //uS
+{
+ UINT64 TicksNeeded;
+ UINT64 EndValue;
+
+ //
+ // There are 3.58 ticks per us.
+ //
+ // TicksNeeded = Time * 358 / 100
+ //
+ TicksNeeded = Div64 (Mul64 (Time, 358), 100, NULL);
+
+ // Read ACPI Timer
+ Timeout->OldTimerValue = IoRead32(PM_TMR_BLK_ADDRESS);
+ EndValue = TicksNeeded + Timeout->OldTimerValue;
+
+ //
+ // Calculate Overflow and EndValue from FullEndValue,
+ // based on number of bits in ACPI Timer
+ //
+ Timeout->OverFlow = (UINT32)Shr64 (EndValue, NUM_BITS_IN_ACPI_TIMER);
+ Timeout->EndValue = ((UINT32)EndValue) & (UINT32)(((UINT64)1 << NUM_BITS_IN_ACPI_TIMER) - 1);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: HasItTimedOut
+//
+// Description:
+// Return EFI_TIMEOUT if timer has expired.
+//
+// Input:
+// IN OUT SMM_TIMEOUT *Timeout
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS HasItTimedOut(IN OUT SMM_TIMEOUT *Timeout)
+{
+ UINT32 TimerValue;
+
+ //Read ACPI Timer
+ TimerValue = IoRead32(PM_TMR_BLK_ADDRESS);
+
+ if (Timeout->OverFlow > 0) {
+ //
+ // See if the current timer value is less than the previous value.
+ // If it is, then the timer had wrapped around.
+ //
+ if (TimerValue < Timeout->OldTimerValue) {
+ --Timeout->OverFlow;
+ }
+
+ // Update OldTimerValue
+ Timeout->OldTimerValue = TimerValue;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // See if the current timer value is less than the previous value.
+ // If it is, then we are done.
+ //
+ if (TimerValue < Timeout->OldTimerValue) return EFI_TIMEOUT;
+
+ // If we passed the EndValue, we are done.
+ if (TimerValue >= Timeout->EndValue) return EFI_TIMEOUT;
+
+ // Update OldTimerValue
+ Timeout->OldTimerValue = TimerValue;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS GetNumOfCpusInsideSmm(
+ IN AMI_SMM_INFO_PROTOCOL *This,
+ OUT UINT32 *Cpus
+)
+{
+ if (Cpus == NULL) return EFI_INVALID_PARAMETER;
+ *Cpus = gDispatcherPrivate->NumCpusInSmm;
+ return EFI_SUCCESS;
+}
+
+AMI_SMM_INFO_PROTOCOL gAmiSmmInfo = {
+ 0, //Protocol Ver
+ GetNumOfCpusInsideSmm
+};
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitializeDispatcher
+//
+// Description: Initialize Dispatcher.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output:
+// EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InitializeDispatcher(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN SMM_BASE_PRIVATE_STRUCT *BasePrivate,
+ IN SMM_DISPATCHER_PRIVATE_STRUCT *DispatcherPrivate,
+ OUT VOID **SmstTable,
+ OUT VOID **SmstTable2
+)
+{
+ //SwSmiCpuTrigger is temporary. When installed in the configuration table
+ // a copy will be made. The copy will be used.
+ SW_SMI_CPU_TRIGGER SwSmiCpuTrigger = {(UINTN)-1};
+ VOID *Address;
+ UINT8 *SmmAllocMemoryStart = BasePrivate->SmmAllocMemoryStart;
+ SMM_HOB *SmmHob = BasePrivate->SmmHob;
+ EFI_HANDLE Handle=NULL;
+ EFI_STATUS Status;
+ UINT32 i;
+//-------------------------------
+ InitAmiLib(ImageHandle, SystemTable);
+
+ gBasePrivate = BasePrivate;
+ gDispatcherPrivate = DispatcherPrivate;
+
+ gInSmm = gBasePrivate->InSmm; //Initialize pointer SMM BASE function InSmm to notify if inside of SMM.
+
+ InitializeMemoryManager(BasePrivate);
+
+ //Allocate Image
+ Address = Allocate(gBasePrivate->Pe32DispatcherImage, BasePrivate->Pe32DispatcherImageSize, 0);
+ ASSERT(Address != NULL);
+
+ InitInterrupts();
+
+ gSmmBase = (UINT8**)Allocate(0, sizeof(UINT8**) * SmmHob->NumCpus, 0);
+ ASSERT(gSmmBase != NULL);
+
+ gEfiSmmCpuSaveState.CpuSaveState = (EFI_SMM_CPU_STATE**)Allocate(0, sizeof(EFI_SMM_CPU_STATE*) * SmmHob->NumCpus, 0);
+ ASSERT(gEfiSmmCpuSaveState.CpuSaveState != NULL);
+
+/*
+ //Any Cpu number can be BSP.
+ for(i = 0; i < SmmHob->NumCpus; ++i) {
+ gSmmBase[i] = (UINT8*)(SmmHob->SmmBase[i]);
+ gEfiSmmCpuSaveState.CpuSaveState[i] = (EFI_SMM_CPU_STATE*)(SmmHob->SmmBase[i] + 0x10000-0x400);
+ }
+*/
+
+ //CPU Number 0 must be BSP.
+ gSmmBase[0] = (UINT8*)(SmmHob->SmmBase[SmmHob->Bsp]);
+ gEfiSmmCpuSaveState.CpuSaveState[0] = (EFI_SMM_CPU_STATE*)(SmmHob->SmmBase[SmmHob->Bsp] + 0x10000-0x400);
+
+
+ for(i = 0; i < SmmHob->NumCpus; ++i) {
+ static UINT32 ApNum = 0; //BSP is given CPU #0, and APs 1,2...
+ if (i == SmmHob->Bsp) continue;
+ ++ApNum;
+
+ gSmmBase[ApNum] = (UINT8*)(SmmHob->SmmBase[i]);
+ gEfiSmmCpuSaveState.CpuSaveState[ApNum] = (EFI_SMM_CPU_STATE*)(SmmHob->SmmBase[i] + 0x10000-0x400);
+ }
+
+ gSmmEntryData = (SMM_ENTRY_INIT_STRUCT *) (gSmmBase[0] + 0x8004);
+ gSmmEntryData->DispatcherEntry = CommonEntry;
+ gSmmEntryData->DispatcherPrivate = DispatcherPrivate;
+
+ gSbsp = 0;//SmmHob->Bsp;
+
+ InitCrc();
+#if SMM_USE_PI
+ InitializeSmmPiSystemTable();
+#endif
+#if SMM_USE_FRAMEWORK
+ InitializeSmmSystemTable();
+#endif
+
+
+//If installed, it will install on both SMST tables.
+#if SMM_USE_PI
+ Status = gSmmSystemTable2.SmmInstallConfigurationTable(
+ &gSmmSystemTable2,
+ &gSwSmiCpuTriggerGuid,
+ &SwSmiCpuTrigger,
+ sizeof(SW_SMI_CPU_TRIGGER)
+ );
+ ASSERT_EFI_ERROR(Status);
+#else
+ Status = gSmmSystemTable.SmmInstallConfigurationTable(
+ &gSmmSystemTable,
+ &gSwSmiCpuTriggerGuid,
+ &SwSmiCpuTrigger,
+ sizeof(SW_SMI_CPU_TRIGGER)
+ );
+ ASSERT_EFI_ERROR(Status);
+#endif
+
+#if SMM_USE_PI
+ gSwSmiCpuTrigger = gSmmSystemTable2.SmmConfigurationTable[0].VendorTable;
+#else
+ gSwSmiCpuTrigger = gSmmSystemTable.SmmConfigurationTable[0].VendorTable;
+#endif
+
+#if SMM_USE_FRAMEWORK
+ *SmstTable = &gSmmSystemTable;
+#endif
+#if SMM_USE_PI
+ *SmstTable2 = &gSmmSystemTable2;
+#endif
+
+#if SMM_USE_FRAMEWORK
+ pBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gAmiSmmInfoProtcolGuid, &gAmiSmmInfo,
+ &gEfiSmmCpuSaveStateProtocolGuid, &gEfiSmmCpuSaveState,
+//SMM thunk either requires AB Segment or CSM.
+#if SMM_THUNK_NO_AB_SEG == 0 || SMM_THUNK_IN_CSM == 1
+ &gEfiSmmThunkProtocolGuid, &EfiSmmThunkProtocol,
+#endif
+ NULL
+ );
+#endif
+
+#if SMM_USE_PI
+ Handle = NULL;
+ gSmmSystemTable2.SmmInstallProtocolInterface(
+ &Handle,
+ &gAmiSmmInfoProtcolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gAmiSmmInfo
+ );
+
+ Handle = NULL;
+ gSmmSystemTable2.SmmInstallProtocolInterface(
+ &Handle,
+ &gEfiSmmCpuSaveStateProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gEfiSmmCpuSaveState
+ );
+
+#if SMM_THUNK_NO_AB_SEG == 0 || SMM_THUNK_IN_CSM == 1
+ Handle = NULL;
+ gSmmSystemTable2.SmmInstallProtocolInterface(
+ &Handle,
+ &gEfiSmmThunkProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &EfiSmmThunkProtocol
+ );
+#endif
+
+ Handle = NULL;
+ gSmmSystemTable2.SmmInstallProtocolInterface(
+ &Handle,
+ &gEfiCpuIo2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gSmmSystemTable2.SmmIo
+ );
+
+ Handle = NULL;
+ gSmmSystemTable2.SmmInstallProtocolInterface(
+ &Handle,
+ &gEfiCpuProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gEfiSmmCpuProtocol
+ );
+#endif
+
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmDispatcher.cif b/Core/EM/SMM/SmmDispatcher.cif
new file mode 100644
index 0000000..cada3c7
--- /dev/null
+++ b/Core/EM/SMM/SmmDispatcher.cif
@@ -0,0 +1,17 @@
+<component>
+ name = "SmmDispatcher"
+ category = ModulePart
+ LocalRoot = "Core\EM\SMM"
+ RefName = "SmmDispatcher"
+[files]
+"SmmDispatcher.sdl"
+"SmmDispatcher.mak"
+"SmmEntry.asm"
+"SmmDispatcher.h"
+"SmmDispatcher.c"
+"Smst.c"
+"SmmPiSmst.c"
+"SmmMemoryManager.c"
+"SmmDispatcherAsm.asm"
+"SmmDispatcher.dxs"
+<endComponent>
diff --git a/Core/EM/SMM/SmmDispatcher.dxs b/Core/EM/SMM/SmmDispatcher.dxs
new file mode 100644
index 0000000..fd931d5
--- /dev/null
+++ b/Core/EM/SMM/SmmDispatcher.dxs
@@ -0,0 +1,59 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcher.dxs 2 8/05/09 3:04p Markw $
+//
+// $Revision: 2 $
+//
+// $Date: 8/05/09 3:04p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcher.dxs $
+//
+// 2 8/05/09 3:04p Markw
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmDispatcher.dxs
+//
+// Description: Dependency file for the SMM dispatcher
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+DEPENDENCY_START
+ FALSE
+DEPENDENCY_END
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmDispatcher.h b/Core/EM/SMM/SmmDispatcher.h
new file mode 100644
index 0000000..2b0f07c
--- /dev/null
+++ b/Core/EM/SMM/SmmDispatcher.h
@@ -0,0 +1,253 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcher.h 2 2/07/11 3:29p Markw $
+//
+// $Revision: 2 $
+//
+// $Date: 2/07/11 3:29p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcher.h $
+//
+// 2 2/07/11 3:29p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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: SmmDispatcher.h
+//
+// Description: SmmDispatcher header file
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef __SMM_DISPATCHER__H__
+#define __SMM_DISPATCHER__H__
+
+#include <SmmPi.h>
+#include <AmiLib.h>
+
+//
+// CONTAINING_RECORD - returns a pointer to the structure
+// from one of it's elements.
+//
+#ifndef _CR
+#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
+#endif
+
+#ifndef CR
+#define CR(record, TYPE, field, signature) _CR(record, TYPE, field)
+#endif
+
+//
+// Define macros to build data structure signatures from characters.
+//
+#define SIGNATURE_16(A, B) ((A) | (B << 8))
+#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
+#define SIGNATURE_64(A, B, C, D, E, F, G, H) \
+ (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32))
+//---- Added from Core\Tiano.h
+
+
+//
+// SMM_HANDLER - used for each SMM handler
+//
+
+#define SMI_ENTRY_SIGNATURE SIGNATURE_32('s','m','i','e')
+
+ typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY AllEntries; // All entries
+
+ EFI_GUID HandlerType; // Type of interrupt
+ EFI_LIST_ENTRY SmiHandlers; // All handlers
+} SMM_SMI_ENTRY;
+
+#define SMI_HANDLER_SIGNATURE SIGNATURE_32('s','m','i','h')
+
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY Link; // Link on SMI_ENTRY.SmiHandlers
+ EFI_SMM_HANDLER_ENTRY_POINT2 Handler; // The smm handler's entry point
+ SMM_SMI_ENTRY *SmiEntry;
+} SMM_SMI_HANDLER;
+
+
+
+
+#define SMM_EFI_HANDLE_SIGNATURE SIGNATURE_32('S','h','n','d')
+//#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
+
+#define SMM_PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('S','p','r','E')
+
+#define SMM_SMST_SIGNATURE2 SIGNATURE_32('S','M','T','2')
+
+
+#ifndef EFI_LIST_ENTRY_DEFINED
+#define EFI_LIST_ENTRY_DEFINED
+typedef struct _EFI_LIST_ENTRY {
+ struct _EFI_LIST_ENTRY *ForwardLink;
+ struct _EFI_LIST_ENTRY *BackLink;
+} EFI_LIST_ENTRY;
+#endif
+
+
+typedef struct {
+ UINTN Signature;
+ /// All handles list of IHANDLE
+ EFI_LIST_ENTRY AllHandles;
+ /// List of PROTOCOL_INTERFACE's for this handle
+ EFI_LIST_ENTRY Protocols;
+ UINTN LocateRequest;
+} SMM_IHANDLE;
+
+
+
+typedef struct {
+ UINTN Signature;
+ /// Link Entry inserted to mProtocolDatabase
+ EFI_LIST_ENTRY AllEntries;
+ /// ID of the protocol
+ EFI_GUID ProtocolID;
+ /// All protocol interfaces
+ EFI_LIST_ENTRY Protocols;
+ /// Registerd notification handlers
+ EFI_LIST_ENTRY Notify;
+} SMM_PROTOCOL_ENTRY;
+
+
+#define SMM_PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('S','p','i','f')
+
+typedef struct {
+ UINTN Signature;
+ /// Link on IHANDLE.Protocols
+ EFI_LIST_ENTRY Link;
+ /// Back pointer
+ SMM_IHANDLE *Handle;
+ /// Link on PROTOCOL_ENTRY.Protocols
+ EFI_LIST_ENTRY ByProtocol;
+ /// The protocol ID
+ SMM_PROTOCOL_ENTRY *Protocol;
+ /// The interface value
+ VOID *Interface;
+} SMM_PROTOCOL_INTERFACE;
+
+#define SMM_PROTOCOL_NOTIFY_SIGNATURE ('S','p','r','n')
+
+typedef struct {
+ UINTN Signature;
+ SMM_PROTOCOL_ENTRY *Protocol;
+ /// All notifications for this protocol
+ EFI_LIST_ENTRY Link;
+ /// Notification function
+ EFI_SMM_NOTIFY_FN Function;
+ /// Last position notified
+ EFI_LIST_ENTRY *Position;
+} SMM_PROTOCOL_NOTIFY;
+
+typedef struct {
+ EFI_GUID *Protocol;
+ VOID *SearchKey;
+ EFI_LIST_ENTRY *Position;
+ SMM_PROTOCOL_ENTRY *ProtEntry;
+} SMM_LOCATE_POSITION;
+
+typedef
+SMM_IHANDLE *
+(* SMM_CORE_GET_NEXT) (
+ IN OUT SMM_LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+VOID
+SmmNotifyProtocol (
+ IN SMM_PROTOCOL_INTERFACE *Prot
+ );
+
+EFI_STATUS
+SmmSmstInstallProtocolInterfaceNotify (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface,
+ IN BOOLEAN Notify
+ );
+
+EFI_STATUS
+EFIAPI
+SmmSmstHandleProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ );
+
+
+EFI_STATUS
+EFIAPI
+SmmSmstLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+ );
+
+EFI_STATUS
+EFIAPI
+SmmUninstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ );
+
+SMM_PROTOCOL_INTERFACE *
+SmmRemoveInterfaceFromProtocol (
+ IN SMM_IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ );
+
+
+
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmDispatcher.mak b/Core/EM/SMM/SmmDispatcher.mak
new file mode 100644
index 0000000..241d939
--- /dev/null
+++ b/Core/EM/SMM/SmmDispatcher.mak
@@ -0,0 +1,127 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcher.mak 9 2/07/11 3:29p Markw $
+#
+# $Revision: 9 $
+#
+# $Date: 2/07/11 3:29p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcher.mak $
+#
+# 9 2/07/11 3:29p Markw
+# [TAG] EIP53481
+# [Category] New Feature
+# [Description] Add PIWG 1.1 SMM support
+# [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
+#
+# 8 7/08/09 9:28p Markw
+# Update headers.
+#
+# 7 3/05/09 5:20p Fasihm
+# Rolled back accidental check-in.
+#
+# 5 8/28/08 3:52p Markw
+#
+# 4 6/09/08 5:48p Markw
+# Add SmmDispatcherBoard.obj and SmmDispatcherAsm.obj to be linked.
+#
+# 3 10/24/07 12:01p Markw
+# Combined BSP and AP SmmEntry.
+#
+# 2 8/24/06 3:28p Felixp
+# Preliminary x64 support (work in progress)
+#
+# 1 1/28/05 4:32p Sivagarn
+# SMM Dispatcher Component - Initial check in
+#
+#
+#**********************************************************************
+
+#<AMI_FHDR_START>
+#---------------------------------------------------------------------------
+#
+# Name: SmmDispatcher.mak
+#
+# Description: Make file for the SMM Dispatcher
+#
+#---------------------------------------------------------------------------
+#<AMI_FHDR_END>
+SMM_DISPATCHER_BUILD_DIR = $(BUILD_DIR)\$(SMM_DISPATCHER_DIR)
+
+all : SmmDispatcher SmmEntry
+
+SMM_DISPATCHER_OBJECTS = \
+ $(SMM_DISPATCHER_BUILD_DIR)\SmmDispatcher.obj \
+ $(SMM_DISPATCHER_BUILD_DIR)\Smst.obj \
+ $(SMM_DISPATCHER_BUILD_DIR)\SmmPiSmst.obj \
+ $(SMM_DISPATCHER_BUILD_DIR)\SmmMemoryManager.obj \
+ $(SMM_DISPATCHER_BUILD_DIR)\SmmDispatcherAsm.obj
+
+SmmDispatcher : $(BUILD_DIR)\SmmDispatcher.mak SmmDispatcherBin
+SmmEntry : $(BUILD_DIR)\SmmDispatcher.mak SmmEntryBin
+
+$(BUILD_DIR)\SmmDispatcher.mak : $(SMM_DISPATCHER_DIR)\$(@B).cif $(SMM_DISPATCHER_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SMM_DISPATCHER_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+!IFNDEF PI_SPECIFICATION_VERSION
+PI_SPECIFICATION_VERSION = 0
+!ENDIF
+
+SmmDispatcherBin : $(AMIDXELIB) $(AMICSPLib)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SmmDispatcher.mak all\
+# Don't change the GUID. SmmBase driver expects this GUID.
+ GUID=4A37320B-3FB3-4365-9730-9E89C600395D\
+ ENTRY_POINT=InitializeDispatcher \
+!IF $(PI_SPECIFICATION_VERSION) >= 0x00001000A
+ TYPE=SMM_CORE \
+!ELSE
+ TYPE=BS_DRIVER \
+!ENDIF
+ "OBJECTS=$(SMM_DISPATCHER_OBJECTS)"\
+ "EXT_HEADERS=$(SMM_DISPATCHER_DIR)\SmmPrivateShared.h"\
+ "CFLAGS=$(CFLAGS) /D\"SmmSaveRestoreEnvironment=$(SmmSaveRestoreEnvironment)\""\
+ COMPRESS=1\
+
+SmmEntryBin :
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\SmmDispatcher.mak all\
+# Don't change the GUID. SmmBase driver expects this GUID.
+ GUID=D2596F82-F0E1-49fa-95BC-62012C795728\
+ MAKEFILE=$(SMM_DISPATCHER_DIR)\SmmDispatcher.mak \
+ TYPE=LEGACY16 NAME=SmmEntry DEPEX1= \
+ "OBJECTS=$(SMM_DISPATCHER_BUILD_DIR)\SmmEntry.obj"\
+ COMPRESS=1\
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/Core/EM/SMM/SmmDispatcher.sdl b/Core/EM/SMM/SmmDispatcher.sdl
new file mode 100644
index 0000000..5ec4c24
--- /dev/null
+++ b/Core/EM/SMM/SmmDispatcher.sdl
@@ -0,0 +1,35 @@
+TOKEN
+ Name = "SmmDispatcher_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable SmmDispatcher support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "SMM_DISPATCHER_DIR"
+End
+
+MODULE
+ Help = "Includes SmmDispatcher.mak to Project"
+ File = "SmmDispatcher.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SmmDispatcher.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\SmmEntry.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SmmSaveRestoreEnvironment"
+ InvokeOrder = ReplaceParent
+End
diff --git a/Core/EM/SMM/SmmDispatcherAsm.asm b/Core/EM/SMM/SmmDispatcherAsm.asm
new file mode 100644
index 0000000..1abc682
--- /dev/null
+++ b/Core/EM/SMM/SmmDispatcherAsm.asm
@@ -0,0 +1,196 @@
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2009, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;*************************************************************************
+;*************************************************************************
+
+;**********************************************************************
+; $Header: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcherAsm.asm 4 10/03/11 2:53p Markw $
+;
+; $Revision: 4 $
+;
+; $Date: 10/03/11 2:53p $
+;**********************************************************************
+; Revision History
+; ----------------
+; $Log: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmDispatcherAsm.asm $
+;
+; 4 10/03/11 2:53p Markw
+; Add SMM Machine Check handler.
+; Files: SmmDispatcher.c, SmmDispatcherAsm.asm
+;
+; 3 7/08/09 8:18p Markw
+; Update headers.
+;
+; 2 11/21/08 5:00p Markw
+; Add LockInc32 and LockDec32.
+;
+; 1 6/09/08 5:56p Markw
+; Assembly functions for Dispatcher.
+;
+;**********************************************************************
+
+;<AMI_FHDR_START>
+;----------------------------------------------------------------------------
+;
+; Name: SmmDispatcher.asm
+;
+; Description: File that contains assembly for Smm Dispatcher.
+;
+;----------------------------------------------------------------------------
+;<AMI_FHDR_END>
+
+IFDEF EFIx64
+.code
+include token.equ
+
+;<AMI_PHDR_START>
+;----------------------------------------------------------------------------
+;
+; Procedure: Xchg8
+;
+; Description: Exchange a value with a pointer and return the exchanged value.
+;
+; Input:
+; IN OUT volatile UINT8 * Pointer to value to exchange.
+; IN UINT8 Value to exchange.
+;
+; Output: UINT8 Exchanged Value
+;
+; Modified: Nothing
+;
+;----------------------------------------------------------------------------
+;<AMI_PHDR_END>
+Xchg8 proc public
+ xchg dl, [rcx]
+ mov al, dl
+ ret
+Xchg8 endp
+
+;<AMI_PHDR_START>
+;---------------------------------------------------------------------------
+;
+; Procedure: LockInc32
+;
+; Description: Increment value at pointer locking address.
+;
+; Input: IN OUT UINT32 *ptr
+;
+; Output: None
+;---------------------------------------------------------------------------
+;<AMI_PHDR_END>
+
+LockInc32 proc public
+ lock inc dword ptr [rcx]
+ ret
+LockInc32 endp
+
+;<AMI_PHDR_START>
+;---------------------------------------------------------------------------
+;
+; Procedure: LockDec32
+;
+; Description: Decrement value at pointer locking address.
+;
+; Input: IN OUT UINT32 *ptr
+;
+; Output: None
+;---------------------------------------------------------------------------
+;<AMI_PHDR_END>
+
+LockDec32 proc public
+ lock dec dword ptr [rcx]
+ ret
+LockDec32 endp
+
+;<AMI_PHDR_START>
+;---------------------------------------------------------------------------
+;
+; Procedure: MachineCheckHandler
+;
+; Description: SMM Machine Check Handler
+;
+; Input: VOID
+;
+; Output: VOID
+;---------------------------------------------------------------------------
+;<AMI_PHDR_END>
+
+MachineCheckHandler proc public
+ push rax
+ push rcx
+ push rdx
+ mov ecx, 17ah ;IA32_MCG_STATUS
+ rdmsr
+ btr eax, 2 ;MCIP
+ wrmsr
+ pop rdx
+ pop rcx
+ pop rax
+ iretq
+MachineCheckHandler endp
+
+ELSE ;32-bits
+.586p
+.model small
+.code
+
+_Xchg8 proc public
+ mov al, [esp + 8]
+ mov edx, [esp + 4]
+ xchg al, [edx]
+ ret
+_Xchg8 endp
+
+_LockInc32 proc public
+ mov eax, [esp + 4]
+ lock inc dword ptr [eax]
+ ret
+_LockInc32 endp
+
+
+_LockDec32 proc public
+ mov eax, [esp + 4]
+ lock dec dword ptr [eax]
+ ret
+_LockDec32 endp
+
+_MachineCheckHandler proc public
+ push eax
+ push ecx
+ push edx
+ mov ecx, 17ah ;IA32_MCG_STATUS
+ rdmsr
+ btr eax, 2 ;MCIP
+ wrmsr
+ pop edx
+ pop ecx
+ pop eax
+ iretd
+_MachineCheckHandler endp
+
+ENDIF
+
+end
+
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2008, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;*************************************************************************
+;*************************************************************************
diff --git a/Core/EM/SMM/SmmDriverDispatcher.c b/Core/EM/SMM/SmmDriverDispatcher.c
new file mode 100644
index 0000000..c5b4431
--- /dev/null
+++ b/Core/EM/SMM/SmmDriverDispatcher.c
@@ -0,0 +1,1694 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+/** SmmDriverDispatcher.c - Modified from Intel's SMM source.
+
+ Copyright (c) 2009, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmDriverDispatcher.c 6 2/13/12 4:42p Markw $
+//
+// $Revision: 6 $
+//
+// $Date: 2/13/12 4:42p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMBase/SmmDriverDispatcher.c $
+//
+// 6 2/13/12 4:42p Markw
+// [TAG] EIP83005
+// [Category] Improvement
+// [Description] Some framework based SMM libraries expect a DXE image
+// handle on input. However, PI 1.1 SMM drivers expect a SMM handle on
+// input.
+// Update code to provide proper EFI_HANDLE when calling SMM functions.
+//
+// [Files] SmmBase.c, SmmDriverDispatcher.c
+//
+// 5 1/10/12 12:58p Markw
+// [TAG] EIP78978
+// [Category] Improvement
+// [Description] Cleanup of SmmLoadImage function - removing unused and
+// removing unneeded variable initialization.
+// [Files] SmmDriverDispatcher.c
+//
+// 4 1/09/12 3:06p Markw
+// [TAG] EIP78978
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] SMM driver will authentication failed.
+// [RootCause] Incorrect device path as input parameter when checking
+// authentication.
+//
+// [Solution] Authentication is done twice. Remove redundant code.
+// Second authentication check is using the correct original device path.
+//
+// [Files] SmmDriverDispatcher.c
+//
+// 3 3/15/11 2:37p Markw
+// Copyright header update.
+//
+// 2 3/08/11 4:57p Markw
+// Header and spacing updates.
+//
+// 1 2/07/11 3:34p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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: SmmDriverDispatcher.c
+//
+// Description: Dispatch SMM Drivers
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//This include should come first.
+#include "SmmPrivateShared.h"
+#if SMM_USE_PI
+#include <SmmPi.h>
+#include <Protocol\DevicePath.h>
+#include <Protocol\Security.h>
+#include <Dxe.h>
+#include <Protocol\FirmwareVolume2.h>
+#include <Protocol\LoadedImage.h>
+#include <AmiDxeLib.h>
+#include <AmiLib.h>
+
+extern EFI_SMM_SYSTEM_TABLE2 *gSmstTable2;
+extern SMM_BASE_PRIVATE_STRUCT *gBasePrivate;
+extern BOOLEAN gRegisterForPi;
+
+//
+// CONTAINING_RECORD - returns a pointer to the structure
+// from one of it's elements.
+//
+#ifndef _CR
+#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
+#endif
+
+#ifndef CR
+#define CR(record, TYPE, field, signature) _CR(record, TYPE, field)
+#endif
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+#define SIGNATURE_16(A, B) ((A) | (B << 8))
+#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
+#define SIGNATURE_64(A, B, C, D, E, F, G, H) \
+ (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32))
+//---- Added from Core\Tiano.h
+
+
+// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependency expression
+// to save time. A EFI_DEP_PUSH is evaluated one an
+// replaced with EFI_DEP_REPLACE_TRUE. If PI spec's Vol 2
+// Driver Execution Environment Core Interface use 0xff
+// as new DEPEX opcode. EFI_DEP_REPLACE_TRUE should be
+// defined to a new value that is not conflicting with PI spec.
+//
+#define EFI_DEP_REPLACE_TRUE 0xff
+
+/// Define the initial size of the dependency expression evaluation stack
+#define DEPEX_STACK_SIZE_INCREMENT 0x1000
+
+//
+//
+// EFI_DEP_BEFORE - If present, it must be the first and only opcode
+// EFI_DEP_AFTER - If present, it must be the first and only opcode
+// EFI_DEP_SOR - If present, it must be the first opcode
+// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependency expression
+// to save time. A EFI_DEP_PUSH is evaluated one an
+// replaced with EFI_DEP_REPLACE_TRUE
+//
+#define EFI_DEP_BEFORE 0x00
+#define EFI_DEP_AFTER 0x01
+#define EFI_DEP_PUSH 0x02
+#define EFI_DEP_AND 0x03
+#define EFI_DEP_OR 0x04
+#define EFI_DEP_NOT 0x05
+#define EFI_DEP_TRUE 0x06
+#define EFI_DEP_FALSE 0x07
+#define EFI_DEP_END 0x08
+#define EFI_DEP_SOR 0x09
+#define EFI_DEP_REPLACE_TRUE 0xff
+
+
+// Global stack used to evaluate dependency expressions
+BOOLEAN *mDepexEvaluationStack = NULL;
+BOOLEAN *mDepexEvaluationStackEnd = NULL;
+BOOLEAN *mDepexEvaluationStackPointer = NULL;
+
+#define LIST_ENTRY EFI_LIST_ENTRY
+
+//
+// The Driver List contains one copy of every driver that has been discovered.
+// Items are never removed from the driver list. List of EFI_SMM_DRIVER_ENTRY
+//
+LIST_ENTRY mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList);
+
+//
+// Queue of drivers that are ready to dispatch. This queue is a subset of the
+// mDiscoveredList.list of EFI_SMM_DRIVER_ENTRY.
+//
+LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
+
+//
+// List of handles who's Fv's have been parsed and added to the mFwDriverList.
+//
+LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList);
+
+//
+// Flag for the SMM Dispacher. TRUE if dispatcher is executing.
+//
+BOOLEAN gDispatcherRunning = FALSE;
+
+//
+// Flag for the SMM Dispacher. TRUE if there is one or more SMM drivers ready to be dispatched
+//
+BOOLEAN gRequestDispatch = FALSE;
+
+//
+// List of file types supported by dispatcher
+//
+EFI_FV_FILETYPE mSmmFileTypes[] = {
+ EFI_FV_FILETYPE_SMM,
+ EFI_FV_FILETYPE_COMBINED_SMM_DXE
+ //
+ // Note: DXE core will process the FV image file, so skip it in SMM core
+ // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
+ //
+};
+
+typedef struct {
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} FV_FILEPATH_DEVICE_PATH;
+
+FV_FILEPATH_DEVICE_PATH mFvDevicePath;
+
+//
+// DXE Architecture Protocols
+//
+EFI_SECURITY_ARCH_PROTOCOL *mSecurity = NULL;
+
+//
+// SMM Dispatcher Data structures
+//
+#define KNOWN_HANDLE_SIGNATURE SIGNATURE_32('k','n','o','w')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link; // mFvHandleList
+ EFI_HANDLE Handle;
+} KNOWN_HANDLE;
+
+//
+// Structure for recording the state of an SMM Driver
+//
+#define EFI_SMM_DRIVER_ENTRY_SIGNATURE SIGNATURE_32('s', 'd','r','v')
+
+#define LIST_ENTRY EFI_LIST_ENTRY
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link; // mDriverList
+
+ LIST_ENTRY ScheduledLink; // mScheduledQueue
+
+ EFI_HANDLE FvHandle;
+ EFI_GUID FileName;
+ EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+
+ VOID *Depex;
+ UINTN DepexSize;
+
+ BOOLEAN Before;
+ BOOLEAN After;
+ EFI_GUID BeforeAfterGuid;
+
+ BOOLEAN Dependent;
+ BOOLEAN Unrequested;
+ BOOLEAN Scheduled;
+ BOOLEAN Untrusted;
+ BOOLEAN Initialized;
+ BOOLEAN DepexProtocolError;
+
+ EFI_HANDLE ImageHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ //
+ // Image EntryPoint in SMRAM
+ //
+ EFI_PHYSICAL_ADDRESS ImageEntryPoint;
+ //
+ // Image Buffer in SMRAM
+ //
+ EFI_PHYSICAL_ADDRESS ImageBuffer;
+ //
+ // Image Page Number
+ //
+ UINTN NumberOfPage;
+} EFI_SMM_DRIVER_ENTRY;
+
+EFI_GUID gAprioriGuid=EFI_APRIORI_GUID;
+
+EFI_STATUS SmmDispatcher();
+
+EFI_HANDLE gThisImageHandle;
+
+EFI_STATUS EfiSmmRegister(
+ IN VOID *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle,
+ IN BOOLEAN LegacyIA32Binary OPTIONAL
+);
+
+//////////////////////////////////////////////////////////////////////
+// ----- PI 1.1 --------------------------------------------- START //
+//////////////////////////////////////////////////////////////////////
+
+#define SetDevicePathNodeLength(a,l) { \
+ (a)->Length[0] = (UINT8) (l); \
+ (a)->Length[1] = (UINT8) ((l) >> 8); \
+ }
+
+#define SetDevicePathEndNode(a) { \
+ (a)->Type = END_DEVICE_PATH; \
+ (a)->SubType = END_ENTIRE_SUBTYPE; \
+ (a)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); \
+ (a)->Length[1] = 0; \
+ }
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AllocatePool
+//
+// Description: Allocate memory.
+//
+// Input:
+// IN UINTN Size
+//
+// Output: VOID * - Address
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID *AllocatePool(UINTN Size){
+ return Malloc(Size);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GrowDepexStack
+//
+// Description: Increase Depex Stack..
+//
+// Input: VOID
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GrowDepexStack(VOID)
+{
+ BOOLEAN *NewStack;
+ UINTN Size;
+
+ Size = DEPEX_STACK_SIZE_INCREMENT;
+ if (mDepexEvaluationStack != NULL) {
+ Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);
+ }
+
+ NewStack = AllocatePool (Size * sizeof(BOOLEAN));
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (mDepexEvaluationStack != NULL) {
+ //
+ // Copy to Old Stack to the New Stack
+ //
+
+ MemCpy(
+ NewStack,
+ mDepexEvaluationStack,
+ (mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (BOOLEAN)
+ );
+
+ //
+ // Free The Old Stack
+ //
+ pBS->FreePool (mDepexEvaluationStack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);
+ mDepexEvaluationStack = NewStack;
+ mDepexEvaluationStackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PushBool
+//
+// Description: Push boolean value to stack.
+//
+// Input: IN BOOLEAN Value
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PushBool(IN BOOLEAN Value)
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowDepexStack ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ *mDepexEvaluationStackPointer = Value;
+ mDepexEvaluationStackPointer++;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PopBool
+//
+// Description: Pop boolean value to stack.
+//
+// Input: OUT BOOLEAN *Value
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PopBool(OUT BOOLEAN *Value)
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ mDepexEvaluationStackPointer--;
+ *Value = *mDepexEvaluationStackPointer;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmIsSchedulable
+//
+// Description: Check if driver meets dependencies.
+//
+// Input: IN EFI_SMM_DRIVER_ENTRY *DriverEntry
+//
+// Output: BOOLEAN
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN SmmIsSchedulable (IN EFI_SMM_DRIVER_ENTRY *DriverEntry)
+{
+ EFI_STATUS Status;
+ UINT8 *Iterator;
+ BOOLEAN Operator;
+ BOOLEAN Operator2;
+ EFI_GUID DriverGuid;
+ VOID *Interface;
+
+ Operator = FALSE;
+ Operator2 = FALSE;
+
+ if (DriverEntry->After || DriverEntry->Before) {
+ //
+ // If Before or After Depex skip as SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter ()
+ // processes them.
+ //
+ return FALSE;
+ }
+
+ if (DriverEntry->Depex == NULL) {
+ //
+ // A NULL Depex means that the SMM driver is schedulable.
+ //
+ //ASSERT (FALSE);
+ return TRUE;
+ }
+
+ //
+ // Clean out memory leaks in Depex Boolean stack. Leaks are only caused by
+ // incorrectly formed DEPEX expressions
+ //
+ mDepexEvaluationStackPointer = mDepexEvaluationStack;
+
+ Iterator = DriverEntry->Depex;
+
+ while (TRUE) {
+ //
+ // Check to see if we are attempting to fetch dependency expression instructions
+ // past the end of the dependency expression.
+ //
+ if (((UINTN)Iterator - (UINTN)DriverEntry->Depex) >= DriverEntry->DepexSize) {
+ return FALSE;
+ }
+
+ //
+ // Look at the opcode of the dependency expression instruction.
+ //
+ switch (*Iterator) {
+ case EFI_DEP_BEFORE:
+ case EFI_DEP_AFTER:
+ //
+ // For a well-formed Dependency Expression, the code should never get here.
+ // The BEFORE and AFTER are processed prior to this routine's invocation.
+ // If the code flow arrives at this point, there was a BEFORE or AFTER
+ // that were not the first opcodes.
+ //
+ ASSERT (FALSE);
+ case EFI_DEP_SOR:
+ //
+ // These opcodes can only appear once as the first opcode. If it is found
+ // at any other location, then the dependency expression evaluates to FALSE
+ //
+ if (Iterator != DriverEntry->Depex) {
+ return FALSE;
+ }
+ //
+ // Otherwise, it is the first opcode and should be treated as a NOP.
+ //
+ break;
+ case EFI_DEP_PUSH:
+ //
+ // Push operator is followed by a GUID. Test to see if the GUID protocol
+ // is installed and push the boolean result on the stack.
+ //
+
+ MemCpy (&DriverGuid, Iterator + 1, sizeof (EFI_GUID));
+
+ Status = gSmstTable2->SmmLocateProtocol (&DriverGuid, NULL, &Interface);
+ if (EFI_ERROR (Status)) {
+ //
+ // For SMM Driver, it may depend on uefi protocols
+ //
+ Status = pBS->LocateProtocol (&DriverGuid, NULL, &Interface);
+ }
+
+ if (EFI_ERROR (Status)) {
+ Status = PushBool (FALSE);
+ } else {
+ *Iterator = EFI_DEP_REPLACE_TRUE;
+ Status = PushBool (TRUE);
+ }
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Iterator += sizeof (EFI_GUID);
+ break;
+ case EFI_DEP_AND:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PopBool (&Operator2);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN)(Operator && Operator2));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+ case EFI_DEP_OR:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PopBool (&Operator2);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN)(Operator || Operator2));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+ case EFI_DEP_NOT:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN)(!Operator));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+ case EFI_DEP_TRUE:
+ Status = PushBool (TRUE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+ case EFI_DEP_FALSE:
+ Status = PushBool (FALSE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+ case EFI_DEP_END:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return Operator;
+ case EFI_DEP_REPLACE_TRUE:
+ Status = PushBool (TRUE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Iterator += sizeof (EFI_GUID);
+ break;
+ default:
+ goto Done;
+ }
+
+ //
+ // Skip over the Dependency Op Code we just processed in the switch.
+ // The math is done out of order, but it should not matter. That is
+ // we may add in the sizeof (EFI_GUID) before we account for the OP Code.
+ // This is not an issue, since we just need the correct end result. You
+ // need to be careful using Iterator in the loop as it's intermediate value
+ // may be strange.
+ //
+ Iterator++;
+ }
+
+ Done:
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EfiInitializeFwVolDevicepathNode
+//
+// Description: Create Firmware volume device path.
+//
+// Input:
+// IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode,
+// IN EFI_GUID *NameGuid
+
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EFIAPI EfiInitializeFwVolDevicepathNode (
+ IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode,
+ IN EFI_GUID *NameGuid
+)
+{
+ //
+ // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10.
+ // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with
+ // EFI 1.10 and UEFI 2.10.
+ //
+
+ FvDevicePathNode->Header.Type = MEDIA_DEVICE_PATH;
+ FvDevicePathNode->Header.SubType = MEDIA_FV_FILEPATH_DP;
+ SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
+
+ MemCpy (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmDisplayDiscoveredNotDispatched
+//
+// Description: Display to debug output drivers discovered, but not loaded.
+//
+// Input: VOID
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmDisplayDiscoveredNotDispatched(VOID)
+{
+ LIST_ENTRY *Link;
+ EFI_SMM_DRIVER_ENTRY *DriverEntry;
+
+ for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->Dependent) {
+ TRACE ((-1, "SMM Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: FvHasBeenProcessed
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN FvHasBeenProcessed (IN EFI_HANDLE FvHandle)
+{
+ LIST_ENTRY *Link;
+ KNOWN_HANDLE *KnownHandle;
+
+ for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
+ KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
+ if (KnownHandle->Handle == FvHandle) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: FvIsBeingProcesssed
+//
+// Description: This firmware volume is marked as being processed.
+//
+// Input: IN EFI_HANDLE FvHandle
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID FvIsBeingProcesssed(IN EFI_HANDLE FvHandle)
+{
+ KNOWN_HANDLE *KnownHandle;
+
+ KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));
+ ASSERT (KnownHandle != NULL);
+
+ KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
+ KnownHandle->Handle = FvHandle;
+ InsertTailList (&mFvHandleList, &KnownHandle->Link);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmFvToDevicePath
+//
+// Description: Create device path for Driver.
+//
+// Input:
+// IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv
+// IN EFI_HANDLE FvHandle
+// IN EFI_GUID *DriverName
+//
+// Output: EFI_DEVICE_PATH_PROTOCOL *
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_DEVICE_PATH_PROTOCOL * SmmFvToDevicePath (
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+)
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *FileNameDevicePath;
+
+ //
+ // Remember the device path of the FV
+ //
+ Status = pBS->HandleProtocol(FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
+ if (EFI_ERROR (Status)) {
+ FileNameDevicePath = NULL;
+ } else {
+ //
+ // Build a device path to the file in the FV to pass into gBS->LoadImage
+ //
+ EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
+ SetDevicePathEndNode (&mFvDevicePath.End);
+
+ //
+ // Note: FileNameDevicePath is in DXE memory
+ //
+ FileNameDevicePath = DPAdd (
+ FvDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
+ );
+ }
+ return FileNameDevicePath;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmPreProcessDepex
+//
+// Description: Check driver dependencies for SOR, BEFORE, or AFTER, and update DriverEntry.
+//
+// Input: IN OUT EFI_SMM_DRIVER_ENTRY *DriverEntry
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmPreProcessDepex (
+ IN OUT EFI_SMM_DRIVER_ENTRY *DriverEntry
+)
+{
+ UINT8 *Iterator;
+
+ Iterator = DriverEntry->Depex;
+ if (*Iterator == EFI_DEP_SOR) {
+ DriverEntry->Unrequested = TRUE;
+ } else {
+ DriverEntry->Dependent = TRUE;
+ }
+
+ if (*Iterator == EFI_DEP_BEFORE) {
+ DriverEntry->Before = TRUE;
+ } else if (*Iterator == EFI_DEP_AFTER) {
+ DriverEntry->After = TRUE;
+ }
+
+ if (DriverEntry->Before || DriverEntry->After) {
+ MemCpy (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GUID));
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmGetDepexSectionAndPreProccess
+//
+// Description: Get driver depex section.
+//
+// Input: IN OUT EFI_SMM_DRIVER_ENTRY *DriverEntry
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmGetDepexSectionAndPreProccess (
+ IN OUT EFI_SMM_DRIVER_ENTRY *DriverEntry
+)
+{
+ EFI_STATUS Status;
+ EFI_SECTION_TYPE SectionType;
+ UINT32 AuthenticationStatus;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+
+ Fv = DriverEntry->Fv;
+
+ //
+ // Grab Depex info, it will never be free'ed.
+ // (Note: DriverEntry->Depex is in DXE memory)
+ //
+ SectionType = EFI_SECTION_SMM_DEPEX;
+ Status = Fv->ReadSection (
+ DriverEntry->Fv,
+ &DriverEntry->FileName,
+ SectionType,
+ 0,
+ &DriverEntry->Depex,
+ (UINTN *)&DriverEntry->DepexSize,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_PROTOCOL_ERROR) {
+ //
+ // The section extraction protocol failed so set protocol error flag
+ //
+ DriverEntry->DepexProtocolError = TRUE;
+ } else {
+ //
+ // If no Depex assume depend on all architectural protocols
+ //
+ DriverEntry->Depex = NULL;
+ DriverEntry->Dependent = TRUE;
+ DriverEntry->DepexProtocolError = FALSE;
+ }
+ } else {
+ //
+ // Set Before, After, and Unrequested state information based on Depex
+ // Driver will be put in Dependent or Unrequested state
+ //
+ SmmPreProcessDepex (DriverEntry);
+ DriverEntry->DepexProtocolError = FALSE;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmAddToDriverList
+//
+// Description: Add Driver to database for processing.
+//
+// Input:
+// IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv
+// IN EFI_HANDLE FvHandle
+// IN EFI_GUID *DriverName
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmAddToDriverList (
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+)
+{
+ EFI_SMM_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Create the Driver Entry for the list. ZeroPool initializes lots of variables to
+ // NULL or FALSE.
+ //
+ DriverEntry = MallocZ(sizeof (EFI_SMM_DRIVER_ENTRY));
+ ASSERT (DriverEntry != NULL);
+
+ DriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;
+ MemCpy(&DriverEntry->FileName, DriverName, sizeof(EFI_GUID));
+ DriverEntry->FvHandle = FvHandle;
+ DriverEntry->Fv = Fv;
+ DriverEntry->FvFileDevicePath = SmmFvToDevicePath (Fv, FvHandle, DriverName);
+
+ SmmGetDepexSectionAndPreProccess (DriverEntry);
+
+ InsertTailList (&mDiscoveredList, &DriverEntry->Link);
+ gRequestDispatch = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmLoadImage
+//
+// Description: Load driver into memory and give control.
+//
+// Input: IN OUT EFI_SMM_DRIVER_ENTRY *DriverEntry
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI SmmLoadImage (
+ IN OUT EFI_SMM_DRIVER_ENTRY *DriverEntry
+)
+{
+ UINT32 AuthenticationStatus;
+ VOID *Buffer;
+ UINTN Size;
+ //UINTN PageCount;
+ EFI_GUID *NameGuid;
+ EFI_STATUS Status;
+ //EFI_HANDLE DeviceHandle;
+ //EFI_PHYSICAL_ADDRESS DstBuffer;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ //PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ Buffer = NULL;
+ Size = 0;
+ Fv = DriverEntry->Fv;
+ NameGuid = &DriverEntry->FileName;
+ FilePath = DriverEntry->FvFileDevicePath;
+
+ AuthenticationStatus = 0;
+
+ //
+ // Try reading PE32 section firstly
+ //
+ Status = Fv->ReadSection (
+ Fv,
+ NameGuid,
+ EFI_SECTION_PE32,
+ 0,
+ &Buffer,
+ &Size,
+ &AuthenticationStatus
+ );
+
+/*
+ if (EFI_ERROR (Status)) {
+ //
+ // Try reading TE section secondly
+ //
+ Buffer = NULL;
+ Size = 0;
+ Status = Fv->ReadSection (
+ Fv,
+ NameGuid,
+ EFI_SECTION_TE,
+ 0,
+ &Buffer,
+ &Size,
+ &AuthenticationStatus
+ );
+ }
+*/
+
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = pBS->FreePool (Buffer);
+ }
+ return Status;
+ }
+
+ gRegisterForPi = TRUE;
+ Status=EfiSmmRegister(NULL, FilePath, Buffer, Size,
+ &DriverEntry->ImageHandle, FALSE);
+ gRegisterForPi = FALSE;
+/*
+ //
+ // Initialize ImageContext
+ //
+ ImageContext.Handle = Buffer;
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+
+ //
+ // Get information about the image being loaded
+ //
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ return Status;
+ }
+ //
+ // if Loading module at Fixed Address feature is enabled, then cut out a memory range started from TESG BASE
+ // to hold the Smm driver code
+ //
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
+ //
+ // Get the fixed loading address assigned by Build tool
+ //
+ Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Since the memory range to load Smm core alreay been cut out, so no need to allocate and free this range
+ // following statements is to bypass SmmFreePages
+ //
+ PageCount = 0;
+ DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;
+ } else {
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
+ //
+ // allocate the memory to load the SMM driver
+ //
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
+ DstBuffer = (UINTN)(-1);
+
+ Status = SmmAllocatePages (
+ AllocateMaxAddress,
+ EfiRuntimeServicesCode,
+ PageCount,
+ &DstBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ return Status;
+ }
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
+ }
+ } else {
+ PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
+ DstBuffer = (UINTN)(-1);
+
+ Status = SmmAllocatePages (
+ AllocateMaxAddress,
+ EfiRuntimeServicesCode,
+ PageCount,
+ &DstBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ return Status;
+ }
+
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
+ }
+ //
+ // Align buffer on section boundary
+ //
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+ ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
+
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ SmmFreePages (DstBuffer, PageCount);
+ return Status;
+ }
+
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ SmmFreePages (DstBuffer, PageCount);
+ return Status;
+ }
+
+ //
+ // Flush the instruction cache so the image data are written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN) ImageContext.ImageAddress, (UINTN) ImageContext.ImageSize);
+
+ //
+ // Save Image EntryPoint in DriverEntry
+ //
+ DriverEntry->ImageEntryPoint = ImageContext.EntryPoint;
+ DriverEntry->ImageBuffer = DstBuffer;
+ DriverEntry->NumberOfPage = PageCount;
+
+ //
+ // Allocate a Loaded Image Protocol in EfiBootServicesData
+ //
+ Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&DriverEntry->LoadedImage);
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ SmmFreePages (DstBuffer, PageCount);
+ return Status;
+ }
+
+ //
+ // Fill in the remaining fields of the Loaded Image Protocol instance.
+ // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.
+ //
+ DriverEntry->LoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
+ DriverEntry->LoadedImage->ParentHandle = gThisImageHandle;
+ DriverEntry->LoadedImage->SystemTable = pST;
+ DriverEntry->LoadedImage->DeviceHandle = DeviceHandle;
+
+ //
+ // Make an EfiBootServicesData buffer copy of FilePath
+ //
+ Status = gBS->AllocatePool (EfiBootServicesData, GetDevicePathSize (FilePath), (VOID **)&DriverEntry->LoadedImage->FilePath);
+ if (EFI_ERROR (Status)) {
+ if (Buffer != NULL) {
+ Status = gBS->FreePool (Buffer);
+ }
+ SmmFreePages (DstBuffer, PageCount);
+ return Status;
+ }
+ CopyMem (DriverEntry->LoadedImage->FilePath, FilePath, GetDevicePathSize (FilePath));
+
+ DriverEntry->LoadedImage->ImageBase = (VOID *)(UINTN)DriverEntry->ImageBuffer;
+ DriverEntry->LoadedImage->ImageSize = ImageContext.ImageSize;
+ DriverEntry->LoadedImage->ImageCodeType = EfiRuntimeServicesCode;
+ DriverEntry->LoadedImage->ImageDataType = EfiRuntimeServicesData;
+
+ //
+ // Create a new image handle in the UEFI handle database for the SMM Driver
+ //
+ DriverEntry->ImageHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverEntry->ImageHandle,
+ &gEfiLoadedImageProtocolGuid, DriverEntry->LoadedImage,
+ NULL
+ );
+
+ //
+ // Print the load address and the PDB file name if it is available
+ //
+
+ // DEBUG_CODE_BEGIN ();
+#if EFI_DEBUG
+ {
+ UINTN Index;
+ UINTN StartIndex;
+ CHAR8 EfiFileName[256];
+
+
+ TRACE ((-1,
+ "Loading driver at 0x%11p EntryPoint=0x%11p ",
+ (VOID *)(UINTN) ImageContext.ImageAddress,
+ FUNCTION_ENTRY_POINT (ImageContext.EntryPoint)));
+
+
+ //
+ // Print Module Name by Pdb file path.
+ // Windows and Unix style file path are all trimmed correctly.
+ //
+ if (ImageContext.PdbPointer != NULL) {
+ StartIndex = 0;
+ for (Index = 0; ImageContext.PdbPointer[Index] != 0; Index++) {
+ if ((ImageContext.PdbPointer[Index] == '\\') || (ImageContext.PdbPointer[Index] == '/')) {
+ StartIndex = Index + 1;
+ }
+ }
+ //
+ // Copy the PDB file name to our temporary string, and replace .pdb with .efi
+ // The PDB file name is limited in the range of 0~255.
+ // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
+ //
+ for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
+ EfiFileName[Index] = ImageContext.PdbPointer[Index + StartIndex];
+ if (EfiFileName[Index] == 0) {
+ EfiFileName[Index] = '.';
+ }
+ if (EfiFileName[Index] == '.') {
+ EfiFileName[Index + 1] = 'e';
+ EfiFileName[Index + 2] = 'f';
+ EfiFileName[Index + 3] = 'i';
+ EfiFileName[Index + 4] = 0;
+ break;
+ }
+ }
+
+ if (Index == sizeof (EfiFileName) - 4) {
+ EfiFileName[Index] = 0;
+ }
+ TRACE ((-1, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
+ }
+ TRACE ((-1, "\n"));
+ }
+// DEBUG_CODE_END ();
+#endif
+
+ //
+ // Free buffer allocated by Fv->ReadSection.
+ //
+ // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection
+ // used the UEFI Boot Services AllocatePool() function
+ //
+*/
+ Status = pBS->FreePool(Buffer);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter
+//
+// Description: Add drivers on queue with before or after dependencies.
+//
+// Input: IN EFI_SMM_DRIVER_ENTRY *InsertedDriverEntry
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
+ IN EFI_SMM_DRIVER_ENTRY *InsertedDriverEntry
+)
+{
+ LIST_ENTRY *Link;
+ EFI_SMM_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Process Before Dependency
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->Before && DriverEntry->Dependent) {
+ if (! guidcmp (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
+ //
+ // Recursively process BEFORE
+ //
+ SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ }
+ }
+ }
+
+ //
+ // Convert driver from Dependent to Scheduled state
+ //
+
+ InsertedDriverEntry->Dependent = FALSE;
+ InsertedDriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);
+
+ //
+ // Process After Dependency
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->After && DriverEntry->Dependent) {
+ if (!guidcmp (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
+ //
+ // Recursively process AFTER
+ //
+ SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ }
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmDispatcher
+//
+// Description: Dispatch drivers that dependencies are met.
+//
+// Input: VOID
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmDispatcher(VOID)
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ LIST_ENTRY *Link;
+ EFI_SMM_DRIVER_ENTRY *DriverEntry;
+ BOOLEAN ReadyToRun;
+
+ if (!gRequestDispatch) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (gDispatcherRunning) {
+ //
+ // If the dispatcher is running don't let it be restarted.
+ //
+ return EFI_ALREADY_STARTED;
+ }
+
+ gDispatcherRunning = TRUE;
+ ReturnStatus = EFI_NOT_FOUND;
+
+ do {
+ //
+ // Drain the Scheduled Queue
+ //
+ while (!IsListEmpty (&mScheduledQueue)) {
+ DriverEntry = CR (
+ mScheduledQueue.ForwardLink,
+ EFI_SMM_DRIVER_ENTRY,
+ ScheduledLink,
+ EFI_SMM_DRIVER_ENTRY_SIGNATURE
+ );
+
+ //
+ // Load the SMM Driver image into memory. If the Driver was transitioned from
+ // Untrusted to Scheduled it would have already been loaded so we may need to
+ // skip the LoadImage
+ //
+ if (DriverEntry->ImageHandle == NULL) {
+ Status = SmmLoadImage (DriverEntry);
+
+ //
+ // Update the driver state to reflect that it's been loaded
+ //
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_SECURITY_VIOLATION) {
+ //
+ // Take driver from Scheduled to Untrusted state
+ //
+ DriverEntry->Untrusted = TRUE;
+ } else {
+ //
+ // The SMM Driver could not be loaded, and do not attempt to load or start it again.
+ // Take driver from Scheduled to Initialized.
+ //
+ // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
+ //
+ DriverEntry->Initialized = TRUE;
+ }
+
+ DriverEntry->Scheduled = FALSE;
+ RemoveEntryList (&DriverEntry->ScheduledLink);
+
+ //
+ // If it's an error don't try the StartImage
+ //
+ continue;
+ }
+ }
+
+ DriverEntry->Scheduled = FALSE;
+ DriverEntry->Initialized = TRUE;
+ RemoveEntryList (&DriverEntry->ScheduledLink);
+/*
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_SMM_DRIVER | EFI_SW_PC_INIT_BEGIN,
+ &DriverEntry->ImageHandle,
+ sizeof(DriverEntry->ImageHandle)
+ );
+
+ //
+ // For each SMM driver, pass NULL as ImageHandle
+ //
+ Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, pST);
+ if (EFI_ERROR(Status)){
+ SmmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
+ }
+
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_SMM_DRIVER | EFI_SW_PC_INIT_END,
+ &DriverEntry->ImageHandle,
+ sizeof(DriverEntry->ImageHandle)
+ );
+*/
+ ReturnStatus = EFI_SUCCESS;
+ }
+
+ //
+ // Search DriverList for items to place on Scheduled Queue
+ //
+ ReadyToRun = FALSE;
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
+
+ if (DriverEntry->DepexProtocolError){
+ //
+ // If Section Extraction Protocol did not let the Depex be read before retry the read
+ //
+ Status = SmmGetDepexSectionAndPreProccess (DriverEntry);
+ }
+
+ if (DriverEntry->Dependent) {
+ if (SmmIsSchedulable (DriverEntry)) {
+ SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ ReadyToRun = TRUE;
+ }
+ }
+ }
+ } while (ReadyToRun);
+
+ //
+ // If there is no more SMM driver to dispatch, stop the dispatch request
+ //
+ gRequestDispatch = FALSE;
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
+
+ if (!DriverEntry->Initialized){
+ //
+ // We have SMM driver pending to dispatch
+ //
+ gRequestDispatch = TRUE;
+ break;
+ }
+ }
+
+ gDispatcherRunning = FALSE;
+
+ return ReturnStatus;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmDriverDispatchHandler
+//
+// Description: Dispatch SMM drivers
+//
+// Input: VOID
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmDriverDispatchHandler ()
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ EFI_STATUS GetNextFileStatus;
+ EFI_STATUS SecurityStatus;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
+ EFI_HANDLE FvHandle;
+ EFI_GUID NameGuid;
+ UINTN Key;
+ EFI_FV_FILETYPE Type;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ EFI_SMM_DRIVER_ENTRY *DriverEntry;
+ EFI_GUID *AprioriFile;
+ UINTN AprioriEntryCount;
+ UINTN Index;
+ LIST_ENTRY *Link;
+ UINT32 AuthenticationStatus;
+ UINTN SizeOfBuffer;
+
+ HandleBuffer = NULL;
+ Status = pBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) return; //return EFI_NOT_FOUND;
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ FvHandle = HandleBuffer[Index];
+
+ if (FvHasBeenProcessed (FvHandle)) {
+ //
+ // This Fv has already been processed so lets skip it!
+ //
+ continue;
+ }
+
+ //
+ // Since we are about to process this Fv mark it as processed.
+ //
+ FvIsBeingProcesssed (FvHandle);
+
+ Status = pBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
+ if (EFI_ERROR (Status)) {
+ //
+ // FvHandle must have a Firmware Volume2 Protocol thus we should never get here.
+ //
+ ASSERT (FALSE);
+ continue;
+ }
+
+ Status = pBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
+ if (EFI_ERROR (Status)) {
+ //
+ // The Firmware volume doesn't have device path, can't be dispatched.
+ //
+ continue;
+ }
+
+ //
+ // If the Security Architectural Protocol has not been located yet, then attempt to locate it
+ //
+ if (mSecurity == NULL) {
+ pBS->LocateProtocol (&gEfiSecurityArchProtocolGuid, NULL, (VOID**)&mSecurity);
+ }
+
+ //
+ // Evaluate the authentication status of the Firmware Volume through
+ // Security Architectural Protocol
+ //
+ if (mSecurity != NULL) {
+ SecurityStatus = mSecurity->FileAuthenticationState (
+ mSecurity,
+ 0,
+ FvDevicePath
+ );
+ if (SecurityStatus != EFI_SUCCESS) {
+ //
+ // Security check failed. The firmware volume should not be used for any purpose.
+ //
+ continue;
+ }
+ }
+
+ //
+ // Discover Drivers in FV and add them to the Discovered Driver List.
+ // Process EFI_FV_FILETYPE_SMM type and then EFI_FV_FILETYPE_COMBINED_SMM_DXE
+ //
+ for (Index = 0; Index < sizeof (mSmmFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {
+ //
+ // Initialize the search key
+ //
+ Key = 0;
+ do {
+ Type = mSmmFileTypes[Index];
+ GetNextFileStatus = Fv->GetNextFile (
+ Fv,
+ &Key,
+ &Type,
+ &NameGuid,
+ &Attributes,
+ &Size
+ );
+ if (!EFI_ERROR (GetNextFileStatus)) {
+ SmmAddToDriverList (Fv, FvHandle, &NameGuid);
+ }
+ } while (!EFI_ERROR (GetNextFileStatus));
+ }
+
+ //
+ // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
+ // (Note: AprioriFile is in DXE memory)
+ //
+ AprioriFile = NULL;
+ Status = Fv->ReadSection (
+ Fv,
+ &gAprioriGuid,
+ EFI_SECTION_RAW,
+ 0,
+ (VOID **)&AprioriFile,
+ &SizeOfBuffer,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
+ } else {
+ AprioriEntryCount = 0;
+ }
+
+ //
+ // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
+ // drivers not in the current FV and these must be skipped since the a priori list
+ // is only valid for the FV that it resided in.
+ //
+
+ for (Index = 0; Index < AprioriEntryCount; Index++) {
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
+ if (!guidcmp (&DriverEntry->FileName, &AprioriFile[Index]) &&
+ (FvHandle == DriverEntry->FvHandle)
+ ){
+ DriverEntry->Dependent = FALSE;
+ DriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
+ break;
+ }
+ }
+ }
+
+ //
+ // Free data allocated by Fv->ReadSection ()
+ //
+ // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection
+ // used the UEFI Boot Services AllocatePool() function
+ //
+ pBS->FreePool (AprioriFile);
+ }
+
+ //
+ // Execute the SMM Dispatcher on any newly discovered FVs and previously
+ // discovered SMM drivers that have been discovered but not dispatched.
+ //
+ SmmDispatcher();
+}
+#endif
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmDxeCommunicate.dxs b/Core/EM/SMM/SmmDxeCommunicate.dxs
new file mode 100644
index 0000000..24f46a0
--- /dev/null
+++ b/Core/EM/SMM/SmmDxeCommunicate.dxs
@@ -0,0 +1,69 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmDxeCommunicate.dxs 1 4/18/11 12:03p Markw $
+//
+// $Revision: 1 $
+//
+// $Date: 4/18/11 12:03p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SmmCommunicate/SmmDxeCommunicate.dxs $
+//
+// 1 4/18/11 12:03p Markw
+// [TAG] EIP57440
+// [Category] New Feature
+// [Description] Add SMM PI 1.1 Communicate Support.
+// [Files] SmmCommunicate.cif
+// SmmCommunicate.sdl
+// SmmCommunicate.c
+// SmmCommunicate.dxs
+// SmmDxeCommunicate.dxs
+// SmmCommunicate.mak
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmCommunicate.dxs
+//
+// Description: Dependency file for the SMM Communicate driver
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <Protocol\SmmBase2.h>
+#include <Protocol\AmiInternalSmmComm.h>
+
+DEPENDENCY_START
+ EFI_SMM_BASE2_PROTOCOL_GUID AND
+ AMI_INT_SMM_COMM_PROTOCOL_GUID
+DEPENDENCY_END
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmEntry.asm b/Core/EM/SMM/SmmEntry.asm
new file mode 100644
index 0000000..883d1c6
--- /dev/null
+++ b/Core/EM/SMM/SmmEntry.asm
@@ -0,0 +1,1041 @@
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2008, 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/SmmEntry.asm 2 10/31/12 10:26a Wesleychen $
+;
+; $Revision: 2 $
+;
+; $Date: 10/31/12 10:26a $
+;**********************************************************************
+; Revision History
+; ----------------
+; $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/SMM/SmmEntry.asm $
+;
+; 2 10/31/12 10:26a Wesleychen
+; Update SMM to 4.6.3_SMM_46.
+;
+; 1 10/22/12 7:08a Wesleychen
+; Support Intel PFAT.
+;
+; 58 4/01/11 10:33a 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, SmmEntry.asm
+;
+; 57 11/23/09 11:20a Markw
+; Update fxsave and fxrstor for 64-bit.
+;
+; 56 8/11/09 11:49a Markw
+; Removed Legacy registration. This is removed from latest PI and not
+; used by projects. Also, update clearing upper 32-bits of 64-bit
+; registers.
+;
+; 55 7/08/09 8:13p Markw
+; Update headers.
+;
+; 54 5/12/09 7:02p Markw
+; EIP #22087 - Always reinialize IDT in SMM even with AMI Debugger. Some
+; processors place junk value in IDT.
+;
+; 53 12/23/08 2:18p Markw
+; EIP #17900 Set up TSS. Borland C in DOS hangs otherwise.
+;
+; 52 11/21/08 4:57p Markw
+; Add SmmInit into SMM_ENTRY_STRUCT.
+;
+; 51 9/07/08 12:51a Markw
+;
+; 50 9/07/08 12:43a Markw
+; Separate SMM Private structure into inside SMM and outside SMM
+; structure.
+;
+; 49 8/27/08 9:05p Markw
+; Nehalem SMRR is now WB. Fix SMM Thunk Stack bug.
+;
+; 48 5/23/08 11:14a Markw
+; Don't load idt if AMI Debugger. Debugger won't work in SMM if idt is
+; reloaded.
+;
+; 47 4/04/08 6:22p Markw
+; User Smm Msr from SMM_BASE_PRIVATE_STRUCT instead of token.
+;
+; 46 3/03/08 6:36p Markw
+; Added 32-bit register for smm thunk.
+;
+; 45 1/07/08 1:58p Markw
+; For SMM thunk, read cs in 16-bit real mode instead of undefined CPU
+; execution between real and protected mode.
+; cs was invalid when read.
+;
+; 44 11/26/07 6:00p Markw
+; Fix bug in previous bug fix.
+;
+; 43 11/26/07 5:51p Markw
+; Fix smm thunk bug - store return address.
+;
+; 42 11/21/07 3:38p Markw
+; Update checking MKF_SMM_THUNK_IN_CSM condition from 1 to -1.
+;
+; 41 11/14/07 2:02p Markw
+; Added SMRR support and updated SMM Cache for non-SMRR.
+;
+; 40 10/29/07 3:24p Markw
+;
+; 39 10/29/07 10:58a Markw
+; Smm Thunk:
+; * Code and data different segments.
+; * Code position independent.
+; * Switch for CSM for code and EBDA for data.
+;
+; 38 10/24/07 12:02p Markw
+; SMM Thunk code position independent. Data in a separate segment than
+; code in Smm Thunk.
+; Combined BSP and AP SmmEntry.
+;
+; 37 9/10/07 1:39p Markw
+; Add Interrupt Handling in SMM.
+;
+; 36 6/14/07 10:54a Markw
+; In SmmThunk, jump condition is incorrect. pushf wasn't occurring before
+; iret call.
+;
+; 35 6/08/07 6:51p Markw
+; Save/Restore XMM.
+;
+; 34 4/13/07 11:04a Markw
+; Update header.
+;
+; 33 3/22/07 5:37p Markw
+; Set stack before calling legacy_handler.
+;
+; 32 3/12/07 11:24a Markw
+; Enable XMM for 32-bit. Guarantee 16-byte stack alignment.
+;
+; 31 3/06/07 10:40a Markw
+; Fix legacy handler calling entry point.
+;
+; 30 2/08/07 10:49a Markw
+; Preserve stack on legacy_handler.
+;
+; 29 1/11/07 12:31p Markw
+; Use switch to enable/disable legacy code during build.
+;
+; 28 1/10/07 2:12p Markw
+; Move legacy only code to end. Otherwise, if 64-bit BSP entry in TSEG,
+; APs will overlap part of smm bsp entry code.
+;
+; 27 1/09/07 6:47p Markw
+; Store fixup addresses in SmmEntry for locations that have to fixed-up
+; during BIOS.
+;
+; 26 1/09/07 11:47a Markw
+; Removed using MKF_SMM_BSP_BASE in memory access and segment changes.
+; Uses indexing or retf.
+;
+; 25 12/29/06 4:46p Markw
+; Update CPU syncronization.
+;
+; 24 12/11/06 5:53p Markw
+; Commented out initializing the flags because of potentional errors, and
+; using flags as input would be unusual.
+;
+; 23 11/13/06 7:15p Markw
+; Combine more common code between 32 and 64 bit.
+;
+; 22 11/10/06 3:18p Markw
+; Combined x32 and x64 where it is the same.
+;
+; 21 10/17/06 11:23a Davidd
+; Change made to not setting the Page Global Enable bit in CR4 to correct
+; the system reset problem when installing / booting Vista 32.
+;
+; 20 9/22/06 6:07p Markw
+; In 32-bit fix stack after calling dispatcher.
+;
+; 19 9/18/06 3:21p Markw
+; Updated 32 bit part for BSP an AP sync.
+;
+; 18 9/18/06 11:44a Markw
+; Add a check to guarentee that BSP and Ap can't get out of sync. Also
+; clear WT bit in cr0 in 64-bit.
+;
+; 17 8/25/06 10:49a Markw
+; Enable XMM for 64-bit.
+;
+; 16 8/24/06 3:28p Felixp
+; Preliminary x64 support (work in progress)
+;
+; 15 4/20/06 1:50p Markw
+; Fixed SmmThunk to use token for BSP SMM Base.
+; For SmmThunk calls that don't pass arguments on stack, added 3f to
+; emulate INT calls.
+;
+; 14 2/03/06 10:27a Markw
+; Moved Smm Base change to PEI CPU.
+; Added a token for SMM BSP Base Address.
+; Added IED support.
+;
+; 13 1/13/06 11:28a Markw
+; Added SMM Thunk support.
+;
+; 12 1/10/06 2:57p Markw
+; Add support for multi-threadding and sync all CPUs during entry/exit of
+; SMM.
+;
+; 11 11/03/05 5:35p Markw
+; Added entries to GDT for addional descriptors that Intel uses.
+;
+; 10 7/21/05 11:28a Srinin
+; Fixed Legacy SMI handler support.
+;
+; 8 7/19/05 8:00p Markw
+; Add support for calling real mode handlers.
+;
+; 7 7/12/05 3:14p Markw
+; Moved BSP entry from 0xa8000 to 0xa0000.
+;
+; 6 7/11/05 12:04p Markw
+; Removed setting isCallback. This simplified the dispatcher.
+;
+; 5 7/06/05 2:15p Markw
+; Commented out unused code.
+;
+; 4 4/07/05 4:05p Sivagarn
+; Corrected the make token issue
+;
+; 3 4/04/05 5:18p Sivagarn
+; Converted hard coded S/W SMI port to generic SDL token
+;
+; 1 1/28/05 4:32p Sivagarn
+; SMM Dispatcher Component - Initial check in
+;
+;
+;**********************************************************************
+
+;<AMI_FHDR_START>
+;----------------------------------------------------------------------------
+;
+; Name: SmmEntry.ASM
+;
+; Description: File that contains the code for BSP SMM entry point
+;
+;----------------------------------------------------------------------------
+;<AMI_FHDR_END>
+
+.586p
+.model small
+.xmm
+
+include token.equ
+include SmmHdr.equ
+
+IFNDEF MKF_SMM_THUNK_IN_CSM
+MKF_SMM_THUNK_IN_CSM EQU 0
+ENDIF
+
+IFNDEF MKF_AMI_DEBUGGER_SUPPORT
+MKF_AMI_DEBUGGER_SUPPORT EQU 0
+ENDIF
+
+IA32_HANDLER_LIST STRUCT
+ Entry dd ?
+ Link dd ?
+IA32_HANDLER_LIST ENDS
+
+;org 8000h
+SMM SEGMENT USE16
+
+;<AMI_PHDR_START>
+;----------------------------------------------------------------------------
+;
+; Procedure: SmmEntry
+;
+; Description: Call any Legacy Handlers and call 32 bit protected Mode Dispatcher.
+;
+; Input: None
+;
+; Output: None
+;
+;----------------------------------------------------------------------------
+;<AMI_PHDR_END>
+
+;To make assembler happy.
+; SmmThunkData will have an address of 0, but a different segment.
+SmmThunkData equ $
+SmmEntry:
+ jmp SmmStart
+align 4
+SmmEntryData label dword
+ SmmEntryInit SMM_ENTRY_INIT_STRUCT < \
+ 1, \
+ SmmEntryEnd - SmmEntry, \
+ GDT_DESC_FIXUP - SmmEntry, \
+ L_CODE_SEL_FIXUP - SmmEntry, \
+ TSS_SEL_FIXUP - SmmEntry, \
+ THUNK - SmmEntry, \
+ SmmThunkEnd - THUNK, \
+ -1 \
+ >
+SmmStart:
+;Note use cs override on data access. This code may be executed above 1MB.
+ mov ax, cs
+ mov ds, ax
+ mov ss, ax
+ cld
+
+IF MKF_SMM_CACHE_SUPPORT
+IFNDEF MKF_NEHALEM_CPU_MODULE
+ ; *************** CACHE ENABLE **************
+;-----------
+;HT support
+;-----------
+ ;TODO: Move HT detection to SMM Base and out of SMM entry.
+
+ mov eax, -1
+ cmp cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).Ht0, eax
+ jne ht0_flag_is_init
+
+ mov eax, 1 ;default true
+ mov cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).Ht0, eax
+
+ mov eax, 1
+ cpuid
+ test edx, 1 SHL 28 ;Set if hyper-threading support.
+ jz ht0_flag_is_init
+ shr ebx, 16 ;After shift, bl = number of logical processors
+ movzx esi, bl ;Store # local processors.
+
+ mov eax, 4
+ xor ecx, ecx
+ cpuid
+ shr eax, 26
+ inc eax ;Number of Cores.
+
+ xor edx, edx ;clear for div.
+ xchg esi, eax ;esi = NumCores, eax = num #logical CPUS
+ div esi ;#logical CPUs / NumCores
+ cmp eax, 1
+ jle ht0_flag_is_init
+
+ mov ebx, MKF_LOCAL_APIC_BASE + MKF_APIC_ID_REGISTER
+ mov eax, es:[ebx]
+ bt eax, 24
+ jnc ht0_flag_is_init
+ xor eax, eax ;This not Ht0 flag, so clear.
+ mov cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).Ht0, eax
+ht0_flag_is_init:
+
+ mov esi, dword ptr cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).SmmDispatcherPrivateStruct
+
+ mov eax, cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).Ht0
+ or eax, eax
+ jz cache_enable_end ;skip if HT
+
+ mov al, 1
+ cmp es:(SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).SmrrEnable, al
+ jne non_smrr_cache
+ ;Disable SMRR.
+ mov ecx, es:(SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).SmrrMsr
+ inc ecx
+ rdmsr
+ btr ax, 11 ;Disable UC SMRR. This makes the region WT by overlapping MTRR.
+ wrmsr
+ jmp cache_enable_end
+
+non_smrr_cache:
+ mov ecx, es:(SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).TsegMsr
+ or ecx, ecx
+ jz cache_enable_end ;Not enough/or moved MTRR to support cache.
+
+ rdmsr
+ cmp eax, dword ptr es:(SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).TsegMsrBase
+ je @f
+ ;---Disable future cache. Validation failed.
+ xor ecx, ecx
+ mov es:(SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).TsegMsr, ecx
+ jmp cache_enable_end
+@@:
+ mov al, 4
+ wrmsr ;Make MTRR WT.
+;-----------------
+cache_enable_end:
+; ************** END CACHE ENABLE *************
+ENDIF
+ENDIF
+
+IFDEF MKF_PfatServices_SUPPORT
+IF MKF_PfatServices_SUPPORT
+ mov eax, cr0
+ or al, 20h ;Set NE bit
+ mov cr0, eax
+ENDIF
+ENDIF
+
+ mov esi, dword ptr cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).SmmDispatcherPrivateStruct
+ mov edi, dword ptr cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).SmmEntryStart
+ mov ebx, dword ptr cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).SmmDispatcherAddr
+ mov edx, dword ptr cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).CpuNo
+
+ mov byte ptr cs:TSS_SEL_FIXUP + 8000h + 3, 89h
+
+ ;Switch to protected mode
+ db 66h
+ lgdt fword ptr cs:GdtDescriptor + 8000h
+ mov eax, cr0
+ or al, 1 ;Set PE bit
+ mov cr0, eax ;Turn on Protected Mode
+
+ ;In 16 bit protected mode
+ jmp $+2 ;Clear prefetch queue
+
+ mov ax, DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ xor ax, ax
+ lldt ax
+
+ str ax
+ or ax, ax
+ jz @f
+ mov ax,TSS_SEL
+ ltr ax
+@@:
+
+ ;Stack starts near bottom of Smm TSEG after BSP/AP entries
+ mov esp, dword ptr cs:(SMM_ENTRY_INIT_STRUCT ptr [SmmEntryInit + 8000h]).SmmStack
+ and esp, 0fffffff0h ;guarentee 16-byte stack.
+
+ ;set cs segment
+ lea eax, [edi + offset P32Mode]
+ pushd CODE32_SEL
+ push eax
+ db 66h
+ retf
+P32Mode::
+ mov eax, cr4
+ ;or eax, 0620h ;Enable XMM.
+ db 0dh
+ dd 0600h
+ mov cr4, eax
+
+ ;mov eax, dword ptr (SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).SmmXmmSave
+ db 8bh, 46h, SMM_DISPATCHER_PRIVATE_STRUCT.SmmXmmSave
+IFNDEF EFIx64
+ ;mov edx, [eax + 4 * edx]
+ db 8bh, 14h, 90h
+ELSE
+ ;mov edx, [eax + 8 * edx]
+ db 8bh, 14h, 0d0h
+ENDIF
+
+IFNDEF EFIx64
+ ;lidt fword ptr (SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).Idt
+ db 0fh, 1, 5eh
+ db SMM_DISPATCHER_PRIVATE_STRUCT.IDT
+
+ ;fxsave [edx]
+ db 0fh, 0aeh, 2
+ push dx ;push edx
+ sub sp, 12 ;sub esp, 12 -- make stack 16 byte aligned
+ ;Call Dispatcher
+
+ add di, 4 ;edi = SmmEntryInit
+ push di ;push edi ;Optimization will modify this stack location.
+ call bx ;call ebx ;SmmDispatcherAddr
+ add sp, 12 + 4 ;add esp, 12 + 4
+ pop dx ;pop edx
+ ;fxrstor [edx]
+ db 0fh, 0aeh, 0ah
+ELSE
+ push dx ;push edx This is read later directly from [esp]
+
+ ;mov eax, dword ptr (SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).PageDirectories
+ db 8bh, 86h
+ dd SMM_DISPATCHER_PRIVATE_STRUCT.PageDirectories
+ mov cr3, eax ;Set CR3 to first page directory pointer table
+
+ mov eax, cr4
+ or al, 20h ;Enable PAE.
+ mov cr4, eax
+
+ ;Enable long mode in msr register. Doesn't actually enter long mode yet.
+
+ ;mov ecx, 0c0000080h
+ db 0b9h
+ dd 0C0000080h
+ rdmsr
+ ;bts eax, 8
+ db 0Fh, 0BAh, 0E8h, 08h
+ wrmsr
+
+ ;Enable paging
+ mov eax, cr0
+ ;bts eax, 31
+ db 0Fh, 0BAh, 0E8h, 1fh
+ ;btr eax, 16 ;Clear WT bit. This affects paging.
+ db 0fh, 0bah, 0f0h, 10h
+ mov cr0, eax ;Now in long mode compatiblity.
+ jmp @f
+@@:
+
+ ;set cs segment
+ ;lea eax, [edi + offset long_mode_64]
+ db 8dh, 87h
+ dd offset long_mode_64
+ ;push CODE64_SEL
+ db 68h
+ dd CODE64_SEL
+ push ax ;push eax
+ retf
+
+long_mode_64:
+ ;in 64-bit long mode
+
+ ;mov rax, 0ffffffffh
+ db 48h, 0b8h
+ dq 0ffffffffh
+
+ db 48h
+ and bx, ax ;and rbx, rax
+ db 48h
+ and dx, ax ;and rdx, rax
+ db 48h
+ and si, ax ;and rsi, rax
+ db 48h
+ and di, ax ;and rdi, rax
+ db 48h
+ and sp, ax ;and esp, rax
+
+ ;mov edx, [rsp]
+ db 8bh, 14h, 24h
+ ;fxsave [rdx]
+ db 48h, 0fh, 0aeh, 2
+
+ ;align stack by 16-bytes, sub 0ch and reserve stack for caller.
+ sub sp, 0ch + 20h ;sub esp, 12 + 20
+
+ ;Call Dispatcher
+
+ ;lidt fword ptr (SMM_DISPATCHER_PRIVATE_STRUCT ptr [rsi]).Idt
+ db 0fh, 1, 5eh
+ db SMM_DISPATCHER_PRIVATE_STRUCT.IDT
+
+ add di, 4 ;di = SmmEntryInit
+
+ db 48h
+ mov cx, di ;mov rcx, rdi
+
+ call bx ;call rbx
+
+ ;restore stack
+ add sp, 0ch + 20h
+
+ ;mov edx, [rsp]
+ db 8bh, 14h, 24h
+
+ ;fxrstor [rdx]
+ db 48h, 0fh, 0aeh, 0ah
+
+ ;lea rax, [@f];
+ db 48h, 8Dh, 05
+ dd offset @f - $ - 4
+ ;push CODE32_SEL
+ db 68h
+ dd CODE32_SEL
+ db 48h
+ push ax ;push rax
+ db 48h
+ retf ;retq ;switch to compatibility mode.
+@@:
+ pop dx ;pop edx
+endif
+;---We are in 32-bit protected or 32-bit compatibility mode.---
+;C calls preserve ESI, EDI, EBX, and EBP.
+;esi = SMM_DISPATCHER_PRIVATE_STRUCT
+;edi = SMM_ENTRY_INIT_STRUCT
+
+IFDEF MKF_PfatServices_SUPPORT
+IF MKF_PfatServices_SUPPORT
+ mov eax, cr0
+ and al, 0DFh ;Clear NE bit
+ mov cr0, eax
+ENDIF
+ENDIF
+
+IF MKF_SMM_CACHE_SUPPORT
+IFNDEF MKF_NEHALEM_CPU_MODULE
+; **************** CACHE DISABLE ****************
+ ;mov al, byte ptr (SMM_ENTRY_INIT_STRUCT ptr [edi]).Ht0
+ db 8Ah, 47h
+ db SMM_ENTRY_INIT_STRUCT.Ht0
+ or al, al ;or al, al
+ jz cache_disable_end ;skip if HT
+
+ mov al, 1
+ ;cmp (SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).SmrrEnable, al
+ db 38h, 46h
+ db SMM_DISPATCHER_PRIVATE_STRUCT.SmrrEnable
+ jne non_smrr_cache2
+ ;Disable SMRR.
+
+ ;mov ecx, (SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).SmrrMsr
+ db 08bh, 4eh
+ db SMM_DISPATCHER_PRIVATE_STRUCT.SmrrMsr
+ inc cx ;inc ecx
+
+ rdmsr
+ bts eax, 11 ;Disable UC SMRR. This makes the region WT by overlapping MTRR.
+ wrmsr
+ jmp cache_disable_end
+
+non_smrr_cache2:
+ ;mov ecx, (SMM_DISPATCHER_PRIVATE_STRUCT ptr [esi]).TsegMsr
+ db 8bh, 4eh
+ db SMM_DISPATCHER_PRIVATE_STRUCT.TsegMsr
+ or cx, cx ;or ecx, ecx
+ jz cache_disable_end ;Not enough/or moved MTRR to support cache.
+
+ rdmsr
+ xor al, al
+ wrmsr ;Make MTRR UC
+;-----------------
+cache_disable_end:
+; ************** END OF CACHE DISABLE ************
+ENDIF
+ENDIF
+ rsm
+
+align 16
+GDT_BASE:
+NULL_SEL equ $-GDT_BASE ;NULL Selector 0
+ dd 0, 0
+
+DATA_SEL equ $-GDT_BASE ; Selector 8, Data 0-ffffffff 32 bit
+ dd 0000ffffh
+ dd 00cf9300h
+
+CODE32_SEL equ $-GDT_BASE ; Selector 10h, CODE 0-ffffffff 32 bit
+ dd 0000ffffh
+ dd 00cf9b00h
+
+; We only need this because Intel DebugSupport driver
+; (RegisterPeriodicCallback function) assumes that selector 0x20 is valid
+; The funciton sets 0x20 as a code selector in IDT
+;
+; System data segment descriptor
+;
+SYS_DATA_SEL equ $ - GDT_BASE ; Selector [0x18]
+ dd 0000FFFFh ;0 - f_ffff
+ dd 00cf9300h ;data, expand-up, notwritable, 32-bit
+
+; System code segment descriptor
+SYS_CODE_SEL equ $ - GDT_BASE ; Selector [0x20]
+ dd 0000FFFFh ;0 - f_ffff
+ dd 00cf9b00h ;data, expand-up, writable, 32-bit
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dd 0, 0
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dd 0000FFFFh
+ dd 00cf9300h
+CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dd 0000FFFFh
+ dd 00af9b00h
+TSS_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0067h
+TSS_SEL_FIXUP:
+ dw 0000h
+ dd 00008900h
+L_DATA_SEL equ $-GDT_BASE
+ dd 0000ffffh
+ dd 008f9300h
+L_CODE_SEL equ $-GDT_BASE
+ dw 0ffffh
+L_CODE_SEL_FIXUP:
+ dd 09a000000h ;Fix up by adding SMM BASE + 8000h
+ dw 0
+GDT_SIZE equ $-GDT_BASE ;Size of Descriptor Table
+
+GdtDescriptor:
+ dw GDT_SIZE - 1 ;GDT limit
+GDT_DESC_FIXUP:
+ dd offset GDT_BASE ;Fix up by adding SMM BASE + 8000h
+SmmEntryEnd:
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;<AMI_PHDR_START>
+;---------------------------------------------------------------------------
+;
+; Procedure: Thunk
+;
+; Description: The thunk code is copied to below 1MB and used in SMM to thunk to
+; 16-bit mode.
+;
+; Input: None
+;
+; Output: None
+;---------------------------------------------------------------------------
+;<AMI_PHDR_END>
+
+THUNK:
+ jmp short skip_thunk_fixup_data
+ dw offset thunk_data_fixup - offset THUNK
+ dw offset thunk_data_fixup2 - offset THUNK
+skip_thunk_fixup_data:
+IFDEF EFIx64
+;Starts in 64-bit mode. Need to turn this into machine code.
+ push dx ;rdx
+;---Jump from long mode to compatiblity mode---
+ push 10h
+ ;push eip (call next instruction)
+ db 0e8h
+ dd 0
+ ;add dword ptr [rsp], 6 ;rip = ComMode.
+ db 83h, 04h, 24h
+ db 6
+ db 48h
+ retf
+ComMode:
+;---Go to protected mode---
+ mov eax, cr0
+ btr ax, 31 ;btr eax, 31
+ mov cr0, eax ;Now in protected mode.
+ jmp $+2
+
+ ;mov ecx, 0c0000080h
+ db 0b9h
+ dd 0c0000080h
+ rdmsr
+ btr ax, 8 ;btr eax, 8
+ wrmsr
+ENDIF
+;Starts in protected mode. Need to turn this into machine code.
+ db 60h ;pushad
+ db 9ch ;pushfd
+
+ ;mov ebx, ThunkData
+ db 0bbh
+thunk_data_fixup:
+ dd 0
+
+if MKF_SMM_THUNK_IN_CSM EQ -1
+ ;movzx eax, word ptr [40eh] ;Get segment of ebda.
+ db 0Fh, 0B7h, 05
+ dd 40eh
+ shl ax, 4 ;shl eax, 4 ;Get address ebda
+ add bx, ax ;add ebx, eax
+endif
+
+;--Save Data--
+ ;mov ds:(SMM_THUNK_DATA ptr [ebx]).StackSave, esp ;Save 32 bit stack address of this module.
+ db 89h, 63h
+ db SMM_THUNK_DATA.StackSave
+ ;sgdt ds:(SMM_THUNK_DATA ptr [ebx]).GdtSave
+ db 0Fh, 01h, 43h
+ db SMM_THUNK_DATA.GdtSave
+ ;sidt ds:(SMM_THUNK_DATA ptr [ebx]).IdtSave
+ db 0Fh, 01h, 4Bh
+ db SMM_THUNK_DATA.IdtSave
+;---Copy Stack parameters of LegacyBiosFarCall---
+ ;mov ecx, ds:(SMM_THUNK_DATA ptr [ebx]).StackParm.StackSize
+ db 8Bh, 4Bh
+ db SMM_THUNK_DATA.StackParm.StackSize
+
+ or cx, cx ;32-bit or ecx, ecx
+ jz no_stack_to_copy
+
+ ;movzx edi, ds:(SMM_THUNK_DATA ptr [ebx]).Below1MStack
+ db 0Fh, 0B7h, 7Bh
+ db SMM_THUNK_DATA.Below1MStack
+ add di, bx ;32-bit add edi, ebx
+ sub di, cx ;32-bit sub edi, ecx
+
+ ;mov esi, ds:(SMM_THUNK_DATA ptr [ebx]).StackParm.StackPtr
+ db 8Bh, 73h
+ db SMM_THUNK_DATA.StackParm.StackPtr
+
+
+ rep movsb
+no_stack_to_copy:
+
+;--Get Real mode address to switch to--
+ ;call get_eip ;push eip
+ db 0E8h
+ dd 0h
+get_eip:pop dx ;pop edx
+ ;add edx, offset RealMode - offset get_eip
+ db 83h, 0C2h
+ db offset RealMode - offset get_eip
+
+;--Switch to real mode--
+ ;lidt fword ptr ds:(SMM_THUNK_DATA ptr [ebx]).LegacyIdtDesc
+ db 0Fh, 01h, 5Bh
+ db SMM_THUNK_DATA.LegacyIdtDesc
+ ;Jump to L_CODE_SEL:next
+ ;push L_CODE_SEL
+ db 6ah
+ db L_CODE_SEL
+ ;push offset next - offset THUNK
+ db 68h
+ dd offset next - offset THUNK
+ retf
+next:
+ mov ax, L_DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ mov eax, cr0
+ and al, 0feh
+ mov cr0, eax
+ shr ebx, 4
+ mov ds, bx
+ mov ss, bx
+;---------------Real mode operations-----------
+ movzx esp, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).Below1MStack
+ sub sp, word ptr ds:(SMM_THUNK_DATA ptr [SmmThunkData]).StackParm.StackSize
+
+ ;--jump to real mode--
+ mov eax, edx
+ shr edx, 4 ;edx = segment
+ and eax, 0fh ;eax = ip
+ push dx
+ push ax
+ retf
+RealMode:
+ mov ax, cs
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ ;---copy registers for FarCall---
+ mov eax, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_eax
+ mov ebx, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ebx
+ mov ecx, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ecx
+ mov edx, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_edx
+ mov esi, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_esi
+ mov edi, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_edi
+ mov ebp, ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ebp
+
+ push ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_es
+ pop es
+ push ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_fs
+ pop fs
+ push ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_gs
+ pop gs
+
+ ;Generally, flags are not used to pass information as a parameter only to return information.
+ ;Uninialized flags in the parameters may cause an exception if they are set.
+
+ cmp word ptr ds:(SMM_THUNK_DATA ptr [SmmThunkData]).StackParm.StackSize, 0
+ jne @f
+ ;If no stack, push flags to imitate INT xx, in case of using call to emulate interrupt.
+ pushf
+@@:
+ ;---Push return cs:ip---
+ push cs
+ call store_ret_ptr ;push ip
+store_ret_ptr:
+ push bp ;save bp for temp use.
+ mov bp, sp
+
+ add word ptr [bp + 2], ret_from_16bit - store_ret_ptr ;Change return address in stack.
+ pop bp ;restore bp
+
+ ;----------------------
+ ;---Call 16-bit code---
+ ;----------------------
+
+ ;push the function to stack.
+ push ds:(SMM_THUNK_DATA ptr [SmmThunkData]).FarCallPtr16.seg_offset
+ push ds:(SMM_THUNK_DATA ptr [SmmThunkData]).FarCallPtr16.ptr_offset
+
+ ;This is done last because of ds is used.
+ push ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ds
+ pop ds
+
+ ;---Execute 16-bit call---
+ retf ;Execute far call
+ret_from_16bit:
+ push ds ;Save orginal ds
+if MKF_SMM_THUNK_IN_CSM EQ -1
+ push ax
+ xor ax, ax
+ mov fs, ax
+ movzx eax, word ptr fs:[40eh]
+
+ ;add ax, thunk_data_fixup2
+ db 5
+thunk_data_fixup2:
+ dw 0
+ mov ds, ax
+ pop ax
+else
+ ;push ThunkData2 ;ds = thunk data >> 4
+ db 68h
+thunk_data_fixup2:
+ dw 0
+ pop ds
+endif
+
+ pop ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ds
+
+
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_eax, eax
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ebx, ebx
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ecx, ecx
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_edx, edx
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_esi, esi
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_edi, edi
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_ebp, ebp
+
+ pushfd
+ pop ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_flags
+
+ mov ax, es
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_es, ax
+
+ mov ax, fs
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_fs, ax
+
+ mov ax, gs
+ mov ds:(SMM_THUNK_DATA ptr [SmmThunkData]).regs.reg_gs, ax
+
+;--------------End Real Mode operations---------
+
+ xor ebx, ebx
+ mov bx, ds
+ shl ebx, 4
+
+ xor edx,edx
+ mov dx, cs
+ shl edx, 4 ;edx+ already 0
+
+ ;--Switch to protected mode--
+ db 66h
+ lgdt fword ptr ds:(SMM_THUNK_DATA ptr [SmmThunkData]).GdtSave
+
+ mov eax, cr0
+ or al, 1 ;Set PE bit
+ mov cr0, eax ;Turn on Protected Mode
+
+;---Switch into protected mode---
+ ;jmp 10:TP32MODE to set cs segment
+
+ mov eax, edx
+ call get_eip2 ;push ip
+get_eip2:
+ xor edx, edx
+ pop dx
+ add edx, offset TP32Mode - offset get_eip2
+ add edx, eax ;eip = cs * 10h + offset
+ pushd 10h
+ push edx
+ db 66h
+ retf
+TP32Mode::
+;---In protected mode.---
+ ;mov ax, DATA_SEL
+ db 66h, 0b8h
+ dw DATA_SEL
+ db 66h, 8eh, 0d8h ;mov ds, ax
+ db 66h, 8eh, 0c0h ;mov es, ax
+ db 66h, 8eh, 0d0h ;mov ss, ax
+ db 66h, 8eh, 0e0h ;mov fs, ax
+ db 66h, 8eh, 0e8h ;mov gs, ax
+
+ ;lidt fword ptr ds:(SMM_THUNK_DATA ptr [ebx]).IdtSave
+ db 0Fh, 01h, 5Bh
+ db SMM_THUNK_DATA.IdtSave
+
+ ;mov esp, ds:(SMM_THUNK_DATA ptr [ebx]).StackSave ;Get original stack back.
+ db 8Bh, 63h
+ db SMM_THUNK_DATA.StackSave
+
+ xor ax, ax ;xor eax, eax short/quick way to set EAX = 0
+ lldt ax ;(source operand == 0) => LDTR is invalid
+ db 9dh ;popfd
+ db 61h ;popad
+
+IFDEF EFIx64
+;---Switch to long mode---
+ ;mov ecx, 0c0000080h
+ db 0b9h
+ dd 0c0000080h
+ rdmsr
+ bts ax, 8 ;bts eax, 8
+ wrmsr
+
+ mov eax, cr0
+ bts ax, 31 ;bts eax, 31
+ mov cr0, eax ;Now in compatibility mode.
+ jmp $+2
+
+ ;jmp 38:LongModeThk to set cs segment
+ ;call get_eip3 ;push eip
+ db 0E8h
+ dd 0h
+get_eip3:
+ pop dx ;pop edx (edx = eip)
+ ;add edx, offset LongModeThk - offset get_eip3
+ db 83h, 0C2h
+ db offset LongModeThk - offset get_eip3
+ push 38h
+ push dx ;push edx
+ retf
+LongModeThk:
+ ;mov ax, DATA_SEL
+ db 66h, 0b8h
+ dw DATA_SEL
+ db 66h, 8eh, 0d8h ;mov ds, ax
+ db 66h, 8eh, 0c0h ;mov es, ax
+ db 66h, 8eh, 0d0h ;mov ss, ax
+ db 66h, 8eh, 0e0h ;mov fs, ax
+ db 66h, 8eh, 0e8h ;mov gs, ax
+
+ pop dx ;pop rdx
+ENDIF
+ ret
+SmmThunkEnd:
+SMM ENDS
+
+end
+
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2008, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;*************************************************************************
+;*************************************************************************
diff --git a/Core/EM/SMM/SmmHdr.equ b/Core/EM/SMM/SmmHdr.equ
new file mode 100644
index 0000000..5209fe0
--- /dev/null
+++ b/Core/EM/SMM/SmmHdr.equ
@@ -0,0 +1,286 @@
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2011, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;*************************************************************************
+;*************************************************************************
+
+;**********************************************************************
+; $Header: /Alaska/SOURCE/Modules/SMM/SmmHdr.equ 26 4/01/11 10:09a Markw $
+;
+; $Revision: 26 $
+;
+; $Date: 4/01/11 10:09a $
+;**********************************************************************
+; Revision History
+; ----------------
+; $Log: /Alaska/SOURCE/Modules/SMM/SmmHdr.equ $
+;
+; 26 4/01/11 10:09a 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
+;
+; 25 8/11/09 11:46a Markw
+; Removed Legacy registration. This is removed from latest PI and not
+; used by projects.
+;
+; 24 7/08/09 8:09p Markw
+; Update headers.
+;
+; 23 12/23/08 2:15p Markw
+; EIP #17900 Set up TSS. Borland C in DOS hangs otherwise.
+;
+; 22 11/21/08 4:57p Markw
+; Add SmmInit to SMM_ENTRY_STRUCT for SMM init for first normal/S3 boot.
+; 32-bit CPU count.
+;
+; 21 9/07/08 12:42a Markw
+; Separate SMM Private structure into inside SMM and outside SMM
+; structure.
+;
+; 20 4/04/08 6:21p Markw
+; Add Smrr MSR to SMM_BASE_PRIVATE_STRUCT.
+;
+; 19 3/03/08 6:35p Markw
+; Added 32-bit register for smm thunk.
+;
+; 18 11/14/07 2:03p Markw
+; Added SMRR support and updated SMM Cache for non-SMRR.
+;
+; 17 10/29/07 10:58a Markw
+; Smm Thunk:
+; * Code and data different segments.
+; * Code position independent.
+; * Switch for CSM for code and EBDA for data.
+;
+; 16 10/24/07 12:00p Markw
+; SMM Thunk code position independent. Data in a separate segment than
+; code in Smm Thunk.
+;
+; 15 9/10/07 1:39p Markw
+; Add Interrupt Handling in SMM.
+;
+; 14 6/08/07 6:51p Markw
+; Save/Restore XMM.
+;
+; 13 1/11/07 12:28p Markw
+; Adjusted location of fields in structure for removal of legacy.
+;
+; 12 1/09/07 6:40p Markw
+; Update BSP Entry Structure to remove dependencies on SMM_BSP_BASE.
+;
+; 11 12/29/06 4:45p Markw
+; Add Smm Cache Support and update CPU syncronization.
+;
+; 10 12/21/06 5:19p Markw
+; Remove old unused SmmStackSize from Private structure.
+;
+; 9 11/13/06 11:23a Markw
+; Added structure for AP entry.
+;
+; 8 9/18/06 3:20p Markw
+; Updated 32 bit part for BSP an AP sync.
+;
+; 7 9/18/06 11:47a Markw
+;
+; 6 8/24/06 3:27p Felixp
+; Preliminary x64 support (work in progress)
+;
+; 5 1/13/06 11:27a Markw
+; Added SMM Thunk support.
+;
+; 4 1/10/06 2:56p Markw
+; Add support for multi-threadding and sync all CPUs during entry/exit of
+; SMM.
+;
+; 3 7/19/05 7:59p Markw
+; Fixed smm base private header.
+;
+; 2 7/11/05 1:06p Markw
+; Removed isCallback from structure.
+;
+; 1 1/28/05 4:29p Sivagarn
+; Generic SMM module - Intial Check in
+;
+;
+;**********************************************************************
+
+;<AMI_FHDR_START>
+;----------------------------------------------------------------------------
+;
+; Name: SmmHdr.EQU
+;
+; Description: Header file for the SMM x86 assembly source
+;
+;----------------------------------------------------------------------------
+;<AMI_FHDR_END>
+
+
+FAR_CALL_PTR_16 struct
+ ptr_offset dw ?
+ seg_offset dw ?
+FAR_CALL_PTR_16 ends
+
+REGISTERS struct
+ reg_eax dd ?
+ reg_ebx dd ?
+ reg_ecx dd ?
+ reg_edx dd ?
+ reg_esi dd ?
+ reg_edi dd ?
+ reg_flags dd ?
+ reg_es dw ?
+ reg_cs dw ?
+ reg_ss dw ?
+ reg_ds dw ?
+ reg_fs dw ?
+ reg_gs dw ?
+ reg_ebp dd ?
+REGISTERS ends
+
+IFNDEF EFIx64
+
+SMM_DESC STRUCT 1
+ Limit dw ?
+ Base dd ?
+ Rsv dw ? ;For alignment
+SMM_DESC ENDS
+
+STACK_PARAM STRUCT
+ StackPtr dd ?
+ StackSize dd ?
+STACK_PARAM ENDS
+
+SMM_ENTRY_INIT_STRUCT STRUCT
+ SmmInit dd ? ;This must be first.
+ SmmEntryLength dd ?
+ GdtDescBaseOffset dd ?
+ LCodeSelBaseOffset dd ?
+ TssSelBaseOffset dd ?
+ SmmThunkProcOffset dd ?
+ SmmThunkLength dd ?
+ Ht0 dd ?
+ SmmEntryStart dd ?
+ SmmDispatcherAddr dd ?
+ SmmDispatcherPrivateStruct dd ?
+ SmmStack dd ?
+ CpuNo dd ?
+SMM_ENTRY_INIT_STRUCT ENDS
+
+SMM_THUNK_DATA STRUCT 8
+ ;Real mode thunk
+ FarCallPtr16 FAR_CALL_PTR_16 <>
+ Regs REGISTERS <>
+ StackParm STACK_PARAM <>
+ StackSave dd ?
+ GdtSave SMM_DESC <>
+ IdtSave SMM_DESC <>
+ LegacyIdtDesc SMM_DESC <>
+
+ Below1MStack dw ? ;ss = ds
+SMM_THUNK_DATA ENDS
+
+DESCRIPTOR_TABLE STRUCT 1
+ Limit dw ?
+ Base dd ?
+DESCRIPTOR_TABLE ends
+
+SMM_DISPATCHER_PRIVATE_STRUCT STRUCT 8
+ PageDirectories dd ?
+ SmmXmmSave dd ?
+ SmrrEnable db ?
+ SmrrMsr dd ?
+ TsegMsr dd ?
+ TsegMsrBase dq ?
+ TsegMsrMask dq ?
+ Idt DESCRIPTOR_TABLE <>
+
+ ;Addional members not specified here.
+SMM_DISPATCHER_PRIVATE_STRUCT ENDS
+
+ELSE
+
+STACK_PARAM struct
+ StackPtr dd ?
+ StackSize dd ?
+STACK_PARAM ends
+
+SMM_DESC STRUCT 1
+ Limit dw ?
+ Base dd ?
+ Rsv dw ? ;For alignment
+SMM_DESC ENDS
+
+DESCRIPTOR_TABLE STRUCT 1
+ Limit dw ?
+ Base dq ?
+DESCRIPTOR_TABLE ends
+
+SMM_DISPATCHER_PRIVATE_STRUCT STRUCT 8
+ PageDirectories dq ?
+ SmmXmmSave dq ?
+ SmrrEnable db ?
+ SmrrMsr dd ?
+ TsegMsr dd ?
+ TsegMsrBase dq ?
+ TsegMsrMask dq ?
+ Idt DESCRIPTOR_TABLE <>
+ ;Addional members not specified here.
+SMM_DISPATCHER_PRIVATE_STRUCT ENDS
+
+SMM_ENTRY_INIT_STRUCT STRUCT 8
+ SmmInit dd ? ;This must be first.
+ SmmEntryLength dd ?
+ GdtDescBaseOffset dd ?
+ LCodeSelBaseOffset dd ?
+ TssSelBaseOffset dd ?
+ SmmThunkProcOffset dd ?
+ SmmThunkLength dd ?
+ Ht0 dd ?
+ SmmEntryStart dq ?
+ SmmDispatcherAddr dq ?
+ SmmDispatcherPrivateStruct dq ?
+ SmmStack dq ?
+ CpuNo dd ?
+ Ia32HandlerListHead dq ?
+SMM_ENTRY_INIT_STRUCT ENDS
+
+SMM_THUNK_DATA STRUCT 8
+ ;Real mode thunk
+ FarCallPtr16 FAR_CALL_PTR_16 <>
+ Regs REGISTERS <>
+ StackParm STACK_PARAM <>
+ StackSave dd ?
+ GdtSave SMM_DESC <>
+ IdtSave SMM_DESC <>
+ LegacyIdtDesc SMM_DESC <>
+ Below1MStack dw ? ;ss = ds
+SMM_THUNK_DATA ENDS
+
+ENDIF
+
+;*************************************************************************
+;*************************************************************************
+;** **
+;** (C)Copyright 1985-2011, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;*************************************************************************
+;*************************************************************************
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 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmMemoryManager.c b/Core/EM/SMM/SmmMemoryManager.c
new file mode 100644
index 0000000..0e6addb
--- /dev/null
+++ b/Core/EM/SMM/SmmMemoryManager.c
@@ -0,0 +1,962 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmMemoryManager.c 12 4/22/10 4:39p Markw $
+//
+// $Revision: 12 $
+//
+// $Date: 4/22/10 4:39p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmMemoryManager.c $
+//
+// 12 4/22/10 4:39p Markw
+// Update to build with /w4 flag.
+//
+// 11 5/08/09 10:56a Markw
+// Header updates.
+//
+// 10 12/16/08 2:34a Iminglin
+// (EIP17767) The function value of FindFreeSpace, FindFreeAddress,
+// Allocate for compliance.
+//
+// 9 10/29/07 10:58a Markw
+// Smm Thunk:
+// * Code and data different segments.
+// * Code position independent.
+// * Switch for CSM for code and EBDA for data.
+//
+// 8 10/24/07 12:02p Markw
+// SMM Thunk code position independent. Data in a separate segment than
+// code in Smm Thunk.
+//
+// 7 7/25/07 2:11p Markw
+// Exclude A000 region if needed.
+//
+// 6 8/24/06 7:13p Felixp
+//
+// 5 8/24/06 7:00p Felixp
+// x64 support (warnings/errors fixed)
+//
+// 4 4/25/06 6:25p Markw
+//
+// 3 4/21/06 5:14p Markw
+//
+// 2 7/19/05 6:09p Markw
+// Add support for managing A&B SMM segments.
+//
+// 1 1/28/05 4:32p Sivagarn
+// SMM Dispatcher Component - Initial check in
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SmmMemoryManager.c
+//
+// Description: Provides functions to manage SMM memory. Allocate and Free memory.
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <efi.h>
+#include <AmiDxeLib.h>
+#include "SmmPrivateShared.h"
+
+#define NUM_MEM_DESCRIPTORS 30 //<--Number of descriptors before in a table. If more descriptors needed, a new table is created.
+
+typedef struct _MEMORY_DESCRIPTOR MEMORY_DESCRIPTOR;
+typedef struct _MEMORY_RESERVED_TABLE MEMORY_RESERVED_TABLE;
+
+
+//<AMI_SHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: MEMORY_DESCRIPTOR
+//
+// Description:
+// Each descriptor contains the Base and end + 1 of each
+// memory allocation. The list is sorted from lowest to highest.
+// Last linked descriptor has a Link = 0.
+// Unused descriptors have links = 0xffffffff.
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// MemBase UINT8* Base address of allocated memory.
+// MemEnd UINT8* End address + 1 of allocated memory.
+// Link MEMORY_DESCRIPTOR* Link to next Descriptor.
+//
+//---------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+struct _MEMORY_DESCRIPTOR
+{
+ UINT8 *MemBase;
+ UINT8 *MemEnd;
+ MEMORY_DESCRIPTOR *Link;
+};
+
+//<AMI_SHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: MEMORY_RESERVED_TABLE
+//
+// Description:
+// Table stores memory descriptors. If runs out of descriptors,
+// additional tables will be linked. New tables can not be removed.
+// Unused descriptors Link will be 0xffffffff.
+// Last table Link = 0.
+//
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------
+// MemDesc MEMORY_DESCRIPTOR[] Array of memory descriptors.
+// MemNextTable MEMORY_DESCRIPTOR A descriptor used if a new table is created.
+// NumMemDescUsed UINTN Number of descriptors used.
+// Link MEMORY_RESERVED_TABLE* Link to next table.
+//
+//---------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+struct _MEMORY_RESERVED_TABLE
+{
+ MEMORY_DESCRIPTOR MemDesc[NUM_MEM_DESCRIPTORS];
+ MEMORY_DESCRIPTOR MemNextTable;
+ UINTN NumMemDescUsed;
+ MEMORY_RESERVED_TABLE *Link;
+};
+
+//Default descriptor for unused descriptor.
+MEMORY_DESCRIPTOR gDefaultMemoryDescriptor = {0,0,(MEMORY_DESCRIPTOR*)(UINTN)0xffffffff};
+
+//Default descriptor for next table.
+MEMORY_DESCRIPTOR gDefaultMemoryDescriptor2 = {0,0,0};
+
+UINT8 *gSmmMemBase;
+UINT8 *gSmmMemEnd; //Top of SMM memory + 1.
+
+MEMORY_RESERVED_TABLE gTableHead; //First memory table.
+MEMORY_DESCRIPTOR *gDescHead; //Pointer to first descriptor. (Lowest memory address.)
+
+BOOLEAN ABSegPageAlloc[32] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //ASEG.
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //BSEG.
+};
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: Align8
+//
+// Description: Align the address to nearest 8 byte alignment.
+//
+// Input:
+// UINTN Value - Value to Align.
+//
+// Output:
+// UINTN - Aligned Value.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN Align8(UINTN Value)
+{
+ return (Value + 7) & ~7;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: Align2n
+//
+// Description: Align the address to nearest specified 2n alignment.
+// If the alignment isn't 2^n-1, then result will be invalid.
+//
+// Input:
+// UINT8 *Value - Pointer to value to Align.
+// UINTN Alignment (This the 2n Alignment - 1. Example Alignment = 31, for 32 byte alignment.
+//
+// Output:
+// UINT8* - Aligned Value.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8* Align2n(UINT8 *Value,UINTN Alignment)
+{
+ return (UINT8*)(((UINTN)Value+Alignment) & ~Alignment);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ConstructMemoryReservedTable
+//
+// Description: Intitialize the MEMORY_RESERVED_TABLE.
+//
+// Input:
+// MEMORY_RESERVED_TABLE *Table
+//
+// Output:
+// VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID ConstructMemoryReservedTable(MEMORY_RESERVED_TABLE *Table)
+{
+ UINTN i;
+ for(i=0;i<NUM_MEM_DESCRIPTORS;++i) Table->MemDesc[i] = gDefaultMemoryDescriptor;
+ Table->MemNextTable = gDefaultMemoryDescriptor2;
+ Table->Link = 0;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: FindFreeSpace
+//
+// Description: Find a gap of free memory of a size and possibly of an alignment. This returns
+// the preceding memory descriptor. If no gaps are found, the last memory descriptor
+// is returned.
+//
+// Input:
+// UINTN Size - Size of free space.
+// UINTN Alignment OPTIONAL - This the 2n Alignment - 1. Example Alignment = 31, for 32 byte alignment.
+//
+// Output:
+// MEMORY_DESCRIPTOR *
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Start with the first descriptor.
+// 2. Evaluate the difference (empty space) between the
+// (a) the base of address of the next descriptor and (b) the
+// aligned End address of the current descriptor.
+// 3. If the difference is greater or equal to the requested size,
+// return the link.
+// 4. Repeat 2-4, until out of descriptors.
+// 5. Return the last descriptor.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+MEMORY_DESCRIPTOR *FindFreeSpace(
+ IN UINTN Size,
+ IN UINTN Alignment OPTIONAL)
+{
+ MEMORY_DESCRIPTOR *Link;
+ UINT8 *FreeStart;
+ UINT8 *UsedNext;
+
+ if (!Size) return NULL;
+
+ //Find the preceding descriptor of a memory gap of the specified size (and alignment).
+ for (Link = gDescHead; Link->Link; Link = Link->Link)
+ {
+ UINTN EmptySpace;
+ FreeStart = Link->MemEnd; //Beginning of possible gap.
+ if (Alignment) FreeStart = Align2n(FreeStart,Alignment); //Align possible gap to requested alignment.
+ UsedNext = Link->Link->MemBase; //Find end of possible gap.
+ EmptySpace = (UINTN)UsedNext - (UINTN)FreeStart; //Gap size (may be negative because of alligned start)
+ if ((INTN)EmptySpace >= (INTN) Size) return Link; //If gap size is larger or equal requested size,
+ // return link of descriptor preceding link.
+ }
+ return Link; //Out of descriptors, return last Link.
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: FindAddress
+//
+// Description: Find a gap of free memory of an specific Address and a size.
+// If part of the space is taken, return 0.
+// If the space is found, return the preceding memory descriptor,
+// or the last memory descriptor.
+//
+// Input:
+// UINTN Size - Size of memory.
+// UINTN Alignment - This the 2n Alignment - 1. Example Alignment = 31, for 32 byte alignment.
+//
+// Output:
+// MEMORY_DESCRIPTOR * - 0 if the address range is taken.
+// - not zero, if gap is found, or last link.
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Start with the first descriptor.
+// 2. If the specifed address is in the descriptor, it is taken return 0.
+// 3. If the specified address is in the gap after the descriptor,
+// if the gap is big enough, return the preceding link, otherwise return 0.
+// 4. Repeat steps 2-4 until iterated all the descriptors.
+// 5. Return the last descriptor.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+MEMORY_DESCRIPTOR *FindFreeAddress(UINT8 *Address, UINTN Size)
+{
+ MEMORY_DESCRIPTOR *Link;
+ UINT8 *FreeStart;
+ UINT8 *UsedNext;
+
+ if (!Size) return NULL;
+
+ for(Link = gDescHead; Link->Link; Link = Link->Link)
+ {
+ UINTN EmptySpace;
+ FreeStart = Link->MemEnd;
+ UsedNext = Link->Link->MemBase;
+
+ if (Address >= Link->MemBase && Address < FreeStart) return NULL; //Space taken, if address is in the descriptor.
+
+ if (Address >= FreeStart && Address <= UsedNext ) { //Is address in the, gap after the descriptor.
+ //UINTN typecasts used instead of UINT32, so complier won't give warning.
+ EmptySpace = (UINTN)UsedNext - (UINTN)Address;
+ if ((INTN)EmptySpace >= (INTN) Size) return Link; //If enough space in gap, return Link
+ return NULL; //Space not available.
+ }
+ }
+ return Link; //Out of descriptors, return last Link.
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetEmptyDescriptor
+//
+// Description: Find an unused memory descriptor in the tables.
+//
+// Input: VOID
+//
+// Output:
+// MEMORY_DESCRIPTOR * - 0 if can not allocate a new descriptor.
+// - Empty descriptor.
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Find a table with empty descriptors.
+// 2. If a table is not found with an empty descriptor, go to step 5.
+// ---Found table with an empty descriptor---
+// 3. Search descriptor array for an unused descriptors (Link = 0xffffffff)
+// 4. Return the descriptor.
+// ---Did not find table with an empty descriptor---
+// 5. Search memory descriptors for free space for a new table.
+// 6. Check if last descriptor and enough free space at end, if not return 0.
+// 7. Add a new memory table descriptor at the end of the returned descriptor.
+// 8. Add new table link.
+// 9. Construct a new table.
+// 10. Return the first descriptor.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+MEMORY_DESCRIPTOR * GetEmptyDescriptor()
+{
+ MEMORY_RESERVED_TABLE *Table = &gTableHead;
+ MEMORY_RESERVED_TABLE *PrevTable = NULL;
+ MEMORY_DESCRIPTOR *MemDesc;
+ UINTN i;
+
+ //Find a table with an unused descriptor.
+ while (Table && (Table->NumMemDescUsed == NUM_MEM_DESCRIPTORS)) //If table full, find next descriptor.
+ {
+ PrevTable = Table; //Keep track of last table, in case we need to create a new one.
+ Table = Table->Link;
+ }
+
+ if (Table) //Found table.
+ {
+ for(i=0;i<NUM_MEM_DESCRIPTORS;++i)
+ {
+ if (Table->MemDesc[i].Link == (MEMORY_DESCRIPTOR*)(UINTN)0xffffffff) //Search for empty descriptor
+ {
+ ++Table->NumMemDescUsed;
+ return &Table->MemDesc[i]; //Return empty descriptor.
+ }
+ } //Will not exit from this loop. An empty descriptor is guaranteed since NumMemDescUsed isn't the max.
+ }
+
+ //No more empty descriptors. Create a new table
+ MemDesc = FindFreeSpace(sizeof(MEMORY_RESERVED_TABLE),0); //Find free memory.
+
+ //This is the address of the new table if there is space available for the table. The table doesn't exist yet.
+ Table = (MEMORY_RESERVED_TABLE*) MemDesc->MemEnd;
+
+ if (!MemDesc->Link) { //If end of descriptors, check if enough space for table.
+ if ((UINT8*) Table + Align8(sizeof(MEMORY_RESERVED_TABLE)) > gSmmMemEnd) return 0; //If out of space
+ }
+
+ PrevTable->MemNextTable.Link = MemDesc->Link; //Add new table descriptor.
+ MemDesc->Link = &PrevTable->MemNextTable;
+
+ PrevTable->MemNextTable.MemBase = (UINT8*) Table; //Fill in table descriptor
+ PrevTable->MemNextTable.MemEnd = (UINT8*) Table + Align8(sizeof(MEMORY_RESERVED_TABLE));
+ PrevTable->Link = Table; //Add table end of previous table link.
+
+ ConstructMemoryReservedTable(Table); //Fill in table with default values.
+ Table->NumMemDescUsed = 1; //1 descriptor is being allocated.
+
+ return &Table->MemDesc[0]; //Return first descriptor.
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RemoveDescriptor
+//
+// Description: Find an unused memory descriptor in the tables.
+//
+// Input: MEMORY_DESCRIPTOR * Descriptor - Descriptor to free.
+//
+// Output: VOID
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Start with first table.
+// 2. Check each table's descriptor array for the descriptor to be removed.
+// 3. If descriptor not found go to step 7.
+// ---Descriptor found---
+// 4. Replace the Link with 0xffffffff.
+// 5. Reduce number of descripors being used.
+// 6. return.
+// ---Descriptor not found---
+// 7. Repeat for next table steps 2-7 until last table.
+// 8. Return
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID RemoveDescriptor(MEMORY_DESCRIPTOR * Descriptor)
+{
+ MEMORY_RESERVED_TABLE *Table;
+ UINTN i;
+
+ for (Table = &gTableHead; Table; Table = Table->Link)
+ {
+ if (Table->NumMemDescUsed==0) continue;
+ for(i=0; i < NUM_MEM_DESCRIPTORS; ++i)
+ {
+ if (&Table->MemDesc[i] == Descriptor)
+ {
+ Table->MemDesc[i].Link = (MEMORY_DESCRIPTOR*)(UINTN)0xffffffff;
+ --Table->NumMemDescUsed;
+ return;
+ }
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: Allocate
+//
+// Description:
+// Allocate a memory. Caller may specify either a specific address
+// or alignment, or neither. Alignment is a minimum of 8 bytes.
+//
+// Input:
+// IN VOID *Address OPTIONAL - If caller wants to specify a specific address (Alignment is ignored).
+// IN UINTN Size - Size of allocation.
+// UINTN Alignment OPTIONAL - Specific alignment, if required. An address must not be given.
+// If alignment is set to 0, then alignment is 8 bytes. (Required by SMM spec.)
+//
+// Output:
+// VOID * - Memory allocated start address.
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If no size requested return 0.
+// 2. Align Size up to the nearest 8 bytes.
+// 3. Get an empty descriptor. If none, return 0.
+// 4. If Address is given, set BaseStart to address.
+// If not aligned on 8 byte boundary, remove descriptor and return 0.
+// 5. Otherwise, set BaseStart to gSmmMemBase and
+// align if and to the given alignment. (Bottom of SMM.)
+// 6. If Size requested is greater than the Smm memory region,
+// remove descriptor and return 0.
+// 7. If no memory is previously allocated, setup descriptor, and point to it from gDescHead.
+// (Baseaddress is either the Address requested or beggining of Smm RAM.) Return address.
+// 8. Otherwise if requested memory base is lower than the base pointed by gDescHead or
+// gap between start of smm ram and memory base pointed to by gDescHead is larger than
+// the size requested is available,
+// fill in memory descriptor, and add it in front of gDescHead, replacing gDescHead. Return Address.
+// 9. Otherwise, if address address, find descriptor preceding the Address requested.
+// 10. If size requested, find the descriptor preceding the gap >= Size requested.
+// 11. If last descriptor, if not enough space left, remove descriptor, and return 0.
+// 12. Fill in descriptor. Return Address.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+void * Allocate(
+ IN VOID *Address OPTIONAL,
+ IN UINTN Size,
+ UINTN Alignment OPTIONAL
+ )
+{
+ MEMORY_DESCRIPTOR *EmptyDesc = NULL;
+ MEMORY_DESCRIPTOR *FreeSpaceDesc;
+ UINT8 *BaseStart;
+
+ if (!Size) return NULL;
+
+ Size = Align8(Size); //Minimum size requested is 8 bytes.
+
+ EmptyDesc = GetEmptyDescriptor();
+ if (!EmptyDesc){
+ return NULL; //Return if out of descriptors.
+ }
+
+ if (Address)
+ {
+ if ((UINTN)Address != Align8((UINTN)Address)) {RemoveDescriptor(EmptyDesc);return 0;} //Address must be 8 byte aligned.
+ BaseStart = Address;
+ } else {
+ BaseStart = gSmmMemBase;
+ if (Alignment) BaseStart = Align2n(BaseStart,Alignment);
+ }
+
+ if (Size > (UINTN)(gSmmMemEnd - BaseStart)) { //If Smm Memory is smaller than requested, return error.
+ RemoveDescriptor(EmptyDesc);
+ return NULL;
+ }
+
+ if (!gDescHead) //True if no previous allocated memory.
+ {
+ EmptyDesc->MemBase = BaseStart;
+ EmptyDesc->Link = 0;
+
+ gDescHead = EmptyDesc;
+ //else if is true if requested memory base or gap larger than the size requested is available.
+ } else if (((INTN) gDescHead->MemBase - (INTN)BaseStart) >= (INTN) Size) {//Insert before gDescHead;
+ EmptyDesc->MemBase=BaseStart;
+ EmptyDesc->Link = gDescHead;
+ gDescHead = EmptyDesc;
+ //else is true if memory base is more than
+ } else {
+ if (Address)
+ {
+ FreeSpaceDesc = FindFreeAddress(Address,Size);
+ if (!FreeSpaceDesc)
+ {
+ RemoveDescriptor(EmptyDesc);
+ return NULL;
+ }
+ BaseStart = Address;
+ } else {
+ FreeSpaceDesc = FindFreeSpace(Size,Alignment);
+ BaseStart = FreeSpaceDesc->MemEnd;
+ if (Alignment) BaseStart = Align2n(BaseStart,Alignment);
+ }
+
+ if(!FreeSpaceDesc->Link && (UINTN)(gSmmMemEnd - BaseStart) < Size)
+ { //Last Link and not enough room.
+ RemoveDescriptor(EmptyDesc);
+ return NULL;
+ }
+
+ EmptyDesc->MemBase = BaseStart;
+ EmptyDesc->Link = FreeSpaceDesc->Link;
+ FreeSpaceDesc->Link = EmptyDesc;
+ }
+
+ EmptyDesc->MemEnd = EmptyDesc->MemBase + Size;
+
+ return EmptyDesc->MemBase;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: Free
+//
+// Description: Free an allocated buffer.
+//
+// Input:
+// IN VOID *Buffer - Allocation to free.
+//
+// Output:
+// BOOLEAN - TRUE if buffer freed.
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If no allocations, return FALSE.
+// 2. If Buffer to free is gDescHead, set gDescHead to next Link, remove decriptor, and return TRUE.
+// 3. Search link list for buffer.
+// 4. If not found, return FALSE.
+// 5. Set previous link of buffer to link after buffer.
+// 6. Remove Descriptor.
+// 7. Return TRUE.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN Free(VOID *Buffer)
+{
+ MEMORY_DESCRIPTOR *Link;
+ MEMORY_DESCRIPTOR *Prev;
+
+ if (!gDescHead) return FALSE;
+ if (gDescHead->MemBase == (UINT8*)Buffer)
+ {
+ Link = gDescHead;
+ gDescHead = gDescHead->Link;
+ RemoveDescriptor(Link);
+ return TRUE;
+ }
+
+ Prev = gDescHead; Link = gDescHead->Link;
+
+ while(Link)
+ {
+ if (Link->MemBase == Buffer)
+ {
+ Prev->Link = Link->Link;
+ RemoveDescriptor(Link);
+ return TRUE;
+ }
+ Prev = Link;
+ Link = Link->Link;
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: Free4kPages
+//
+// Description: Free pages from buffer.
+//
+// Input:
+// IN VOID *StartAddress - Pages to free.
+// IN UINTN Pages - # of 4k pages.
+//
+// Output:
+// BOOLEAN - TRUE if buffer freed.
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If End Address is not greater than 4G, return FALSE.
+// 2. If StartAddress is not aligned 4k, return FALSE.
+// 3. If no allocations, return FALSE.
+// 4. Search for a descriptor with the StartAddress is allocated.
+// 5. If descriptor not found, return FALSE.
+// 6. Search for a descriptor with the EndAddress is allocated. These criteria must be met which searching.
+// * Allocation size of each descriptor must be 4k pages, otherwise return FALSE.
+// * End address of descriptor must match base address of next descriptor (no free space), otherwise return FALSE.
+// 7. If descriptor not found, return FALSE.
+// 8. If Start and End descriptors are not the same go to step 13.
+// -----Start and End Descriptor match exactly.----
+// 9. If Base and End descriptor match exactly, remove the descriptor from the list.
+// 10. If only Start Address matches exactly, free that space by setting the start address to the End Address.
+// 11. If only the End Address matches exactly, move the end address to Start Address.
+// Note: the end address of the descriptor is not allocated.
+// 12. return TRUE.
+// ----Start and End Descriptors are different descriptors.----
+// 13. If Base address of the Start Descriptor, adjust its end address to the space, and
+// move the Start Descriptor to the next descriptor.
+// 14. Free the descriptors up till the end descriptor.
+// 15. If the End Descriptor's End address doesn match the end address to free,
+// set the base address to the end address, to free the space.
+// 16. Otherwise, remove the end descriptor.
+// 17. Return True.
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN Free4kPages(VOID *StartAddress,UINTN Pages)
+{
+ MEMORY_DESCRIPTOR *StartDesc,*EndDesc,*PrevStart = NULL,*Link,*Link2;
+ UINT8* EndAddress = (UINT8*) StartAddress + 4096 * Pages;
+ if (EndAddress < (UINT8*)StartAddress) return FALSE; //If Endaddress > 4G.
+
+ if (StartAddress != Align2n(StartAddress,4095)) return FALSE; //Must be align 4k.
+
+ //--------Find Beginning and End of Descriptors to adjust--------
+
+ if (!gDescHead) return FALSE;
+ for (StartDesc = gDescHead; StartDesc; StartDesc = StartDesc->Link)
+ {
+ if ((UINT8*)StartAddress >= StartDesc->MemBase && (UINT8*)StartAddress < StartDesc->MemEnd) break;
+ PrevStart = StartDesc;
+ }
+
+ if (!StartDesc) return FALSE;
+
+ EndDesc = StartDesc;
+ for (;;)
+ {
+ if ((UINT8*)(EndDesc->MemEnd - EndDesc->MemBase) != Align2n((UINT8*)(EndDesc->MemEnd - EndDesc->MemBase),4095))
+ return FALSE; //Size must be multiple of 4k.
+
+ if (EndAddress >= EndDesc->MemBase && EndAddress <= EndDesc->MemEnd) break;
+ if (!EndDesc->Link) return FALSE;
+ if (EndDesc->MemEnd != EndDesc->Link->MemBase) return FALSE; //Gap of unallocated space in region to free.
+ EndDesc=EndDesc->Link;
+ }
+
+ //--------Adjust Descriptors, Removing unused ones--------
+
+ if (StartDesc == EndDesc) //If true, range only affects 1 descriptor.
+ {
+ if (StartAddress == StartDesc->MemBase)
+ {
+ if (EndAddress == StartDesc->MemEnd) //If descriptor matches address exactly, free descriptor.
+ {
+ if (StartDesc == gDescHead) gDescHead = StartDesc->Link;
+ else PrevStart->Link = StartDesc->Link;
+ RemoveDescriptor(StartDesc);
+ return TRUE;
+ }
+ StartDesc->MemBase = EndAddress; //Start address matches, change start address.
+ return TRUE;
+ }
+ StartDesc->MemEnd = StartAddress; //If End address matches, change End address.
+ return TRUE;
+ }
+
+
+ //Range affects multiple descriptors.
+ if (StartAddress != StartDesc->MemBase)
+ {
+ StartDesc->MemEnd = StartAddress;
+
+ PrevStart = StartDesc;
+ StartDesc = StartDesc->Link; //Don't delete this descriptor, since it has been adjusted.
+ }
+
+
+ //Remove descriptors in the middle before End.
+ if (StartDesc == gDescHead) gDescHead = EndDesc;
+ else PrevStart->Link = EndDesc;
+
+ for (Link = StartDesc; Link != EndDesc; Link = Link2)
+ {
+ Link2 = Link->Link;
+ RemoveDescriptor(Link); //Remove Descriptors in between.
+ }
+
+
+ //If end address matches, free descriptor, otherwise adjust end address.
+ if (EndAddress != EndDesc->MemEnd)
+ {
+ EndDesc->MemBase = EndAddress;
+ } else {
+ if (EndDesc==gDescHead) gDescHead = EndDesc->Link;
+ else PrevStart->Link = EndDesc->Link;
+ RemoveDescriptor(EndDesc);
+ }
+
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AllocateABSegPages
+//
+// Description: Allocate SMM 4k pages of memory in A or B segment.
+//
+// Input:
+// IN EFI_ALLOCATE_TYPE Type
+// IN UINTN NumberOfPages
+// IN OUT EFI_PHYSICAL_ADDRESS *Memory
+//
+// Output:
+// EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AllocateABSegPages(
+ IN EFI_ALLOCATE_TYPE Type,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+)
+{
+ UINTN i;
+ UINT8 FreePageCount;
+ UINTN StartPage, EndPage;
+ UINT32 MaxAddress;
+
+ VOID **pMemory32 = (VOID**) Memory;
+ UINT32 Memory32 = (UINT32)(UINTN)*pMemory32;
+
+ //Only supported types.
+ if (Type != AllocateMaxAddress && Type != AllocateAddress)
+ return EFI_INVALID_PARAMETER;
+
+ if (Memory32 < 0xa0000) return EFI_NOT_FOUND;
+
+ if (Type == AllocateAddress) {
+ //Check memory alignment.
+ if ((Memory32 & (EFI_PAGE_SIZE - 1)) != 0) return EFI_INVALID_PARAMETER;
+
+ StartPage = (Memory32 - 0xa0000) >> 12;
+
+ //Check for allocation range.
+ if ((StartPage + NumberOfPages) > 32) return EFI_OUT_OF_RESOURCES;
+
+ //Check if pages are free.
+ for (i = StartPage; i < (StartPage + NumberOfPages); ++i)
+ {
+ if (ABSegPageAlloc[i] == TRUE) return EFI_OUT_OF_RESOURCES;
+ }
+ for(i = StartPage; i < (StartPage + NumberOfPages); ++i)
+ ABSegPageAlloc[i] = TRUE;
+
+ return EFI_SUCCESS;
+ }
+
+ if (Memory32 < 0xa0ffe) return EFI_OUT_OF_RESOURCES; //Max address must be whole page.
+
+ MaxAddress = Memory32 & ~(EFI_PAGE_SIZE - 1); //Round down to 4k alignment
+
+ EndPage = (Memory32 - 0xa0000) >> 12;
+ if (EndPage > 31) EndPage = 31; //Max page is 31.
+
+ //Find free pages.
+ FreePageCount = (UINT8) NumberOfPages;
+ for (i = 0; i < EndPage; ++i)
+ {
+ UINTN j;
+ if (ABSegPageAlloc[i] == TRUE)
+ {
+ FreePageCount = (UINT8) NumberOfPages;
+ continue; //Page allocated. Find next
+ }
+ if (--FreePageCount) continue;
+
+ //Found page
+ StartPage = i + 1 - NumberOfPages;
+ *pMemory32 = (VOID *)((StartPage << 12) + 0xa0000);
+
+ for (j = StartPage; j <= i; ++j) ABSegPageAlloc[j] = TRUE;
+
+ return EFI_SUCCESS;
+ }
+ return EFI_OUT_OF_RESOURCES;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AllocateABSegPages
+//
+// Description: Allocate SMM 4k pages of memory in A or B segment.
+//
+// Input:
+// IN EFI_PHYSICAL_ADDRESS Memory - Memory address.
+// IN UINTN NumberOfPages
+//
+// Output:
+// EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS FreeABSegPages(
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+)
+{
+ UINTN i, StartPage, EndPage;
+ VOID *Memory32 = (VOID*)(UINTN)Memory;
+
+ if (((UINT32)(UINTN)Memory32 & (EFI_PAGE_SIZE - 1)) != 0) return EFI_INVALID_PARAMETER;
+
+ if ((UINT32)(UINTN)Memory32 < 0xa0000) return EFI_NOT_FOUND;
+
+ StartPage = ((UINT32)(UINTN)Memory32 - 0xa0000) >> 12;
+
+ //Check for allocation range.
+ if ((StartPage + NumberOfPages) > 32) return EFI_NOT_FOUND;
+
+ EndPage = StartPage + NumberOfPages;
+
+ for (i = StartPage; i < EndPage; ++i) if (ABSegPageAlloc[i] == FALSE) return EFI_NOT_FOUND;
+ for (i = StartPage; i < EndPage; ++i) ABSegPageAlloc[i] = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitializeMemoryManager
+//
+// Description: Initialize the memory manager, so the functions can be used.
+//
+// Input: VOID
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InitializeMemoryManager(SMM_BASE_PRIVATE_STRUCT *Private) {
+ UINT32 *pSmmBase = &Private->SmmHob->SmmBase[0];
+ UINT32 NumCpus = Private->SmmHob->NumCpus;
+ UINT8 i;
+
+#if SMM_EXCLUDE_A000 == 1
+ for (i = 0; i < 16; ++i) ABSegPageAlloc[i] = TRUE;
+#endif
+
+ //Initalize Legacy memory management.
+ for (i = 0; i < NumCpus; ++i) {
+ if (pSmmBase[i] < 0x100000) {
+ UINT8 Page = (UINT8)((pSmmBase[i] - 0x98000) / 4096);
+ ASSERT(Page < 32);
+ ASSERT((Page + 7) < 32);
+ ABSegPageAlloc[Page] = TRUE;
+ ABSegPageAlloc[Page + 7] = TRUE;
+ }
+ }
+
+//If Bsp = TSEG, reserve 1 page for SMM thunk and its stack.
+ if (pSmmBase[0] > 0x100000) {
+#if SMM_EXCLUDE_A000 != 1
+ ABSegPageAlloc[0] = TRUE;
+#else
+ ABSegPageAlloc[16] = TRUE;
+#endif
+ }
+
+ //Initialize TSEG memory management.
+ gSmmMemBase = Private->SmmAllocMemoryStart;
+ gSmmMemEnd = gSmmMemBase + Private->SmmAllocMemoryLength;
+ ConstructMemoryReservedTable(&gTableHead);
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmPiSmst.c b/Core/EM/SMM/SmmPiSmst.c
new file mode 100644
index 0000000..f6a676b
--- /dev/null
+++ b/Core/EM/SMM/SmmPiSmst.c
@@ -0,0 +1,1827 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+/** SmmPiSmst.c - Protocol functions are modified verision from Intel's SMM source.
+
+ Copyright (c) 2009, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmPiSmst.c 6 3/31/11 6:52p Markw $
+//
+// $Revision: 6 $
+//
+// $Date: 3/31/11 6:52p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmPiSmst.c $
+//
+// 6 3/31/11 6:52p Markw
+// Add back revisions 2 to 4.
+//
+// 5 3/31/11 6:45p 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
+//
+// 4 3/15/11 2:35p Markw
+// Copyright header update.
+//
+// 3 3/14/11 3:19p Markw
+// Update for EIP 53481.
+// Rename gSmmFirmwareVender to gSmmFirmwareVendor.
+// For gSmmFirmwareVendor use CONVERT_TO_WSTRING(CORE_VENDOR); instead of
+// AMI.
+//
+// 2 3/08/11 2:00p Markw
+// Update headers and spacing.
+//
+// 1 2/07/11 3:28p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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: SmmPiSmst.c
+//
+// Description: PI Smst functions.
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//This include should come first.
+//#include "SmmPi.h"
+#include "SmmPrivateShared.h"
+#include <AmiDxeLib.h>
+#include <Protocol\SmmCpu.h>
+#if SMM_USE_PI
+#include "SmmDispatcher.h"
+#include <AmiLib.h>
+#include <AmiCspLib.h>
+#endif
+
+CHAR16 gSmmFirmwareVendor[] = CONVERT_TO_WSTRING(CORE_VENDOR);
+
+extern UINT8 **gSmmBase;
+
+//TODOx64: move it to a library header
+VOID CPULib_Pause();
+
+VOID *Allocate(VOID *Base, UINTN Size,UINTN Alignment);
+
+EFI_STATUS AllocateABSegPages(
+ IN EFI_ALLOCATE_TYPE Type,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+);
+EFI_STATUS FreeABSegPages(
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+);
+
+BOOLEAN Free(VOID *Buffer);
+BOOLEAN Free4kPages(VOID *StartAddress,UINTN Pages);
+
+EFI_STATUS InterruptManage(
+ IN CONST EFI_GUID *HandlerType,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+);
+
+VOID UpdateFrameworkSmmConfigTable(IN EFI_CONFIGURATION_TABLE *SmmConfigurationTable, IN UINTN NumberOfTableEntries);
+
+UINT8* Align2n(UINT8 *Value,UINTN Alignment);
+
+#if SMM_USE_FRAMEWORK
+extern EFI_SMM_SYSTEM_TABLE gSmmSystemTable;
+#endif
+#if SMM_USE_PI
+extern EFI_SMM_SYSTEM_TABLE2 gSmmSystemTable2;
+extern EFI_SMM_ENTRY_CONTEXT gEfiSmmEntryContext; //For now, hardcode.
+#endif
+extern SMM_DISPATCHER_PRIVATE_STRUCT *gDispatcherPrivate;
+
+#if SMM_USE_PI
+EFI_STATUS SmmMemRead(
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+);
+
+EFI_STATUS SmmMemWrite(
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+);
+
+EFI_STATUS SmmIoRead(
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+);
+
+EFI_STATUS SmmIoWrite(
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+);
+
+EFI_STATUS SmmSmstAllocatePages(
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+);
+
+EFI_STATUS SmmSmstFreePages(
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+);
+
+EFI_STATUS SmmStartupThisAp(
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuNumber,
+ IN OUT VOID *ProcArguments OPTIONAL
+);
+
+#endif
+
+EFI_STATUS SmmSmstAllocatePool(
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+);
+
+EFI_STATUS SmmSmstFreePool(
+ IN VOID *Buffer
+);
+
+EFI_STATUS CalculateCrc32(
+ IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32
+);
+
+#if SMM_USE_PI
+
+EFI_STATUS SmmInstallConfigurationTable(
+ IN EFI_SMM_SYSTEM_TABLE2 *SystemTable,
+ IN EFI_GUID *Guid,
+ IN VOID *Table,
+ IN UINTN TableSize
+ );
+
+EFI_STATUS ReadSaveState(
+ IN CONST EFI_SMM_CPU_PROTOCOL *This,
+ IN UINTN Width,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN CpuIndex,
+ OUT VOID *Buffer
+)
+{
+ UINT8 *SmmBase;
+#if SMM_USE_FRAMEWORK
+ UINT8 *SstSaveState;
+#endif
+
+ if (CpuIndex >= gDispatcherPrivate->NumCpus) return EFI_INVALID_PARAMETER;
+
+ SmmBase = gSmmBase[CpuIndex];
+#if SMM_USE_FRAMEWORK
+ SstSaveState = (UINT8*)&gSmmSystemTable.CpuSaveState[CpuIndex];
+#endif
+
+ if (Register >= EFI_SMM_SAVE_STATE_REGISTER_FCW && Register <= EFI_SMM_SAVE_STATE_REGISTER_XMM15) {
+ return CpuLib_SmmReadSaveStateFxSave(
+ gDispatcherPrivate->SmmXmmSave[CpuIndex],
+ (UINT8)Width,
+ Register,
+ (VOID*)Buffer
+ );
+ }
+
+ return CPULib_SmmReadSaveState(
+ SmmBase,
+#if SMM_USE_FRAMEWORK
+ SstSaveState,
+ TRUE,
+#else
+ NULL,
+ FALSE,
+#endif
+ (UINT8)Width,
+ Register,
+ Buffer
+ );
+}
+
+EFI_STATUS WriteSaveState(
+ IN CONST EFI_SMM_CPU_PROTOCOL *This,
+ IN UINTN Width,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN CpuIndex,
+ IN CONST VOID *Buffer
+)
+{
+ UINT8 *SmmBase;
+#if SMM_USE_FRAMEWORK
+ UINT8 *SstSaveState;
+#endif
+
+ if (CpuIndex >= gDispatcherPrivate->NumCpus) return EFI_INVALID_PARAMETER;
+
+ SmmBase = gSmmBase[CpuIndex];
+#if SMM_USE_FRAMEWORK
+ SstSaveState = (UINT8*)&gSmmSystemTable.CpuSaveState[CpuIndex];
+#endif
+
+ if (Register >= EFI_SMM_SAVE_STATE_REGISTER_FCW && Register <= EFI_SMM_SAVE_STATE_REGISTER_XMM15) {
+ return CpuLib_SmmWriteSaveStateFxSave(
+ gDispatcherPrivate->SmmXmmSave[CpuIndex],
+ (UINT8)Width,
+ Register,
+ (VOID*)Buffer
+ );
+ }
+
+ return CPULib_SmmWriteSaveState(
+ SmmBase,
+#if SMM_USE_FRAMEWORK
+ SstSaveState,
+ TRUE,
+#else
+ NULL,
+ FALSE,
+#endif
+ (UINT8)Width,
+ Register,
+ Buffer
+ );
+}
+
+EFI_SMM_CPU_PROTOCOL gEfiSmmCpuProtocol = {
+ ReadSaveState,
+ WriteSaveState
+};
+
+
+static EFI_LIST_ENTRY SmmProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (SmmProtocolDatabase);
+EFI_LIST_ENTRY SmmHandleList = INITIALIZE_LIST_HEAD_VARIABLE (SmmHandleList);
+UINTN mEfiLocateHandleRequest = 0; // Added for SmmSmstLocateProtocol
+
+EFI_LIST_ENTRY mRootSmiHandlerList = INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiHandlerList);
+EFI_LIST_ENTRY mSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mSmiEntryList);
+
+SMM_IHANDLE *SmmGetNextLocateByRegisterNotify(
+ IN OUT SMM_LOCATE_POSITION *Position,
+ OUT VOID **Interface
+);
+
+
+SMM_IHANDLE *SmmGetNextLocateByProtocol (
+ IN OUT SMM_LOCATE_POSITION *Position,
+ OUT VOID **Interface
+);
+
+SMM_IHANDLE *SmmGetNextLocateAllHandles (
+ IN OUT SMM_LOCATE_POSITION *Position,
+ OUT VOID **Interface
+);
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmValidateHandle
+//
+// Description: Check whether a handle is a valid EFI_HANDLE.
+//
+// Input:
+// IN EFI_HANDLE UserHandle
+
+// Output:
+// EFI_STATUS
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SmmValidateHandle (
+ IN EFI_HANDLE UserHandle
+)
+{
+ SMM_IHANDLE *Handle;
+ Handle = (SMM_IHANDLE *)UserHandle;
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Handle->Signature != SMM_EFI_HANDLE_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmFindProtocolEntry
+//
+// Description: Finds the protocol entry for the requested protocol.
+//
+// Input:
+// IN EFI_GUID *Protocol
+// IN BOOLEAN Create
+//
+// Output:
+// Protocol entry
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+SMM_PROTOCOL_ENTRY *
+SmmFindProtocolEntry (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN Create
+ )
+{
+ EFI_LIST_ENTRY *Link;
+ SMM_PROTOCOL_ENTRY *Item;
+ SMM_PROTOCOL_ENTRY *ProtEntry;
+ EFI_STATUS Status;
+ //
+ // Search the database for the matching GUID
+ //
+
+ ProtEntry = NULL;
+ for (Link = SmmProtocolDatabase.ForwardLink;
+ Link != &SmmProtocolDatabase;
+ Link = Link->ForwardLink
+ ) {
+ Item = CR(Link, SMM_PROTOCOL_ENTRY, AllEntries, SMM_PROTOCOL_ENTRY_SIGNATURE);
+ if ( !guidcmp (&Item->ProtocolID, Protocol)) {
+ //
+ // This is the protocol entry
+ //
+ ProtEntry = Item;
+ break;
+ }
+ }
+
+ //
+ // If the protocol entry was not found and Create is TRUE, then
+ // allocate a new entry
+ //
+ if ((ProtEntry == NULL) && Create) {
+ Status = SmmSmstAllocatePool(0,sizeof(SMM_PROTOCOL_ENTRY),&ProtEntry); // ********** Probe whether it works? Typecast to VOID** to make it go thro SmmPiAllocatePool.
+ if (ProtEntry != NULL) {
+ //
+ // Initialize new protocol entry structure
+ //
+ ProtEntry->Signature = SMM_PROTOCOL_ENTRY_SIGNATURE;
+ ProtEntry->ProtocolID = *Protocol; // This done as Core Handle.C function implementation.
+ InitializeListHead (&ProtEntry->Protocols);
+ InitializeListHead (&ProtEntry->Notify);
+
+ //
+ // Add it to protocol database
+ //
+ InsertTailList (&SmmProtocolDatabase, &ProtEntry->AllEntries);
+ }
+ }
+ return ProtEntry;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmFindProtocolInterface
+//
+// Description:
+// Finds the protocol instance for the requested handle and protocol.
+// Note: This function doesn't do parameters checking, it's caller's responsibility
+// to pass in valid parameters.
+//
+// Input:
+// IN SMM_IHANDLE *Handle,
+// IN EFI_GUID *Protocol
+// IN VOID *Interface
+//
+// Output:
+// Protocol instance (NULL: Not found)
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+SMM_PROTOCOL_INTERFACE * SmmFindProtocolInterface (
+ IN SMM_IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+{
+ SMM_PROTOCOL_INTERFACE *Prot;
+ SMM_PROTOCOL_ENTRY *ProtEntry;
+ EFI_LIST_ENTRY *Link;
+
+ Prot = NULL;
+
+ //
+ // Lookup the protocol entry for this protocol ID
+ //
+ ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);
+ if (ProtEntry != NULL) {
+ //
+ // Look at each protocol interface for any matches
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
+ //
+ // If this protocol interface matches, remove it
+ //
+ Prot = CR(Link, SMM_PROTOCOL_INTERFACE, Link, SMM_PROTOCOL_INTERFACE_SIGNATURE);
+ if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
+ break;
+ }
+ Prot = NULL;
+ }
+ }
+ return Prot;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmNotifyProtocol
+//
+// Description: Signal event for every protocol in protocol entry.
+//
+// Input:
+// IN SMM_PROTOCOL_INTERFACE *Prot
+
+// Output:
+// VOID
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SmmNotifyProtocol (
+ IN SMM_PROTOCOL_INTERFACE *Prot
+ )
+{
+ SMM_PROTOCOL_ENTRY *ProtEntry;
+ SMM_PROTOCOL_NOTIFY *ProtNotify;
+ EFI_LIST_ENTRY *Link;
+
+ ProtEntry = Prot->Protocol;
+ for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+ ProtNotify = CR(Link, SMM_PROTOCOL_NOTIFY, Link, SMM_PROTOCOL_NOTIFY_SIGNATURE);
+ ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstInstallProtocolInterface
+//
+// Description:
+// Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which
+// Calls the private one which contains a BOOLEAN parameter for notifications
+//
+// Input:
+// IN OUT EFI_HANDLE *Handle
+// IN EFI_GUID *Protocol
+// IN EFI_INTERFACE_TYPE InterfaceType
+// IN VOID Interface
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstInstallProtocolInterface (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+)
+{
+ return SmmSmstInstallProtocolInterfaceNotify (
+ UserHandle,
+ Protocol,
+ InterfaceType,
+ Interface,
+ TRUE
+ );
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstInstallProtocolInterfaceNotify
+//
+// Description: Installs a protocol interface into the boot services environment.
+
+// Input:
+// IN OUT EFI_HANDLE *UserHandle,
+// IN EFI_GUID *Protocol,
+// IN EFI_INTERFACE_TYPE InterfaceType,
+// IN VOID *Interface,
+// IN BOOLEAN Notify
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SmmSmstInstallProtocolInterfaceNotify (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface,
+ IN BOOLEAN Notify
+)
+{
+ SMM_PROTOCOL_INTERFACE *Prot;
+ SMM_PROTOCOL_ENTRY *ProtEntry;
+ SMM_IHANDLE *Handle;
+ EFI_STATUS Status;
+ VOID *ExistingInterface;
+
+ //
+ // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
+ // Also added check for invalid UserHandle and Protocol pointers.
+ //
+
+ if (UserHandle == NULL || Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterfaceType != EFI_NATIVE_INTERFACE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Print debug message
+ //
+ //DEBUG((DEBUG_LOAD | DEBUG_INFO, "SmmInstallProtocolInterface: %g %p\n", Protocol, Interface));
+
+ Status = EFI_OUT_OF_RESOURCES;
+
+ Prot = NULL;
+ Handle = NULL;
+
+ if (*UserHandle != NULL) {
+ Status = SmmSmstHandleProtocol(*UserHandle, Protocol, (VOID **)&ExistingInterface);
+
+ if (!EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Lookup the Protocol Entry for the requested protocol
+ //
+ ProtEntry = SmmFindProtocolEntry (Protocol, TRUE);
+
+ if (ProtEntry == NULL) {
+ goto Done;
+ }
+
+ //
+ // Allocate a new protocol interface structure
+ //
+ Status = SmmSmstAllocatePool(0,sizeof(SMM_PROTOCOL_INTERFACE),&Prot);
+ MemSet(Prot,(Prot == NULL) ? 0 : sizeof(SMM_PROTOCOL_INTERFACE), 0);
+
+ if (Prot == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // If caller didn't supply a handle, allocate a new one
+ //
+ Handle = (SMM_IHANDLE *)*UserHandle;
+ if (Handle == NULL) {
+ Status = SmmSmstAllocatePool(0,sizeof(SMM_IHANDLE),&Handle);
+ MemSet(Handle,(Handle == NULL) ? 0 : sizeof(SMM_IHANDLE), 0);
+ if (Handle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Initialize new handler structure
+ //
+ Handle->Signature = SMM_EFI_HANDLE_SIGNATURE;
+ InitializeListHead (&Handle->Protocols);
+
+ //
+ // Add this handle to the list global list of all handles
+ // in the system
+ //
+ InsertTailList (&SmmHandleList, &Handle->AllHandles);
+ }
+
+ Status = SmmValidateHandle (Handle);
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Each interface that is added must be unique
+ //
+ ASSERT (SmmFindProtocolInterface (Handle, Protocol, Interface) == NULL);
+
+ //
+ // Initialize the protocol interface structure
+ //
+ Prot->Signature = SMM_PROTOCOL_INTERFACE_SIGNATURE;
+ Prot->Handle = Handle;
+ Prot->Protocol = ProtEntry;
+ Prot->Interface = Interface;
+
+ //
+ // Add this protocol interface to the head of the supported
+ // protocol list for this handle
+ //
+ InsertHeadList (&Handle->Protocols, &Prot->Link);
+
+ //
+ // Add this protocol interface to the tail of the
+ // protocol entry
+ //
+ InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
+
+ //
+ // Notify the notification list for this protocol
+ //
+ if (Notify) {
+ SmmNotifyProtocol (Prot);
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ if (!EFI_ERROR (Status)) {
+ //
+ // Return the new handle back to the caller
+ //
+ *UserHandle = Handle;
+ } else {
+ //
+ // There was an error, clean up
+ //
+ if (Prot != NULL) {
+ SmmSmstFreePool (Prot);
+ }
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstUninstallProtocolInterface
+//
+// Description:
+// Uninstalls all instances of a protocol:interfacer from a handle.
+// If the last protocol interface is remove from the handle, the
+// handle is freed.
+//
+// Input:
+// IN OUT EFI_HANDLE UserHandle
+// IN EFI_GUID *Protocol
+// IN VOID *Interface
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstUninstallProtocolInterface (
+ IN OUT EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+)
+{
+ EFI_STATUS Status;
+ SMM_IHANDLE *Handle;
+ SMM_PROTOCOL_INTERFACE *Prot;
+
+ //
+ // Check that Protocol is valid
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check that UserHandle is a valid handle
+ //
+ Status = SmmValidateHandle (UserHandle);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+ //
+ Prot = SmmFindProtocolInterface (UserHandle, Protocol, Interface);
+
+ if (Prot == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Remove the protocol interface from the protocol
+ //
+ Status = EFI_NOT_FOUND;
+ Handle = (SMM_IHANDLE *)UserHandle;
+
+ Prot = SmmRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
+
+ if (Prot != NULL) {
+ //
+ // Remove the protocol interface from the handle
+ //
+ RemoveEntryList (&Prot->Link);
+
+ //
+ // Free the memory
+ //
+ Prot->Signature = 0;
+ SmmSmstFreePool(Prot);
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // If there are no more handlers for the handle, free the handle
+ //
+ if (IsListEmpty (&Handle->Protocols)) {
+ Handle->Signature = 0;
+ RemoveEntryList (&Handle->AllHandles);
+ SmmSmstFreePool (Handle);
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmRemoveInterfaceFromProtocol
+//
+// Description: Removes Protocol from the protocol list (but not the handle list).
+//
+// Input:
+// IN SMM_IHANDLE *Handle,
+// IN EFI_GUID *Protocol
+// IN VOID *Interface
+//
+// Output: Protocol Entry
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+SMM_PROTOCOL_INTERFACE * SmmRemoveInterfaceFromProtocol (
+ IN SMM_IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+)
+{
+ SMM_PROTOCOL_INTERFACE *Prot;
+ SMM_PROTOCOL_NOTIFY *ProtNotify;
+ SMM_PROTOCOL_ENTRY *ProtEntry;
+ EFI_LIST_ENTRY *Link;
+
+ Prot = SmmFindProtocolInterface (Handle, Protocol, Interface);
+ if (Prot != NULL) {
+ ProtEntry = Prot->Protocol;
+
+ //
+ // If there's a protocol notify location pointing to this entry, back it up one
+ //
+ for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+ ProtNotify = CR(Link, SMM_PROTOCOL_NOTIFY, Link, SMM_PROTOCOL_NOTIFY_SIGNATURE);
+
+ if (ProtNotify->Position == &Prot->ByProtocol) {
+ ProtNotify->Position = Prot->ByProtocol.BackLink;
+ }
+ }
+
+ //
+ // Remove the protocol interface entry
+ //
+ RemoveEntryList (&Prot->ByProtocol);
+ }
+
+ return Prot;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmGetProtocolInterface
+//
+// Description: Locate a certain GUID protocol interface in a Handle's protocols.
+//
+// Input:
+// IN EFI_HANDLE UserHandle,
+// IN EFI_GUID *Protocol
+//
+// Output:
+// The requested protocol interface for the handle.
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+SMM_PROTOCOL_INTERFACE * SmmGetProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol
+)
+{
+ EFI_STATUS Status;
+ SMM_PROTOCOL_ENTRY *ProtEntry;
+ SMM_PROTOCOL_INTERFACE *Prot;
+ SMM_IHANDLE *Handle;
+ EFI_LIST_ENTRY *Link;
+
+ Status = SmmValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Handle = (SMM_IHANDLE *)UserHandle;
+
+ //
+ // Look at each protocol interface for a match
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, SMM_PROTOCOL_INTERFACE, Link, SMM_PROTOCOL_INTERFACE_SIGNATURE);
+ ProtEntry = Prot->Protocol;
+ if (!guidcmp(&ProtEntry->ProtocolID, Protocol)) {
+ return Prot;
+ }
+ }
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstHandleProtocol
+//
+// Description: Queries a handle to determine if it supports a specified protocol.
+//
+// Input:
+// IN OUT EFI_HANDLE UserHandle
+// IN EFI_GUID *Protocol
+// OUT VOID **Interface
+//
+// Output:
+// EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstHandleProtocol (
+ IN OUT EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+)
+{
+ EFI_STATUS Status;
+ SMM_PROTOCOL_INTERFACE *Prot;
+
+ //
+ // Check for invalid Protocol
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check for invalid Interface
+ //
+ if (Interface == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ *Interface = NULL;
+ }
+
+ //
+ // Check for invalid UserHandle
+ //
+ Status = SmmValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Prot = SmmGetProtocolInterface (UserHandle, Protocol);
+ if (Prot == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // This is the protocol interface entry for this protocol
+ //
+ *Interface = Prot->Interface;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstRegisterProtocolNotify
+//
+// Description: Add a new protocol notification record for the request protocol.
+//
+// Input:
+// IN EFI_GUID *Protocol
+// IN EFI_SMM_NOTIFY_FN Function
+// OUT VOID **Registration
+//
+// Output:
+// EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstRegisterProtocolNotify (
+ IN CONST EFI_GUID *Protocol,
+ IN EFI_SMM_NOTIFY_FN Function,
+ OUT VOID **Registration)
+{
+ SMM_PROTOCOL_ENTRY *ProtEntry=NULL;
+ SMM_PROTOCOL_NOTIFY *ProtNotify=NULL;
+ EFI_LIST_ENTRY *Link;
+// EFI_GUID *protocol=(EFI_GUID*)Protocol;
+ EFI_STATUS Status;
+
+ if ((Protocol == NULL) || (Function == NULL) || (Registration == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ProtNotify = NULL;
+
+ //
+ // Get the protocol entry to add the notification too
+ //
+ ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);
+ if (ProtEntry != NULL) {
+ //
+ // Find whether notification already exist
+ //
+ for (Link = ProtEntry->Notify.ForwardLink;
+ Link != &ProtEntry->Notify;
+ Link = Link->ForwardLink) {
+
+ ProtNotify = CR(Link, SMM_PROTOCOL_NOTIFY, Link, SMM_PROTOCOL_NOTIFY_SIGNATURE);
+ if ((!guidcmp(&ProtNotify->Protocol->ProtocolID, (EFI_GUID*)Protocol)) &&
+ (ProtNotify->Function == Function)
+ ) {
+
+ //
+ // Notification already exist
+ //
+ *Registration = ProtNotify;
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Allocate a new notification record
+ //
+ Status = SmmSmstAllocatePool(0,sizeof(SMM_PROTOCOL_NOTIFY),&ProtNotify);
+ ASSERT_EFI_ERROR(Status);
+ if (ProtNotify != NULL) {
+ ProtNotify->Signature = SMM_PROTOCOL_NOTIFY_SIGNATURE;
+ ProtNotify->Protocol = ProtEntry;
+ ProtNotify->Function = Function;
+ //
+ // Start at the ending
+ //
+ ProtNotify->Position = ProtEntry->Protocols.BackLink;
+
+ InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
+ }
+ }
+
+ //
+ // Done. If we have a protocol notify entry, then return it.
+ // Otherwise, we must have run out of resources trying to add one
+ //
+ Status = EFI_OUT_OF_RESOURCES;
+ if (ProtNotify != NULL) {
+ *Registration = ProtNotify;
+ Status = EFI_SUCCESS;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstLocateHandle
+//
+// Description: Locates the requested handle(s) and returns them in Buffer.
+//
+// Input:
+// IN EFI_LOCATE_SEARCH_TYPE SearchType
+// IN EFI_GUID *Protocol OPTIONAL
+// IN VOID *SearchKey OPTIONAL
+// IN OUT UINTN *BufferSize
+// OUT EFI_HANDLE *Buffer
+//
+// Output:
+// EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SmmSmstLocateHandle (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HANDLE *Buffer
+)
+
+{
+ EFI_STATUS Status;
+ SMM_LOCATE_POSITION Position;
+ SMM_PROTOCOL_NOTIFY *ProtNotify;
+ SMM_CORE_GET_NEXT GetNext;
+ UINTN ResultSize;
+ SMM_IHANDLE *Handle;
+ SMM_IHANDLE **ResultBuffer;
+ VOID *Interface;
+
+ if (BufferSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GetNext = NULL;
+
+ //
+ // Set initial position
+ //
+ Position.Protocol = Protocol;
+ Position.SearchKey = SearchKey;
+ Position.Position = &SmmHandleList;
+
+ ResultSize = 0;
+ ResultBuffer = (SMM_IHANDLE **) Buffer;
+ Status = EFI_SUCCESS;
+
+ //
+ // Get the search function based on type
+ //
+ switch (SearchType) {
+ case AllHandles:
+ GetNext = SmmGetNextLocateAllHandles;
+ break;
+
+ case ByRegisterNotify:
+ GetNext = SmmGetNextLocateByRegisterNotify;
+ //
+ // Must have SearchKey for locate ByRegisterNotify
+ //
+ if (SearchKey == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ break;
+ case ByProtocol:
+ GetNext = SmmGetNextLocateByProtocol;
+ if (Protocol == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ //
+ // Look up the protocol entry and set the head pointer
+ //
+ Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);
+ if (Position.ProtEntry == NULL) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ Position.Position = &Position.ProtEntry->Protocols;
+ break;
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Enumerate out the matching handles
+ //
+ mEfiLocateHandleRequest += 1;
+ for (; ;) {
+ //
+ // Get the next handle. If no more handles, stop
+ //
+ Handle = GetNext (&Position, &Interface);
+ if (NULL == Handle) {
+ break;
+ }
+
+ //
+ // Increase the resulting buffer size, and if this handle
+ // fits return it
+ //
+ ResultSize += sizeof(Handle);
+ if (ResultSize <= *BufferSize) {
+ *ResultBuffer = Handle;
+ ResultBuffer += 1;
+ }
+ }
+
+ //
+ // If the result is a zero length buffer, then there were no
+ // matching handles
+ //
+ if (ResultSize == 0) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // Return the resulting buffer size. If it's larger than what
+ // was passed, then set the error code
+ //
+ if (ResultSize > *BufferSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *BufferSize = ResultSize;
+
+ if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
+ ASSERT (SearchKey != NULL);
+ //
+ // If this is a search by register notify and a handle was
+ // returned, update the register notification position
+ //
+ ProtNotify = SearchKey;
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;
+ }
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstLocateProtocol
+//
+// Description:
+// Return the first Protocol Interface that matches the Protocol GUID. If
+// Registration is passed in, return a Protocol Instance that was just add
+// to the system. If Registration is NULL return the first Protocol Interface
+// you find.
+//
+// Input:
+// IN EFI_GUID *Protocol,
+// IN VOID *Registration OPTIONAL
+// OUT VOID **Interface
+//
+// Output:
+// EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+)
+{
+ EFI_STATUS Status;
+ SMM_LOCATE_POSITION Position;
+ SMM_PROTOCOL_NOTIFY *ProtNotify;
+ SMM_IHANDLE *Handle;
+
+ if (Interface == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Protocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Interface = NULL;
+ Status = EFI_SUCCESS;
+ //
+ // Set initial position
+ //
+ Position.Protocol = Protocol;
+ Position.SearchKey = Registration;
+ Position.Position = &SmmHandleList;
+
+ mEfiLocateHandleRequest += 1;
+
+ if (Registration == NULL) {
+ //
+ // Look up the protocol entry and set the head pointer
+ //
+ Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);
+ if (Position.ProtEntry == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ Position.Position = &Position.ProtEntry->Protocols;
+
+ Handle = SmmGetNextLocateByProtocol (&Position, Interface);
+ } else {
+ Handle = SmmGetNextLocateByRegisterNotify (&Position, Interface);
+ }
+
+ if (Handle == NULL) {
+ Status = EFI_NOT_FOUND;
+ } else if (Registration != NULL) {
+ //
+ // If this is a search by register notify and a handle was
+ // returned, update the register notification position
+ //
+ ProtNotify = Registration;
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmGetNextLocateAllHandles
+//
+// Description:
+// Find next handle.
+//
+// Input:
+// IN OUT SMM_LOCATE_POSITION *Position,
+// OUT VOID **Interface
+//
+// Output:
+// SMM_IHANDLE
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+SMM_IHANDLE *SmmGetNextLocateAllHandles (
+ IN OUT SMM_LOCATE_POSITION *Position,
+ OUT VOID **Interface
+)
+{
+ SMM_IHANDLE *Handle;
+
+ //
+ // Next handle
+ //
+ Position->Position = Position->Position->ForwardLink;
+
+ //
+ // If not at the end of the list, get the handle
+ //
+ Handle = NULL;
+ *Interface = NULL;
+ if (Position->Position != &SmmHandleList) {
+ Handle = CR (Position->Position, SMM_IHANDLE, AllHandles, SMM_EFI_HANDLE_SIGNATURE);
+ }
+ return Handle;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmGetNextLocateByRegisterNotify
+//
+// Description: Routine to get the next Handle, when you are searching for register protocol
+// notifies.
+//
+// Input:
+// IN OUT SMM_LOCATE_POSITION *Position
+// OUT VOID **Interface
+//
+// Output:
+// An pointer to SMM_IHANDLE if the next Position is not the end of the list.
+// Otherwise,NULL is returned.
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+SMM_IHANDLE *SmmGetNextLocateByRegisterNotify (
+ IN OUT SMM_LOCATE_POSITION *Position,
+ OUT VOID **Interface
+)
+{
+ SMM_IHANDLE *Handle;
+ SMM_PROTOCOL_NOTIFY *ProtNotify;
+ SMM_PROTOCOL_INTERFACE *Prot;
+ EFI_LIST_ENTRY *Link;
+
+ Handle = NULL;
+ *Interface = NULL;
+ ProtNotify = Position->SearchKey;
+
+ //
+ // If this is the first request, get the next handle
+ //
+ if (ProtNotify != NULL) {
+ ASSERT(ProtNotify->Signature == SMM_PROTOCOL_NOTIFY_SIGNATURE);
+ Position->SearchKey = NULL;
+
+ //
+ // If not at the end of the list, get the next handle
+ //
+ Link = ProtNotify->Position->ForwardLink;
+ if (Link != &ProtNotify->Protocol->Protocols) {
+ Prot = CR (Link, SMM_PROTOCOL_INTERFACE, ByProtocol, SMM_PROTOCOL_INTERFACE_SIGNATURE);
+ Handle = Prot->Handle;
+ *Interface = Prot->Interface;
+ }
+ }
+ return Handle;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmGetNextLocateByProtocol
+//
+// Description: Routine to get the next Handle, when you are searching for a given protocol.
+//
+// Input:
+// IN OUT SMM_LOCATE_POSITION *Position
+// OUT VOID **Interface
+//
+// Output:
+// An pointer to SMM_IHANDLE if the next Position is not the end of the list.
+// Otherwise,NULL is returned.
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+SMM_IHANDLE *SmmGetNextLocateByProtocol (
+ IN OUT SMM_LOCATE_POSITION *Position,
+ OUT VOID **Interface
+)
+{
+ SMM_IHANDLE *Handle;
+ EFI_LIST_ENTRY *Link;
+ SMM_PROTOCOL_INTERFACE *Prot;
+
+ Handle = NULL;
+ *Interface = NULL;
+
+ for (; ;) {
+ //
+ // Next entry
+ //
+ Link = Position->Position->ForwardLink;
+ Position->Position = Link;
+
+ //
+ // If not at the end, return the handle
+ //
+ if (Link == &Position->ProtEntry->Protocols) {
+ Handle = NULL;
+ break;
+ }
+
+ //
+ // Get the handle
+ //
+ Prot = CR(Link, SMM_PROTOCOL_INTERFACE, ByProtocol, SMM_PROTOCOL_INTERFACE_SIGNATURE);
+ Handle = Prot->Handle;
+ *Interface = Prot->Interface;
+
+ //
+ // If this handle has not been returned this request, then
+ // return it now
+ //
+ if (Handle->LocateRequest != mEfiLocateHandleRequest) {
+ Handle->LocateRequest = mEfiLocateHandleRequest;
+ break;
+ }
+ }
+ return Handle;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmCoreFindSmiEntry
+//
+// Description: Find Smi Entry
+//
+// Input:
+// IN EFI_GUID *HandlerType
+// IN BOOLEAN Create
+//
+// Output: SMM_SMI_ENTRY
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+SMM_SMI_ENTRY* SmmCoreFindSmiEntry (
+ IN EFI_GUID *HandlerType,
+ IN BOOLEAN Create
+)
+{
+ EFI_LIST_ENTRY *Link;
+ SMM_SMI_ENTRY *Item;
+ SMM_SMI_ENTRY *SmiEntry;
+ EFI_STATUS Status;
+
+ //
+ // Search the SMI entry list for the matching GUID
+ //
+ SmiEntry = NULL;
+ for (Link = mSmiEntryList.ForwardLink;
+ Link != &mSmiEntryList;
+ Link = Link->ForwardLink) {
+
+ Item = CR (Link, SMM_SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
+ if (!guidcmp(&Item->HandlerType, HandlerType)) {
+ //
+ // This is the SMI entry
+ //
+ SmiEntry = Item;
+ break;
+ }
+ }
+
+ //
+ // If the protocol entry was not found and Create is TRUE, then
+ // allocate a new entry
+ //
+ if ((SmiEntry == NULL) && Create) {
+ Status = SmmSmstAllocatePool (0,sizeof(SMM_SMI_ENTRY),&SmiEntry);
+ if (EFI_ERROR(Status) || (SmiEntry != NULL)) {
+ //
+ // Initialize new SMI entry structure
+ //
+ SmiEntry->Signature = SMI_ENTRY_SIGNATURE;
+ MemCpy((VOID *)&SmiEntry->HandlerType, HandlerType, sizeof(EFI_GUID));
+ InitializeListHead (&SmiEntry->SmiHandlers);
+
+ // Add it to SMI entry list
+ InsertTailList (&mSmiEntryList, &SmiEntry->AllEntries);
+ }
+ }
+ return SmiEntry;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmiHandlerRegister
+//
+// Description: Register SMI Handle
+//
+// Input:
+// IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
+// IN CONST EFI_GUID *HandlerType OPTIONAL,
+// OUT EFI_HANDLE *DispatchHandle
+//
+// Output: EFI_STATUS
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmiHandlerRegister(
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
+ IN CONST EFI_GUID *HandlerType OPTIONAL,
+ OUT EFI_HANDLE *DispatchHandle
+)
+{
+ HANDLER_LIST *HandlerInfo, *Link;
+
+ if (gSmmSystemTable2.SmmAllocatePool(0, sizeof(HANDLER_LIST), &HandlerInfo) != EFI_SUCCESS)
+ return EFI_OUT_OF_RESOURCES;
+
+ HandlerInfo->IsPi = TRUE;
+ HandlerInfo->EntryPoint = Handler;
+ HandlerInfo->SmmImageHandle = HandlerInfo;
+ if (HandlerType) {
+ MemCpy(&HandlerInfo->HandlerType, (EFI_GUID*)HandlerType, sizeof(EFI_GUID));
+ HandlerInfo->IsRoot = FALSE;
+ } else HandlerInfo->IsRoot = TRUE;
+
+ HandlerInfo->Link = 0;
+
+ //If very first add.
+ if (!gDispatcherPrivate->HandlerListHead) {
+ gDispatcherPrivate->HandlerListHead = HandlerInfo;
+ return EFI_SUCCESS;
+ }
+
+ //Add to end of list.
+ for (Link = gDispatcherPrivate->HandlerListHead; Link->Link; Link = Link->Link); //Find end of list
+ Link->Link = HandlerInfo;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS SmiHandlerUnRegister(IN EFI_HANDLE DispatchHandle)
+{
+ HANDLER_LIST *Link = gDispatcherPrivate->HandlerListHead;
+ HANDLER_LIST *PrevLink;
+
+ while (Link != 0) {
+ if (Link->SmmImageHandle == DispatchHandle) {
+ if (Link == gDispatcherPrivate->HandlerListHead) {
+ gDispatcherPrivate->HandlerListHead = Link->Link;
+ } else {
+ PrevLink->Link = Link->Link;
+ }
+ SmmSmstFreePool(Link);
+ return EFI_SUCCESS;
+ }
+ PrevLink = Link;
+ Link = Link->Link;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_SMM_SYSTEM_TABLE2 gSmmSystemTable2 =
+{
+ { //Header
+ SMM_SMST_SIGNATURE2, //Signature
+ EFI_SMM_SYSTEM_TABLE_REVISION2, //Revison will show 1.1
+ sizeof(EFI_SMM_SYSTEM_TABLE2), //Header size
+ 0, //CRC32
+ 0 //Reserved
+ },
+ gSmmFirmwareVendor, //Vendor
+ 0, //Vendor version
+
+ SmmInstallConfigurationTable,
+ {
+ {
+ SmmMemRead,
+ SmmMemWrite
+ },
+ {
+ SmmIoRead,
+ SmmIoWrite
+ }
+ },
+ SmmSmstAllocatePool,
+ SmmSmstFreePool,
+ SmmSmstAllocatePages,
+ SmmSmstFreePages,
+ SmmStartupThisAp,
+ 1, //Executing CPU
+ 1, //Number of CPUs
+ 0, //CpuSaveStateSize...PI 1.1
+ 0, //Cpu Save State
+ 0, //Number of Table Entries
+ 0, //Table pointer
+ SmmSmstInstallProtocolInterface,
+ SmmSmstUninstallProtocolInterface,
+ SmmSmstHandleProtocol,
+ SmmSmstRegisterProtocolNotify,
+ SmmSmstLocateHandle,
+ SmmSmstLocateProtocol,
+ InterruptManage,
+ SmiHandlerRegister,
+ SmiHandlerUnRegister
+};
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InsertTailList
+//
+// Description:
+// Insert a Node into the end of a doubly linked list. The list must have
+// been initialized with InitializeListHead () before using this function.
+//
+//
+// Input:
+// IN EFI_LIST_ENTRY *ListHead
+// IN EFI_LIST_ENTRY *Entry
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InsertTailList (
+ IN EFI_LIST_ENTRY *ListHead,
+ IN EFI_LIST_ENTRY *Entry
+)
+{
+ EFI_LIST_ENTRY *_ListHead;
+ EFI_LIST_ENTRY *_BackLink;
+
+ _ListHead = ListHead;
+ _BackLink = _ListHead->BackLink;
+ Entry->ForwardLink = _ListHead;
+ Entry->BackLink = _BackLink;
+ _BackLink->ForwardLink = Entry;
+ _ListHead->BackLink = Entry;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InsertHeadList
+//
+// Description:
+// Insert a Node into the start of a doubly linked list. The list must have
+// been initialized with InitializeListHead () before using this function.
+//
+// Input:
+// IN EFI_LIST_ENTRY *ListHead
+// IN EFI_LIST_ENTRY *Entry
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InsertHeadList (
+ IN EFI_LIST_ENTRY *ListHead,
+ IN EFI_LIST_ENTRY *Entry
+)
+{
+ EFI_LIST_ENTRY *_ListHead;
+ EFI_LIST_ENTRY *_ForwardLink;
+
+ _ListHead = ListHead;
+ _ForwardLink = _ListHead->ForwardLink;
+ Entry->ForwardLink = _ForwardLink;
+ Entry->BackLink = _ListHead;
+ _ForwardLink->BackLink = Entry;
+ _ListHead->ForwardLink = Entry;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitializeListHead
+//
+// Description:
+// Initialize the head of the List. The caller must allocate the memory
+// for the EFI_LIST. This function must be called before the other linked
+// list macros can be used.
+//
+// Input:
+// IN EFI_LIST_ENTRY *List
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InitializeListHead (
+ IN EFI_LIST_ENTRY *List
+)
+{
+ List->ForwardLink = List;
+ List->BackLink = List;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsListEmpty
+//
+// Description:
+// Return TRUE is the list contains zero nodes. Otherwise return FALSE.
+// The list must have been initialized with InitializeListHead () before using
+// this function.
+//
+// Input:
+// IN EFI_LIST_ENTRY *List
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsListEmpty (
+ IN EFI_LIST_ENTRY *List
+)
+{
+ return (BOOLEAN)(List->ForwardLink == List);
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RemoveEntryList
+//
+// Description:
+// Remove Node from the doubly linked list. It is the caller's responsibility
+// to free any memory used by the entry if needed. The list must have been
+// initialized with InitializeListHead () before using this function.
+//
+// Input:
+// IN EFI_LIST_ENTRY *Entry
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID RemoveEntryList (
+ EFI_LIST_ENTRY *Entry
+)
+{
+ EFI_LIST_ENTRY *_ForwardLink;
+ EFI_LIST_ENTRY *_BackLink;
+
+ _ForwardLink = Entry->ForwardLink;
+ _BackLink = Entry->BackLink;
+ _BackLink->ForwardLink = _ForwardLink;
+ _ForwardLink->BackLink = _BackLink;
+
+#if EFI_DEBUG
+ Entry->ForwardLink = (EFI_LIST_ENTRY *) 0xAFAFAFAF;
+ Entry->BackLink = (EFI_LIST_ENTRY *) 0xAFAFAFAF;
+#endif
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitializeSmmPiSystemTable
+//
+// Description:
+// Initialize SMM PI System Table.
+//
+// Input: VOID
+//
+// Output: VOID
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InitializeSmmPiSystemTable()
+{
+ UINT32 CRC32;
+ UINT32 NumCpus = gDispatcherPrivate->NumCpus;
+ UINT32 i;
+
+ gSmmSystemTable2.NumberOfCpus = NumCpus;
+
+ gSmmSystemTable2.CpuSaveStateSize = Allocate(0,sizeof(UINTN) * NumCpus,0);
+ for (i = 0; i < NumCpus; ++i) gSmmSystemTable2.CpuSaveStateSize[i] = MAX_SMM_SAVE_STATE_SIZE;
+
+ gSmmSystemTable2.CpuSaveState = Allocate(0,sizeof(VOID*) * NumCpus,0);
+ for (i = 0; i < NumCpus; ++i) {
+ gSmmSystemTable2.CpuSaveState[i] = (VOID*)(gSmmBase[i] + 0x10000 - MAX_SMM_SAVE_STATE_SIZE);
+ }
+
+ CalculateCrc32(&gSmmSystemTable2, sizeof(EFI_SMM_SYSTEM_TABLE2), &CRC32);
+ gSmmSystemTable2.Hdr.CRC32 = CRC32;
+
+ gEfiSmmEntryContext.SmmStartupThisAp = gSmmSystemTable2.SmmStartupThisAp;
+ gEfiSmmEntryContext.NumberOfCpus = gSmmSystemTable2.NumberOfCpus;
+ gEfiSmmEntryContext.CpuSaveStateSize = gSmmSystemTable2.CpuSaveStateSize;
+ gEfiSmmEntryContext.CpuSaveState = gSmmSystemTable2.CpuSaveState;
+}
+#endif
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/SmmPrivateShared.h b/Core/EM/SMM/SmmPrivateShared.h
new file mode 100644
index 0000000..46f94e9
--- /dev/null
+++ b/Core/EM/SMM/SmmPrivateShared.h
@@ -0,0 +1,392 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SMM/SmmPrivateShared.h 36 4/01/11 10:08a Markw $
+//
+// $Revision: 36 $
+//
+// $Date: 4/01/11 10:08a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMM/SmmPrivateShared.h $
+//
+// 36 4/01/11 10:08a 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
+//
+//
+// 35 2/07/11 4:07p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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
+//
+// 34 8/11/09 11:46a Markw
+// Removed Legacy registration. This is removed from latest PI and not
+// used by projects.
+//
+// 33 7/08/09 8:04p Markw
+// Update headers.
+//
+// 32 1/22/09 12:59p Markw
+// EIP #18671 (OPEN) Clear SW SMI status and set EOS inside SMM. Add
+// SmmControl to private structure.
+//
+// 31 12/24/08 10:53a Markw
+// EIP #18423: Adjust EBDA location as more EBDA data is allocated.
+//
+// 30 12/23/08 2:15p Markw
+// EIP #17900 Set up TSS. Borland C in DOS hangs otherwise.
+//
+// 29 11/21/08 4:56p Markw
+// Add SmmInit to SMM_ENTRY_STRUCT for SMM init for first normal/S3 boot.
+// 32-bit CPU count.
+//
+// 28 9/26/08 4:52p Markw
+// The Private InSmm is now a pointer.
+//
+// 27 9/09/08 3:05p Markw
+// Add in SMM_BASE_PRIVATE_STRUCT, Dispatcher pe32 Image Start.
+//
+// 26 9/07/08 12:41a Markw
+// Separate SMM Private structure into inside SMM and outside SMM
+// structure.
+//
+// 25 8/28/08 3:51p Markw
+// Added support for saving/restoring chipset context.
+//
+// 24 6/09/08 5:57p Markw
+// Add SMM_CPU_INFO for Cpu specific information in the Private structure.
+//
+// 23 5/23/08 11:18a Markw
+// Add member for disallowing callbacks.
+//
+// 22 4/04/08 6:21p Markw
+// Add Smrr MSR to SMM_BASE_PRIVATE_STRUCT.
+//
+// 21 3/03/08 6:35p Markw
+// Added 32-bit register for smm thunk.
+//
+// 20 11/14/07 2:03p Markw
+// Added SMRR support and updated SMM Cache for non-SMRR.
+//
+// 19 10/29/07 10:58a Markw
+// Smm Thunk:
+// * Code and data different segments.
+// * Code position independent.
+// * Switch for CSM for code and EBDA for data.
+//
+// 18 10/24/07 12:00p Markw
+// SMM Thunk code position independent. Data in a separate segment than
+// code in Smm Thunk.
+//
+// 17 9/10/07 1:38p Markw
+// Add IDT entry.
+//
+// 16 6/08/07 6:51p Markw
+// Save/Restore XMM.
+//
+// 15 1/11/07 12:28p Markw
+// Adjusted location of fields in structure for removal of legacy.
+//
+// 14 1/09/07 6:40p Markw
+// Update BSP Entry Structure to remove dependencies on SMM_BSP_BASE.
+//
+// 13 12/29/06 4:44p Markw
+// Add Smm Cache Support and update CPU syncronization.
+//
+// 12 12/21/06 5:19p Markw
+// Remove old unused SmmStackSize from Private structure.
+//
+// 11 11/13/06 11:24a Markw
+// Updated structure for Ap Entry.
+//
+// 10 9/18/06 11:47a Markw
+// Add a check to guarentee that BSP and Ap can't get out of sync.
+//
+// 9 8/24/06 3:27p Felixp
+// Preliminary x64 support (work in progress)
+//
+// 8 5/08/06 6:47p Markw
+// Use Hob for initalizing SMM.
+//
+// 7 2/03/06 10:26a Markw
+// Moved Smm Base change to PEI CPU.
+//
+// 6 1/13/06 11:27a Markw
+// Added SMM Thunk support.
+//
+// 5 1/10/06 2:56p Markw
+// Add support for multi-threadding and sync all CPUs during entry/exit of
+// SMM.
+//
+// 4 8/10/05 5:01p Markw
+// Added ChangeBaseInfo Structure for changing bases and passing
+// information to a runtime function.
+//
+// 3 7/12/05 11:08a Markw
+// Added TSEG start to private structure.
+//
+// 2 7/11/05 1:05p Markw
+// Removed isCallback from structure. Chaged Io Port from UINT8 to UINT16.
+//
+// 1 1/28/05 4:29p Sivagarn
+// Generic SMM module - Intial Check in
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SMMPrivateShared.h
+//
+// Description: Header file for the SMM shared equates and structures
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef __SMM_PRIVATE_SHARED__H__
+#define __SMM_PRIVATE_SHARED__H__
+
+#include <efi.h>
+#include <Protocol\SmmThunk.h>
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x00010000)
+#define USE_FV2 1
+#else
+#define USE_FV2 0
+#endif
+
+#define SMM_USE_FRAMEWORK 1
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+#define SMM_USE_PI 1
+#else
+#define SMM_USE_PI 0
+#endif
+
+#include <AmiHobs.h>
+#include <Token.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SMMBASE_CALLBACK 0xf0
+typedef struct _SMM_ENTRY_INIT_STRUCT SMM_ENTRY_INIT_STRUCT;
+typedef struct _SMM_THUNK_DATA SMM_THUNK_DATA;
+
+typedef VOID (*SMM_AP_PROCEDURE) (
+ IN VOID *Buffer
+);
+
+typedef struct {
+ SMM_AP_PROCEDURE Procedure;
+ VOID *ProcArguments;
+} SMM_AP_CPU_CONTROL;
+
+
+typedef struct _HANDLER_LIST HANDLER_LIST;
+struct _HANDLER_LIST
+{
+ EFI_GUID HandlerType; //Only filled if non-root.
+ VOID *EntryPoint;
+ EFI_HANDLE SmmImageHandle;
+ VOID *Context;
+ VOID *CommunicationBuffer; //Framework only
+ UINTN *SourceSize; //Framework only
+
+ BOOLEAN IsRoot;
+ BOOLEAN IsPi;
+ HANDLER_LIST *Link;
+};
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ VOID *SourceBuffer;
+ UINTN SourceSize;
+ EFI_HANDLE *ImageHandle;
+ BOOLEAN LegacyIA32Binary;
+} REGISTER_HANDLER_CALLBACK;
+
+typedef struct {
+ EFI_HANDLE ImageHandle;
+} UNREGISTER_HANDLER_CALLBACK;
+
+typedef struct {
+ EFI_HANDLE ImageHandle;
+ VOID *CommunicationBuffer;
+ UINTN *SourceSize;
+} COMMUNICATE_CALLBACK;
+
+typedef struct {
+ UINTN Size;
+ VOID **Buffer;
+} ALLOCATE_POOL_CALLBACK;
+
+typedef struct {
+ VOID *Buffer;
+} FREE_POOL_CALLBACK;
+
+
+typedef union {
+ REGISTER_HANDLER_CALLBACK RegisterHandler;
+ UNREGISTER_HANDLER_CALLBACK UnregisterHandler;
+ COMMUNICATE_CALLBACK Communicate;
+ ALLOCATE_POOL_CALLBACK AllocatePool;
+ FREE_POOL_CALLBACK FreePool;
+} CALLBACKS;
+
+#pragma pack (1)
+typedef struct {
+ UINT16 Limit;
+ UINTN Base; //This shared between 32 bit and 64 bit.
+} DESCRIPTOR_TABLE;
+#pragma pack()
+
+typedef struct {
+ BOOLEAN InSmm;
+ UINT32 ApicId;
+} SMM_CPU_INFO;
+
+typedef struct {
+ VOID (*CallBackFunc)();
+ BOOLEAN *InSmm;
+ BOOLEAN DisallowCallbacks;
+ EFI_STATUS CallbackStatus;
+ VOID *Pe32DispatcherImage;
+ UINTN Pe32DispatcherImageSize;
+
+ CALLBACKS CallbackParameters;
+ SMM_HOB *SmmHob;
+ VOID *SmmAllocMemoryStart; //Area to allocate memory
+ UINT32 SmmAllocMemoryLength;
+} SMM_BASE_PRIVATE_STRUCT;
+
+typedef struct {
+ VOID *PageDirectories;
+ VOID **SmmXmmSave;
+ BOOLEAN SmrrEnable;
+ UINT32 SmrrMsr;
+ UINT32 TsegMsr;
+ UINT64 TsegMsrBase;
+ UINT64 TsegMsrMask;
+ DESCRIPTOR_TABLE Idt;
+ SMM_CPU_INFO *SmmCpuInfo;
+
+ VOID (*SmmThunkProc)();
+ SMM_THUNK_DATA *SmmThunkData;
+ UINT32 EbdaStartOffset;
+ UINT32 NumCpus;
+ UINT32 NumCpusInSmm;
+
+ HANDLER_LIST *HandlerListHead;
+ BOOLEAN FloatingPointSave;
+
+ volatile SMM_AP_CPU_CONTROL *SmmApCpuControl;
+ UINT32 SmmBspNumber; //This can change each SMM entry.
+ VOID *SmmControl;
+} SMM_DISPATCHER_PRIVATE_STRUCT;
+
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Offset;
+ UINT16 Segment;
+} FAR_CALL_PTR_16;
+
+typedef struct {
+ UINT32 Stack;
+ UINT32 StackSize;
+} STACK;
+
+typedef struct {
+ UINT16 Limit;
+ UINT32 Base;
+ UINT16 Rsv; //For alignment
+} SMM_DESC;
+
+#pragma pack()
+
+struct _SMM_ENTRY_INIT_STRUCT {
+ UINT32 SmmInit; //This must be first.
+ UINT32 SmmEntrySize;
+ UINT32 GdtDescBaseOffset;
+ UINT32 LCodeSelBaseOffset;
+ UINT32 TssSelBaseOffset;
+ UINT32 SmmThunkProcOffset;
+ UINT32 SmmThunkLength;
+ UINT32 HtCpu;
+ VOID *SmmEntryStart;
+ VOID (*DispatcherEntry)(SMM_ENTRY_INIT_STRUCT *);
+ SMM_DISPATCHER_PRIVATE_STRUCT *DispatcherPrivate;
+ UINT8 *SmmStackTop;
+ UINT32 CpuNo;
+};
+
+struct _SMM_THUNK_DATA {
+ FAR_CALL_PTR_16 FarCall;
+ SMM_THUNK_IA32_REGISTER_SET_EX Regs;
+ STACK Stack;
+ UINT32 StackSave;
+ SMM_DESC GdtSave;
+ SMM_DESC IdtSave;
+ SMM_DESC LegacyIdtDesc;
+ UINT16 Below1MStack;
+};
+
+typedef EFI_STATUS (*DISPATCHER_ENTRY_POINT)(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN SMM_BASE_PRIVATE_STRUCT *BasePrivate,
+ IN SMM_DISPATCHER_PRIVATE_STRUCT *DispatcherPrivate,
+ OUT VOID **SmstTable,
+ OUT VOID **SmstTable2
+);
+
+
+typedef VOID (*EFI_SMM_SAVE_RESTORE_FUNCTION)(BOOLEAN Save);
+
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/SMM/Smst.c b/Core/EM/SMM/Smst.c
new file mode 100644
index 0000000..8ac8add
--- /dev/null
+++ b/Core/EM/SMM/Smst.c
@@ -0,0 +1,917 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (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/Smst.c 2 11/21/12 4:07a Wesleychen $
+//
+// $Revision: 2 $
+//
+// $Date: 11/21/12 4:07a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/SMM/Smst.c $
+//
+// 2 11/21/12 4:07a Wesleychen
+// Support Intel PFAT.
+//
+// 25 3/14/11 3:18p Markw
+// Rename gSmmFirmwareVender to gSmmFirmwareVendor.
+//
+// 24 2/07/11 3:29p Markw
+// [TAG] EIP53481
+// [Category] New Feature
+// [Description] Add PIWG 1.1 SMM support
+// [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
+//
+// 23 6/18/10 12:29p Markw
+// Fix history log.
+//
+// 22 4/22/10 6:22p Markw
+// Support /w4 compilier option.
+//
+// 21 2/25/10 5:16p Markw
+// Add support for all APs to execute non-blocking.
+// Fixed issue with memory allocation
+//
+// 20 2/12/10 3:54p Markw
+// Update SmmSmstAllocatePages for AllocateAddress to return correct
+// Status.
+//
+// 19 5/08/09 10:55a Markw
+// Header updates.
+//
+// 18 11/05/08 5:25p Markw
+// Fix SMM Allocate Pool of type AllocateMaxAddress.
+//
+// 17 9/09/08 4:30p Markw
+// Add headers.
+//
+// 16 9/07/08 12:45a Markw
+// Separate SMM Private structure into inside SMM and outside SMM
+// structure. Remove access to BS function for CRC.
+//
+// 15 6/09/08 5:47p Markw
+// CPU0 has its own AP control structure. CPU0 can now be the AP.
+//
+// 14 3/14/07 5:57p Markw
+// Only allow SmmStartupThisAp if all CPUs are in SMM.
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Smst.c
+//
+// Description: Smst functions.
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//This include should come first.
+#include "SmmPrivateShared.h"
+#include <AmiDxeLib.h>
+#include <AmiCspLib.h>
+
+#if SMM_USE_FRAMEWORK
+#include <Smm.h>
+#endif
+
+#if SMM_USE_PI
+#include <SmmPi.h>
+#endif
+
+#include "ReferenceCode\Haswell\Include\CpuRegs.h"
+#ifndef BIT35
+#define BIT35 0x0000000800000000ULL
+#endif
+
+//TODOx64: move it to a library header
+VOID CPULib_Pause();
+
+VOID *Allocate(VOID *Base, UINTN Size,UINTN Alignment);
+
+EFI_STATUS AllocateABSegPages(
+ IN EFI_ALLOCATE_TYPE Type,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+);
+EFI_STATUS FreeABSegPages(
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+);
+
+BOOLEAN Free(VOID *Buffer);
+BOOLEAN Free4kPages(VOID *StartAddress,UINTN Pages);
+
+UINT8* Align2n(UINT8 *Value,UINTN Alignment);
+
+#if SMM_USE_FRAMEWORK
+
+EFI_STATUS CalculateCrc32(
+ IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32
+);
+
+extern EFI_SMM_SYSTEM_TABLE gSmmSystemTable;
+extern UINT8 **gSmmBase;
+#endif
+
+#if SMM_USE_PI
+extern EFI_SMM_SYSTEM_TABLE2 gSmmSystemTable2;
+#endif
+
+
+extern SMM_DISPATCHER_PRIVATE_STRUCT *gDispatcherPrivate;
+
+static UINT32 CrcTable[256];
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitCrc
+//
+// Description: InitCrc
+//
+// Input: VOID
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InitCrc()
+{
+ UINT32 i, j;
+ for(i = 0; i < 256; i++) {
+ CrcTable[i] = i;
+ for(j = 8; j > 0; j--)
+ CrcTable[i] =
+ (CrcTable[i] & 1) ? (CrcTable[i] >> 1) ^ 0xedb88320 : CrcTable[i] >> 1;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CalculateCrc32
+//
+// Description: Calculate Crc 32
+//
+// Input:
+// IN VOID *Data
+// IN UINTN DataSize
+// OUT UINT32 *Crc32
+//
+// Output:
+// EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS CalculateCrc32(
+ IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32
+)
+{
+ UINT32 i, crc = (UINT32)-1;
+ if (!Data || !DataSize || !Crc32) return EFI_INVALID_PARAMETER;
+ for(i = 0; i < DataSize; i++) crc = (crc >> 8) ^ CrcTable[(UINT8)crc ^ ((UINT8*)Data)[i]];
+ *Crc32 = ~crc;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmMemRead
+//
+// Description: Read memory buffer.
+//
+// Input:
+// IN EFI_SMM_CPU_IO_INTERFACE *This
+// IN EFI_SMM_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Buffer written Successfully.
+// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmMemRead(
+ IN EFI_SMM_CPU_IO_INTERFACE *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ UINT8 ByteWidth;
+ if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER;
+ if (!Count) return EFI_INVALID_PARAMETER;
+
+ ByteWidth = (UINT8)(1 << Width);
+
+
+ //Alignment must be done by the caller.
+ switch(ByteWidth) {
+ case 1:
+ while(Count--) {
+ *(UINT8*)Buffer = *(UINT8*)(UINTN)Address;
+ ++((UINT8*)(UINTN)Buffer);
+ ++((UINT8*)(UINTN)Address);
+ }
+ break;
+ case 2:
+ while(Count--) {
+ *(UINT16*)Buffer = *(UINT16*)(UINTN)Address;
+ ++((UINT16*)(UINTN)Buffer);
+ ++((UINT16*)(UINTN)Address);
+ }
+ break;
+ default: //case 4:
+ while(Count--) {
+ *(UINT32*)Buffer = *(UINT32*)(UINTN)Address;
+ ++((UINT32*)(UINTN)Buffer);
+ ++((UINT32*)(UINTN)Address);
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmMemWrite
+//
+// Description: Write to memory from buffer.
+//
+// Input:
+// IN EFI_SMM_CPU_IO_INTERFACE *This
+// IN EFI_SMM_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Buffer written Successfully.
+// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmMemWrite(
+ IN EFI_SMM_CPU_IO_INTERFACE *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT8 ByteWidth;
+ if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER;
+ if (!Count) return EFI_INVALID_PARAMETER;
+
+ //Alignment must be done by the caller.
+ ByteWidth = (UINT8)(1 << Width);
+
+ switch(ByteWidth) {
+ case 1:
+ while(Count--) {
+ *(UINT8*)(UINTN)Address = *(UINT8*)(UINTN)Buffer;
+ ++((UINT8*)(UINTN)Buffer);
+ ++((UINT8*)(UINTN)Address);
+ }
+ break;
+ case 2:
+ while(Count--) {
+ *(UINT16*)(UINTN)Address = *(UINT16*)(UINTN)Buffer;
+ ++((UINT16*)(UINTN)Buffer);
+ ++((UINT16*)(UINTN)Address);
+ }
+ break;
+ default: //case 4:
+ while(Count--) {
+ *(UINT32*)(UINTN)Address = *(UINT32*)(UINTN)Buffer;
+ ++((UINT32*)(UINTN)Buffer);
+ ++((UINT32*)(UINTN)Address);
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmIoRead
+//
+// Description: Read io buffer.
+//
+// Input:
+// IN EFI_SMM_CPU_IO_INTERFACE *This
+// IN EFI_SMM_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Buffer written Successfully.
+// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmIoRead(
+ IN EFI_SMM_CPU_IO_INTERFACE *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT8 ByteWidth;
+ if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER;
+ if (!Count) return EFI_INVALID_PARAMETER;
+
+ ByteWidth = (UINT8)(1 << Width);
+
+ if (Address + ByteWidth * Count > 0x10000) return EFI_INVALID_PARAMETER; //Beyond IO space.
+ if ((UINT64)(UINTN)Buffer + ByteWidth * Count > (UINT64)0x100000000) return EFI_INVALID_PARAMETER; //Beyond address space.
+
+ //Alignment must be done by the caller.
+ switch(ByteWidth) {
+ case 1:
+ while(Count--) {
+ *(UINT8*)Buffer = IoRead8((UINT16)Address);
+ ++((UINT8*)(UINTN)Buffer);
+ ++((UINT8*)(UINTN)Address);
+ }
+ break;
+ case 2:
+ while(Count--) {
+ *(UINT16*)(UINTN)Buffer = IoRead16((UINT16)Address);
+ ++((UINT16*)(UINTN)Buffer);
+ ++((UINT16*)(UINTN)Address);
+ }
+ break;
+ default: //case 4:
+ while(Count--) {
+ *(UINT32*)Buffer = IoRead32((UINT16)Address);
+ ++((UINT32*)(UINTN)Buffer);
+ ++((UINT32*)(UINTN)Address);
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmIoWrite
+//
+// Description: Write to Io from buffer.
+//
+// Input:
+// IN EFI_SMM_CPU_IO_INTERFACE *This
+// IN EFI_SMM_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Buffer written Successfully.
+// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmIoWrite(
+ IN EFI_SMM_CPU_IO_INTERFACE *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT8 ByteWidth;
+ if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER;
+ if (!Count) return EFI_INVALID_PARAMETER;
+
+ ByteWidth = (UINT8)(1 << Width);
+
+ if (Address + ByteWidth * Count > 0x10000) return EFI_INVALID_PARAMETER; //Beyond IO space.
+ if ((UINT64)(UINTN)Buffer + ByteWidth * Count > (UINT64)0x100000000) return EFI_INVALID_PARAMETER; //Beyond address space.
+
+ //Alignment must be done by the caller.
+ switch(ByteWidth) {
+ case 1:
+ while(Count--) {
+ IoWrite8((UINT16)Address,*(UINT8*)(UINTN)Buffer);
+ ++((UINT8*)(UINTN)Buffer);
+ ++((UINT8*)(UINTN)Address);
+ }
+ break;
+ case 2:
+ while(Count--) {
+ IoWrite16((UINT16)Address,*(UINT16*)(UINTN)Buffer);
+ ++((UINT16*)(UINTN)Buffer);
+ ++((UINT16*)(UINTN)Address);
+ }
+ break;
+ default: //case 4:
+ while(Count--) {
+ IoWrite32((UINT16)Address,*(UINT32*)(UINTN)Buffer);
+ ++((UINT32*)(UINTN)Buffer);
+ ++((UINT32*)(UINTN)Address);
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstAllocatePool
+//
+// Description: Allocate a pool of memory.
+//
+// Input:
+// IN EFI_MEMORY_TYPE PoolType
+// IN UINTN Size
+// OUT VOID **Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Pool of memory allocated.
+// * EFI_INVALID_PARAMETER - Allocate 0 size.
+// * EFI_OUT_OF_RESOURCES - Memory unavailable.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstAllocatePool(
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ if (!Size) return EFI_INVALID_PARAMETER;
+ *Buffer = Allocate(0,Size,0);
+ if (!(*Buffer)) return EFI_OUT_OF_RESOURCES;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstFreePool
+//
+// Description: Free Allocated memory.
+//
+// Input:
+// IN VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Memory is freed.
+// * EFI_INVALID_PARAMETER - Memory starting at Buffer was not allocated.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstFreePool(
+ IN VOID *Buffer
+ )
+{
+ if (!Free(Buffer)) return EFI_INVALID_PARAMETER;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstAllocatePages
+//
+// Description: Allocate # pages at any address, a max address, or a specified address.
+//
+// Input:
+// IN EFI_ALLOCATE_TYPE Type
+// IN EFI_MEMORY_TYPE MemoryType
+// IN UINTN NumberOfPages
+// OUT EFI_PHYSICAL_ADDRESS *Memory
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Memory allocated.
+// * EFI_OUT_OF_RESOURCES - Memory already allocated or unavailable.
+// * EFI_INVALID_PARAMETER - Incorrect Type or specified address not 4k aligned.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstAllocatePages(
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+ )
+{
+ VOID *AllocatedMemory;
+
+ if (!NumberOfPages) return EFI_INVALID_PARAMETER;
+ if (Type != AllocateAnyPages && *Memory <= 0x100000) return AllocateABSegPages(Type, NumberOfPages, Memory);
+
+ switch(Type) {
+ case AllocateAnyPages:
+ *Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)Allocate(0, NumberOfPages * 4096, 4095);
+ if (!(*Memory)) return EFI_OUT_OF_RESOURCES;
+ return EFI_SUCCESS;
+
+ case AllocateMaxAddress:
+ AllocatedMemory = Allocate(0, NumberOfPages * 4096, 4095);
+ if (!AllocatedMemory) return EFI_OUT_OF_RESOURCES;
+ if ((UINTN)AllocatedMemory > *(UINTN*)(UINTN)Memory) {
+ Free(AllocatedMemory);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatedMemory;
+ return EFI_SUCCESS;
+ case AllocateAddress:
+ if ((UINT8*)(UINTN)*Memory != Align2n((UINT8*)(UINTN)*Memory,4095)) return EFI_INVALID_PARAMETER;
+ AllocatedMemory = Allocate((UINT8*)(UINTN)*Memory,NumberOfPages * 4096,0);
+ if (!AllocatedMemory) return EFI_OUT_OF_RESOURCES;
+ return EFI_SUCCESS;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmSmstFreePages
+//
+// Description:
+// Free pages. The address must be on a page boundary, but it doesn't have to
+// start on address from AllocatePages. It only frees the requested pages.
+//
+// Input:
+// IN EFI_PHYSICAL_ADDRESS Memory
+// IN UINTN NumberOfPages
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmSmstFreePages(
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+{
+ if (Memory <= 0x100000) return FreeABSegPages(Memory, NumberOfPages);
+
+ if (!Free4kPages((VOID*)(UINTN)Memory,NumberOfPages)) return EFI_INVALID_PARAMETER;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmStartupThisAp
+//
+// Description: Execute a procedure on an AP.
+//
+// Input:
+// IN EFI_AP_PROCEDURE Procedure
+// IN UINTN CpuNumber
+// IN OUT VOID *ProcArguments OPTIONAL
+//
+// Output:
+// EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmStartupThisAp(
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuNumber,
+ IN OUT VOID *ProcArguments OPTIONAL
+)
+{
+ volatile SMM_AP_CPU_CONTROL *SmmApCpuControl;
+ BOOLEAN IsBlocking = (BOOLEAN)(CpuNumber != (UINTN)-1);
+ UINT32 i;
+
+ if (Procedure == NULL) return EFI_INVALID_PARAMETER;
+ if (CpuNumber == gDispatcherPrivate->SmmBspNumber) return EFI_INVALID_PARAMETER;
+ if (CpuNumber >= gDispatcherPrivate->NumCpus && IsBlocking) return EFI_INVALID_PARAMETER;
+
+ if (IsBlocking) {
+ if (!gDispatcherPrivate->SmmCpuInfo[CpuNumber].InSmm) return EFI_NOT_READY;
+ SmmApCpuControl = &gDispatcherPrivate->SmmApCpuControl[CpuNumber];
+
+ SmmApCpuControl->ProcArguments = ProcArguments;
+ SmmApCpuControl->Procedure = Procedure;
+
+ if ( !((ReadMsr (MSR_PLATFORM_INFO) & B_MSR_PLATFORM_INFO_PFAT_AVAIL) &&
+ (ReadMsr (MSR_PLAT_FRMW_PROT_CTRL) & B_MSR_PLAT_FRMW_PROT_CTRL_EN)) ) {
+ while(SmmApCpuControl->Procedure) CPULib_Pause();
+ }
+ return EFI_SUCCESS;
+ }
+
+ for (i = 0; i < gDispatcherPrivate->NumCpus; ++i) {
+ if (i == gDispatcherPrivate->SmmBspNumber) continue;
+ if (!gDispatcherPrivate->SmmCpuInfo[i].InSmm) continue;
+ SmmApCpuControl = &gDispatcherPrivate->SmmApCpuControl[i];
+ ASSERT(SmmApCpuControl->Procedure == NULL);
+ if (SmmApCpuControl->Procedure != NULL) continue;
+
+ SmmApCpuControl->ProcArguments = ProcArguments;
+ SmmApCpuControl->Procedure = Procedure;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: MoveToNewConfigurationTable
+//
+// Description: Create a new bigger or smaller table and copy the old table to the new table.
+//
+// Input:
+// IN EFI_CONFIGURATION_TABLE *OldTable
+// IN UINTN NumOldDescriptors
+// IN UINTN NumDescriptors
+//
+// Output:
+// EFI_CONFIGURATION_TABLE * - New table address.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_CONFIGURATION_TABLE * MoveToNewConfigurationTable(
+ EFI_CONFIGURATION_TABLE *OldTable,
+ UINTN NumOldDescriptors,
+ UINTN NumDescriptors
+ )
+{
+ EFI_CONFIGURATION_TABLE *NewTable,*Descriptor,*OldDescriptor;
+ UINTN i;
+ //Create new table
+ if (SmmSmstAllocatePool(0,NumDescriptors * sizeof(EFI_CONFIGURATION_TABLE),&NewTable)!=EFI_SUCCESS) return 0;
+
+ //If new table is larger, only copy valid descriptors.
+ //If new table is smaller, only copy descriptors for allocated table.
+ NumDescriptors = NumDescriptors > NumOldDescriptors ? NumOldDescriptors : NumDescriptors;
+ Descriptor = NewTable;
+ OldDescriptor = OldTable;
+ for (i=0;i<NumDescriptors;++i) *Descriptor++ = *OldDescriptor++;
+
+ //Free old table
+ SmmSmstFreePool(OldTable);
+
+ return NewTable;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SmmInstallConfigurationTable
+//
+// Description:
+// This procedure add/updates/deletes configuration table entries.
+//
+// Configuration Table Entry definition:
+// EFI_GUID VendorGuid
+// VOID *VenderTable
+//
+// 1. If Vendor Guid is not in table and Input table isn't NULL, add Guid/Table pair.
+// 2. If Vendor Guid is in table and Input table isn't NULL, update Guid/Table pair.
+// 3. If Vendor Guid is in table and Input table is NULL, remove Guid/Tablble pair.
+// 4. If Vendor Guid is not in table, Input table is NULL, return EFI_NOT_FOUND. Nothing to delete.
+//
+// Input:
+// IN EFI_SMM_SYSTEM_TABLE *SystemTable
+// IN EFI_GUID *Guid
+// IN VOID *Table
+// IN UINTN TableSize
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Add/update/remove operation successful.
+// * EFI_INVALID_PARAMETER - Guid = 0.
+// * EFI_NOT_FOUND - Can not delete a nonexistent entry.
+// * EFI_OUT_OF_RESOURCES - Not enough memory to complete operation.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SmmInstallConfigurationTable(
+#if SMM_USE_FRAMEWORK
+ IN EFI_SMM_SYSTEM_TABLE *SystemTable,
+#else
+ IN EFI_SMM_SYSTEM_TABLE2 *SystemTable,
+#endif
+ IN EFI_GUID *Guid,
+ IN VOID *Table,
+ IN UINTN TableSize
+ )
+{
+ UINTN i;
+ UINT32 CRC32;
+
+#if SMM_USE_PI
+ EFI_CONFIGURATION_TABLE **FirstEntryPtr = &gSmmSystemTable2.SmmConfigurationTable;
+ EFI_CONFIGURATION_TABLE *Entry = *FirstEntryPtr;
+ UINTN *NumberOfTableEntries = &gSmmSystemTable2.NumberOfTableEntries;
+ UINT32 SystemTableSize = sizeof(gSmmSystemTable2);
+ #else
+ EFI_CONFIGURATION_TABLE **FirstEntryPtr = &gSmmSystemTable.SmmConfigurationTable;
+ EFI_CONFIGURATION_TABLE *Entry = *FirstEntryPtr;
+ UINTN *NumberOfTableEntries = &gSmmSystemTable.NumberOfTableEntries;
+ UINT32 SystemTableSize = sizeof(gSmmSystemTable);
+#endif
+
+ EFI_CONFIGURATION_TABLE *NewConfigTable;
+ VOID *NewVendorTable;
+
+ if (!Guid) return EFI_INVALID_PARAMETER;
+
+ for (i=0;i < *NumberOfTableEntries;++i) {
+ if (guidcmp(&Entry->VendorGuid,Guid)==0) break;
+ ++Entry;
+ }
+ if (i == *NumberOfTableEntries) Entry=0;
+
+ if (!Entry) {
+ if (!Table) return EFI_NOT_FOUND;
+ //Add Guid
+ NewConfigTable = MoveToNewConfigurationTable(
+ *FirstEntryPtr,
+ *NumberOfTableEntries,
+ *NumberOfTableEntries+1);
+ if (!NewConfigTable) return EFI_OUT_OF_RESOURCES;
+
+ if (SmmSmstAllocatePool(0,TableSize,&NewVendorTable)!=EFI_SUCCESS) return EFI_OUT_OF_RESOURCES;
+ MemCpy(NewVendorTable,Table,TableSize);
+ *FirstEntryPtr = NewConfigTable;
+ ++(*NumberOfTableEntries);
+ NewConfigTable[*NumberOfTableEntries - 1].VendorGuid = *Guid;
+ NewConfigTable[*NumberOfTableEntries - 1].VendorTable = NewVendorTable;
+ } else {
+ if (!Table) {
+ //Remove Guid
+ EFI_CONFIGURATION_TABLE *LastEntry = *FirstEntryPtr + *NumberOfTableEntries;
+
+ SmmSmstFreePool(Entry->VendorTable);
+
+ while (Entry != LastEntry) {
+ *Entry = *(Entry + 1);
+ ++Entry;
+ }
+
+ --(*NumberOfTableEntries);
+ } else {
+ //Update Guid
+ if (SmmSmstAllocatePool(0,TableSize,&NewVendorTable)!=EFI_SUCCESS) return EFI_OUT_OF_RESOURCES;
+ MemCpy(NewVendorTable,Table,TableSize);
+
+ SmmSmstFreePool(Entry->VendorTable);
+ Entry->VendorTable = NewVendorTable;
+ }
+ }
+
+#if SMM_USE_PI && SMM_USE_FRAMEWORK
+ gSmmSystemTable.SmmConfigurationTable = gSmmSystemTable2.SmmConfigurationTable;
+ gSmmSystemTable.NumberOfTableEntries = gSmmSystemTable2.NumberOfTableEntries;
+#endif
+
+#if SMM_USE_PI
+ gSmmSystemTable2.Hdr.CRC32 = 0;
+ CalculateCrc32(&gSmmSystemTable2, SystemTableSize, &CRC32);
+ gSmmSystemTable2.Hdr.CRC32 = CRC32;
+#endif
+
+#if SMM_USE_FRAMEWORK
+ gSmmSystemTable.Hdr.CRC32 = 0;
+ CalculateCrc32(&gSmmSystemTable, sizeof(EFI_SMM_SYSTEM_TABLE), &CRC32);
+ gSmmSystemTable.Hdr.CRC32 = CRC32;
+#endif
+
+ return EFI_SUCCESS;
+}
+
+
+#if SMM_USE_FRAMEWORK
+
+//////////////////////////////////////////
+extern CHAR16 gSmmFirmwareVendor[];
+EFI_SMM_SYSTEM_TABLE gSmmSystemTable =
+{
+ { //Header
+ SMM_SMST_SIGNATURE, //Signature
+ EFI_SMM_SYSTEM_TABLE_REVISION, //Revision
+ sizeof(EFI_SMM_SYSTEM_TABLE), //Header size
+ 0, //CRC32
+ 0 //Reserved
+ },
+ gSmmFirmwareVendor, //Vendor
+ 0, //Vendor version
+ SmmInstallConfigurationTable,
+ EFI_SMM_CPU_IO_GUID,
+ {
+ {
+ SmmMemRead,
+ SmmMemWrite
+ },
+ { SmmIoRead,
+ SmmIoWrite
+ }
+ },
+ SmmSmstAllocatePool,
+ SmmSmstFreePool,
+ SmmSmstAllocatePages,
+ SmmSmstFreePages,
+ SmmStartupThisAp,
+ 1, //Executing CPU
+ 1, //Number of CPUs
+ 0, //Cpu Save State
+ 0, //Cpu Floating Point Save
+ 0, //Number of Table Entries
+ 0 //Table pointer
+};
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitializeSmmSystemTable
+//
+// Description: Initialize the System Table.
+//
+// Input: SMM_BASE_PRIVATE_STRUCT *Private
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID InitializeSmmSystemTable()
+{
+ UINT32 CRC32;
+
+ gSmmSystemTable.NumberOfCpus = gDispatcherPrivate->NumCpus;
+
+ gSmmSystemTable.CpuSaveState = Allocate(0,sizeof(EFI_SMM_CPU_SAVE_STATE) * gSmmSystemTable.NumberOfCpus,0);
+ gSmmSystemTable.CpuOptionalFloatingPointState = Allocate(0, 512 * gSmmSystemTable.NumberOfCpus, 15); //16 byte alignment, Save floating point context.
+
+ CalculateCrc32(&gSmmSystemTable, sizeof(EFI_SMM_SYSTEM_TABLE), &CRC32);
+ gSmmSystemTable.Hdr.CRC32 = CRC32;
+}
+
+#endif
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************