drivers to run. Drain the mScheduledQueue and load and start a PE\r
image for each driver. Search the mDiscoveredList to see if any driver can\r
be placed on the mScheduledQueue. If no drivers are placed on the\r
- mScheduledQueue exit the function. On exit it is assumed the Bds()\r
- will be called, and when the Bds() exits the Dispatcher will be called\r
- again.\r
-\r
+ mScheduledQueue exit the function. \r
+\r
+ @retval EFI_SUCCESS All of the SMM Drivers that could be dispatched\r
+ have been run and the SMM Entry Point has been\r
+ registered.\r
+ @retval EFI_NOT_READY The SMM Driver that registered the SMM Entry Point\r
+ was just dispatched.\r
+ @retval EFI_NOT_FOUND There are no SMM Drivers available to be dispatched.\r
@retval EFI_ALREADY_STARTED The SMM Dispatcher is already running\r
- @retval EFI_NOT_FOUND No SMM Drivers were dispatched\r
- @retval EFI_SUCCESS One or more SMM Drivers were dispatched\r
\r
**/\r
EFI_STATUS\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_STATUS ReturnStatus;\r
LIST_ENTRY *Link;\r
EFI_SMM_DRIVER_ENTRY *DriverEntry;\r
BOOLEAN ReadyToRun;\r
+ BOOLEAN PreviousSmmEntryPointRegistered;\r
\r
if (!gRequestDispatch) {\r
return EFI_NOT_FOUND;\r
\r
gDispatcherRunning = TRUE;\r
\r
- ReturnStatus = EFI_NOT_FOUND;\r
do {\r
//\r
// Drain the Scheduled Queue\r
sizeof (DriverEntry->ImageHandle)\r
);\r
\r
+ //\r
+ // Cache state of SmmEntryPointRegistered before calling entry point\r
+ //\r
+ PreviousSmmEntryPointRegistered = gSmmCorePrivate->SmmEntryPointRegistered;\r
+\r
//\r
// For each SMM driver, pass NULL as ImageHandle\r
//\r
sizeof (DriverEntry->ImageHandle)\r
);\r
\r
- ReturnStatus = EFI_SUCCESS;\r
+ if (!PreviousSmmEntryPointRegistered && gSmmCorePrivate->SmmEntryPointRegistered) {\r
+ //\r
+ // Return immediately if the SMM Entry Point was registered by the SMM \r
+ // Driver that was just dispatched. The SMM IPL will reinvoke the SMM\r
+ // Core Dispatcher. This is required so SMM Mode may be enabled as soon \r
+ // as all the dependent SMM Drivers for SMM Mode have been dispatched. \r
+ // Once the SMM Entry Point has been registered, then SMM Mode will be \r
+ // used.\r
+ //\r
+ gRequestDispatch = TRUE;\r
+ gDispatcherRunning = FALSE;\r
+ return EFI_NOT_READY;\r
+ }\r
}\r
\r
//\r
\r
gDispatcherRunning = FALSE;\r
\r
- return ReturnStatus;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
// Execute the SMM Dispatcher on any newly discovered FVs and previously \r
// discovered SMM drivers that have been discovered but not dispatched.\r
//\r
- return SmmDispatcher ();\r
+ Status = SmmDispatcher ();\r
+\r
+ //\r
+ // Check to see if CommBuffer and CommBufferSize are valid\r
+ //\r
+ if (CommBuffer != NULL && CommBufferSize != NULL) {\r
+ if (*CommBufferSize > 0) {\r
+ if (Status == EFI_NOT_READY) {\r
+ //\r
+ // If a the SMM Core Entry Point was just registered, then set flag to \r
+ // request the SMM Dispatcher to be restarted.\r
+ //\r
+ *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_RESTART;\r
+ } else if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Set the flag to show that the SMM Dispatcher executed without errors\r
+ //\r
+ *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_SUCCESS;\r
+ } else {\r
+ //\r
+ // Set the flag to show that the SMM Dispatcher encountered an error\r
+ //\r
+ *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_ERROR;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r