]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/StandaloneMmCore.c
StandaloneMmPkg: Apply uncrustify changes
[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 // The table header for the MMST.
37 {
38 MM_MMST_SIGNATURE,
39 EFI_MM_SYSTEM_TABLE_REVISION,
40 sizeof (gMmCoreMmst.Hdr)
41 },
42 // MmFirmwareVendor
43 NULL,
44 // MmFirmwareRevision
45 0,
46 // MmInstallConfigurationTable
47 MmInstallConfigurationTable,
48 // I/O Service
49 {
50 {
51 (EFI_MM_CPU_IO)MmEfiNotAvailableYetArg5, // MmMemRead
52 (EFI_MM_CPU_IO)MmEfiNotAvailableYetArg5 // MmMemWrite
53 },
54 {
55 (EFI_MM_CPU_IO)MmEfiNotAvailableYetArg5, // MmIoRead
56 (EFI_MM_CPU_IO)MmEfiNotAvailableYetArg5 // MmIoWrite
57 }
58 },
59 // Runtime memory services
60 MmAllocatePool,
61 MmFreePool,
62 MmAllocatePages,
63 MmFreePages,
64 // MP service
65 NULL, // MmStartupThisAp
66 0, // CurrentlyExecutingCpu
67 0, // NumberOfCpus
68 NULL, // CpuSaveStateSize
69 NULL, // CpuSaveState
70 0, // NumberOfTableEntries
71 NULL, // MmConfigurationTable
72 MmInstallProtocolInterface,
73 MmUninstallProtocolInterface,
74 MmHandleProtocol,
75 MmRegisterProtocolNotify,
76 MmLocateHandle,
77 MmLocateProtocol,
78 MmiManage,
79 MmiHandlerRegister,
80 MmiHandlerUnRegister
81 };
82
83 //
84 // Table of MMI Handlers that are registered by the MM Core when it is initialized
85 //
86 MM_CORE_MMI_HANDLERS mMmCoreMmiHandlers[] = {
87 { MmReadyToLockHandler, &gEfiDxeMmReadyToLockProtocolGuid, NULL, TRUE },
88 { MmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, FALSE },
89 { MmExitBootServiceHandler, &gEfiEventExitBootServicesGuid, NULL, FALSE },
90 { MmReadyToBootHandler, &gEfiEventReadyToBootGuid, NULL, FALSE },
91 { NULL, NULL, NULL, FALSE },
92 };
93
94 EFI_SYSTEM_TABLE *mEfiSystemTable;
95 UINTN mMmramRangeCount;
96 EFI_MMRAM_DESCRIPTOR *mMmramRanges;
97
98 /**
99 Place holder function until all the MM System Table Service are available.
100
101 Note: This function is only used by MMRAM invocation. It is never used by DXE invocation.
102
103 @param Arg1 Undefined
104 @param Arg2 Undefined
105 @param Arg3 Undefined
106 @param Arg4 Undefined
107 @param Arg5 Undefined
108
109 @return EFI_NOT_AVAILABLE_YET
110
111 **/
112 EFI_STATUS
113 EFIAPI
114 MmEfiNotAvailableYetArg5 (
115 UINTN Arg1,
116 UINTN Arg2,
117 UINTN Arg3,
118 UINTN Arg4,
119 UINTN Arg5
120 )
121 {
122 //
123 // This function should never be executed. If it does, then the architectural protocols
124 // have not been designed correctly.
125 //
126 return EFI_NOT_AVAILABLE_YET;
127 }
128
129 /**
130 Software MMI handler that is called when a ExitBoot Service event is signaled.
131
132 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
133 @param Context Points to an optional handler context which was specified when the handler was registered.
134 @param CommBuffer A pointer to a collection of data in memory that will
135 be conveyed from a non-MM environment into an MM environment.
136 @param CommBufferSize The size of the CommBuffer.
137
138 @return Status Code
139
140 **/
141 EFI_STATUS
142 EFIAPI
143 MmExitBootServiceHandler (
144 IN EFI_HANDLE DispatchHandle,
145 IN CONST VOID *Context OPTIONAL,
146 IN OUT VOID *CommBuffer OPTIONAL,
147 IN OUT UINTN *CommBufferSize OPTIONAL
148 )
149 {
150 EFI_HANDLE MmHandle;
151 EFI_STATUS Status;
152 STATIC BOOLEAN mInExitBootServices = FALSE;
153
154 Status = EFI_SUCCESS;
155 if (!mInExitBootServices) {
156 MmHandle = NULL;
157 Status = MmInstallProtocolInterface (
158 &MmHandle,
159 &gEfiEventExitBootServicesGuid,
160 EFI_NATIVE_INTERFACE,
161 NULL
162 );
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
205 mInReadyToBoot = TRUE;
206 return Status;
207 }
208
209 /**
210 Software MMI handler that is called when the DxeMmReadyToLock protocol is added
211 or if gEfiEventReadyToBootGuid is signaled. This function unregisters the
212 Software SMIs that are nor required after MMRAM is locked and installs the
213 MM Ready To Lock Protocol so MM Drivers are informed that MMRAM is about
214 to be locked.
215
216 @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
217 @param Context Points to an optional handler context which was specified when the handler was registered.
218 @param CommBuffer A pointer to a collection of data in memory that will
219 be conveyed from a non-MM environment into an MM environment.
220 @param CommBufferSize The size of the CommBuffer.
221
222 @return Status Code
223
224 **/
225 EFI_STATUS
226 EFIAPI
227 MmReadyToLockHandler (
228 IN EFI_HANDLE DispatchHandle,
229 IN CONST VOID *Context OPTIONAL,
230 IN OUT VOID *CommBuffer OPTIONAL,
231 IN OUT UINTN *CommBufferSize OPTIONAL
232 )
233 {
234 EFI_STATUS Status;
235 UINTN Index;
236 EFI_HANDLE MmHandle;
237
238 DEBUG ((DEBUG_INFO, "MmReadyToLockHandler\n"));
239
240 //
241 // Unregister MMI Handlers that are no longer required after the MM driver dispatch is stopped
242 //
243 for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) {
244 if (mMmCoreMmiHandlers[Index].UnRegister) {
245 MmiHandlerUnRegister (mMmCoreMmiHandlers[Index].DispatchHandle);
246 }
247 }
248
249 //
250 // Install MM Ready to lock protocol
251 //
252 MmHandle = NULL;
253 Status = MmInstallProtocolInterface (
254 &MmHandle,
255 &gEfiMmReadyToLockProtocolGuid,
256 EFI_NATIVE_INTERFACE,
257 NULL
258 );
259
260 //
261 // Make sure MM CPU I/O 2 Protocol has been installed into the handle database
262 //
263 // Status = MmLocateProtocol (&EFI_MM_CPU_IO_PROTOCOL_GUID, NULL, &Interface);
264
265 //
266 // Print a message on a debug build if the MM CPU I/O 2 Protocol is not installed
267 //
268 // if (EFI_ERROR (Status)) {
269 // DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));
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 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 occurred, 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 /** Register the MM Entry Point provided by the MM Core with the
416 MM Configuration protocol.
417
418 @param [in] Protocol Pointer to the protocol.
419 @param [in] Interface Pointer to the MM Configuration protocol.
420 @param [in] Handle Handle.
421
422 @retval EFI_SUCCESS Success.
423 **/
424 EFI_STATUS
425 EFIAPI
426 MmConfigurationMmNotify (
427 IN CONST EFI_GUID *Protocol,
428 IN VOID *Interface,
429 IN EFI_HANDLE Handle
430 )
431 {
432 EFI_STATUS Status;
433 EFI_MM_CONFIGURATION_PROTOCOL *MmConfiguration;
434
435 DEBUG ((DEBUG_INFO, "MmConfigurationMmNotify(%g) - %x\n", Protocol, Interface));
436
437 MmConfiguration = Interface;
438
439 //
440 // Register the MM Entry Point provided by the MM Core with the MM COnfiguration protocol
441 //
442 Status = MmConfiguration->RegisterMmEntry (MmConfiguration, (EFI_MM_ENTRY_POINT)(UINTN)gMmCorePrivate->MmEntryPoint);
443 ASSERT_EFI_ERROR (Status);
444
445 //
446 // Set flag to indicate that the MM Entry Point has been registered which
447 // means that MMIs are now fully operational.
448 //
449 gMmCorePrivate->MmEntryPointRegistered = TRUE;
450
451 //
452 // Print debug message showing MM Core entry point address.
453 //
454 DEBUG ((DEBUG_INFO, "MM Core registered MM Entry Point address %p\n", (VOID *)(UINTN)gMmCorePrivate->MmEntryPoint));
455 return EFI_SUCCESS;
456 }
457
458 /** Returns the HOB list size.
459
460 @param [in] HobStart Pointer to the start of the HOB list.
461
462 @retval Size of the HOB list.
463 **/
464 UINTN
465 GetHobListSize (
466 IN VOID *HobStart
467 )
468 {
469 EFI_PEI_HOB_POINTERS Hob;
470
471 ASSERT (HobStart != NULL);
472
473 Hob.Raw = (UINT8 *)HobStart;
474 while (!END_OF_HOB_LIST (Hob)) {
475 Hob.Raw = GET_NEXT_HOB (Hob);
476 }
477
478 //
479 // Need plus END_OF_HOB_LIST
480 //
481 return (UINTN)Hob.Raw - (UINTN)HobStart + sizeof (EFI_HOB_GENERIC_HEADER);
482 }
483
484 /**
485 The Entry Point for MM Core
486
487 Install DXE Protocols and reload MM Core into MMRAM and register MM Core
488 EntryPoint on the MMI vector.
489
490 Note: This function is called for both DXE invocation and MMRAM invocation.
491
492 @param HobStart Pointer to the start of the HOB list.
493
494 @retval EFI_SUCCESS Success.
495 @retval EFI_UNSUPPORTED Unsupported operation.
496 **/
497 EFI_STATUS
498 EFIAPI
499 StandaloneMmMain (
500 IN VOID *HobStart
501 )
502 {
503 EFI_STATUS Status;
504 UINTN Index;
505 VOID *MmHobStart;
506 UINTN HobSize;
507 VOID *Registration;
508 EFI_HOB_GUID_TYPE *GuidHob;
509 MM_CORE_DATA_HOB_DATA *DataInHob;
510 EFI_HOB_GUID_TYPE *MmramRangesHob;
511 EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData;
512 EFI_MMRAM_DESCRIPTOR *MmramRanges;
513 UINTN MmramRangeCount;
514 EFI_HOB_FIRMWARE_VOLUME *BfvHob;
515
516 ProcessLibraryConstructorList (HobStart, &gMmCoreMmst);
517
518 DEBUG ((DEBUG_INFO, "MmMain - 0x%x\n", HobStart));
519
520 //
521 // Determine if the caller has passed a reference to a MM_CORE_PRIVATE_DATA
522 // structure in the Hoblist. This choice will govern how boot information is
523 // extracted later.
524 //
525 GuidHob = GetNextGuidHob (&gMmCoreDataHobGuid, HobStart);
526 if (GuidHob == NULL) {
527 //
528 // Allocate and zero memory for a MM_CORE_PRIVATE_DATA table and then
529 // initialise it
530 //
531 gMmCorePrivate = (MM_CORE_PRIVATE_DATA *)AllocateRuntimePages (EFI_SIZE_TO_PAGES (sizeof (MM_CORE_PRIVATE_DATA)));
532 SetMem ((VOID *)(UINTN)gMmCorePrivate, sizeof (MM_CORE_PRIVATE_DATA), 0);
533 gMmCorePrivate->Signature = MM_CORE_PRIVATE_DATA_SIGNATURE;
534 gMmCorePrivate->MmEntryPointRegistered = FALSE;
535 gMmCorePrivate->InMm = FALSE;
536 gMmCorePrivate->ReturnStatus = EFI_SUCCESS;
537
538 //
539 // Extract the MMRAM ranges from the MMRAM descriptor HOB
540 //
541 MmramRangesHob = GetNextGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, HobStart);
542 if (MmramRangesHob == NULL) {
543 return EFI_UNSUPPORTED;
544 }
545
546 MmramRangesHobData = GET_GUID_HOB_DATA (MmramRangesHob);
547 ASSERT (MmramRangesHobData != NULL);
548 MmramRanges = MmramRangesHobData->Descriptor;
549 MmramRangeCount = (UINTN)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 = (UINT64)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 = (UINTN)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 ((
579 DEBUG_INFO,
580 "MmramRanges[%d]: 0x%016lx - 0x%lx\n",
581 Index,
582 MmramRanges[Index].CpuStart,
583 MmramRanges[Index].PhysicalSize
584 ));
585 }
586
587 //
588 // Copy the MMRAM ranges into private MMRAM
589 //
590 mMmramRangeCount = MmramRangeCount;
591 DEBUG ((DEBUG_INFO, "mMmramRangeCount - 0x%x\n", mMmramRangeCount));
592 mMmramRanges = AllocatePool (mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
593 DEBUG ((DEBUG_INFO, "mMmramRanges - 0x%x\n", mMmramRanges));
594 ASSERT (mMmramRanges != NULL);
595 CopyMem (mMmramRanges, (VOID *)(UINTN)MmramRanges, mMmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
596
597 //
598 // Get Boot Firmware Volume address from the BFV Hob
599 //
600 BfvHob = GetFirstHob (EFI_HOB_TYPE_FV);
601 if (BfvHob != NULL) {
602 DEBUG ((DEBUG_INFO, "BFV address - 0x%x\n", BfvHob->BaseAddress));
603 DEBUG ((DEBUG_INFO, "BFV size - 0x%x\n", BfvHob->Length));
604 gMmCorePrivate->StandaloneBfvAddress = BfvHob->BaseAddress;
605 }
606
607 gMmCorePrivate->Mmst = (EFI_PHYSICAL_ADDRESS)(UINTN)&gMmCoreMmst;
608 gMmCorePrivate->MmEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)MmEntryPoint;
609
610 //
611 // No need to initialize memory service.
612 // It is done in the constructor of StandaloneMmCoreMemoryAllocationLib(),
613 // so that the library linked with StandaloneMmCore can use AllocatePool() in
614 // the constructor.
615
616 DEBUG ((DEBUG_INFO, "MmInstallConfigurationTable For HobList\n"));
617 //
618 // Install HobList
619 //
620 HobSize = GetHobListSize (HobStart);
621 DEBUG ((DEBUG_INFO, "HobSize - 0x%x\n", HobSize));
622 MmHobStart = AllocatePool (HobSize);
623 DEBUG ((DEBUG_INFO, "MmHobStart - 0x%x\n", MmHobStart));
624 ASSERT (MmHobStart != NULL);
625 CopyMem (MmHobStart, HobStart, HobSize);
626 Status = MmInstallConfigurationTable (&gMmCoreMmst, &gEfiHobListGuid, MmHobStart, HobSize);
627 ASSERT_EFI_ERROR (Status);
628
629 //
630 // Register notification for EFI_MM_CONFIGURATION_PROTOCOL registration and
631 // use it to register the MM Foundation entrypoint
632 //
633 DEBUG ((DEBUG_INFO, "MmRegisterProtocolNotify - MmConfigurationMmProtocol\n"));
634 Status = MmRegisterProtocolNotify (
635 &gEfiMmConfigurationProtocolGuid,
636 MmConfigurationMmNotify,
637 &Registration
638 );
639 ASSERT_EFI_ERROR (Status);
640
641 //
642 // Dispatch standalone BFV
643 //
644 DEBUG ((DEBUG_INFO, "Mm Dispatch StandaloneBfvAddress - 0x%08x\n", gMmCorePrivate->StandaloneBfvAddress));
645 if (gMmCorePrivate->StandaloneBfvAddress != 0) {
646 MmCoreFfsFindMmDriver ((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)gMmCorePrivate->StandaloneBfvAddress);
647 MmDispatcher ();
648 }
649
650 //
651 // Register all handlers in the core table
652 //
653 for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) {
654 Status = MmiHandlerRegister (
655 mMmCoreMmiHandlers[Index].Handler,
656 mMmCoreMmiHandlers[Index].HandlerType,
657 &mMmCoreMmiHandlers[Index].DispatchHandle
658 );
659 DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status));
660 }
661
662 DEBUG ((DEBUG_INFO, "MmMain Done!\n"));
663
664 return EFI_SUCCESS;
665 }