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