+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)\r
+/**\r
+ Get physical address bits.\r
+\r
+ @return Physical address bits.\r
+\r
+**/\r
+UINT8\r
+GetPhysicalAddressBits (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 RegEax;\r
+ UINT8 PhysicalAddressBits;\r
+ VOID *Hob;\r
+\r
+ //\r
+ // Get physical address bits supported.\r
+ //\r
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
+ if (Hob != NULL) {\r
+ PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
+ } else {\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000008) {\r
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+ PhysicalAddressBits = (UINT8) RegEax;\r
+ } else {\r
+ PhysicalAddressBits = 36;\r
+ }\r
+ }\r
+\r
+ //\r
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
+ //\r
+ ASSERT (PhysicalAddressBits <= 52);\r
+ if (PhysicalAddressBits > 48) {\r
+ PhysicalAddressBits = 48;\r
+ }\r
+\r
+ return PhysicalAddressBits;\r
+}\r
+#endif\r
+\r
+/**\r
+ Sort memory resource entries based upon PhysicalStart, from low to high.\r
+\r
+ @param[in, out] MemoryResource A pointer to the memory resource entry buffer.\r
+\r
+**/\r
+VOID\r
+SortMemoryResourceDescriptor (\r
+ IN OUT MEMORY_RESOURCE_DESCRIPTOR *MemoryResource\r
+ )\r
+{\r
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResourceEntry;\r
+ MEMORY_RESOURCE_DESCRIPTOR *NextMemoryResourceEntry;\r
+ MEMORY_RESOURCE_DESCRIPTOR TempMemoryResource;\r
+\r
+ MemoryResourceEntry = MemoryResource;\r
+ NextMemoryResourceEntry = MemoryResource + 1;\r
+ while (MemoryResourceEntry->ResourceLength != 0) {\r
+ while (NextMemoryResourceEntry->ResourceLength != 0) {\r
+ if (MemoryResourceEntry->PhysicalStart > NextMemoryResourceEntry->PhysicalStart) {\r
+ CopyMem (&TempMemoryResource, MemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+ CopyMem (MemoryResourceEntry, NextMemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+ CopyMem (NextMemoryResourceEntry, &TempMemoryResource, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+ }\r
+\r
+ NextMemoryResourceEntry = NextMemoryResourceEntry + 1;\r
+ }\r
+\r
+ MemoryResourceEntry = MemoryResourceEntry + 1;\r
+ NextMemoryResourceEntry = MemoryResourceEntry + 1;\r
+ }\r
+}\r
+\r
+/**\r
+ Merge continous memory resource entries.\r
+\r
+ @param[in, out] MemoryResource A pointer to the memory resource entry buffer.\r
+\r
+**/\r
+VOID\r
+MergeMemoryResourceDescriptor (\r
+ IN OUT MEMORY_RESOURCE_DESCRIPTOR *MemoryResource\r
+ )\r
+{\r
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResourceEntry;\r
+ MEMORY_RESOURCE_DESCRIPTOR *NewMemoryResourceEntry;\r
+ MEMORY_RESOURCE_DESCRIPTOR *NextMemoryResourceEntry;\r
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResourceEnd;\r
+\r
+ MemoryResourceEntry = MemoryResource;\r
+ NewMemoryResourceEntry = MemoryResource;\r
+ while (MemoryResourceEntry->ResourceLength != 0) {\r
+ CopyMem (NewMemoryResourceEntry, MemoryResourceEntry, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+ NextMemoryResourceEntry = MemoryResourceEntry + 1;\r
+\r
+ while ((NextMemoryResourceEntry->ResourceLength != 0) &&\r
+ (NextMemoryResourceEntry->PhysicalStart == (MemoryResourceEntry->PhysicalStart + MemoryResourceEntry->ResourceLength))) {\r
+ MemoryResourceEntry->ResourceLength += NextMemoryResourceEntry->ResourceLength;\r
+ if (NewMemoryResourceEntry != MemoryResourceEntry) {\r
+ NewMemoryResourceEntry->ResourceLength += NextMemoryResourceEntry->ResourceLength;\r
+ }\r
+\r
+ NextMemoryResourceEntry = NextMemoryResourceEntry + 1;\r
+ }\r
+\r
+ MemoryResourceEntry = NextMemoryResourceEntry;\r
+ NewMemoryResourceEntry = NewMemoryResourceEntry + 1;\r
+ }\r
+\r
+ //\r
+ // Set NULL terminate memory resource descriptor after merging.\r
+ //\r
+ MemoryResourceEnd = NewMemoryResourceEntry;\r
+ ZeroMem (MemoryResourceEnd, sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+}\r
+\r
+/**\r
+ Build memory resource descriptor from resource descriptor in HOB list.\r
+\r
+ @return Pointer to the buffer of memory resource descriptor.\r
+ NULL if no memory resource descriptor reported in HOB list\r
+ before capsule Coalesce.\r
+\r
+**/\r
+MEMORY_RESOURCE_DESCRIPTOR *\r
+BuildMemoryResourceDescriptor (\r
+ VOID\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ UINTN Index;\r
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor;\r
+ MEMORY_RESOURCE_DESCRIPTOR *MemoryResource;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Get the count of memory resource descriptor.\r
+ //\r
+ Index = 0;\r
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
+ while (Hob.Raw != NULL) {\r
+ ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;\r
+ if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
+ Index++;\r
+ }\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
+ }\r
+\r
+ if (Index == 0) {\r
+ DEBUG ((EFI_D_INFO | EFI_D_WARN, "No memory resource descriptor reported in HOB list before capsule Coalesce\n"));\r
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)\r
+ //\r
+ // Allocate memory to hold memory resource descriptor,\r
+ // include extra one NULL terminate memory resource descriptor.\r
+ //\r
+ Status = PeiServicesAllocatePool ((1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);\r
+ ASSERT_EFI_ERROR (Status);\r
+ ZeroMem (MemoryResource, (1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+\r
+ MemoryResource[0].PhysicalStart = 0;\r
+ MemoryResource[0].ResourceLength = LShiftU64 (1, GetPhysicalAddressBits ());\r
+ DEBUG ((EFI_D_INFO, "MemoryResource[0x0] - Start(0x%0lx) Length(0x%0lx)\n",\r
+ MemoryResource[0x0].PhysicalStart, MemoryResource[0x0].ResourceLength));\r
+ return MemoryResource;\r
+#else\r
+ return NULL;\r
+#endif\r
+ }\r
+\r
+ //\r
+ // Allocate memory to hold memory resource descriptor,\r
+ // include extra one NULL terminate memory resource descriptor.\r
+ //\r
+ Status = PeiServicesAllocatePool ((Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);\r
+ ASSERT_EFI_ERROR (Status);\r
+ ZeroMem (MemoryResource, (Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));\r
+\r
+ //\r
+ // Get the content of memory resource descriptor.\r
+ //\r
+ Index = 0;\r
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
+ while (Hob.Raw != NULL) {\r
+ ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;\r
+ if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
+ DEBUG ((EFI_D_INFO, "MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
+ Index, ResourceDescriptor->PhysicalStart, ResourceDescriptor->ResourceLength));\r
+ MemoryResource[Index].PhysicalStart = ResourceDescriptor->PhysicalStart;\r
+ MemoryResource[Index].ResourceLength = ResourceDescriptor->ResourceLength;\r
+ Index++;\r
+ }\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
+ }\r
+\r
+ SortMemoryResourceDescriptor (MemoryResource);\r
+ MergeMemoryResourceDescriptor (MemoryResource);\r
+\r
+ DEBUG ((DEBUG_INFO, "Dump MemoryResource[] after sorted and merged\n"));\r
+ for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",\r
+ Index,\r
+ MemoryResource[Index].PhysicalStart,\r
+ MemoryResource[Index].ResourceLength\r
+ ));\r
+ }\r
+\r
+ return MemoryResource;\r
+}\r
+\r