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