summaryrefslogtreecommitdiff
path: root/Core/EM/SMM/SmmBase.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/SMM/SmmBase.c')
-rw-r--r--Core/EM/SMM/SmmBase.c911
1 files changed, 911 insertions, 0 deletions
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 **
+//** **
+//*************************************************************************
+//*************************************************************************