]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
Add comments for EFI_CACHE_SRAM_TYPE_DATA because of the inconsistency between CacheS...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Dispatcher / Dispatcher.c
index f1f940716cbd9950e3486c6d38e0e8eb469b7adc..68f5ef5d6463385c9de692a49db72ebf435dbc3d 100644 (file)
@@ -26,8 +26,8 @@
   Depex - Dependency Expresion.\r
   SOR   - Schedule On Request - Don't schedule if this bit is set.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -78,6 +78,7 @@ VOID            *mFwVolEventRegistration;
 //\r
 EFI_FV_FILETYPE mDxeFileTypes[] = {\r
   EFI_FV_FILETYPE_DRIVER,\r
+  EFI_FV_FILETYPE_COMBINED_SMM_DXE,\r
   EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\r
   EFI_FV_FILETYPE_DXE_CORE,\r
   EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\r
@@ -167,6 +168,7 @@ CoreFvToDevicePath (
                                 EFI_CORE_DRIVER_ENTRY so that the PE image can be\r
                                 read out of the FV at a later time.\r
   @param  DriverName            Name of driver to add to mDiscoveredList.\r
+  @param  Type                  Fv File Type of file to add to mDiscoveredList.\r
 \r
   @retval EFI_SUCCESS           If driver was added to the mDiscoveredList.\r
   @retval EFI_ALREADY_STARTED   The driver has already been started. Only one\r
@@ -178,7 +180,8 @@ EFI_STATUS
 CoreAddToDriverList (\r
   IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
   IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_GUID                        *DriverName,\r
+  IN  EFI_FV_FILETYPE                 Type\r
   );\r
 \r
 /**\r
@@ -332,9 +335,14 @@ CoreSchedule (
       DriverEntry->Dependent    = TRUE;\r
       CoreReleaseDispatcherLock ();\r
 \r
+      DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_SUCCESS\n", DriverName));\r
+      \r
       return EFI_SUCCESS;\r
     }\r
   }\r
+  \r
+  DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_NOT_FOUND\n", DriverName));\r
+  \r
   return EFI_NOT_FOUND;\r
 }\r
 \r
@@ -386,6 +394,23 @@ CoreTrust (
 }\r
 \r
 \r
+/**\r
+  An empty function to pass error checking of CreateEventEx ().\r
+\r
+  @param  Event                 Event whose notification function is being invoked.\r
+  @param  Context               Pointer to the notification function's context,\r
+                                which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CoreEmptyCallbackFunction (\r
+  IN EFI_EVENT                Event,\r
+  IN VOID                     *Context\r
+  )\r
+{\r
+  return;\r
+}\r
 \r
 /**\r
   This is the main Dispatcher for DXE and it exits when there are no more\r
@@ -412,6 +437,8 @@ CoreDispatcher (
   LIST_ENTRY                      *Link;\r
   EFI_CORE_DRIVER_ENTRY           *DriverEntry;\r
   BOOLEAN                         ReadyToRun;\r
+  EFI_EVENT                       DxeDispatchEvent;\r
+  \r
 \r
   if (gDispatcherRunning) {\r
     //\r
@@ -422,6 +449,17 @@ CoreDispatcher (
 \r
   gDispatcherRunning = TRUE;\r
 \r
+  Status = CoreCreateEventEx (\r
+             EVT_NOTIFY_SIGNAL,\r
+             TPL_NOTIFY,\r
+             CoreEmptyCallbackFunction,\r
+             NULL,\r
+             &gEfiEventDxeDispatchGuid,\r
+             &DxeDispatchEvent\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   ReturnStatus = EFI_NOT_FOUND;\r
   do {\r
@@ -441,7 +479,8 @@ CoreDispatcher (
       // Untrused to Scheduled it would have already been loaded so we may need to\r
       // skip the LoadImage\r
       //\r
-      if (DriverEntry->ImageHandle == NULL) {\r
+      if (DriverEntry->ImageHandle == NULL && !DriverEntry->IsFvImage) {\r
+        DEBUG ((DEBUG_INFO, "Loading driver %g\n", &DriverEntry->FileName));\r
         Status = CoreLoadImage (\r
                         FALSE,\r
                         gDxeCoreImageHandle,\r
@@ -493,25 +532,41 @@ CoreDispatcher (
       CoreReleaseDispatcherLock ();\r
 \r
  \r
-      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
-        EFI_PROGRESS_CODE,\r
-        FixedPcdGet32(PcdStatusCodeValueDxeDriverBegin),\r
-        &DriverEntry->ImageHandle,\r
-        sizeof (DriverEntry->ImageHandle)\r
-        );\r
-\r
-      Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);\r
-\r
-      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
-        EFI_PROGRESS_CODE,\r
-        FixedPcdGet32(PcdStatusCodeValueDxeDriverEnd),\r
-        &DriverEntry->ImageHandle,\r
-        sizeof (DriverEntry->ImageHandle)\r
-        );\r
+      if (DriverEntry->IsFvImage) {\r
+        //\r
+        // Produce a firmware volume block protocol for FvImage so it gets dispatched from. \r
+        //\r
+        Status = CoreProcessFvImageFile (DriverEntry->Fv, DriverEntry->FvHandle, &DriverEntry->FileName);\r
+      } else {\r
+        REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+          EFI_PROGRESS_CODE,\r
+          (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN),\r
+          &DriverEntry->ImageHandle,\r
+          sizeof (DriverEntry->ImageHandle)\r
+          );\r
+  \r
+        Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);\r
+  \r
+        REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+          EFI_PROGRESS_CODE,\r
+          (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END),\r
+          &DriverEntry->ImageHandle,\r
+          sizeof (DriverEntry->ImageHandle)\r
+          );\r
+      }\r
 \r
       ReturnStatus = EFI_SUCCESS;\r
     }\r
 \r
+    //\r
+    // Now DXE Dispatcher finished one round of dispatch, signal an event group\r
+    // so that SMM Dispatcher get chance to dispatch SMM Drivers which depend\r
+    // on UEFI protocols\r
+    //\r
+    if (!EFI_ERROR (ReturnStatus)) {\r
+      CoreSignalEvent (DxeDispatchEvent);\r
+    }\r
+\r
     //\r
     // Search DriverList for items to place on Scheduled Queue\r
     //\r
@@ -531,10 +586,21 @@ CoreDispatcher (
           CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
           ReadyToRun = TRUE;\r
         }\r
+      } else {\r
+        if (DriverEntry->Unrequested) {\r
+          DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+          DEBUG ((DEBUG_DISPATCH, "  SOR                                             = Not Requested\n"));\r
+          DEBUG ((DEBUG_DISPATCH, "  RESULT = FALSE\n"));\r
+        }\r
       }\r
     }\r
   } while (ReadyToRun);\r
 \r
+  //\r
+  // Close DXE dispatch Event\r
+  //\r
+  CoreCloseEvent (DxeDispatchEvent);\r
+\r
   gDispatcherRunning = FALSE;\r
 \r
   return ReturnStatus;\r
@@ -565,12 +631,17 @@ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
   //\r
   for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
     DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
-    if (DriverEntry->Before && DriverEntry->Dependent) {\r
+    if (DriverEntry->Before && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {\r
+      DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+      DEBUG ((DEBUG_DISPATCH, "  BEFORE FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
       if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
         //\r
         // Recursively process BEFORE\r
         //\r
+        DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));\r
         CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
+      } else {\r
+        DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));\r
       }\r
     }\r
   }\r
@@ -591,12 +662,17 @@ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
   //\r
   for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
     DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
-    if (DriverEntry->After && DriverEntry->Dependent) {\r
+    if (DriverEntry->After && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {\r
+      DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+      DEBUG ((DEBUG_DISPATCH, "  AFTER FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
       if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
         //\r
         // Recursively process AFTER\r
         //\r
+        DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));\r
         CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
+      } else {\r
+        DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));\r
       }\r
     }\r
   }\r
@@ -717,6 +793,7 @@ CoreFvToDevicePath (
                                 EFI_CORE_DRIVER_ENTRY so that the PE image can be\r
                                 read out of the FV at a later time.\r
   @param  DriverName            Name of driver to add to mDiscoveredList.\r
+  @param  Type                  Fv File Type of file to add to mDiscoveredList.\r
 \r
   @retval EFI_SUCCESS           If driver was added to the mDiscoveredList.\r
   @retval EFI_ALREADY_STARTED   The driver has already been started. Only one\r
@@ -728,7 +805,8 @@ EFI_STATUS
 CoreAddToDriverList (\r
   IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
   IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_GUID                        *DriverName,\r
+  IN  EFI_FV_FILETYPE                 Type\r
   )\r
 {\r
   EFI_CORE_DRIVER_ENTRY               *DriverEntry;\r
@@ -740,6 +818,9 @@ CoreAddToDriverList (
   //\r
   DriverEntry = AllocateZeroPool (sizeof (EFI_CORE_DRIVER_ENTRY));\r
   ASSERT (DriverEntry != NULL);\r
+  if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+    DriverEntry->IsFvImage = TRUE;\r
+  }\r
 \r
   DriverEntry->Signature        = EFI_CORE_DRIVER_ENTRY_SIGNATURE;\r
   CopyGuid (&DriverEntry->FileName, DriverName);\r
@@ -844,9 +925,12 @@ CoreProcessFvImageFile (
     // FvImage should be at its required alignment.\r
     //\r
     FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;\r
+    //\r
+    // Get FvHeader alignment\r
+    //\r
     FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
     //\r
-    // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
+    // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value. \r
     //\r
     if (FvAlignment < 8) {\r
       FvAlignment = 8;\r
@@ -936,7 +1020,7 @@ CoreFwVolEventProtocolNotify (
   LIST_ENTRY                    *Link;\r
   UINT32                        AuthenticationStatus;\r
   UINTN                         SizeOfBuffer;\r
-\r
+  VOID                          *DepexBuffer;\r
 \r
   while (TRUE) {\r
     BufferSize = sizeof (EFI_HANDLE);\r
@@ -961,25 +1045,15 @@ CoreFwVolEventProtocolNotify (
       continue;\r
     }\r
 \r
-    Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, (VOID **)&Fv);\r
-    if (EFI_ERROR (Status)) {\r
-      //\r
-      // If no dispatch protocol then skip, but do not marked as being processed as it\r
-      // may show up later.\r
-      //\r
-      continue;\r
-    }\r
-\r
     //\r
     // Since we are about to process this Fv mark it as processed.\r
     //\r
     FvIsBeingProcesssed (FvHandle);\r
 \r
     Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);\r
-    if (EFI_ERROR (Status)) {\r
+    if (EFI_ERROR (Status) || Fv == NULL) {\r
       //\r
-      // The Handle has a FirmwareVolumeDispatch protocol and should also contiain\r
-      // a FirmwareVolume protocol thus we should never get here.\r
+      // FvHandle must have Firmware Volume2 protocol thus we should never get here.\r
       //\r
       ASSERT (FALSE);\r
       continue;\r
@@ -1060,17 +1134,84 @@ CoreFwVolEventProtocolNotify (
             if (FvFoundInHobFv2 (FvHandle, &NameGuid)) {\r
               continue;\r
             }\r
+\r
             //\r
-            // Found a firmware volume image. Produce a firmware volume block\r
-            // protocol for it so it gets dispatched from. This is usually a\r
-            // capsule.\r
+            // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has PEI depex section.\r
             //\r
-            CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);\r
+            DepexBuffer  = NULL;\r
+            SizeOfBuffer = 0;\r
+            Status = Fv->ReadSection (\r
+                           Fv,\r
+                           &NameGuid,\r
+                           EFI_SECTION_PEI_DEPEX,\r
+                           0,\r
+                           &DepexBuffer,\r
+                           &SizeOfBuffer,\r
+                           &AuthenticationStatus\r
+                           );\r
+            if (!EFI_ERROR (Status)) {\r
+              //\r
+              // If PEI depex section is found, this FV image will be ignored in DXE phase.\r
+              // Now, DxeCore doesn't support FV image with more one type DEPEX section.\r
+              //\r
+              FreePool (DepexBuffer);\r
+              continue;\r
+            }\r
+\r
+            //\r
+            // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has SMM depex section.\r
+            //\r
+            DepexBuffer  = NULL;\r
+            SizeOfBuffer = 0;\r
+            Status = Fv->ReadSection (\r
+                           Fv,\r
+                           &NameGuid,\r
+                           EFI_SECTION_SMM_DEPEX,\r
+                           0,\r
+                           &DepexBuffer,\r
+                           &SizeOfBuffer,\r
+                           &AuthenticationStatus\r
+                           );\r
+            if (!EFI_ERROR (Status)) {\r
+              //\r
+              // If SMM depex section is found, this FV image will be ignored in DXE phase.\r
+              // Now, DxeCore doesn't support FV image with more one type DEPEX section.\r
+              //\r
+              FreePool (DepexBuffer);\r
+              continue;\r
+            }\r
+\r
+            //\r
+            // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has DXE depex section.\r
+            //\r
+            DepexBuffer  = NULL;\r
+            SizeOfBuffer = 0;\r
+            Status = Fv->ReadSection (\r
+                           Fv,\r
+                           &NameGuid,\r
+                           EFI_SECTION_DXE_DEPEX,\r
+                           0,\r
+                           &DepexBuffer,\r
+                           &SizeOfBuffer,\r
+                           &AuthenticationStatus\r
+                           );\r
+            if (EFI_ERROR (Status)) {\r
+              //\r
+              // If no depex section, produce a firmware volume block protocol for it so it gets dispatched from. \r
+              //\r
+              CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);\r
+            } else {\r
+              //\r
+              // If depex section is found, this FV image will be dispatched until its depex is evaluated to TRUE.\r
+              //\r
+              FreePool (DepexBuffer);\r
+              CoreAddToDriverList (Fv, FvHandle, &NameGuid, Type);\r
+            }\r
           } else {\r
             //\r
             // Transition driver from Undiscovered to Discovered state\r
             //\r
-            CoreAddToDriverList (Fv, FvHandle, &NameGuid);\r
+            CoreAddToDriverList (Fv, FvHandle, &NameGuid, Type);\r
           }\r
         }\r
       } while (!EFI_ERROR (GetNextFileStatus));\r
@@ -1100,23 +1241,24 @@ CoreFwVolEventProtocolNotify (
     // drivers not in the current FV and these must be skipped since the a priori list\r
     // is only valid for the FV that it resided in.\r
     //\r
-    CoreAcquireDispatcherLock ();\r
 \r
     for (Index = 0; Index < AprioriEntryCount; Index++) {\r
       for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
         DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
         if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&\r
             (FvHandle == DriverEntry->FvHandle)) {\r
+          CoreAcquireDispatcherLock ();\r
           DriverEntry->Dependent = FALSE;\r
           DriverEntry->Scheduled = TRUE;\r
           InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);\r
+          CoreReleaseDispatcherLock ();\r
+          DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+          DEBUG ((DEBUG_DISPATCH, "  RESULT = TRUE (Apriori)\n"));\r
           break;\r
         }\r
       }\r
     }\r
 \r
-    CoreReleaseDispatcherLock ();\r
-\r
     //\r
     // Free data allocated by Fv->ReadSection ()\r
     //\r