]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c
EdkCompatibilityPkg: Remove EdkCompatibilityPkg
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / SmmBaseHelper / SmmBaseHelper.c
diff --git a/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c b/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c
deleted file mode 100644 (file)
index 5f220dd..0000000
+++ /dev/null
@@ -1,1224 +0,0 @@
-/** @file\r
-  SMM Base Helper SMM driver.\r
-\r
-  This driver is the counterpart of the SMM Base On SMM Base2 Thunk driver. It\r
-  provides helping services in SMM to the SMM Base On SMM Base2 Thunk driver.\r
-\r
-  Caution: This module requires additional review when modified.\r
-  This driver will have external input - communicate buffer in SMM mode.\r
-  This external input must be validated carefully to avoid security issue like\r
-  buffer overflow, integer overflow.\r
-\r
-  SmmHandlerEntry() will receive untrusted input and do validation.\r
-\r
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <PiSmm.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/SmmServicesTableLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/PeCoffLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/CacheMaintenanceLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/SynchronizationLib.h>\r
-#include <Library/CpuLib.h>\r
-#include <Library/SmmMemLib.h>\r
-#include <Guid/SmmBaseThunkCommunication.h>\r
-#include <Protocol/SmmBaseHelperReady.h>\r
-#include <Protocol/SmmCpu.h>\r
-#include <Protocol/LoadedImage.h>\r
-#include <Protocol/SmmCpuSaveState.h>\r
-#include <Protocol/MpService.h>\r
-#include <Protocol/LoadPe32Image.h>\r
-#include <Protocol/SmmReadyToLock.h>\r
-\r
-/**\r
-  Register SMM image to SMRAM profile.\r
-\r
-  @param[in] FilePath           File path of the image.\r
-  @param[in] ImageBuffer        Image base address.\r
-  @param[in] NumberOfPage       Number of page.\r
-\r
-  @retval TRUE                  Register success.\r
-  @retval FALSE                 Register fail.\r
-\r
-**/\r
-BOOLEAN\r
-RegisterSmramProfileImage (\r
-  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,\r
-  IN PHYSICAL_ADDRESS           ImageBuffer,\r
-  IN UINTN                      NumberOfPage\r
-  );\r
-\r
-/**\r
-  Unregister SMM image from SMRAM profile.\r
-\r
-  @param[in] FilePath           File path of the image.\r
-  @param[in] ImageBuffer        Image base address.\r
-  @param[in] NumberOfPage       Number of page.\r
-\r
-  @retval TRUE                  Unregister success.\r
-  @retval FALSE                 Unregister fail.\r
-\r
-**/\r
-BOOLEAN\r
-UnregisterSmramProfileImage (\r
-  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,\r
-  IN PHYSICAL_ADDRESS           ImageBuffer,\r
-  IN UINTN                      NumberOfPage\r
-  );\r
-\r
-///\r
-/// Structure for tracking paired information of registered Framework SMI handler\r
-/// and correpsonding dispatch handle for SMI handler thunk.\r
-///\r
-typedef struct {\r
-  LIST_ENTRY                    Link;\r
-  EFI_HANDLE                    DispatchHandle;\r
-  EFI_HANDLE                    SmmImageHandle;\r
-  EFI_SMM_CALLBACK_ENTRY_POINT  CallbackAddress;\r
-  VOID                          *CommunicationBuffer;\r
-  UINTN                         *SourceSize;\r
-} CALLBACK_INFO;\r
-\r
-typedef struct {\r
-  ///\r
-  /// PI SMM CPU Save State register index\r
-  ///\r
-  EFI_SMM_SAVE_STATE_REGISTER   Register;\r
-  ///\r
-  /// Offset in Framework SMST\r
-  ///\r
-  UINTN                         Offset;\r
-} CPU_SAVE_STATE_CONVERSION;\r
-\r
-#define CPU_SAVE_STATE_GET_OFFSET(Field)  (UINTN)(&(((EFI_SMM_CPU_SAVE_STATE *) 0)->Ia32SaveState.Field))\r
-\r
-\r
-EFI_HANDLE                         mDispatchHandle;\r
-EFI_SMM_CPU_PROTOCOL               *mSmmCpu;\r
-EFI_PE32_IMAGE_PROTOCOL            *mLoadPe32Image;\r
-EFI_GUID                           mEfiSmmCpuIoGuid = EFI_SMM_CPU_IO_GUID;\r
-EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady;\r
-EFI_SMM_SYSTEM_TABLE               *mFrameworkSmst;\r
-UINTN                              mNumberOfProcessors;\r
-BOOLEAN                            mLocked = FALSE;\r
-BOOLEAN                            mPageTableHookEnabled;\r
-BOOLEAN                            mHookInitialized;\r
-UINT64                             *mCpuStatePageTable;\r
-SPIN_LOCK                          mPFLock;\r
-UINT64                             mPhyMask;\r
-VOID                               *mOriginalHandler;\r
-EFI_SMM_CPU_SAVE_STATE             *mShadowSaveState;\r
-\r
-LIST_ENTRY mCallbackInfoListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead);\r
-\r
-CPU_SAVE_STATE_CONVERSION mCpuSaveStateConvTable[] = {\r
-  {EFI_SMM_SAVE_STATE_REGISTER_LDTBASE  , CPU_SAVE_STATE_GET_OFFSET(LDTBase)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_ES       , CPU_SAVE_STATE_GET_OFFSET(ES)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_CS       , CPU_SAVE_STATE_GET_OFFSET(CS)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_SS       , CPU_SAVE_STATE_GET_OFFSET(SS)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_DS       , CPU_SAVE_STATE_GET_OFFSET(DS)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_FS       , CPU_SAVE_STATE_GET_OFFSET(FS)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_GS       , CPU_SAVE_STATE_GET_OFFSET(GS)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_TR_SEL   , CPU_SAVE_STATE_GET_OFFSET(TR)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_DR7      , CPU_SAVE_STATE_GET_OFFSET(DR7)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_DR6      , CPU_SAVE_STATE_GET_OFFSET(DR6)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RAX      , CPU_SAVE_STATE_GET_OFFSET(EAX)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RBX      , CPU_SAVE_STATE_GET_OFFSET(EBX)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RCX      , CPU_SAVE_STATE_GET_OFFSET(ECX)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RDX      , CPU_SAVE_STATE_GET_OFFSET(EDX)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RSP      , CPU_SAVE_STATE_GET_OFFSET(ESP)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RBP      , CPU_SAVE_STATE_GET_OFFSET(EBP)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RSI      , CPU_SAVE_STATE_GET_OFFSET(ESI)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RDI      , CPU_SAVE_STATE_GET_OFFSET(EDI)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RIP      , CPU_SAVE_STATE_GET_OFFSET(EIP)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_RFLAGS   , CPU_SAVE_STATE_GET_OFFSET(EFLAGS)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_CR0      , CPU_SAVE_STATE_GET_OFFSET(CR0)},\r
-  {EFI_SMM_SAVE_STATE_REGISTER_CR3      , CPU_SAVE_STATE_GET_OFFSET(CR3)}\r
-};\r
-\r
-/**\r
-  Page fault handler.\r
-\r
-**/\r
-VOID\r
-PageFaultHandlerHook (\r
-  VOID\r
-  );\r
-\r
-/**\r
-  Read CpuSaveStates from PI for Framework use.\r
-\r
-  The function reads PI style CpuSaveStates of CpuIndex-th CPU for Framework driver use. If\r
-  ToRead is specified, the CpuSaveStates will be copied to ToRead, otherwise copied to\r
-  mFrameworkSmst->CpuSaveState[CpuIndex].\r
-\r
-  @param[in]      CpuIndex        The zero-based CPU index.\r
-  @param[in, out] ToRead          If not NULL, CpuSaveStates will be copied to it.\r
-\r
-**/\r
-VOID\r
-ReadCpuSaveState (\r
-  IN     UINTN                   CpuIndex,\r
-  IN OUT EFI_SMM_CPU_SAVE_STATE  *ToRead\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-  UINTN Index;\r
-  EFI_SMM_CPU_STATE *State;\r
-  EFI_SMI_CPU_SAVE_STATE *SaveState;\r
-\r
-  State = (EFI_SMM_CPU_STATE *)gSmst->CpuSaveState[CpuIndex];\r
-  if (ToRead != NULL) {\r
-    SaveState = &ToRead->Ia32SaveState;\r
-  } else {\r
-    SaveState = &mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState;\r
-  }\r
-\r
-  //\r
-  // Note that SMBASE/SMMRevId/IORestart/AutoHALTRestart are in same location in IA32 and X64 CPU Save State Map.\r
-  //\r
-  SaveState->SMBASE = State->x86.SMBASE;\r
-  SaveState->SMMRevId = State->x86.SMMRevId;\r
-  SaveState->IORestart = State->x86.IORestart;\r
-  SaveState->AutoHALTRestart = State->x86.AutoHALTRestart;\r
-\r
-  for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {\r
-    ///\r
-    /// Try to use SMM CPU Protocol to access CPU save states if possible\r
-    ///\r
-    Status = mSmmCpu->ReadSaveState (\r
-                        mSmmCpu,\r
-                        (UINTN)sizeof (UINT32),\r
-                        mCpuSaveStateConvTable[Index].Register,\r
-                        CpuIndex,\r
-                        ((UINT8 *)SaveState) + mCpuSaveStateConvTable[Index].Offset\r
-                        );\r
-    ASSERT_EFI_ERROR (Status);\r
-  }\r
-}\r
-\r
-/**\r
-  Write CpuSaveStates from Framework into PI.\r
-\r
-  The function writes back CpuSaveStates of CpuIndex-th CPU from PI to Framework. If\r
-  ToWrite is specified, it contains the CpuSaveStates to write from, otherwise CpuSaveStates\r
-  to write from mFrameworkSmst->CpuSaveState[CpuIndex].\r
-\r
-  @param[in] CpuIndex      The zero-based CPU index.\r
-  @param[in] ToWrite       If not NULL, CpuSaveStates to write from.\r
-\r
-**/\r
-VOID\r
-WriteCpuSaveState (\r
-  IN UINTN                   CpuIndex,\r
-  IN EFI_SMM_CPU_SAVE_STATE  *ToWrite\r
-  )\r
-{\r
-  UINTN                  Index;\r
-  EFI_SMM_CPU_STATE      *State;\r
-  EFI_SMI_CPU_SAVE_STATE *SaveState;\r
-\r
-  State = (EFI_SMM_CPU_STATE *)gSmst->CpuSaveState[CpuIndex];\r
-\r
-  if (ToWrite != NULL) {\r
-    SaveState = &ToWrite->Ia32SaveState;\r
-  } else {\r
-    SaveState = &mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState;\r
-  }\r
-\r
-  //\r
-  // SMMRevId is read-only.\r
-  // Note that SMBASE/IORestart/AutoHALTRestart are in same location in IA32 and X64 CPU Save State Map.\r
-  //\r
-  State->x86.SMBASE = SaveState->SMBASE;\r
-  State->x86.IORestart = SaveState->IORestart;\r
-  State->x86.AutoHALTRestart = SaveState->AutoHALTRestart;\r
-  \r
-  for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {\r
-    mSmmCpu->WriteSaveState (\r
-               mSmmCpu,\r
-               (UINTN)sizeof (UINT32),\r
-               mCpuSaveStateConvTable[Index].Register,\r
-               CpuIndex,\r
-               ((UINT8 *)SaveState) +\r
-               mCpuSaveStateConvTable[Index].Offset\r
-               );\r
-  }\r
-}\r
-\r
-/**\r
-  Read or write a page that contains CpuSaveStates. Read is from PI to Framework.\r
-  Write is from Framework to PI.\r
-\r
-  This function reads or writes a page that contains CpuSaveStates. The page contains Framework\r
-  CpuSaveStates. On read, it reads PI style CpuSaveStates and fill the page up. On write, it\r
-  writes back from the page content to PI CpuSaveStates struct.\r
-  The first Framework CpuSaveStates (for CPU 0) is from mFrameworkSmst->CpuSaveState which is\r
-  page aligned. Because Framework CpuSaveStates are continuous, we can know which CPUs' SaveStates\r
-  are in the page start from PageAddress.\r
-\r
-  @param[in] PageAddress   The base address for a page.\r
-  @param[in] IsRead        TRUE for Read, FALSE for Write.\r
-\r
-**/\r
-VOID\r
-ReadWriteCpuStatePage (\r
-  IN UINT64  PageAddress,\r
-  IN BOOLEAN IsRead\r
-  )\r
-{\r
-  UINTN          FirstSSIndex;   // Index of first CpuSaveState in the page\r
-  UINTN          LastSSIndex;    // Index of last CpuSaveState in the page\r
-  BOOLEAN        FirstSSAligned; // Whether first CpuSaveState is page-aligned\r
-  BOOLEAN        LastSSAligned;  // Whether the end of last CpuSaveState is page-aligned\r
-  UINTN          ClippedSize;\r
-  UINTN          CpuIndex;\r
-\r
-  FirstSSIndex = ((UINTN)PageAddress - (UINTN)mFrameworkSmst->CpuSaveState) / sizeof (EFI_SMM_CPU_SAVE_STATE);\r
-  FirstSSAligned = TRUE;\r
-  if (((UINTN)PageAddress - (UINTN)mFrameworkSmst->CpuSaveState) % sizeof (EFI_SMM_CPU_SAVE_STATE) != 0) {\r
-    FirstSSIndex++;\r
-    FirstSSAligned = FALSE;\r
-  }\r
-  LastSSIndex = ((UINTN)PageAddress + SIZE_4KB - (UINTN)mFrameworkSmst->CpuSaveState - 1) / sizeof (EFI_SMM_CPU_SAVE_STATE);\r
-  LastSSAligned = TRUE;\r
-  if (((UINTN)PageAddress + SIZE_4KB - (UINTN)mFrameworkSmst->CpuSaveState) % sizeof (EFI_SMM_CPU_SAVE_STATE) != 0) {\r
-    LastSSIndex--;\r
-    LastSSAligned = FALSE;\r
-  }\r
-  for (CpuIndex = FirstSSIndex; CpuIndex <= LastSSIndex && CpuIndex < mNumberOfProcessors; CpuIndex++) {\r
-    if (IsRead) {\r
-      ReadCpuSaveState (CpuIndex, NULL);\r
-    } else {\r
-      WriteCpuSaveState (CpuIndex, NULL);\r
-    }\r
-  }\r
-  if (!FirstSSAligned) {\r
-    ReadCpuSaveState (FirstSSIndex - 1, mShadowSaveState);\r
-    ClippedSize = (UINTN)&mFrameworkSmst->CpuSaveState[FirstSSIndex] & (SIZE_4KB - 1);\r
-    if (IsRead) {\r
-      CopyMem ((VOID*)(UINTN)PageAddress, (VOID*)((UINTN)(mShadowSaveState + 1) - ClippedSize), ClippedSize);\r
-    } else {\r
-      CopyMem ((VOID*)((UINTN)(mShadowSaveState + 1) - ClippedSize), (VOID*)(UINTN)PageAddress, ClippedSize);\r
-      WriteCpuSaveState (FirstSSIndex - 1, mShadowSaveState);\r
-    }\r
-  }\r
-  if (!LastSSAligned && LastSSIndex + 1 < mNumberOfProcessors) {\r
-    ReadCpuSaveState (LastSSIndex + 1, mShadowSaveState);\r
-    ClippedSize = SIZE_4KB - ((UINTN)&mFrameworkSmst->CpuSaveState[LastSSIndex + 1] & (SIZE_4KB - 1));\r
-    if (IsRead) {\r
-      CopyMem (&mFrameworkSmst->CpuSaveState[LastSSIndex + 1], mShadowSaveState, ClippedSize);\r
-    } else {\r
-      CopyMem (mShadowSaveState, &mFrameworkSmst->CpuSaveState[LastSSIndex + 1], ClippedSize);\r
-      WriteCpuSaveState (LastSSIndex + 1, mShadowSaveState);\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
-  The page fault handler that on-demand read PI CpuSaveStates for framework use. If the fault\r
-  is not targeted to mFrameworkSmst->CpuSaveState range, the function will return FALSE to let\r
-  PageFaultHandlerHook know it needs to pass the fault over to original page fault handler.\r
-  \r
-  @retval TRUE     The page fault is correctly handled.\r
-  @retval FALSE    The page fault is not handled and is passed through to original handler.\r
-\r
-**/\r
-BOOLEAN\r
-PageFaultHandler (\r
-  VOID\r
-  )\r
-{\r
-  BOOLEAN        IsHandled;\r
-  UINT64         PFAddress;\r
-  UINTN          NumCpuStatePages;\r
-  \r
-  ASSERT (mPageTableHookEnabled);\r
-  AcquireSpinLock (&mPFLock);\r
-\r
-  PFAddress = AsmReadCr2 ();\r
-  NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));\r
-  IsHandled = FALSE;\r
-  if (((UINTN)mFrameworkSmst->CpuSaveState & ~(SIZE_2MB-1)) == (PFAddress & ~(SIZE_2MB-1))) {\r
-    if ((UINTN)mFrameworkSmst->CpuSaveState <= PFAddress &&\r
-        PFAddress < (UINTN)mFrameworkSmst->CpuSaveState + EFI_PAGES_TO_SIZE (NumCpuStatePages)\r
-        ) {\r
-      mCpuStatePageTable[BitFieldRead64 (PFAddress, 12, 20)] |= BIT0 | BIT1; // present and rw\r
-      CpuFlushTlb ();\r
-      ReadWriteCpuStatePage (PFAddress & ~(SIZE_4KB-1), TRUE);\r
-      IsHandled = TRUE;\r
-    } else {\r
-      ASSERT (FALSE);\r
-    }\r
-  }\r
-\r
-  ReleaseSpinLock (&mPFLock);\r
-  return IsHandled;\r
-}\r
-\r
-/**\r
-  Write back the dirty Framework CpuSaveStates to PI.\r
-  \r
-  The function scans the page table for dirty pages in mFrameworkSmst->CpuSaveState\r
-  to write back to PI CpuSaveStates. It is meant to be called on each SmmBaseHelper SMI\r
-  callback after Framework handler is called.\r
-\r
-**/\r
-VOID\r
-WriteBackDirtyPages (\r
-  VOID\r
-  )\r
-{\r
-  UINTN  NumCpuStatePages;\r
-  UINTN  PTIndex;\r
-  UINTN  PTStartIndex;\r
-  UINTN  PTEndIndex;\r
-\r
-  NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));\r
-  PTStartIndex = (UINTN)BitFieldRead64 ((UINT64) (UINTN) mFrameworkSmst->CpuSaveState, 12, 20);\r
-  PTEndIndex   = (UINTN)BitFieldRead64 ((UINT64) (UINTN) mFrameworkSmst->CpuSaveState + EFI_PAGES_TO_SIZE(NumCpuStatePages) - 1, 12, 20);\r
-  for (PTIndex = PTStartIndex; PTIndex <= PTEndIndex; PTIndex++) {\r
-    if ((mCpuStatePageTable[PTIndex] & (BIT0|BIT6)) == (BIT0|BIT6)) { // present and dirty?\r
-      ReadWriteCpuStatePage (mCpuStatePageTable[PTIndex] & mPhyMask, FALSE);\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
-  Hook IDT with our page fault handler so that the on-demand paging works on page fault.\r
-  \r
-  The function hooks the IDT with PageFaultHandlerHook to get on-demand paging work for\r
-  PI<->Framework CpuSaveStates marshalling. It also saves original handler for pass-through\r
-  purpose.\r
-\r
-**/\r
-VOID\r
-HookPageFaultHandler (\r
-  VOID\r
-  )\r
-{\r
-  IA32_DESCRIPTOR           Idtr;\r
-  IA32_IDT_GATE_DESCRIPTOR  *IdtGateDesc;\r
-  UINT32                    OffsetUpper;\r
-  \r
-  InitializeSpinLock (&mPFLock);\r
-  \r
-  AsmReadIdtr (&Idtr);\r
-  IdtGateDesc = (IA32_IDT_GATE_DESCRIPTOR *) Idtr.Base;\r
-  OffsetUpper = *(UINT32*)((UINT64*)IdtGateDesc + 1);\r
-  mOriginalHandler = (VOID *)(UINTN)(LShiftU64 (OffsetUpper, 32) + IdtGateDesc[14].Bits.OffsetLow + (IdtGateDesc[14].Bits.OffsetHigh << 16));\r
-  IdtGateDesc[14].Bits.OffsetLow = (UINT32)((UINTN)PageFaultHandlerHook & ((1 << 16) - 1));\r
-  IdtGateDesc[14].Bits.OffsetHigh = (UINT32)(((UINTN)PageFaultHandlerHook >> 16) & ((1 << 16) - 1));\r
-}\r
-\r
-/**\r
-  Initialize page table for pages contain HookData.\r
-  \r
-  The function initialize PDE for 2MB range that contains HookData. If the related PDE points\r
-  to a 2MB page, a page table will be allocated and initialized for 4KB pages. Otherwise we juse\r
-  use the original page table.\r
-\r
-  @param[in] HookData   Based on which to initialize page table.\r
-\r
-  @return    The pointer to a Page Table that points to 4KB pages which contain HookData.\r
-**/\r
-UINT64 *\r
-InitCpuStatePageTable (\r
-  IN VOID *HookData\r
-  )\r
-{\r
-  UINTN  Index;\r
-  UINT64 *PageTable;\r
-  UINT64 *Pdpte;\r
-  UINT64 HookAddress;\r
-  UINT64 Pde;\r
-  UINT64 Address;\r
-  \r
-  //\r
-  // Initialize physical address mask\r
-  // NOTE: Physical memory above virtual address limit is not supported !!!\r
-  //\r
-  AsmCpuid (0x80000008, (UINT32*)&Index, NULL, NULL, NULL);\r
-  mPhyMask = LShiftU64 (1, (UINT8)Index) - 1;\r
-  mPhyMask &= (1ull << 48) - EFI_PAGE_SIZE;\r
-  \r
-  HookAddress = (UINT64)(UINTN)HookData;\r
-  PageTable   = (UINT64 *)(UINTN)(AsmReadCr3 () & mPhyMask);\r
-  PageTable = (UINT64 *)(UINTN)(PageTable[BitFieldRead64 (HookAddress, 39, 47)] & mPhyMask);\r
-  PageTable = (UINT64 *)(UINTN)(PageTable[BitFieldRead64 (HookAddress, 30, 38)] & mPhyMask);\r
-  \r
-  Pdpte = (UINT64 *)(UINTN)PageTable;\r
-  Pde = Pdpte[BitFieldRead64 (HookAddress, 21, 29)];\r
-  ASSERT ((Pde & BIT0) != 0); // Present and 2M Page\r
-  \r
-  if ((Pde & BIT7) == 0) { // 4KB Page Directory\r
-    PageTable = (UINT64 *)(UINTN)(Pde & mPhyMask);\r
-  } else {\r
-    ASSERT ((Pde & mPhyMask) == (HookAddress & ~(SIZE_2MB-1))); // 2MB Page Point to HookAddress\r
-    PageTable = AllocatePages (1);\r
-    ASSERT (PageTable != NULL);\r
-    Address = HookAddress & ~(SIZE_2MB-1);\r
-    for (Index = 0; Index < 512; Index++) {\r
-      PageTable[Index] = Address | BIT0 | BIT1; // Present and RW\r
-      Address += SIZE_4KB;\r
-    }\r
-    Pdpte[BitFieldRead64 (HookAddress, 21, 29)] = (UINT64)(UINTN)PageTable | BIT0 | BIT1; // Present and RW\r
-  }\r
-  return PageTable;\r
-}\r
-\r
-/**\r
-  Mark all the CpuSaveStates as not present.\r
-  \r
-  The function marks all CpuSaveStates memory range as not present so that page fault can be triggered\r
-  on CpuSaveStates access. It is meant to be called on each SmmBaseHelper SMI callback before Framework\r
-  handler is called.\r
-\r
-  @param[in] CpuSaveState   The base of CpuSaveStates.\r
-\r
-**/\r
-VOID\r
-HookCpuStateMemory (\r
-  IN EFI_SMM_CPU_SAVE_STATE *CpuSaveState\r
-  )\r
-{\r
-  UINT64 Index;\r
-  UINT64 PTStartIndex;\r
-  UINT64 PTEndIndex;\r
-\r
-  PTStartIndex = BitFieldRead64 ((UINTN)CpuSaveState, 12, 20);\r
-  PTEndIndex = BitFieldRead64 ((UINTN)CpuSaveState + mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE) - 1, 12, 20);\r
-  for (Index = PTStartIndex; Index <= PTEndIndex; Index++) {\r
-    mCpuStatePageTable[Index] &= ~(BIT0|BIT5|BIT6); // not present nor accessed nor dirty\r
-  }\r
-}  \r
-\r
-/**\r
-  Framework SMST SmmInstallConfigurationTable() Thunk.\r
-\r
-  This thunk calls the PI SMM SmmInstallConfigurationTable() and then update the configuration\r
-  table related fields in the Framework SMST because the PI SMM SmmInstallConfigurationTable()\r
-  function may modify these fields.\r
-\r
-  @param[in] SystemTable         A pointer to the SMM System Table.\r
-  @param[in] Guid                A pointer to the GUID for the entry to add, update, or remove.\r
-  @param[in] Table               A pointer to the buffer of the table to add.\r
-  @param[in] TableSize           The size of the table to install.\r
-\r
-  @retval EFI_SUCCESS            The (Guid, Table) pair was added, updated, or removed.\r
-  @retval EFI_INVALID_PARAMETER  Guid is not valid.\r
-  @retval EFI_NOT_FOUND          An attempt was made to delete a non-existent entry.\r
-  @retval EFI_OUT_OF_RESOURCES   There is not enough memory available to complete the operation.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmInstallConfigurationTable (\r
-  IN EFI_SMM_SYSTEM_TABLE  *SystemTable,\r
-  IN EFI_GUID              *Guid,\r
-  IN VOID                  *Table,\r
-  IN UINTN                 TableSize\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  \r
-  Status = gSmst->SmmInstallConfigurationTable (gSmst, Guid, Table, TableSize);\r
-  if (!EFI_ERROR (Status)) {\r
-    mFrameworkSmst->NumberOfTableEntries = gSmst->NumberOfTableEntries;\r
-    mFrameworkSmst->SmmConfigurationTable = gSmst->SmmConfigurationTable;\r
-  }\r
-  return Status;         \r
-}\r
-\r
-/**\r
-  Initialize all the stuff needed for on-demand paging hooks for PI<->Framework\r
-  CpuSaveStates marshalling.\r
-\r
-  @param[in] FrameworkSmst   Framework SMM system table pointer.\r
-\r
-**/\r
-VOID\r
-InitHook (\r
-  IN EFI_SMM_SYSTEM_TABLE  *FrameworkSmst\r
-  )\r
-{\r
-  UINTN                 NumCpuStatePages;\r
-  UINTN                 CpuStatePage;\r
-  UINTN                 Bottom2MPage;\r
-  UINTN                 Top2MPage;\r
-  \r
-  mPageTableHookEnabled = FALSE;\r
-  NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));\r
-  //\r
-  // Only hook page table for X64 image and less than 2MB needed to hold all CPU Save States\r
-  //\r
-  if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) && NumCpuStatePages <= EFI_SIZE_TO_PAGES (SIZE_2MB)) {\r
-    //\r
-    // Allocate double page size to make sure all CPU Save States are in one 2MB page.\r
-    //\r
-    CpuStatePage = (UINTN)AllocatePages (NumCpuStatePages * 2);\r
-    ASSERT (CpuStatePage != 0);\r
-    Bottom2MPage = CpuStatePage & ~(SIZE_2MB-1);\r
-    Top2MPage    = (CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - 1) & ~(SIZE_2MB-1);\r
-    if (Bottom2MPage == Top2MPage ||\r
-        CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - Top2MPage >= EFI_PAGES_TO_SIZE (NumCpuStatePages)\r
-        ) {\r
-      //\r
-      // If the allocated 4KB pages are within the same 2MB page or higher portion is larger, use higher portion pages.\r
-      //\r
-      FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages));\r
-      FreePages ((VOID*)CpuStatePage, NumCpuStatePages);\r
-    } else {\r
-      FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)CpuStatePage;\r
-      FreePages ((VOID*)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages)), NumCpuStatePages);\r
-    }\r
-    //\r
-    // Add temporary working buffer for hooking\r
-    //\r
-    mShadowSaveState = (EFI_SMM_CPU_SAVE_STATE*) AllocatePool (sizeof (EFI_SMM_CPU_SAVE_STATE));\r
-    ASSERT (mShadowSaveState != NULL);\r
-    //\r
-    // Allocate and initialize 4KB Page Table for hooking CpuSaveState.\r
-    // Replace the original 2MB PDE with new 4KB page table.\r
-    //\r
-    mCpuStatePageTable = InitCpuStatePageTable (FrameworkSmst->CpuSaveState);\r
-    //\r
-    // Mark PTE for CpuSaveState as non-exist.\r
-    //\r
-    HookCpuStateMemory (FrameworkSmst->CpuSaveState);\r
-    HookPageFaultHandler ();\r
-    CpuFlushTlb ();\r
-    mPageTableHookEnabled = TRUE;\r
-  }\r
-  mHookInitialized = TRUE;\r
-}\r
-\r
-/**\r
-  Construct a Framework SMST based on the PI SMM SMST.\r
-\r
-  @return  Pointer to the constructed Framework SMST.\r
-**/\r
-EFI_SMM_SYSTEM_TABLE *\r
-ConstructFrameworkSmst (\r
-  VOID\r
-  )\r
-{\r
-  EFI_SMM_SYSTEM_TABLE  *FrameworkSmst;\r
-\r
-  FrameworkSmst = (EFI_SMM_SYSTEM_TABLE  *)AllocatePool (sizeof (EFI_SMM_SYSTEM_TABLE));\r
-  ASSERT (FrameworkSmst != NULL);\r
-\r
-  ///\r
-  /// Copy same things from PI SMST to Framework SMST\r
-  ///\r
-  CopyMem (FrameworkSmst, gSmst, (UINTN)(&((EFI_SMM_SYSTEM_TABLE *)0)->SmmIo));\r
-  CopyMem (\r
-    &FrameworkSmst->SmmIo, \r
-    &gSmst->SmmIo,\r
-    sizeof (EFI_SMM_SYSTEM_TABLE) - (UINTN)(&((EFI_SMM_SYSTEM_TABLE *)0)->SmmIo)\r
-    );\r
-\r
-  ///\r
-  /// Update Framework SMST\r
-  ///\r
-  FrameworkSmst->Hdr.Revision = EFI_SMM_SYSTEM_TABLE_REVISION;\r
-  CopyGuid (&FrameworkSmst->EfiSmmCpuIoGuid, &mEfiSmmCpuIoGuid);\r
-\r
-  mHookInitialized = FALSE;\r
-  FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)AllocateZeroPool (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));\r
-  ASSERT (FrameworkSmst->CpuSaveState != NULL);\r
-\r
-  ///\r
-  /// Do not support floating point state now\r
-  ///\r
-  FrameworkSmst->CpuOptionalFloatingPointState = NULL;\r
-\r
-  FrameworkSmst->SmmInstallConfigurationTable = SmmInstallConfigurationTable;\r
-\r
-  return FrameworkSmst;\r
-}\r
-\r
-/**\r
-  Load a given Framework SMM driver into SMRAM and invoke its entry point.\r
-\r
-  @param[in]   ParentImageHandle     Parent Image Handle.\r
-  @param[in]   FilePath              Location of the image to be installed as the handler.\r
-  @param[in]   SourceBuffer          Optional source buffer in case the image file\r
-                                     is in memory.\r
-  @param[in]   SourceSize            Size of the source image file, if in memory.\r
-  @param[out]  ImageHandle           The handle that the base driver uses to decode \r
-                                     the handler. Unique among SMM handlers only, \r
-                                     not unique across DXE/EFI.\r
-\r
-  @retval      EFI_SUCCESS           The operation was successful.\r
-  @retval      EFI_OUT_OF_RESOURCES  There were no additional SMRAM resources to load the handler\r
-  @retval      EFI_UNSUPPORTED       Can not find its copy in normal memory.\r
-  @retval      EFI_INVALID_PARAMETER The handlers was not the correct image type\r
-**/\r
-EFI_STATUS\r
-LoadImage (\r
-  IN      EFI_HANDLE                ParentImageHandle,\r
-  IN      EFI_DEVICE_PATH_PROTOCOL  *FilePath,\r
-  IN      VOID                      *SourceBuffer,\r
-  IN      UINTN                     SourceSize,\r
-  OUT     EFI_HANDLE                *ImageHandle\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINTN                 PageCount;\r
-  UINTN                 OrgPageCount;\r
-  EFI_PHYSICAL_ADDRESS  DstBuffer;\r
-\r
-  if (FilePath == NULL || ImageHandle == NULL) {    \r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  PageCount = 1;\r
-  do {\r
-    OrgPageCount = PageCount;\r
-    DstBuffer = (UINTN)-1;\r
-    Status = gSmst->SmmAllocatePages (\r
-                      AllocateMaxAddress,\r
-                      EfiRuntimeServicesCode,\r
-                      PageCount,\r
-                      &DstBuffer\r
-                      );\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-\r
-    Status = mLoadPe32Image->LoadPeImage (\r
-                               mLoadPe32Image,\r
-                               ParentImageHandle,\r
-                               FilePath,\r
-                               SourceBuffer,\r
-                               SourceSize,\r
-                               DstBuffer,\r
-                               &PageCount,\r
-                               ImageHandle,\r
-                               NULL,\r
-                               EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE\r
-                               );\r
-    if (EFI_ERROR (Status)) {\r
-      FreePages ((VOID *)(UINTN)DstBuffer, OrgPageCount);\r
-    }\r
-  } while (Status == EFI_BUFFER_TOO_SMALL);\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    ///\r
-    /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point\r
-    ///\r
-    mFrameworkSmst->SmmStartupThisAp      = gSmst->SmmStartupThisAp;\r
-    mFrameworkSmst->NumberOfCpus          = mNumberOfProcessors;\r
-    mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;\r
-\r
-    RegisterSmramProfileImage (FilePath, DstBuffer, PageCount);\r
-    Status = gBS->StartImage (*ImageHandle, NULL, NULL);\r
-    if (EFI_ERROR (Status)) {\r
-      UnregisterSmramProfileImage (FilePath, DstBuffer, PageCount);\r
-      mLoadPe32Image->UnLoadPeImage (mLoadPe32Image, *ImageHandle);\r
-      *ImageHandle = NULL;\r
-      FreePages ((VOID *)(UINTN)DstBuffer, PageCount);\r
-    }\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/** \r
-  Thunk service of EFI_SMM_BASE_PROTOCOL.Register().\r
-\r
-  @param[in, out] FunctionData  Pointer to SMMBASE_FUNCTION_DATA.\r
-**/\r
-VOID\r
-Register (\r
-  IN OUT SMMBASE_FUNCTION_DATA *FunctionData\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-\r
-  if (mLocked || FunctionData->Args.Register.LegacyIA32Binary) {\r
-    Status = EFI_UNSUPPORTED;\r
-  } else {\r
-    Status = LoadImage (\r
-               FunctionData->SmmBaseImageHandle,\r
-               FunctionData->Args.Register.FilePath,\r
-               FunctionData->Args.Register.SourceBuffer,\r
-               FunctionData->Args.Register.SourceSize,\r
-               FunctionData->Args.Register.ImageHandle\r
-               );\r
-  }\r
-  FunctionData->Status = Status;\r
-}\r
-\r
-/** \r
-  Thunk service of EFI_SMM_BASE_PROTOCOL.UnRegister().\r
-\r
-  @param[in, out] FunctionData  Pointer to SMMBASE_FUNCTION_DATA.\r
-**/\r
-VOID\r
-UnRegister (\r
-  IN OUT SMMBASE_FUNCTION_DATA *FunctionData\r
-  )\r
-{\r
-  ///\r
-  /// Unregister not supported now\r
-  ///\r
-  FunctionData->Status = EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
-  Search for Framework SMI handler information according to specific PI SMM dispatch handle.\r
-\r
-  @param[in] DispatchHandle  The unique handle assigned by SmiHandlerRegister().  \r
-\r
-  @return  Pointer to CALLBACK_INFO. If NULL, no callback info record is found.\r
-**/\r
-CALLBACK_INFO *\r
-GetCallbackInfo (\r
-  IN EFI_HANDLE  DispatchHandle\r
-  )\r
-{\r
-  LIST_ENTRY  *Node;\r
-\r
-  Node = GetFirstNode (&mCallbackInfoListHead);\r
-  while (!IsNull (&mCallbackInfoListHead, Node)) {\r
-    if (((CALLBACK_INFO *)Node)->DispatchHandle == DispatchHandle) {\r
-      return (CALLBACK_INFO *)Node;\r
-    }\r
-    Node = GetNextNode (&mCallbackInfoListHead, Node);\r
-  }\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Callback thunk for Framework SMI handler.\r
-\r
-  This thunk functions calls the Framework SMI handler and converts the return value\r
-  defined from Framework SMI handlers to a correpsonding return value defined by PI SMM.\r
-\r
-  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
-  @param[in]     Context         Points to an optional handler context which was specified when the\r
-                                 handler was registered.\r
-  @param[in, out] CommBuffer      A pointer to a collection of data in memory that will\r
-                                 be conveyed from a non-SMM environment into an SMM environment.\r
-  @param[in, out] CommBufferSize  The size of the CommBuffer.\r
-\r
-  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers \r
-                                              should still be called.\r
-  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should \r
-                                              still be called.\r
-  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still \r
-                                              be called.\r
-  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CallbackThunk (\r
-  IN EFI_HANDLE  DispatchHandle,\r
-  IN CONST VOID  *Context         OPTIONAL,\r
-  IN OUT VOID    *CommBuffer      OPTIONAL,\r
-  IN OUT UINTN   *CommBufferSize  OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS        Status;\r
-  CALLBACK_INFO     *CallbackInfo;\r
-  UINTN             CpuIndex;\r
-\r
-  ///\r
-  /// Before transferring the control into the Framework SMI handler, update CPU Save States\r
-  /// and MP states in the Framework SMST.\r
-  ///\r
-\r
-  if (!mHookInitialized) {\r
-    InitHook (mFrameworkSmst);\r
-  }\r
-  if (mPageTableHookEnabled) {\r
-    HookCpuStateMemory (mFrameworkSmst->CpuSaveState);\r
-    CpuFlushTlb ();\r
-  } else {\r
-    for (CpuIndex = 0; CpuIndex < mNumberOfProcessors; CpuIndex++) {\r
-      ReadCpuSaveState (CpuIndex, NULL);\r
-    }\r
-  }\r
-\r
-  mFrameworkSmst->SmmStartupThisAp      = gSmst->SmmStartupThisAp;\r
-  mFrameworkSmst->NumberOfCpus          = mNumberOfProcessors;\r
-  mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;\r
-\r
-  ///\r
-  /// Search for Framework SMI handler information\r
-  ///\r
-  CallbackInfo = GetCallbackInfo (DispatchHandle);\r
-  ASSERT (CallbackInfo != NULL);\r
-\r
-  ///\r
-  /// Thunk into original Framwork SMI handler\r
-  ///\r
-  Status = (CallbackInfo->CallbackAddress) (\r
-                            CallbackInfo->SmmImageHandle,\r
-                            CallbackInfo->CommunicationBuffer,\r
-                            CallbackInfo->SourceSize\r
-                            );\r
-  ///\r
-  /// Save CPU Save States in case any of them was modified\r
-  ///\r
-  if (mPageTableHookEnabled) {\r
-    WriteBackDirtyPages ();\r
-  } else {\r
-    for (CpuIndex = 0; CpuIndex < mNumberOfProcessors; CpuIndex++) {\r
-      WriteCpuSaveState (CpuIndex, NULL);\r
-    }\r
-  }\r
-\r
-  ///\r
-  /// Conversion of returned status code\r
-  ///\r
-  switch (Status) {\r
-    case EFI_HANDLER_SUCCESS:\r
-      Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED;\r
-      break;\r
-    case EFI_HANDLER_CRITICAL_EXIT:\r
-    case EFI_HANDLER_SOURCE_QUIESCED:\r
-      Status = EFI_SUCCESS;\r
-      break;\r
-    case EFI_HANDLER_SOURCE_PENDING:\r
-      Status = EFI_WARN_INTERRUPT_SOURCE_PENDING;\r
-      break;\r
-  }\r
-  return Status;\r
-}\r
-\r
-/** \r
-  Thunk service of EFI_SMM_BASE_PROTOCOL.RegisterCallback().\r
-\r
-  @param[in, out] FunctionData  Pointer to SMMBASE_FUNCTION_DATA.\r
-**/\r
-VOID\r
-RegisterCallback (\r
-  IN OUT SMMBASE_FUNCTION_DATA  *FunctionData\r
-  )\r
-{\r
-  CALLBACK_INFO  *Buffer;\r
-\r
-  if (mLocked) {\r
-    FunctionData->Status = EFI_UNSUPPORTED;\r
-    return;\r
-  }\r
-\r
-  ///\r
-  /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM\r
-  ///\r
-\r
-  ///\r
-  /// Allocate buffer for callback thunk information\r
-  ///\r
-  Buffer = (CALLBACK_INFO *)AllocateZeroPool (sizeof (CALLBACK_INFO));\r
-  if (Buffer == NULL) {\r
-    FunctionData->Status = EFI_OUT_OF_RESOURCES;\r
-    return;\r
-  }\r
-\r
-  ///\r
-  /// Fill SmmImageHandle and CallbackAddress into the thunk\r
-  ///\r
-  Buffer->SmmImageHandle = FunctionData->Args.RegisterCallback.SmmImageHandle;\r
-  Buffer->CallbackAddress = FunctionData->Args.RegisterCallback.CallbackAddress;\r
-\r
-  ///\r
-  /// Register the thunk code as a root SMI handler\r
-  ///\r
-  FunctionData->Status = gSmst->SmiHandlerRegister (\r
-                                  CallbackThunk,\r
-                                  NULL,\r
-                                  &Buffer->DispatchHandle\r
-                                  );\r
-  if (EFI_ERROR (FunctionData->Status)) {\r
-    FreePool (Buffer);\r
-    return;\r
-  }\r
-\r
-  ///\r
-  /// Save this callback info\r
-  ///\r
-  InsertTailList (&mCallbackInfoListHead, &Buffer->Link);\r
-}\r
-\r
-\r
-/** \r
-  Thunk service of EFI_SMM_BASE_PROTOCOL.SmmAllocatePool().\r
-\r
-  @param[in, out] FunctionData  Pointer to SMMBASE_FUNCTION_DATA.\r
-**/\r
-VOID\r
-HelperAllocatePool (\r
-  IN OUT SMMBASE_FUNCTION_DATA *FunctionData\r
-  )\r
-{\r
-  if (mLocked) {\r
-    FunctionData->Status =  EFI_UNSUPPORTED;\r
-  } else {\r
-    FunctionData->Status = gSmst->SmmAllocatePool (\r
-                                    FunctionData->Args.AllocatePool.PoolType,\r
-                                    FunctionData->Args.AllocatePool.Size,\r
-                                    FunctionData->Args.AllocatePool.Buffer\r
-                                    );\r
-  }\r
-}\r
-\r
-/** \r
-  Thunk service of EFI_SMM_BASE_PROTOCOL.SmmFreePool().\r
-\r
-  @param[in, out] FunctionData  Pointer to SMMBASE_FUNCTION_DATA.\r
-**/\r
-VOID\r
-HelperFreePool (\r
-  IN OUT SMMBASE_FUNCTION_DATA *FunctionData\r
-  )\r
-{\r
-  if (mLocked) {\r
-    FunctionData->Status =  EFI_UNSUPPORTED;\r
-  } else {\r
-    FreePool (FunctionData->Args.FreePool.Buffer);\r
-    FunctionData->Status = EFI_SUCCESS;\r
-  }\r
-}\r
-\r
-/** \r
-  Thunk service of EFI_SMM_BASE_PROTOCOL.Communicate().\r
-\r
-  @param[in, out] FunctionData  Pointer to SMMBASE_FUNCTION_DATA.\r
-**/\r
-VOID\r
-HelperCommunicate (\r
-  IN OUT SMMBASE_FUNCTION_DATA *FunctionData\r
-  )\r
-{\r
-  LIST_ENTRY     *Node;\r
-  CALLBACK_INFO  *CallbackInfo;\r
-\r
-  if (FunctionData->Args.Communicate.CommunicationBuffer == NULL) {\r
-    FunctionData->Status = EFI_INVALID_PARAMETER;\r
-    return;\r
-  }\r
-\r
-  Node = GetFirstNode (&mCallbackInfoListHead);\r
-  while (!IsNull (&mCallbackInfoListHead, Node)) {\r
-    CallbackInfo = (CALLBACK_INFO *)Node;\r
-\r
-    if (FunctionData->Args.Communicate.ImageHandle == CallbackInfo->SmmImageHandle) {\r
-      CallbackInfo->CommunicationBuffer = FunctionData->Args.Communicate.CommunicationBuffer;\r
-      CallbackInfo->SourceSize          = FunctionData->Args.Communicate.SourceSize;\r
-\r
-      ///\r
-      /// The message was successfully posted.\r
-      ///\r
-      FunctionData->Status = EFI_SUCCESS;\r
-      return;\r
-    }\r
-    Node = GetNextNode (&mCallbackInfoListHead, Node);\r
-  }\r
-\r
-  FunctionData->Status = EFI_INVALID_PARAMETER;\r
-}\r
-\r
-/**\r
-  Communication service SMI Handler entry.\r
-\r
-  This SMI handler provides services for the SMM Base Thunk driver.\r
-\r
-  Caution: This function may receive untrusted input during runtime.\r
-  The communicate buffer is external input, so this function will do operations only if the communicate\r
-  buffer is outside of SMRAM so that returning the status code in the buffer won't overwrite anywhere in SMRAM.\r
-\r
-  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
-  @param[in]     RegisterContext Points to an optional handler context which was specified when the\r
-                                 handler was registered.\r
-  @param[in, out] CommBuffer      A pointer to a collection of data in memory that will\r
-                                 be conveyed from a non-SMM environment into an SMM environment.\r
-  @param[in, out] CommBufferSize  The size of the CommBuffer.\r
-\r
-  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers \r
-                                              should still be called.\r
-  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should \r
-                                              still be called.\r
-  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still \r
-                                              be called.\r
-  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmHandlerEntry (\r
-  IN     EFI_HANDLE               DispatchHandle,\r
-  IN     CONST VOID               *RegisterContext,\r
-  IN OUT VOID                     *CommBuffer,\r
-  IN OUT UINTN                    *CommBufferSize\r
-  )\r
-{\r
-  SMMBASE_FUNCTION_DATA *FunctionData;\r
-\r
-  ASSERT (CommBuffer != NULL);\r
-  ASSERT (CommBufferSize != NULL);\r
-\r
-  if (*CommBufferSize == sizeof (SMMBASE_FUNCTION_DATA) &&\r
-      SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, (UINT64)*CommBufferSize)) {\r
-    FunctionData = (SMMBASE_FUNCTION_DATA *)CommBuffer;\r
-\r
-    switch (FunctionData->Function) {\r
-      case SmmBaseFunctionRegister:\r
-        Register (FunctionData);\r
-        break;\r
-      case SmmBaseFunctionUnregister:\r
-        UnRegister (FunctionData);\r
-        break;\r
-      case SmmBaseFunctionRegisterCallback:\r
-        RegisterCallback (FunctionData);\r
-        break;\r
-      case SmmBaseFunctionAllocatePool:\r
-        HelperAllocatePool (FunctionData);\r
-        break;\r
-      case SmmBaseFunctionFreePool:\r
-        HelperFreePool (FunctionData);\r
-        break;\r
-      case SmmBaseFunctionCommunicate:\r
-        HelperCommunicate (FunctionData);\r
-        break;\r
-      default:\r
-        DEBUG ((EFI_D_WARN, "SmmBaseHelper: invalid SMM Base function.\n"));\r
-        FunctionData->Status = EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Smm Ready To Lock event notification handler.\r
-\r
-  It sets a flag indicating that SMRAM has been locked.\r
-  \r
-  @param[in] Protocol   Points to the protocol's unique identifier.\r
-  @param[in] Interface  Points to the interface instance.\r
-  @param[in] Handle     The handle on which the interface was installed.\r
-\r
-  @retval EFI_SUCCESS   Notification handler runs successfully.\r
- **/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmReadyToLockEventNotify (\r
-  IN CONST EFI_GUID  *Protocol,\r
-  IN VOID            *Interface,\r
-  IN EFI_HANDLE      Handle\r
-  )\r
-{\r
-  mLocked = TRUE;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Entry point function of the SMM Base Helper SMM driver.\r
-\r
-  @param[in] ImageHandle  The firmware allocated handle for the EFI image.  \r
-  @param[in] SystemTable  A pointer to the EFI System Table.\r
-  \r
-  @retval EFI_SUCCESS     The entry point is executed successfully.\r
-  @retval other           Some error occurs when executing this entry point.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmBaseHelperMain (\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_SYSTEM_TABLE  *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  EFI_MP_SERVICES_PROTOCOL   *MpServices;\r
-  EFI_HANDLE                 Handle;\r
-  UINTN                      NumberOfEnabledProcessors;\r
-  VOID                       *Registration;\r
-  \r
-  Handle = NULL;\r
-  ///\r
-  /// Locate SMM CPU Protocol which is used later to retrieve/update CPU Save States\r
-  ///\r
-  Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ///\r
-  /// Locate PE32 Image Protocol which is used later to load Framework SMM driver\r
-  ///\r
-  Status = SystemTable->BootServices->LocateProtocol (&gEfiLoadPeImageProtocolGuid, NULL, (VOID **) &mLoadPe32Image);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Get MP Services Protocol\r
-  //\r
-  Status = SystemTable->BootServices->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Use MP Services Protocol to retrieve the number of processors and number of enabled processors\r
-  //\r
-  Status = MpServices->GetNumberOfProcessors (MpServices, &mNumberOfProcessors, &NumberOfEnabledProcessors);\r
-  ASSERT_EFI_ERROR (Status);\r
-  \r
-  ///\r
-  /// Interface structure of SMM BASE Helper Ready Protocol is allocated from UEFI pool\r
-  /// instead of SMM pool so that SMM Base Thunk driver can access it in Non-SMM mode.\r
-  ///\r
-  Status = gBS->AllocatePool (\r
-                  EfiBootServicesData,\r
-                  sizeof (EFI_SMM_BASE_HELPER_READY_PROTOCOL),\r
-                  (VOID **)&mSmmBaseHelperReady\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ///\r
-  /// Construct Framework SMST from PI SMST\r
-  ///\r
-  mFrameworkSmst = ConstructFrameworkSmst ();\r
-  mSmmBaseHelperReady->FrameworkSmst = mFrameworkSmst;\r
-  mSmmBaseHelperReady->ServiceEntry = SmmHandlerEntry;\r
-\r
-  //\r
-  // Register SMM Ready To Lock Protocol notification\r
-  //\r
-  Status = gSmst->SmmRegisterProtocolNotify (\r
-                    &gEfiSmmReadyToLockProtocolGuid,\r
-                    SmmReadyToLockEventNotify,\r
-                    &Registration\r
-                    );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ///\r
-  /// Register SMM Base Helper services for SMM Base Thunk driver\r
-  ///\r
-  Status = gSmst->SmiHandlerRegister (SmmHandlerEntry, &gEfiSmmBaseThunkCommunicationGuid, &mDispatchHandle);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ///\r
-  /// Install EFI SMM Base Helper Protocol in the UEFI handle database\r
-  ///\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &Handle,\r
-                  &gEfiSmmBaseHelperReadyProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  mSmmBaseHelperReady\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return Status;\r
-}\r
-\r