+/**\r
+ Gets the reserved long mode buffer.\r
+\r
+ @param LongModeBuffer Pointer to the long mode buffer for output.\r
+\r
+ @retval EFI_SUCCESS Long mode buffer successfully retrieved.\r
+ @retval Others Variable storing long mode buffer not found.\r
+\r
+**/\r
+EFI_STATUS\r
+GetLongModeContext (\r
+ OUT EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;\r
+\r
+ Status = PeiServicesLocatePpi (\r
+ &gEfiPeiReadOnlyVariable2PpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID **) &PPIVariableServices\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Size = sizeof (EFI_CAPSULE_LONG_MODE_BUFFER);\r
+ Status = PPIVariableServices->GetVariable (\r
+ PPIVariableServices,\r
+ EFI_CAPSULE_LONG_MODE_BUFFER_NAME,\r
+ &gEfiCapsuleVendorGuid,\r
+ NULL,\r
+ &Size,\r
+ LongModeBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));\r
+ }\r
+ return Status;\r
+}\r
+#endif\r
+\r
+#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
+ 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