]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/StandaloneMmCore.c
StandaloneMmPkg: Fix ECC error 4002 and 9002 in StandaloneMmCore
[mirror_edk2.git] / StandaloneMmPkg / Core / StandaloneMmCore.c
1 /** @file
2 MM Core Main Entry Point
3
4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "StandaloneMmCore.h"
11
12 EFI_STATUS
13 MmCoreFfsFindMmDriver (
14 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
15 );
16
17 EFI_STATUS
18 MmDispatcher (
19 VOID
20 );
21
22 //
23 // Globals used to initialize the protocol
24 //
25 EFI_HANDLE mMmCpuHandle = NULL;
26
27 //
28 // Physical pointer to private structure shared between MM IPL and the MM Core
29 //
30 MM_CORE_PRIVATE_DATA *gMmCorePrivate;
31
32 //
33 // MM Core global variable for MM System Table. Only accessed as a physical structure in MMRAM.
34 //
35 EFI_MM_SYSTEM_TABLE gMmCoreMmst = {
36
37 // The table header for the MMST.
38 {
39 MM_MMST_SIGNATURE,
40 EFI_MM_SYSTEM_TABLE_REVISION,
41 sizeof (gMmCoreMmst.Hdr)
42 },
43 // MmFirmwareVendor
44 NULL,
45 // MmFirmwareRevision
46 0,
47 // MmInstallConfigurationTable
48 MmInstallConfigurationTable,
49 // I/O Service
50 {
51 {
52 (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5, // MmMemRead
53 (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5 // MmMemWrite
54 },
55 {
56 (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5, // MmIoRead
57 (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5 // MmIoWrite
58 }
59 },
60 // Runtime memory services
61 MmAllocatePool,
62 MmFreePool,
63 MmAllocatePages,
64 MmFreePages,
65 // MP service
66 NULL, // MmStartupThisAp
67 0, // CurrentlyExecutingCpu
68 0, // NumberOfCpus
69 NULL, // CpuSaveStateSize
70 NULL, // CpuSaveState
71 0, // NumberOfTableEntries
72 NULL, // MmConfigurationTable
73 MmInstallProtocolInterface,
74 MmUninstallProtocolInterface,
75 MmHandleProtocol,
76 MmRegisterProtocolNotify,
77 MmLocateHandle,
78 MmLocateProtocol,
79 MmiManage,
80 MmiHandlerRegister,
81 MmiHandlerUnRegister
82 };
83
84 //
85 // Table of MMI Handlers that are registered by the MM Core when it is initialized
86 //
87 MM_CORE_MMI_HANDLERS mMmCoreMmiHandlers[] = {
88 { MmReadyToLockHandler, &gEfiDxeMmReadyToLockProtocolGuid, NULL, TRUE },
89 { MmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, FALSE },
90 { MmExitBootServiceHandler,&gEfiEventExitBootServicesGuid, NULL, FALSE },
91 { MmReadyToBootHandler, &gEfiEventReadyToBootGuid, NULL, FALSE },
92 { NULL, NULL, NULL, FALSE },
93 };
94
95 EFI_SYSTEM_TABLE *mEfiSystemTable;
96 UINTN mMmramRangeCount;
97 EFI_MMRAM_DESCRIPTOR *mMmramRanges;
98
99 /**
100 Place holder function until all the MM System Table Service are available.
101
102 Note: This function is only used by MMRAM invocation. It is never used by DXE invocation.
103
104 @param Arg1 Undefined
105 @param Arg2 Undefined
106 @param Arg3 Undefined
107 @param Arg4 Undefined
108 @param Arg5 Undefined
109
110 @return EFI_NOT_AVAILABLE_YET
111
112 **/
113 EFI_STATUS
114 EFIAPI
115 MmEfiNotAvailableYetArg5 (
116 UINTN Arg1,
117 UINTN Arg2,
118 UINTN Arg3,
119 UINTN Arg4,
120 UINTN Arg5
121 )
122 {
123 //
124 // This function should never be executed. If it does, then the architectural protocols
125 // have not been designed correctly.
126 //
127 return EFI_NOT_AVAILABLE_YET;
128 }
129
130 /**
131 Software MMI handler that is called when a ExitBoot Service event is signaled.
132
133 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
134 @param Context Points to an optional handler context which was specified when the handler was registered.
135 @param CommBuffer A pointer to a collection of data in memory that will
136 be conveyed from a non-MM environment into an MM environment.
137 @param CommBufferSize The size of the CommBuffer.
138
139 @return Status Code
140
141 **/
142 EFI_STATUS
143 EFIAPI
144 MmExitBootServiceHandler (
145 IN EFI_HANDLE DispatchHandle,
146 IN CONST VOID *Context, OPTIONAL
147 IN OUT VOID *CommBuffer, OPTIONAL
148 IN OUT UINTN *CommBufferSize OPTIONAL
149 )
150 {
151 EFI_HANDLE MmHandle;
152 EFI_STATUS Status;
153 STATIC BOOLEAN mInExitBootServices = FALSE;
154
155 Status = EFI_SUCCESS;
156 if (!mInExitBootServices) {
157 MmHandle = NULL;
158 Status = MmInstallProtocolInterface (
159 &MmHandle,
160 &gEfiEventExitBootServicesGuid,
161 EFI_NATIVE_INTERFACE,
162 NULL
163 );
164 }
165 mInExitBootServices = TRUE;
166 return Status;
167 }
168
169 /**
170 Software MMI handler that is called when a ExitBoot Service event is signaled.
171
172 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
173 @param Context Points to an optional handler context which was specified when the handler was registered.
174 @param CommBuffer A pointer to a collection of data in memory that will
175 be conveyed from a non-MM environment into an MM environment.
176 @param CommBufferSize The size of the CommBuffer.
177
178 @return Status Code
179
180 **/
181 EFI_STATUS
182 EFIAPI
183 MmReadyToBootHandler (
184 IN EFI_HANDLE DispatchHandle,
185 IN CONST VOID *Context, OPTIONAL
186 IN OUT VOID *CommBuffer, OPTIONAL
187 IN OUT UINTN *CommBufferSize OPTIONAL
188 )
189 {
190 EFI_HANDLE MmHandle;
191 EFI_STATUS Status;
192 STATIC BOOLEAN mInReadyToBoot = FALSE;
193
194 Status = EFI_SUCCESS;
195 if (!mInReadyToBoot) {
196 MmHandle = NULL;
197 Status = MmInstallProtocolInterface (
198 &MmHandle,
199 &gEfiEventReadyToBootGuid,
200 EFI_NATIVE_INTERFACE,
201 NULL
202 );
203 }
204 mInReadyToBoot = TRUE;
205 return Status;
206 }
207
208 /**
209 Software MMI handler that is called when the DxeMmReadyToLock protocol is added
210 or if gEfiEventReadyToBootGuid is signaled. This function unregisters the
211 Software SMIs that are nor required after MMRAM is locked and installs the
212 MM Ready To Lock Protocol so MM Drivers are informed that MMRAM is about
213 to be locked.
214
215 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
216 @param Context Points to an optional handler context which was specified when the handler was registered.
217 @param CommBuffer A pointer to a collection of data in memory that will
218 be conveyed from a non-MM environment into an MM environment.
219 @param CommBufferSize The size of the CommBuffer.
220
221 @return Status Code
222
223 **/
224 EFI_STATUS
225 EFIAPI
226 MmReadyToLockHandler (
227 IN EFI_HANDLE DispatchHandle,
228 IN CONST VOID *Context, OPTIONAL
229 IN OUT VOID *CommBuffer, OPTIONAL
230 IN OUT UINTN *CommBufferSize OPTIONAL
231 )
232 {
233 EFI_STATUS Status;
234 UINTN Index;
235 EFI_HANDLE MmHandle;
236
237 DEBUG ((DEBUG_INFO, "MmReadyToLockHandler\n"));
238
239 //
240 // Unregister MMI Handlers that are no longer required after the MM driver dispatch is stopped
241 //
242 for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) {
243 if (mMmCoreMmiHandlers[Index].UnRegister) {
244 MmiHandlerUnRegister (mMmCoreMmiHandlers[Index].DispatchHandle);
245 }
246 }
247
248 //
249 // Install MM Ready to lock protocol
250 //
251 MmHandle = NULL;
252 Status = MmInstallProtocolInterface (
253 &MmHandle,
254 &gEfiMmReadyToLockProtocolGuid,
255 EFI_NATIVE_INTERFACE,
256 NULL
257 );
258
259 //
260 // Make sure MM CPU I/O 2 Protocol has been installed into the handle database
261 //
262 //Status = MmLocateProtocol (&EFI_MM_CPU_IO_PROTOCOL_GUID, NULL, &Interface);
263
264 //
265 // Print a message on a debug build if the MM CPU I/O 2 Protocol is not installed
266 //
267 //if (EFI_ERROR (Status)) {
268 //DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));
269 //}
270
271
272 //
273 // Assert if the CPU I/O 2 Protocol is not installed
274 //
275 //ASSERT_EFI_ERROR (Status);
276
277 //
278 // Display any drivers that were not dispatched because dependency expression
279 // evaluated to false if this is a debug build
280 //
281 //MmDisplayDiscoveredNotDispatched ();
282
283 return Status;
284 }
285
286 /**
287 Software MMI handler that is called when the EndOfDxe event is signaled.
288 This function installs the MM EndOfDxe Protocol so MM Drivers are informed that
289 platform code will invoke 3rd part code.
290
291 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
292 @param Context Points to an optional handler context which was specified when the handler was registered.
293 @param CommBuffer A pointer to a collection of data in memory that will
294 be conveyed from a non-MM environment into an MM environment.
295 @param CommBufferSize The size of the CommBuffer.
296
297 @return Status Code
298
299 **/
300 EFI_STATUS
301 EFIAPI
302 MmEndOfDxeHandler (
303 IN EFI_HANDLE DispatchHandle,
304 IN CONST VOID *Context, OPTIONAL
305 IN OUT VOID *CommBuffer, OPTIONAL
306 IN OUT UINTN *CommBufferSize OPTIONAL
307 )
308 {
309 EFI_STATUS Status;
310 EFI_HANDLE MmHandle;
311
312 DEBUG ((DEBUG_INFO, "MmEndOfDxeHandler\n"));
313 //
314 // Install MM EndOfDxe protocol
315 //
316 MmHandle = NULL;
317 Status = MmInstallProtocolInterface (
318 &MmHandle,
319 &gEfiMmEndOfDxeProtocolGuid,
320 EFI_NATIVE_INTERFACE,
321 NULL
322 );
323 return Status;
324 }
325
326
327
328 /**
329 The main entry point to MM Foundation.
330
331 Note: This function is only used by MMRAM invocation. It is never used by DXE invocation.
332
333 @param MmEntryContext Processor information and functionality
334 needed by MM Foundation.
335
336 **/
337 VOID
338 EFIAPI
339 MmEntryPoint (
340 IN CONST EFI_MM_ENTRY_CONTEXT *MmEntryContext
341 )
342 {
343 EFI_STATUS Status;
344 EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
345
346 DEBUG ((DEBUG_INFO, "MmEntryPoint ...\n"));
347
348 //
349 // Update MMST using the context
350 //
351 CopyMem (&gMmCoreMmst.MmStartupThisAp, MmEntryContext, sizeof (EFI_MM_ENTRY_CONTEXT));
352
353 //
354 // Call platform hook before Mm Dispatch
355 //
356 //PlatformHookBeforeMmDispatch ();
357
358 //
359 // If a legacy boot has occurred, then make sure gMmCorePrivate is not accessed
360 //
361
362 //
363 // TBD: Mark the InMm flag as TRUE
364 //
365 gMmCorePrivate->InMm = TRUE;
366
367 //
368 // Check to see if this is a Synchronous MMI sent through the MM Communication
369 // Protocol or an Asynchronous MMI
370 //
371 if (gMmCorePrivate->CommunicationBuffer != 0) {
372 //
373 // Synchronous MMI for MM Core or request from Communicate protocol
374 //
375 if (!MmIsBufferOutsideMmValid ((UINTN)gMmCorePrivate->CommunicationBuffer, gMmCorePrivate->BufferSize)) {
376 //
377 // If CommunicationBuffer is not in valid address scope, return EFI_INVALID_PARAMETER
378 //
379 gMmCorePrivate->CommunicationBuffer = 0;
380 gMmCorePrivate->ReturnStatus = EFI_INVALID_PARAMETER;
381 } else {
382 CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)gMmCorePrivate->CommunicationBuffer;
383 gMmCorePrivate->BufferSize -= OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);
384 Status = MmiManage (
385 &CommunicateHeader->HeaderGuid,
386 NULL,
387 CommunicateHeader->Data,
388 (UINTN *)&gMmCorePrivate->BufferSize
389 );
390 //
391 // Update CommunicationBuffer, BufferSize and ReturnStatus
392 // Communicate service finished, reset the pointer to CommBuffer to NULL
393 //
394 gMmCorePrivate->BufferSize += OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);
395 gMmCorePrivate->CommunicationBuffer = 0;
396 gMmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
397 }
398 }
399
400 //
401 // Process Asynchronous MMI sources
402 //
403 MmiManage (NULL, NULL, NULL, NULL);
404
405 //
406 // TBD: Do not use private data structure ?
407 //
408
409 //
410 // Clear the InMm flag as we are going to leave MM
411 //
412 gMmCorePrivate->InMm = FALSE;
413
414 DEBUG ((DEBUG_INFO, "MmEntryPoint Done\n"));
415 }
416
417 /** Register the MM Entry Point provided by the MM Core with the
418 MM Configuration protocol.
419
420 @param [in] Protocol Pointer to the protocol.
421 @param [in] Interface Pointer to the MM Configuration protocol.
422 @param [in] Handle Handle.
423
424 @retval EFI_SUCCESS Success.
425 **/
426 EFI_STATUS
427 EFIAPI
428 MmConfigurationMmNotify (
429 IN CONST EFI_GUID *Protocol,
430 IN VOID *Interface,
431 IN EFI_HANDLE Handle
432 )
433 {
434 EFI_STATUS Status;
435 EFI_MM_CONFIGURATION_PROTOCOL *MmConfiguration;
436
437 DEBUG ((DEBUG_INFO, "MmConfigurationMmNotify(%g) - %x\n", Protocol, Interface));
438
439 MmConfiguration = Interface;
440
441 //
442 // Register the MM Entry Point provided by the MM Core with the MM COnfiguration protocol
443 //
444 Status = MmConfiguration->RegisterMmEntry (MmConfiguration, (EFI_MM_ENTRY_POINT)(UINTN)gMmCorePrivate->MmEntryPoint);
445 ASSERT_EFI_ERROR (Status);
446
447 //
448 // Set flag to indicate that the MM Entry Point has been registered which
449 // means that MMIs are now fully operational.
450 //
451 gMmCorePrivate->MmEntryPointRegistered = TRUE;
452
453 //
454 // Print debug message showing MM Core entry point address.
455 //
456 DEBUG ((DEBUG_INFO, "MM Core registered MM Entry Point address %p\n", (VOID *)(UINTN)gMmCorePrivate->MmEntryPoint));
457 return EFI_SUCCESS;
458 }
459
460 /** Returns the HOB list size.
461
462 @param [in] HobStart Pointer to the start of the HOB list.
463
464 @retval Size of the HOB list.
465 **/
466 UINTN
467 GetHobListSize (
468 IN VOID *HobStart
469 )
470 {
471 EFI_PEI_HOB_POINTERS Hob;
472
473 ASSERT (HobStart != NULL);
474
475 Hob.Raw = (UINT8 *) HobStart;
476 while (!END_OF_HOB_LIST (Hob)) {
477 Hob.Raw = GET_NEXT_HOB (Hob);
478 }
479 //
480 // Need plus END_OF_HOB_LIST
481 //
482 return (UINTN)Hob.Raw - (UINTN)HobStart + sizeof (EFI_HOB_GENERIC_HEADER);
483 }
484
485 /**
486 The Entry Point for MM Core
487
488 Install DXE Protocols and reload MM Core into MMRAM and register MM Core
489 EntryPoint on the MMI vector.
490
491 Note: This function is called for both DXE invocation and MMRAM invocation.
492
493 @param HobStart Pointer to the start of the HOB list.
494
495 @retval EFI_SUCCESS Success.
496 @retval EFI_UNSUPPORTED Unsupported operation.
497 **/
498 EFI_STATUS
499 EFIAPI
500 StandaloneMmMain (
501 IN VOID *HobStart
502 )
503 {
504 EFI_STATUS Status;
505 UINTN Index;
506 VOID *MmHobStart;
507 UINTN HobSize;
508 VOID *Registration;
509 EFI_HOB_GUID_TYPE *GuidHob;
510 MM_CORE_DATA_HOB_DATA *DataInHob;
511 EFI_HOB_GUID_TYPE *MmramRangesHob;
512 EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData;
513 EFI_MMRAM_DESCRIPTOR *MmramRanges;
514 UINT32 MmramRangeCount;
515 EFI_HOB_FIRMWARE_VOLUME *BfvHob;
516
517 ProcessLibraryConstructorList (HobStart, &gMmCoreMmst);
518
519 DEBUG ((DEBUG_INFO, "MmMain - 0x%x\n", HobStart));
520
521 //
522 // Determine if the caller has passed a reference to a MM_CORE_PRIVATE_DATA
523 // structure in the Hoblist. This choice will govern how boot information is
524 // extracted later.
525 //
526 GuidHob = GetNextGuidHob (&gMmCoreDataHobGuid, HobStart);
527 if (GuidHob == NULL) {
528 //
529 // Allocate and zero memory for a MM_CORE_PRIVATE_DATA table and then
530 // initialise it
531 //
532 gMmCorePrivate = (MM_CORE_PRIVATE_DATA *) AllocateRuntimePages(EFI_SIZE_TO_PAGES(sizeof (MM_CORE_PRIVATE_DATA)));
533 SetMem ((VOID *)(UINTN)gMmCorePrivate, sizeof (MM_CORE_PRIVATE_DATA), 0);
534 gMmCorePrivate->Signature = MM_CORE_PRIVATE_DATA_SIGNATURE;
535 gMmCorePrivate->MmEntryPointRegistered = FALSE;
536 gMmCorePrivate->InMm = FALSE;
537 gMmCorePrivate->ReturnStatus = EFI_SUCCESS;
538
539 //
540 // Extract the MMRAM ranges from the MMRAM descriptor HOB
541 //
542 MmramRangesHob = GetNextGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, HobStart);
543 if (MmramRangesHob == NULL)
544 return EFI_UNSUPPORTED;
545
546 MmramRangesHobData = GET_GUID_HOB_DATA (MmramRangesHob);
547 ASSERT (MmramRangesHobData != NULL);
548 MmramRanges = MmramRangesHobData->Descriptor;
549 MmramRangeCount = MmramRangesHobData->NumberOfMmReservedRegions;
550 ASSERT (MmramRanges);
551 ASSERT (MmramRangeCount);
552
553 //
554 // Copy the MMRAM ranges into MM_CORE_PRIVATE_DATA table just in case any
555 // code relies on them being present there
556 //
557 gMmCorePrivate->MmramRangeCount = MmramRangeCount;
558 gMmCorePrivate->MmramRanges =
559 (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (MmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
560 ASSERT (gMmCorePrivate->MmramRanges != 0);
561 CopyMem (
562 (VOID *)(UINTN)gMmCorePrivate->MmramRanges,
563 MmramRanges,
564 MmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR)
565 );
566 } else {
567 DataInHob = GET_GUID_HOB_DATA (GuidHob);
568 gMmCorePrivate = (MM_CORE_PRIVATE_DATA *)(UINTN)DataInHob->Address;
569 MmramRanges = (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRanges;
570 MmramRangeCount = gMmCorePrivate->MmramRangeCount;
571 }
572
573 //
574 // Print the MMRAM ranges passed by the caller
575 //
576 DEBUG ((DEBUG_INFO, "MmramRangeCount - 0x%x\n", MmramRangeCount));
577 for (Index = 0; Index < MmramRangeCount; Index++) {
578 DEBUG ((DEBUG_INFO, "MmramRanges[%d]: 0x%016lx - 0x%lx\n", Index,
579 MmramRanges[Index].CpuStart,
580 MmramRanges[Index].PhysicalSize));
581 }
582
583 //
584 // Copy the MMRAM ranges into private MMRAM
585 //
586 mMmramRangeCount = MmramRangeCount;
587 DEBUG ((DEBUG_INFO, "mMmramRangeCount - 0x%x\n", mMmramRangeCount));
588 mMmramRanges = AllocatePool (mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
589 DEBUG ((DEBUG_INFO, "mMmramRanges - 0x%x\n", mMmramRanges));
590 ASSERT (mMmramRanges != NULL);
591 CopyMem (mMmramRanges, (VOID *)(UINTN)MmramRanges, mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
592
593 //
594 // Get Boot Firmware Volume address from the BFV Hob
595 //
596 BfvHob = GetFirstHob (EFI_HOB_TYPE_FV);
597 if (BfvHob != NULL) {
598 DEBUG ((DEBUG_INFO, "BFV address - 0x%x\n", BfvHob->BaseAddress));
599 DEBUG ((DEBUG_INFO, "BFV size - 0x%x\n", BfvHob->Length));
600 gMmCorePrivate->StandaloneBfvAddress = BfvHob->BaseAddress;
601 }
602
603 gMmCorePrivate->Mmst = (EFI_PHYSICAL_ADDRESS)(UINTN)&gMmCoreMmst;
604 gMmCorePrivate->MmEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)MmEntryPoint;
605
606 //
607 // No need to initialize memory service.
608 // It is done in the constructor of StandaloneMmCoreMemoryAllocationLib(),
609 // so that the library linked with StandaloneMmCore can use AllocatePool() in
610 // the constructor.
611
612 DEBUG ((DEBUG_INFO, "MmInstallConfigurationTable For HobList\n"));
613 //
614 // Install HobList
615 //
616 HobSize = GetHobListSize (HobStart);
617 DEBUG ((DEBUG_INFO, "HobSize - 0x%x\n", HobSize));
618 MmHobStart = AllocatePool (HobSize);
619 DEBUG ((DEBUG_INFO, "MmHobStart - 0x%x\n", MmHobStart));
620 ASSERT (MmHobStart != NULL);
621 CopyMem (MmHobStart, HobStart, HobSize);
622 Status = MmInstallConfigurationTable (&gMmCoreMmst, &gEfiHobListGuid, MmHobStart, HobSize);
623 ASSERT_EFI_ERROR (Status);
624
625 //
626 // Register notification for EFI_MM_CONFIGURATION_PROTOCOL registration and
627 // use it to register the MM Foundation entrypoint
628 //
629 DEBUG ((DEBUG_INFO, "MmRegisterProtocolNotify - MmConfigurationMmProtocol\n"));
630 Status = MmRegisterProtocolNotify (
631 &gEfiMmConfigurationProtocolGuid,
632 MmConfigurationMmNotify,
633 &Registration
634 );
635 ASSERT_EFI_ERROR (Status);
636
637 //
638 // Dispatch standalone BFV
639 //
640 DEBUG ((DEBUG_INFO, "Mm Dispatch StandaloneBfvAddress - 0x%08x\n", gMmCorePrivate->StandaloneBfvAddress));
641 if (gMmCorePrivate->StandaloneBfvAddress != 0) {
642 MmCoreFfsFindMmDriver ((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)gMmCorePrivate->StandaloneBfvAddress);
643 MmDispatcher ();
644 }
645
646 //
647 // Register all handlers in the core table
648 //
649 for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) {
650 Status = MmiHandlerRegister (
651 mMmCoreMmiHandlers[Index].Handler,
652 mMmCoreMmiHandlers[Index].HandlerType,
653 &mMmCoreMmiHandlers[Index].DispatchHandle
654 );
655 DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status));
656 }
657
658 DEBUG ((DEBUG_INFO, "MmMain Done!\n"));
659
660 return EFI_SUCCESS;
661 }