]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Merge branch of PI tree to main trunk
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
index 900e1d2d5040a396703c288cb89fed8a1ca1b2b3..b9780a2c7b46b75577bc90ea1848998111d78aa6 100644 (file)
@@ -23,12 +23,6 @@ Revision History
 \r
 #include <PeiMain.h>\r
 \r
-STATIC\r
-VOID *\r
-TransferOldDataToNewDataRange (\r
-  IN PEI_CORE_INSTANCE        *PrivateData\r
-  );\r
-\r
 STATIC\r
 VOID\r
 InvokePeiCore (\r
@@ -36,11 +30,165 @@ InvokePeiCore (
   VOID          *Context2\r
   );\r
 \r
-EFI_STATUS\r
+\r
+VOID\r
+DiscoverPeimsAndOrderWithApriori (\r
+  IN  PEI_CORE_INSTANCE    *Private,\r
+  IN  EFI_PEI_FV_HANDLE    VolumeHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Discover all Peims and optional Apriori file in one FV. There is at most one\r
+  Apriori file in one FV.\r
+\r
+Arguments:\r
+\r
+  Private          - Pointer to the private data passed in from caller\r
+  VolumeHandle     - Fv handle.\r
+Returns:\r
+\r
+  NONE\r
+\r
+--*/  \r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_PEI_FV_HANDLE                   FileHandle;\r
+  EFI_PEI_FV_HANDLE                   AprioriFileHandle;\r
+  EFI_GUID                            *Apriori;\r
+  UINTN                               Index;\r
+  UINTN                               Index2;\r
+  UINTN                               PeimIndex;\r
+  UINTN                               PeimCount;\r
+  EFI_GUID                            *Guid;\r
+  EFI_PEI_FV_HANDLE                   TempFileHandles[PEI_CORE_MAX_PEIM_PER_FV];\r
+  EFI_GUID                            FileGuid[PEI_CORE_MAX_PEIM_PER_FV];\r
+\r
+  //\r
+  // Walk the FV and find all the PEIMs and the Apriori file.\r
+  //\r
+  AprioriFileHandle = NULL;\r
+  Private->CurrentFvFileHandles[0] = NULL;\r
+  Guid = NULL;\r
+  FileHandle = NULL;\r
+\r
+  //\r
+  // If the current Fv has been scanned, directly get its cachable record.\r
+  //\r
+  if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {\r
+    CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Go ahead to scan this Fv, and cache FileHandles within it.\r
+  //\r
+  for (PeimCount = 0; PeimCount < PEI_CORE_MAX_PEIM_PER_FV; PeimCount++) {\r
+    Status = PeiFindFileEx (\r
+                VolumeHandle, \r
+                NULL, \r
+                PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, \r
+                &FileHandle,\r
+                &AprioriFileHandle\r
+                );\r
+    if (Status != EFI_SUCCESS) {\r
+      break;\r
+    }\r
+    \r
+    Private->CurrentFvFileHandles[PeimCount] = FileHandle;\r
+  }\r
+\r
+  Private->AprioriCount = 0; \r
+  if (AprioriFileHandle != NULL) {\r
+    //\r
+    // Read the Apriori file\r
+    //\r
+    Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, &AprioriFileHandle, (VOID **) &Apriori);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Calculate the number of PEIMs in the A Priori list\r
+      //\r
+      Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF;\r
+      Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER);   \r
+      Private->AprioriCount /= sizeof (EFI_GUID);\r
+        \r
+      SetMem (FileGuid, sizeof (FileGuid), 0);\r
+      for (Index = 0; Index < PeimCount; Index++) {\r
+        //\r
+        // Make an array of file name guids that matches the FileHandle array so we can convert\r
+        // quickly from file name to file handle\r
+        //\r
+        CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID));    \r
+      }\r
+\r
+      //\r
+      // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.\r
+      // Add avalible PEIMs in Apriori file into TempFileHandles array at first. \r
+      //\r
+      Index2 = 0;\r
+      for (Index = 0; Index2 < Private->AprioriCount; Index++) {\r
+        while (Index2 < Private->AprioriCount) {\r
+          Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);\r
+          if (Guid != NULL) {\r
+            break;\r
+          }\r
+        }\r
+        if (Guid == NULL) {\r
+          break;  \r
+        }\r
+        PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);\r
+        TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];\r
+\r
+        //\r
+        // Since we have copied the file handle we can remove it from this list.\r
+        //\r
+        Private->CurrentFvFileHandles[PeimIndex] = NULL;\r
+      }\r
+\r
+      //\r
+      // Update valid Aprioricount\r
+      //\r
+      Private->AprioriCount = Index;\r
+      \r
+      //\r
+      // Add in any PEIMs not in the Apriori file\r
+      //\r
+      for (;Index < PeimCount; Index++) {\r
+        for (Index2 = 0; Index2 < PeimCount; Index2++) {\r
+          if (Private->CurrentFvFileHandles[Index2] != NULL) {\r
+            TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];\r
+            Private->CurrentFvFileHandles[Index2] = NULL;\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      //\r
+      //Index the end of array contains re-range Pei moudle.\r
+      //\r
+      TempFileHandles[Index] = NULL;\r
+      \r
+      //\r
+      // Private->CurrentFvFileHandles is currently in PEIM in the FV order.\r
+      // We need to update it to start with files in the A Priori list and \r
+      // then the remaining files in PEIM order. \r
+      //\r
+      CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));\r
+    }\r
+  }\r
+  //\r
+  // Cache the current Fv File Handle. So that we don't have to scan the Fv again.\r
+  // Instead, we can retrieve the file handles within this Fv from cachable data.\r
+  //\r
+  Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;\r
+  CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
+  \r
+}\r
+\r
+VOID\r
 PeiDispatcher (\r
   IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,\r
-  IN PEI_CORE_INSTANCE           *PrivateData,\r
-  IN PEI_CORE_DISPATCH_DATA      *DispatchData\r
+  IN PEI_CORE_INSTANCE           *Private\r
   )\r
 \r
 /*++\r
@@ -64,24 +212,78 @@ Returns:
 \r
 --*/\r
 {\r
-  EFI_STATUS                        Status;\r
-  PEI_CORE_TEMP_POINTERS            TempPtr;\r
-  BOOLEAN                           NextFvFound;\r
-  EFI_FIRMWARE_VOLUME_HEADER        *NextFvAddress;\r
-  EFI_FIRMWARE_VOLUME_HEADER        *DefaultFvAddress;\r
-  VOID                              *TopOfStack;\r
-  PEI_CORE_PARAMETERS               PeiCoreParameters;\r
-\r
-  //\r
-  // Debug data for uninstalled Peim list\r
-  //\r
-  EFI_GUID                          DebugFoundPeimList[32];\r
-  EFI_DEVICE_HANDLE_EXTENDED_DATA   ExtendedData;\r
-\r
-  //\r
-  // save the Current FV Address so that we will not process it again if FindFv returns it later\r
-  //\r
-  DefaultFvAddress = DispatchData->BootFvAddress;\r
+  EFI_STATUS                          Status;\r
+  UINT32                              Index1;\r
+  UINT32                              Index2;\r
+  EFI_PEI_SERVICES                    **PeiServices;\r
+  VOID                                *PrivateInMem;\r
+  EFI_PEI_FV_HANDLE                   VolumeHandle; \r
+  EFI_PEI_FILE_HANDLE                 PeiCoreFileHandle;\r
+  EFI_PEI_FILE_HANDLE                 PeimFileHandle;\r
+  UINTN                               FvCount;\r
+  UINTN                               PeimCount;\r
+  UINT32                              AuthenticationState;\r
+  EFI_PHYSICAL_ADDRESS                EntryPoint;\r
+  EFI_PEIM_ENTRY_POINT                PeimEntryPoint;\r
+  BOOLEAN                             PeimNeedingDispatch;\r
+  BOOLEAN                             PeimDispatchOnThisPass;\r
+  UINTN                               SaveCurrentPeimCount;\r
+  EFI_PEI_FILE_HANDLE                 SaveCurrentFileHandle;\r
+  VOID                                *TopOfStack;\r
+  PEI_CORE_PARAMETERS                 PeiCoreParameters;\r
+  EFI_DEVICE_HANDLE_EXTENDED_DATA     ExtendedData;\r
+\r
+\r
+  PeiServices = &Private->PS;\r
+  PeimEntryPoint = NULL;\r
+  PeimFileHandle = NULL;\r
+\r
+  if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+    //\r
+    // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
+    // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.\r
+    //\r
+    SaveCurrentPeimCount  = Private->CurrentPeimCount;\r
+    SaveCurrentFileHandle =  Private->CurrentFileHandle;\r
+\r
+    for (Index1 = 0;Index1 <= Private->CurrentPeimFvCount; Index1++) {\r
+      for (Index2 = 0; (Index2 < PEI_CORE_MAX_PEIM_PER_FV) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
+        if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
+          PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];  \r
+          Status = PeiLoadImage (\r
+                    &Private->PS, \r
+                    PeimFileHandle,  \r
+                    &EntryPoint, \r
+                    &AuthenticationState\r
+                    );\r
+          if (Status == EFI_SUCCESS) {\r
+            //\r
+            // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
+            //\r
+            Private->Fv[Index1].PeimState[Index2]++;\r
+            Private->CurrentFileHandle = PeimFileHandle;\r
+            Private->CurrentPeimCount  = Index2;        \r
+            //\r
+            // Call the PEIM entry point\r
+            //\r
+            PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;\r
+            \r
+            PERF_START (0, "PEIM", NULL, 0);\r
+            PeimEntryPoint(PeimFileHandle, &Private->PS);\r
+            PERF_END (0, "PEIM", NULL, 0);\r
+          } \r
+          \r
+          //\r
+          // Process the Notify list and dispatch any notifies for\r
+          // newly installed PPIs.\r
+          //\r
+          ProcessNotifyList (Private);\r
+        }\r
+      }\r
+    }\r
+    Private->CurrentFileHandle = SaveCurrentFileHandle;   \r
+    Private->CurrentPeimCount  = SaveCurrentPeimCount;    \r
+  }\r
 \r
   //\r
   // This is the main dispatch loop.  It will search known FVs for PEIMs and\r
