StandaloneMmCore.c 21 KB

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