]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
MdeModulePkg: remove PE/COFF header workaround for ELILO on IPF
[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 //
648 // Update SMST with contents of the SmmEntryContext structure
649 //
650 gSmmCoreSmst.SmmStartupThisAp = SmmEntryContext->SmmStartupThisAp;
651 gSmmCoreSmst.CurrentlyExecutingCpu = SmmEntryContext->CurrentlyExecutingCpu;
652 gSmmCoreSmst.NumberOfCpus = SmmEntryContext->NumberOfCpus;
653 gSmmCoreSmst.CpuSaveStateSize = SmmEntryContext->CpuSaveStateSize;
654 gSmmCoreSmst.CpuSaveState = SmmEntryContext->CpuSaveState;
655
656 //
657 // Call platform hook before Smm Dispatch
658 //
659 PlatformHookBeforeSmmDispatch ();
660
661 //
662 // Call memory management hook function
663 //
664 SmmEntryPointMemoryManagementHook ();
665
666 //
667 // If a legacy boot has occured, then make sure gSmmCorePrivate is not accessed
668 //
669 InLegacyBoot = mInLegacyBoot;
670 if (!InLegacyBoot) {
671 //
672 // Mark the InSmm flag as TRUE, it will be used by SmmBase2 protocol
673 //
674 gSmmCorePrivate->InSmm = TRUE;
675
676 //
677 // Check to see if this is a Synchronous SMI sent through the SMM Communication
678 // Protocol or an Asynchronous SMI
679 //
680 CommunicationBuffer = gSmmCorePrivate->CommunicationBuffer;
681 BufferSize = gSmmCorePrivate->BufferSize;
682 if (CommunicationBuffer != NULL) {
683 //
684 // Synchronous SMI for SMM Core or request from Communicate protocol
685 //
686 IsOverlapped = InternalIsBufferOverlapped (
687 (UINT8 *) CommunicationBuffer,
688 BufferSize,
689 (UINT8 *) gSmmCorePrivate,
690 sizeof (*gSmmCorePrivate)
691 );
692 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) || IsOverlapped) {
693 //
694 // If CommunicationBuffer is not in valid address scope,
695 // or there is overlap between gSmmCorePrivate and CommunicationBuffer,
696 // return EFI_INVALID_PARAMETER
697 //
698 gSmmCorePrivate->CommunicationBuffer = NULL;
699 gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
700 } else {
701 CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
702 BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
703 Status = SmiManage (
704 &CommunicateHeader->HeaderGuid,
705 NULL,
706 CommunicateHeader->Data,
707 &BufferSize
708 );
709 //
710 // Update CommunicationBuffer, BufferSize and ReturnStatus
711 // Communicate service finished, reset the pointer to CommBuffer to NULL
712 //
713 gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
714 gSmmCorePrivate->CommunicationBuffer = NULL;
715 gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
716 }
717 }
718 }
719
720 //
721 // Process Asynchronous SMI sources
722 //
723 SmiManage (NULL, NULL, NULL, NULL);
724
725 //
726 // Call platform hook after Smm Dispatch
727 //
728 PlatformHookAfterSmmDispatch ();
729
730 //
731 // If a legacy boot has occured, then make sure gSmmCorePrivate is not accessed
732 //
733 if (!InLegacyBoot) {
734 //
735 // Clear the InSmm flag as we are going to leave SMM
736 //
737 gSmmCorePrivate->InSmm = FALSE;
738 }
739 }
740
741 /**
742 Install LoadedImage protocol for SMM Core.
743 **/
744 VOID
745 SmmCoreInstallLoadedImage (
746 VOID
747 )
748 {
749 EFI_STATUS Status;
750 EFI_HANDLE Handle;
751
752 //
753 // Allocate a Loaded Image Protocol in EfiBootServicesData
754 //
755 Status = gBS->AllocatePool (EfiBootServicesData, sizeof(EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&mSmmCoreLoadedImage);
756 ASSERT_EFI_ERROR (Status);
757
758 ZeroMem (mSmmCoreLoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));
759 //
760 // Fill in the remaining fields of the Loaded Image Protocol instance.
761 // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.
762 //
763 mSmmCoreLoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
764 mSmmCoreLoadedImage->ParentHandle = gSmmCorePrivate->SmmIplImageHandle;
765 mSmmCoreLoadedImage->SystemTable = gST;
766
767 mSmmCoreLoadedImage->ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
768 mSmmCoreLoadedImage->ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;
769 mSmmCoreLoadedImage->ImageCodeType = EfiRuntimeServicesCode;
770 mSmmCoreLoadedImage->ImageDataType = EfiRuntimeServicesData;
771
772 //
773 // Create a new image handle in the UEFI handle database for the SMM Driver
774 //
775 Handle = NULL;
776 Status = gBS->InstallMultipleProtocolInterfaces (
777 &Handle,
778 &gEfiLoadedImageProtocolGuid, mSmmCoreLoadedImage,
779 NULL
780 );
781 ASSERT_EFI_ERROR (Status);
782
783 //
784 // Allocate a Loaded Image Protocol in SMM
785 //
786 Status = SmmAllocatePool (EfiRuntimeServicesData, sizeof(EFI_SMM_DRIVER_ENTRY), (VOID **)&mSmmCoreDriverEntry);
787 ASSERT_EFI_ERROR(Status);
788
789 ZeroMem (mSmmCoreDriverEntry, sizeof(EFI_SMM_DRIVER_ENTRY));
790 //
791 // Fill in the remaining fields of the Loaded Image Protocol instance.
792 //
793 mSmmCoreDriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;
794 mSmmCoreDriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
795 mSmmCoreDriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;
796 mSmmCoreDriverEntry->SmmLoadedImage.SystemTable = gST;
797
798 mSmmCoreDriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
799 mSmmCoreDriverEntry->SmmLoadedImage.ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;
800 mSmmCoreDriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;
801 mSmmCoreDriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;
802
803 mSmmCoreDriverEntry->ImageEntryPoint = gSmmCorePrivate->PiSmmCoreEntryPoint;
804 mSmmCoreDriverEntry->ImageBuffer = gSmmCorePrivate->PiSmmCoreImageBase;
805 mSmmCoreDriverEntry->NumberOfPage = EFI_SIZE_TO_PAGES((UINTN)gSmmCorePrivate->PiSmmCoreImageSize);
806
807 //
808 // Create a new image handle in the SMM handle database for the SMM Driver
809 //
810 mSmmCoreDriverEntry->SmmImageHandle = NULL;
811 Status = SmmInstallProtocolInterface (
812 &mSmmCoreDriverEntry->SmmImageHandle,
813 &gEfiLoadedImageProtocolGuid,
814 EFI_NATIVE_INTERFACE,
815 &mSmmCoreDriverEntry->SmmLoadedImage
816 );
817 ASSERT_EFI_ERROR(Status);
818
819 return ;
820 }
821
822 /**
823 The Entry Point for SMM Core
824
825 Install DXE Protocols and reload SMM Core into SMRAM and register SMM Core
826 EntryPoint on the SMI vector.
827
828 Note: This function is called for both DXE invocation and SMRAM invocation.
829
830 @param ImageHandle The firmware allocated handle for the EFI image.
831 @param SystemTable A pointer to the EFI System Table.
832
833 @retval EFI_SUCCESS The entry point is executed successfully.
834 @retval Other Some error occurred when executing this entry point.
835
836 **/
837 EFI_STATUS
838 EFIAPI
839 SmmMain (
840 IN EFI_HANDLE ImageHandle,
841 IN EFI_SYSTEM_TABLE *SystemTable
842 )
843 {
844 EFI_STATUS Status;
845 UINTN Index;
846
847 //
848 // Get SMM Core Private context passed in from SMM IPL in ImageHandle.
849 //
850 gSmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;
851
852 //
853 // Fill in SMRAM physical address for the SMM Services Table and the SMM Entry Point.
854 //
855 gSmmCorePrivate->Smst = &gSmmCoreSmst;
856 gSmmCorePrivate->SmmEntryPoint = SmmEntryPoint;
857
858 //
859 // No need to initialize memory service.
860 // It is done in constructor of PiSmmCoreMemoryAllocationLib(),
861 // so that the library linked with PiSmmCore can use AllocatePool() in constuctor.
862 //
863
864 SmramProfileInit ();
865
866 //
867 // Copy FullSmramRanges to SMRAM
868 //
869 mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;
870 mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
871 ASSERT (mFullSmramRanges != NULL);
872 CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
873
874 //
875 // Register all SMI Handlers required by the SMM Core
876 //
877 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
878 Status = SmiHandlerRegister (
879 mSmmCoreSmiHandlers[Index].Handler,
880 mSmmCoreSmiHandlers[Index].HandlerType,
881 &mSmmCoreSmiHandlers[Index].DispatchHandle
882 );
883 ASSERT_EFI_ERROR (Status);
884 }
885
886 RegisterSmramProfileHandler ();
887 SmramProfileInstallProtocol ();
888
889 SmmCoreInstallLoadedImage ();
890
891 SmmCoreInitializeMemoryAttributesTable ();
892
893 SmmCoreInitializeSmiHandlerProfile ();
894
895 return EFI_SUCCESS;
896 }