/** @file\r
EFI PEI Core dispatch services\r
\r
-Copyright (c) 2006 - 2009, Intel Corporation\r
+Copyright (c) 2006 - 2010, 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
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_GUID *Guid;\r
EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
-\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
// Go ahead to scan this Fv, and cache FileHandles within it.\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
+ Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);\r
if (Status != EFI_SUCCESS) {\r
break;\r
}\r
//\r
ASSERT (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv));\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
//\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 & 0x00FFFFFF;\r
+ Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);\r
Private->AprioriCount /= sizeof (EFI_GUID);\r
\r
ZeroMem (FileGuid, sizeof (FileGuid));\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, Private->CurrentFvFileHandles[Index], &FileInfo);\r
+ CopyMem (&FileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));\r
}\r
\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
+ Status = PrivateInMem->Fv[0].FvPpi->FindFileByType (\r
+ PrivateInMem->Fv[0].FvPpi,\r
+ EFI_FV_FILETYPE_PEI_CORE,\r
+ PrivateInMem->Fv[0].FvHandle,\r
+ &PeiCoreFileHandle\r
+ );\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
Status = PeiLoadImage (\r
PeiServices,\r
*((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),\r
+ PEIM_STATE_REGISITER_FOR_SHADOW,\r
&EntryPoint,\r
&AuthenticationState\r
);\r
//\r
return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);\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_PHYSICAL_ADDRESS MaxMemoryBaseAddress;\r
+ UINT64 MaxMemoryLength;\r
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
+ //\r
+ // Initialize Local Variables\r
+ //\r
+ CurrentResourceHob = NULL;\r
+ ResourceHob = NULL;\r
+ NextResourceHob = NULL;\r
+ MaxMemoryBaseAddress = 0;\r
+ MaxMemoryLength = 0;\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 heigher 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
+ // 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 heigher 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 memroy 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 seperate 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
+ // 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 descrior 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
+ // Print the recomended 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
+ \r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ //\r
+ // See if this resource descrior 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
+ // 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
+ \r
+ ResourceHob = Hob.ResourceDescriptor; \r
+ //\r
+ // See if this resource descrior 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
+ // 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 memmory 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
+ // reinstall the PEI memory relative to TopLoadingAddress\r
+ //\r
+ PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;\r
+ PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;\r
+}\r
/**\r
Conduct PEIM dispatch.\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
EFI_FV_FILE_INFO FvFileInfo;\r
UINTN OldCheckingTop;\r
UINTN OldCheckingBottom;\r
+ PEI_CORE_FV_HANDLE *CoreFvHandle;\r
+ VOID *LoadFixPeiCodeBegin;\r
\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
if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
Status = PeiLoadImage (\r
- (CONST EFI_PEI_SERVICES **) &Private->PS,\r
+ (CONST EFI_PEI_SERVICES **) &Private->Ps,\r
PeimFileHandle,\r
+ PEIM_STATE_REGISITER_FOR_SHADOW,\r
&EntryPoint,\r
&AuthenticationState\r
);\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 (PeimFileHandle, "PEIM", NULL, 0);\r
+ PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);\r
+ PERF_END (PeimFileHandle, "PEIM", NULL, 0);\r
}\r
\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
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
//\r
- Status = ProcessFvFile (PeiServices, VolumeHandle, PeimFileHandle, &AuthenticationState);\r
+ Status = ProcessFvFile (&Private->Fv[FvCount], PeimFileHandle);\r
+ AuthenticationState = 0;\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
// 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
+ PERF_START (PeimFileHandle, "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
+ (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
(VOID *)(&ExtendedData),\r
sizeof (ExtendedData)\r
);\r
\r
- Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);\r
+ Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle);\r
if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {\r
//\r
// PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
\r
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
EFI_PROGRESS_CODE,\r
- FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
+ (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
(VOID *)(&ExtendedData),\r
sizeof (ExtendedData)\r
);\r
- PERF_END (0, "PEIM", NULL, 0);\r
+ PERF_END (PeimFileHandle, "PEIM", NULL, 0);\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
+ // 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
OldPeiStackSize = (UINT64) SecCoreData->StackSize;\r
NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;\r
- if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {\r
+ if (PcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {\r
Private->StackSize = NewPeiStackSize;\r
} else {\r
- Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize);\r
+ Private->StackSize = PcdGet32(PcdPeiCoreMaxPeiStackSize);\r
}\r
\r
//\r
//\r
// Fixup the PeiCore's private data\r
//\r
- PrivateInMem->PS = &PrivateInMem->ServiceTableShadow;\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
+ PeiServices = (CONST EFI_PEI_SERVICES **) &PrivateInMem->Ps;\r
\r
//\r
// Fixup for PeiService's address\r
//\r
PrivateInMem->PeimDispatcherReenter = TRUE;\r
\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (PrivateInMem->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+ //\r
+ // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.\r
+ // Every bit in the array indicate the status of the corresponding memory page available or not\r
+ //\r
+ PrivateInMem->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));\r
+ }\r
//\r
// Shadow PEI Core. When permanent memory is avaiable, shadow\r
// PEI Core and PEIMs to get high performance.\r
if (OldCoreData == NULL) {\r
PrivateData->PeimDispatcherReenter = FALSE;\r
PeiInitializeFv (PrivateData, SecCoreData);\r
+ } else {\r
+ PeiReinitializeFv (PrivateData);\r
}\r
\r
return;\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_SUCCESS;\r
}\r
\r
+\r
+\r