]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/StandaloneMmCore.c
StandaloneMmPkg: Fix ECC error 5007 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 EFI_STATUS
418 EFIAPI
419 MmConfigurationMmNotify (
420 IN CONST EFI_GUID *Protocol,
421 IN VOID *Interface,
422 IN EFI_HANDLE Handle
423 )
424 {
425 EFI_STATUS Status;
426 EFI_MM_CONFIGURATION_PROTOCOL *MmConfiguration;
427
428 DEBUG ((DEBUG_INFO, "MmConfigurationMmNotify(%g) - %x\n", Protocol, Interface));
429
430 MmConfiguration = Interface;
431
432 //
433 // Register the MM Entry Point provided by the MM Core with the MM COnfiguration protocol
434 //
435 Status = MmConfiguration->RegisterMmEntry (MmConfiguration, (EFI_MM_ENTRY_POINT)(UINTN)gMmCorePrivate->MmEntryPoint);
436 ASSERT_EFI_ERROR (Status);
437
438 //
439 // Set flag to indicate that the MM Entry Point has been registered which
440 // means that MMIs are now fully operational.
441 //
442 gMmCorePrivate->MmEntryPointRegistered = TRUE;
443
444 //
445 // Print debug message showing MM Core entry point address.
446 //
447 DEBUG ((DEBUG_INFO, "MM Core registered MM Entry Point address %p\n", (VOID *)(UINTN)gMmCorePrivate->MmEntryPoint));
448 return EFI_SUCCESS;
449 }
450
451 UINTN
452 GetHobListSize (
453 IN VOID *HobStart
454 )
455 {
456 EFI_PEI_HOB_POINTERS Hob;
457
458 ASSERT (HobStart != NULL);
459
460 Hob.Raw = (UINT8 *) HobStart;
461 while (!END_OF_HOB_LIST (Hob)) {
462 Hob.Raw = GET_NEXT_HOB (Hob);
463 }
464 //
465 // Need plus END_OF_HOB_LIST
466 //
467 return (UINTN)Hob.Raw - (UINTN)HobStart + sizeof (EFI_HOB_GENERIC_HEADER);
468 }
469
470 /**
471 The Entry Point for MM Core
472
473 Install DXE Protocols and reload MM Core into MMRAM and register MM Core
474 EntryPoint on the MMI vector.
475
476 Note: This function is called for both DXE invocation and MMRAM invocation.
477
478 @param ImageHandle The firmware allocated handle for the EFI image.
479 @param SystemTable A pointer to the EFI System Table.
480
481 @retval EFI_SUCCESS The entry point is executed successfully.
482 @retval Other Some error occurred when executing this entry point.
483
484 **/
485 EFI_STATUS
486 EFIAPI
487 StandaloneMmMain (
488 IN VOID *HobStart
489 )
490 {
491 EFI_STATUS Status;
492 UINTN Index;
493 VOID *MmHobStart;
494 UINTN HobSize;
495 VOID *Registration;
496 EFI_HOB_GUID_TYPE *GuidHob;
497 MM_CORE_DATA_HOB_DATA *DataInHob;
498 EFI_HOB_GUID_TYPE *MmramRangesHob;
499 EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData;
500 EFI_MMRAM_DESCRIPTOR *MmramRanges;
501 UINT32 MmramRangeCount;
502 EFI_HOB_FIRMWARE_VOLUME *BfvHob;
503
504 ProcessLibraryConstructorList (HobStart, &gMmCoreMmst);
505
506 DEBUG ((DEBUG_INFO, "MmMain - 0x%x\n", HobStart));
507
508 //
509 // Determine if the caller has passed a reference to a MM_CORE_PRIVATE_DATA
510 // structure in the Hoblist. This choice will govern how boot information is
511 // extracted later.
512 //
513 GuidHob = GetNextGuidHob (&gMmCoreDataHobGuid, HobStart);
514 if (GuidHob == NULL) {
515 //
516 // Allocate and zero memory for a MM_CORE_PRIVATE_DATA table and then
517 // initialise it
518 //
519 gMmCorePrivate = (MM_CORE_PRIVATE_DATA *) AllocateRuntimePages(EFI_SIZE_TO_PAGES(sizeof (MM_CORE_PRIVATE_DATA)));
520 SetMem ((VOID *)(UINTN)gMmCorePrivate, sizeof (MM_CORE_PRIVATE_DATA), 0);
521 gMmCorePrivate->Signature = MM_CORE_PRIVATE_DATA_SIGNATURE;
522 gMmCorePrivate->MmEntryPointRegistered = FALSE;
523 gMmCorePrivate->InMm = FALSE;
524 gMmCorePrivate->ReturnStatus = EFI_SUCCESS;
525
526 //
527 // Extract the MMRAM ranges from the MMRAM descriptor HOB
528 //
529 MmramRangesHob = GetNextGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, HobStart);
530 if (MmramRangesHob == NULL)
531 return EFI_UNSUPPORTED;
532
533 MmramRangesHobData = GET_GUID_HOB_DATA (MmramRangesHob);
534 ASSERT (MmramRangesHobData != NULL);
535 MmramRanges = MmramRangesHobData->Descriptor;
536 MmramRangeCount = MmramRangesHobData->NumberOfMmReservedRegions;
537 ASSERT (MmramRanges);
538 ASSERT (MmramRangeCount);
539
540 //
541 // Copy the MMRAM ranges into MM_CORE_PRIVATE_DATA table just in case any
542 // code relies on them being present there
543 //
544 gMmCorePrivate->MmramRangeCount = MmramRangeCount;
545 gMmCorePrivate->MmramRanges =
546 (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (MmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
547 ASSERT (gMmCorePrivate->MmramRanges != 0);
548 CopyMem (
549 (VOID *)(UINTN)gMmCorePrivate->MmramRanges,
550 MmramRanges,
551 MmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR)
552 );
553 } else {
554 DataInHob = GET_GUID_HOB_DATA (GuidHob);
555 gMmCorePrivate = (MM_CORE_PRIVATE_DATA *)(UINTN)DataInHob->Address;
556 MmramRanges = (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRanges;
557 MmramRangeCount = gMmCorePrivate->MmramRangeCount;
558 }
559
560 //
561 // Print the MMRAM ranges passed by the caller
562 //
563 DEBUG ((DEBUG_INFO, "MmramRangeCount - 0x%x\n", MmramRangeCount));
564 for (Index = 0; Index < MmramRangeCount; Index++) {
565 DEBUG ((DEBUG_INFO, "MmramRanges[%d]: 0x%016lx - 0x%lx\n", Index,
566 MmramRanges[Index].CpuStart,
567 MmramRanges[Index].PhysicalSize));
568 }
569
570 //
571 // Copy the MMRAM ranges into private MMRAM
572 //
573 mMmramRangeCount = MmramRangeCount;
574 DEBUG ((DEBUG_INFO, "mMmramRangeCount - 0x%x\n", mMmramRangeCount));
575 mMmramRanges = AllocatePool (mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
576 DEBUG ((DEBUG_INFO, "mMmramRanges - 0x%x\n", mMmramRanges));
577 ASSERT (mMmramRanges != NULL);
578 CopyMem (mMmramRanges, (VOID *)(UINTN)MmramRanges, mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
579
580 //
581 // Get Boot Firmware Volume address from the BFV Hob
582 //
583 BfvHob = GetFirstHob (EFI_HOB_TYPE_FV);
584 if (BfvHob != NULL) {
585 DEBUG ((DEBUG_INFO, "BFV address - 0x%x\n", BfvHob->BaseAddress));
586 DEBUG ((DEBUG_INFO, "BFV size - 0x%x\n", BfvHob->Length));
587 gMmCorePrivate->StandaloneBfvAddress = BfvHob->BaseAddress;
588 }
589
590 gMmCorePrivate->Mmst = (EFI_PHYSICAL_ADDRESS)(UINTN)&gMmCoreMmst;
591 gMmCorePrivate->MmEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)MmEntryPoint;
592
593 //
594 // No need to initialize memory service.
595 // It is done in the constructor of StandaloneMmCoreMemoryAllocationLib(),
596 // so that the library linked with StandaloneMmCore can use AllocatePool() in
597 // the constructor.
598
599 DEBUG ((DEBUG_INFO, "MmInstallConfigurationTable For HobList\n"));
600 //
601 // Install HobList
602 //
603 HobSize = GetHobListSize (HobStart);
604 DEBUG ((DEBUG_INFO, "HobSize - 0x%x\n", HobSize));
605 MmHobStart = AllocatePool (HobSize);
606 DEBUG ((DEBUG_INFO, "MmHobStart - 0x%x\n", MmHobStart));
607 ASSERT (MmHobStart != NULL);
608 CopyMem (MmHobStart, HobStart, HobSize);
609 Status = MmInstallConfigurationTable (&gMmCoreMmst, &gEfiHobListGuid, MmHobStart, HobSize);
610 ASSERT_EFI_ERROR (Status);
611
612 //
613 // Register notification for EFI_MM_CONFIGURATION_PROTOCOL registration and
614 // use it to register the MM Foundation entrypoint
615 //
616 DEBUG ((DEBUG_INFO, "MmRegisterProtocolNotify - MmConfigurationMmProtocol\n"));
617 Status = MmRegisterProtocolNotify (
618 &gEfiMmConfigurationProtocolGuid,
619 MmConfigurationMmNotify,
620 &Registration
621 );
622 ASSERT_EFI_ERROR (Status);
623
624 //
625 // Dispatch standalone BFV
626 //
627 DEBUG ((DEBUG_INFO, "Mm Dispatch StandaloneBfvAddress - 0x%08x\n", gMmCorePrivate->StandaloneBfvAddress));
628 if (gMmCorePrivate->StandaloneBfvAddress != 0) {
629 MmCoreFfsFindMmDriver ((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)gMmCorePrivate->StandaloneBfvAddress);
630 MmDispatcher ();
631 }
632
633 //
634 // Register all handlers in the core table
635 //
636 for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) {
637 Status = MmiHandlerRegister (
638 mMmCoreMmiHandlers[Index].Handler,
639 mMmCoreMmiHandlers[Index].HandlerType,
640 &mMmCoreMmiHandlers[Index].DispatchHandle
641 );
642 DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status));
643 }
644
645 DEBUG ((DEBUG_INFO, "MmMain Done!\n"));
646
647 return EFI_SUCCESS;
648 }