• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
SmmEfiNotAvailableYetArg5(UINTN Arg1,UINTN Arg2,UINTN Arg3,UINTN Arg4,UINTN Arg5)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
SmmLegacyBootHandler(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,OPTIONAL IN OUT VOID * CommBuffer,OPTIONAL IN OUT UINTN * CommBufferSize OPTIONAL)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
SmmExitBootServicesHandler(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,OPTIONAL IN OUT VOID * CommBuffer,OPTIONAL IN OUT UINTN * CommBufferSize OPTIONAL)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
SmmReadyToBootHandler(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,OPTIONAL IN OUT VOID * CommBuffer,OPTIONAL IN OUT UINTN * CommBufferSize OPTIONAL)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
SmmReadyToLockHandler(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,OPTIONAL IN OUT VOID * CommBuffer,OPTIONAL IN OUT UINTN * CommBufferSize OPTIONAL)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
SmmEndOfDxeHandler(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,OPTIONAL IN OUT VOID * CommBuffer,OPTIONAL IN OUT UINTN * CommBufferSize OPTIONAL)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
InternalIsBufferOverlapped(IN UINT8 * Buff1,IN UINTN Size1,IN UINT8 * Buff2,IN UINTN Size2)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
SmmEntryPoint(IN CONST EFI_SMM_ENTRY_CONTEXT * SmmEntryContext)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
SmmCoreInstallLoadedImage(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
SmmMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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