]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Code scrub DxeIpl, Runtime, DevicePath, FvbServicesLib, DiskIo, Partition, English...
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
index fd4778fdc7b108f295818453087c65ec110add89..e6e3a11b168ff203e747ba02329a5400cc156893 100644 (file)
@@ -1,5 +1,6 @@
-/*++\r
-\r
+/** @file\r
+  EFI PEI Core dispatch services\r
+  \r
 Copyright (c) 2006, Intel Corporation\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
@@ -9,49 +10,35 @@ http://opensource.org/licenses/bsd-license.php
 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
 \r
-Module Name:\r
+**/\r
 \r
-  Dispatcher.c\r
+#include "PeiMain.h"\r
 \r
-Abstract:\r
+///\r
+/// CAR is filled with this initial value during SEC phase\r
+///\r
+#define INIT_CAR_VALUE 0x5AA55AA5\r
 \r
-  EFI PEI Core dispatch services\r
+typedef struct {\r
+  EFI_STATUS_CODE_DATA  DataHeader;\r
+  EFI_HANDLE            Handle;\r
+} PEIM_FILE_HANDLE_EXTENDED_DATA;\r
 \r
-Revision History\r
-\r
---*/\r
+/**\r
 \r
-#include <PeiMain.h>\r
+  Discover all Peims and optional Apriori file in one FV. There is at most one\r
+  Apriori file in one FV.\r
 \r
-STATIC\r
-VOID\r
-InvokePeiCore (\r
-  VOID          *Context1,\r
-  VOID          *Context2\r
-  );\r
 \r
+  @param Private         - Pointer to the private data passed in from caller\r
+  @param VolumeHandle    - Fv handle.\r
 \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
@@ -86,20 +73,20 @@ Returns:
   //\r
   for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
     Status = PeiFindFileEx (\r
-                VolumeHandle, \r
-                NULL, \r
-                PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, \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
+\r
     Private->CurrentFvFileHandles[PeimCount] = FileHandle;\r
   }\r
 \r
-  Private->AprioriCount = 0; \r
+  Private->AprioriCount = 0;\r
   if (AprioriFileHandle != NULL) {\r
     //\r
     // Read the Apriori file\r
@@ -110,21 +97,21 @@ Returns:
       // 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_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER);\r
       Private->AprioriCount /= sizeof (EFI_GUID);\r
-        \r
-      SetMem (FileGuid, sizeof (FileGuid), 0);\r
+\r
+      ZeroMem (FileGuid, sizeof (FileGuid));\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
+        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
+      // Add avalible PEIMs in Apriori file into TempFileHandles array at first.\r
       //\r
       Index2 = 0;\r
       for (Index = 0; Index2 < Private->AprioriCount; Index++) {\r
@@ -135,7 +122,7 @@ Returns:
           }\r
         }\r
         if (Guid == NULL) {\r
-          break;  \r
+          break;\r
         }\r
         PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);\r
         TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];\r
@@ -150,7 +137,7 @@ Returns:
       // Update valid Aprioricount\r
       //\r
       Private->AprioriCount = Index;\r
-      \r
+\r
       //\r
       // Add in any PEIMs not in the Apriori file\r
       //\r
@@ -167,11 +154,11 @@ Returns:
       //Index the end of array contains re-range Pei moudle.\r
       //\r
       TempFileHandles[Index] = NULL;\r
-      \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
+      // 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
@@ -182,62 +169,109 @@ Returns:
   //\r
   Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;\r
   CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
-  \r
+\r
 }\r
 \r
-VOID\r
-PeiDispatcher (\r
-  IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,\r
-  IN PEI_CORE_INSTANCE           *Private\r
+/**\r
+  Shadow PeiCore module from flash to installed memory.\r
+  \r
+  @param PeiServices     An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+  @param PrivateInMem    PeiCore's private data structure\r
+\r
+  @return PeiCore function address after shadowing.\r
+**/\r
+VOID*\r
+ShadowPeiCore(\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices,\r
+  IN       PEI_CORE_INSTANCE    *PrivateInMem\r
   )\r
