+ // 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