@@ -91,69 +293,50 @@ Returns:
   // FV where PEIMs are found in the order their dependencies are also\r
   // satisfied, this dipatcher should run only once.\r
   //\r
-  for (;;) {\r
-    //\r
-    // This is the PEIM search loop. It will scan through all PEIMs it can find\r
-    // looking for PEIMs to dispatch, and will dipatch them if they have not\r
-    // already been dispatched and all of their dependencies are met.\r
-    // If no more PEIMs can be found in this pass through all known FVs,\r
-    // then it will break out of this loop.\r
-    //\r
-    for (;;) {\r
+  do {\r
+    PeimNeedingDispatch = FALSE;\r
+    PeimDispatchOnThisPass = FALSE;\r
+\r
+    for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
+      Private->CurrentPeimFvCount = FvCount;\r
+      VolumeHandle = Private->Fv[FvCount].FvHeader;\r
 \r
-      Status = FindNextPeim (\r
-                 &PrivateData->PS,\r
-                 DispatchData->CurrentFvAddress,\r
-                 &DispatchData->CurrentPeimAddress\r
-                 );\r
+      if (Private->CurrentPeimCount == 0) {\r
+        //\r
+        // When going through each FV, at first, search Apriori file to\r
+        // reorder all PEIMs to ensure the PEIMs in Apriori file to get \r
+        // dispatch at first.\r
+        //\r
+        DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle);\r
+      }\r
 \r
       //\r
-      // If we found a PEIM, check if it is dispatched.  If so, go to the\r
-      // next PEIM.  If not, dispatch it if its dependencies are satisfied.\r
-      // If its dependencies are not satisfied, go to the next PEIM.\r
+      // Start to dispatch all modules within the current Fv.\r
       //\r
-      if (Status == EFI_SUCCESS) {\r
-\r
-        DEBUG_CODE_BEGIN ();\r
-\r
-          //\r
-          // Fill list of found Peims for later list of those not installed\r
-          //\r
-          CopyMem (\r
-            &DebugFoundPeimList[DispatchData->CurrentPeim],\r
-            &DispatchData->CurrentPeimAddress->Name,\r
-            sizeof (EFI_GUID)\r
-            );\r
-\r
-        DEBUG_CODE_END ();\r
-\r
-        if (!Dispatched (\r
-               DispatchData->CurrentPeim,\r
-               DispatchData->DispatchedPeimBitMap\r
-               )) {\r
-          if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) {\r
+      for (PeimCount = Private->CurrentPeimCount; \r
+           (PeimCount < PEI_CORE_MAX_PEIM_PER_FV) && (Private->CurrentFvFileHandles[PeimCount] != NULL); \r
+           PeimCount++) {\r
+        Private->CurrentPeimCount  = PeimCount;\r
+        PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
+\r
+        if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {\r
+          if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
+            PeimNeedingDispatch = TRUE;\r
+          } else {\r
             Status = PeiLoadImage (\r
-                       &PrivateData->PS,\r
-                       DispatchData->CurrentPeimAddress,\r
-                       &TempPtr.Raw\r
+                       PeiServices, \r
+                       PeimFileHandle,  \r
+                       &EntryPoint, \r
+                       &AuthenticationState\r
                        );\r
-            if (Status == EFI_SUCCESS) {\r
-\r
+            if ((Status == EFI_SUCCESS)) {\r
               //\r
               // The PEIM has its dependencies satisfied, and its entry point\r
               // has been found, so invoke it.\r
               //\r
-              PERF_START (\r
-                (VOID *) (UINTN) (DispatchData->CurrentPeimAddress),\r
-                "PEIM",\r
-                NULL,\r
-                0\r
-                );\r
+              PERF_START (0, "PEIM", NULL, 0);\r
 \r
-              //\r
-              // BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE\r
-              //\r
-              ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress;\r
+              ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;\r
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
                 EFI_PROGRESS_CODE,\r
@@ -162,24 +345,19 @@ Returns:
                 sizeof (ExtendedData)\r
                 );\r
 \r
-              //\r
-              // Is this a authentic image\r
-              //\r
-              Status = VerifyPeim (\r
-                        &PrivateData->PS,\r
-                        DispatchData->CurrentPeimAddress\r
-                        );\r
-\r
-              if (Status != EFI_SECURITY_VIOLATION) {\r
+              Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);\r
+              if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {\r
+                //\r
+                // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
+                //\r
+                Private->Fv[FvCount].PeimState[PeimCount]++;\r
 \r
                 //\r
-                // BUGBUG: Before enable PI, we need cast EFI_FFS_FILE_HEADER* to EFI_PEI_FILE_HANDLE*\r
-                //         Because we use new MdePkg's definition, but they are binary compatible in fact.\r
+                // Call the PEIM entry point\r
                 //\r
-                Status =  TempPtr.PeimEntry (\r
-                                    (EFI_PEI_FILE_HANDLE*)DispatchData->CurrentPeimAddress,\r
-                                    &PrivateData->PS\r
-                                    );\r
+                PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;\r
+                PeimEntryPoint (PeimFileHandle, PeiServices);\r
+                PeimDispatchOnThisPass = TRUE;\r
               }\r
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
@@ -188,189 +366,146 @@ Returns:
                 (VOID *)(&ExtendedData),\r
                 sizeof (ExtendedData)\r
                 );\r
+              PERF_END (0, "PEIM", NULL, 0);\r
+\r
+            }\r
 \r
-              PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 0);\r
+            //\r
+            // Process the Notify list and dispatch any notifies for\r
+            // newly installed PPIs.\r
+            //\r
+            ProcessNotifyList (Private);\r
+\r
+            //\r
+            // If permanent memory was discovered and installed by this\r
+            // PEIM, shadow PEI Core and switch the stacks to the new memory.  \r
+            //\r
+            if (Private->SwitchStackSignal) {\r
 \r
               //\r
-              // Mark the PEIM as dispatched so we don't attempt to run it again\r
+              // Make sure we don't retry the same PEIM that added memory\r
               //\r
-              SetDispatched (\r
-                &PrivateData->PS,\r
-                DispatchData->CurrentPeim,\r
-                &DispatchData->DispatchedPeimBitMap\r
-                );\r
+              Private->CurrentPeimCount++;\r
 \r
               //\r
-              // Process the Notify list and dispatch any notifies for\r
-              // newly installed PPIs.\r
+              // Migrate IDT from CAR into real memory, so after stack switches to\r
+              // the new memory, the caller can get memory version PeiServiceTable. \r
               //\r
-              ProcessNotifyList (&PrivateData->PS);\r
+              //MigrateIdtTable (PeiServices);              \r
+              //\r
+              // Since we are at dispatch level, only the Core's private data \r
+              // is preserved, nobody else should have any data on the stack. \r
+              // So we need to copy PEI core instance data to memory.\r
+              //\r
+              PrivateInMem = AllocateCopyPool (sizeof (PEI_CORE_INSTANCE), Private);\r
+              ASSERT (PrivateInMem != NULL);\r
 \r
               //\r
-              // If real system memory was discovered and installed by this\r
-              // PEIM, switch the stacks to the new memory.  Since we are\r
-              // at dispatch level, only the Core's private data is preserved,\r
-              // nobody else should have any data on the stack.\r
+              // Shadow PEI Core. When permanent memory is avaiable, shadow\r
+              // PEI Core and PEIMs to get high performance.\r
               //\r
-              if (PrivateData->SwitchStackSignal) {\r
-                //\r
-                // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT\r
-                //\r
-                TopOfStack = (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - CPU_STACK_ALIGNMENT);\r
-                TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
-                \r
-                PeiCoreParameters.SecCoreData = SecCoreData;\r
-                PeiCoreParameters.PpiList     = NULL;\r
-                PeiCoreParameters.Data        = TransferOldDataToNewDataRange (PrivateData);\r
-                ASSERT (PeiCoreParameters.Data != 0);\r
-\r
-                PeiSwitchStacks (\r
-                  InvokePeiCore,\r
-                  (VOID*) (UINTN) PeiCore,\r
-                  (VOID*) &PeiCoreParameters,  \r
-                  TopOfStack,\r
-                  (VOID*)(UINTN)PrivateData->StackBase\r
-                  );\r
-              }\r
+              PeiCoreFileHandle = NULL;\r
+              //\r
+              // Find the PEI Core in the BFV\r
+              //\r
+              Status = PeiFindFileEx (\r
+                        (EFI_PEI_FV_HANDLE)Private->Fv[0].FvHeader, \r
+                        NULL, \r
+                        EFI_FV_FILETYPE_PEI_CORE, \r
+                        &PeiCoreFileHandle,\r
+                        NULL\r
+                        );\r
+              ASSERT_EFI_ERROR (Status);\r
+  \r
+              //\r
+              // Shadow PEI Core into memory so it will run faster\r
+              //\r
+              Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState);\r
+              ASSERT_EFI_ERROR (Status);\r
+  \r
+              //\r
+              // Switch to memory based stack and reenter PEI Core that has been\r
+              //  shadowed to memory.\r
+              //\r
+              //\r
+              // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT\r
+              //\r
+              TopOfStack = (VOID *)((UINTN)Private->StackBase + (UINTN)Private->StackSize - CPU_STACK_ALIGNMENT);\r
+              TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
+              \r
+              PeiCoreParameters.SecCoreData = SecCoreData;\r
+              PeiCoreParameters.PpiList     = NULL;\r
+              PeiCoreParameters.Data        = PrivateInMem;\r
+              ASSERT (PeiCoreParameters.Data != 0);\r
+\r
+              PeiSwitchStacks (\r
+                InvokePeiCore,\r
+                (VOID*) (UINTN) PeiCore,\r
+                (VOID*) &PeiCoreParameters,  \r
+                TopOfStack,\r
+                (VOID*)(UINTN)Private->StackBase\r
+                );\r
             }\r
-          }\r
-        }\r
-        DispatchData->CurrentPeim++;\r
-        continue;\r
 \r
-      } else {\r
-\r
-        //\r
-        // If we could not find another PEIM in the current FV, go try\r
-        // the FindFv PPI to look in other FVs for more PEIMs.  If we can\r
-        // not locate the FindFv PPI, or if the FindFv PPI can not find\r
-        // anymore FVs, then exit the PEIM search loop.\r
-        //\r
-        if (DispatchData->FindFv == NULL) {\r
-          Status = PeiServicesLocatePpi (\r
-                     &gEfiFindFvPpiGuid,\r
-                     0,\r
-                     NULL,\r
-                     (VOID **)&DispatchData->FindFv\r
-                     );\r
-          if (Status != EFI_SUCCESS) {\r
-            break;\r
-          }\r
-        }\r
-        NextFvFound = FALSE;\r
-        while (!NextFvFound) {\r
-          Status = DispatchData->FindFv->FindFv (\r
-                                           DispatchData->FindFv,\r
-                                           &PrivateData->PS,\r
-                                           &DispatchData->CurrentFv,\r
-                                           &NextFvAddress\r
-                                           );\r
-          //\r
-          // if there is no next fv, get out of this loop of finding FVs\r
-          //\r
-          if (Status != EFI_SUCCESS) {\r
-            break;\r
-          }\r
-          //\r
-          // don't process the default Fv again. (we don't know the order in which the hobs were created)\r
-          //\r
-          if ((NextFvAddress != DefaultFvAddress) &&\r
-              (NextFvAddress != DispatchData->CurrentFvAddress)) {\r
+            if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) &&   \\r
+                (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+              //\r
+              // If memory is availble we shadow images by default for performance reasons. \r
+              // We call the entry point a 2nd time so the module knows it's shadowed. \r
+              //\r
+              //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
+              PeimEntryPoint (PeimFileHandle, PeiServices);\r
+              //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
+              \r
+              //\r
+              // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
+              //\r
+              Private->Fv[FvCount].PeimState[PeimCount]++;\r
 \r
-            //\r
-            // VerifyFv() is currently returns SUCCESS all the time, add code to it to\r
-            // actually verify the given FV\r
-            //\r
-            Status = VerifyFv (NextFvAddress);\r
-            if (Status == EFI_SUCCESS) {\r
-              NextFvFound = TRUE;\r
-              DispatchData->CurrentFvAddress = NextFvAddress;\r
-              DispatchData->CurrentPeimAddress = NULL;\r
               //\r
-              // current PRIM number (CurrentPeim) must continue as is, don't reset it here\r
+              // Process the Notify list and dispatch any notifies for\r
+              // newly installed PPIs.\r
               //\r
+              ProcessNotifyList (Private);\r
             }\r
           }\r
         }\r
-        //\r
-        // if there is no next fv, get out of this loop of dispatching PEIMs\r
-        //\r
-        if (!NextFvFound) {\r
-          break;\r
-        }\r
-        //\r
-        // continue in the inner for(;;) loop with a new FV;\r
-        //\r
       }\r
