diff --git a/StandaloneMmPkg/Core/Dispatcher.c b/StandaloneMmPkg/Core/Dispatcher.c index dd8f79a2d2..462a4abd8a 100644 --- a/StandaloneMmPkg/Core/Dispatcher.c +++ b/StandaloneMmPkg/Core/Dispatcher.c @@ -384,6 +384,7 @@ MmDispatcher ( LIST_ENTRY *Link; EFI_MM_DRIVER_ENTRY *DriverEntry; BOOLEAN ReadyToRun; + BOOLEAN PreviousMmEntryPointRegistered; DEBUG ((DEBUG_INFO, "MmDispatcher\n")); @@ -447,6 +448,11 @@ MmDispatcher ( DriverEntry->Initialized = TRUE; RemoveEntryList (&DriverEntry->ScheduledLink); + // + // Cache state of MmEntryPointRegistered before calling entry point + // + PreviousMmEntryPointRegistered = mMmEntryPointRegistered; + // // For each MM driver, pass NULL as ImageHandle // @@ -463,6 +469,22 @@ MmDispatcher ( ); } } + + if (!PreviousMmEntryPointRegistered && mMmEntryPointRegistered) { + if (FeaturePcdGet (PcdRestartMmDispatcherOnceMmEntryRegistered)) { + // + // Return immediately if the MM Entry Point was registered by the MM + // Driver that was just dispatched. The MM IPL will reinvoke the MM + // Core Dispatcher. This is required so MM Mode may be enabled as soon + // as all the dependent MM Drivers for MM Mode have been dispatched. + // Once the MM Entry Point has been registered, then MM Mode will be + // used. + // + gRequestDispatch = TRUE; + gDispatcherRunning = FALSE; + return EFI_NOT_READY; + } + } } // @@ -693,6 +715,55 @@ MmAddToDriverList ( return EFI_SUCCESS; } +/** + Event notification that is fired MM IPL to dispatch the previously discovered MM drivers. + + @param[in] DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister(). + @param[in] Context Points to an optional handler context which was specified when the + handler was registered. + @param[in, out] CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-MM environment into an MM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @return EFI_SUCCESS Dispatcher is executed. + +**/ +EFI_STATUS +EFIAPI +MmDriverDispatchHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "MmDriverDispatchHandler\n")); + + // + // Execute the MM Dispatcher on MM drivers that have been discovered + // previously but not dispatched. + // + Status = MmDispatcher (); + + // + // Check to see if CommBuffer and CommBufferSize are valid + // + if ((CommBuffer != NULL) && (CommBufferSize != NULL)) { + if (*CommBufferSize > sizeof (EFI_STATUS)) { + // + // Set the status of MmDispatcher to CommBuffer + // + *(EFI_STATUS *)CommBuffer = Status; + } + } + + MmiHandlerUnRegister (DispatchHandle); + + return EFI_SUCCESS; +} + /** Traverse the discovered list for any drivers that were discovered but not loaded because the dependency expressions evaluated to false. diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.c b/StandaloneMmPkg/Core/StandaloneMmCore.c index e5c28be4e0..6bdb30f954 100644 --- a/StandaloneMmPkg/Core/StandaloneMmCore.c +++ b/StandaloneMmPkg/Core/StandaloneMmCore.c @@ -74,6 +74,7 @@ EFI_MM_SYSTEM_TABLE gMmCoreMmst = { // Table of MMI Handlers that are registered by the MM Core when it is initialized // MM_CORE_MMI_HANDLERS mMmCoreMmiHandlers[] = { + { MmDriverDispatchHandler, &gEventMmDispatchGuid, NULL, FALSE }, { MmReadyToLockHandler, &gEfiDxeMmReadyToLockProtocolGuid, NULL, TRUE }, { MmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, FALSE }, { MmExitBootServiceHandler, &gEfiEventExitBootServicesGuid, NULL, FALSE }, diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.h b/StandaloneMmPkg/Core/StandaloneMmCore.h index 84d1632505..681b7ff61d 100644 --- a/StandaloneMmPkg/Core/StandaloneMmCore.h +++ b/StandaloneMmPkg/Core/StandaloneMmCore.h @@ -177,6 +177,7 @@ typedef struct { // extern EFI_MM_SYSTEM_TABLE gMmCoreMmst; extern LIST_ENTRY gHandleList; +extern BOOLEAN mMmEntryPointRegistered; /** Called to initialize the memory service. diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.inf b/StandaloneMmPkg/Core/StandaloneMmCore.inf index dd9af16ca4..0073f51894 100644 --- a/StandaloneMmPkg/Core/StandaloneMmCore.inf +++ b/StandaloneMmPkg/Core/StandaloneMmCore.inf @@ -63,7 +63,7 @@ [Guids] gAprioriGuid ## SOMETIMES_CONSUMES ## File - gEfiEventDxeDispatchGuid ## PRODUCES ## GUID # SmiHandlerRegister + gEventMmDispatchGuid ## PRODUCES ## GUID # SmiHandlerRegister gEfiEndOfDxeEventGroupGuid ## PRODUCES ## GUID # SmiHandlerRegister ## SOMETIMES_CONSUMES ## GUID # Locate protocol ## SOMETIMES_PRODUCES ## GUID # SmiHandlerRegister @@ -79,6 +79,7 @@ [Pcd] gStandaloneMmPkgTokenSpaceGuid.PcdFwVolMmMaxEncapsulationDepth ##CONSUMES + gStandaloneMmPkgTokenSpaceGuid.PcdRestartMmDispatcherOnceMmEntryRegistered ##CONSUMES # # This configuration fails for CLANGPDB, which does not support PIE in the GCC diff --git a/StandaloneMmPkg/StandaloneMmPkg.dec b/StandaloneMmPkg/StandaloneMmPkg.dec index 8ba0a54706..54fe59e999 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dec +++ b/StandaloneMmPkg/StandaloneMmPkg.dec @@ -56,3 +56,10 @@ # in the MM phase. Minimum value is 1. Sections nested more deeply are rejected. # @Prompt Maximum permitted FwVol section nesting depth (exclusive) in MM. gStandaloneMmPkgTokenSpaceGuid.PcdFwVolMmMaxEncapsulationDepth|0x10|UINT32|0x00000001 + +[PcdsFeatureFlag] + ## Indicates if restart MM Dispatcher once MM Entry Point is registered.

+ # TRUE - Restart MM Dispatcher once MM Entry Point is registered.
+ # FALSE - Do not restart MM Dispatcher once MM Entry Point is registered.
+ # @Prompt Restart MM Dispatcher once MM Entry Point is registered. + gStandaloneMmPkgTokenSpaceGuid.PcdRestartMmDispatcherOnceMmEntryRegistered|FALSE|BOOLEAN|0x00000002