/** @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
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "PeiMain.h"\r
\r
-///\r
-/// CAR is filled with this initial value during SEC phase\r
-///\r
-#define INIT_CAR_VALUE 0x5AA55AA5\r
-\r
-typedef struct {\r
- EFI_STATUS_CODE_DATA DataHeader;\r
- EFI_HANDLE Handle;\r
-} PEIM_FILE_HANDLE_EXTENDED_DATA;\r
-\r
/**\r
\r
- Discover all Peims and optional Apriori file in one FV. There is at most one\r
+ Discover all PEIMs and optional Apriori file in one FV. There is at most one\r
Apriori file in one FV.\r
\r
\r
- @param Private - Pointer to the private data passed in from caller\r
- @param VolumeHandle - Fv handle.\r
+ @param Private Pointer to the private data passed in from caller\r
+ @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.\r
\r
**/\r
VOID\r
DiscoverPeimsAndOrderWithApriori (\r
IN PEI_CORE_INSTANCE *Private,\r
- IN EFI_PEI_FV_HANDLE VolumeHandle\r
+ IN PEI_CORE_FV_HANDLE *CoreFileHandle\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_PEI_FV_HANDLE FileHandle;\r
+ EFI_PEI_FILE_HANDLE FileHandle;\r
EFI_PEI_FILE_HANDLE AprioriFileHandle;\r
EFI_GUID *Apriori;\r
UINTN Index;\r
UINTN PeimIndex;\r
UINTN PeimCount;\r
EFI_GUID *Guid;\r
- EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
- EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
+ EFI_PEI_FILE_HANDLE *TempFileHandles;\r
+ EFI_GUID *TempFileGuid;\r
+ EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
+ EFI_FV_FILE_INFO FileInfo;\r
+\r
+ FvPpi = CoreFileHandle->FvPpi;\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
+ Private->CurrentFvFileHandles = NULL;\r
Guid = NULL;\r
- FileHandle = NULL;\r
\r
//\r
- // If the current Fv has been scanned, directly get its cachable record.\r
+ // If the current FV has been scanned, directly get its cached records.\r
//\r
- if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {\r
- CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
+ if (CoreFileHandle->ScanFv) {\r
+ Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;\r
return;\r
}\r
\r
+ TempFileHandles = Private->TempFileHandles;\r
+ TempFileGuid = Private->TempFileGuid;\r
+\r
//\r
- // Go ahead to scan this Fv, and cache FileHandles within it.\r
+ // Go ahead to scan this FV, get PeimCount and cache FileHandles within it to TempFileHandles.\r
//\r
- for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); 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
+ PeimCount = 0;\r
+ FileHandle = NULL;\r
+ do {\r
+ Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (PeimCount >= Private->TempPeimCount) {\r
+ //\r
+ // Run out of room, grow the buffer.\r
+ //\r
+ TempFileHandles = AllocatePool (\r
+ sizeof (EFI_PEI_FILE_HANDLE) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP));\r
+ ASSERT (TempFileHandles != NULL);\r
+ CopyMem (\r
+ TempFileHandles,\r
+ Private->TempFileHandles,\r
+ sizeof (EFI_PEI_FILE_HANDLE) * Private->TempPeimCount\r
+ );\r
+ Private->TempFileHandles = TempFileHandles;\r
+ TempFileGuid = AllocatePool (\r
+ sizeof (EFI_GUID) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP));\r
+ ASSERT (TempFileGuid != NULL);\r
+ CopyMem (\r
+ TempFileGuid,\r
+ Private->TempFileGuid,\r
+ sizeof (EFI_GUID) * Private->TempPeimCount\r
+ );\r
+ Private->TempFileGuid = TempFileGuid;\r
+ Private->TempPeimCount = Private->TempPeimCount + TEMP_FILE_GROWTH_STEP;\r
+ }\r
+\r
+ TempFileHandles[PeimCount++] = FileHandle;\r
}\r
+ } while (!EFI_ERROR (Status));\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a(): Found 0x%x PEI FFS files in the %dth FV\n",\r
+ __FUNCTION__,\r
+ PeimCount,\r
+ Private->CurrentPeimFvCount\r
+ ));\r
\r
- Private->CurrentFvFileHandles[PeimCount] = FileHandle;\r
+ if (PeimCount == 0) {\r
+ //\r
+ // No PEIM FFS file is found, set ScanFv flag and return.\r
+ //\r
+ CoreFileHandle->ScanFv = TRUE;\r
+ return;\r
}\r
\r
+ //\r
+ // Record PeimCount, allocate buffer for PeimState and FvFileHandles.\r
+ //\r
+ CoreFileHandle->PeimCount = PeimCount;\r
+ CoreFileHandle->PeimState = AllocateZeroPool (sizeof (UINT8) * PeimCount);\r
+ ASSERT (CoreFileHandle->PeimState != NULL);\r
+ CoreFileHandle->FvFileHandles = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);\r
+ ASSERT (CoreFileHandle->FvFileHandles != NULL);\r
+\r
+ //\r
+ // Get Apriori File handle\r
+ //\r
Private->AprioriCount = 0;\r
- if (AprioriFileHandle != NULL) {\r
+ Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);\r
+ if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {\r
//\r
// Read the Apriori file\r
//\r
- Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
+ Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
if (!EFI_ERROR (Status)) {\r
//\r
- // Calculate the number of PEIMs in the A Priori list\r
+ // Calculate the number of PEIMs in the Apriori file\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
+ Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Private->AprioriCount = FileInfo.BufferSize;\r
+ if (IS_SECTION2 (FileInfo.Buffer)) {\r
+ Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER2);\r
+ } else {\r
+ Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);\r
+ }\r
Private->AprioriCount /= sizeof (EFI_GUID);\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
+ // 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
+ Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+ CopyMem (&TempFileGuid[Index], &FileInfo.FileName, 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
+ // Walk through TempFileGuid array to find out who is invalid PEIM GUID in Apriori file.\r
+ // Add available PEIMs in Apriori file into FvFileHandles array.\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
+ Index = 0;\r
+ for (Index2 = 0; Index2 < Private->AprioriCount; Index2++) {\r
+ Guid = ScanGuid (TempFileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2]);\r
+ if (Guid != NULL) {\r
+ PeimIndex = ((UINTN)Guid - (UINTN)&TempFileGuid[0])/sizeof (EFI_GUID);\r
+ CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[PeimIndex];\r
+\r
+ //\r
+ // Since we have copied the file handle we can remove it from this list.\r
+ //\r
+ TempFileHandles[PeimIndex] = NULL;\r
}\r
- if (Guid == NULL) {\r
- break;\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 (Index2 = 0; Index2 < PeimCount; Index2++) {\r
+ if (TempFileHandles[Index2] != NULL) {\r
+ CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[Index2];\r
+ TempFileHandles[Index2] = NULL;\r
}\r
- PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);\r
- TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];\r
+ }\r
+ ASSERT (Index == PeimCount);\r
+ }\r
+ } else {\r
+ CopyMem (CoreFileHandle->FvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);\r
+ }\r
\r
+ //\r
+ // The current FV File Handles have been cached. So that we don't have to scan the FV again.\r
+ // Instead, we can retrieve the file handles within this FV from cached records.\r
+ //\r
+ CoreFileHandle->ScanFv = TRUE;\r
+ Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;\r
+}\r
+\r
+//\r
+// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,\r
+// This part of memory still need reserved on the very top of memory so that the DXE Core could\r
+// use these memory for data initialization. This macro should be sync with the same marco\r
+// defined in DXE Core.\r
+//\r
+#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
+/**\r
+ This function is to test if the memory range described in resource HOB is available or not.\r
+\r
+ This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the\r
+ memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is\r
+ available or not.\r
+\r
+ @param PrivateData Pointer to the private data passed in from caller\r
+ @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB\r
+**/\r
+BOOLEAN\r
+PeiLoadFixAddressIsMemoryRangeAvailable (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob\r
+ )\r
+{\r
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
+ BOOLEAN IsAvailable;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+\r
+ IsAvailable = TRUE;\r
+ if (PrivateData == NULL || ResourceHob == NULL) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // test if the memory range describe in the HOB is already allocated.\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
+ if(MemoryHob->AllocDescriptor.MemoryBaseAddress == ResourceHob->PhysicalStart &&\r
+ MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength == ResourceHob->PhysicalStart + ResourceHob->ResourceLength) {\r
+ IsAvailable = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return IsAvailable;\r
+\r
+}\r
+/**\r
+ Hook function for Loading Module at Fixed Address feature\r
+\r
+ This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is\r
+ configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When\r
+ feature is configured as Load Modules at Fixed Offset, the functino is to find the top address which is TOLM-TSEG in general.\r
+ And also the function will re-install PEI memory.\r
+\r
+ @param PrivateData Pointer to the private data passed in from caller\r
+\r
+**/\r
+VOID\r
+PeiLoadFixAddressHook(\r
+ IN PEI_CORE_INSTANCE *PrivateData\r
+ )\r
+{\r
+ EFI_PHYSICAL_ADDRESS TopLoadingAddress;\r
+ UINT64 PeiMemorySize;\r
+ UINT64 TotalReservedMemorySize;\r
+ UINT64 MemoryRangeEnd;\r
+ EFI_PHYSICAL_ADDRESS HighAddress;\r
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
+ EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob;\r
+ EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob;\r
+ EFI_PEI_HOB_POINTERS CurrentHob;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_PEI_HOB_POINTERS NextHob;\r
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
+ //\r
+ // Initialize Local Variables\r
+ //\r
+ CurrentResourceHob = NULL;\r
+ ResourceHob = NULL;\r
+ NextResourceHob = NULL;\r
+ HighAddress = 0;\r
+ TopLoadingAddress = 0;\r
+ MemoryRangeEnd = 0;\r
+ CurrentHob.Raw = PrivateData->HobList.Raw;\r
+ PeiMemorySize = PrivateData->PhysicalMemoryLength;\r
+ //\r
+ // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE\r
+ // then RuntimeCodePage range and Boot time code range.\r
+ //\r
+ TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));\r
+ TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ;\r
+ //\r
+ // PEI memory range lies below the top reserved memory\r
+ //\r
+ TotalReservedMemorySize += PeiMemorySize;\r
+\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize));\r
+ //\r
+ // Loop through the system memory typed HOB to merge the adjacent 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 resource descriptor HOB\r
+ //\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+\r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ //\r
+ // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.\r
+ //\r
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY ||\r
+ ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) {\r
+ continue;\r
+ }\r
+\r
+ for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {\r
+ if (NextHob.Raw == Hob.Raw){\r
+ continue;\r
+ }\r
+ //\r
+ // See if this is a resource descriptor HOB\r
+ //\r
+ if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+\r
+ NextResourceHob = NextHob.ResourceDescriptor;\r
+ //\r
+ // test if range described in this NextResourceHob is system memory and have the same attribute.\r
+ // Note: Here is a assumption that system memory should always be healthy even without test.\r
+ //\r
+ if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
+ (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){\r
+\r
+ //\r
+ // See if the memory range described in ResourceHob and NextResourceHob is adjacent\r
+ //\r
+ if ((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart &&\r
+ ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)||\r
+ (ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart&&\r
+ ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) {\r
+\r
+ MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?\r
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);\r
+\r
+ ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ?\r
+ ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;\r
+\r
+\r
+ ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);\r
+\r
+ ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);\r
+ //\r
+ // Delete the NextResourceHob by marking it as unused.\r
+ //\r
+ 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
- // Since we have copied the file handle we can remove it from this list.\r
+ // See if this is a resource descriptor HOB\r
//\r
- Private->CurrentFvFileHandles[PeimIndex] = NULL;\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
+ // 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
+ // 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
+ 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
+ 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 ((EFI_D_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 ((EFI_D_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
+ // 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
- // Update valid Aprioricount\r
+ // See if this is a resource descriptor HOB\r
//\r
- Private->AprioriCount = Index;\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
\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
+ // 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
+ CurrentResourceHob = ResourceHob;\r
+ CurrentHob = Hob;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (CurrentResourceHob != NULL) {\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress));\r
+ TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress));\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));\r
//\r
- // Add in any PEIMs not in the Apriori file\r
+ // Print the recommended Top address range.\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
+ 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
+\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
+ // See if Top address specified by user is valid.\r
+ //\r
+ if (ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
+ DEBUG ((EFI_D_INFO, "(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
- //Index the end of array contains re-range Pei moudle.\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
- TempFileHandles[Index] = NULL;\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
\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
+ // 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
+ if (CurrentResourceHob == NULL) {\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));\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
+ // Assert here\r
//\r
- CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));\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
+ 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
+ // Delete CurrentHob by marking it as unused since the 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 ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));\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
+ // reinstall the PEI memory relative to TopLoadingAddress\r
//\r
- Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;\r
- CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));\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
- 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
+ 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
- @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
+VOID\r
+PeiCheckAndSwitchStack (\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
+ IN PEI_CORE_INSTANCE *Private\r
)\r
{\r
- EFI_PEI_FILE_HANDLE PeiCoreFileHandle;\r
- EFI_PHYSICAL_ADDRESS EntryPoint;\r
- EFI_STATUS Status;\r
- UINT32 AuthenticationState;\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
- PeiCoreFileHandle = NULL;\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 ((DEBUG_INFO, " temporary memory stack ever used: %d bytes.\n",\r
+ (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
+ ));\r
+ DEBUG ((DEBUG_INFO, " temporary memory heap used for HobList: %d bytes.\n",\r
+ (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)\r
+ ));\r
+ DEBUG ((DEBUG_INFO, " 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 ((DEBUG_INFO, "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
+ DEBUG_CODE_END ();\r
\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
+ 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
- // 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
+ // 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
- // 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
+ // 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 ((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 permanent\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 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
+ 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, 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
+ 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
UINT32 Index1;\r
UINT32 Index2;\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
UINTN SaveCurrentPeimCount;\r
UINTN SaveCurrentFvCount;\r
EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;\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
+ PEI_CORE_FV_HANDLE *CoreFvHandle;\r
\r
- PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;\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
+ if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\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
+ // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.\r
//\r
SaveCurrentPeimCount = Private->CurrentPeimCount;\r
SaveCurrentFvCount = Private->CurrentPeimFvCount;\r
SaveCurrentFileHandle = Private->CurrentFileHandle;\r
\r
- 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
+ for (Index1 = 0; Index1 < Private->FvCount; Index1++) {\r
+ for (Index2 = 0; Index2 < Private->Fv[Index1].PeimCount; Index2++) {\r
+ if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISTER_FOR_SHADOW) {\r
PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
+ Private->CurrentFileHandle = PeimFileHandle;\r
+ Private->CurrentPeimFvCount = Index1;\r
+ Private->CurrentPeimCount = Index2;\r
Status = PeiLoadImage (\r
- (CONST EFI_PEI_SERVICES **) &Private->PS,\r
+ (CONST EFI_PEI_SERVICES **) &Private->Ps,\r
PeimFileHandle,\r
+ PEIM_STATE_REGISTER_FOR_SHADOW,\r
&EntryPoint,\r
&AuthenticationState\r
);\r
if (Status == EFI_SUCCESS) {\r
//\r
- // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
+ // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE\r
//\r
Private->Fv[Index1].PeimState[Index2]++;\r
- Private->CurrentFileHandle = PeimFileHandle;\r
- Private->CurrentPeimFvCount = Index1;\r
- Private->CurrentPeimCount = Index2;\r
//\r
// Call the PEIM entry point\r
//\r
PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
\r
- PERF_START (0, "PEIM", NULL, 0);\r
- PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);\r
- PERF_END (0, "PEIM", NULL, 0);\r
+ PERF_START_IMAGE_BEGIN (PeimFileHandle);\r
+ PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);\r
+ PERF_START_IMAGE_END (PeimFileHandle);\r
}\r
\r
//\r
// Process the Notify list and dispatch any notifies for\r
// newly installed PPIs.\r
//\r
- ProcessNotifyList (Private);\r
+ ProcessDispatchNotifyList (Private);\r
}\r
}\r
}\r
//\r
// This is the main dispatch loop. It will search known FVs for PEIMs and\r
// attempt to dispatch them. If any PEIM gets dispatched through a single\r
- // pass of the dispatcher, it will start over from the Bfv again to see\r
+ // pass of the dispatcher, it will start over from the BFV again to see\r
// if any new PEIMs dependencies got satisfied. With a well ordered\r
// FV where PEIMs are found in the order their dependencies are also\r
- // satisfied, this dipatcher should run only once.\r
+ // satisfied, this dispatcher should run only once.\r
//\r
do {\r
//\r
- // In case that reenter PeiCore happens, the last pass record is still available. \r
+ // In case that reenter PeiCore happens, the last pass record is still available.\r
//\r
if (!Private->PeimDispatcherReenter) {\r
Private->PeimNeedingDispatch = FALSE;\r
} else {\r
Private->PeimDispatcherReenter = FALSE;\r
}\r
- \r
+\r
for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
- Private->CurrentPeimFvCount = FvCount;\r
+ CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);\r
+ ASSERT (CoreFvHandle != NULL);\r
+\r
//\r
- // Get this Fv Handle by PeiService FvFindNextVolume.\r
+ // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.\r
//\r
- PeiFvFindNextVolume (PeiServices, FvCount, &VolumeHandle);\r
+ if (CoreFvHandle->FvPpi == NULL) {\r
+ continue;\r
+ }\r
+\r
+ Private->CurrentPeimFvCount = FvCount;\r
\r
if (Private->CurrentPeimCount == 0) {\r
//\r
// reorder all PEIMs to ensure the PEIMs in Apriori file to get\r
// dispatch at first.\r
//\r
- DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle);\r
+ DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);\r
}\r
\r
//\r
- // Start to dispatch all modules within the current Fv.\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
+ PeimCount < Private->Fv[FvCount].PeimCount;\r
PeimCount++) {\r
Private->CurrentPeimCount = PeimCount;\r
PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
Private->PeimNeedingDispatch = TRUE;\r
} else {\r
- Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo);\r
+ Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, 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
+ // For FV type file, Produce new FvInfo PPI and FV HOB\r
//\r
- Status = ProcessFvFile (PeiServices, PeimFileHandle, &AuthenticationState);\r
+ Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);\r
+ if (Status == EFI_SUCCESS) {\r
+ //\r
+ // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
+ //\r
+ Private->Fv[FvCount].PeimState[PeimCount]++;\r
+ Private->PeimDispatchOnThisPass = TRUE;\r
+ } else {\r
+ //\r
+ // The related GuidedSectionExtraction/Decompress PPI for the\r
+ // encapsulated FV image section may be installed in the rest\r
+ // of this do-while loop, so need to make another pass.\r
+ //\r
+ Private->PeimNeedingDispatch = TRUE;\r
+ }\r
} else {\r
//\r
// For PEIM driver, Load its entry point\r
Status = PeiLoadImage (\r
PeiServices,\r
PeimFileHandle,\r
+ PEIM_STATE_NOT_DISPATCHED,\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
- // has been found, so invoke it.\r
- //\r
- PERF_START (0, "PEIM", NULL, 0);\r
-\r
- ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;\r
-\r
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
- EFI_PROGRESS_CODE,\r
- FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
- (VOID *)(&ExtendedData),\r
- sizeof (ExtendedData)\r
- );\r
-\r
- Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);\r
- if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {\r
+ if (Status == EFI_SUCCESS) {\r
//\r
- // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
+ // The PEIM has its dependencies satisfied, and its entry point\r
+ // has been found, so invoke it.\r
//\r
- Private->Fv[FvCount].PeimState[PeimCount]++;\r
+ PERF_START_IMAGE_BEGIN (PeimFileHandle);\r
+\r
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
+ (VOID *)(&PeimFileHandle),\r
+ sizeof (PeimFileHandle)\r
+ );\r
\r
- if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+ Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);\r
+ if (Status != EFI_SECURITY_VIOLATION) {\r
+ //\r
+ // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
+ //\r
+ Private->Fv[FvCount].PeimState[PeimCount]++;\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
+ Private->PeimDispatchOnThisPass = TRUE;\r
+ } else {\r
+ //\r
+ // The related GuidedSectionExtraction PPI for the\r
+ // signed PEIM image section may be installed in the rest\r
+ // of this do-while loop, so need to make another pass.\r
+ //\r
+ Private->PeimNeedingDispatch = TRUE;\r
}\r
\r
- Private->PeimDispatchOnThisPass = TRUE;\r
- }\r
-\r
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
- EFI_PROGRESS_CODE,\r
- FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
- (VOID *)(&ExtendedData),\r
- sizeof (ExtendedData)\r
- );\r
- PERF_END (0, "PEIM", NULL, 0);\r
-\r
- }\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
- // 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
- ASSERT (Private->StackSize >= OldPeiStackSize);\r
- StackGap = Private->StackSize - OldPeiStackSize;\r
-\r
- //\r
- // Update HandOffHob for new installed permenent memory\r
- //\r
- OldHandOffTable = Private->HobList.HandoffInformationTable;\r
- OldCheckingBottom = (UINTN)(SecCoreData->TemporaryRamBase);\r
- OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);\r
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),\r
+ (VOID *)(&PeimFileHandle),\r
+ sizeof (PeimFileHandle)\r
+ );\r
+ PERF_START_IMAGE_END (PeimFileHandle);\r
\r
- //\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
- NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);\r
- PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);\r
-\r
- //\r
- // TemporaryRamSupportPpi is produced by platform's SEC\r
- //\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
- //\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
- // Fixup for PeiService's address\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
- // After the whole temporary memory is migrated, then we can allocate page in\r
- // permenent memory.\r
- //\r
- PrivateInMem->PeiMemoryInstalled = TRUE;\r
-\r
- //\r
- // Indicate that PeiCore reenter\r
- //\r
- PrivateInMem->PeimDispatcherReenter = TRUE;\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
+ PeiCheckAndSwitchStack (SecCoreData, Private);\r
+\r
//\r
// Process the Notify list and dispatch any notifies for\r
// newly installed PPIs.\r
//\r
- ProcessNotifyList (Private);\r
+ ProcessDispatchNotifyList (Private);\r
+\r
+ //\r
+ // Recheck SwitchStackSignal after ProcessDispatchNotifyList()\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)) {\r
+ if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \\r
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
//\r
- // If memory is availble we shadow images by default for performance reasons.\r
+ // If memory is available 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
+ if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) {\r
+ //\r
+ // Load PEIM into Memory for Register for shadow PEIM.\r
+ //\r
+ Status = PeiLoadImage (\r
+ PeiServices,\r
+ PeimFileHandle,\r
+ PEIM_STATE_REGISTER_FOR_SHADOW,\r
+ &EntryPoint,\r
+ &AuthenticationState\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
+ }\r
+ }\r
+ ASSERT (PeimEntryPoint != NULL);\r
PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
//PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
\r
//\r
- // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
+ // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE\r
//\r
Private->Fv[FvCount].PeimState[PeimCount]++;\r
\r
// Process the Notify list and dispatch any notifies for\r
// newly installed PPIs.\r
//\r
- ProcessNotifyList (Private);\r
+ ProcessDispatchNotifyList (Private);\r
}\r
}\r
}\r
}\r
\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
+ // Before walking through the next FV, we should set them to NULL/0 to\r
+ // 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
+ Private->CurrentFvFileHandles = NULL;\r
}\r
\r
//\r
- // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go\r
- // through all the FV.\r
+ // Before making another pass, we should set it to 0 to\r
+ // go through all the FVs.\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/FV 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
- // pass. If we did not dispatch a PEIM there is no point in trying again\r
+ // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this\r
+ // pass. If we did not dispatch a PEIM/FV there is no point in trying again\r
// as it will fail the next time too (nothing has changed).\r
//\r
} while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);\r
if (OldCoreData == NULL) {\r
PrivateData->PeimDispatcherReenter = FALSE;\r
PeiInitializeFv (PrivateData, SecCoreData);\r
+ } else {\r
+ PeiReinitializeFv (PrivateData);\r
}\r
\r
return;\r
{\r
EFI_STATUS Status;\r
VOID *DepexData;\r
+ EFI_FV_FILE_INFO FileInfo;\r
+\r
+ Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));\r
+ } else {\r
+ DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));\r
+ }\r
\r
if (PeimCount < Private->AprioriCount) {\r
//\r
- // If its in the A priori file then we set Depex to TRUE\r
+ // If it's in the Apriori file then we set DEPEX to TRUE\r
//\r
+ DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));\r
return TRUE;\r
}\r
\r
//\r
// If there is no DEPEX, assume the module can be executed\r
//\r
+ DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n"));\r
return TRUE;\r
}\r
\r
//\r
// Evaluate a given DEPEX\r
//\r
- return PeimDispatchReadiness (&Private->PS, DepexData);\r
+ return PeimDispatchReadiness (&Private->Ps, DepexData);\r
}\r
\r
/**\r
return EFI_NOT_FOUND;\r
}\r
\r
- if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {\r
+ if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISTER_FOR_SHADOW) {\r
//\r
// If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started\r
//\r
return EFI_ALREADY_STARTED;\r
}\r
\r
- Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;\r
+ Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISTER_FOR_SHADOW;\r
\r
return EFI_SUCCESS;\r
}\r
\r
+\r
+\r