+ GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe\r
+ // the allocated memory range\r
+ //\r
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ //\r
+ // See if this is a memory allocation HOB\r
+ //\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
+ MemoryHob = Hob.MemoryAllocation;\r
+ for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (NextHob); NextHob.Raw = GET_NEXT_HOB (NextHob)) {\r
+ //\r
+ // See if this is a resource descriptor HOB\r
+ //\r
+ if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ NextResourceHob = NextHob.ResourceDescriptor;\r
+ //\r
+ // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.\r
+ //\r
+ if ((NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) || (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If the range describe in memory allocation HOB belongs to the memory range described by the resource HOB\r
+ //\r
+ if ((MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart) &&\r
+ (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength))\r
+ {\r
+ //\r
+ // Build separate resource HOB for this allocated range\r
+ //\r
+ if (MemoryHob->AllocDescriptor.MemoryBaseAddress > NextResourceHob->PhysicalStart) {\r
+ BuildResourceDescriptorHob (\r
+ EFI_RESOURCE_SYSTEM_MEMORY,\r
+ NextResourceHob->ResourceAttribute,\r
+ NextResourceHob->PhysicalStart,\r
+ (MemoryHob->AllocDescriptor.MemoryBaseAddress - NextResourceHob->PhysicalStart)\r
+ );\r
+ }\r
+\r
+ if (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength < NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {\r
+ BuildResourceDescriptorHob (\r
+ EFI_RESOURCE_SYSTEM_MEMORY,\r
+ NextResourceHob->ResourceAttribute,\r
+ MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength,\r
+ (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength -(MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength))\r
+ );\r
+ }\r
+\r
+ NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
+ NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Try to find and validate the TOP address.\r
+ //\r
+ if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0 ) {\r
+ //\r
+ // The LMFA feature is enabled as load module at fixed absolute address.\r
+ //\r
+ TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdLoadModuleAtFixAddressEnable);\r
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));\r
+ //\r
+ // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range\r
+ //\r
+ if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {\r
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress));\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ //\r
+ // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies\r
+ //\r
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ //\r
+ // See if this is a resource descriptor HOB\r
+ //\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ //\r
+ // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS\r
+ //\r
+ if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS))\r
+ {\r
+ //\r
+ // See if Top address specified by user is valid.\r
+ //\r
+ if ((ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress) &&\r
+ ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress) &&\r
+ PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob))\r
+ {\r
+ CurrentResourceHob = ResourceHob;\r
+ CurrentHob = Hob;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (CurrentResourceHob != NULL) {\r
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress));\r
+ TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress));\r
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));\r
+ //\r
+ // Print the recommended Top address range.\r
+ //\r
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ //\r
+ // See if this is a resource descriptor HOB\r
+ //\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ //\r
+ // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS\r
+ //\r
+ if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS))\r
+ {\r
+ //\r
+ // See if Top address specified by user is valid.\r
+ //\r
+ if ((ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob)) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "(0x%lx, 0x%lx)\n",\r
+ (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE),\r
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE)\r
+ ));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Assert here\r
+ //\r
+ ASSERT (FALSE);\r
+ return;\r
+ }\r
+ } else {\r
+ //\r
+ // The LMFA feature is enabled as load module at fixed offset relative to TOLM\r
+ // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)\r
+ //\r
+ //\r
+ // Search for a tested memory region that is below MAX_ADDRESS\r
+ //\r
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ //\r
+ // See if this is a resource descriptor HOB\r
+ //\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ //\r
+ // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS\r
+ //\r
+ if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) &&\r
+ (ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob))\r
+ {\r
+ //\r
+ // See if this is the highest largest system memory region below MaxAddress\r
+ //\r
+ if (ResourceHob->PhysicalStart > HighAddress) {\r
+ CurrentResourceHob = ResourceHob;\r
+ CurrentHob = Hob;\r
+ HighAddress = CurrentResourceHob->PhysicalStart;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (CurrentResourceHob == NULL) {\r
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));\r
+ //\r
+ // Assert here\r
+ //\r
+ ASSERT (FALSE);\r
+ return;\r
+ } else {\r
+ TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength;\r
+ }\r
+ }\r
+\r
+ if (CurrentResourceHob != NULL) {\r
+ //\r
+ // rebuild resource HOB for PEI memory and reserved memory\r
+ //\r
+ BuildResourceDescriptorHob (\r
+ EFI_RESOURCE_SYSTEM_MEMORY,\r
+ (\r
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+ EFI_RESOURCE_ATTRIBUTE_TESTED |\r
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+ ),\r
+ (TopLoadingAddress - TotalReservedMemorySize),\r
+ TotalReservedMemorySize\r
+ );\r
+ //\r
+ // rebuild resource for the remain memory if necessary\r
+ //\r
+ if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {\r
+ BuildResourceDescriptorHob (\r
+ EFI_RESOURCE_SYSTEM_MEMORY,\r
+ (\r
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+ ),\r
+ CurrentResourceHob->PhysicalStart,\r
+ (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart)\r
+ );\r
+ }\r
+\r
+ if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {\r
+ BuildResourceDescriptorHob (\r
+ EFI_RESOURCE_SYSTEM_MEMORY,\r
+ (\r
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+ ),\r
+ TopLoadingAddress,\r
+ (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress)\r
+ );\r
+ }\r
+\r
+ //\r
+ // Delete CurrentHob by marking it as unused since the memory range described by is rebuilt.\r
+ //\r
+ GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;\r
+ }\r
+\r
+ //\r
+ // Cache the top address for Loading Module at Fixed Address feature\r
+ //\r
+ PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;\r
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));\r
+ //\r
+ // reinstall the PEI memory relative to TopLoadingAddress\r
+ //\r
+ PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;\r
+ PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;\r
+}\r
+\r
+/**\r
+ This routine is invoked in switch stack as PeiCore Entry.\r
+\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
+ @param Private Pointer to old core data that is used to initialize the\r
+ core's data areas.\r
+**/\r
+VOID\r
+EFIAPI\r
+PeiCoreEntry (\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
+ IN PEI_CORE_INSTANCE *Private\r
+ )\r
+{\r
+ //\r
+ // Entry PEI Phase 2\r
+ //\r
+ 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 permanent memory, calculate the heap and stack\r
+ // usage in temporary memory for debugging.\r
+ //\r
+ DEBUG_CODE_BEGIN ();\r
+ UINT32 *StackPointer;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+\r
+ for ( StackPointer = (UINT32 *)SecCoreData->StackBase;\r
+ (StackPointer < (UINT32 *)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \\r
+ && (*StackPointer == PcdGet32 (PcdInitValueInTempStack));\r
+ StackPointer++)\r
+ {\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));\r
+ DEBUG ((DEBUG_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize));\r
+ DEBUG ((DEBUG_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " temporary memory stack ever used: %d bytes.\n",\r
+ (UINT32)(SecCoreData->StackSize - ((UINTN)StackPointer - (UINTN)SecCoreData->StackBase))\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " temporary memory heap used for HobList: %d bytes.\n",\r
+ (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " temporary memory heap occupied by memory pages: %d bytes.\n",\r
+ (UINT32)(UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop - Private->HobList.HandoffInformationTable->EfiFreeMemoryTop)\r
+ ));\r
+ for (Hob.Raw = Private->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \\r
+ Hob.MemoryAllocation->AllocDescriptor.MemoryType, \\r
+ Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, \\r
+ Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1\r
+ ));\r
+ }\r
+ }\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 ((DEBUG_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 permanent 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 permanent memory.\r
+ //\r
+ NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);\r
+ NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);\r
+ NewStackSize = MIN (PcdGet32 (PcdPeiCoreMaxPeiStackSize), NewStackSize);\r
+ DEBUG ((DEBUG_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 permanent\r
+ // memory separately.\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
+\r
+ Private->StackOffsetPositive = StackOffsetPositive;\r
+ Private->StackOffset = StackOffset;\r
+\r
+ //\r
+ // Build Stack HOB that describes the permanent memory stack\r
+ //\r
+ DEBUG ((DEBUG_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 ((DEBUG_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 permanent 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
+ // Migrate memory pages allocated in pre-memory phase.\r
+ // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()\r
+ // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().\r
+ //\r
+ MigrateMemoryPages (Private, TRUE);\r
+\r
+ //\r
+ // Entry PEI Phase 2\r
+ //\r
+ PeiCore (SecCoreData, NULL, Private);\r
+ } else {\r
+ //\r
+ // Migrate memory pages allocated in pre-memory phase.\r
+ //\r
+ MigrateMemoryPages (Private, FALSE);\r
+\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
+\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 ((DEBUG_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, PeiTemporaryRamBase, HeapTemporaryRamSize);\r
+\r
+ //\r
+ // Migrate Stack\r
+ //\r
+ CopyMem ((UINT8 *)(UINTN)(TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);\r
+\r
+ //\r
+ // Copy Hole Range Data\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
+\r
+ if (TemporaryRamBase < TempBase1) {\r
+ Private->HoleData[0].Base = TemporaryRamBase;\r
+ Private->HoleData[0].Size = (UINTN)(TempBase1 - TemporaryRamBase);\r
+ }\r
+\r
+ if (TempBase1 + TempSize1 < TempBase2) {\r
+ Private->HoleData[1].Base = TempBase1 + TempSize1;\r
+ Private->HoleData[1].Size = (UINTN)(TempBase2 - TempBase1 - TempSize1);\r
+ }\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
+\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