]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Dispatcher / Dispatcher.c
index 5fbb2d442d2d4d2406ce55aa98ba7bc8c5c5e686..fb9ae3ce78dacacead90ed30f2fcc3c527f26670 100644 (file)
   Depex - Dependency Expresion.\r
   SOR   - Schedule On Request - Don't schedule if this bit is set.\r
 \r
-Copyright (c) 2006 - 2009, Intel Corporation. <BR>\r
-All rights reserved. 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
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -61,7 +55,6 @@ LIST_ENTRY  mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList);
 //\r
 EFI_LOCK  mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);\r
 \r
-\r
 //\r
 // Flag for the DXE Dispacher.  TRUE if dispatcher is execuing.\r
 //\r
@@ -70,13 +63,13 @@ BOOLEAN  gDispatcherRunning = FALSE;
 //\r
 // Module globals to manage the FwVol registration notification event\r
 //\r
-EFI_EVENT       mFwVolEvent;\r
-VOID            *mFwVolEventRegistration;\r
+EFI_EVENT  mFwVolEvent;\r
+VOID       *mFwVolEventRegistration;\r
 \r
 //\r
 // List of file types supported by dispatcher\r
 //\r
-EFI_FV_FILETYPE mDxeFileTypes[] = {\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
@@ -85,16 +78,16 @@ EFI_FV_FILETYPE mDxeFileTypes[] = {
 };\r
 \r
 typedef struct {\r
-  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   File;\r
-  EFI_DEVICE_PATH_PROTOCOL            End;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH    File;\r
+  EFI_DEVICE_PATH_PROTOCOL             End;\r
 } FV_FILEPATH_DEVICE_PATH;\r
 \r
-FV_FILEPATH_DEVICE_PATH mFvDevicePath;\r
-\r
+FV_FILEPATH_DEVICE_PATH  mFvDevicePath;\r
 \r
 //\r
 // Function Prototypes\r
 //\r
+\r
 /**\r
   Insert InsertedDriverEntry onto the mScheduledQueue. To do this you\r
   must add any driver with a before dependency on InsertedDriverEntry first.\r
@@ -108,7 +101,7 @@ FV_FILEPATH_DEVICE_PATH mFvDevicePath;
 **/\r
 VOID\r
 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (\r
-  IN  EFI_CORE_DRIVER_ENTRY   *InsertedDriverEntry\r
+  IN  EFI_CORE_DRIVER_ENTRY  *InsertedDriverEntry\r
   );\r
 \r
 /**\r
@@ -131,8 +124,8 @@ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
 VOID\r
 EFIAPI\r
 CoreFwVolEventProtocolNotify (\r
-  IN  EFI_EVENT       Event,\r
-  IN  VOID            *Context\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
   );\r
 \r
 /**\r
@@ -150,9 +143,9 @@ CoreFwVolEventProtocolNotify (
 **/\r
 EFI_DEVICE_PATH_PROTOCOL *\r
 CoreFvToDevicePath (\r
-  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
-  IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,\r
+  IN  EFI_HANDLE                     FvHandle,\r
+  IN  EFI_GUID                       *DriverName\r
   );\r
 \r
 /**\r
@@ -168,6 +161,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
@@ -177,31 +171,30 @@ CoreFvToDevicePath (
 **/\r
 EFI_STATUS\r
 CoreAddToDriverList (\r
-  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
-  IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,\r
+  IN  EFI_HANDLE                     FvHandle,\r
+  IN  EFI_GUID                       *DriverName,\r
+  IN  EFI_FV_FILETYPE                Type\r
   );\r
 \r
 /**\r
-  Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.\r
+  Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).\r
 \r
   @param  Fv                    The FIRMWARE_VOLUME protocol installed on the FV.\r
   @param  FvHandle              The handle which FVB protocol installed on.\r
-  @param  DriverName            The driver guid specified.\r
+  @param  FileName              The file name guid specified.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  No enough memory or other resource.\r
-  @retval EFI_VOLUME_CORRUPTED  Corrupted volume.\r
   @retval EFI_SUCCESS           Function successfully returned.\r
 \r
 **/\r
 EFI_STATUS\r
 CoreProcessFvImageFile (\r
-  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
-  IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,\r
+  IN  EFI_HANDLE                     FvHandle,\r
+  IN  EFI_GUID                       *FileName\r
   );\r
 \r
-\r
 /**\r
   Enter critical section by gaining lock on mDispatcherLock.\r
 \r
@@ -214,7 +207,6 @@ CoreAcquireDispatcherLock (
   CoreAcquireLock (&mDispatcherLock);\r
 }\r
 \r
-\r
 /**\r
   Exit critical section by releasing lock on mDispatcherLock.\r
 \r
@@ -227,7 +219,6 @@ CoreReleaseDispatcherLock (
   CoreReleaseLock (&mDispatcherLock);\r
 }\r
 \r
-\r
 /**\r
   Read Depex and pre-process the Depex for Before and After. If Section Extraction\r
   protocol returns an error via ReadSection defer the reading of the Depex.\r
@@ -242,30 +233,29 @@ CoreReleaseDispatcherLock (
 **/\r
 EFI_STATUS\r
 CoreGetDepexSectionAndPreProccess (\r
-  IN  EFI_CORE_DRIVER_ENTRY   *DriverEntry\r
+  IN  EFI_CORE_DRIVER_ENTRY  *DriverEntry\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_SECTION_TYPE              SectionType;\r
-  UINT32                        AuthenticationStatus;\r
-  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
-\r
+  EFI_STATUS                     Status;\r
+  EFI_SECTION_TYPE               SectionType;\r
+  UINT32                         AuthenticationStatus;\r
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;\r
 \r
   Fv = DriverEntry->Fv;\r
 \r
   //\r
   // Grab Depex info, it will never be free'ed.\r
   //\r
-  SectionType         = EFI_SECTION_DXE_DEPEX;\r
-  Status = Fv->ReadSection (\r
-                DriverEntry->Fv,\r
-                &DriverEntry->FileName,\r
-                SectionType,\r
-                0,\r
-                &DriverEntry->Depex,\r
-                (UINTN *)&DriverEntry->DepexSize,\r
-                &AuthenticationStatus\r
-                );\r
+  SectionType = EFI_SECTION_DXE_DEPEX;\r
+  Status      = Fv->ReadSection (\r
+                      DriverEntry->Fv,\r
+                      &DriverEntry->FileName,\r
+                      SectionType,\r
+                      0,\r
+                      &DriverEntry->Depex,\r
+                      (UINTN *)&DriverEntry->DepexSize,\r
+                      &AuthenticationStatus\r
+                      );\r
   if (EFI_ERROR (Status)) {\r
     if (Status == EFI_PROTOCOL_ERROR) {\r
       //\r
@@ -276,8 +266,8 @@ CoreGetDepexSectionAndPreProccess (
       //\r
       // If no Depex assume UEFI 2.0 driver model\r
       //\r
-      DriverEntry->Depex = NULL;\r
-      DriverEntry->Dependent = TRUE;\r
+      DriverEntry->Depex              = NULL;\r
+      DriverEntry->Dependent          = TRUE;\r
       DriverEntry->DepexProtocolError = FALSE;\r
     }\r
   } else {\r
@@ -292,7 +282,6 @@ CoreGetDepexSectionAndPreProccess (
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Check every driver and locate a matching one. If the driver is found, the Unrequested\r
   state flag is cleared.\r
@@ -314,32 +303,36 @@ CoreSchedule (
   IN  EFI_GUID    *DriverName\r
   )\r
 {\r
-  LIST_ENTRY            *Link;\r
-  EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
+  LIST_ENTRY             *Link;\r
+  EFI_CORE_DRIVER_ENTRY  *DriverEntry;\r
 \r
   //\r
   // Check every driver\r
   //\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->FvHandle == FirmwareVolumeHandle &&\r
+    DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
+    if ((DriverEntry->FvHandle == FirmwareVolumeHandle) &&\r
         DriverEntry->Unrequested &&\r
-        CompareGuid (DriverName, &DriverEntry->FileName)) {\r
+        CompareGuid (DriverName, &DriverEntry->FileName))\r
+    {\r
       //\r
       // Move the driver from the Unrequested to the Dependent state\r
       //\r
       CoreAcquireDispatcherLock ();\r
-      DriverEntry->Unrequested  = FALSE;\r
-      DriverEntry->Dependent    = TRUE;\r
+      DriverEntry->Unrequested = FALSE;\r
+      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
-  return EFI_NOT_FOUND;\r
-}\r
 \r
+  DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_NOT_FOUND\n", DriverName));\r
 \r
+  return EFI_NOT_FOUND;\r
+}\r
 \r
 /**\r
   Convert a driver from the Untrused back to the Scheduled state.\r
@@ -360,17 +353,18 @@ CoreTrust (
   IN  EFI_GUID    *DriverName\r
   )\r
 {\r
-  LIST_ENTRY            *Link;\r
-  EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
+  LIST_ENTRY             *Link;\r
+  EFI_CORE_DRIVER_ENTRY  *DriverEntry;\r
 \r
   //\r
   // Check every driver\r
   //\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->FvHandle == FirmwareVolumeHandle &&\r
+    DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
+    if ((DriverEntry->FvHandle == FirmwareVolumeHandle) &&\r
         DriverEntry->Untrusted &&\r
-        CompareGuid (DriverName, &DriverEntry->FileName)) {\r
+        CompareGuid (DriverName, &DriverEntry->FileName))\r
+    {\r
       //\r
       // Transition driver from Untrusted to Scheduled state.\r
       //\r
@@ -383,26 +377,8 @@ CoreTrust (
       return EFI_SUCCESS;\r
     }\r
   }\r
-  return EFI_NOT_FOUND;\r
-}\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
-EmptyFuntion (\r
-  IN EFI_EVENT                Event,\r
-  IN VOID                     *Context\r
-  )\r
-{\r
-  return;\r
+  return EFI_NOT_FOUND;\r
 }\r
 \r
 /**\r
@@ -425,13 +401,14 @@ CoreDispatcher (
   VOID\r
   )\r
 {\r
-  EFI_STATUS                      Status;\r
-  EFI_STATUS                      ReturnStatus;\r
-  LIST_ENTRY                      *Link;\r
-  EFI_CORE_DRIVER_ENTRY           *DriverEntry;\r
-  BOOLEAN                         ReadyToRun;\r
-  EFI_EVENT                       DxeDispatchEvent;\r
-  \r
+  EFI_STATUS             Status;\r
+  EFI_STATUS             ReturnStatus;\r
+  LIST_ENTRY             *Link;\r
+  EFI_CORE_DRIVER_ENTRY  *DriverEntry;\r
+  BOOLEAN                ReadyToRun;\r
+  EFI_EVENT              DxeDispatchEvent;\r
+\r
+  PERF_FUNCTION_BEGIN ();\r
 \r
   if (gDispatcherRunning) {\r
     //\r
@@ -445,7 +422,7 @@ CoreDispatcher (
   Status = CoreCreateEventEx (\r
              EVT_NOTIFY_SIGNAL,\r
              TPL_NOTIFY,\r
-             EmptyFuntion,\r
+             EfiEventEmptyFunction,\r
              NULL,\r
              &gEfiEventDxeDispatchGuid,\r
              &DxeDispatchEvent\r
@@ -472,16 +449,16 @@ 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
-                        DriverEntry->FvFileDevicePath,\r
-                        NULL,\r
-                        0,\r
-                        &DriverEntry->ImageHandle\r
-                        );\r
+                   FALSE,\r
+                   gDxeCoreImageHandle,\r
+                   DriverEntry->FvFileDevicePath,\r
+                   NULL,\r
+                   0,\r
+                   &DriverEntry->ImageHandle\r
+                   );\r
 \r
         //\r
         // Update the driver state to reflect that it's been loaded\r
@@ -501,7 +478,7 @@ CoreDispatcher (
             //\r
             // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned\r
             //\r
-            DriverEntry->Initialized  = TRUE;\r
+            DriverEntry->Initialized = TRUE;\r
           }\r
 \r
           DriverEntry->Scheduled = FALSE;\r
@@ -518,32 +495,48 @@ CoreDispatcher (
 \r
       CoreAcquireDispatcherLock ();\r
 \r
-      DriverEntry->Scheduled    = FALSE;\r
-      DriverEntry->Initialized  = TRUE;\r
+      DriverEntry->Scheduled   = FALSE;\r
+      DriverEntry->Initialized = TRUE;\r
       RemoveEntryList (&DriverEntry->ScheduledLink);\r
 \r
       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
+        ASSERT (DriverEntry->ImageHandle != NULL);\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
@@ -551,7 +544,7 @@ CoreDispatcher (
     for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
       DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
 \r
-      if (DriverEntry->DepexProtocolError){\r
+      if (DriverEntry->DepexProtocolError) {\r
         //\r
         // If Section Extraction Protocol did not let the Depex be read before retry the read\r
         //\r
@@ -563,17 +556,14 @@ 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
-\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
   } while (ReadyToRun);\r
 \r
   //\r
@@ -583,10 +573,11 @@ CoreDispatcher (
 \r
   gDispatcherRunning = FALSE;\r
 \r
+  PERF_FUNCTION_END ();\r
+\r
   return ReturnStatus;\r
 }\r
 \r
-\r
 /**\r
   Insert InsertedDriverEntry onto the mScheduledQueue. To do this you\r
   must add any driver with a before dependency on InsertedDriverEntry first.\r
@@ -600,23 +591,28 @@ CoreDispatcher (
 **/\r
 VOID\r
 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (\r
-  IN  EFI_CORE_DRIVER_ENTRY   *InsertedDriverEntry\r
+  IN  EFI_CORE_DRIVER_ENTRY  *InsertedDriverEntry\r
   )\r
 {\r
-  LIST_ENTRY            *Link;\r
-  EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
+  LIST_ENTRY             *Link;\r
+  EFI_CORE_DRIVER_ENTRY  *DriverEntry;\r
 \r
   //\r
   // Process Before Dependency\r
   //\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
+    DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\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
@@ -636,19 +632,23 @@ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
   // Process After Dependency\r
   //\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
+    DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\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
 }\r
 \r
-\r
 /**\r
   Return TRUE if the Fv has been processed, FALSE if not.\r
 \r
@@ -660,48 +660,131 @@ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
 **/\r
 BOOLEAN\r
 FvHasBeenProcessed (\r
-  IN  EFI_HANDLE      FvHandle\r
+  IN  EFI_HANDLE  FvHandle\r
   )\r
 {\r
-  LIST_ENTRY      *Link;\r
-  KNOWN_HANDLE    *KnownHandle;\r
+  LIST_ENTRY    *Link;\r
+  KNOWN_HANDLE  *KnownHandle;\r
 \r
   for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {\r
-    KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);\r
+    KnownHandle = CR (Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);\r
     if (KnownHandle->Handle == FvHandle) {\r
       return TRUE;\r
     }\r
   }\r
+\r
   return FALSE;\r
 }\r
 \r
-\r
 /**\r
   Remember that Fv protocol on FvHandle has had it's drivers placed on the\r
-  mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are\r
-  never removed/freed from the mFvHandleList.\r
+  mDiscoveredList. This fucntion adds entries on the mFvHandleList if new\r
+  entry is different from one in mFvHandleList by checking FvImage Guid.\r
+  Items are never removed/freed from the mFvHandleList.\r
 \r
   @param  FvHandle              The handle of a FV that has been processed\r
 \r
+  @return A point to new added FvHandle entry. If FvHandle with the same FvImage guid\r
+          has been added, NULL will return.\r
+\r
 **/\r
-VOID\r
-FvIsBeingProcesssed (\r
-  IN  EFI_HANDLE    FvHandle\r
+KNOWN_HANDLE *\r
+FvIsBeingProcessed (\r
+  IN  EFI_HANDLE  FvHandle\r
   )\r
 {\r
-  KNOWN_HANDLE  *KnownHandle;\r
+  EFI_STATUS                          Status;\r
+  EFI_GUID                            FvNameGuid;\r
+  BOOLEAN                             FvNameGuidIsFound;\r
+  UINT32                              ExtHeaderOffset;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
+  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
+  EFI_FV_BLOCK_MAP_ENTRY              *BlockMap;\r
+  UINTN                               LbaOffset;\r
+  UINTN                               Index;\r
+  EFI_LBA                             LbaIndex;\r
+  LIST_ENTRY                          *Link;\r
+  KNOWN_HANDLE                        *KnownHandle;\r
+\r
+  FwVolHeader = NULL;\r
+\r
+  //\r
+  // Get the FirmwareVolumeBlock protocol on that handle\r
+  //\r
+  FvNameGuidIsFound = FALSE;\r
+  Status            = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Get the full FV header based on FVB protocol.\r
+    //\r
+    ASSERT (Fvb != NULL);\r
+    Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
+    if (!EFI_ERROR (Status)) {\r
+      ASSERT (FwVolHeader != NULL);\r
+      if (VerifyFvHeaderChecksum (FwVolHeader) && (FwVolHeader->ExtHeaderOffset != 0)) {\r
+        ExtHeaderOffset = (UINT32)FwVolHeader->ExtHeaderOffset;\r
+        BlockMap        = FwVolHeader->BlockMap;\r
+        LbaIndex        = 0;\r
+        LbaOffset       = 0;\r
+        //\r
+        // Find LbaIndex and LbaOffset for FV extension header based on BlockMap.\r
+        //\r
+        while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
+          for (Index = 0; Index < BlockMap->NumBlocks && ExtHeaderOffset >= BlockMap->Length; Index++) {\r
+            ExtHeaderOffset -= BlockMap->Length;\r
+            LbaIndex++;\r
+          }\r
+\r
+          //\r
+          // Check whether FvExtHeader is crossing the multi block range.\r
+          //\r
+          if (Index < BlockMap->NumBlocks) {\r
+            LbaOffset = ExtHeaderOffset;\r
+            break;\r
+          }\r
+\r
+          BlockMap++;\r
+        }\r
 \r
-  KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));\r
+        //\r
+        // Read FvNameGuid from FV extension header.\r
+        //\r
+        Status = ReadFvbData (Fvb, &LbaIndex, &LbaOffset, sizeof (FvNameGuid), (UINT8 *)&FvNameGuid);\r
+        if (!EFI_ERROR (Status)) {\r
+          FvNameGuidIsFound = TRUE;\r
+        }\r
+      }\r
+\r
+      CoreFreePool (FwVolHeader);\r
+    }\r
+  }\r
+\r
+  if (FvNameGuidIsFound) {\r
+    //\r
+    // Check whether the FV image with the found FvNameGuid has been processed.\r
+    //\r
+    for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {\r
+      KnownHandle = CR (Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);\r
+      if (CompareGuid (&FvNameGuid, &KnownHandle->FvNameGuid)) {\r
+        DEBUG ((DEBUG_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, &FvNameGuid));\r
+        return NULL;\r
+      }\r
+    }\r
+  }\r
+\r
+  KnownHandle = AllocateZeroPool (sizeof (KNOWN_HANDLE));\r
   ASSERT (KnownHandle != NULL);\r
 \r
   KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;\r
-  KnownHandle->Handle = FvHandle;\r
+  KnownHandle->Handle    = FvHandle;\r
+  if (FvNameGuidIsFound) {\r
+    CopyGuid (&KnownHandle->FvNameGuid, &FvNameGuid);\r
+  }\r
+\r
   InsertTailList (&mFvHandleList, &KnownHandle->Link);\r
+  return KnownHandle;\r
 }\r
 \r
-\r
-\r
-\r
 /**\r
   Convert FvHandle and DriverName into an EFI device path\r
 \r
@@ -717,14 +800,14 @@ FvIsBeingProcesssed (
 **/\r
 EFI_DEVICE_PATH_PROTOCOL *\r
 CoreFvToDevicePath (\r
-  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
-  IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,\r
+  IN  EFI_HANDLE                     FvHandle,\r
+  IN  EFI_GUID                       *DriverName\r
   )\r
 {\r
-  EFI_STATUS                          Status;\r
-  EFI_DEVICE_PATH_PROTOCOL            *FvDevicePath;\r
-  EFI_DEVICE_PATH_PROTOCOL            *FileNameDevicePath;\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FvDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FileNameDevicePath;\r
 \r
   //\r
   // Remember the device path of the FV\r
@@ -740,16 +823,14 @@ CoreFvToDevicePath (
     SetDevicePathEndNode (&mFvDevicePath.End);\r
 \r
     FileNameDevicePath = AppendDevicePath (\r
-                            FvDevicePath,\r
-                            (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath\r
-                            );\r
+                           FvDevicePath,\r
+                           (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath\r
+                           );\r
   }\r
 \r
   return FileNameDevicePath;\r
 }\r
 \r
-\r
-\r
 /**\r
   Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,\r
   and initilize any state variables. Read the Depex from the FV and store it\r
@@ -763,6 +844,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
@@ -772,13 +854,13 @@ CoreFvToDevicePath (
 **/\r
 EFI_STATUS\r
 CoreAddToDriverList (\r
-  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
-  IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,\r
+  IN  EFI_HANDLE                     FvHandle,\r
+  IN  EFI_GUID                       *DriverName,\r
+  IN  EFI_FV_FILETYPE                Type\r
   )\r
 {\r
-  EFI_CORE_DRIVER_ENTRY               *DriverEntry;\r
-\r
+  EFI_CORE_DRIVER_ENTRY  *DriverEntry;\r
 \r
   //\r
   // Create the Driver Entry for the list. ZeroPool initializes lots of variables to\r
@@ -786,8 +868,11 @@ 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
+  DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE;\r
   CopyGuid (&DriverEntry->FileName, DriverName);\r
   DriverEntry->FvHandle         = FvHandle;\r
   DriverEntry->Fv               = Fv;\r
@@ -804,12 +889,11 @@ CoreAddToDriverList (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is\r
   described by a EFI_HOB_FIRMWARE_VOLUME2 Hob.\r
 \r
-  @param  FvHandle              The handle which FVB protocol installed on.\r
+  @param  FvNameGuid            The FV image guid specified.\r
   @param  DriverName            The driver guid specified.\r
 \r
   @retval TRUE                  This file is found in a EFI_HOB_FIRMWARE_VOLUME2\r
@@ -819,129 +903,280 @@ CoreAddToDriverList (
 **/\r
 BOOLEAN\r
 FvFoundInHobFv2 (\r
-  IN  EFI_HANDLE                      FvHandle,\r
-  IN  CONST EFI_GUID                  *DriverName\r
+  IN  CONST EFI_GUID  *FvNameGuid,\r
+  IN  CONST EFI_GUID  *DriverName\r
   )\r
 {\r
-  EFI_PEI_HOB_POINTERS                HobFv2;\r
+  EFI_PEI_HOB_POINTERS  HobFv2;\r
 \r
   HobFv2.Raw = GetHobList ();\r
 \r
   while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {\r
-    if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName)) {\r
+    //\r
+    // Compare parent FvNameGuid and FileGuid both.\r
+    //\r
+    if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName) &&\r
+        CompareGuid (FvNameGuid, &HobFv2.FirmwareVolume2->FvName))\r
+    {\r
       return TRUE;\r
     }\r
+\r
     HobFv2.Raw = GET_NEXT_HOB (HobFv2);\r
   }\r
 \r
   return FALSE;\r
 }\r
 \r
+/**\r
+  Find USED_SIZE FV_EXT_TYPE entry in FV extension header and get the FV used size.\r
+\r
+  @param[in]  FvHeader      Pointer to FV header.\r
+  @param[out] FvUsedSize    Pointer to FV used size returned,\r
+                            only valid if USED_SIZE FV_EXT_TYPE entry is found.\r
+  @param[out] EraseByte     Pointer to erase byte returned,\r
+                            only valid if USED_SIZE FV_EXT_TYPE entry is found.\r
 \r
+  @retval TRUE              USED_SIZE FV_EXT_TYPE entry is found,\r
+                            FV used size and erase byte are returned.\r
+  @retval FALSE             No USED_SIZE FV_EXT_TYPE entry found.\r
+\r
+**/\r
+BOOLEAN\r
+GetFvUsedSize (\r
+  IN EFI_FIRMWARE_VOLUME_HEADER  *FvHeader,\r
+  OUT UINT32                     *FvUsedSize,\r
+  OUT UINT8                      *EraseByte\r
+  )\r
+{\r
+  UINT16                                        ExtHeaderOffset;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER                *ExtHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_ENTRY                 *ExtEntryList;\r
+  EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE  *ExtEntryUsedSize;\r
+\r
+  ExtHeaderOffset = ReadUnaligned16 (&FvHeader->ExtHeaderOffset);\r
+  if (ExtHeaderOffset != 0) {\r
+    ExtHeader    = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + ExtHeaderOffset);\r
+    ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)(ExtHeader + 1);\r
+    while ((UINTN)ExtEntryList < ((UINTN)ExtHeader + ReadUnaligned32 (&ExtHeader->ExtHeaderSize))) {\r
+      if (ReadUnaligned16 (&ExtEntryList->ExtEntryType) == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {\r
+        //\r
+        // USED_SIZE FV_EXT_TYPE entry is found.\r
+        //\r
+        ExtEntryUsedSize = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)ExtEntryList;\r
+        *FvUsedSize      = ReadUnaligned32 (&ExtEntryUsedSize->UsedSize);\r
+        if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ERASE_POLARITY) != 0) {\r
+          *EraseByte = 0xFF;\r
+        } else {\r
+          *EraseByte = 0;\r
+        }\r
+\r
+        DEBUG ((\r
+          DEBUG_INFO,\r
+          "FV at 0x%x has 0x%x used size, and erase byte is 0x%02x\n",\r
+          FvHeader,\r
+          *FvUsedSize,\r
+          *EraseByte\r
+          ));\r
+        return TRUE;\r
+      }\r
+\r
+      ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)\r
+                     ((UINT8 *)ExtEntryList + ReadUnaligned16 (&ExtEntryList->ExtEntrySize));\r
+    }\r
+  }\r
+\r
+  //\r
+  // No USED_SIZE FV_EXT_TYPE entry found.\r
+  //\r
+  return FALSE;\r
+}\r
 \r
 /**\r
-  Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.\r
+  Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).\r
 \r
   @param  Fv                    The FIRMWARE_VOLUME protocol installed on the FV.\r
   @param  FvHandle              The handle which FVB protocol installed on.\r
-  @param  DriverName            The driver guid specified.\r
+  @param  FileName              The file name guid specified.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  No enough memory or other resource.\r
-  @retval EFI_VOLUME_CORRUPTED  Corrupted volume.\r
   @retval EFI_SUCCESS           Function successfully returned.\r
 \r
 **/\r
 EFI_STATUS\r
 CoreProcessFvImageFile (\r
-  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,\r
-  IN  EFI_HANDLE                      FvHandle,\r
-  IN  EFI_GUID                        *DriverName\r
+  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,\r
+  IN  EFI_HANDLE                     FvHandle,\r
+  IN  EFI_GUID                       *FileName\r
   )\r
 {\r
-  EFI_STATUS                          Status;\r
-  EFI_SECTION_TYPE                    SectionType;\r
-  UINT32                              AuthenticationStatus;\r
-  VOID                                *Buffer;\r
-  VOID                                *AlignedBuffer;\r
-  UINTN                               BufferSize;\r
-  EFI_FIRMWARE_VOLUME_HEADER          *FvHeader;\r
-  UINT32                              FvAlignment;\r
+  EFI_STATUS                  Status;\r
+  EFI_SECTION_TYPE            SectionType;\r
+  UINT32                      AuthenticationStatus;\r
+  VOID                        *Buffer;\r
+  VOID                        *AlignedBuffer;\r
+  UINTN                       BufferSize;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  UINT32                      FvAlignment;\r
+  EFI_DEVICE_PATH_PROTOCOL    *FvFileDevicePath;\r
+  UINT32                      FvUsedSize;\r
+  UINT8                       EraseByte;\r
+  UINTN                       Index;\r
 \r
   //\r
-  // Read the first (and only the first) firmware volume section\r
+  // Read firmware volume section(s)\r
   //\r
-  SectionType   = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
-  FvHeader      = NULL;\r
-  FvAlignment   = 0;\r
-  Buffer        = NULL;\r
-  BufferSize    = 0;\r
-  AlignedBuffer = NULL;\r
-  Status = Fv->ReadSection (\r
-                 Fv,\r
-                 DriverName,\r
-                 SectionType,\r
-                 0,\r
-                 &Buffer,\r
-                 &BufferSize,\r
-                 &AuthenticationStatus\r
-                 );\r
-  if (!EFI_ERROR (Status)) {\r
-    //\r
-    // 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 greater than or equal to 8 bytes of the minimum FFS alignment value. \r
-    //\r
-    if (FvAlignment < 8) {\r
-      FvAlignment = 8;\r
-    }\r
-    //\r
-    // Allocate the aligned buffer for the FvImage.\r
-    //\r
-    AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);\r
-    if (AlignedBuffer == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-    } else {\r
+  SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
+\r
+  Index = 0;\r
+  do {\r
+    FvHeader      = NULL;\r
+    FvAlignment   = 0;\r
+    Buffer        = NULL;\r
+    BufferSize    = 0;\r
+    AlignedBuffer = NULL;\r
+    Status        = Fv->ReadSection (\r
+                          Fv,\r
+                          FileName,\r
+                          SectionType,\r
+                          Index,\r
+                          &Buffer,\r
+                          &BufferSize,\r
+                          &AuthenticationStatus\r
+                          );\r
+    if (!EFI_ERROR (Status)) {\r
       //\r
-      // Move FvImage into the aligned buffer and release the original buffer.\r
+      // Evaluate the authentication status of the Firmware Volume through\r
+      // Security Architectural Protocol\r
       //\r
-      CopyMem (AlignedBuffer, Buffer, BufferSize);\r
-      CoreFreePool (Buffer);\r
-      Buffer = NULL;\r
+      if (gSecurity != NULL) {\r
+        FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, FileName);\r
+        Status           = gSecurity->FileAuthenticationState (\r
+                                        gSecurity,\r
+                                        AuthenticationStatus,\r
+                                        FvFileDevicePath\r
+                                        );\r
+        if (FvFileDevicePath != NULL) {\r
+          FreePool (FvFileDevicePath);\r
+        }\r
+\r
+        if (Status != EFI_SUCCESS) {\r
+          //\r
+          // Security check failed. The firmware volume should not be used for any purpose.\r
+          //\r
+          if (Buffer != NULL) {\r
+            FreePool (Buffer);\r
+          }\r
+\r
+          break;\r
+        }\r
+      }\r
+\r
+      //\r
+      // FvImage should be at its required alignment.\r
+      //\r
+      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Buffer;\r
+      //\r
+      // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume\r
+      // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from\r
+      // its initial linked location and maintain its alignment.\r
+      //\r
+      if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {\r
+        //\r
+        // Get FvHeader alignment\r
+        //\r
+        FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);\r
+        //\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
+        }\r
+\r
+        DEBUG ((\r
+          DEBUG_INFO,\r
+          "%a() FV at 0x%x, FvAlignment required is 0x%x\n",\r
+          __FUNCTION__,\r
+          FvHeader,\r
+          FvAlignment\r
+          ));\r
+\r
+        //\r
+        // Check FvImage alignment.\r
+        //\r
+        if ((UINTN)FvHeader % FvAlignment != 0) {\r
+          //\r
+          // Allocate the aligned buffer for the FvImage.\r
+          //\r
+          AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN)FvAlignment);\r
+          if (AlignedBuffer == NULL) {\r
+            FreePool (Buffer);\r
+            Status = EFI_OUT_OF_RESOURCES;\r
+            break;\r
+          } else {\r
+            //\r
+            // Move FvImage into the aligned buffer and release the original buffer.\r
+            //\r
+            if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) {\r
+              //\r
+              // Copy the used bytes and fill the rest with the erase value.\r
+              //\r
+              CopyMem (AlignedBuffer, FvHeader, (UINTN)FvUsedSize);\r
+              SetMem (\r
+                (UINT8 *)AlignedBuffer + FvUsedSize,\r
+                (UINTN)(BufferSize - FvUsedSize),\r
+                EraseByte\r
+                );\r
+            } else {\r
+              CopyMem (AlignedBuffer, Buffer, BufferSize);\r
+            }\r
+\r
+            FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AlignedBuffer;\r
+            FreePool (Buffer);\r
+            Buffer = NULL;\r
+          }\r
+        }\r
+      }\r
+\r
       //\r
       // Produce a FVB protocol for the file\r
       //\r
       Status = ProduceFVBProtocolOnBuffer (\r
-                (EFI_PHYSICAL_ADDRESS) (UINTN) AlignedBuffer,\r
-                (UINT64)BufferSize,\r
-                FvHandle,\r
-                NULL\r
-                );\r
+                 (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,\r
+                 (UINT64)BufferSize,\r
+                 FvHandle,\r
+                 AuthenticationStatus,\r
+                 NULL\r
+                 );\r
     }\r
