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