diff options
-rw-r--r-- | include/lib/psci/psci.h | 6 | ||||
-rw-r--r-- | include/lib/utils.h | 19 | ||||
-rw-r--r-- | include/plat/arm/board/common/board_arm_def.h | 19 | ||||
-rw-r--r-- | include/plat/arm/board/common/v2m_def.h | 1 | ||||
-rw-r--r-- | include/plat/arm/common/arm_def.h | 15 | ||||
-rw-r--r-- | include/plat/arm/common/plat_arm.h | 4 | ||||
-rw-r--r-- | lib/psci/psci_lib.mk | 1 | ||||
-rw-r--r-- | lib/psci/psci_main.c | 9 | ||||
-rw-r--r-- | lib/psci/psci_mem_protect.c | 38 | ||||
-rw-r--r-- | lib/psci/psci_private.h | 4 | ||||
-rw-r--r-- | lib/psci/psci_setup.c | 5 | ||||
-rw-r--r-- | lib/utils/mem_region.c | 78 | ||||
-rw-r--r-- | plat/arm/board/common/board_common.mk | 8 | ||||
-rw-r--r-- | plat/arm/board/common/board_css_common.c | 9 | ||||
-rw-r--r-- | plat/arm/board/fvp/fvp_common.c | 4 | ||||
-rw-r--r-- | plat/arm/board/fvp/fvp_pm.c | 13 | ||||
-rw-r--r-- | plat/arm/board/fvp/sp_min/sp_min-fvp.mk | 5 | ||||
-rw-r--r-- | plat/arm/board/juno/include/platform_def.h | 12 | ||||
-rw-r--r-- | plat/arm/board/juno/sp_min/sp_min-juno.mk | 3 | ||||
-rw-r--r-- | plat/arm/common/arm_bl2_setup.c | 4 | ||||
-rw-r--r-- | plat/arm/common/arm_nor_psci_mem_protect.c | 95 | ||||
-rw-r--r-- | plat/arm/css/common/css_pm.c | 11 |
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 }; |