-    }\r
 \r
-    //\r
-    // If all the PEIMs that we have found have been dispatched, then\r
-    // there is nothing left to dispatch and we don't need to go search\r
-    // through all PEIMs again.\r
-    //\r
-    if ((~(DispatchData->DispatchedPeimBitMap) &\r
-         ((1 << DispatchData->CurrentPeim)-1)) == 0) {\r
-      break;\r
-    }\r
-\r
-    //\r
-    // Check if no more PEIMs that depex was satisfied\r
-    //\r
-    if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) {\r
-      break;\r
+      //\r
+      // We set to NULL here to optimize the 2nd entry to this routine after\r
+      //  memory is found. This reprevents rescanning of the FV. We set to\r
+      //  NULL here so we start at the begining of the next FV\r
+      //\r
+      Private->CurrentFileHandle = NULL;\r
+      Private->CurrentPeimCount = 0;\r
+      //\r
+      // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL\r
+      //\r
+      SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);\r
     }\r
 \r
     //\r
-    // Case when Depex is not satisfied and has to traverse the list again\r
+    // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go \r
+    // through all the FV.\r
     //\r
-    DispatchData->CurrentPeim = 0;\r
-    DispatchData->CurrentPeimAddress = 0;\r
-    DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap;\r
+    Private->CurrentPeimFvCount = 0;\r
 \r
     //\r
