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