+{\r
+  EFI_PEI_FILE_HANDLE  PeiCoreFileHandle;\r
+  EFI_PHYSICAL_ADDRESS EntryPoint;\r
+  EFI_STATUS           Status;\r
+  UINT32               AuthenticationState;\r
 \r
-/*++\r
+  PeiCoreFileHandle = NULL;\r
 \r
-Routine Description:\r
+  //\r
+  // Find the PEI Core in the BFV\r
+  //\r
+  Status = PeiFindFileEx (\r
+             (EFI_PEI_FV_HANDLE)PrivateInMem->Fv[0].FvHeader,\r
+             NULL,\r
+             EFI_FV_FILETYPE_PEI_CORE,\r
+             &PeiCoreFileHandle,\r
+             NULL\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-  Conduct PEIM dispatch.\r
+  //\r
+  // Shadow PEI Core into memory so it will run faster\r
+  //\r
+  Status = PeiLoadImage (\r
+              PeiServices,\r
+              *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),\r
+              &EntryPoint,\r
+              &AuthenticationState\r
+              );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Compute the PeiCore's function address after shaowed PeiCore.\r
+  // _ModuleEntryPoint is PeiCore main function entry\r
+  //\r
+  return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);\r
+}\r
 \r
-Arguments:\r
+/**\r
+  Conduct PEIM dispatch.\r
 \r
-  SecCoreData          - Points to a data structure containing information about the PEI core's operating\r
+  @param SecCoreData     Points to a data structure containing information about the PEI core's operating\r
                          environment, such as the size and location of temporary RAM, the stack location and\r
                          the BFV location.\r
-  PrivateData          - Pointer to the private data passed in from caller\r
-  DispatchData         - Pointer to PEI_CORE_DISPATCH_DATA data.\r
-\r
-Returns:\r
+  @param Private         Pointer to the private data passed in from caller\r
 \r
-  EFI_SUCCESS   - Successfully dispatched PEIM.\r
-  EFI_NOT_FOUND - The dispatch failed.\r
-\r
---*/\r
+**/\r
+VOID\r
+PeiDispatcher (\r
+  IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,\r
+  IN PEI_CORE_INSTANCE           *Private\r
+  )\r
 {\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
+  CONST EFI_PEI_SERVICES              **PeiServices;\r
+  EFI_PEI_FV_HANDLE                   VolumeHandle;\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
+  EFI_PEIM_ENTRY_POINT2               PeimEntryPoint;\r
   UINTN                               SaveCurrentPeimCount;\r
   UINTN                               SaveCurrentFvCount;\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
+  PEIM_FILE_HANDLE_EXTENDED_DATA      ExtendedData;\r
+  EFI_PHYSICAL_ADDRESS                NewPermenentMemoryBase;\r
+  TEMPORARY_RAM_SUPPORT_PPI           *TemporaryRamSupportPpi;\r
+  EFI_HOB_HANDOFF_INFO_TABLE          *OldHandOffTable;\r
+  EFI_HOB_HANDOFF_INFO_TABLE          *NewHandOffTable;\r
+  INTN                                StackOffset;\r
+  INTN                                HeapOffset;\r
+  PEI_CORE_INSTANCE                   *PrivateInMem;\r
+  UINT64                              NewPeiStackSize;\r
+  UINT64                              OldPeiStackSize;\r
+  UINT64                              StackGap;\r
+  EFI_FV_FILE_INFO                    FvFileInfo;\r
+  UINTN                               OldCheckingTop;\r
+  UINTN                               OldCheckingBottom;\r
+\r
+\r
+  PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;\r
   PeimEntryPoint = NULL;\r
   PeimFileHandle = NULL;\r
+  EntryPoint     = 0;\r
 \r
   if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
     //\r
@@ -251,11 +285,11 @@ Returns:
     for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
       for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (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
+          PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
           Status = PeiLoadImage (\r
-                    &Private->PS, \r
-                    PeimFileHandle,  \r
-                    &EntryPoint, \r
+                    (CONST EFI_PEI_SERVICES **) &Private->PS,\r
+                    PeimFileHandle,\r
+                    &EntryPoint,\r
                     &AuthenticationState\r
                     );\r
           if (Status == EFI_SUCCESS) {\r
@@ -264,18 +298,18 @@ Returns:
             //\r
             Private->Fv[Index1].PeimState[Index2]++;\r
             Private->CurrentFileHandle   = PeimFileHandle;\r
-            Private->CurrentPeimFvCount  = Index1;        \r
-            Private->CurrentPeimCount    = Index2;        \r
+            Private->CurrentPeimFvCount  = Index1;\r
+            Private->CurrentPeimCount    = Index2;\r
             //\r
             // Call the PEIM entry point\r
             //\r
-            PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;\r
-            \r
+            PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
+\r
             PERF_START (0, "PEIM", NULL, 0);\r
-            PeimEntryPoint(PeimFileHandle, &Private->PS);\r
+            PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);\r
             PERF_END (0, "PEIM", NULL, 0);\r
-          } \r
-          \r
+          }\r
+\r
           //\r
           // Process the Notify list and dispatch any notifies for\r
           // newly installed PPIs.\r
@@ -284,9 +318,9 @@ Returns:
         }\r
       }\r
     }\r
