#include <Library/QemuFwCfgSimpleParserLib.h>\r
\r
#include "Platform.h"\r
+#include "Cmos.h"\r
\r
UINT8 mPhysMemAddressWidth;\r
\r
{\r
EFI_STATUS Status;\r
UINT64 LowerMemorySize = 0;\r
+ UINT8 Cmos0x34;\r
+ UINT8 Cmos0x35;\r
\r
Status = ScanOrAdd64BitE820Ram (FALSE, &LowerMemorySize, NULL);\r
- ASSERT_EFI_ERROR (Status);\r
- ASSERT (LowerMemorySize > 0);\r
- return (UINT32)LowerMemorySize;\r
+ if ((Status == EFI_SUCCESS) && (LowerMemorySize > 0)) {\r
+ return (UINT32)LowerMemorySize;\r
+ }\r
+\r
+ //\r
+ // CMOS 0x34/0x35 specifies the system memory above 16 MB.\r
+ // * CMOS(0x35) is the high byte\r
+ // * CMOS(0x34) is the low byte\r
+ // * The size is specified in 64kb chunks\r
+ // * Since this is memory above 16MB, the 16MB must be added\r
+ // into the calculation to get the total memory size.\r
+ //\r
+\r
+ Cmos0x34 = (UINT8)CmosRead8 (0x34);\r
+ Cmos0x35 = (UINT8)CmosRead8 (0x35);\r
+\r
+ return (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);\r
+}\r
+\r
+STATIC\r
+UINT64\r
+GetSystemMemorySizeAbove4gb (\r
+ )\r
+{\r
+ UINT32 Size;\r
+ UINTN CmosIndex;\r
+\r
+ //\r
+ // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.\r
+ // * CMOS(0x5d) is the most significant size byte\r
+ // * CMOS(0x5c) is the middle size byte\r
+ // * CMOS(0x5b) is the least significant size byte\r
+ // * The size is specified in 64kb chunks\r
+ //\r
+\r
+ Size = 0;\r
+ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {\r
+ Size = (UINT32)(Size << 8) + (UINT32)CmosRead8 (CmosIndex);\r
+ }\r
+\r
+ return LShiftU64 (Size, 16);\r
}\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
//\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 = ScanOrAdd64BitE820Ram (FALSE, NULL, &FirstNonAddress);\r
if (EFI_ERROR (Status)) {\r
- FirstNonAddress = BASE_4GB;\r
+ FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();\r
}\r
\r
//\r
)\r
{\r
UINT64 LowerMemorySize;\r
+ UINT64 UpperMemorySize;\r
MTRR_SETTINGS MtrrSettings;\r
EFI_STATUS Status;\r
\r
// memory size read from the CMOS.\r
//\r
Status = ScanOrAdd64BitE820Ram (TRUE, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ UpperMemorySize = GetSystemMemorySizeAbove4gb ();\r
+ if (UpperMemorySize != 0) {\r
+ AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);\r
+ }\r
+ }\r
}\r
\r
//\r