@@ -38,6 +38,7 @@ Module Name:
38
38
#include <Library/QemuFwCfgSimpleParserLib.h>
39
39
40
40
#include "Platform.h"
41
+ #include "Cmos.h"
41
42
42
43
UINT8 mPhysMemAddressWidth ;
43
44
@@ -321,11 +322,51 @@ GetSystemMemorySizeBelow4gb (
321
322
{
322
323
EFI_STATUS Status ;
323
324
UINT64 LowerMemorySize = 0 ;
325
+ UINT8 Cmos0x34 ;
326
+ UINT8 Cmos0x35 ;
324
327
325
328
Status = ScanOrAdd64BitE820Ram (FALSE, & LowerMemorySize , NULL );
326
- ASSERT_EFI_ERROR (Status );
327
- ASSERT (LowerMemorySize > 0 );
328
- return (UINT32 )LowerMemorySize ;
329
+ if ((Status == EFI_SUCCESS ) && (LowerMemorySize > 0 )) {
330
+ return (UINT32 )LowerMemorySize ;
331
+ }
332
+
333
+ //
334
+ // CMOS 0x34/0x35 specifies the system memory above 16 MB.
335
+ // * CMOS(0x35) is the high byte
336
+ // * CMOS(0x34) is the low byte
337
+ // * The size is specified in 64kb chunks
338
+ // * Since this is memory above 16MB, the 16MB must be added
339
+ // into the calculation to get the total memory size.
340
+ //
341
+
342
+ Cmos0x34 = (UINT8 )CmosRead8 (0x34 );
343
+ Cmos0x35 = (UINT8 )CmosRead8 (0x35 );
344
+
345
+ return (UINT32 )(((UINTN )((Cmos0x35 << 8 ) + Cmos0x34 ) << 16 ) + SIZE_16MB );
346
+ }
347
+
348
+ STATIC
349
+ UINT64
350
+ GetSystemMemorySizeAbove4gb (
351
+ )
352
+ {
353
+ UINT32 Size ;
354
+ UINTN CmosIndex ;
355
+
356
+ //
357
+ // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
358
+ // * CMOS(0x5d) is the most significant size byte
359
+ // * CMOS(0x5c) is the middle size byte
360
+ // * CMOS(0x5b) is the least significant size byte
361
+ // * The size is specified in 64kb chunks
362
+ //
363
+
364
+ Size = 0 ;
365
+ for (CmosIndex = 0x5d ; CmosIndex >= 0x5b ; CmosIndex -- ) {
366
+ Size = (UINT32 )(Size << 8 ) + (UINT32 )CmosRead8 (CmosIndex );
367
+ }
368
+
369
+ return LShiftU64 (Size , 16 );
329
370
}
330
371
331
372
/**
@@ -355,9 +396,12 @@ GetFirstNonAddress (
355
396
// If QEMU presents an E820 map, then get the highest exclusive >=4GB RAM
356
397
// address from it. This can express an address >= 4GB+1TB.
357
398
//
399
+ // Otherwise, get the flat size of the memory above 4GB from the CMOS (which
400
+ // can only express a size smaller than 1TB), and add it to 4GB.
401
+ //
358
402
Status = ScanOrAdd64BitE820Ram (FALSE, NULL , & FirstNonAddress );
359
403
if (EFI_ERROR (Status )) {
360
- FirstNonAddress = BASE_4GB ;
404
+ FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb () ;
361
405
}
362
406
363
407
//
@@ -729,6 +773,7 @@ QemuInitializeRam (
729
773
)
730
774
{
731
775
UINT64 LowerMemorySize ;
776
+ UINT64 UpperMemorySize ;
732
777
MTRR_SETTINGS MtrrSettings ;
733
778
EFI_STATUS Status ;
734
779
@@ -787,6 +832,12 @@ QemuInitializeRam (
787
832
// memory size read from the CMOS.
788
833
//
789
834
Status = ScanOrAdd64BitE820Ram (TRUE, NULL , NULL );
835
+ if (EFI_ERROR (Status )) {
836
+ UpperMemorySize = GetSystemMemorySizeAbove4gb ();
837
+ if (UpperMemorySize != 0 ) {
838
+ AddMemoryBaseSizeHob (BASE_4GB , UpperMemorySize );
839
+ }
840
+ }
790
841
}
791
842
792
843
//
0 commit comments