-    Private->CurrentFileHandle  = SaveCurrentFileHandle;   \r
-    Private->CurrentPeimFvCount = SaveCurrentFvCount;    \r
-    Private->CurrentPeimCount   = SaveCurrentPeimCount;    \r
+    Private->CurrentFileHandle  = SaveCurrentFileHandle;\r
+    Private->CurrentPeimFvCount = SaveCurrentFvCount;\r
+    Private->CurrentPeimCount   = SaveCurrentPeimCount;\r
   }\r
 \r
   //\r
@@ -298,17 +332,27 @@ Returns:
   // satisfied, this dipatcher should run only once.\r
   //\r
   do {\r
-    PeimNeedingDispatch = FALSE;\r
-    PeimDispatchOnThisPass = FALSE;\r
-\r
+    //\r
+    // In case that reenter PeiCore happens, the last pass record is still available.   \r
+    //\r
+    if (!Private->PeimDispatcherReenter) {\r
+      Private->PeimNeedingDispatch      = FALSE;\r
+      Private->PeimDispatchOnThisPass   = FALSE;\r
+    } else {\r
+      Private->PeimDispatcherReenter    = FALSE;\r
+    }\r
+    \r
     for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
       Private->CurrentPeimFvCount = FvCount;\r
-      VolumeHandle = Private->Fv[FvCount].FvHeader;\r
+      //\r
+      // Get this Fv Handle by PeiService FvFindNextVolume.\r
+      //\r
+      PeiFvFindNextVolume (PeiServices, FvCount, &VolumeHandle);\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
+        // reorder all PEIMs to ensure the PEIMs in Apriori file to get\r
         // dispatch at first.\r
         //\r
         DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle);\r
@@ -317,22 +361,35 @@ Returns:
       //\r
       // Start to dispatch all modules within the current Fv.\r
       //\r
-      for (PeimCount = Private->CurrentPeimCount; \r
-           (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL); \r
+      for (PeimCount = Private->CurrentPeimCount;\r
+           (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (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
+            Private->PeimNeedingDispatch = TRUE;\r
           } else {\r
-            Status = PeiLoadImage (\r
-                       PeiServices, \r
-                       PeimFileHandle,  \r
-                       &EntryPoint, \r
-                       &AuthenticationState\r
-                       );\r
+            Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo);\r
+            ASSERT_EFI_ERROR (Status);\r
+            if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+              //\r
+              // For Fv type file, Produce new FV PPI and FV hob\r
+              //\r
+              Status = ProcessFvFile (PeiServices, PeimFileHandle, &AuthenticationState);\r
+            } else {\r
+              //\r
+              // For PEIM driver, Load its entry point\r
+              //\r
+              Status = PeiLoadImage (\r
+                         PeiServices,\r
+                         PeimFileHandle,\r
+                         &EntryPoint,\r
+                         &AuthenticationState\r
+                         );\r
+            }\r
+\r
             if ((Status == EFI_SUCCESS)) {\r
               //\r
               // The PEIM has its dependencies satisfied, and its entry point\r
@@ -344,7 +401,7 @@ Returns:
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
                 EFI_PROGRESS_CODE,\r
-                EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN,\r
+                FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
                 (VOID *)(&ExtendedData),\r
                 sizeof (ExtendedData)\r
                 );\r
@@ -356,17 +413,20 @@ Returns:
                 //\r
                 Private->Fv[FvCount].PeimState[PeimCount]++;\r
 \r
-                //\r
-                // Call the PEIM entry point\r
-                //\r
-                PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;\r
-                PeimEntryPoint (PeimFileHandle, PeiServices);\r
-                PeimDispatchOnThisPass = TRUE;\r
+                if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+                  //\r
+                  // Call the PEIM entry point for PEIM driver\r
+                  //\r
+                  PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
+                  PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
+                }\r
+\r
+                Private->PeimDispatchOnThisPass = TRUE;\r
               }\r
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
                 EFI_PROGRESS_CODE,\r
