return EFI_SUCCESS;\r
}\r
\r
+typedef VOID (*E820_SCAN_CALLBACK) (\r
+ EFI_E820_ENTRY64 *E820Entry,\r
+ EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
+ );\r
+\r
+/**\r
+ Store first address not used by e820 RAM entries in\r
+ PlatformInfoHob->FirstNonAddress\r
+**/\r
+STATIC\r
+VOID\r
+PlatformGetFirstNonAddressCB (\r
+ IN EFI_E820_ENTRY64 *E820Entry,\r
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
+ )\r
+{\r
+ UINT64 Candidate;\r
+\r
+ if (E820Entry->Type != EfiAcpiAddressRangeMemory) {\r
+ return;\r
+ }\r
+\r
+ Candidate = E820Entry->BaseAddr + E820Entry->Length;\r
+ if (PlatformInfoHob->FirstNonAddress < Candidate) {\r
+ DEBUG ((DEBUG_INFO, "%a: FirstNonAddress=0x%Lx\n", __FUNCTION__, Candidate));\r
+ PlatformInfoHob->FirstNonAddress = Candidate;\r
+ }\r
+}\r
+\r
+/**\r
+ Iterate over the entries in QEMU's fw_cfg E820 RAM map, call the\r
+ passed callback for each entry.\r
+\r
+ @param[in] Callback The callback function to be called.\r
+\r
+ @param[in out] PlatformInfoHob PlatformInfo struct which is passed\r
+ through to the callback.\r
+\r
+ @retval EFI_SUCCESS The fw_cfg E820 RAM map was found and processed.\r
+\r
+ @retval EFI_PROTOCOL_ERROR The RAM map was found, but its size wasn't a\r
+ whole multiple of sizeof(EFI_E820_ENTRY64). No\r
+ RAM entry was processed.\r
+\r
+ @return Error codes from QemuFwCfgFindFile(). No RAM\r
+ entry was processed.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+PlatformScanE820 (\r
+ IN E820_SCAN_CALLBACK Callback,\r
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FIRMWARE_CONFIG_ITEM FwCfgItem;\r
+ UINTN FwCfgSize;\r
+ EFI_E820_ENTRY64 E820Entry;\r
+ UINTN Processed;\r
+\r
+ Status = QemuFwCfgFindFile ("etc/e820", &FwCfgItem, &FwCfgSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (FwCfgSize % sizeof E820Entry != 0) {\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+\r
+ QemuFwCfgSelectItem (FwCfgItem);\r
+ for (Processed = 0; Processed < FwCfgSize; Processed += sizeof E820Entry) {\r
+ QemuFwCfgReadBytes (sizeof E820Entry, &E820Entry);\r
+ Callback (&E820Entry, PlatformInfoHob);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Returns PVH memmap\r
\r
Return the highest address that DXE could possibly use, plus one.\r
**/\r
STATIC\r
-UINT64\r
+VOID\r
PlatformGetFirstNonAddress (\r
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
)\r
{\r
- UINT64 FirstNonAddress;\r
UINT32 FwCfgPciMmio64Mb;\r
EFI_STATUS Status;\r
FIRMWARE_CONFIG_ITEM FwCfgItem;\r
UINTN FwCfgSize;\r
UINT64 HotPlugMemoryEnd;\r
\r
- //\r
- // set FirstNonAddress to suppress incorrect compiler/analyzer warnings\r
- //\r
- FirstNonAddress = 0;\r
-\r
//\r
// If QEMU presents an E820 map, then get the highest exclusive >=4GB RAM\r
// address from it. This can express an address >= 4GB+1TB.\r
// Otherwise, get the flat size of the memory above 4GB from the CMOS (which\r
// can only express a size smaller than 1TB), and add it to 4GB.\r
//\r
- Status = PlatformScanOrAdd64BitE820Ram (FALSE, NULL, &FirstNonAddress);\r
+ PlatformInfoHob->FirstNonAddress = BASE_4GB;\r
+ Status = PlatformScanE820 (PlatformGetFirstNonAddressCB, PlatformInfoHob);\r
if (EFI_ERROR (Status)) {\r
- FirstNonAddress = BASE_4GB + PlatformGetSystemMemorySizeAbove4gb ();\r
+ PlatformInfoHob->FirstNonAddress = BASE_4GB + PlatformGetSystemMemorySizeAbove4gb ();\r
}\r
\r
//\r
//\r
#ifdef MDE_CPU_IA32\r
if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
- return FirstNonAddress;\r
+ return;\r
}\r
\r
#endif\r
// determines the highest address plus one. The memory hotplug area (see\r
// below) plays no role for the firmware in this case.\r
//\r
- return FirstNonAddress;\r
+ return;\r
}\r
\r
//\r
HotPlugMemoryEnd\r
));\r
\r
- ASSERT (HotPlugMemoryEnd >= FirstNonAddress);\r
- FirstNonAddress = HotPlugMemoryEnd;\r
+ ASSERT (HotPlugMemoryEnd >= PlatformInfoHob->FirstNonAddress);\r
+ PlatformInfoHob->FirstNonAddress = HotPlugMemoryEnd;\r
}\r
\r
//\r
// SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so\r
// that the host can map it with 1GB hugepages. Follow suit.\r
//\r
- PlatformInfoHob->PcdPciMmio64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);\r
+ PlatformInfoHob->PcdPciMmio64Base = ALIGN_VALUE (PlatformInfoHob->FirstNonAddress, (UINT64)SIZE_1GB);\r
PlatformInfoHob->PcdPciMmio64Size = ALIGN_VALUE (PlatformInfoHob->PcdPciMmio64Size, (UINT64)SIZE_1GB);\r
\r
//\r
//\r
// The useful address space ends with the 64-bit PCI host aperture.\r
//\r
- FirstNonAddress = PlatformInfoHob->PcdPciMmio64Base + PlatformInfoHob->PcdPciMmio64Size;\r
- return FirstNonAddress;\r
+ PlatformInfoHob->FirstNonAddress = PlatformInfoHob->PcdPciMmio64Base + PlatformInfoHob->PcdPciMmio64Size;\r
+ return;\r
}\r
\r
/*\r
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
)\r
{\r
- UINT64 FirstNonAddress;\r
UINT8 PhysMemAddressWidth;\r
EFI_STATUS Status;\r
\r
// First scan host-provided hardware information to assess if the address\r
// space is already known. If so, guest must use those values.\r
//\r
- Status = PlatformScanHostProvided64BitPciMmioEnd (&FirstNonAddress);\r
+ Status = PlatformScanHostProvided64BitPciMmioEnd (&PlatformInfoHob->FirstNonAddress);\r
\r
if (EFI_ERROR (Status)) {\r
//\r
// The DXL IPL keys off of the physical address bits advertized in the CPU\r
// HOB. To conserve memory, we calculate the minimum address width here.\r
//\r
- FirstNonAddress = PlatformGetFirstNonAddress (PlatformInfoHob);\r
+ PlatformGetFirstNonAddress (PlatformInfoHob);\r
}\r
\r
PlatformAddressWidthFromCpuid (PlatformInfoHob, TRUE);\r
if (PlatformInfoHob->PhysMemAddressWidth != 0) {\r
// physical address width is known\r
- PlatformInfoHob->FirstNonAddress = FirstNonAddress;\r
PlatformDynamicMmioWindow (PlatformInfoHob);\r
return;\r
}\r
// -> try be conservstibe to stay below the guaranteed minimum of\r
// 36 phys bits (aka 64 GB).\r
//\r
- PhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);\r
+ PhysMemAddressWidth = (UINT8)HighBitSet64 (PlatformInfoHob->FirstNonAddress);\r
\r
//\r
// If FirstNonAddress is not an integral power of two, then we need an\r
// additional bit.\r
//\r
- if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {\r
+ if ((PlatformInfoHob->FirstNonAddress & (PlatformInfoHob->FirstNonAddress - 1)) != 0) {\r
++PhysMemAddressWidth;\r
}\r
\r
ASSERT (PhysMemAddressWidth <= 48);\r
#endif\r
\r
- PlatformInfoHob->FirstNonAddress = FirstNonAddress;\r
PlatformInfoHob->PhysMemAddressWidth = PhysMemAddressWidth;\r
}\r
\r