diff --git a/Platforms/Marvell/Armada/Armada.dsc.inc b/Platforms/Marvell/Armada/Armada.dsc.inc
index 222ab89cb45e..002c3b3ec961 100644
--- a/Platforms/Marvell/Armada/Armada.dsc.inc
+++ b/Platforms/Marvell/Armada/Armada.dsc.inc
@@ -371,7 +371,7 @@
 
   # ARM Pcds
   gArmTokenSpaceGuid.PcdSystemMemoryBase|0
-  gArmTokenSpaceGuid.PcdSystemMemorySize|0x100000000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x80000000
   gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|36
 
   gMarvellTokenSpaceGuid.PcdSecureRegionBase|0x4000000
diff --git a/Platforms/Marvell/Armada/Library/Armada70x0Lib/AArch64/ArmPlatformHelper.S b/Platforms/Marvell/Armada/Library/Armada70x0Lib/AArch64/ArmPlatformHelper.S
index ba9685f1d36e..8246892f2585 100644
--- a/Platforms/Marvell/Armada/Library/Armada70x0Lib/AArch64/ArmPlatformHelper.S
+++ b/Platforms/Marvell/Armada/Library/Armada70x0Lib/AArch64/ArmPlatformHelper.S
@@ -26,37 +26,47 @@
 #define CCU_MC_RTBR_OFFSET              0x8
 #define CCU_MC_RTBR_TARGET_BASE(Base)   (((Base) >> 20) << 10)
 
+#define SYSTEM_INFO_ADDRESS             0x4000000
+#define SYSINFO_ARRAY_SIZE              0x0
+#define SYSINFO_DRAM_CS0_SIZE           0x1
+
 ASM_FUNC(ArmPlatformPeiBootAction)
   mov   x29, xzr
+  mov   x28, x30
 
   .if   FixedPcdGet64 (PcdSystemMemoryBase) != 0
   .err  PcdSystemMemoryBase should be 0x0 on this platform!
   .endif
 
   .if   FixedPcdGet64 (PcdSystemMemorySize) > FixedPcdGet32 (PcdDramRemapTarget)
