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