\r
#include "UefiPayloadEntry.h"\r
\r
+STATIC UINT32 mTopOfLowerUsableDram = 0;\r
+\r
/**\r
Callback function to build resource descriptor HOB\r
\r
This function build a HOB based on the memory map entry info.\r
+ It creates only EFI_RESOURCE_MEMORY_MAPPED_IO and EFI_RESOURCE_MEMORY_RESERVED\r
+ resources.\r
+\r
+ @param MemoryMapEntry Memory map entry info got from bootloader.\r
+ @param Params A pointer to ACPI_BOARD_INFO.\r
+\r
+ @retval EFI_SUCCESS Successfully build a HOB.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter provided.\r
+**/\r
+EFI_STATUS\r
+MemInfoCallbackMmio (\r
+ IN MEMROY_MAP_ENTRY *MemoryMapEntry,\r
+ IN VOID *Params\r
+ )\r
+{\r
+ EFI_PHYSICAL_ADDRESS Base;\r
+ EFI_RESOURCE_TYPE Type;\r
+ UINT64 Size;\r
+ EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;\r
+ ACPI_BOARD_INFO *AcpiBoardInfo;\r
+\r
+ AcpiBoardInfo = (ACPI_BOARD_INFO *)Params;\r
+ if (AcpiBoardInfo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Skip types already handled in MemInfoCallback\r
+ //\r
+ if (MemoryMapEntry->Type == E820_RAM || MemoryMapEntry->Type == E820_ACPI) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (MemoryMapEntry->Base == AcpiBoardInfo->PcieBaseAddress) {\r
+ //\r
+ // MMCONF is always MMIO\r
+ //\r
+ Type = EFI_RESOURCE_MEMORY_MAPPED_IO;\r
+ } else if (MemoryMapEntry->Base < mTopOfLowerUsableDram) {\r
+ //\r
+ // It's in DRAM and thus must be reserved\r
+ //\r
+ Type = EFI_RESOURCE_MEMORY_RESERVED;\r
+ } else if ((MemoryMapEntry->Base < 0x100000000ULL) && (MemoryMapEntry->Base >= mTopOfLowerUsableDram)) {\r
+ //\r
+ // It's not in DRAM, must be MMIO\r
+ //\r
+ Type = EFI_RESOURCE_MEMORY_MAPPED_IO;\r
+ } else {\r
+ Type = EFI_RESOURCE_MEMORY_RESERVED;\r
+ }\r
+\r
+ Base = MemoryMapEntry->Base;\r
+ Size = MemoryMapEntry->Size;\r
+\r
+ Attribue = 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
+ BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size);\r
+ DEBUG ((DEBUG_INFO , "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type));\r
+\r
+ if (MemoryMapEntry->Type == E820_UNUSABLE ||\r
+ MemoryMapEntry->Type == E820_DISABLED) {\r
+ BuildMemoryAllocationHob (Base, Size, EfiUnusableMemory);\r
+ } else if (MemoryMapEntry->Type == E820_PMEM) {\r
+ BuildMemoryAllocationHob (Base, Size, EfiPersistentMemory);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Callback function to find TOLUD (Top of Lower Usable DRAM)\r
+\r
+ Estimate where TOLUD (Top of Lower Usable DRAM) resides. The exact position\r
+ would require platform specific code.\r
+\r
+ @param MemoryMapEntry Memory map entry info got from bootloader.\r
+ @param Params Not used for now.\r
+\r
+ @retval EFI_SUCCESS Successfully updated mTopOfLowerUsableDram.\r
+**/\r
+EFI_STATUS\r
+FindToludCallback (\r
+ IN MEMROY_MAP_ENTRY *MemoryMapEntry,\r
+ IN VOID *Params\r
+ )\r
+{\r
+ //\r
+ // This code assumes that the memory map on this x86 machine below 4GiB is continous\r
+ // until TOLUD. In addition it assumes that the bootloader provided memory tables have\r
+ // no "holes" and thus the first memory range not covered by e820 marks the end of\r
+ // usable DRAM. In addition it's assumed that every reserved memory region touching\r
+ // usable RAM is also covering DRAM, everything else that is marked reserved thus must be\r
+ // MMIO not detectable by bootloader/OS\r
+ //\r
+\r
+ //\r
+ // Skip memory types not RAM or reserved\r
+ //\r
+ if ((MemoryMapEntry->Type == E820_UNUSABLE) || (MemoryMapEntry->Type == E820_DISABLED) ||\r
+ (MemoryMapEntry->Type == E820_PMEM)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Skip resources above 4GiB\r
+ //\r
+ if ((MemoryMapEntry->Base + MemoryMapEntry->Size) > 0x100000000ULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if ((MemoryMapEntry->Type == E820_RAM) || (MemoryMapEntry->Type == E820_ACPI) ||\r
+ (MemoryMapEntry->Type == E820_NVS)) {\r
+ //\r
+ // It's usable DRAM. Update TOLUD.\r
+ //\r
+ if (mTopOfLowerUsableDram < (MemoryMapEntry->Base + MemoryMapEntry->Size)) {\r
+ mTopOfLowerUsableDram = (UINT32)(MemoryMapEntry->Base + MemoryMapEntry->Size);\r
+ }\r
+ } else {\r
+ //\r
+ // It might be 'reserved DRAM' or 'MMIO'.\r
+ //\r
+ // If it touches usable DRAM at Base assume it's DRAM as well,\r
+ // as it could be bootloader installed tables, TSEG, GTT, ...\r
+ //\r
+ if (mTopOfLowerUsableDram == MemoryMapEntry->Base) {\r
+ mTopOfLowerUsableDram = (UINT32)(MemoryMapEntry->Base + MemoryMapEntry->Size);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Callback function to build resource descriptor HOB\r
+\r
+ This function build a HOB based on the memory map entry info.\r
+ Only add EFI_RESOURCE_SYSTEM_MEMORY.\r
\r
@param MemoryMapEntry Memory map entry info got from bootloader.\r
@param Params Not used for now.\r
UINT64 Size;\r
EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;\r
\r
- Type = (MemoryMapEntry->Type == 1) ? EFI_RESOURCE_SYSTEM_MEMORY : EFI_RESOURCE_MEMORY_RESERVED;\r
+ //\r
+ // Skip everything not known to be usable DRAM.\r
+ // It will be added later.\r
+ //\r
+ if ((MemoryMapEntry->Type != E820_RAM) && (MemoryMapEntry->Type != E820_ACPI) &&\r
+ (MemoryMapEntry->Type != E820_NVS)) {\r
+ return RETURN_SUCCESS;\r
+ }\r
+\r
+ Type = EFI_RESOURCE_SYSTEM_MEMORY;\r
Base = MemoryMapEntry->Base;\r
Size = MemoryMapEntry->Size;\r
\r
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;\r
\r
- if (Base >= BASE_4GB ) {\r
+ if (Base >= BASE_4GB) {\r
// Remove tested attribute to avoid DXE core to dispatch driver to memory above 4GB\r
Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED;\r
}\r
BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size);\r
DEBUG ((DEBUG_INFO , "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type));\r
\r
+ if (MemoryMapEntry->Type == E820_ACPI) {\r
+ BuildMemoryAllocationHob (Base, Size, EfiACPIReclaimMemory);\r
+ } else if (MemoryMapEntry->Type == E820_NVS) {\r
+ BuildMemoryAllocationHob (Base, Size, EfiACPIMemoryNVS);\r
+ }\r
+\r
return RETURN_SUCCESS;\r
}\r
\r
UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTableHob;\r
\r
//\r
- // Parse memory info and build memory HOBs\r
+ // First find TOLUD\r
+ //\r
+ DEBUG ((DEBUG_INFO , "Guessing Top of Lower Usable DRAM:\n"));\r
+ Status = ParseMemoryInfo (FindToludCallback, NULL);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ DEBUG ((DEBUG_INFO , "Assuming TOLUD = 0x%x\n", mTopOfLowerUsableDram));\r
+\r
+ //\r
+ // Parse memory info and build memory HOBs for Usable RAM\r
//\r
+ DEBUG ((DEBUG_INFO , "Building ResourceDescriptorHobs for usable memory:\n"));\r
Status = ParseMemoryInfo (MemInfoCallback, NULL);\r
if (EFI_ERROR(Status)) {\r
return Status;\r
DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n"));\r
}\r
\r
+ //\r
+ // Parse memory info and build memory HOBs for reserved DRAM and MMIO\r
+ //\r
+ DEBUG ((DEBUG_INFO , "Building ResourceDescriptorHobs for reserved memory:\n"));\r
+ Status = ParseMemoryInfo (MemInfoCallbackMmio, &AcpiBoardInfo);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
//\r
// Parse platform specific information.\r
//\r