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