-    // don't go back to the loop without making sure that the CurrentFvAddress is the\r
-    // same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and\r
-    // mess it up, always start processing the PEIMs from the default FV just like in the first time around.\r
-    //\r
-    DispatchData->CurrentFv = 0;\r
-    DispatchData->CurrentFvAddress = DefaultFvAddress;\r
-  }\r
-\r
-  DEBUG_CODE_BEGIN ();\r
+    // PeimNeedingDispatch being TRUE means we found a PEIM that did not get \r
+    //  dispatched. So we need to make another pass\r
     //\r
-    // Debug data for uninstalled Peim list\r
+    // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this \r
+    //  pass. If we did not dispatch a PEIM there is no point in trying again\r
+    //  as it will fail the next time too (nothing has changed).\r
     //\r
-    UINT32        DebugNotDispatchedBitmap;\r
-    UINT8         DebugFoundPeimPoint;\r
+  } while (PeimNeedingDispatch && PeimDispatchOnThisPass);\r
 \r
-    DebugFoundPeimPoint = 0;\r
-    //\r
-    // Get bitmap of Peims that were not dispatched,\r
-    //\r
-\r
-    DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1));\r
-    //\r
-    // Scan bitmap of Peims not installed and print GUIDS\r
-    //\r
-    while (DebugNotDispatchedBitmap != 0) {\r
-      if ((DebugNotDispatchedBitmap & 1) != 0) {\r
-        DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n",\r
-           &DebugFoundPeimList[DebugFoundPeimPoint]\r
-           ));\r
-      }\r
-      DebugFoundPeimPoint++;\r
-      DebugNotDispatchedBitmap >>= 1;\r
-    }\r
-\r
-  DEBUG_CODE_END ();\r
-\r
-  return EFI_NOT_FOUND;\r
 }\r
 \r
 VOID\r
 InitializeDispatcherData (\r
-  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_CORE_INSTANCE            *PrivateData,\r
   IN PEI_CORE_INSTANCE            *OldCoreData,\r
   IN CONST EFI_SEC_PEI_HAND_OFF   *SecCoreData\r
   )\r
