]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/StandaloneMmCore.c
StandaloneMmPkg: Replace BSD License with BSD+Patent License
[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 - 2018, 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 = EFI_SUCCESS;
153 STATIC BOOLEAN mInExitBootServices = FALSE;
154
155 if (!mInExitBootServices) {
156 MmHandle = NULL;
157 Status = MmInstallProtocolInterface (
158 &MmHandle,
159 &gEfiEventExitBootServicesGuid,
160 EFI_NATIVE_INTERFACE,
161 NULL
162 );
163 }
164 mInExitBootServices = TRUE;
165 return Status;
166 }
167
168 /**
169 Software MMI handler that is called when a ExitBoot Service event is signaled.
170
171 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
172 @param Context Points to an optional handler context which was specified when the handler was registered.
173 @param CommBuffer A pointer to a collection of data in memory that will
174 be conveyed from a non-MM environment into an MM environment.
175 @param CommBufferSize The size of the CommBuffer.
176
177 @return Status Code
178
179 **/
180 EFI_STATUS
181 EFIAPI
182 MmReadyToBootHandler (
183 IN EFI_HANDLE DispatchHandle,
184 IN CONST VOID *Context, OPTIONAL
185 IN OUT VOID *CommBuffer, OPTIONAL
186 IN OUT UINTN *CommBufferSize OPTIONAL
187 )
188 {
189 EFI_HANDLE MmHandle;
190 EFI_STATUS Status = EFI_SUCCESS;
191 STATIC BOOLEAN mInReadyToBoot = FALSE;
192
193 if (!mInReadyToBoot) {
194 MmHandle = NULL;
195 Status = MmInstallProtocolInterface (
196 &MmHandle,
197 &gEfiEventReadyToBootGuid,
198 EFI_NATIVE_INTERFACE,
199 NULL
200 );
201 }
202 mInReadyToBoot = TRUE;
203 return Status;
204 }
205
206 /**
207 Software MMI handler that is called when the DxeMmReadyToLock protocol is added
208 or if gEfiEventReadyToBootGuid is signaled. This function unregisters the
209 Software SMIs that are nor required after MMRAM is locked and installs the
210 MM Ready To Lock Protocol so MM Drivers are informed that MMRAM is about
211 to be locked.
212
213 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
214 @param Context Points to an optional handler context which was specified when the handler was registered.
215 @param CommBuffer A pointer to a collection of data in memory that will
216 be conveyed from a non-MM environment into an MM environment.
217 @param CommBufferSize The size of the CommBuffer.
218
219 @return Status Code
220
221 **/
222 EFI_STATUS
223 EFIAPI
224 MmReadyToLockHandler (
225 IN EFI_HANDLE DispatchHandle,
226 IN CONST VOID *Context, OPTIONAL
227 IN OUT VOID *CommBuffer, OPTIONAL
228 IN OUT UINTN *CommBufferSize OPTIONAL
229 )
230 {
231 EFI_STATUS Status;
232 UINTN Index;
233 EFI_HANDLE MmHandle;
234
235 DEBUG ((DEBUG_INFO, "MmReadyToLockHandler\n"));
236
237 //
238 // Unregister MMI Handlers that are no longer required after the MM driver dispatch is stopped
239 //
240 for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) {
241 if (mMmCoreMmiHandlers[Index].UnRegister) {
242 MmiHandlerUnRegister (mMmCoreMmiHandlers[Index].DispatchHandle);
243 }
244 }
245
246 //
247 // Install MM Ready to lock protocol
248 //
249 MmHandle = NULL;
250 Status = MmInstallProtocolInterface (
251 &MmHandle,
252 &gEfiMmReadyToLockProtocolGuid,
253 EFI_NATIVE_INTERFACE,
254 NULL
255 );
256
257 //
258 // Make sure MM CPU I/O 2 Protocol has been installed into the handle database
259 //
260 //Status = MmLocateProtocol (&EFI_MM_CPU_IO_PROTOCOL_GUID, NULL, &Interface);
261
262 //
263 // Print a message on a debug build if the MM CPU I/O 2 Protocol is not installed
264 //
265 //if (EFI_ERROR (Status)) {
266 //DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));
267 //}
268
269
270 //
271 // Assert if the CPU I/O 2 Protocol is not installed
272 //
273 //ASSERT_EFI_ERROR (Status);
274
275 //
276 // Display any drivers that were not dispatched because dependency expression
277 // evaluated to false if this is a debug build
278 //
279 //MmDisplayDiscoveredNotDispatched ();
280
281 return Status;
282 }
283
284 /**
285 Software MMI handler that is called when the EndOfDxe event is signaled.
286 This function installs the MM EndOfDxe Protocol so MM Drivers are informed that
287 platform code will invoke 3rd part code.
288
289 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
290 @param Context Points to an optional handler context which was specified when the handler was registered.
291 @param CommBuffer A pointer to a collection of data in memory that will
292 be conveyed from a non-MM environment into an MM environment.
293 @param CommBufferSize The size of the CommBuffer.
294
295 @return Status Code
296
297 **/
298 EFI_STATUS
299 EFIAPI
300 MmEndOfDxeHandler (
301 IN EFI_HANDLE DispatchHandle,
302 IN CONST VOID *Context, OPTIONAL
303 IN OUT VOID *CommBuffer, OPTIONAL
304 IN OUT UINTN *CommBufferSize OPTIONAL
305 )
306 {
307 EFI_STATUS Status;
308 EFI_HANDLE MmHandle;
309
310 DEBUG ((DEBUG_INFO, "MmEndOfDxeHandler\n"));
311 //
312 // Install MM EndOfDxe protocol
313 //
314 MmHandle = NULL;
315 Status = MmInstallProtocolInterface (
316 &MmHandle,
317 &gEfiMmEndOfDxeProtocolGuid,
318 EFI_NATIVE_INTERFACE,
319 NULL
320 );
321 return Status;
322 }
323
324
325
326 /**
327 The main entry point to MM Foundation.
328
329 Note: This function is only used by MMRAM invocation. It is never used by DXE invocation.
330
331 @param MmEntryContext Processor information and functionality
332 needed by MM Foundation.
333
334 **/
335 VOID
336 EFIAPI
337 MmEntryPoint (
338 IN CONST EFI_MM_ENTRY_CONTEXT *MmEntryContext
339 )
340 {
341 EFI_STATUS Status;
342 EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
343
344 DEBUG ((DEBUG_INFO, "MmEntryPoint ...\n"));
345
346 //
347 // Update MMST using the context
348 //
349 CopyMem (&gMmCoreMmst.MmStartupThisAp, MmEntryContext, sizeof (EFI_MM_ENTRY_CONTEXT));
350
351 //
352 // Call platform hook before Mm Dispatch
353 //
354 //PlatformHookBeforeMmDispatch ();
355
356 //
357 // If a legacy boot has occured, then make sure gMmCorePrivate is not accessed
358 //
359
360 //
361 // TBD: Mark the InMm flag as TRUE
362 //
363 gMmCorePrivate->InMm = TRUE;
364
365 //
366 // Check to see if this is a Synchronous MMI sent through the MM Communication
367 // Protocol or an Asynchronous MMI
368 //
369 if (gMmCorePrivate->CommunicationBuffer != 0) {
370 //
371 // Synchronous MMI for MM Core or request from Communicate protocol
372 //
373 if (!MmIsBufferOutsideMmValid ((UINTN)gMmCorePrivate->CommunicationBuffer, gMmCorePrivate->BufferSize)) {
374 //
375 // If CommunicationBuffer is not in valid address scope, return EFI_INVALID_PARAMETER
376 //
377 gMmCorePrivate->CommunicationBuffer = 0;
378 gMmCorePrivate->ReturnStatus = EFI_INVALID_PARAMETER;
379 } else {
380 CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)gMmCorePrivate->CommunicationBuffer;
381 gMmCorePrivate->BufferSize -= OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);
382 Status = MmiManage (
383 &CommunicateHeader->HeaderGuid,
384 NULL,
385 CommunicateHeader->Data,
386 (UINTN *)&gMmCorePrivate->BufferSize
387 );
388 //
389 // Update CommunicationBuffer, BufferSize and ReturnStatus
390 // Communicate service finished, reset the pointer to CommBuffer to NULL
391 //
392 gMmCorePrivate->BufferSize += OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);
393 gMmCorePrivate->CommunicationBuffer = 0;
394 gMmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
395 }
396 }
397
398 //
399 // Process Asynchronous MMI sources
400 //
401 MmiManage (NULL, NULL, NULL, NULL);
402
403 //
404 // TBD: Do not use private data structure ?
405 //
406
407 //
408 // Clear the InMm flag as we are going to leave MM
409 //
410 gMmCorePrivate->InMm = FALSE;
411
412 DEBUG ((DEBUG_INFO, "MmEntryPoint Done\n"));
413 }
414
415 EFI_STATUS
416 EFIAPI
417 MmConfigurationMmNotify (
418 IN CONST EFI_GUID *Protocol,
419 IN VOID *Interface,
420 IN EFI_HANDLE Handle
421 )
422 {
423 EFI_STATUS Status;
424 EFI_MM_CONFIGURATION_PROTOCOL *MmConfiguration;
425
426 DEBUG ((DEBUG_INFO, "MmConfigurationMmNotify(%g) - %x\n", Protocol, Interface));
427
428 MmConfiguration = Interface;
429
430 //
431 // Register the MM Entry Point provided by the MM Core with the MM COnfiguration protocol
432 //
433 Status = MmConfiguration->RegisterMmEntry (MmConfiguration, (EFI_MM_ENTRY_POINT)(UINTN)gMmCorePrivate->MmEntryPoint);
434 ASSERT_EFI_ERROR (Status);
435
436 //
437 // Set flag to indicate that the MM Entry Point has been registered which
438 // means that MMIs are now fully operational.
439 //
440 gMmCorePrivate->MmEntryPointRegistered = TRUE;
441
442 //
443 // Print debug message showing MM Core entry point address.
444 //
445 DEBUG ((DEBUG_INFO, "MM Core registered MM Entry Point address %p\n", (VOID *)(UINTN)gMmCorePrivate->MmEntryPoint));
446 return EFI_SUCCESS;
447 }
448
449 UINTN
450 GetHobListSize (
451 IN VOID *HobStart
452 )
453 {
454 EFI_PEI_HOB_POINTERS Hob;
455
456 ASSERT (HobStart != NULL);
457
458 Hob.Raw = (UINT8 *) HobStart;
459 while (!END_OF_HOB_LIST (Hob)) {
460 Hob.Raw = GET_NEXT_HOB (Hob);
461 }
462 //
463 // Need plus END_OF_HOB_LIST
464 //
465 return (UINTN)Hob.Raw - (UINTN)HobStart + sizeof (EFI_HOB_GENERIC_HEADER);
466 }
467
468 /**
469 The Entry Point for MM Core
470
471 Install DXE Protocols and reload MM Core into MMRAM and register MM Core
472 EntryPoint on the MMI vector.
473
474 Note: This function is called for both DXE invocation and MMRAM invocation.
475
476 @param ImageHandle The firmware allocated handle for the EFI image.
477 @param SystemTable A pointer to the EFI System Table.
478
479 @retval EFI_SUCCESS The entry point is executed successfully.
480 @retval Other Some error occurred when executing this entry point.
481
482 **/
483 EFI_STATUS
484 EFIAPI
485 StandaloneMmMain (
486 IN VOID *HobStart
487 )
488 {
489 EFI_STATUS Status;
490 UINTN Index;
491 VOID *MmHobStart;
492 UINTN HobSize;
493 VOID *Registration;
494 EFI_HOB_GUID_TYPE *GuidHob;
495 MM_CORE_DATA_HOB_DATA *DataInHob;
496 EFI_HOB_GUID_TYPE *MmramRangesHob;
497 EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData;
498 EFI_MMRAM_DESCRIPTOR *MmramRanges;
499 UINT32 MmramRangeCount;
500 EFI_HOB_FIRMWARE_VOLUME *BfvHob;
501
502 ProcessLibraryConstructorList (HobStart, &gMmCoreMmst);
503
504 DEBUG ((DEBUG_INFO, "MmMain - 0x%x\n", HobStart));
505
506 //
507 // Determine if the caller has passed a reference to a MM_CORE_PRIVATE_DATA
508 // structure in the Hoblist. This choice will govern how boot information is
509 // extracted later.
510 //
511 GuidHob = GetNextGuidHob (&gMmCoreDataHobGuid, HobStart);
512 if (GuidHob == NULL) {
513 //
514 // Allocate and zero memory for a MM_CORE_PRIVATE_DATA table and then
515 // initialise it
516 //
517 gMmCorePrivate = (MM_CORE_PRIVATE_DATA *) AllocateRuntimePages(EFI_SIZE_TO_PAGES(sizeof (MM_CORE_PRIVATE_DATA)));
518 SetMem ((VOID *)(UINTN)gMmCorePrivate, sizeof (MM_CORE_PRIVATE_DATA), 0);
519 gMmCorePrivate->Signature = MM_CORE_PRIVATE_DATA_SIGNATURE;
520 gMmCorePrivate->MmEntryPointRegistered = FALSE;
521 gMmCorePrivate->InMm = FALSE;
522 gMmCorePrivate->ReturnStatus = EFI_SUCCESS;
523
524 //
525 // Extract the MMRAM ranges from the MMRAM descriptor HOB
526 //
527 MmramRangesHob = GetNextGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, HobStart);
528 if (MmramRangesHob == NULL)
529 return EFI_UNSUPPORTED;
530
531 MmramRangesHobData = GET_GUID_HOB_DATA (MmramRangesHob);
532 ASSERT (MmramRangesHobData != NULL);
533 MmramRanges = MmramRangesHobData->Descriptor;
534 MmramRangeCount = MmramRangesHobData->NumberOfMmReservedRegions;
535 ASSERT (MmramRanges);
536 ASSERT (MmramRangeCount);
537
538 //
539 // Copy the MMRAM ranges into MM_CORE_PRIVATE_DATA table just in case any
540 // code relies on them being present there
541 //
542 gMmCorePrivate->MmramRangeCount = MmramRangeCount;
543 gMmCorePrivate->MmramRanges =
544 (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (MmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
545 ASSERT (gMmCorePrivate->MmramRanges != 0);
546 CopyMem (
547 (VOID *)(UINTN)gMmCorePrivate->MmramRanges,
548 MmramRanges,
549 MmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR)
550 );
551 } else {
552 DataInHob = GET_GUID_HOB_DATA (GuidHob);
553 gMmCorePrivate = (MM_CORE_PRIVATE_DATA *)(UINTN)DataInHob->Address;
554 MmramRanges = (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRanges;
555 MmramRangeCount = gMmCorePrivate->MmramRangeCount;
556 }
557
558 //
559 // Print the MMRAM ranges passed by the caller
560 //
561 DEBUG ((DEBUG_INFO, "MmramRangeCount - 0x%x\n", MmramRangeCount));
562 for (Index = 0; Index < MmramRangeCount; Index++) {
563 DEBUG ((DEBUG_INFO, "MmramRanges[%d]: 0x%016lx - 0x%lx\n", Index,
564 MmramRanges[Index].CpuStart,
565 MmramRanges[Index].PhysicalSize));
566 }
567
568 //
569 // Copy the MMRAM ranges into private MMRAM
570 //
571 mMmramRangeCount = MmramRangeCount;
572 DEBUG ((DEBUG_INFO, "mMmramRangeCount - 0x%x\n", mMmramRangeCount));
573 mMmramRanges = AllocatePool (mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
574 DEBUG ((DEBUG_INFO, "mMmramRanges - 0x%x\n", mMmramRanges));
575 ASSERT (mMmramRanges != NULL);
576 CopyMem (mMmramRanges, (VOID *)(UINTN)MmramRanges, mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
577
578 //
579 // Get Boot Firmware Volume address from the BFV Hob
580 //
581 BfvHob = GetFirstHob (EFI_HOB_TYPE_FV);
582 if (BfvHob != NULL) {
583 DEBUG ((DEBUG_INFO, "BFV address - 0x%x\n", BfvHob->BaseAddress));
584 DEBUG ((DEBUG_INFO, "BFV size - 0x%x\n", BfvHob->Length));
585 gMmCorePrivate->StandaloneBfvAddress = BfvHob->BaseAddress;
586 }
587
588 gMmCorePrivate->Mmst = (EFI_PHYSICAL_ADDRESS)(UINTN)&gMmCoreMmst;
589 gMmCorePrivate->MmEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)MmEntryPoint;
590
591 //
592 // No need to initialize memory service.
593 // It is done in constructor of StandaloneMmCoreMemoryAllocationLib(),
594 // so that the library linked with StandaloneMmCore can use AllocatePool() in constuctor.
595 //
596
597 DEBUG ((DEBUG_INFO, "MmInstallConfigurationTable For HobList\n"));
598 //
599 // Install HobList
600 //
601 HobSize = GetHobListSize (HobStart);
602 DEBUG ((DEBUG_INFO, "HobSize - 0x%x\n", HobSize));
603 MmHobStart = AllocatePool (HobSize);
604 DEBUG ((DEBUG_INFO, "MmHobStart - 0x%x\n", MmHobStart));
605 ASSERT (MmHobStart != NULL);
606 CopyMem (MmHobStart, HobStart, HobSize);
607 Status = MmInstallConfigurationTable (&gMmCoreMmst, &gEfiHobListGuid, MmHobStart, HobSize);
608 ASSERT_EFI_ERROR (Status);
609
610 //
611 // Register notification for EFI_MM_CONFIGURATION_PROTOCOL registration and
612 // use it to register the MM Foundation entrypoint
613 //
614 DEBUG ((DEBUG_INFO, "MmRegisterProtocolNotify - MmConfigurationMmProtocol\n"));
615 Status = MmRegisterProtocolNotify (
616 &gEfiMmConfigurationProtocolGuid,
617 MmConfigurationMmNotify,
618 &Registration
619 );
620 ASSERT_EFI_ERROR (Status);
621
622 //
623 // Dispatch standalone BFV
624 //
625 DEBUG ((DEBUG_INFO, "Mm Dispatch StandaloneBfvAddress - 0x%08x\n", gMmCorePrivate->StandaloneBfvAddress));
626 if (gMmCorePrivate->StandaloneBfvAddress != 0) {
627 MmCoreFfsFindMmDriver ((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)gMmCorePrivate->StandaloneBfvAddress);
628 MmDispatcher ();
629 }
630
631 //
632 // Register all handlers in the core table
633 //
634 for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) {
635 Status = MmiHandlerRegister (
636 mMmCoreMmiHandlers[Index].Handler,
637 mMmCoreMmiHandlers[Index].HandlerType,
638 &mMmCoreMmiHandlers[Index].DispatchHandle
639 );
640 DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status));
641 }
642
643 DEBUG ((DEBUG_INFO, "MmMain Done!\n"));
644
645 return EFI_SUCCESS;
646 }