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