-                EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END,\r
+                FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
                 (VOID *)(&ExtendedData),\r
                 sizeof (ExtendedData)\r
                 );\r
@@ -374,94 +434,207 @@ Returns:
 \r
             }\r
 \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
+              // Before switch stack from CAR to permenent memory, caculate the heap and stack\r
+              // usage in temporary memory for debuging.\r
+              //\r
+              DEBUG_CODE_BEGIN ();\r
+                UINT32  *StackPointer;\r
+                \r
+                for (StackPointer = (UINT32*)SecCoreData->StackBase;\r
+                     (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \\r
+                     && (*StackPointer == INIT_CAR_VALUE);\r
+                     StackPointer ++);\r
+                     \r
+                DEBUG ((EFI_D_INFO, "Total Cache as RAM:    %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
+                DEBUG ((EFI_D_INFO, "  CAR stack ever used: %d bytes.\n",\r
+                       (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
+                      ));\r
+                DEBUG ((EFI_D_INFO, "  CAR heap used:       %d bytes.\n",\r
+                       ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -\r
+                       (UINTN) Private->HobList.Raw)\r
+                      ));\r
+              DEBUG_CODE_END ();\r
+              \r
+              //\r
+              // Reserve the size of new stack at bottom of physical memory\r
+              //\r
+              OldPeiStackSize = (UINT64) SecCoreData->StackSize;\r
+              NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;\r
+              if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {\r
+                Private->StackSize = NewPeiStackSize;\r
+              } else {\r
+                Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize);\r
+              }\r
 \r
               //\r
-              // Make sure we don't retry the same PEIM that added memory\r
+              // In theory, the size of new stack in permenent memory should large than\r
+              // size of old stack in temporary memory.\r
+              // But if new stack is smaller than the size of old stack, we also reserve\r
+              // the size of old stack at bottom of permenent memory.\r
               //\r
-              Private->CurrentPeimCount++;\r
+              DEBUG ((EFI_D_ERROR, "Old Stack Size%d, New stack size%d\n", (INT32) Private->StackSize, (INT32) OldPeiStackSize));\r
+              ASSERT (Private->StackSize >= OldPeiStackSize);\r
+              StackGap = Private->StackSize - OldPeiStackSize;\r
 \r
               //\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
+              // Update HandOffHob for new installed permenent memory\r
               //\r
-              MigrateIdtTable (PeiServices);\r
+              OldHandOffTable   = Private->HobList.HandoffInformationTable;\r
+              OldCheckingBottom = (UINTN)(SecCoreData->TemporaryRamBase);\r
+              OldCheckingTop    = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);\r
 \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
+              // The whole temporary memory will be migrated to physical memory.\r
+              // CAUTION: The new base is computed accounding to gap of new stack.\r
+              //\r
+              NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;\r
+              \r
+              //\r
+              // Caculate stack offset and heap offset between CAR and new permement \r
+              // memory seperately.\r
+              //\r
+              StackOffset            = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase;\r
+              HeapOffset             = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \\r
+                                               (UINTN) SecCoreData->PeiTemporaryRamBase);\r
+              DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64)HeapOffset, (INT64)StackOffset));\r
+              \r
+              //\r
+              // Caculate new HandOffTable and PrivateData address in permenet memory's stack\r
               //\r