-  }\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // ReadSection or Produce FVB failed, Free data buffer\r
-    //\r
-    if (Buffer != NULL) {\r
-      FreePool (Buffer);\r
-    }\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // ReadSection or Produce FVB failed, Free data buffer\r
+      //\r
+      if (Buffer != NULL) {\r
+        FreePool (Buffer);\r
+      }\r
+\r
+      if (AlignedBuffer != NULL) {\r
+        FreeAlignedPages (AlignedBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+      }\r
 \r
-    if (AlignedBuffer != NULL) {\r
-      FreeAlignedPages (AlignedBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+      break;\r
+    } else {\r
+      Index++;\r
     }\r
-  }\r
+  } while (TRUE);\r
 \r
-  return Status;\r
+  if (Index > 0) {\r
+    //\r
+    // At least one FvImage has been processed successfully.\r
+    //\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return Status;\r
+  }\r
 }\r
 \r
-\r
 /**\r
   Event notification that is fired every time a FV dispatch protocol is added.\r
   More than one protocol may have been added when this event is fired, so you\r
@@ -962,40 +1197,42 @@ CoreProcessFvImageFile (
 VOID\r
 EFIAPI\r
 CoreFwVolEventProtocolNotify (\r
-  IN  EFI_EVENT       Event,\r
-  IN  VOID            *Context\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_STATUS                    GetNextFileStatus;\r
-  EFI_STATUS                    SecurityStatus;\r
-  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
-  EFI_DEVICE_PATH_PROTOCOL      *FvDevicePath;\r
-  EFI_HANDLE                    FvHandle;\r
-  UINTN                         BufferSize;\r
-  EFI_GUID                      NameGuid;\r
-  UINTN                         Key;\r
-  EFI_FV_FILETYPE               Type;\r
-  EFI_FV_FILE_ATTRIBUTES        Attributes;\r
-  UINTN                         Size;\r
-  EFI_CORE_DRIVER_ENTRY         *DriverEntry;\r
-  EFI_GUID                      *AprioriFile;\r
-  UINTN                         AprioriEntryCount;\r
-  UINTN                         Index;\r
-  LIST_ENTRY                    *Link;\r
-  UINT32                        AuthenticationStatus;\r
-  UINTN                         SizeOfBuffer;\r
-\r
+  EFI_STATUS                     Status;\r
+  EFI_STATUS                     GetNextFileStatus;\r
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;\r
+  EFI_DEVICE_PATH_PROTOCOL       *FvDevicePath;\r
+  EFI_HANDLE                     FvHandle;\r
+  UINTN                          BufferSize;\r
+  EFI_GUID                       NameGuid;\r
+  UINTN                          Key;\r
+  EFI_FV_FILETYPE                Type;\r
+  EFI_FV_FILE_ATTRIBUTES         Attributes;\r
+  UINTN                          Size;\r
+  EFI_CORE_DRIVER_ENTRY          *DriverEntry;\r
+  EFI_GUID                       *AprioriFile;\r
+  UINTN                          AprioriEntryCount;\r
+  UINTN                          Index;\r
+  LIST_ENTRY                     *Link;\r
+  UINT32                         AuthenticationStatus;\r
+  UINTN                          SizeOfBuffer;\r
+  VOID                           *DepexBuffer;\r
+  KNOWN_HANDLE                   *KnownHandle;\r
+\r
+  FvHandle = NULL;\r
 \r
   while (TRUE) {\r
     BufferSize = sizeof (EFI_HANDLE);\r
-    Status = CoreLocateHandle (\r
-               ByRegisterNotify,\r
-               NULL,\r
-               mFwVolEventRegistration,\r
-               &BufferSize,\r
-               &FvHandle\r
-               );\r
+    Status     = CoreLocateHandle (\r
+                   ByRegisterNotify,\r
+                   NULL,\r
+                   mFwVolEventRegistration,\r
+                   &BufferSize,\r
+                   &FvHandle\r
+                   );\r
     if (EFI_ERROR (Status)) {\r
       //\r
       // If no more notification events exit\r
@@ -1013,13 +1250,19 @@ CoreFwVolEventProtocolNotify (
     //\r
     // Since we are about to process this Fv mark it as processed.\r
     //\r
-    FvIsBeingProcesssed (FvHandle);\r
+    KnownHandle = FvIsBeingProcessed (FvHandle);\r
+    if (KnownHandle == NULL) {\r
+      //\r
+      // The FV with the same FV name guid has already been processed.\r
+      // So lets skip it!\r
+      //\r
+      continue;\r
+    }\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
@@ -1033,24 +1276,6 @@ CoreFwVolEventProtocolNotify (
       continue;\r
     }\r
 \r
-    //\r
-    // Evaluate the authentication status of the Firmware Volume through\r
-    // Security Architectural Protocol\r
-    //\r
-    if (gSecurity != NULL) {\r
-      SecurityStatus = gSecurity->FileAuthenticationState (\r
-                                    gSecurity,\r
-                                    0,\r
-                                    FvDevicePath\r
-                                    );\r
-      if (SecurityStatus != EFI_SUCCESS) {\r
-        //\r
-        // Security check failed. The firmware volume should not be used for any purpose.\r
-        //\r
-        continue;\r
-      }\r
-    }\r
-\r
     //\r
     // Discover Drivers in FV and add them to the Discovered Driver List.\r
     // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
@@ -1063,7 +1288,7 @@ CoreFwVolEventProtocolNotify (
       //\r
       Key = 0;\r
       do {\r
-        Type = mDxeFileTypes[Index];\r
+        Type              = mDxeFileTypes[Index];\r
         GetNextFileStatus = Fv->GetNextFile (\r
                                   Fv,\r
                                   &Key,\r
@@ -1097,20 +1322,64 @@ CoreFwVolEventProtocolNotify (
             // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
             // been extracted.\r
             //\r
-            if (FvFoundInHobFv2 (FvHandle, &NameGuid)) {\r
+            if (FvFoundInHobFv2 (&KnownHandle->FvNameGuid, &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 SMM 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_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 is invalid to be supported.\r
+              // ASSERT FALSE to report this FV image.\r
+              //\r
+              FreePool (DepexBuffer);\r
+              ASSERT (FALSE);\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
@@ -1120,15 +1389,15 @@ CoreFwVolEventProtocolNotify (
     // Read the array of GUIDs from the Apriori file if it is present in the firmware volume\r
     //\r
     AprioriFile = NULL;\r
-    Status = Fv->ReadSection (\r
-                  Fv,\r
-                  &gAprioriGuid,\r
-                  EFI_SECTION_RAW,\r
-                  0,\r
-                  (VOID **)&AprioriFile,\r
-                  &SizeOfBuffer,\r
-                  &AuthenticationStatus\r
-                  );\r
+    Status      = Fv->ReadSection (\r
+                        Fv,\r
+                        &gAprioriGuid,\r
+                        EFI_SECTION_RAW,\r
+                        0,\r
+                        (VOID **)&AprioriFile,\r
+                        &SizeOfBuffer,\r
+                        &AuthenticationStatus\r
+                        );\r
     if (!EFI_ERROR (Status)) {\r
       AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);\r
     } else {\r
@@ -1140,23 +1409,25 @@ 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
+        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
+            (FvHandle == DriverEntry->FvHandle))\r
+        {\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
@@ -1164,8 +1435,6 @@ CoreFwVolEventProtocolNotify (
   }\r
 }\r
 \r
-\r
-\r
 /**\r
   Initialize the dispatcher. Initialize the notification function that runs when\r
   an FV2 protocol is added to the system.\r
@@ -1176,6 +1445,8 @@ CoreInitializeDispatcher (
   VOID\r
   )\r
 {\r
+  PERF_FUNCTION_BEGIN ();\r
+\r
   mFwVolEvent = EfiCreateProtocolNotifyEvent (\r
                   &gEfiFirmwareVolume2ProtocolGuid,\r
                   TPL_CALLBACK,\r
@@ -1183,6 +1454,8 @@ CoreInitializeDispatcher (
                   NULL,\r
                   &mFwVolEventRegistration\r
                   );\r
+\r
+  PERF_FUNCTION_END ();\r
 }\r
 \r
 //\r
@@ -1199,11 +1472,11 @@ CoreDisplayDiscoveredNotDispatched (
   VOID\r
   )\r
 {\r
-  LIST_ENTRY                    *Link;\r
-  EFI_CORE_DRIVER_ENTRY         *DriverEntry;\r
+  LIST_ENTRY             *Link;\r
+  EFI_CORE_DRIVER_ENTRY  *DriverEntry;\r
 \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
+  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->Dependent) {\r
       DEBUG ((DEBUG_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));\r
     }\r