]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
388 DEBUG_CODE_END ();
389
390 //
391 // Assert if the CPU I/O 2 Protocol is not installed
392 //
393 ASSERT_EFI_ERROR (Status);
394
395 //
396 // Display any drivers that were not dispatched because dependency expression
397 // evaluated to false if this is a debug build
398 //
399 DEBUG_CODE_BEGIN ();
400 SmmDisplayDiscoveredNotDispatched ();
401 DEBUG_CODE_END ();
402
403 //
404 // Not allowed to use gST or gBS after lock
405 //
406 gST = NULL;
407 gBS = NULL;
408
409 SmramProfileReadyToLock ();
410
411 return Status;
412 }
413
414 /**
415 Software SMI handler that is called when the EndOfDxe event is signalled.
416 This function installs the SMM EndOfDxe Protocol so SMM Drivers are informed that
417 platform code will invoke 3rd part code.
418
419 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
420 @param Context Points to an optional handler context which was specified when the handler was registered.
421 @param CommBuffer A pointer to a collection of data in memory that will
422 be conveyed from a non-SMM environment into an SMM environment.
423 @param CommBufferSize The size of the CommBuffer.
424
425 @return Status Code
426
427 **/
428 EFI_STATUS
429 EFIAPI
430 SmmEndOfDxeHandler (
431 IN EFI_HANDLE DispatchHandle,
432 IN CONST VOID *Context OPTIONAL,
433 IN OUT VOID *CommBuffer OPTIONAL,
434 IN OUT UINTN *CommBufferSize OPTIONAL
435 )
436 {
437 EFI_STATUS Status;
438 EFI_HANDLE SmmHandle;
439 EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;
440 EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;
441 EFI_HANDLE S3EntryHandle;
442
443 DEBUG ((DEBUG_INFO, "SmmEndOfDxeHandler\n"));
444
445 //
446 // Install SMM EndOfDxe protocol
447 //
448 SmmHandle = NULL;
449 Status = SmmInstallProtocolInterface (
450 &SmmHandle,
451 &gEfiSmmEndOfDxeProtocolGuid,
452 EFI_NATIVE_INTERFACE,
453 NULL
454 );
455
456 if (mAcpiS3Enable) {
457 //
458 // Locate SmmSxDispatch2 protocol.
459 //
460 Status = SmmLocateProtocol (
461 &gEfiSmmSxDispatch2ProtocolGuid,
462 NULL,
463 (VOID **)&SxDispatch
464 );
465 if (!EFI_ERROR (Status) && (SxDispatch != NULL)) {
466 //
467 // Register a S3 entry callback function to
468 // determine if it will be during S3 resume.
469 //
470 EntryRegisterContext.Type = SxS3;
471 EntryRegisterContext.Phase = SxEntry;
472 Status = SxDispatch->Register (
473 SxDispatch,
474 SmmS3EntryCallBack,
475 &EntryRegisterContext,
476 &S3EntryHandle
477 );
478 ASSERT_EFI_ERROR (Status);
479 }
480 }
481
482 return EFI_SUCCESS;
483 }
484
485 /**
486 Software SMI handler that is called when the S3SmmInitDone signal is triggered.
487 This function installs the SMM S3SmmInitDone Protocol so SMM Drivers are informed that
488 S3 SMM initialization has been done.
489
490 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
491 @param Context Points to an optional handler context which was specified when the handler was registered.
492 @param CommBuffer A pointer to a collection of data in memory that will
493 be conveyed from a non-SMM environment into an SMM environment.
494 @param CommBufferSize The size of the CommBuffer.
495
496 @return Status Code
497
498 **/
499 EFI_STATUS
500 EFIAPI
501 SmmS3SmmInitDoneHandler (
502 IN EFI_HANDLE DispatchHandle,
503 IN CONST VOID *Context OPTIONAL,
504 IN OUT VOID *CommBuffer OPTIONAL,
505 IN OUT UINTN *CommBufferSize OPTIONAL
506 )
507 {
508 EFI_STATUS Status;
509 EFI_HANDLE SmmHandle;
510
511 DEBUG ((DEBUG_INFO, "SmmS3SmmInitDoneHandler\n"));
512
513 if (!mDuringS3Resume) {
514 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));
515 return EFI_SUCCESS;
516 }
517
518 //
519 // Install SMM S3SmmInitDone protocol
520 //
521 SmmHandle = NULL;
522 Status = SmmInstallProtocolInterface (
523 &SmmHandle,
524 &gEdkiiS3SmmInitDoneGuid,
525 EFI_NATIVE_INTERFACE,
526 NULL
527 );
528 ASSERT_EFI_ERROR (Status);
529
530 //
531 // Uninstall the protocol here because the comsumer just hook the
532 // installation event.
533 //
534 Status = SmmUninstallProtocolInterface (
535 SmmHandle,
536 &gEdkiiS3SmmInitDoneGuid,
537 NULL
538 );
539 ASSERT_EFI_ERROR (Status);
540
541 return Status;
542 }
543
544 /**
545 Software SMI handler that is called when the EndOfS3Resume signal is triggered.
546 This function installs the SMM EndOfS3Resume Protocol so SMM Drivers are informed that
547 S3 resume has finished.
548
549 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
550 @param Context Points to an optional handler context which was specified when the handler was registered.
551 @param CommBuffer A pointer to a collection of data in memory that will
552 be conveyed from a non-SMM environment into an SMM environment.
553 @param CommBufferSize The size of the CommBuffer.
554
555 @return Status Code
556
557 **/
558 EFI_STATUS
559 EFIAPI
560 SmmEndOfS3ResumeHandler (
561 IN EFI_HANDLE DispatchHandle,
562 IN CONST VOID *Context OPTIONAL,
563 IN OUT VOID *CommBuffer OPTIONAL,
564 IN OUT UINTN *CommBufferSize OPTIONAL
565 )
566 {
567 EFI_STATUS Status;
568 EFI_HANDLE SmmHandle;
569
570 DEBUG ((DEBUG_INFO, "SmmEndOfS3ResumeHandler\n"));
571
572 if (!mDuringS3Resume) {
573 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));
574 return EFI_SUCCESS;
575 }
576
577 //
578 // Install SMM EndOfS3Resume protocol
579 //
580 SmmHandle = NULL;
581 Status = SmmInstallProtocolInterface (
582 &SmmHandle,
583 &gEdkiiEndOfS3ResumeGuid,
584 EFI_NATIVE_INTERFACE,
585 NULL
586 );
587 ASSERT_EFI_ERROR (Status);
588
589 //
590 // Uninstall the protocol here because the consumer just hook the
591 // installation event.
592 //
593 Status = SmmUninstallProtocolInterface (
594 SmmHandle,
595 &gEdkiiEndOfS3ResumeGuid,
596 NULL
597 );
598 ASSERT_EFI_ERROR (Status);
599
600 mDuringS3Resume = FALSE;
601 return Status;
602 }
603
604 /**
605 Determine if two buffers overlap in memory.
606
607 @param[in] Buff1 Pointer to first buffer
608 @param[in] Size1 Size of Buff1
609 @param[in] Buff2 Pointer to second buffer
610 @param[in] Size2 Size of Buff2
611
612 @retval TRUE Buffers overlap in memory.
613 @retval TRUE Math error. Prevents potential math over and underflows.
614 @retval FALSE Buffer doesn't overlap.
615
616 **/
617 BOOLEAN
618 InternalIsBufferOverlapped (
619 IN UINT8 *Buff1,
620 IN UINTN Size1,
621 IN UINT8 *Buff2,
622 IN UINTN Size2
623 )
624 {
625 UINTN End1;
626 UINTN End2;
627 BOOLEAN IsOverUnderflow1;
628 BOOLEAN IsOverUnderflow2;
629
630 // Check for over or underflow
631 IsOverUnderflow1 = EFI_ERROR (SafeUintnAdd ((UINTN)Buff1, Size1, &End1));
632 IsOverUnderflow2 = EFI_ERROR (SafeUintnAdd ((UINTN)Buff2, Size2, &End2));
633
634 if (IsOverUnderflow1 || IsOverUnderflow2) {
635 return TRUE;
636 }
637
638 //
639 // If buff1's end is less than the start of buff2, then it's ok.
640 // Also, if buff1's start is beyond buff2's end, then it's ok.
641 //
642 if ((End1 <= (UINTN)Buff2) || ((UINTN)Buff1 >= End2)) {
643 return FALSE;
644 }
645
646 return TRUE;
647 }
648
649 /**
650 The main entry point to SMM Foundation.
651
652 Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.
653
654 @param SmmEntryContext Processor information and functionality
655 needed by SMM Foundation.
656
657 **/
658 VOID
659 EFIAPI
660 SmmEntryPoint (
661 IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext
662 )
663 {
664 EFI_STATUS Status;
665 EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
666 BOOLEAN InLegacyBoot;
667 BOOLEAN IsOverlapped;
668 BOOLEAN IsOverUnderflow;
669 VOID *CommunicationBuffer;
670 UINTN BufferSize;
671
672 //
673 // Update SMST with contents of the SmmEntryContext structure
674 //
675 gSmmCoreSmst.SmmStartupThisAp = SmmEntryContext->SmmStartupThisAp;
676 gSmmCoreSmst.CurrentlyExecutingCpu = SmmEntryContext->CurrentlyExecutingCpu;
677 gSmmCoreSmst.NumberOfCpus = SmmEntryContext->NumberOfCpus;
678 gSmmCoreSmst.CpuSaveStateSize = SmmEntryContext->CpuSaveStateSize;
679 gSmmCoreSmst.CpuSaveState = SmmEntryContext->CpuSaveState;
680
681 //
682 // Call platform hook before Smm Dispatch
683 //
684 PlatformHookBeforeSmmDispatch ();
685
686 //
687 // Call memory management hook function
688 //
689 SmmEntryPointMemoryManagementHook ();
690
691 //
692 // If a legacy boot has occurred, then make sure gSmmCorePrivate is not accessed
693 //
694 InLegacyBoot = mInLegacyBoot;
695 if (!InLegacyBoot) {
696 //
697 // Mark the InSmm flag as TRUE, it will be used by SmmBase2 protocol
698 //
699 gSmmCorePrivate->InSmm = TRUE;
700
701 //
702 // Check to see if this is a Synchronous SMI sent through the SMM Communication
703 // Protocol or an Asynchronous SMI
704 //
705 CommunicationBuffer = gSmmCorePrivate->CommunicationBuffer;
706 BufferSize = gSmmCorePrivate->BufferSize;
707 if (CommunicationBuffer != NULL) {
708 //
709 // Synchronous SMI for SMM Core or request from Communicate protocol
710 //
711 IsOverlapped = InternalIsBufferOverlapped (
712 (UINT8 *)CommunicationBuffer,
713 BufferSize,
714 (UINT8 *)gSmmCorePrivate,
715 sizeof (*gSmmCorePrivate)
716 );
717 //
718 // Check for over or underflows
719 //
720 IsOverUnderflow = EFI_ERROR (SafeUintnSub (BufferSize, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data), &BufferSize));
721
722 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) ||
723 IsOverlapped || IsOverUnderflow)
724 {
725 //
726 // If CommunicationBuffer is not in valid address scope,
727 // or there is overlap between gSmmCorePrivate and CommunicationBuffer,
728 // or there is over or underflow,
729 // return EFI_INVALID_PARAMETER
730 //
731 gSmmCorePrivate->CommunicationBuffer = NULL;
732 gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
733 } else {
734 CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
735 // BufferSize was updated by the SafeUintnSub() call above.
736 Status = SmiManage (
737 &CommunicateHeader->HeaderGuid,
738 NULL,
739 CommunicateHeader->Data,
740 &BufferSize
741 );
742 //
743 // Update CommunicationBuffer, BufferSize and ReturnStatus
744 // Communicate service finished, reset the pointer to CommBuffer to NULL
745 //
746 gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
747 gSmmCorePrivate->CommunicationBuffer = NULL;
748 gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
749 }
750 }
751 }
752
753 //
754 // Process Asynchronous SMI sources
755 //
756 SmiManage (NULL, NULL, NULL, NULL);
757
758 //
759 // Call platform hook after Smm Dispatch
760 //
761 PlatformHookAfterSmmDispatch ();
762
763 //
764 // If a legacy boot has occurred, then make sure gSmmCorePrivate is not accessed
765 //
766 if (!InLegacyBoot) {
767 //
768 // Clear the InSmm flag as we are going to leave SMM
769 //
770 gSmmCorePrivate->InSmm = FALSE;
771 }
772 }
773
774 /**
775 Install LoadedImage protocol for SMM Core.
776 **/
777 VOID
778 SmmCoreInstallLoadedImage (
779 VOID
780 )
781 {
782 EFI_STATUS Status;
783 EFI_HANDLE Handle;
784
785 //
786 // Allocate a Loaded Image Protocol in EfiBootServicesData
787 //
788 Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&mSmmCoreLoadedImage);
789 ASSERT_EFI_ERROR (Status);
790
791 ZeroMem (mSmmCoreLoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));
792 //
793 // Fill in the remaining fields of the Loaded Image Protocol instance.
794 // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.
795 //
796 mSmmCoreLoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
797 mSmmCoreLoadedImage->ParentHandle = gSmmCorePrivate->SmmIplImageHandle;
798 mSmmCoreLoadedImage->SystemTable = gST;
799
800 mSmmCoreLoadedImage->ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
801 mSmmCoreLoadedImage->ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;
802 mSmmCoreLoadedImage->ImageCodeType = EfiRuntimeServicesCode;
803 mSmmCoreLoadedImage->ImageDataType = EfiRuntimeServicesData;
804
805 //
806 // Create a new image handle in the UEFI handle database for the SMM Driver
807 //
808 Handle = NULL;
809 Status = gBS->InstallMultipleProtocolInterfaces (
810 &Handle,
811 &gEfiLoadedImageProtocolGuid,
812 mSmmCoreLoadedImage,
813 NULL
814 );
815 ASSERT_EFI_ERROR (Status);
816
817 //
818 // Allocate a Loaded Image Protocol in SMM
819 //
820 Status = SmmAllocatePool (EfiRuntimeServicesData, sizeof (EFI_SMM_DRIVER_ENTRY), (VOID **)&mSmmCoreDriverEntry);
821 ASSERT_EFI_ERROR (Status);
822
823 ZeroMem (mSmmCoreDriverEntry, sizeof (EFI_SMM_DRIVER_ENTRY));
824 //
825 // Fill in the remaining fields of the Loaded Image Protocol instance.
826 //
827 mSmmCoreDriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;
828 mSmmCoreDriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
829 mSmmCoreDriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;
830 mSmmCoreDriverEntry->SmmLoadedImage.SystemTable = gST;
831
832 mSmmCoreDriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
833 mSmmCoreDriverEntry->SmmLoadedImage.ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;
834 mSmmCoreDriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;
835 mSmmCoreDriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;
836
837 mSmmCoreDriverEntry->ImageEntryPoint = gSmmCorePrivate->PiSmmCoreEntryPoint;
838 mSmmCoreDriverEntry->ImageBuffer = gSmmCorePrivate->PiSmmCoreImageBase;
839 mSmmCoreDriverEntry->NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)gSmmCorePrivate->PiSmmCoreImageSize);
840
841 //
842 // Create a new image handle in the SMM handle database for the SMM Driver
843 //
844 mSmmCoreDriverEntry->SmmImageHandle = NULL;
845 Status = SmmInstallProtocolInterface (
846 &mSmmCoreDriverEntry->SmmImageHandle,
847 &gEfiLoadedImageProtocolGuid,
848 EFI_NATIVE_INTERFACE,
849 &mSmmCoreDriverEntry->SmmLoadedImage
850 );
851 ASSERT_EFI_ERROR (Status);
852
853 return;
854 }
855
856 /**
857 The Entry Point for SMM Core
858
859 Install DXE Protocols and reload SMM Core into SMRAM and register SMM Core
860 EntryPoint on the SMI vector.
861
862 Note: This function is called for both DXE invocation and SMRAM invocation.
863
864 @param ImageHandle The firmware allocated handle for the EFI image.
865 @param SystemTable A pointer to the EFI System Table.
866
867 @retval EFI_SUCCESS The entry point is executed successfully.
868 @retval Other Some error occurred when executing this entry point.
869
870 **/
871 EFI_STATUS
872 EFIAPI
873 SmmMain (
874 IN EFI_HANDLE ImageHandle,
875 IN EFI_SYSTEM_TABLE *SystemTable
876 )
877 {
878 EFI_STATUS Status;
879 UINTN Index;
880
881 //
882 // Get SMM Core Private context passed in from SMM IPL in ImageHandle.
883 //
884 gSmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;
885
886 //
887 // Fill in SMRAM physical address for the SMM Services Table and the SMM Entry Point.
888 //
889 gSmmCorePrivate->Smst = &gSmmCoreSmst;
890 gSmmCorePrivate->SmmEntryPoint = SmmEntryPoint;
891
892 //
893 // No need to initialize memory service.
894 // It is done in constructor of PiSmmCoreMemoryAllocationLib(),
895 // so that the library linked with PiSmmCore can use AllocatePool() in constructor.
896 //
897
898 SmramProfileInit ();
899
900 //
901 // Copy FullSmramRanges to SMRAM
902 //
903 mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;
904 mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
905 ASSERT (mFullSmramRanges != NULL);
906 CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
907
908 //
909 // Register all SMI Handlers required by the SMM Core
910 //
911 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
912 Status = SmiHandlerRegister (
913 mSmmCoreSmiHandlers[Index].Handler,
914 mSmmCoreSmiHandlers[Index].HandlerType,
915 &mSmmCoreSmiHandlers[Index].DispatchHandle
916 );
917 ASSERT_EFI_ERROR (Status);
918 }
919
920 mAcpiS3Enable = PcdGetBool (PcdAcpiS3Enable);
921 if (mAcpiS3Enable) {
922 //
923 // Register all S3 related SMI Handlers required by the SMM Core
924 //
925 for (Index = 0; mSmmCoreS3SmiHandlers[Index].HandlerType != NULL; Index++) {
926 Status = SmiHandlerRegister (
927 mSmmCoreS3SmiHandlers[Index].Handler,
928 mSmmCoreS3SmiHandlers[Index].HandlerType,
929 &mSmmCoreS3SmiHandlers[Index].DispatchHandle
930 );
931 ASSERT_EFI_ERROR (Status);
932 }
933 }
934
935 RegisterSmramProfileHandler ();
936 SmramProfileInstallProtocol ();
937
938 SmmCoreInstallLoadedImage ();
939
940 SmmCoreInitializeMemoryAttributesTable ();
941
942 SmmCoreInitializeSmiHandlerProfile ();
943
944 return EFI_SUCCESS;
945 }