diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CacheMaintenance.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CacheMaintenance.c
new file mode 100644
index 000000000000..dc05e345fb8d
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CacheMaintenance.c
@@ -0,0 +1,70 @@
+ /** @file
+  Capsule cache maintenance as is required on ARM and AARCH64
+
+  Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License which accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+/**
+  Writes Back a range of data cache lines covering a set of capsules in memory.
+
+  Writes Back the data cache lines specified by ScatterGatherList.
+
+  @param  ScatterGatherList Physical address of the data structure that
+                            describes a set of capsules in memory
+
+  @return EFI_SUCCESS       if the operation succeeded.
+          EFI_UNSUPPORTED   if cache maintenance cannot be performed at this
+                            time.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleCacheWriteBack (
+  IN  EFI_PHYSICAL_ADDRESS    ScatterGatherList
+  )
+{
+  EFI_CAPSULE_BLOCK_DESCRIPTOR    *Desc;
+
+  //
+  // ARM requires the capsule payload to be cleaned to the point of coherency
+  // (PoC), but only permits doing so using cache maintenance instructions that
+  // operate on virtual addresses. Since at runtime, we don't know the virtual
+  // addresses of the data structures that make up the scatter/gather list, we
+  // cannot perform the maintenance, and all we can do is give up.
+  //
+  if (EfiAtRuntime ()) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)ScatterGatherList;
+  do {
+    WriteBackDataCacheRange (Desc, sizeof *Desc);
+
+    if (Desc->Length > 0) {
+      WriteBackDataCacheRange ((VOID *)(UINTN)Desc->Union.DataBlock,
+                               Desc->Length
+                               );
+      Desc++;
+    } else if (Desc->Union.ContinuationPointer > 0) {
+      Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)Desc->Union.ContinuationPointer;
+    }
+  } while (Desc->Length > 0 || Desc->Union.ContinuationPointer > 0);
+
+  WriteBackDataCacheRange (Desc, sizeof *Desc);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CacheMaintenance.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CacheMaintenance.c
new file mode 100644
index 000000000000..fb7504bb3e1d
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CacheMaintenance.c
@@ -0,0 +1,39 @@
+/** @file
+  Create NULL function for capsule cache maintenance which is only needed
+  on ARM and AARCH64
+
+  Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License which accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+/**
+  Writes Back a range of data cache lines covering a set of capsules in memory.
+
+  Writes Back the data cache lines specified by ScatterGatherList.
+
+  @param  ScatterGatherList Physical address of the data structure that
+                            describes a set of capsules in memory
+
+  @return EFI_SUCCESS       if the operation succeeded.
+          EFI_UNSUPPORTED   if cache maintenance cannot be performed at this
+                            time.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleCacheWriteBack (
+  IN  EFI_PHYSICAL_ADDRESS    ScatterGatherList
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
index 9ab04ce1b301..3ceebc5d9646 100644
--- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -27,17 +27,23 @@ [Defines]
 #
 # The following information is for reference only and not required by the build tools.
 #
-#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC ARM AARCH64
 #
 
 [Sources]
   CapsuleService.c
 
-[Sources.Ia32, Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64]
+[Sources.Ia32, Sources.IPF, Sources.EBC]
   SaveLongModeContext.c
+  CacheMaintenance.c
 
 [Sources.X64]
   X64/SaveLongModeContext.c
+  CacheMaintenance.c
+
+[Sources.ARM, Sources.AARCH64]
+  SaveLongModeContext.c
+  Arm/CacheMaintenance.c
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -59,6 +65,9 @@ [LibraryClasses.X64]
   UefiLib
   BaseMemoryLib
 
+[LibraryClasses.ARM, LibraryClasses.AARCH64]
+  CacheMaintenanceLib
+
 [Guids]
   ## SOMETIMES_PRODUCES   ## Variable:L"CapsuleUpdateData" # (Process across reset capsule image) for capsule updated data
   ## SOMETIMES_PRODUCES   ## Variable:L"CapsuleLongModeBuffer" # The long mode buffer used by IA32 Capsule PEIM to call X64 CapsuleCoalesce code to handle >4GB capsule blocks
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
index 216798d1617e..ee8515adf62f 100644
--- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
@@ -53,6 +53,25 @@ SaveLongModeContext (
   VOID
   );
 
+/**
+  Writes Back a range of data cache lines covering a set of capsules in memory.
+
+  Writes Back the data cache lines specified by ScatterGatherList.
+
+  @param  ScatterGatherList Physical address of the data structure that
+                            describes a set of capsules in memory
+
+  @return EFI_SUCCESS       if the operation succeeded.
+          EFI_UNSUPPORTED   if cache maintenance cannot be performed at this
+                            time.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleCacheWriteBack (
+  IN  EFI_PHYSICAL_ADDRESS    ScatterGatherList
+  );
+
 /**
   Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended
   consumption, the firmware may process the capsule immediately. If the payload should persist
@@ -214,6 +233,11 @@ UpdateCapsule (
       );
   }
 
+  Status = CapsuleCacheWriteBack (ScatterGatherList);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
   //
   // ScatterGatherList is only referenced if the capsules are defined to persist across
   // system reset. Set its value into NV storage to let pre-boot driver to pick it up 