-              PrivateInMem = AllocateCopyPool (sizeof (PEI_CORE_INSTANCE), Private);\r
-              ASSERT (PrivateInMem != NULL);\r
+              NewHandOffTable        = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);\r
+              PrivateInMem           = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);\r
 \r
               //\r
-              // Shadow PEI Core. When permanent memory is avaiable, shadow\r
-              // PEI Core and PEIMs to get high performance.\r
+              // TemporaryRamSupportPpi is produced by platform's SEC\r
               //\r
-              PeiCoreFileHandle = NULL;\r
+              Status = PeiLocatePpi (\r
+                         (CONST EFI_PEI_SERVICES **) PeiServices,\r
+                         &gEfiTemporaryRamSupportPpiGuid,\r
+                         0,\r
+                         NULL,\r
+                         (VOID**)&TemporaryRamSupportPpi\r
+                         );\r
+\r
+\r
+              if (!EFI_ERROR (Status)) {\r
+                //\r
+                // Temporary Ram support Ppi is provided by platform, it will copy \r
+                // temporary memory to permenent memory and do stack switching.\r
+                // After invoken temporary Ram support, following code's stack is in \r
+                // memory but not in CAR.\r
+                //\r
+                TemporaryRamSupportPpi->TemporaryRamMigration (\r
+                                          (CONST EFI_PEI_SERVICES **) PeiServices,\r
+                                          (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,\r
+                                          (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,\r
+                                          SecCoreData->TemporaryRamSize\r
+                                          );\r
+\r
+              } else {\r
+                //\r
+                // In IA32/x64/Itanium architecture, we need platform provide\r
+                // TEMPORAY_RAM_MIGRATION_PPI.\r
+                //\r
+                ASSERT (FALSE);\r
+              }\r
+\r
+\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
+              // Fixup the PeiCore's private data\r
+              //\r
+              PrivateInMem->PS          = &PrivateInMem->ServiceTableShadow;\r
+              PrivateInMem->CpuIo       = &PrivateInMem->ServiceTableShadow.CpuIo;\r
+              PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset);\r
+              PrivateInMem->StackBase   = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);\r
+\r
+              PeiServices = (CONST EFI_PEI_SERVICES **) &PrivateInMem->PS;\r
+\r
               //\r
-              // Shadow PEI Core into memory so it will run faster\r
+              // Fixup for PeiService's address\r
               //\r
-              Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState);\r
-              ASSERT_EFI_ERROR (Status);\r
-  \r
+              SetPeiServicesTablePointer(PeiServices);\r
+\r
+              //\r
+              // Update HandOffHob for new installed permenent memory\r
+              //\r
+              NewHandOffTable->EfiEndOfHobList =\r
+                (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset);\r
+              NewHandOffTable->EfiMemoryTop        = PrivateInMem->PhysicalMemoryBegin +\r
+                                                     PrivateInMem->PhysicalMemoryLength;\r
+              NewHandOffTable->EfiMemoryBottom     = PrivateInMem->PhysicalMemoryBegin;\r
+              NewHandOffTable->EfiFreeMemoryTop    = PrivateInMem->FreePhysicalMemoryTop;\r
+              NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +\r
+                                                     sizeof (EFI_HOB_GENERIC_HEADER);\r
+\r
+              //\r
+              // We need convert the PPI desciptor's pointer\r
+              //\r
+              ConvertPpiPointers (PrivateInMem, \r
+                                  OldCheckingBottom, \r
+                                  OldCheckingTop, \r
+                                  HeapOffset\r
+                                  );\r
+\r
+              DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",\r
+                                  PrivateInMem->StackBase,\r
+                                  PrivateInMem->StackSize));\r
+              BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);\r
+\r
               //\r
-              // Switch to memory based stack and reenter PEI Core that has been\r
-              //  shadowed to memory.\r
+              // After the whole temporary memory is migrated, then we can allocate page in\r
+              // permenent memory.\r
               //\r
+              PrivateInMem->PeiMemoryInstalled     = TRUE;\r
+\r
               //\r
-              // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT\r
+              // Indicate that PeiCore reenter\r
               //\r
