]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Update SMM Core to use SMM Mode as soon as SMM Mode is available
authormdkinney <mdkinney@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 24 Aug 2011 06:49:21 +0000 (06:49 +0000)
committermdkinney <mdkinney@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 24 Aug 2011 06:49:21 +0000 (06:49 +0000)
Signed-off-by: mdkinney
Reviewed-by: rsun3
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12190 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Core/PiSmmCore/Dispatcher.c
MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c

index 78c29ffe2255670927cd4251dbce074d317ff4be..53eedbbf61055ffad18e58f1a45629cc803e89ac 100644 (file)
@@ -743,13 +743,15 @@ SmmGetDepexSectionAndPreProccess (
   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
@@ -758,10 +760,10 @@ SmmDispatcher (
   )\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
@@ -776,7 +778,6 @@ SmmDispatcher (
 \r
   gDispatcherRunning = TRUE;\r
 \r
-  ReturnStatus = EFI_NOT_FOUND;\r
   do {\r
     //\r
     // Drain the Scheduled Queue\r
@@ -827,6 +828,11 @@ SmmDispatcher (
         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
@@ -842,7 +848,19 @@ SmmDispatcher (
         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
@@ -886,7 +904,7 @@ SmmDispatcher (
 \r
   gDispatcherRunning = FALSE;\r
 \r
-  return ReturnStatus;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -1309,7 +1327,34 @@ SmmDriverDispatchHandler (
   // 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
index bfacfbb6bd2108d1b24fe1abe894d3c8c9881022..411ebd823f2f5f1897faf287847c2ff479b8a1d6 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file that declared a data structure that is shared\r
   between the SMM IPL and the SMM Core.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available \r
   under the terms and conditions of the BSD License which accompanies this \r
   distribution.  The full text of the license may be found at        \r
 #ifndef _PI_SMM_CORE_PRIVATE_DATA_H_\r
 #define _PI_SMM_CORE_PRIVATE_DATA_H_\r
 \r
+///\r
+/// Define values for the communications buffer used when gEfiEventDxeDispatchGuid is\r
+/// event signaled.  This event is signaled by the DXE Core each time the DXE Core \r
+/// dispatcher has completed its work.  When this event is signaled, the SMM Core\r
+/// if notified, so the SMM Core can dispatch SMM drivers.  If COMM_BUFFER_SMM_DISPATCH_ERROR\r
+/// is returned in the communication buffer, then an error occurred dispatching SMM\r
+/// Drivers.  If COMM_BUFFER_SMM_DISPATCH_SUCCESS is returned, then the SMM Core \r
+/// dispatched all the drivers it could.  If COMM_BUFFER_SMM_DISPATCH_RESTART is \r
+/// returned, then the SMM Core just dispatched the SMM Driver that registered\r
+/// the SMM Entry Point enabling the use of SMM Mode.  In this case, the SMM Core\r
+/// should be notified again to dispatch more SMM Drivers using SMM Mode.\r
+///\r
+#define COMM_BUFFER_SMM_DISPATCH_ERROR    0x00\r
+#define COMM_BUFFER_SMM_DISPATCH_SUCCESS  0x01\r
+#define COMM_BUFFER_SMM_DISPATCH_RESTART  0x02\r
+\r
 ///\r
 /// Signature for the private structure shared between the SMM IPL and the SMM Core\r
 ///\r
index 0cfd746a07c7938e4f1b7ac4ec53591dbd36452d..fa6f2f1eb97087c124f244163b367eddfacfc579 100644 (file)
@@ -140,6 +140,20 @@ SmmIplReadyToLockEventNotify (
   @param  Event                 The Event that is being processed, not used.\r
   @param  Context               Event Context, not used.\r
 \r
+**/\r
+VOID\r
+EFIAPI\r
+SmmIplDxeDispatchEventNotify (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  );\r
+\r
+/**\r
+  Event notification that is fired when a GUIDed Event Group is signaled.\r
+\r
+  @param  Event                 The Event that is being processed, not used.\r
+  @param  Context               Event Context, not used.\r
+\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -175,6 +189,7 @@ typedef struct {
   EFI_GUID          *Guid;\r
   EFI_EVENT_NOTIFY  NotifyFunction;\r
   VOID              *NotifyContext;\r
+  EFI_TPL           NotifyTpl;\r
   EFI_EVENT         Event;\r
 } SMM_IPL_EVENT_NOTIFICATION;\r
 \r
@@ -240,39 +255,39 @@ SMM_IPL_EVENT_NOTIFICATION  mSmmIplEvents[] = {
   // the associated event is immediately signalled, so the notification function will be executed and the \r
   // SMM Configuration Protocol will be found if it is already in the handle database.\r
   //\r
-  { TRUE,  FALSE, &gEfiSmmConfigurationProtocolGuid,  SmmIplSmmConfigurationEventNotify, &gEfiSmmConfigurationProtocolGuid,  NULL },\r
+  { TRUE,  FALSE, &gEfiSmmConfigurationProtocolGuid,  SmmIplSmmConfigurationEventNotify, &gEfiSmmConfigurationProtocolGuid,  TPL_NOTIFY,   NULL },\r
   //\r
   // Declare protocl notification on DxeSmmReadyToLock protocols.  When this notification is etablished, \r
   // the associated event is immediately signalled, so the notification function will be executed and the \r
   // DXE SMM Ready To Lock Protocol will be found if it is already in the handle database.\r
   //\r
-  { TRUE,  TRUE,  &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify,      &gEfiDxeSmmReadyToLockProtocolGuid, NULL },\r
+  { TRUE,  TRUE,  &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify,      &gEfiDxeSmmReadyToLockProtocolGuid, TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on the DXE Dispatch Event Group.  This event is signaled by the DXE Core\r
   // each time the DXE Core dispatcher has completed its work.  When this event is signalled, the SMM Core\r
   // if notified, so the SMM Core can dispatch SMM drivers.\r
   //\r
-  { FALSE, TRUE,  &gEfiEventDxeDispatchGuid,          SmmIplGuidedEventNotify,           &gEfiEventDxeDispatchGuid,          NULL },\r
+  { FALSE, TRUE,  &gEfiEventDxeDispatchGuid,          SmmIplDxeDispatchEventNotify,      &gEfiEventDxeDispatchGuid,          TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on Ready To Boot Event Group.  This is an extra event notification that is\r
   // used to make sure SMRAM is locked before any boot options are processed.\r
   //\r
-  { FALSE, TRUE,  &gEfiEventReadyToBootGuid,          SmmIplReadyToLockEventNotify,      &gEfiEventReadyToBootGuid,          NULL },\r
+  { FALSE, TRUE,  &gEfiEventReadyToBootGuid,          SmmIplReadyToLockEventNotify,      &gEfiEventReadyToBootGuid,          TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on Legacy Boot Event Group.  This is used to inform the SMM Core that the platform \r
   // is performing a legacy boot operation, and that the UEFI environment is no longer available and the SMM Core \r
   // must guarantee that it does not access any UEFI related structures outside of SMRAM.\r
   //\r
-  { FALSE, FALSE, &gEfiEventLegacyBootGuid,           SmmIplGuidedEventNotify,           &gEfiEventLegacyBootGuid,           NULL },\r
+  { FALSE, FALSE, &gEfiEventLegacyBootGuid,           SmmIplGuidedEventNotify,           &gEfiEventLegacyBootGuid,           TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on SetVirtualAddressMap() Event Group.  This is used to convert gSmmCorePrivate \r
   // and mSmmControl2 from physical addresses to virtual addresses.\r
   //\r
-  { FALSE, FALSE, &gEfiEventVirtualAddressChangeGuid, SmmIplSetVirtualAddressNotify,     NULL,                               NULL },\r
+  { FALSE, FALSE, &gEfiEventVirtualAddressChangeGuid, SmmIplSetVirtualAddressNotify,     NULL,                               TPL_CALLBACK, NULL },\r
   //\r
   // Terminate the table of event notifications\r
   //\r
-  { FALSE, FALSE, NULL,                               NULL,                              NULL,                               NULL }\r
+  { FALSE, FALSE, NULL,                               NULL,                              NULL,                               TPL_CALLBACK, NULL }\r
 };\r
 \r
 /**\r
@@ -493,7 +508,7 @@ SmmCommunicationCommunicate (
 }\r
 \r
 /**\r
-  Event notification that is fired when DxeDispatch Event Group is signaled.\r
+  Event notification that is fired when GUIDed Event Group is signaled.\r
 \r
   @param  Event                 The Event that is being processed, not used.\r
   @param  Context               Event Context, not used.\r
@@ -523,6 +538,86 @@ SmmIplGuidedEventNotify (
   SmmCommunicationCommunicate (&mSmmCommunication, &CommunicateHeader, &Size);\r
 }\r
 \r
+/**\r
+  Event notification that is fired when DxeDispatch Event Group is signaled.\r
+\r
+  @param  Event                 The Event that is being processed, not used.\r
+  @param  Context               Event Context, not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmIplDxeDispatchEventNotify (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  EFI_SMM_COMMUNICATE_HEADER  CommunicateHeader;\r
+  UINTN                       Size;\r
+  EFI_STATUS                  Status;\r
+\r
+  //\r
+  // Keep calling the SMM Core Dispatcher until there is no request to restart it.\r
+  //\r
+  while (TRUE) {\r
+    //\r
+    // Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure\r
+    // Clear the buffer passed into the Software SMI.  This buffer will return\r
+    // the status of the SMM Core Dispatcher.\r
+    //\r
+    CopyGuid (&CommunicateHeader.HeaderGuid, (EFI_GUID *)Context);\r
+    CommunicateHeader.MessageLength = 1;\r
+    CommunicateHeader.Data[0] = 0;\r
+\r
+    //\r
+    // Generate the Software SMI and return the result\r
+    //\r
+    Size = sizeof (CommunicateHeader);\r
+    SmmCommunicationCommunicate (&mSmmCommunication, &CommunicateHeader, &Size);\r
+    \r
+    //\r
+    // Return if there is no request to restart the SMM Core Dispatcher\r
+    //\r
+    if (CommunicateHeader.Data[0] != COMM_BUFFER_SMM_DISPATCH_RESTART) {\r
+      return;\r
+    }\r
+      \r
+    //\r
+    // Attempt to reset SMRAM cacheability to UC\r
+    // Assume CPU AP is available at this time\r
+    //\r
+    Status = gDS->SetMemorySpaceAttributes(\r
+                    mSmramCacheBase, \r
+                    mSmramCacheSize,\r
+                    EFI_MEMORY_UC\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
+    }  \r
+\r
+    //\r
+    // Close all SMRAM ranges to protect SMRAM\r
+    //\r
+    Status = mSmmAccess->Close (mSmmAccess);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Print debug message that the SMRAM window is now closed.\r
+    //\r
+    DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n"));\r
+\r
+    //\r
+    // Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)\r
+    //\r
+    mSmmAccess->Lock (mSmmAccess);\r
+\r
+    //\r
+    // Print debug message that the SMRAM window is now locked\r
+    //\r
+    DEBUG ((DEBUG_INFO, "SMM IPL locked SMRAM window\n"));\r
+  }\r
+}\r
+\r
 /**\r
   Event notification that is fired every time a gEfiSmmConfigurationProtocol installs.\r
 \r
@@ -555,7 +650,7 @@ SmmIplSmmConfigurationEventNotify (
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Set flag to indicate that the SM< Entry Point has been registered which \r
+  // Set flag to indicate that the SMM Entry Point has been registered which \r
   // means that SMIs are now fully operational.\r
   //\r
   gSmmCorePrivate->SmmEntryPointRegistered = TRUE;\r
@@ -564,30 +659,6 @@ SmmIplSmmConfigurationEventNotify (
   // Print debug message showing SMM Core entry point address.\r
   //\r
   DEBUG ((DEBUG_INFO, "SMM IPL registered SMM Entry Point address %p\n", (VOID *)(UINTN)gSmmCorePrivate->SmmEntryPoint));\r
-\r
-  //\r
-  // Attempt to reset SMRAM cacheability to UC\r
-  // Assume CPU AP is available at this time\r
-  //\r
-  Status = gDS->SetMemorySpaceAttributes(\r
-                  mSmramCacheBase, \r
-                  mSmramCacheSize,\r
-                  EFI_MEMORY_UC\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
-  }  \r
-\r
-  //\r
-  // Close all SMRAM ranges to protect SMRAM\r
-  //\r
-  Status = mSmmAccess->Close (mSmmAccess);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Print debug message that the SMRAM window is now closed.\r
-  //\r
-  DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n"));\r
 }\r
 \r
 /**\r
@@ -1190,7 +1261,7 @@ SmmIplEntry (
     if (mSmmIplEvents[Index].Protocol) {\r
       mSmmIplEvents[Index].Event = EfiCreateProtocolNotifyEvent (\r
                                      mSmmIplEvents[Index].Guid,\r
-                                    TPL_CALLBACK,\r
+                                     mSmmIplEvents[Index].NotifyTpl,\r
                                      mSmmIplEvents[Index].NotifyFunction,\r
                                      mSmmIplEvents[Index].NotifyContext,\r
                                     &Registration\r
@@ -1198,7 +1269,7 @@ SmmIplEntry (
     } else {\r
       Status = gBS->CreateEventEx (\r
                       EVT_NOTIFY_SIGNAL,\r
-                      TPL_CALLBACK,\r
+                      mSmmIplEvents[Index].NotifyTpl,\r
                       mSmmIplEvents[Index].NotifyFunction,\r
                       mSmmIplEvents[Index].NotifyContext,\r
                       mSmmIplEvents[Index].Guid,\r