summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/lib/psci/psci.h6
-rw-r--r--include/lib/utils.h19
-rw-r--r--include/plat/arm/board/common/board_arm_def.h19
-rw-r--r--include/plat/arm/board/common/v2m_def.h1
-rw-r--r--include/plat/arm/common/arm_def.h15
-rw-r--r--include/plat/arm/common/plat_arm.h4
-rw-r--r--lib/psci/psci_lib.mk1
-rw-r--r--lib/psci/psci_main.c9
-rw-r--r--lib/psci/psci_mem_protect.c38
-rw-r--r--lib/psci/psci_private.h4
-rw-r--r--lib/psci/psci_setup.c5
-rw-r--r--lib/utils/mem_region.c78
-rw-r--r--plat/arm/board/common/board_common.mk8
-rw-r--r--plat/arm/board/common/board_css_common.c9
-rw-r--r--plat/arm/board/fvp/fvp_common.c4
-rw-r--r--plat/arm/board/fvp/fvp_pm.c13
-rw-r--r--plat/arm/board/fvp/sp_min/sp_min-fvp.mk5
-rw-r--r--plat/arm/board/juno/include/platform_def.h12
-rw-r--r--plat/arm/board/juno/sp_min/sp_min-juno.mk3
-rw-r--r--plat/arm/common/arm_bl2_setup.c4
-rw-r--r--plat/arm/common/arm_nor_psci_mem_protect.c95
-rw-r--r--plat/arm/css/common/css_pm.c11
22 files changed, 349 insertions, 14 deletions
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index 0ed39c9a..0b44ab2e 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -65,6 +65,9 @@
#define PSCI_STAT_RESIDENCY_AARCH64 U(0xc4000010)
#define PSCI_STAT_COUNT_AARCH32 U(0x84000011)
#define PSCI_STAT_COUNT_AARCH64 U(0xc4000011)
+#define PSCI_MEM_PROTECT U(0x84000013)
+#define PSCI_MEM_CHK_RANGE_AARCH32 U(0x84000014)
+#define PSCI_MEM_CHK_RANGE_AARCH64 U(0xc4000014)
/* Macro to help build the psci capabilities bitfield */
#define define_psci_cap(x) (U(1) << (x & U(0x1f)))
@@ -288,6 +291,9 @@ typedef struct plat_psci_ops {
unsigned int power_state,
psci_power_state_t *output_state);
int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level);
+ int (*mem_protect_chk)(uintptr_t base, u_register_t length);
+ int (*read_mem_protect)(int *val);
+ int (*write_mem_protect)(int val);
} plat_psci_ops_t;
/*******************************************************************************
diff --git a/include/lib/utils.h b/include/lib/utils.h
index b75813f7..cfc83022 100644
--- a/include/lib/utils.h
+++ b/include/lib/utils.h
@@ -19,6 +19,25 @@
#include <types.h>
+typedef struct mem_region_t {
+ uintptr_t base;
+ size_t nbytes;
+} mem_region_t;
+
+/*
+ * zero_normalmem all the regions defined in tbl.
+ */
+void clear_mem_regions(mem_region_t *tbl, size_t nregions);
+
+
+/*
+ * checks that a region (addr + nbytes-1) of memory is totally covered by
+ * one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1)
+ * doesn't overflow.
+ */
+int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
+ uintptr_t addr, size_t nbytes);
+
/*
* Fill a region of normal memory of size "length" in bytes with zero bytes.
*
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 4d145005..ae0f9566 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -89,11 +89,26 @@
#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 KB */
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
#define PLAT_ARM_FIP_BASE V2M_FLASH0_BASE
-#define PLAT_ARM_FIP_MAX_SIZE V2M_FLASH0_SIZE
+#define PLAT_ARM_FIP_MAX_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
-#define PLAT_ARM_NVM_SIZE V2M_FLASH0_SIZE
+#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \
+ V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * Map mem_protect flash region with read and write permissions
+ */
+#define ARM_V2M_MAP_MEM_PROTECT MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR, \
+ V2M_FLASH_BLOCK_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
#endif /* __BOARD_ARM_DEF_H__ */
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index 2ad513ac..364b7803 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -69,6 +69,7 @@
/* NOR Flash */
#define V2M_FLASH0_BASE 0x08000000
#define V2M_FLASH0_SIZE 0x04000000
+#define V2M_FLASH_BLOCK_SIZE 0x00040000 /* 256 KB */
#define V2M_IOFPGA_BASE 0x1c000000
#define V2M_IOFPGA_SIZE 0x03000000
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 787ccb02..dbf102b8 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -177,7 +177,12 @@
ARM_NS_DRAM1_SIZE, \
MT_MEMORY | MT_RW | MT_NS)
+#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \
+ ARM_DRAM2_BASE, \
+ ARM_DRAM2_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
#ifdef SPD_tspd
+
#define ARM_MAP_TSP_SEC_MEM MAP_REGION_FLAT( \
TSP_SEC_MEM_BASE, \
TSP_SEC_MEM_SIZE, \
@@ -224,8 +229,18 @@
* Required platform porting definitions common to all ARM standard platforms
*****************************************************************************/
+/*
+ * We need to access DRAM2 from BL2 for PSCI_MEM_PROTECT for
+ * AArch64 builds
+ */
+#ifdef AARCH64
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 36)
+#else
#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#endif
+
/*
* This macro defines the deepest retention state possible. A higher state
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index f0e97678..4e589c0c 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -122,6 +122,10 @@ int arm_validate_power_state(unsigned int power_state,
int arm_validate_ns_entrypoint(uintptr_t entrypoint);
void arm_system_pwr_domain_resume(void);
void arm_program_trusted_mailbox(uintptr_t address);
+int arm_psci_read_mem_protect(int *val);
+int arm_nor_psci_write_mem_protect(int val);
+void arm_nor_psci_do_mem_protect(void);
+int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length);
/* Topology utility function */
int arm_check_mpidr(u_register_t mpidr);
diff --git a/lib/psci/psci_lib.mk b/lib/psci/psci_lib.mk
index 29080dbb..1d4aac4a 100644
--- a/lib/psci/psci_lib.mk
+++ b/lib/psci/psci_lib.mk
@@ -17,6 +17,7 @@ PSCI_LIB_SOURCES := lib/el3_runtime/cpu_data_array.c \
lib/psci/psci_main.c \
lib/psci/psci_setup.c \
lib/psci/psci_system_off.c \
+ lib/psci/psci_mem_protect.c \
lib/psci/${ARCH}/psci_helpers.S
ifeq (${ARCH}, aarch64)
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 257479aa..a5d707e0 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -408,6 +408,11 @@ u_register_t psci_smc_handler(uint32_t smc_fid,
case PSCI_STAT_COUNT_AARCH32:
return psci_stat_count(x1, x2);
#endif
+ case PSCI_MEM_PROTECT:
+ return psci_mem_protect(x1);
+
+ case PSCI_MEM_CHK_RANGE_AARCH32:
+ return psci_mem_chk_range(x1, x2);
default:
break;
@@ -445,6 +450,10 @@ u_register_t psci_smc_handler(uint32_t smc_fid,
return psci_stat_count(x1, x2);
#endif
+ case PSCI_MEM_CHK_RANGE_AARCH64:
+ return psci_mem_chk_range(x1, x2);
+
+
default:
break;
}
diff --git a/lib/psci/psci_mem_protect.c b/lib/psci/psci_mem_protect.c
new file mode 100644
index 00000000..fca84e90
--- /dev/null
+++ b/lib/psci/psci_mem_protect.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <utils.h>
+#include "psci_private.h"
+
+int psci_mem_protect(unsigned int enable)
+{
+ int val;
+
+ assert(psci_plat_pm_ops->read_mem_protect);
+ assert(psci_plat_pm_ops->write_mem_protect);
+
+ if (psci_plat_pm_ops->read_mem_protect(&val) < 0)
+ return PSCI_E_NOT_SUPPORTED;
+ if (psci_plat_pm_ops->write_mem_protect(enable) < 0)
+ return PSCI_E_NOT_SUPPORTED;
+
+ return val != 0;
+}
+
+int psci_mem_chk_range(uintptr_t base, u_register_t length)
+{
+ int ret;
+
+ assert(psci_plat_pm_ops->mem_protect_chk);
+
+ if (length == 0 || check_uptr_overflow(base, length-1))
+ return PSCI_E_DENIED;
+
+ ret = psci_plat_pm_ops->mem_protect_chk(base, length);
+ return (ret < 0) ? PSCI_E_DENIED : PSCI_E_SUCCESS;
+}
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index da6a20fa..facfacb0 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -269,4 +269,8 @@ u_register_t psci_stat_residency(u_register_t target_cpu,
u_register_t psci_stat_count(u_register_t target_cpu,
unsigned int power_state);
+/* Private exported functions from psci_mem_protect.c */
+int psci_mem_protect(unsigned int enable);
+int psci_mem_chk_range(uintptr_t base, u_register_t length);
+
#endif /* __PSCI_PRIVATE_H__ */
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index f70e34da..5ef49acb 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -243,6 +243,11 @@ int psci_setup(const psci_lib_args_t *lib_args)
psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET);
if (psci_plat_pm_ops->get_node_hw_state)
psci_caps |= define_psci_cap(PSCI_NODE_HW_STATE_AARCH64);
+ if (psci_plat_pm_ops->read_mem_protect &&
+ psci_plat_pm_ops->write_mem_protect)
+ psci_caps |= define_psci_cap(PSCI_MEM_PROTECT);
+ if (psci_plat_pm_ops->mem_protect_chk)
+ psci_caps |= define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64);
#if ENABLE_PSCI_STAT
psci_caps |= define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64);
diff --git a/lib/utils/mem_region.c b/lib/utils/mem_region.c
new file mode 100644
index 00000000..31c6231f
--- /dev/null
+++ b/lib/utils/mem_region.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <utils.h>
+
+/*
+ * All the regions defined in mem_region_t must have the following properties
+ *
+ * - Any contiguous regions must be merged into a single entry.
+ * - The number of bytes of each region must be greater than zero.
+ * - The calculation of the highest address within the region (base + nbytes-1)
+ * doesn't produce an overflow.
+ *
+ * These conditions must be fulfilled by the caller and they aren't checked
+ * at runtime.
+ */
+
+/*
+ * zero_normalmem all the regions defined in tbl.
+ * It assumes that MMU is enabled and the memory is Normal memory.
+ * tbl must be a valid pointer to a memory mem_region_t array,
+ * nregions is the size of the array.
+ */
+void clear_mem_regions(mem_region_t *tbl, size_t nregions)
+{
+ size_t i;
+
+ assert(tbl);
+ assert(nregions > 0);
+
+ for (i = 0; i < nregions; i++) {
+ assert(tbl->nbytes > 0);
+ assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
+ zero_normalmem((void *) (tbl->base), tbl->nbytes);
+ tbl++;
+ }
+}
+
+/*
+ * This function checks that a region (addr + nbytes-1) of memory is totally
+ * covered by one of the regions defined in tbl.
+ * tbl must be a valid pointer to a memory mem_region_t array, nregions
+ * is the size of the array and the region described by addr and nbytes must
+ * not generate an overflow.
+ * Returns:
+ * -1 means that the region is not covered by any of the regions
+ * described in tbl.
+ * 0 the region (addr + nbytes-1) is covered by one of the regions described
+ * in tbl
+ */
+int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
+ uintptr_t addr, size_t nbytes)
+{
+ uintptr_t region_start, region_end, start, end;
+ size_t i;
+
+ assert(tbl);
+ assert(nbytes > 0);
+ assert(!check_uptr_overflow(addr, nbytes-1));
+
+ region_start = addr;
+ region_end = addr + (nbytes - 1);
+ for (i = 0; i < nregions; i++) {
+ assert(tbl->nbytes > 0);
+ assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
+ start = tbl->base;
+ end = start + (tbl->nbytes - 1);
+ if (region_start >= start && region_end <= end)
+ return 0;
+ tbl++;
+ }
+
+ return -1;
+}
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index 643047ce..d63ae9a3 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -12,9 +12,13 @@ PLAT_BL_COMMON_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \
BL1_SOURCES += plat/arm/board/common/drivers/norflash/norflash.c
-BL2_SOURCES += plat/arm/board/common/drivers/norflash/norflash.c
+BL2_SOURCES += lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
+ plat/arm/board/common/drivers/norflash/norflash.c
-#BL31_SOURCES +=
+BL31_SOURCES += lib/utils/mem_region.c \
+ plat/arm/board/common/drivers/norflash/norflash.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
ifneq (${TRUSTED_BOARD_BOOT},0)
ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c
index 159bf86f..032ebdf7 100644
--- a/plat/arm/board/common/board_css_common.c
+++ b/plat/arm/board/common/board_css_common.c
@@ -29,10 +29,16 @@ const mmap_region_t plat_arm_mmap[] = {
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
V2M_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
V2M_MAP_IOFPGA,
CSS_MAP_DEVICE,
SOC_CSS_MAP_DEVICE,
ARM_MAP_NS_DRAM1,
+#ifdef AARCH64
+ ARM_MAP_DRAM2,
+#endif
#ifdef SPD_tspd
ARM_MAP_TSP_SEC_MEM,
#endif
@@ -56,6 +62,9 @@ const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
V2M_MAP_IOFPGA,
CSS_MAP_DEVICE,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
SOC_CSS_MAP_DEVICE,
{0}
};
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index e869f5b2..7015ac04 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -79,6 +79,9 @@ const mmap_region_t plat_arm_mmap[] = {
MAP_DEVICE0,
MAP_DEVICE1,
ARM_MAP_NS_DRAM1,
+#ifdef AARCH64
+ ARM_MAP_DRAM2,
+#endif
#ifdef SPD_tspd
ARM_MAP_TSP_SEC_MEM,
#endif
@@ -109,6 +112,7 @@ const mmap_region_t plat_arm_mmap[] = {
V2M_MAP_IOFPGA,
MAP_DEVICE0,
MAP_DEVICE1,
+ ARM_V2M_MAP_MEM_PROTECT,
{0}
};
#endif
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 9a02089e..dad3a794 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -324,5 +324,14 @@ plat_psci_ops_t plat_arm_psci_pm_ops = {
.system_reset = fvp_system_reset,
.validate_power_state = arm_validate_power_state,
.validate_ns_entrypoint = arm_validate_ns_entrypoint,
- .get_node_hw_state = fvp_node_hw_state
+ .get_node_hw_state = fvp_node_hw_state,
+/*
+ * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+ * as that would require mapping in all of NS DRAM into BL31 or BL32.
+ */
+#if !RESET_TO_BL31 && !RESET_TO_SP_MIN
+ .mem_protect_chk = arm_psci_mem_protect_chk,
+ .read_mem_protect = arm_psci_read_mem_protect,
+ .write_mem_protect = arm_nor_psci_write_mem_protect,
+#endif
};
diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
index 864df1ba..b370fd55 100644
--- a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
+++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
@@ -5,11 +5,14 @@
#
# SP_MIN source files specific to FVP platform
-BL32_SOURCES += plat/arm/board/fvp/aarch32/fvp_helpers.S \
+BL32_SOURCES += lib/utils/mem_region.c \
+ plat/arm/board/fvp/aarch32/fvp_helpers.S \
plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c \
plat/arm/board/fvp/fvp_pm.c \
plat/arm/board/fvp/fvp_topology.c \
plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c \
+ plat/arm/board/common/drivers/norflash/norflash.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
${FVP_CPU_LIBS} \
${FVP_GIC_SOURCES} \
${FVP_INTERCONNECT_SOURCES} \
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 7794af55..3c44a1e9 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -68,11 +68,11 @@
#ifdef IMAGE_BL2
#ifdef SPD_opteed
-# define PLAT_ARM_MMAP_ENTRIES 9
-# define MAX_XLAT_TABLES 4
+# define PLAT_ARM_MMAP_ENTRIES 11
+# define MAX_XLAT_TABLES 5
#else
-# define PLAT_ARM_MMAP_ENTRIES 8
-# define MAX_XLAT_TABLES 3
+# define PLAT_ARM_MMAP_ENTRIES 10
+# define MAX_XLAT_TABLES 4
#endif
#endif
@@ -82,8 +82,8 @@
#endif
#ifdef IMAGE_BL31
-# define PLAT_ARM_MMAP_ENTRIES 5
-# define MAX_XLAT_TABLES 2
+# define PLAT_ARM_MMAP_ENTRIES 7
+# define MAX_XLAT_TABLES 3
#endif
#ifdef IMAGE_BL32
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
index 336c4e7c..cd1f4976 100644
--- a/plat/arm/board/juno/sp_min/sp_min-juno.mk
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -8,7 +8,10 @@
BL32_SOURCES += lib/cpus/aarch32/cortex_a53.S \
lib/cpus/aarch32/cortex_a57.S \
lib/cpus/aarch32/cortex_a72.S \
+ lib/utils/mem_region.c \
+ plat/arm/board/common/drivers/norflash/norflash.c \
plat/arm/board/juno/juno_topology.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
plat/arm/soc/common/soc_css_security.c \
${JUNO_GIC_SOURCES} \
${JUNO_INTERCONNECT_SOURCES} \
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index cab6113e..5d83118a 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -193,6 +193,10 @@ void arm_bl2_platform_setup(void)
{
/* Initialize the secure environment */
plat_arm_security_setup();
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+ arm_nor_psci_do_mem_protect();
+#endif
}
void bl2_platform_setup(void)
diff --git a/plat/arm/common/arm_nor_psci_mem_protect.c b/plat/arm/common/arm_nor_psci_mem_protect.c
new file mode 100644
index 00000000..c5263fd8
--- /dev/null
+++ b/plat/arm/common/arm_nor_psci_mem_protect.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <norflash.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <utils.h>
+
+mem_region_t arm_ram_ranges[] = {
+ {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_SIZE},
+#ifdef AARCH64
+ {ARM_DRAM2_BASE, ARM_DRAM2_SIZE},
+#endif
+};
+
+/*******************************************************************************
+ * Function that reads the content of the memory protect variable that
+ * enables clearing of non secure memory when system boots. This variable
+ * should be stored in a secure NVRAM.
+ ******************************************************************************/
+int arm_psci_read_mem_protect(int *enabled)
+{
+ int tmp;
+
+ tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
+ *enabled = (tmp == 1);
+ return 0;
+}
+
+/*******************************************************************************
+ * Function that writes the content of the memory protect variable that
+ * enables overwritten of non secure memory when system boots.
+ ******************************************************************************/
+int arm_nor_psci_write_mem_protect(int val)
+{
+ int enable = (val != 0);
+
+ if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+ ERROR("unlocking memory protect variable\n");
+ return -1;
+ }
+
+ if (enable) {
+ /*
+ * If we want to write a value different than 0
+ * then we have to erase the full block because
+ * otherwise we cannot ensure that the value programmed
+ * into the flash is going to be the same than the value
+ * requested by the caller
+ */
+ if (nor_erase(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+ ERROR("erasing block containing memory protect variable\n");
+ return -1;
+ }
+ }
+
+ if (nor_word_program(PLAT_ARM_MEM_PROT_ADDR, enable) != 0) {
+ ERROR("programming memory protection variable\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ * Function used for required psci operations performed when
+ * system boots
+ ******************************************************************************/
+void arm_nor_psci_do_mem_protect(void)
+{
+ int enable;
+
+ arm_psci_read_mem_protect(&enable);
+ if (!enable)
+ return;
+ INFO("PSCI: Overwritting non secure memory\n");
+ clear_mem_regions(arm_ram_ranges, ARRAY_SIZE(arm_ram_ranges));
+ arm_nor_psci_write_mem_protect(0);
+}
+
+/*******************************************************************************
+ * Function that checks if a region is protected by the memory protect
+ * mechanism
+ ******************************************************************************/
+int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length)
+{
+ return mem_region_in_array_chk(arm_ram_ranges,
+ ARRAY_SIZE(arm_ram_ranges),
+ base, length);
+}
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index e0e52004..93d51fe6 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -290,5 +290,14 @@ plat_psci_ops_t plat_arm_psci_pm_ops = {
.validate_ns_entrypoint = arm_validate_ns_entrypoint,
.translate_power_state_by_mpidr = css_translate_power_state_by_mpidr,
.get_node_hw_state = css_node_hw_state,
- .get_sys_suspend_power_state = css_get_sys_suspend_power_state
+ .get_sys_suspend_power_state = css_get_sys_suspend_power_state,
+/*
+ * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+ * as that would require mapping in all of NS DRAM into BL31 or BL32.
+ */
+#if defined(PLAT_ARM_MEM_PROT_ADDR) && !RESET_TO_BL31 && !RESET_TO_SP_MIN
+ .mem_protect_chk = arm_psci_mem_protect_chk,
+ .read_mem_protect = arm_psci_read_mem_protect,
+ .write_mem_protect = arm_nor_psci_write_mem_protect,
+#endif
};