// 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
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
}\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
// 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
+ (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
} \r
//\r
// See if Top address specified by user is valid.\r
//\r
- if (ResourceHob->ResourceLength > TotalReservedMemorySize) {\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
// Assert here \r
//\r
- ASSERT (FALSE); \r
+ ASSERT (FALSE); \r
+ return; \r
} \r
} else {\r
//\r
//\r
if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && \r
ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&\r
- ResourceHob->ResourceLength > TotalReservedMemorySize) {\r
+ ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
//\r
// See if this is the highest largest system memory region below MaxAddress\r
//\r
//\r
// Assert here \r
//\r
- ASSERT (FALSE); \r
+ ASSERT (FALSE);\r
+ return; \r
} else {\r
TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ; \r
} \r
\r
if (CurrentResourceHob != NULL) {\r
//\r
- // rebuild hob for PEI memmory and reserved memory\r
+ // rebuild resource HOB for PEI memmory and reserved memory\r
//\r
BuildResourceDescriptorHob (\r
- EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,\r
+ EFI_RESOURCE_SYSTEM_MEMORY, \r
(\r
EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
),\r
- (TopLoadingAddress - TotalReservedMemorySize), // MemoryBegin\r
- TotalReservedMemorySize // MemoryLength\r
+ (TopLoadingAddress - TotalReservedMemorySize), \r
+ TotalReservedMemorySize \r
);\r
//\r
- // rebuild hob for the remain memory if necessary\r
+ // rebuild resource for the remain memory if necessary\r
//\r
if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {\r
BuildResourceDescriptorHob (\r
- EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,\r
+ EFI_RESOURCE_SYSTEM_MEMORY, \r
(\r
EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
),\r
- CurrentResourceHob->PhysicalStart, // MemoryBegin\r
- (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart) // MemoryLength\r
+ CurrentResourceHob->PhysicalStart, \r
+ (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart) \r
);\r
}\r
if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {\r
//\r
PeiLoadFixAddressHook(Private);\r
//\r
- // if Loading Module at Fixed Address is enabled, This is the first invoke to page\r
- // allocation for Pei Code range. This memory range should be reserved for loading PEIMs\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