-              TopOfStack = (VOID *)((UINTN)Private->StackBase + (UINTN)Private->StackSize - CPU_STACK_ALIGNMENT);\r
-              TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
+              PrivateInMem->PeimDispatcherReenter  = TRUE;\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) EntryPoint + ((UINTN) PeiCore - (UINTN) _ModuleEntryPoint)),\r
-                (VOID*) &PeiCoreParameters,  \r
-                TopOfStack,\r
-                (VOID*)(UINTN)Private->StackBase\r
-                );\r
+              //\r
+              // Shadow PEI Core. When permanent memory is avaiable, shadow\r
+              // PEI Core and PEIMs to get high performance.\r
+              //\r
+              PrivateInMem->ShadowedPeiCore = ShadowPeiCore (\r
+                                                PeiServices,\r
+                                                PrivateInMem\r
+                                                );\r
+              //\r
+              // Process the Notify list and dispatch any notifies for\r
+              // newly installed PPIs.\r
+              //\r
+              ProcessNotifyList (PrivateInMem);\r
+\r
+              //\r
+              // Entry PEI Phase 2\r
+              //\r
+              PeiCore (SecCoreData, NULL, PrivateInMem);\r
+\r
+              //\r
+              // Code should not come here\r
+              //\r
+              ASSERT_EFI_ERROR(FALSE);\r
             }\r
 \r
+            //\r
+            // Process the Notify list and dispatch any notifies for\r
+            // newly installed PPIs.\r
+            //\r
+            ProcessNotifyList (Private);\r
+\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
+              // 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
+              PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
               //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
-              \r
+\r
               //\r
               // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
               //\r
@@ -491,83 +664,73 @@ Returns:
     }\r
 \r
     //\r
-    // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go \r
+    // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go\r
     // through all the FV.\r
     //\r
     Private->CurrentPeimFvCount = 0;\r
 \r
     //\r
-    // PeimNeedingDispatch being TRUE means we found a PEIM that did not get \r
+    // PeimNeedingDispatch being TRUE means we found a PEIM that did not get\r
     //  dispatched. So we need to make another pass\r
     //\r
-    // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this \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
-  } while (PeimNeedingDispatch && PeimDispatchOnThisPass);\r
+  } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);\r
 \r
 }\r
 \r
