]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
MdeModulePkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmCore.c
1 /** @file
2 SMM Core Main Entry Point
3
4 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "PiSmmCore.h"
10
11 //
12 // Physical pointer to private structure shared between SMM IPL and the SMM Core
13 //
14 SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;
15
16 //
17 // SMM Core global variable for SMM System Table. Only accessed as a physical structure in SMRAM.
18 //
19 EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst = {
20 {
21 SMM_SMST_SIGNATURE,
22 EFI_SMM_SYSTEM_TABLE2_REVISION,
23 sizeof (gSmmCoreSmst.Hdr)
24 },
25 NULL, // SmmFirmwareVendor
26 0, // SmmFirmwareRevision
27 SmmInstallConfigurationTable,
28 {
29 {
30 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmMemRead
31 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmMemWrite
32 },
33 {
34 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmIoRead
35 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmIoWrite
36 }
37 },
38 SmmAllocatePool,
39 SmmFreePool,
40 SmmAllocatePages,
41 SmmFreePages,
42 NULL, // SmmStartupThisAp
43 0, // CurrentlyExecutingCpu
44 0, // NumberOfCpus
45 NULL, // CpuSaveStateSize
46 NULL, // CpuSaveState
47 0, // NumberOfTableEntries
48 NULL, // SmmConfigurationTable
49 SmmInstallProtocolInterface,
50 SmmUninstallProtocolInterface,
51 SmmHandleProtocol,
52 SmmRegisterProtocolNotify,
53 SmmLocateHandle,
54 SmmLocateProtocol,
55 SmiManage,
56 SmiHandlerRegister,
57 SmiHandlerUnRegister
58 };
59
60 //
61 // Flag to determine if the platform has performed a legacy boot.
62 // If this flag is TRUE, then the runtime code and runtime data associated with the
63 // SMM IPL are converted to free memory, so the SMM Core must guarantee that is
64 // does not touch of the code/data associated with the SMM IPL if this flag is TRUE.
65 //
66 BOOLEAN mInLegacyBoot = FALSE;
67
68 //
69 // Flag to determine if it is during S3 resume.
70 // It will be set in S3 entry callback and cleared at EndOfS3Resume.
71 //
72 BOOLEAN mDuringS3Resume = FALSE;
73
74 //
75 // Flag to determine if platform enabled S3.
76 // Get the value from PcdAcpiS3Enable.
77 //
78 BOOLEAN mAcpiS3Enable = FALSE;
79
80 //
81 // Table of SMI Handlers that are registered by the SMM Core when it is initialized
82 //
83 SMM_CORE_SMI_HANDLERS mSmmCoreSmiHandlers[] = {
84 { SmmDriverDispatchHandler, &gEfiEventDxeDispatchGuid, NULL, TRUE },
85 { SmmReadyToLockHandler, &gEfiDxeSmmReadyToLockProtocolGuid, NULL, TRUE },
86 { SmmLegacyBootHandler, &gEfiEventLegacyBootGuid, NULL, FALSE },
87 { SmmExitBootServicesHandler, &gEfiEventExitBootServicesGuid, NULL, FALSE },
88 { SmmReadyToBootHandler, &gEfiEventReadyToBootGuid, NULL, FALSE },
89 { SmmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, TRUE },
90 { NULL, NULL, NULL, FALSE }
91 };
92
93 //
94 // Table of SMI Handlers that are registered by the SMM Core when it is initialized
95 //
96 SMM_CORE_SMI_HANDLERS mSmmCoreS3SmiHandlers[] = {
97 { SmmS3SmmInitDoneHandler, &gEdkiiS3SmmInitDoneGuid, NULL, FALSE },
98 { SmmEndOfS3ResumeHandler, &gEdkiiEndOfS3ResumeGuid, NULL, FALSE },
99 { NULL, NULL, NULL, FALSE }
100 };
101
102 UINTN mFullSmramRangeCount;
103 EFI_SMRAM_DESCRIPTOR *mFullSmramRanges;
104
105 EFI_SMM_DRIVER_ENTRY *mSmmCoreDriverEntry;
106
107 EFI_LOADED_IMAGE_PROTOCOL *mSmmCoreLoadedImage;
108
109 /**
110 Place holder function until all the SMM System Table Service are available.
111
112 Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.
113
114 @param Arg1 Undefined
115 @param Arg2 Undefined
116 @param Arg3 Undefined
117 @param Arg4 Undefined
118 @param Arg5 Undefined
119
120 @return EFI_NOT_AVAILABLE_YET
121
122 **/
123 EFI_STATUS
124 EFIAPI
125 SmmEfiNotAvailableYetArg5 (
126 UINTN Arg1,
127 UINTN Arg2,
128 UINTN Arg3,
129 UINTN Arg4,
130 UINTN Arg5
131 )
132 {
133 //
134 // This function should never be executed. If it does, then the architectural protocols
135 // have not been designed correctly.
136 //
137 return EFI_NOT_AVAILABLE_YET;
138 }
139
140 /**
141 Software SMI handler that is called when a Legacy Boot event is signalled. The SMM
142 Core uses this signal to know that a Legacy Boot has been performed and that
143 gSmmCorePrivate that is shared between the UEFI and SMM execution environments can
144 not be accessed from SMM anymore since that structure is considered free memory by
145 a legacy OS. Then the SMM Core also install SMM Legacy Boot protocol to notify SMM
146 driver that system enter legacy boot.
147
148 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
149 @param Context Points to an optional handler context which was specified when the handler was registered.
150 @param CommBuffer A pointer to a collection of data in memory that will
151 be conveyed from a non-SMM environment into an SMM environment.
152 @param CommBufferSize The size of the CommBuffer.
153
154 @return Status Code
155
156 **/
157 EFI_STATUS
158 EFIAPI
159 SmmLegacyBootHandler (
160 IN EFI_HANDLE DispatchHandle,
161 IN CONST VOID *Context, OPTIONAL
162 IN OUT VOID *CommBuffer, OPTIONAL
163 IN OUT UINTN *CommBufferSize OPTIONAL
164 )
165 {
166 EFI_STATUS Status;
167 EFI_HANDLE SmmHandle;
168 UINTN Index;
169
170 //
171 // Install SMM Legacy Boot protocol.
172 //
173 SmmHandle = NULL;
174 Status = SmmInstallProtocolInterface (
175 &SmmHandle,
176 &gEdkiiSmmLegacyBootProtocolGuid,
177 EFI_NATIVE_INTERFACE,
178 NULL
179 );
180
181 mInLegacyBoot = TRUE;
182
183 SmiHandlerUnRegister (DispatchHandle);
184
185 //
186 // It is legacy boot, unregister ExitBootService SMI handler.
187 //
188 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
189 if (CompareGuid (mSmmCoreSmiHandlers[Index].HandlerType, &gEfiEventExitBootServicesGuid)) {
190 SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);
191 break;
192 }
193 }
194
195 return Status;
196 }
197
198 /**
199 Software SMI handler that is called when an Exit Boot Services event is signalled.
200 Then the SMM Core also install SMM Exit Boot Services protocol to notify SMM driver
201 that system enter exit boot services.
202
203 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
204 @param Context Points to an optional handler context which was specified when the handler was registered.
205 @param CommBuffer A pointer to a collection of data in memory that will
206 be conveyed from a non-SMM environment into an SMM environment.
207 @param CommBufferSize The size of the CommBuffer.
208
209 @return Status Code
210
211 **/
212 EFI_STATUS
213 EFIAPI
214 SmmExitBootServicesHandler (
215 IN EFI_HANDLE DispatchHandle,
216 IN CONST VOID *Context, OPTIONAL
217 IN OUT VOID *CommBuffer, OPTIONAL
218 IN OUT UINTN *CommBufferSize OPTIONAL
219 )
220 {
221 EFI_STATUS Status;
222 EFI_HANDLE SmmHandle;
223 UINTN Index;
224
225 //
226 // Install SMM Exit Boot Services protocol.
227 //
228 SmmHandle = NULL;
229 Status = SmmInstallProtocolInterface (
230 &SmmHandle,
231 &gEdkiiSmmExitBootServicesProtocolGuid,
232 EFI_NATIVE_INTERFACE,
233 NULL
234 );
235
236 SmiHandlerUnRegister (DispatchHandle);
237
238 //
239 // It is UEFI boot, unregister LegacyBoot SMI handler.
240 //
241 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
242 if (CompareGuid (mSmmCoreSmiHandlers[Index].HandlerType, &gEfiEventLegacyBootGuid)) {
243 SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);
244 break;
245 }
246 }
247
248 return Status;
249 }
250
251 /**
252 Main entry point for an SMM handler dispatch or communicate-based callback.
253
254 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
255 @param[in] Context Points to an optional handler context which was specified when the
256 handler was registered.
257 @param[in,out] CommBuffer A pointer to a collection of data in memory that will
258 be conveyed from a non-SMM environment into an SMM environment.
259 @param[in,out] CommBufferSize The size of the CommBuffer.
260
261 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
262 should still be called.
263 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
264 still be called.
265 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
266 be called.
267 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
268 **/
269 EFI_STATUS
270 EFIAPI
271 SmmS3EntryCallBack (
272 IN EFI_HANDLE DispatchHandle,
273 IN CONST VOID *Context OPTIONAL,
274 IN OUT VOID *CommBuffer OPTIONAL,
275 IN OUT UINTN *CommBufferSize OPTIONAL
276 )
277 {
278 mDuringS3Resume = TRUE;
279 return EFI_SUCCESS;
280 }
281
282 /**
283 Software SMI handler that is called when an Ready To Boot event is signalled.
284 Then the SMM Core also install SMM Ready To Boot protocol to notify SMM driver
285 that system enter ready to boot.
286
287 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
288 @param Context Points to an optional handler context which was specified when the handler was registered.
289 @param CommBuffer A pointer to a collection of data in memory that will
290 be conveyed from a non-SMM environment into an SMM environment.
291 @param CommBufferSize The size of the CommBuffer.
292
293 @return Status Code
294
295 **/
296 EFI_STATUS
297 EFIAPI
298 SmmReadyToBootHandler (
299 IN EFI_HANDLE DispatchHandle,
300 IN CONST VOID *Context, OPTIONAL
301 IN OUT VOID *CommBuffer, OPTIONAL
302 IN OUT UINTN *CommBufferSize OPTIONAL
303 )
304 {
305 EFI_STATUS Status;
306 EFI_HANDLE SmmHandle;
307
308 //
309 // Install SMM Ready To Boot protocol.
310 //
311 SmmHandle = NULL;
312 Status = SmmInstallProtocolInterface (
313 &SmmHandle,
314 &gEdkiiSmmReadyToBootProtocolGuid,
315 EFI_NATIVE_INTERFACE,
316 NULL
317 );
318
319 SmiHandlerUnRegister (DispatchHandle);
320
321 return Status;
322 }
323
324 /**
325 Software SMI handler that is called when the DxeSmmReadyToLock protocol is added
326 or if gEfiEventReadyToBootGuid is signalled. This function unregisters the
327 Software SMIs that are nor required after SMRAM is locked and installs the
328 SMM Ready To Lock Protocol so SMM Drivers are informed that SMRAM is about
329 to be locked. It also verifies the SMM CPU I/O 2 Protocol has been installed
330 and NULLs gBS and gST because they can not longer be used after SMRAM is locked.
331
332 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
333 @param Context Points to an optional handler context which was specified when the handler was registered.
334 @param CommBuffer A pointer to a collection of data in memory that will
335 be conveyed from a non-SMM environment into an SMM environment.
336 @param CommBufferSize The size of the CommBuffer.
337
338 @return Status Code
339
340 **/
341 EFI_STATUS
342 EFIAPI
343 SmmReadyToLockHandler (
344 IN EFI_HANDLE DispatchHandle,
345 IN CONST VOID *Context, OPTIONAL
346 IN OUT VOID *CommBuffer, OPTIONAL
347 IN OUT UINTN *CommBufferSize OPTIONAL
348 )
349 {
350 EFI_STATUS Status;
351 UINTN Index;
352 EFI_HANDLE SmmHandle;
353 VOID *Interface;
354
355 //
356 // Unregister SMI Handlers that are no required after the SMM driver dispatch is stopped
357 //
358 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
359 if (mSmmCoreSmiHandlers[Index].UnRegister) {
360 SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);
361 }
362 }
363
364 //
365 // Install SMM Ready to lock protocol
366 //
367 SmmHandle = NULL;
368 Status = SmmInstallProtocolInterface (
369 &SmmHandle,
370 &gEfiSmmReadyToLockProtocolGuid,
371 EFI_NATIVE_INTERFACE,
372 NULL
373 );
374
375 //
376 // Make sure SMM CPU I/O 2 Protocol has been installed into the handle database
377 //
378 Status = SmmLocateProtocol (&gEfiSmmCpuIo2ProtocolGuid, NULL, &Interface);
379
380 //
381 // Print a message on a debug build if the SMM CPU I/O 2 Protocol is not installed
382 //
383 DEBUG_CODE_BEGIN ();
384 if (EFI_ERROR (Status)) {
385 DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));
386 }
387 DEBUG_CODE_END ();
388
389 //
390 // Assert if the CPU I/O 2 Protocol is not installed
391 //
392 ASSERT_EFI_ERROR (Status);
393
394 //
395 // Display any drivers that were not dispatched because dependency expression
396 // evaluated to false if this is a debug build
397 //
398 DEBUG_CODE_BEGIN ();
399 SmmDisplayDiscoveredNotDispatched ();
400 DEBUG_CODE_END ();
401
402 //
403 // Not allowed to use gST or gBS after lock
404 //
405 gST = NULL;
406 gBS = NULL;
407
408 SmramProfileReadyToLock ();
409
410 return Status;
411 }
412
413 /**
414 Software SMI handler that is called when the EndOfDxe event is signalled.
415 This function installs the SMM EndOfDxe Protocol so SMM Drivers are informed that
416 platform code will invoke 3rd part code.
417
418 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
419 @param Context Points to an optional handler context which was specified when the handler was registered.
420 @param CommBuffer A pointer to a collection of data in memory that will
421 be conveyed from a non-SMM environment into an SMM environment.
422 @param CommBufferSize The size of the CommBuffer.
423
424 @return Status Code
425
426 **/
427 EFI_STATUS
428 EFIAPI
429 SmmEndOfDxeHandler (
430 IN EFI_HANDLE DispatchHandle,
431 IN CONST VOID *Context, OPTIONAL
432 IN OUT VOID *CommBuffer, OPTIONAL
433 IN OUT UINTN *CommBufferSize OPTIONAL
434 )
435 {
436 EFI_STATUS Status;
437 EFI_HANDLE SmmHandle;
438 EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;
439 EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;
440 EFI_HANDLE S3EntryHandle;
441
442 DEBUG ((DEBUG_INFO, "SmmEndOfDxeHandler\n"));
443
444 //
445 // Install SMM EndOfDxe protocol
446 //
447 SmmHandle = NULL;
448 Status = SmmInstallProtocolInterface (
449 &SmmHandle,
450 &gEfiSmmEndOfDxeProtocolGuid,
451 EFI_NATIVE_INTERFACE,
452 NULL
453 );
454
455 if (mAcpiS3Enable) {
456 //
457 // Locate SmmSxDispatch2 protocol.
458 //
459 Status = SmmLocateProtocol (
460 &gEfiSmmSxDispatch2ProtocolGuid,
461 NULL,
462 (VOID **)&SxDispatch
463 );
464 if (!EFI_ERROR (Status) && (SxDispatch != NULL)) {
465 //
466 // Register a S3 entry callback function to
467 // determine if it will be during S3 resume.
468 //
469 EntryRegisterContext.Type = SxS3;
470 EntryRegisterContext.Phase = SxEntry;
471 Status = SxDispatch->Register (
472 SxDispatch,
473 SmmS3EntryCallBack,
474 &EntryRegisterContext,
475 &S3EntryHandle
476 );
477 ASSERT_EFI_ERROR (Status);
478 }
479 }
480
481 return EFI_SUCCESS;
482 }
483
484 /**
485 Software SMI handler that is called when the S3SmmInitDone signal is triggered.
486 This function installs the SMM S3SmmInitDone Protocol so SMM Drivers are informed that
487 S3 SMM initialization has been done.
488
489 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
490 @param Context Points to an optional handler context which was specified when the handler was registered.
491 @param CommBuffer A pointer to a collection of data in memory that will
492 be conveyed from a non-SMM environment into an SMM environment.
493 @param CommBufferSize The size of the CommBuffer.
494
495 @return Status Code
496
497 **/
498 EFI_STATUS
499 EFIAPI
500 SmmS3SmmInitDoneHandler (
501 IN EFI_HANDLE DispatchHandle,
502 IN CONST VOID *Context, OPTIONAL
503 IN OUT VOID *CommBuffer, OPTIONAL
504 IN OUT UINTN *CommBufferSize OPTIONAL
505 )
506 {
507 EFI_STATUS Status;
508 EFI_HANDLE SmmHandle;
509
510 DEBUG ((DEBUG_INFO, "SmmS3SmmInitDoneHandler\n"));
511
512 if (!mDuringS3Resume) {
513 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));
514 return EFI_SUCCESS;
515 }
516
517 //
518 // Install SMM S3SmmInitDone protocol
519 //
520 SmmHandle = NULL;
521 Status = SmmInstallProtocolInterface (
522 &SmmHandle,
523 &gEdkiiS3SmmInitDoneGuid,
524 EFI_NATIVE_INTERFACE,
525 NULL
526 );
527 ASSERT_EFI_ERROR (Status);
528
529 //
530 // Uninstall the protocol here because the comsumer just hook the
531 // installation event.
532 //
533 Status = SmmUninstallProtocolInterface (
534 SmmHandle,
535 &gEdkiiS3SmmInitDoneGuid,
536 NULL
537 );
538 ASSERT_EFI_ERROR (Status);
539
540 return Status;
541 }
542
543 /**
544 Software SMI handler that is called when the EndOfS3Resume signal is triggered.
545 This function installs the SMM EndOfS3Resume Protocol so SMM Drivers are informed that
546 S3 resume has finished.
547
548 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
549 @param Context Points to an optional handler context which was specified when the handler was registered.
550 @param CommBuffer A pointer to a collection of data in memory that will
551 be conveyed from a non-SMM environment into an SMM environment.
552 @param CommBufferSize The size of the CommBuffer.
553
554 @return Status Code
555
556 **/
557 EFI_STATUS
558 EFIAPI
559 SmmEndOfS3ResumeHandler (
560 IN EFI_HANDLE DispatchHandle,
561 IN CONST VOID *Context, OPTIONAL
562 IN OUT VOID *CommBuffer, OPTIONAL
563 IN OUT UINTN *CommBufferSize OPTIONAL
564 )
565 {
566 EFI_STATUS Status;
567 EFI_HANDLE SmmHandle;
568
569 DEBUG ((DEBUG_INFO, "SmmEndOfS3ResumeHandler\n"));
570
571 if (!mDuringS3Resume) {
572 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));
573 return EFI_SUCCESS;
574 }
575
576 //
577 // Install SMM EndOfS3Resume protocol
578 //
579 SmmHandle = NULL;
580 Status = SmmInstallProtocolInterface (
581 &SmmHandle,
582 &gEdkiiEndOfS3ResumeGuid,
583 EFI_NATIVE_INTERFACE,
584 NULL
585 );
586 ASSERT_EFI_ERROR (Status);
587
588 //
589 // Uninstall the protocol here because the consumer just hook the
590 // installation event.
591 //
592 Status = SmmUninstallProtocolInterface (
593 SmmHandle,
594 &gEdkiiEndOfS3ResumeGuid,
595 NULL
596 );
597 ASSERT_EFI_ERROR (Status);
598
599 mDuringS3Resume = FALSE;
600 return Status;
601 }
602
603 /**
604 Determine if two buffers overlap in memory.
605
606 @param[in] Buff1 Pointer to first buffer
607 @param[in] Size1 Size of Buff1
608 @param[in] Buff2 Pointer to second buffer
609 @param[in] Size2 Size of Buff2
610
611 @retval TRUE Buffers overlap in memory.
612 @retval FALSE Buffer doesn't overlap.
613
614 **/
615 BOOLEAN
616 InternalIsBufferOverlapped (
617 IN UINT8 *Buff1,
618 IN UINTN Size1,
619 IN UINT8 *Buff2,
620 IN UINTN Size2
621 )
622 {
623 //
624 // If buff1's end is less than the start of buff2, then it's ok.
625 // Also, if buff1's start is beyond buff2's end, then it's ok.
626 //
627 if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {
628 return FALSE;
629 }
630
631 return TRUE;
632 }
633
634 /**
635 The main entry point to SMM Foundation.
636
637 Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.
638
639 @param SmmEntryContext Processor information and functionality
640 needed by SMM Foundation.
641
642 **/
643 VOID
644 EFIAPI
645 SmmEntryPoint (
646 IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext
647 )
648 {
649 EFI_STATUS Status;
650 EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
651 BOOLEAN InLegacyBoot;
652 BOOLEAN IsOverlapped;
653 VOID *CommunicationBuffer;
654 UINTN BufferSize;
655
656 //
657 // Update SMST with contents of the SmmEntryContext structure
658 //
659 gSmmCoreSmst.SmmStartupThisAp = SmmEntryContext->SmmStartupThisAp;
660 gSmmCoreSmst.CurrentlyExecutingCpu = SmmEntryContext->CurrentlyExecutingCpu;
661 gSmmCoreSmst.NumberOfCpus = SmmEntryContext->NumberOfCpus;
662 gSmmCoreSmst.CpuSaveStateSize = SmmEntryContext->CpuSaveStateSize;
663 gSmmCoreSmst.CpuSaveState = SmmEntryContext->CpuSaveState;
664
665 //
666 // Call platform hook before Smm Dispatch
667 //
668 PlatformHookBeforeSmmDispatch ();
669
670 //
671 // Call memory management hook function
672 //
673 SmmEntryPointMemoryManagementHook ();
674
675 //
676 // If a legacy boot has occurred, then make sure gSmmCorePrivate is not accessed
677 //
678 InLegacyBoot = mInLegacyBoot;
679 if (!InLegacyBoot) {
680 //
681 // Mark the InSmm flag as TRUE, it will be used by SmmBase2 protocol
682 //
683 gSmmCorePrivate->InSmm = TRUE;
684
685 //
686 // Check to see if this is a Synchronous SMI sent through the SMM Communication
687 // Protocol or an Asynchronous SMI
688 //
689 CommunicationBuffer = gSmmCorePrivate->CommunicationBuffer;
690 BufferSize = gSmmCorePrivate->BufferSize;
691 if (CommunicationBuffer != NULL) {
692 //
693 // Synchronous SMI for SMM Core or request from Communicate protocol
694 //
695 IsOverlapped = InternalIsBufferOverlapped (
696 (UINT8 *) CommunicationBuffer,
697 BufferSize,
698 (UINT8 *) gSmmCorePrivate,
699 sizeof (*gSmmCorePrivate)
700 );
701 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) || IsOverlapped) {
702 //
703 // If CommunicationBuffer is not in valid address scope,
704 // or there is overlap between gSmmCorePrivate and CommunicationBuffer,
705 // return EFI_INVALID_PARAMETER
706 //
707 gSmmCorePrivate->CommunicationBuffer = NULL;
708 gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
709 } else {
710 CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
711 BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
712 Status = SmiManage (
713 &CommunicateHeader->HeaderGuid,
714 NULL,
715 CommunicateHeader->Data,
716 &BufferSize
717 );
718 //
719 // Update CommunicationBuffer, BufferSize and ReturnStatus
720 // Communicate service finished, reset the pointer to CommBuffer to NULL
721 //
722 gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
723 gSmmCorePrivate->CommunicationBuffer = NULL;
724 gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
725 }
726 }
727 }
728
729 //
730 // Process Asynchronous SMI sources
731 //
732 SmiManage (NULL, NULL, NULL, NULL);
733
734 //
735 // Call platform hook after Smm Dispatch
736 //
737 PlatformHookAfterSmmDispatch ();
738
739 //
740 // If a legacy boot has occurred, then make sure gSmmCorePrivate is not accessed
741 //
742 if (!InLegacyBoot) {
743 //
744 // Clear the InSmm flag as we are going to leave SMM
745 //
746 gSmmCorePrivate->InSmm = FALSE;
747 }
748 }
749
750 /**
751 Install LoadedImage protocol for SMM Core.
752 **/
753 VOID
754 SmmCoreInstallLoadedImage (
755 VOID
756 )
757 {
758 EFI_STATUS Status;
759 EFI_HANDLE Handle;
760
761 //
762 // Allocate a Loaded Image Protocol in EfiBootServicesData
763 //
764 Status = gBS->AllocatePool (EfiBootServicesData, sizeof(EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&mSmmCoreLoadedImage);
765 ASSERT_EFI_ERROR (Status);
766
767 ZeroMem (mSmmCoreLoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));
768 //
769 // Fill in the remaining fields of the Loaded Image Protocol instance.
770 // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.
771 //
772 mSmmCoreLoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
773 mSmmCoreLoadedImage->ParentHandle = gSmmCorePrivate->SmmIplImageHandle;
774 mSmmCoreLoadedImage->SystemTable = gST;
775
776 mSmmCoreLoadedImage->ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
777 mSmmCoreLoadedImage->ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;
778 mSmmCoreLoadedImage->ImageCodeType = EfiRuntimeServicesCode;
779 mSmmCoreLoadedImage->ImageDataType = EfiRuntimeServicesData;
780
781 //
782 // Create a new image handle in the UEFI handle database for the SMM Driver
783 //
784 Handle = NULL;
785 Status = gBS->InstallMultipleProtocolInterfaces (
786 &Handle,
787 &gEfiLoadedImageProtocolGuid, mSmmCoreLoadedImage,
788 NULL
789 );
790 ASSERT_EFI_ERROR (Status);
791
792 //
793 // Allocate a Loaded Image Protocol in SMM
794 //
795 Status = SmmAllocatePool (EfiRuntimeServicesData, sizeof(EFI_SMM_DRIVER_ENTRY), (VOID **)&mSmmCoreDriverEntry);
796 ASSERT_EFI_ERROR(Status);
797
798 ZeroMem (mSmmCoreDriverEntry, sizeof(EFI_SMM_DRIVER_ENTRY));
799 //
800 // Fill in the remaining fields of the Loaded Image Protocol instance.
801 //
802 mSmmCoreDriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;
803 mSmmCoreDriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
804 mSmmCoreDriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;
805 mSmmCoreDriverEntry->SmmLoadedImage.SystemTable = gST;
806
807 mSmmCoreDriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
808 mSmmCoreDriverEntry->SmmLoadedImage.ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;
809 mSmmCoreDriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;
810 mSmmCoreDriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;
811
812 mSmmCoreDriverEntry->ImageEntryPoint = gSmmCorePrivate->PiSmmCoreEntryPoint;
813 mSmmCoreDriverEntry->ImageBuffer = gSmmCorePrivate->PiSmmCoreImageBase;
814 mSmmCoreDriverEntry->NumberOfPage = EFI_SIZE_TO_PAGES((UINTN)gSmmCorePrivate->PiSmmCoreImageSize);
815
816 //
817 // Create a new image handle in the SMM handle database for the SMM Driver
818 //
819 mSmmCoreDriverEntry->SmmImageHandle = NULL;
820 Status = SmmInstallProtocolInterface (
821 &mSmmCoreDriverEntry->SmmImageHandle,
822 &gEfiLoadedImageProtocolGuid,
823 EFI_NATIVE_INTERFACE,
824 &mSmmCoreDriverEntry->SmmLoadedImage
825 );
826 ASSERT_EFI_ERROR(Status);
827
828 return ;
829 }
830
831 /**
832 The Entry Point for SMM Core
833
834 Install DXE Protocols and reload SMM Core into SMRAM and register SMM Core
835 EntryPoint on the SMI vector.
836
837 Note: This function is called for both DXE invocation and SMRAM invocation.
838
839 @param ImageHandle The firmware allocated handle for the EFI image.
840 @param SystemTable A pointer to the EFI System Table.
841
842 @retval EFI_SUCCESS The entry point is executed successfully.
843 @retval Other Some error occurred when executing this entry point.
844
845 **/
846 EFI_STATUS
847 EFIAPI
848 SmmMain (
849 IN EFI_HANDLE ImageHandle,
850 IN EFI_SYSTEM_TABLE *SystemTable
851 )
852 {
853 EFI_STATUS Status;
854 UINTN Index;
855
856 //
857 // Get SMM Core Private context passed in from SMM IPL in ImageHandle.
858 //
859 gSmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;
860
861 //
862 // Fill in SMRAM physical address for the SMM Services Table and the SMM Entry Point.
863 //
864 gSmmCorePrivate->Smst = &gSmmCoreSmst;
865 gSmmCorePrivate->SmmEntryPoint = SmmEntryPoint;
866
867 //
868 // No need to initialize memory service.
869 // It is done in constructor of PiSmmCoreMemoryAllocationLib(),
870 // so that the library linked with PiSmmCore can use AllocatePool() in constructor.
871 //
872
873 SmramProfileInit ();
874
875 //
876 // Copy FullSmramRanges to SMRAM
877 //
878 mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;
879 mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
880 ASSERT (mFullSmramRanges != NULL);
881 CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
882
883 //
884 // Register all SMI Handlers required by the SMM Core
885 //
886 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
887 Status = SmiHandlerRegister (
888 mSmmCoreSmiHandlers[Index].Handler,
889 mSmmCoreSmiHandlers[Index].HandlerType,
890 &mSmmCoreSmiHandlers[Index].DispatchHandle
891 );
892 ASSERT_EFI_ERROR (Status);
893 }
894
895 mAcpiS3Enable = PcdGetBool (PcdAcpiS3Enable);
896 if (mAcpiS3Enable) {
897 //
898 // Register all S3 related SMI Handlers required by the SMM Core
899 //
900 for (Index = 0; mSmmCoreS3SmiHandlers[Index].HandlerType != NULL; Index++) {
901 Status = SmiHandlerRegister (
902 mSmmCoreS3SmiHandlers[Index].Handler,
903 mSmmCoreS3SmiHandlers[Index].HandlerType,
904 &mSmmCoreS3SmiHandlers[Index].DispatchHandle
905 );
906 ASSERT_EFI_ERROR (Status);
907 }
908 }
909
910 RegisterSmramProfileHandler ();
911 SmramProfileInstallProtocol ();
912
913 SmmCoreInstallLoadedImage ();
914
915 SmmCoreInitializeMemoryAttributesTable ();
916
917 SmmCoreInitializeSmiHandlerProfile ();
918
919 return EFI_SUCCESS;
920 }