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