]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
MdeModulePkg PeiCore: Recheck SwitchStackSignal after ProcessNotifyList()
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
index 46e990d75df06532803d16ace2822e2861e55af2..7480b662c579cbb86a0c915736f5d38480566ea7 100644 (file)
@@ -626,6 +626,291 @@ PeiCoreEntry (
   PeiCore (SecCoreData, NULL, Private);\r
 }\r
 \r
+/**\r
+  Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.\r
+\r
+  @param[in] 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
+  @param[in] Private        Pointer to the private data passed in from caller.\r
+\r
+**/\r
+VOID\r
+PeiCheckAndSwitchStack (\r
+  IN CONST EFI_SEC_PEI_HAND_OFF         *SecCoreData,\r
+  IN PEI_CORE_INSTANCE                  *Private\r
+  )\r
+{\r
+  VOID                                  *LoadFixPeiCodeBegin;\r
+  EFI_STATUS                            Status;\r
+  CONST EFI_PEI_SERVICES                **PeiServices;\r
+  UINT64                                NewStackSize;\r
+  EFI_PHYSICAL_ADDRESS                  TopOfOldStack;\r
+  EFI_PHYSICAL_ADDRESS                  TopOfNewStack;\r
+  UINTN                                 StackOffset;\r
+  BOOLEAN                               StackOffsetPositive;\r
+  EFI_PHYSICAL_ADDRESS                  TemporaryRamBase;\r
+  UINTN                                 TemporaryRamSize;\r
+  UINTN                                 TemporaryStackSize;\r
+  VOID                                  *TemporaryStackBase;\r
+  UINTN                                 PeiTemporaryRamSize;\r
+  VOID                                  *PeiTemporaryRamBase;\r
+  EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI     *TemporaryRamSupportPpi;\r
+  EFI_PHYSICAL_ADDRESS                  BaseOfNewHeap;\r
+  EFI_PHYSICAL_ADDRESS                  HoleMemBase;\r
+  UINTN                                 HoleMemSize;\r
+  UINTN                                 HeapTemporaryRamSize;\r
+  EFI_PHYSICAL_ADDRESS                  TempBase1;\r
+  UINTN                                 TempSize1;\r
+  EFI_PHYSICAL_ADDRESS                  TempBase2;\r
+  UINTN                                 TempSize2;\r
+  UINTN                                 Index;\r
+\r
+  PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;\r
+\r
+  if (Private->SwitchStackSignal) {\r
+    //\r
+    // Before switch stack from temporary memory to permenent memory, calculate 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, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));\r
+        DEBUG ((EFI_D_INFO, "Temp Heap  : BaseAddress=0x%p Length=0x%X\n", Private->HobList.Raw, (UINT32)((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN) Private->HobList.Raw)));\r
+        DEBUG ((EFI_D_INFO, "Total temporary memory:    %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
+        DEBUG ((EFI_D_INFO, "  temporary memory stack ever used: %d bytes.\n",\r
+               (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
+              ));\r
+        DEBUG ((EFI_D_INFO, "  temporary memory heap used:       %d bytes.\n",\r
+               (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)\r
+              ));\r
+    DEBUG_CODE_END ();\r
+\r
+    if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+      //\r
+      // Loading Module at Fixed Address is enabled\r
+      //\r
+      PeiLoadFixAddressHook (Private);\r
+\r
+      //\r
+      // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.\r
+      //\r
+      LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
+      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64)(UINTN)LoadFixPeiCodeBegin, (UINT64)((UINTN)LoadFixPeiCodeBegin + PcdGet32(PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE)));\r
+    }\r
+\r
+    //\r
+    // Reserve the size of new stack at bottom of physical memory\r
+    //\r
+    // The size of new stack in permenent memory must be the same size \r
+    // or larger than the 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
+    NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);\r
+    NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);\r
+    NewStackSize = MIN (PcdGet32(PcdPeiCoreMaxPeiStackSize), NewStackSize);\r
+    DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));\r
+    ASSERT (NewStackSize >= SecCoreData->StackSize);\r
+\r
+    //\r
+    // Calculate stack offset and heap offset between temporary memory and new permement \r
+    // memory seperately.\r
+    //\r
+    TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;\r
+    TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;\r
+    if (TopOfNewStack >= TopOfOldStack) {\r
+      StackOffsetPositive = TRUE;\r
+      StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);\r
+    } else {\r
+      StackOffsetPositive = FALSE;\r
+      StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);\r
+    }\r
+    Private->StackOffsetPositive = StackOffsetPositive;\r
+    Private->StackOffset = StackOffset;\r
+\r
+    //\r
+    // Build Stack HOB that describes the permanent memory stack\r
+    //\r
+    DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));\r
+    BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);\r
+\r
+    //\r
+    // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address\r
+    //\r
+    TemporaryRamBase    = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;\r
+    TemporaryRamSize    = SecCoreData->TemporaryRamSize;\r
+    TemporaryStackSize  = SecCoreData->StackSize;\r
+    TemporaryStackBase  = SecCoreData->StackBase;\r
+    PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;\r
+    PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;\r
+\r
+    //\r
+    // TemporaryRamSupportPpi is produced by platform's SEC\r
+    //\r
+    Status = PeiServicesLocatePpi (\r
+               &gEfiTemporaryRamSupportPpiGuid,\r
+               0,\r
+               NULL,\r
+               (VOID**)&TemporaryRamSupportPpi\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Heap Offset\r
+      //\r
+      BaseOfNewHeap = TopOfNewStack;\r
+      if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
+        Private->HeapOffsetPositive = TRUE;\r
+        Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
+      } else {\r
+        Private->HeapOffsetPositive = FALSE;\r
+        Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
+      }\r
+\r
+      DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
+\r
+      //\r
+      // Calculate new HandOffTable and PrivateData address in permanent memory's stack\r
+      //\r
+      if (StackOffsetPositive) {\r
+        SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);\r
+        Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);\r
+      } else {\r
+        SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);\r
+        Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);\r
+      }\r
+\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 invoking Temporary Ram Support PPI, the following code's \r
+      // stack is in permanent memory.\r
+      //\r
+      TemporaryRamSupportPpi->TemporaryRamMigration (\r
+                                PeiServices,\r
+                                TemporaryRamBase,\r
+                                (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),\r
+                                TemporaryRamSize\r
+                                );\r
+\r
+      //\r
+      // Entry PEI Phase 2\r
+      //\r
+      PeiCore (SecCoreData, NULL, Private);\r
+    } else {\r
+      //\r
+      // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.\r
+      //\r
+      MigratePeiServicesTablePointer ();\r
+                \r
+      //\r
+      // Heap Offset\r
+      //\r
+      BaseOfNewHeap = TopOfNewStack;\r
+      HoleMemBase   = TopOfNewStack;\r
+      HoleMemSize   = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;\r
+      if (HoleMemSize != 0) {\r
+        //\r
+        // Make sure HOB List start address is 8 byte alignment.\r
+        //\r
+        BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);\r
+      }\r
+      if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
+        Private->HeapOffsetPositive = TRUE;\r
+        Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
+      } else {\r
+        Private->HeapOffsetPositive = FALSE;\r
+        Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
+      }\r
+\r
+      DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
+\r
+      //\r
+      // Migrate Heap\r
+      //\r
+      HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);\r
+      ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);\r
+      CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, (UINT8 *) PeiTemporaryRamBase, HeapTemporaryRamSize);\r
+\r
+      //\r
+      // Migrate Stack\r
+      //\r
+      CopyMem ((UINT8 *) (UINTN) (TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);\r
+\r
+      //\r
+      // Copy Hole Range Data\r
+      // Convert PPI from Hole. \r
+      //\r
+      if (HoleMemSize != 0) {\r
+        //\r
+        // Prepare Hole\r
+        //\r
+        if (PeiTemporaryRamBase < TemporaryStackBase) {\r
+          TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
+          TempSize1 = PeiTemporaryRamSize;\r
+          TempBase2 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
+          TempSize2 = TemporaryStackSize;\r
+        } else {\r
+          TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
+          TempSize1 = TemporaryStackSize;\r
+          TempBase2 =(EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
+          TempSize2 = PeiTemporaryRamSize;\r
+        }\r
+        if (TemporaryRamBase < TempBase1) {\r
+          Private->HoleData[0].Base = TemporaryRamBase;\r
+          Private->HoleData[0].Size = (UINTN) (TempBase1 - TemporaryRamBase);\r
+        }\r
+        if (TempBase1 + TempSize1 < TempBase2) {\r
+          Private->HoleData[1].Base = TempBase1 + TempSize1;\r
+          Private->HoleData[1].Size = (UINTN) (TempBase2 - TempBase1 - TempSize1);\r
+        }\r
+        if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {\r
+          Private->HoleData[2].Base = TempBase2 + TempSize2;\r
+          Private->HoleData[2].Size = (UINTN) (TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);\r
+        }\r
+\r
+        //\r
+        // Copy Hole Range data.\r
+        //\r
+        for (Index = 0; Index < HOLE_MAX_NUMBER; Index ++) {\r
+          if (Private->HoleData[Index].Size > 0) {\r
+            if (HoleMemBase > Private->HoleData[Index].Base) {\r
+              Private->HoleData[Index].OffsetPositive = TRUE;\r
+              Private->HoleData[Index].Offset = (UINTN) (HoleMemBase - Private->HoleData[Index].Base);\r
+            } else {\r
+              Private->HoleData[Index].OffsetPositive = FALSE;\r
+              Private->HoleData[Index].Offset = (UINTN) (Private->HoleData[Index].Base - HoleMemBase);\r
+            }\r
+            CopyMem ((VOID *) (UINTN) HoleMemBase, (VOID *) (UINTN) Private->HoleData[Index].Base, Private->HoleData[Index].Size);\r
+            HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;\r
+          }\r
+        }\r
+      }\r
+\r
+      //\r
+      // Switch new stack\r
+      //\r
+      SwitchStack (\r
+        (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,\r
+        (VOID *) SecCoreData,\r
+        (VOID *) Private,\r
+        (VOID *) (UINTN) TopOfNewStack\r
+        );\r
+    }\r
+\r
+    //\r
+    // Code should not come here\r
+    //\r
+    ASSERT (FALSE);\r
+  }\r
+}\r
+\r
 /**\r
   Conduct PEIM dispatch.\r
 \r
@@ -654,30 +939,8 @@ PeiDispatcher (
   UINTN                               SaveCurrentPeimCount;\r
   UINTN                               SaveCurrentFvCount;\r
   EFI_PEI_FILE_HANDLE                 SaveCurrentFileHandle;\r
-  EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI   *TemporaryRamSupportPpi;\r
-  UINT64                              NewStackSize;\r
-  UINTN                               HeapTemporaryRamSize;\r
-  EFI_PHYSICAL_ADDRESS                BaseOfNewHeap;\r
-  EFI_PHYSICAL_ADDRESS                TopOfNewStack;\r
-  EFI_PHYSICAL_ADDRESS                TopOfOldStack;\r
-  EFI_PHYSICAL_ADDRESS                TemporaryRamBase;\r
-  UINTN                               TemporaryRamSize;\r
-  UINTN                               TemporaryStackSize;\r
-  VOID                                *TemporaryStackBase;\r
-  UINTN                               PeiTemporaryRamSize;\r
-  VOID                                *PeiTemporaryRamBase;\r
-  UINTN                               StackOffset;\r
-  BOOLEAN                             StackOffsetPositive;\r
-  EFI_PHYSICAL_ADDRESS                HoleMemBase;\r
-  UINTN                               HoleMemSize;\r
   EFI_FV_FILE_INFO                    FvFileInfo;\r
   PEI_CORE_FV_HANDLE                  *CoreFvHandle;\r
-  VOID                                *LoadFixPeiCodeBegin;\r
-  EFI_PHYSICAL_ADDRESS                TempBase1;\r
-  UINTN                               TempSize1;\r
-  EFI_PHYSICAL_ADDRESS                TempBase2;\r
-  UINTN                               TempSize2;\r
-  UINTN                               Index;\r
   \r
   PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;\r
   PeimEntryPoint = NULL;\r
@@ -853,247 +1116,7 @@ PeiDispatcher (
               }\r
             }\r
 \r
-            if (Private->SwitchStackSignal) {\r
-              //\r
-              // Before switch stack from temporary memory to permenent memory, calculate 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, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));\r
-                DEBUG ((EFI_D_INFO, "Temp Heap  : BaseAddress=0x%p Length=0x%X\n", Private->HobList.Raw, (UINT32)((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN) Private->HobList.Raw)));\r
-                DEBUG ((EFI_D_INFO, "Total temporary memory:    %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
-                DEBUG ((EFI_D_INFO, "  temporary memory stack ever used: %d bytes.\n",\r
-                       (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
-                      ));\r
-                DEBUG ((EFI_D_INFO, "  temporary memory heap used:       %d bytes.\n",\r
-                       (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)\r
-                      ));\r
-              DEBUG_CODE_END ();\r
-              \r
-              if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
-                //\r
-                // Loading Module at Fixed Address is enabled\r
-                //\r
-                PeiLoadFixAddressHook (Private);\r
-\r
-                //\r
-                // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.\r
-                //\r
-                LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
-                DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64)(UINTN)LoadFixPeiCodeBegin, (UINT64)((UINTN)LoadFixPeiCodeBegin + PcdGet32(PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE)));\r
-              }\r
-              \r
-              //\r
-              // Reserve the size of new stack at bottom of physical memory\r
-              //\r
-              // The size of new stack in permenent memory must be the same size \r
-              // or larger than the 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
-              NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);\r
-              NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);\r
-              NewStackSize = MIN (PcdGet32(PcdPeiCoreMaxPeiStackSize), NewStackSize);\r
-              DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));\r
-              ASSERT (NewStackSize >= SecCoreData->StackSize);\r
-\r
-              //\r
-              // Calculate stack offset and heap offset between temporary memory and new permement \r
-              // memory seperately.\r
-              //\r
-              TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;\r
-              TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;\r
-              if (TopOfNewStack >= TopOfOldStack) {\r
-                StackOffsetPositive = TRUE;\r
-                StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);\r
-              } else {\r
-                StackOffsetPositive = FALSE;\r
-                StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);\r
-              }\r
-              Private->StackOffsetPositive = StackOffsetPositive;\r
-              Private->StackOffset = StackOffset;\r
-\r
-              //\r
-              // Build Stack HOB that describes the permanent memory stack\r
-              //\r
-              DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));\r
-              BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);\r
-\r
-              //\r
-              // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address\r
-              //\r
-              TemporaryRamBase    = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;\r
-              TemporaryRamSize    = SecCoreData->TemporaryRamSize;\r
-              TemporaryStackSize  = SecCoreData->StackSize;\r
-              TemporaryStackBase  = SecCoreData->StackBase;\r
-              PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;\r
-              PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;\r
-              \r
-              //\r
-              // TemporaryRamSupportPpi is produced by platform's SEC\r
-              //\r
-              Status = PeiServicesLocatePpi (\r
-                         &gEfiTemporaryRamSupportPpiGuid,\r
-                         0,\r
-                         NULL,\r
-                         (VOID**)&TemporaryRamSupportPpi\r
-                         );\r
-              if (!EFI_ERROR (Status)) {\r
-                //\r
-                // Heap Offset\r
-                //\r
-                BaseOfNewHeap = TopOfNewStack;\r
-                if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
-                  Private->HeapOffsetPositive = TRUE;\r
-                  Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
-                } else {\r
-                  Private->HeapOffsetPositive = FALSE;\r
-                  Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
-                }\r
-\r
-                DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
-\r
-                //\r
-                // Calculate new HandOffTable and PrivateData address in permanent memory's stack\r
-                //\r
-                if (StackOffsetPositive) {\r
-                  SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);\r
-                  Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);\r
-                } else {\r
-                  SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);\r
-                  Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);\r
-                }\r
-\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 invoking Temporary Ram Support PPI, the following code's \r
-                // stack is in permanent memory.\r
-                //\r
-                TemporaryRamSupportPpi->TemporaryRamMigration (\r
-                                          PeiServices,\r
-                                          TemporaryRamBase,\r
-                                          (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),\r
-                                          TemporaryRamSize\r
-                                          );\r
-\r
-                //\r
-                // Entry PEI Phase 2\r
-                //\r
-                PeiCore (SecCoreData, NULL, Private);\r
-              } else {\r
-                //\r
-                // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.\r
-                //\r
-                MigratePeiServicesTablePointer ();\r
-                \r
-                //\r
-                // Heap Offset\r
-                //\r
-                BaseOfNewHeap = TopOfNewStack;\r
-                HoleMemBase   = TopOfNewStack;\r
-                HoleMemSize   = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;\r
-                if (HoleMemSize != 0) {\r
-                  //\r
-                  // Make sure HOB List start address is 8 byte alignment.\r
-                  //\r
-                  BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);\r
-                }\r
-                if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
-                  Private->HeapOffsetPositive = TRUE;\r
-                  Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
-                } else {\r
-                  Private->HeapOffsetPositive = FALSE;\r
-                  Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
-                }\r
-\r
-                DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
-\r
-                //\r
-                // Migrate Heap\r
-                //\r
-                HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);\r
-                ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);\r
-                CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, (UINT8 *) PeiTemporaryRamBase, HeapTemporaryRamSize);\r
-                \r
-                //\r
-                // Migrate Stack\r
-                //\r
-                CopyMem ((UINT8 *) (UINTN) (TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);\r
-                \r
-                //\r
-                // Copy Hole Range Data\r
-                // Convert PPI from Hole. \r
-                //\r
-                if (HoleMemSize != 0) {\r
-                  //\r
-                  // Prepare Hole\r
-                  //\r
-                  if (PeiTemporaryRamBase < TemporaryStackBase) {\r
-                    TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
-                    TempSize1 = PeiTemporaryRamSize;\r
-                    TempBase2 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
-                    TempSize2 = TemporaryStackSize;\r
-                  } else {\r
-                    TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
-                    TempSize1 = TemporaryStackSize;\r
-                    TempBase2 =(EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
-                    TempSize2 = PeiTemporaryRamSize;\r
-                  }\r
-                  if (TemporaryRamBase < TempBase1) {\r
-                    Private->HoleData[0].Base = TemporaryRamBase;\r
-                    Private->HoleData[0].Size = (UINTN) (TempBase1 - TemporaryRamBase);\r
-                  }\r
-                  if (TempBase1 + TempSize1 < TempBase2) {\r
-                    Private->HoleData[1].Base = TempBase1 + TempSize1;\r
-                    Private->HoleData[1].Size = (UINTN) (TempBase2 - TempBase1 - TempSize1);\r
-                  }\r
-                  if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {\r
-                    Private->HoleData[2].Base = TempBase2 + TempSize2;\r
-                    Private->HoleData[2].Size = (UINTN) (TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);\r
-                  }\r
-                  \r
-                  //\r
-                  // Copy Hole Range data.\r
-                  //\r
-                  for (Index = 0; Index < HOLE_MAX_NUMBER; Index ++) {\r
-                    if (Private->HoleData[Index].Size > 0) {\r
-                      if (HoleMemBase > Private->HoleData[Index].Base) {\r
-                        Private->HoleData[Index].OffsetPositive = TRUE;\r
-                        Private->HoleData[Index].Offset = (UINTN) (HoleMemBase - Private->HoleData[Index].Base);\r
-                      } else {\r
-                        Private->HoleData[Index].OffsetPositive = FALSE;\r
-                        Private->HoleData[Index].Offset = (UINTN) (Private->HoleData[Index].Base - HoleMemBase);\r
-                      }\r
-                      CopyMem ((VOID *) (UINTN) HoleMemBase, (VOID *) (UINTN) Private->HoleData[Index].Base, Private->HoleData[Index].Size);\r
-                      HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;\r
-                    }\r
-                  }\r
-                }\r
-\r
-                //\r
-                // Switch new stack\r
-                //\r
-                SwitchStack (\r
-                  (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,\r
-                  (VOID *) SecCoreData,\r
-                  (VOID *) Private,\r
-                  (VOID *) (UINTN) TopOfNewStack\r
-                  );\r
-              }\r
-\r
-              //\r
-              // Code should not come here\r
-              //\r
-              ASSERT (FALSE);\r
-            }\r
+            PeiCheckAndSwitchStack (SecCoreData, Private);\r
 \r
             //\r
             // Process the Notify list and dispatch any notifies for\r
@@ -1101,6 +1124,13 @@ PeiDispatcher (
             //\r
             ProcessNotifyList (Private);\r
 \r
+            //\r
+            // Recheck SwitchStackSignal after ProcessNotifyList()\r
+            // in case PeiInstallPeiMemory() is done in a callback with\r
+            // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.\r
+            //\r
+            PeiCheckAndSwitchStack (SecCoreData, 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 || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
               //\r