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