@@ -395,87 +530,19 @@ Returns:
 \r
 --*/\r
 {\r
-  PEI_CORE_INSTANCE *PrivateData;\r
-\r
-  PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
-\r
   if (OldCoreData == NULL) {\r
-    PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase;\r
-    PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase;\r
-  } else {\r
-\r
-    //\r
-    // Current peim has been dispatched, but not count\r
-    //\r
-    PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1);\r
+    PeiInitializeFv (PrivateData, SecCoreData);\r
   }\r
 \r
   return;\r
 }\r
 \r
 \r
-BOOLEAN\r
-Dispatched (\r
-  IN UINT8  CurrentPeim,\r
-  IN UINT32 DispatchedPeimBitMap\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This routine checks to see if a particular PEIM has been dispatched during\r
-  the PEI core dispatch.\r
-\r
-Arguments:\r
-  CurrentPeim          - The PEIM/FV in the bit array to check.\r
-  DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.\r
-\r
-Returns:\r
-  TRUE  - PEIM already dispatched\r
-  FALSE - Otherwise\r
-\r
---*/\r
-{\r
-  return (BOOLEAN)((DispatchedPeimBitMap & (1 << CurrentPeim)) != 0);\r
-}\r
-\r
-VOID\r
-SetDispatched (\r
-  IN EFI_PEI_SERVICES   **PeiServices,\r
-  IN UINT8              CurrentPeim,\r
-  OUT UINT32            *DispatchedPeimBitMap\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This routine sets a PEIM as having been dispatched once its entry\r
-  point has been invoked.\r
-\r
-Arguments:\r
-\r
-  PeiServices          - The PEI core services table.\r
-  CurrentPeim          - The PEIM/FV in the bit array to check.\r
-  DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.\r
-\r
-Returns:\r
-  None\r
-\r
---*/\r
-{\r
-  //\r
-  // Check if the total number of PEIMs exceed the bitmap.\r
-  // CurrentPeim is 0-based\r
-  //\r
-  ASSERT (CurrentPeim < (sizeof (*DispatchedPeimBitMap) * 8));\r
-  *DispatchedPeimBitMap |= (1 << CurrentPeim);\r
-  return;\r
-}\r
-\r
 BOOLEAN\r
 DepexSatisfied (\r
-  IN EFI_PEI_SERVICES  **PeiServices,\r
-  IN VOID              *CurrentPeimAddress\r
+  IN PEI_CORE_INSTANCE          *Private,\r
+  IN EFI_PEI_FILE_HANDLE        FileHandle,\r
+  IN UINTN                      PeimCount\r
   )\r
 /*++\r
 \r
@@ -495,59 +562,27 @@ Returns:
 --*/\r
 {\r
   EFI_STATUS  Status;\r
-  INT8        *DepexData;\r
-  BOOLEAN     Runnable;\r
-\r
-  Status = PeiServicesFfsFindSectionData (\r
-             EFI_SECTION_PEI_DEPEX,\r
-             CurrentPeimAddress,\r
-             (VOID **)&DepexData\r
-             );\r
-  //\r
-  // If there is no DEPEX, assume the module can be executed\r
-  //\r
+  VOID        *DepexData;\r
+\r
+  if (PeimCount < Private->AprioriCount) {\r
+    //\r
+    // If its in the A priori file then we set Depex to TRUE\r
+    //\r
+    return TRUE;\r
+  }\r
+\r
+  Status = PeiServicesFfsFindSectionData (EFI_SECTION_PEI_DEPEX, FileHandle, (VOID **) &DepexData);\r
   if (EFI_ERROR (Status)) {\r
+    //\r
+    // If there is no DEPEX, assume the module can be executed\r
+    //\r
     return TRUE;\r
   }\r
 \r
   //\r
   // Evaluate a given DEPEX\r
   //\r
-  Status = PeimDispatchReadiness (\r
-            PeiServices,\r
-            DepexData,\r
-            &Runnable\r
-            );\r
-\r
-  return Runnable;\r
-}\r
-\r
-STATIC\r
-VOID *\r
-TransferOldDataToNewDataRange (\r
-  IN PEI_CORE_INSTANCE        *PrivateData\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This routine transfers the contents of the pre-permanent memory\r
-  PEI Core private data to a post-permanent memory data location.\r
-\r
-Arguments:\r
-\r
-  PrivateData       - Pointer to the current PEI Core private data pre-permanent memory\r
-\r
-Returns:\r
-\r
-  Pointer to the PrivateData once the private data has been transferred to permanent memory\r
-\r
---*/\r
-{\r
-  //\r
-  //Build private HOB to PEI core to transfer old NEM-range data to new NEM-range\r
-  //\r
-  return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE));\r
+  return PeimDispatchReadiness (&Private->PS, DepexData);\r
 }\r
 \r
 /**\r
@@ -589,6 +624,7 @@ PeiRegisterForShadow (
   return EFI_SUCCESS;\r
 }\r
 \r
+\r
 /**\r
   This routine invoke the PeiCore's entry in new stack environment.\r
 \r
@@ -627,7 +663,3 @@ InvokePeiCore (
   //\r
   ASSERT_EFI_ERROR (FALSE);\r
 }\r
-\r
-\r
-\r
-\r