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