Home | History | Annotate | Download | only in PiSmmCore
      1 /** @file
      2   SMM Core Main Entry Point
      3 
      4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials are licensed and made available
      6   under the terms and conditions of the BSD License which accompanies this
      7   distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "PiSmmCore.h"
     16 
     17 //
     18 // Physical pointer to private structure shared between SMM IPL and the SMM Core
     19 //
     20 SMM_CORE_PRIVATE_DATA  *gSmmCorePrivate;
     21 
     22 //
     23 // SMM Core global variable for SMM System Table.  Only accessed as a physical structure in SMRAM.
     24 //
     25 EFI_SMM_SYSTEM_TABLE2  gSmmCoreSmst = {
     26   {
     27     SMM_SMST_SIGNATURE,
     28     EFI_SMM_SYSTEM_TABLE2_REVISION,
     29     sizeof (gSmmCoreSmst.Hdr)
     30   },
     31   NULL,                          // SmmFirmwareVendor
     32   0,                             // SmmFirmwareRevision
     33   SmmInstallConfigurationTable,
     34   {
     35     {
     36       (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5,       // SmmMemRead
     37       (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5        // SmmMemWrite
     38     },
     39     {
     40       (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5,       // SmmIoRead
     41       (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5        // SmmIoWrite
     42     }
     43   },
     44   SmmAllocatePool,
     45   SmmFreePool,
     46   SmmAllocatePages,
     47   SmmFreePages,
     48   NULL,                          // SmmStartupThisAp
     49   0,                             // CurrentlyExecutingCpu
     50   0,                             // NumberOfCpus
     51   NULL,                          // CpuSaveStateSize
     52   NULL,                          // CpuSaveState
     53   0,                             // NumberOfTableEntries
     54   NULL,                          // SmmConfigurationTable
     55   SmmInstallProtocolInterface,
     56   SmmUninstallProtocolInterface,
     57   SmmHandleProtocol,
     58   SmmRegisterProtocolNotify,
     59   SmmLocateHandle,
     60   SmmLocateProtocol,
     61   SmiManage,
     62   SmiHandlerRegister,
     63   SmiHandlerUnRegister
     64 };
     65 
     66 //
     67 // Flag to determine if the platform has performed a legacy boot.
     68 // If this flag is TRUE, then the runtime code and runtime data associated with the
     69 // SMM IPL are converted to free memory, so the SMM Core must guarantee that is
     70 // does not touch of the code/data associated with the SMM IPL if this flag is TRUE.
     71 //
     72 BOOLEAN  mInLegacyBoot = FALSE;
     73 
     74 //
     75 // Table of SMI Handlers that are registered by the SMM Core when it is initialized
     76 //
     77 SMM_CORE_SMI_HANDLERS  mSmmCoreSmiHandlers[] = {
     78   { SmmDriverDispatchHandler,   &gEfiEventDxeDispatchGuid,          NULL, TRUE  },
     79   { SmmReadyToLockHandler,      &gEfiDxeSmmReadyToLockProtocolGuid, NULL, TRUE },
     80   { SmmLegacyBootHandler,       &gEfiEventLegacyBootGuid,           NULL, FALSE },
     81   { SmmExitBootServicesHandler, &gEfiEventExitBootServicesGuid,     NULL, FALSE },
     82   { SmmReadyToBootHandler,      &gEfiEventReadyToBootGuid,          NULL, FALSE },
     83   { SmmEndOfDxeHandler,         &gEfiEndOfDxeEventGroupGuid,        NULL, TRUE },
     84   { NULL,                       NULL,                               NULL, FALSE }
     85 };
     86 
     87 UINTN                           mFullSmramRangeCount;
     88 EFI_SMRAM_DESCRIPTOR            *mFullSmramRanges;
     89 
     90 EFI_SMM_DRIVER_ENTRY            *mSmmCoreDriverEntry;
     91 
     92 EFI_LOADED_IMAGE_PROTOCOL       *mSmmCoreLoadedImage;
     93 
     94 /**
     95   Place holder function until all the SMM System Table Service are available.
     96 
     97   Note: This function is only used by SMRAM invocation.  It is never used by DXE invocation.
     98 
     99   @param  Arg1                   Undefined
    100   @param  Arg2                   Undefined
    101   @param  Arg3                   Undefined
    102   @param  Arg4                   Undefined
    103   @param  Arg5                   Undefined
    104 
    105   @return EFI_NOT_AVAILABLE_YET
    106 
    107 **/
    108 EFI_STATUS
    109 EFIAPI
    110 SmmEfiNotAvailableYetArg5 (
    111   UINTN Arg1,
    112   UINTN Arg2,
    113   UINTN Arg3,
    114   UINTN Arg4,
    115   UINTN Arg5
    116   )
    117 {
    118   //
    119   // This function should never be executed.  If it does, then the architectural protocols
    120   // have not been designed correctly.
    121   //
    122   return EFI_NOT_AVAILABLE_YET;
    123 }
    124 
    125 /**
    126   Software SMI handler that is called when a Legacy Boot event is signalled.  The SMM
    127   Core uses this signal to know that a Legacy Boot has been performed and that
    128   gSmmCorePrivate that is shared between the UEFI and SMM execution environments can
    129   not be accessed from SMM anymore since that structure is considered free memory by
    130   a legacy OS. Then the SMM Core also install SMM Legacy Boot protocol to notify SMM
    131   driver that system enter legacy boot.
    132 
    133   @param  DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
    134   @param  Context         Points to an optional handler context which was specified when the handler was registered.
    135   @param  CommBuffer      A pointer to a collection of data in memory that will
    136                           be conveyed from a non-SMM environment into an SMM environment.
    137   @param  CommBufferSize  The size of the CommBuffer.
    138 
    139   @return Status Code
    140 
    141 **/
    142 EFI_STATUS
    143 EFIAPI
    144 SmmLegacyBootHandler (
    145   IN     EFI_HANDLE  DispatchHandle,
    146   IN     CONST VOID  *Context,        OPTIONAL
    147   IN OUT VOID        *CommBuffer,     OPTIONAL
    148   IN OUT UINTN       *CommBufferSize  OPTIONAL
    149   )
    150 {
    151   EFI_STATUS    Status;
    152   EFI_HANDLE    SmmHandle;
    153 
    154   //
    155   // Install SMM Legacy Boot protocol.
    156   //
    157   SmmHandle = NULL;
    158   Status = SmmInstallProtocolInterface (
    159              &SmmHandle,
    160              &gEdkiiSmmLegacyBootProtocolGuid,
    161              EFI_NATIVE_INTERFACE,
    162              NULL
    163              );
    164 
    165   mInLegacyBoot = TRUE;
    166 
    167   SmiHandlerUnRegister (DispatchHandle);
    168 
    169   return Status;
    170 }
    171 
    172 /**
    173   Software SMI handler that is called when an Exit Boot Services event is signalled.
    174   Then the SMM Core also install SMM Exit Boot Services protocol to notify SMM driver
    175   that system enter exit boot services.
    176 
    177   @param  DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
    178   @param  Context         Points to an optional handler context which was specified when the handler was registered.
    179   @param  CommBuffer      A pointer to a collection of data in memory that will
    180                           be conveyed from a non-SMM environment into an SMM environment.
    181   @param  CommBufferSize  The size of the CommBuffer.
    182 
    183   @return Status Code
    184 
    185 **/
    186 EFI_STATUS
    187 EFIAPI
    188 SmmExitBootServicesHandler (
    189   IN     EFI_HANDLE  DispatchHandle,
    190   IN     CONST VOID  *Context,        OPTIONAL
    191   IN OUT VOID        *CommBuffer,     OPTIONAL
    192   IN OUT UINTN       *CommBufferSize  OPTIONAL
    193   )
    194 {
    195   EFI_STATUS    Status;
    196   EFI_HANDLE    SmmHandle;
    197 
    198   //
    199   // Install SMM Exit Boot Services protocol.
    200   //
    201   SmmHandle = NULL;
    202   Status = SmmInstallProtocolInterface (
    203              &SmmHandle,
    204              &gEdkiiSmmExitBootServicesProtocolGuid,
    205              EFI_NATIVE_INTERFACE,
    206              NULL
    207              );
    208 
    209   SmiHandlerUnRegister (DispatchHandle);
    210 
    211   return Status;
    212 }
    213 
    214 /**
    215   Software SMI handler that is called when an Ready To Boot event is signalled.
    216   Then the SMM Core also install SMM Ready To Boot protocol to notify SMM driver
    217   that system enter ready to boot.
    218 
    219   @param  DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
    220   @param  Context         Points to an optional handler context which was specified when the handler was registered.
    221   @param  CommBuffer      A pointer to a collection of data in memory that will
    222                           be conveyed from a non-SMM environment into an SMM environment.
    223   @param  CommBufferSize  The size of the CommBuffer.
    224 
    225   @return Status Code
    226 
    227 **/
    228 EFI_STATUS
    229 EFIAPI
    230 SmmReadyToBootHandler (
    231   IN     EFI_HANDLE  DispatchHandle,
    232   IN     CONST VOID  *Context,        OPTIONAL
    233   IN OUT VOID        *CommBuffer,     OPTIONAL
    234   IN OUT UINTN       *CommBufferSize  OPTIONAL
    235   )
    236 {
    237   EFI_STATUS    Status;
    238   EFI_HANDLE    SmmHandle;
    239 
    240   //
    241   // Install SMM Ready To Boot protocol.
    242   //
    243   SmmHandle = NULL;
    244   Status = SmmInstallProtocolInterface (
    245              &SmmHandle,
    246              &gEdkiiSmmReadyToBootProtocolGuid,
    247              EFI_NATIVE_INTERFACE,
    248              NULL
    249              );
    250 
    251   SmiHandlerUnRegister (DispatchHandle);
    252 
    253   return Status;
    254 }
    255 
    256 /**
    257   Software SMI handler that is called when the DxeSmmReadyToLock protocol is added
    258   or if gEfiEventReadyToBootGuid is signalled.  This function unregisters the
    259   Software SMIs that are nor required after SMRAM is locked and installs the
    260   SMM Ready To Lock Protocol so SMM Drivers are informed that SMRAM is about
    261   to be locked.  It also verifies the SMM CPU I/O 2 Protocol has been installed
    262   and NULLs gBS and gST because they can not longer be used after SMRAM is locked.
    263 
    264   @param  DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
    265   @param  Context         Points to an optional handler context which was specified when the handler was registered.
    266   @param  CommBuffer      A pointer to a collection of data in memory that will
    267                           be conveyed from a non-SMM environment into an SMM environment.
    268   @param  CommBufferSize  The size of the CommBuffer.
    269 
    270   @return Status Code
    271 
    272 **/
    273 EFI_STATUS
    274 EFIAPI
    275 SmmReadyToLockHandler (
    276   IN     EFI_HANDLE  DispatchHandle,
    277   IN     CONST VOID  *Context,        OPTIONAL
    278   IN OUT VOID        *CommBuffer,     OPTIONAL
    279   IN OUT UINTN       *CommBufferSize  OPTIONAL
    280   )
    281 {
    282   EFI_STATUS  Status;
    283   UINTN       Index;
    284   EFI_HANDLE  SmmHandle;
    285   VOID        *Interface;
    286 
    287   //
    288   // Unregister SMI Handlers that are no required after the SMM driver dispatch is stopped
    289   //
    290   for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
    291     if (mSmmCoreSmiHandlers[Index].UnRegister) {
    292       SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);
    293     }
    294   }
    295 
    296   //
    297   // Install SMM Ready to lock protocol
    298   //
    299   SmmHandle = NULL;
    300   Status = SmmInstallProtocolInterface (
    301              &SmmHandle,
    302              &gEfiSmmReadyToLockProtocolGuid,
    303              EFI_NATIVE_INTERFACE,
    304              NULL
    305              );
    306 
    307   //
    308   // Make sure SMM CPU I/O 2 Procol has been installed into the handle database
    309   //
    310   Status = SmmLocateProtocol (&gEfiSmmCpuIo2ProtocolGuid, NULL, &Interface);
    311 
    312   //
    313   // Print a message on a debug build if the SMM CPU I/O 2 Protocol is not installed
    314   //
    315   DEBUG_CODE_BEGIN ();
    316     if (EFI_ERROR (Status)) {
    317       DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));
    318     }
    319   DEBUG_CODE_END ();
    320 
    321   //
    322   // Assert if the CPU I/O 2 Protocol is not installed
    323   //
    324   ASSERT_EFI_ERROR (Status);
    325 
    326   //
    327   // Display any drivers that were not dispatched because dependency expression
    328   // evaluated to false if this is a debug build
    329   //
    330   DEBUG_CODE_BEGIN ();
    331     SmmDisplayDiscoveredNotDispatched ();
    332   DEBUG_CODE_END ();
    333 
    334   //
    335   // Not allowed to use gST or gBS after lock
    336   //
    337   gST = NULL;
    338   gBS = NULL;
    339 
    340   SmramProfileReadyToLock ();
    341 
    342   return Status;
    343 }
    344 
    345 /**
    346   Software SMI handler that is called when the EndOfDxe event is signalled.
    347   This function installs the SMM EndOfDxe Protocol so SMM Drivers are informed that
    348   platform code will invoke 3rd part code.
    349 
    350   @param  DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
    351   @param  Context         Points to an optional handler context which was specified when the handler was registered.
    352   @param  CommBuffer      A pointer to a collection of data in memory that will
    353                           be conveyed from a non-SMM environment into an SMM environment.
    354   @param  CommBufferSize  The size of the CommBuffer.
    355 
    356   @return Status Code
    357 
    358 **/
    359 EFI_STATUS
    360 EFIAPI
    361 SmmEndOfDxeHandler (
    362   IN     EFI_HANDLE  DispatchHandle,
    363   IN     CONST VOID  *Context,        OPTIONAL
    364   IN OUT VOID        *CommBuffer,     OPTIONAL
    365   IN OUT UINTN       *CommBufferSize  OPTIONAL
    366   )
    367 {
    368   EFI_STATUS  Status;
    369   EFI_HANDLE  SmmHandle;
    370 
    371   DEBUG ((EFI_D_INFO, "SmmEndOfDxeHandler\n"));
    372   //
    373   // Install SMM EndOfDxe protocol
    374   //
    375   SmmHandle = NULL;
    376   Status = SmmInstallProtocolInterface (
    377              &SmmHandle,
    378              &gEfiSmmEndOfDxeProtocolGuid,
    379              EFI_NATIVE_INTERFACE,
    380              NULL
    381              );
    382   return Status;
    383 }
    384 
    385 /**
    386   Determine if two buffers overlap in memory.
    387 
    388   @param[in] Buff1  Pointer to first buffer
    389   @param[in] Size1  Size of Buff1
    390   @param[in] Buff2  Pointer to second buffer
    391   @param[in] Size2  Size of Buff2
    392 
    393   @retval TRUE      Buffers overlap in memory.
    394   @retval FALSE     Buffer doesn't overlap.
    395 
    396 **/
    397 BOOLEAN
    398 InternalIsBufferOverlapped (
    399   IN UINT8      *Buff1,
    400   IN UINTN      Size1,
    401   IN UINT8      *Buff2,
    402   IN UINTN      Size2
    403   )
    404 {
    405   //
    406   // If buff1's end is less than the start of buff2, then it's ok.
    407   // Also, if buff1's start is beyond buff2's end, then it's ok.
    408   //
    409   if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {
    410     return FALSE;
    411   }
    412 
    413   return TRUE;
    414 }
    415 
    416 /**
    417   The main entry point to SMM Foundation.
    418 
    419   Note: This function is only used by SMRAM invocation.  It is never used by DXE invocation.
    420 
    421   @param  SmmEntryContext           Processor information and functionality
    422                                     needed by SMM Foundation.
    423 
    424 **/
    425 VOID
    426 EFIAPI
    427 SmmEntryPoint (
    428   IN CONST EFI_SMM_ENTRY_CONTEXT  *SmmEntryContext
    429 )
    430 {
    431   EFI_STATUS                  Status;
    432   EFI_SMM_COMMUNICATE_HEADER  *CommunicateHeader;
    433   BOOLEAN                     InLegacyBoot;
    434   BOOLEAN                     IsOverlapped;
    435   VOID                        *CommunicationBuffer;
    436   UINTN                       BufferSize;
    437 
    438   PERF_START (NULL, "SMM", NULL, 0) ;
    439 
    440   //
    441   // Update SMST with contents of the SmmEntryContext structure
    442   //
    443   gSmmCoreSmst.SmmStartupThisAp      = SmmEntryContext->SmmStartupThisAp;
    444   gSmmCoreSmst.CurrentlyExecutingCpu = SmmEntryContext->CurrentlyExecutingCpu;
    445   gSmmCoreSmst.NumberOfCpus          = SmmEntryContext->NumberOfCpus;
    446   gSmmCoreSmst.CpuSaveStateSize      = SmmEntryContext->CpuSaveStateSize;
    447   gSmmCoreSmst.CpuSaveState          = SmmEntryContext->CpuSaveState;
    448 
    449   //
    450   // Call platform hook before Smm Dispatch
    451   //
    452   PlatformHookBeforeSmmDispatch ();
    453 
    454   //
    455   // If a legacy boot has occured, then make sure gSmmCorePrivate is not accessed
    456   //
    457   InLegacyBoot = mInLegacyBoot;
    458   if (!InLegacyBoot) {
    459     //
    460     // Mark the InSmm flag as TRUE, it will be used by SmmBase2 protocol
    461     //
    462     gSmmCorePrivate->InSmm = TRUE;
    463 
    464     //
    465     // Check to see if this is a Synchronous SMI sent through the SMM Communication
    466     // Protocol or an Asynchronous SMI
    467     //
    468     CommunicationBuffer = gSmmCorePrivate->CommunicationBuffer;
    469     BufferSize          = gSmmCorePrivate->BufferSize;
    470     if (CommunicationBuffer != NULL) {
    471       //
    472       // Synchronous SMI for SMM Core or request from Communicate protocol
    473       //
    474       IsOverlapped = InternalIsBufferOverlapped (
    475                        (UINT8 *) CommunicationBuffer,
    476                        BufferSize,
    477                        (UINT8 *) gSmmCorePrivate,
    478                        sizeof (*gSmmCorePrivate)
    479                        );
    480       if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) || IsOverlapped) {
    481         //
    482         // If CommunicationBuffer is not in valid address scope,
    483         // or there is overlap between gSmmCorePrivate and CommunicationBuffer,
    484         // return EFI_INVALID_PARAMETER
    485         //
    486         gSmmCorePrivate->CommunicationBuffer = NULL;
    487         gSmmCorePrivate->ReturnStatus = EFI_INVALID_PARAMETER;
    488       } else {
    489         CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
    490         BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
    491         Status = SmiManage (
    492                    &CommunicateHeader->HeaderGuid,
    493                    NULL,
    494                    CommunicateHeader->Data,
    495                    &BufferSize
    496                    );
    497         //
    498         // Update CommunicationBuffer, BufferSize and ReturnStatus
    499         // Communicate service finished, reset the pointer to CommBuffer to NULL
    500         //
    501         gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
    502         gSmmCorePrivate->CommunicationBuffer = NULL;
    503         gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
    504       }
    505     }
    506   }
    507 
    508   //
    509   // Process Asynchronous SMI sources
    510   //
    511   SmiManage (NULL, NULL, NULL, NULL);
    512 
    513   //
    514   // Call platform hook after Smm Dispatch
    515   //
    516   PlatformHookAfterSmmDispatch ();
    517 
    518   //
    519   // If a legacy boot has occured, then make sure gSmmCorePrivate is not accessed
    520   //
    521   if (!InLegacyBoot) {
    522     //
    523     // Clear the InSmm flag as we are going to leave SMM
    524     //
    525     gSmmCorePrivate->InSmm = FALSE;
    526   }
    527 
    528   PERF_END (NULL, "SMM", NULL, 0) ;
    529 }
    530 
    531 /**
    532   Install LoadedImage protocol for SMM Core.
    533 **/
    534 VOID
    535 SmmCoreInstallLoadedImage (
    536   VOID
    537   )
    538 {
    539   EFI_STATUS                 Status;
    540   EFI_HANDLE                 Handle;
    541 
    542   //
    543   // Allocate a Loaded Image Protocol in EfiBootServicesData
    544   //
    545   Status = gBS->AllocatePool (EfiBootServicesData, sizeof(EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&mSmmCoreLoadedImage);
    546   ASSERT_EFI_ERROR (Status);
    547 
    548   ZeroMem (mSmmCoreLoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));
    549   //
    550   // Fill in the remaining fields of the Loaded Image Protocol instance.
    551   // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.
    552   //
    553   mSmmCoreLoadedImage->Revision      = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
    554   mSmmCoreLoadedImage->ParentHandle  = gSmmCorePrivate->SmmIplImageHandle;
    555   mSmmCoreLoadedImage->SystemTable   = gST;
    556 
    557   mSmmCoreLoadedImage->ImageBase     = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
    558   mSmmCoreLoadedImage->ImageSize     = gSmmCorePrivate->PiSmmCoreImageSize;
    559   mSmmCoreLoadedImage->ImageCodeType = EfiRuntimeServicesCode;
    560   mSmmCoreLoadedImage->ImageDataType = EfiRuntimeServicesData;
    561 
    562   //
    563   // Create a new image handle in the UEFI handle database for the SMM Driver
    564   //
    565   Handle = NULL;
    566   Status = gBS->InstallMultipleProtocolInterfaces (
    567                   &Handle,
    568                   &gEfiLoadedImageProtocolGuid, mSmmCoreLoadedImage,
    569                   NULL
    570                   );
    571   ASSERT_EFI_ERROR (Status);
    572 
    573   //
    574   // Allocate a Loaded Image Protocol in SMM
    575   //
    576   Status = SmmAllocatePool (EfiRuntimeServicesData, sizeof(EFI_SMM_DRIVER_ENTRY), (VOID **)&mSmmCoreDriverEntry);
    577   ASSERT_EFI_ERROR(Status);
    578 
    579   ZeroMem (mSmmCoreDriverEntry, sizeof(EFI_SMM_DRIVER_ENTRY));
    580   //
    581   // Fill in the remaining fields of the Loaded Image Protocol instance.
    582   //
    583   mSmmCoreDriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;
    584   mSmmCoreDriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
    585   mSmmCoreDriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;
    586   mSmmCoreDriverEntry->SmmLoadedImage.SystemTable = gST;
    587 
    588   mSmmCoreDriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
    589   mSmmCoreDriverEntry->SmmLoadedImage.ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;
    590   mSmmCoreDriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;
    591   mSmmCoreDriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;
    592 
    593   mSmmCoreDriverEntry->ImageEntryPoint = gSmmCorePrivate->PiSmmCoreEntryPoint;
    594   mSmmCoreDriverEntry->ImageBuffer     = gSmmCorePrivate->PiSmmCoreImageBase;
    595   mSmmCoreDriverEntry->NumberOfPage    = EFI_SIZE_TO_PAGES((UINTN)gSmmCorePrivate->PiSmmCoreImageSize);
    596 
    597   //
    598   // Create a new image handle in the SMM handle database for the SMM Driver
    599   //
    600   mSmmCoreDriverEntry->SmmImageHandle = NULL;
    601   Status = SmmInstallProtocolInterface (
    602              &mSmmCoreDriverEntry->SmmImageHandle,
    603              &gEfiLoadedImageProtocolGuid,
    604              EFI_NATIVE_INTERFACE,
    605              &mSmmCoreDriverEntry->SmmLoadedImage
    606              );
    607   ASSERT_EFI_ERROR(Status);
    608 
    609   return ;
    610 }
    611 
    612 /**
    613   The Entry Point for SMM Core
    614 
    615   Install DXE Protocols and reload SMM Core into SMRAM and register SMM Core
    616   EntryPoint on the SMI vector.
    617 
    618   Note: This function is called for both DXE invocation and SMRAM invocation.
    619 
    620   @param  ImageHandle    The firmware allocated handle for the EFI image.
    621   @param  SystemTable    A pointer to the EFI System Table.
    622 
    623   @retval EFI_SUCCESS    The entry point is executed successfully.
    624   @retval Other          Some error occurred when executing this entry point.
    625 
    626 **/
    627 EFI_STATUS
    628 EFIAPI
    629 SmmMain (
    630   IN EFI_HANDLE        ImageHandle,
    631   IN EFI_SYSTEM_TABLE  *SystemTable
    632   )
    633 {
    634   EFI_STATUS  Status;
    635   UINTN       Index;
    636 
    637   //
    638   // Get SMM Core Private context passed in from SMM IPL in ImageHandle.
    639   //
    640   gSmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;
    641 
    642   //
    643   // Fill in SMRAM physical address for the SMM Services Table and the SMM Entry Point.
    644   //
    645   gSmmCorePrivate->Smst          = &gSmmCoreSmst;
    646   gSmmCorePrivate->SmmEntryPoint = SmmEntryPoint;
    647 
    648   //
    649   // No need to initialize memory service.
    650   // It is done in constructor of PiSmmCoreMemoryAllocationLib(),
    651   // so that the library linked with PiSmmCore can use AllocatePool() in constuctor.
    652   //
    653 
    654   SmramProfileInit ();
    655 
    656   //
    657   // Copy FullSmramRanges to SMRAM
    658   //
    659   mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;
    660   mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
    661   ASSERT (mFullSmramRanges != NULL);
    662   CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
    663 
    664   //
    665   // Register all SMI Handlers required by the SMM Core
    666   //
    667   for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
    668     Status = SmiHandlerRegister (
    669                mSmmCoreSmiHandlers[Index].Handler,
    670                mSmmCoreSmiHandlers[Index].HandlerType,
    671                &mSmmCoreSmiHandlers[Index].DispatchHandle
    672                );
    673     ASSERT_EFI_ERROR (Status);
    674   }
    675 
    676   RegisterSmramProfileHandler ();
    677   SmramProfileInstallProtocol ();
    678 
    679   SmmCoreInstallLoadedImage ();
    680 
    681   SmmCoreInitializeMemoryAttributesTable ();
    682 
    683   return EFI_SUCCESS;
    684 }
    685