-    //
-    // Remap the DRAM region [DramRemapTarget, DramRemapTarget + DramRemapSize)
-    // to the top of the DRAM space. This is mainly intended to free up 32-bit
-    // addressable memory for MMIO and PCI windows.
-    //
-    MOV32 (x0, CCU_MC_BASE)
-    MOV32 (w1, CCU_MC_RSBR_SOURCE_BASE (FixedPcdGet64 (PcdSystemMemorySize)))
-    MOV32 (w2, CCU_MC_RTBR_TARGET_BASE (FixedPcdGet32 (PcdDramRemapTarget)))
-    MOV32 (w3, CCU_MC_RCR_REMAP_SIZE (FixedPcdGet32 (PcdDramRemapSize)) | CCU_MC_RCR_REMAP_EN)
-    str   w1, [x0, #CCU_MC_RSBR_OFFSET]
-    str   w2, [x0, #CCU_MC_RTBR_OFFSET]
-    str   w3, [x0, #CCU_MC_RCR_OFFSET]
-
-    //
-    // Use the low range for UEFI itself. The remaining memory will be mapped
-    // and added to the GCD map later.
-    //
-    adr   x0, mSystemMemoryEnd
-    MOV64 (x1, FixedPcdGet32 (PcdDramRemapTarget) - 1)
-    str   x1, [x0]
+  .err  Hard coded PcdSystemMemorySize should not exceed PcdDramRemapTarget
   .endif
 
-  MOV32 (x0, FixedPcdGet64 (PcdFvBaseAddress))
+  bl    DiscoverDramSize
+  cbz   w0, 0f
+
+  //
+  // Remap the DRAM region [DramRemapTarget, DramRemapTarget + DramRemapSize)
+  // to the top of the DRAM space. This is mainly intended to free up 32-bit
+  // addressable memory for MMIO and PCI windows.
+  //
+  lsl   w1, w0, #10          // set CCU_MC_RSBR_SOURCE_BASE to DRAM size in KiB
+  MOV32 (x0, CCU_MC_BASE)
+  MOV32 (w2, CCU_MC_RTBR_TARGET_BASE (FixedPcdGet32 (PcdDramRemapTarget)))
+  MOV32 (w3, CCU_MC_RCR_REMAP_SIZE (FixedPcdGet32 (PcdDramRemapSize)) | CCU_MC_RCR_REMAP_EN)
+  str   w1, [x0, #CCU_MC_RSBR_OFFSET]
+  str   w2, [x0, #CCU_MC_RTBR_OFFSET]
+  str   w3, [x0, #CCU_MC_RCR_OFFSET]
+
+  //
+  // Use the low range for UEFI itself. The remaining memory will be mapped
+  // and added to the GCD map later.
+  //
+  adr   x0, mSystemMemoryEnd
+  MOV64 (x1, FixedPcdGet32 (PcdDramRemapTarget) - 1)
+  str   x1, [x0]
+
+0:MOV32 (x0, FixedPcdGet64 (PcdFvBaseAddress))
   MOV32 (x3, FixedPcdGet32 (PcdFvSize))
   add   x3, x3, x0
 
@@ -70,6 +80,38 @@ ASM_FUNC(ArmPlatformPeiBootAction)
   cmp   x0, x3
   b.lt  0b
 
+  ret   x28
+
+DiscoverDramSize:
+  //
+  // ARM Trusted Firmware leaves us a structure in memory that describes the
+  // nature of the available DRAM. It consists of an array of <u32, u32>
+  // key/value pairs, where the only keys we are [currently] interested in are:
+  //
+  // 0x0 (ARRAY_SIZE)     the overall number of entries (should be the first)
+  // 0x1 (DRAM_CS0_SIZE)  the size in MiB of DRAM bank 0
+  //
+  MOV32 (x4, SYSTEM_INFO_ADDRESS)
+  ldp   w0, w1, [x4], #8
+
+  cmp   w0, #SYSINFO_ARRAY_SIZE   // first entry contains array size?
+  b.ne  1f
+
+0:subs  w1, w1, #1                // more entries to check?
+  b.eq  1f
+
+  ldp   w2, w3, [x4], #8          // next entry contains DRAM CS0 size?
+  cmp   w2, #SYSINFO_DRAM_CS0_SIZE
+  b.ne  0b
+
+  mov   w0, w3                    // return value in MiB
+
+  adr   x1, DiscoveredDramSize    // store value in bytes
+  lsl   x3, x3, #20
+  str   x3, [x1]
+  ret
+
+1:mov   w0, wzr
   ret
 
 //UINTN
diff --git a/Platforms/Marvell/Armada/Library/Armada70x0Lib/ARM/ArmPlatformHelper.S b/Platforms/Marvell/Armada/Library/Armada70x0Lib/ARM/ArmPlatformHelper.S
index 4cd8b3154e82..fdb688ca489a 100644
--- a/Platforms/Marvell/Armada/Library/Armada70x0Lib/ARM/ArmPlatformHelper.S
+++ b/Platforms/Marvell/Armada/Library/Armada70x0Lib/ARM/ArmPlatformHelper.S
@@ -26,36 +26,80 @@
 #define CCU_MC_RTBR_OFFSET              0x8
 #define CCU_MC_RTBR_TARGET_BASE(Base)   (((Base) >> 20) << 10)
 
+#define SYSTEM_INFO_ADDRESS             0x4000000
+#define SYSINFO_ARRAY_SIZE              0x0
+#define SYSINFO_DRAM_CS0_SIZE           0x1
+
 ASM_FUNC(ArmPlatformPeiBootAction)
+  mov   r13, lr
+
   .if   FixedPcdGet64 (PcdSystemMemoryBase) != 0
   .err  PcdSystemMemoryBase should be 0x0 on this platform!
   .endif
 
   .if   FixedPcdGet64 (PcdSystemMemorySize) > FixedPcdGet32 (PcdDramRemapTarget)
-    //
-    // Remap the DRAM region [DramRemapTarget, DramRemapTarget + DramRemapSize)
-    // to the top of the DRAM space. This is mainly intended to free up 32-bit
-    // addressable memory for MMIO and PCI windows.
-    //
-    MOV32 (r0, CCU_MC_BASE)
-    MOV32 (r1, CCU_MC_RSBR_SOURCE_BASE (FixedPcdGet64 (PcdSystemMemorySize)))
-    MOV32 (r2, CCU_MC_RTBR_TARGET_BASE (FixedPcdGet32 (PcdDramRemapTarget)))
-    MOV32 (r3, CCU_MC_RCR_REMAP_SIZE (FixedPcdGet32 (PcdDramRemapSize)) | CCU_MC_RCR_REMAP_EN)
-    str   r1, [r0, #CCU_MC_RSBR_OFFSET]
-    str   r2, [r0, #CCU_MC_RTBR_OFFSET]
-    str   r3, [r0, #CCU_MC_RCR_OFFSET]
-
-    //
-    // Use the low range for UEFI itself. The remaining memory will be mapped
-    // and added to the GCD map later.
-    //
-    ADRL  (r0, mSystemMemoryEnd)
-    MOV32 (r2, FixedPcdGet32 (PcdDramRemapTarget) - 1)
-    mov   r3, #0
-    strd  r2, r3, [r0]
-
+  .err  Hard coded PcdSystemMemorySize should not exceed PcdDramRemapTarget
   .endif
 
+  bl    DiscoverDramSize
+  cmp   r0, #0
+  beq   0f
+
+  //
+  // Remap the DRAM region [DramRemapTarget, DramRemapTarget + DramRemapSize)
+  // to the top of the DRAM space. This is mainly intended to free up 32-bit
+  // addressable memory for MMIO and PCI windows.
+  //
+  lsl   r1, r0, #10          // set CCU_MC_RSBR_SOURCE_BASE to DRAM size in KiB
+  MOV32 (r0, CCU_MC_BASE)
+  MOV32 (r2, CCU_MC_RTBR_TARGET_BASE (FixedPcdGet32 (PcdDramRemapTarget)))
+  MOV32 (r3, CCU_MC_RCR_REMAP_SIZE (FixedPcdGet32 (PcdDramRemapSize)) | CCU_MC_RCR_REMAP_EN)
+  str   r1, [r0, #CCU_MC_RSBR_OFFSET]
+  str   r2, [r0, #CCU_MC_RTBR_OFFSET]
+  str   r3, [r0, #CCU_MC_RCR_OFFSET]
+
+  //
+  // Use the low range for UEFI itself. The remaining memory will be mapped
+  // and added to the GCD map later.
+  //
+  ADRL  (r0, mSystemMemoryEnd)
+  MOV32 (r2, FixedPcdGet32 (PcdDramRemapTarget) - 1)
+  mov   r3, #0
+  strd  r2, r3, [r0]
+
+0:bx    r13
+
+DiscoverDramSize:
+  //
+  // ARM Trusted Firmware leaves us a structure in memory that describes the
+  // nature of the available DRAM. It consists of an array of <u32, u32>
+  // key/value pairs, where the only keys we are [currently] interested in are:
+  //
+  // 0x0 (ARRAY_SIZE)     the overall number of entries (should be the first)
+  // 0x1 (DRAM_CS0_SIZE)  the size in MiB of DRAM bank 0
+  //
+  MOV32 (r4, SYSTEM_INFO_ADDRESS)
+  ldrd  r0, r1, [r4], #8
+
+  cmp   r0, #SYSINFO_ARRAY_SIZE   // first entry contains array size?
+  bne   1f
+
+0:subs  r1, r1, #1                // more entries to check?
+  beq   1f
+
+  ldrd  r2, r3, [r4], #8          // next entry contains DRAM CS0 size?
+  cmp   r2, #SYSINFO_DRAM_CS0_SIZE
+  bne   0b
+
+  mov   r0, r3                    // return value in MiB
+
+  ADRL  (r1, DiscoveredDramSize)
+  lsl   r2, r3, #20               // store value in bytes
+  lsr   r3, r3, #12
+  strd  r2, r3, [r1]
+  bx    lr
+
+1:mov   r0, #0
   bx    lr
 
 //UINTN
diff --git a/Platforms/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c b/Platforms/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c
index 4d80426c177c..85df57164b7f 100644
--- a/Platforms/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c
+++ b/Platforms/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c
@@ -47,6 +47,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 STATIC ARM_MEMORY_REGION_DESCRIPTOR VirtualMemoryTable[MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS];
 
+//
+// This will be overwritten by ArmPlatformPeiBootAction() based on information
+// provided by the secure firmware. PcdSystemMemorySize should be a reasonable
+// default otherwise.
+//
+UINT64 DiscoveredDramSize = FixedPcdGet64 (PcdSystemMemorySize);
+
 /**
   Return the Virtual Memory Map of your platform
 
@@ -63,7 +70,6 @@ ArmPlatformGetVirtualMemoryMap (
   )
 {
   UINTN                         Index = 0;
-  UINT64                        MemSize;
   UINT64                        MemLowSize;
   UINT64                        MemHighStart;
   UINT64                        MemHighSize;
@@ -71,11 +77,10 @@ ArmPlatformGetVirtualMemoryMap (
 
   ASSERT (VirtualMemoryMap != NULL);
 
-  MemSize = FixedPcdGet64 (PcdSystemMemorySize);
-  MemLowSize = MIN (FixedPcdGet64 (PcdDramRemapTarget), MemSize);
+  MemLowSize = MIN (FixedPcdGet64 (PcdDramRemapTarget), DiscoveredDramSize);
   MemHighStart = (UINT64)FixedPcdGet64 (PcdDramRemapTarget) +
                  FixedPcdGet32 (PcdDramRemapSize);
-  MemHighSize = MemSize - MemLowSize;
+  MemHighSize = DiscoveredDramSize - MemLowSize;
 
   ResourceAttributes = (
       EFI_RESOURCE_ATTRIBUTE_PRESENT |
@@ -105,7 +110,7 @@ ArmPlatformGetVirtualMemoryMap (
   VirtualMemoryTable[Index].Length          = 0x20000000;
   VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
 
-  if (MemSize > MemLowSize) {
+  if (DiscoveredDramSize > MemLowSize) {
     //
     // If we have more than MemLowSize worth of DRAM, the remainder will be
     // mapped at the top of the remapped window.
