diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CapsuleReset.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CapsuleReset.c
new file mode 100644
index 0000000000..32579ceefb
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CapsuleReset.c
@@ -0,0 +1,75 @@
+ /** @file
+ ARM implementation of architecture specific routines related to
+ PersistAcrossReset capsules
+
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+
+ 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 "CapsuleService.h"
+
+#include
+
+/**
+ Whether the platform supports capsules that persist across reset. Note that
+ some platforms only support such capsules at boot time.
+
+ @return TRUE if a PersistAcrossReset capsule may be passed to UpdateCapsule()
+ at this time
+ FALSE otherwise
+**/
+BOOLEAN
+IsPersistAcrossResetCapsuleSupported (
+ VOID
+ )
+{
+ //
+ // 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.
+ //
+ return FeaturePcdGet (PcdSupportUpdateCapsuleReset) && !EfiAtRuntime ();
+}
+
+/**
+ 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
+
+**/
+VOID
+CapsuleCacheWriteBack (
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList
+ )
+{
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc;
+
+ 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);
+}
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c
new file mode 100644
index 0000000000..353f6f2090
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c
@@ -0,0 +1,49 @@
+/** @file
+ Default implementation of architecture specific routines related to
+ PersistAcrossReset capsules
+
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+
+ 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 "CapsuleService.h"
+
+/**
+ Whether the platform supports capsules that persist across reset. Note that
+ some platforms only support such capsules at boot time.
+
+ @return TRUE if a PersistAcrossReset capsule may be passed to UpdateCapsule()
+ at this time
+ FALSE otherwise
+**/
+BOOLEAN
+IsPersistAcrossResetCapsuleSupported (
+ VOID
+ )
+{
+ return FeaturePcdGet (PcdSupportUpdateCapsuleReset);
+}
+
+/**
+ 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
+
+**/
+VOID
+CapsuleCacheWriteBack (
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList
+ )
+{
+}
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
index 9ab04ce1b3..43a29ee229 100644
--- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -27,17 +27,24 @@
#
# 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
+ CapsuleService.h
-[Sources.Ia32, Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64]
+[Sources.Ia32, Sources.IPF, Sources.EBC]
SaveLongModeContext.c
+ CapsuleReset.c
[Sources.X64]
X64/SaveLongModeContext.c
+ CapsuleReset.c
+
+[Sources.ARM, Sources.AARCH64]
+ SaveLongModeContext.c
+ Arm/CapsuleReset.c
[Packages]
MdePkg/MdePkg.dec
@@ -59,6 +66,9 @@
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 216798d161..23fd6d59c5 100644
--- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
@@ -15,22 +15,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
-#include
+#include "CapsuleService.h"
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
//
// Handle for the installation of Capsule Architecture Protocol.
//
@@ -44,15 +30,6 @@ UINTN mTimes = 0;
UINT32 mMaxSizePopulateCapsule = 0;
UINT32 mMaxSizeNonPopulateCapsule = 0;
-/**
- Create the variable to save the base address of page table and stack
- for transferring into long mode in IA32 PEI.
-**/
-VOID
-SaveLongModeContext (
- VOID
- );
-
/**
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
@@ -194,10 +171,12 @@ UpdateCapsule (
//
// Check if the platform supports update capsule across a system reset
//
- if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
+ if (!IsPersistAcrossResetCapsuleSupported ()) {
return EFI_UNSUPPORTED;
}
+ CapsuleCacheWriteBack (ScatterGatherList);
+
//
// Construct variable name CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
// if user calls UpdateCapsule multiple times.
@@ -344,7 +323,7 @@ QueryCapsuleCapabilities (
//
//Check if the platform supports update capsule across a system reset
//
- if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
+ if (!IsPersistAcrossResetCapsuleSupported ()) {
return EFI_UNSUPPORTED;
}
*ResetType = EfiResetWarm;
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h
new file mode 100644
index 0000000000..7a5df742f1
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h
@@ -0,0 +1,71 @@
+/** @file
+ Capsule Runtime Driver produces two UEFI capsule runtime services.
+ (UpdateCapsule, QueryCapsuleCapabilities)
+ It installs the Capsule Architectural Protocol defined in PI1.0a to signify
+ the capsule runtime services are ready.
+
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+
+ 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
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ Create the variable to save the base address of page table and stack
+ for transferring into long mode in IA32 PEI.
+**/
+VOID
+SaveLongModeContext (
+ VOID
+ );
+
+/**
+ Whether the platform supports capsules that persist across reset. Note that
+ some platforms only support such capsules at boot time.
+
+ @return TRUE if a PersistAcrossReset capsule may be passed to UpdateCapsule()
+ at this time
+ FALSE otherwise
+**/
+BOOLEAN
+IsPersistAcrossResetCapsuleSupported (
+ 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
+
+**/
+VOID
+CapsuleCacheWriteBack (
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList
+ );