-VOID\r
-InitializeDispatcherData (\r
-  IN PEI_CORE_INSTANCE            *PrivateData,\r
-  IN PEI_CORE_INSTANCE            *OldCoreData,\r
-  IN CONST EFI_SEC_PEI_HAND_OFF   *SecCoreData\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
+/**\r
   Initialize the Dispatcher's data members\r
 \r
-Arguments:\r
-\r
-  PeiServices          - The PEI core services table.\r
-  OldCoreData          - Pointer to old core data (before switching stack).\r
+  @param PrivateData     PeiCore's private data structure\r
+  @param OldCoreData     Old data from SecCore\r
                          NULL if being run in non-permament memory mode.\r
-  SecCoreData          - Points to a data structure containing information about the PEI core's operating\r
+  @param SecCoreData     Points to a data structure containing information about the PEI core's operating\r
                          environment, such as the size and location of temporary RAM, the stack location and\r
                          the BFV location.\r
 \r
-Returns:\r
+  @return None.\r
 \r
-  None.\r
-\r
---*/\r
+**/\r
+VOID\r
+InitializeDispatcherData (\r
+  IN PEI_CORE_INSTANCE            *PrivateData,\r
+  IN PEI_CORE_INSTANCE            *OldCoreData,\r
+  IN CONST EFI_SEC_PEI_HAND_OFF   *SecCoreData\r
+  )\r
 {\r
   if (OldCoreData == NULL) {\r
+    PrivateData->PeimDispatcherReenter = FALSE;\r
     PeiInitializeFv (PrivateData, SecCoreData);\r
   }\r
 \r
   return;\r
 }\r
 \r
+/**\r
+  This routine parses the Dependency Expression, if available, and\r
+  decides if the module can be executed.\r
+\r
+\r
+  @param Private         PeiCore's private data structure\r
+  @param FileHandle      PEIM's file handle\r
+  @param PeimCount       Peim count in all dispatched PEIMs.\r
 \r
+  @retval TRUE   Can be dispatched\r
+  @retval FALSE  Cannot be dispatched\r
+\r
+**/\r
 BOOLEAN\r
 DepexSatisfied (\r
   IN PEI_CORE_INSTANCE          *Private,\r
   IN EFI_PEI_FILE_HANDLE        FileHandle,\r
   IN UINTN                      PeimCount\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This routine parses the Dependency Expression, if available, and\r
-  decides if the module can be executed.\r
-\r
-Arguments:\r
-  PeiServices - The PEI Service Table\r
-  CurrentPeimAddress - Address of the PEIM Firmware File under investigation\r
-\r
-Returns:\r
-  TRUE  - Can be dispatched\r
-  FALSE - Cannot be dispatched\r
-\r
---*/\r
 {\r
-  EFI_STATUS  Status;\r
-  VOID        *DepexData;\r
+  EFI_STATUS           Status;\r
+  VOID                 *DepexData;\r
 \r
   if (PeimCount < Private->AprioriCount) {\r
     //\r
@@ -576,7 +739,15 @@ Returns:
     return TRUE;\r
   }\r
 \r
-  Status = PeiServicesFfsFindSectionData (EFI_SECTION_PEI_DEPEX, FileHandle, (VOID **) &DepexData);\r
+  //\r
+  // Depex section not in the encapsulated section.\r
+  //\r
+  Status = PeiServicesFfsFindSectionData (\r
+              EFI_SECTION_PEI_DEPEX,\r
+              FileHandle,\r
+              (VOID **)&DepexData\r
+              );\r
+\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // If there is no DEPEX, assume the module can be executed\r
@@ -594,13 +765,13 @@ Returns:
   This routine enable a PEIM to register itself to shadow when PEI Foundation\r
   discovery permanent memory.\r
 \r
-       @param FileHandle       File handle of a PEIM.\r
-  \r
-  @retval EFI_NOT_FOUND                                The file handle doesn't point to PEIM itself.\r
-  @retval EFI_ALREADY_STARTED          Indicate that the PEIM has been registered itself.\r
-  @retval EFI_SUCCESS                                          Successfully to register itself.\r
+  @param FileHandle             File handle of a PEIM.\r
 \r
-**/ \r
+  @retval EFI_NOT_FOUND         The file handle doesn't point to PEIM itself.\r
+  @retval EFI_ALREADY_STARTED   Indicate that the PEIM has been registered itself.\r
+  @retval EFI_SUCCESS           Successfully to register itself.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 PeiRegisterForShadow (\r
@@ -623,48 +794,9 @@ PeiRegisterForShadow (
     //\r
     return EFI_ALREADY_STARTED;\r
   }\r
-  \r
+\r
   Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
-/**\r
-  This routine invoke the PeiCore's entry in new stack environment.\r
-\r
-       @param Context1         The first context parameter is entry of PeiCore\r
-  @param Context2      The second context parameter is parameter structure point for PeiCore\r
-\r
-**/ \r
-STATIC\r
-VOID\r
-InvokePeiCore (\r
-  VOID          *Context1,\r
-  VOID          *Context2\r
-  )\r
-{\r
-  PEI_CORE_ENTRY_POINT  PeiCoreEntryPoint;\r
-  PEI_CORE_PARAMETERS       *PeiCoreParameters;\r
-\r
-  //\r
-  // Running on new stack in SEC Core\r
-  //\r
-\r
-  PeiCoreEntryPoint = (PEI_CORE_ENTRY_POINT) (UINTN) Context1;\r
-  PeiCoreParameters = (PEI_CORE_PARAMETERS *)Context2;\r
-\r
-  //\r
-  // Call PEI Core using new stack\r
-  //\r
-  PeiCoreEntryPoint (\r
-    PeiCoreParameters->SecCoreData,\r
-    PeiCoreParameters->PpiList,\r
-    PeiCoreParameters->Data\r
-    );\r
-\r
-  //\r
-  // Never returns\r
-  //\r
-  ASSERT_EFI_ERROR (FALSE);\r
-}\r