diff options
-rw-r--r-- | bl31/bl31_main.c | 3 | ||||
-rw-r--r-- | include/plat/arm/board/common/board_arm_def.h | 2 | ||||
-rw-r--r-- | include/plat/arm/board/common/v2m_def.h | 3 | ||||
-rw-r--r-- | include/plat/arm/common/plat_arm.h | 2 | ||||
-rw-r--r-- | plat/arm/board/juno/juno_bl1_setup.c | 57 | ||||
-rw-r--r-- | plat/arm/board/juno/juno_err.c | 25 | ||||
-rw-r--r-- | plat/arm/board/juno/platform.mk | 18 | ||||
-rw-r--r-- | plat/arm/common/arm_bl1_setup.c | 13 | ||||
-rw-r--r-- | plat/arm/common/arm_dyn_cfg.c | 29 | ||||
-rw-r--r-- | plat/arm/common/arm_dyn_cfg_helpers.c | 21 | ||||
-rw-r--r-- | plat/arm/common/arm_err.c | 9 | ||||
-rw-r--r-- | plat/arm/css/common/css_common.mk | 9 | ||||
-rw-r--r-- | plat/arm/soc/common/soc_css_security.c | 8 | ||||
-rw-r--r-- | services/std_svc/sdei/sdei_main.c | 14 |
14 files changed, 182 insertions, 31 deletions
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index 650181dd..5479a498 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -109,7 +109,8 @@ void bl31_main(void) int32_t rc = (*bl32_init)(); if (rc != 0) { - ERROR("BL31: BL32 initialization failed (rc = %d)", rc); + WARN("BL31: BL32 initialization failed (rc = %d)\n", + rc); } } /* diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index 86c85123..9af8f8c4 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -102,7 +102,7 @@ * little space for growth. */ #if TRUSTED_BOARD_BOOT -# define PLAT_ARM_MAX_BL2_SIZE 0x1C000 +# define PLAT_ARM_MAX_BL2_SIZE 0x1D000 #else # define PLAT_ARM_MAX_BL2_SIZE 0x11000 #endif diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h index e5f53732..ce436d2c 100644 --- a/include/plat/arm/board/common/v2m_def.h +++ b/include/plat/arm/board/common/v2m_def.h @@ -32,6 +32,9 @@ #define V2M_FUNC_SHUTDOWN 0x08 #define V2M_FUNC_REBOOT 0x09 +/* NVFLAGS in the V2M motherboard which is preserved after a watchdog reset */ + #define V2M_SYS_NVFLAGS_ADDR (V2M_SYSREGS_BASE + V2M_SYS_NVFLAGS) + /* * V2M sysled bit definitions. The values written to this * register are defined in arch.h & runtime_svc.h. Only diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 0770c0ec..53b4a45c 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -245,6 +245,8 @@ void plat_arm_interconnect_init(void); void plat_arm_interconnect_enter_coherency(void); void plat_arm_interconnect_exit_coherency(void); void plat_arm_program_trusted_mailbox(uintptr_t address); +int plat_arm_bl1_fwu_needed(void); +void plat_arm_error_handler(int err); #if ARM_PLAT_MT unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr); diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c index 836a6725..3dd2a227 100644 --- a/plat/arm/board/juno/juno_bl1_setup.c +++ b/plat/arm/board/juno/juno_bl1_setup.c @@ -5,15 +5,72 @@ */ #include <bl_common.h> +#include <debug.h> #include <errno.h> #include <plat_arm.h> #include <platform.h> +#include <sds.h> #include <sp805.h> #include <tbbr_img_def.h> #include <v2m_def.h> void juno_reset_to_aarch32_state(void); +static int is_watchdog_reset(void) +{ +#if !CSS_USE_SCMI_SDS_DRIVER + #define RESET_REASON_WDOG_RESET (0x2) + const uint32_t *reset_flags_ptr = (const uint32_t *)SSC_GPRETN; + + if ((*reset_flags_ptr & RESET_REASON_WDOG_RESET) != 0) + return 1; + + return 0; +#else + int ret; + uint32_t scp_reset_synd_flags; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SCP SDS initialization failed\n"); + panic(); + } + + ret = sds_struct_read(SDS_RESET_SYNDROME_STRUCT_ID, + SDS_RESET_SYNDROME_OFFSET, + &scp_reset_synd_flags, + SDS_RESET_SYNDROME_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Getting reset reason from SDS failed\n"); + panic(); + } + + /* Check if the WATCHDOG_RESET_BIT is set in the reset syndrome */ + if (scp_reset_synd_flags & SDS_RESET_SYNDROME_AP_WD_RESET_BIT) + return 1; + + return 0; +#endif +} + +/******************************************************************************* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or watchdog reset happened. + ******************************************************************************/ +int plat_arm_bl1_fwu_needed(void) +{ + const uint32_t *nv_flags_ptr = (const uint32_t *)V2M_SYS_NVFLAGS_ADDR; + + /* Check if TOC is invalid or watchdog reset happened. */ + if ((arm_io_is_toc_valid() != 1) || + (((*nv_flags_ptr == -EAUTH) || (*nv_flags_ptr == -ENOENT)) + && is_watchdog_reset())) + return 1; + + return 0; +} + /******************************************************************************* * On JUNO update the arg2 with address of SCP_BL2U image info. ******************************************************************************/ diff --git a/plat/arm/board/juno/juno_err.c b/plat/arm/board/juno/juno_err.c new file mode 100644 index 00000000..dd8e2788 --- /dev/null +++ b/plat/arm/board/juno/juno_err.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <errno.h> +#include <platform.h> +#include <v2m_def.h> + +/* + * Juno error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + uint32_t *flags_ptr = (uint32_t *)V2M_SYS_NVFLAGS_ADDR; + + /* Propagate the err code in the NV-flags register */ + *flags_ptr = err; + + /* Loop until the watchdog resets the system */ + for (;;) + wfi(); +} diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 16390fa4..481844f0 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -22,7 +22,12 @@ ifneq (${ENABLE_STACK_PROTECTOR}, 0) JUNO_SECURITY_SOURCES += plat/arm/board/juno/juno_stack_protector.c endif -PLAT_INCLUDES := -Iplat/arm/board/juno/include +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +PLAT_INCLUDES := -Iplat/arm/board/juno/include \ + -Iplat/arm/css/drivers/sds PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/${ARCH}/juno_helpers.S @@ -55,11 +60,13 @@ ifeq (${ARCH},aarch64) BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a72.S \ + plat/arm/board/juno/juno_err.c \ plat/arm/board/juno/juno_bl1_setup.c \ ${JUNO_INTERCONNECT_SOURCES} \ ${JUNO_SECURITY_SOURCES} BL2_SOURCES += lib/utils/mem_region.c \ + plat/arm/board/juno/juno_err.c \ plat/arm/board/juno/juno_bl2_setup.c \ plat/arm/common/arm_nor_psci_mem_protect.c \ ${JUNO_SECURITY_SOURCES} @@ -76,6 +83,11 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ ${JUNO_GIC_SOURCES} \ ${JUNO_INTERCONNECT_SOURCES} \ ${JUNO_SECURITY_SOURCES} + +ifeq (${CSS_USE_SCMI_SDS_DRIVER},1) +BL1_SOURCES += plat/arm/css/drivers/sds/sds.c +endif + endif # Errata workarounds for Cortex-A53: @@ -112,10 +124,6 @@ ARM_BOARD_OPTIMISE_MEM := 1 # Do not enable SVE ENABLE_SVE_FOR_NS := 0 -# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the -# SCP during power management operations and for SCP RAM Firmware transfer. -CSS_USE_SCMI_SDS_DRIVER := 1 - include plat/arm/board/common/board_css.mk include plat/arm/common/arm_common.mk include plat/arm/soc/common/soc_css.mk diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index a4d2b44c..d9104ee3 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -23,6 +23,8 @@ #pragma weak bl1_platform_setup #pragma weak bl1_plat_sec_mem_layout #pragma weak bl1_plat_prepare_exit +#pragma weak bl1_plat_get_next_image_id +#pragma weak plat_arm_bl1_fwu_needed #define MAP_BL1_TOTAL MAP_REGION_FLAT( \ bl1_tzram_layout.total_base, \ @@ -186,13 +188,22 @@ void bl1_plat_prepare_exit(entry_point_info_t *ep_info) #endif } +/* + * On Arm platforms, the FWU process is triggered when the FIP image has + * been tampered with. + */ +int plat_arm_bl1_fwu_needed(void) +{ + return (arm_io_is_toc_valid() != 1); +} + /******************************************************************************* * The following function checks if Firmware update is needed, * by checking if TOC in FIP image is valid or not. ******************************************************************************/ unsigned int bl1_plat_get_next_image_id(void) { - if (!arm_io_is_toc_valid()) + if (plat_arm_bl1_fwu_needed() != 0) return NS_BL1U_IMAGE_ID; return BL2_IMAGE_ID; diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c index f2570a84..95fe2c53 100644 --- a/plat/arm/common/arm_dyn_cfg.c +++ b/plat/arm/common/arm_dyn_cfg.c @@ -21,6 +21,7 @@ /* Variable to store the address of TB_FW_CONFIG file */ static void *tb_fw_cfg_dtb; +static size_t tb_fw_cfg_dtb_size; #if TRUSTED_BOARD_BOOT @@ -62,11 +63,15 @@ int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size) int err; /* If in BL2, retrieve the already allocated heap's info from DTB */ - err = arm_get_dtb_mbedtls_heap_info(tb_fw_cfg_dtb, heap_addr, - heap_size); - if (err < 0) { - ERROR("BL2: unable to retrieve shared Mbed TLS heap " - "information from DTB\n"); + if (tb_fw_cfg_dtb != NULL) { + err = arm_get_dtb_mbedtls_heap_info(tb_fw_cfg_dtb, heap_addr, + heap_size); + if (err < 0) { + ERROR("BL2: unable to retrieve shared Mbed TLS heap information from DTB\n"); + panic(); + } + } else { + ERROR("BL2: DTB missing, cannot get Mbed TLS heap\n"); panic(); } #endif @@ -98,10 +103,16 @@ void arm_bl1_set_mbedtls_heap(void) err = arm_set_dtb_mbedtls_heap_info(tb_fw_cfg_dtb, mbedtls_heap_addr, mbedtls_heap_size); if (err < 0) { - ERROR("BL1: unable to write shared Mbed TLS heap " - "information to DTB\n"); + ERROR("BL1: unable to write shared Mbed TLS heap information to DTB\n"); panic(); } + /* + * Ensure that the info written to the DTB is visible to other + * images. It's critical because BL2 won't be able to proceed + * without the heap info. + */ + flush_dcache_range((uintptr_t)tb_fw_cfg_dtb, + tb_fw_cfg_dtb_size); } } @@ -122,7 +133,8 @@ void arm_load_tb_fw_config(void) SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, VERSION_2, image_info_t, 0), .image_info.image_base = ARM_TB_FW_CONFIG_BASE, - .image_info.image_max_size = ARM_TB_FW_CONFIG_LIMIT - ARM_TB_FW_CONFIG_BASE, + .image_info.image_max_size = + ARM_TB_FW_CONFIG_LIMIT - ARM_TB_FW_CONFIG_BASE }; VERBOSE("BL1: Loading TB_FW_CONFIG\n"); @@ -136,6 +148,7 @@ void arm_load_tb_fw_config(void) /* At this point we know that a DTB is indeed available */ config_base = arm_tb_fw_info.image_info.image_base; tb_fw_cfg_dtb = (void *)config_base; + tb_fw_cfg_dtb_size = (size_t)arm_tb_fw_info.image_info.image_max_size; /* The BL2 ep_info arg0 is modified to point to TB_FW_CONFIG */ image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c index e6109038..d12d09c7 100644 --- a/plat/arm/common/arm_dyn_cfg_helpers.c +++ b/plat/arm/common/arm_dyn_cfg_helpers.c @@ -167,8 +167,6 @@ int arm_dyn_tb_fw_cfg_init(void *dtb, int *node) return 0; } - -#if TRUSTED_BOARD_BOOT && LOAD_IMAGE_V2 /* * Reads and returns the Mbed TLS shared heap information from the DTB. * This function is supposed to be called *only* when a DTB is present. @@ -187,8 +185,7 @@ int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr, /* Verify the DTB is valid and get the root node */ err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); if (err < 0) { - ERROR("%s: Invalid TB_FW_CONFIG. Cannot retrieve Mbed TLS " - "heap information from DTB\n", __func__); + ERROR("Invalid TB_FW_CONFIG. Cannot retrieve Mbed TLS heap information from DTB\n"); return -1; } @@ -196,14 +193,14 @@ int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr, err = fdtw_read_cells(dtb, dtb_root, DTB_PROP_MBEDTLS_HEAP_ADDR, 2, heap_addr); if (err < 0) { - ERROR("%s: error while reading %s from DTB\n", __func__, + ERROR("Error while reading %s from DTB\n", DTB_PROP_MBEDTLS_HEAP_ADDR); return -1; } err = fdtw_read_cells(dtb, dtb_root, DTB_PROP_MBEDTLS_HEAP_SIZE, 1, heap_size); if (err < 0) { - ERROR("%s: error while reading %s from DTB\n", __func__, + ERROR("Error while reading %s from DTB\n", DTB_PROP_MBEDTLS_HEAP_SIZE); return -1; } @@ -234,8 +231,7 @@ int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size) */ err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); if (err < 0) { - ERROR("%s: Invalid TB_FW_CONFIG loaded. Unable to get " - "root node\n", __func__); + ERROR("Invalid TB_FW_CONFIG loaded. Unable to get root node\n"); return -1; } @@ -249,19 +245,18 @@ int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size) err = fdtw_write_inplace_cells(dtb, dtb_root, DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr); if (err < 0) { - ERROR("%s: unable to write DTB property %s\n", - __func__, DTB_PROP_MBEDTLS_HEAP_ADDR); + ERROR("Unable to write DTB property %s\n", + DTB_PROP_MBEDTLS_HEAP_ADDR); return -1; } err = fdtw_write_inplace_cells(dtb, dtb_root, DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size); if (err < 0) { - ERROR("%s: unable to write DTB property %s\n", - __func__, DTB_PROP_MBEDTLS_HEAP_SIZE); + ERROR("Unable to write DTB property %s\n", + DTB_PROP_MBEDTLS_HEAP_SIZE); return -1; } return 0; } -#endif /* TRUSTED_BOARD_BOOT && LOAD_IMAGE_V2 */ diff --git a/plat/arm/common/arm_err.c b/plat/arm/common/arm_err.c index 66568e7d..e13e51f7 100644 --- a/plat/arm/common/arm_err.c +++ b/plat/arm/common/arm_err.c @@ -13,10 +13,12 @@ #include <platform_def.h> #include <stdint.h> +#pragma weak plat_arm_error_handler + /* * ARM common implementation for error handler */ -void plat_error_handler(int err) +void __dead2 plat_arm_error_handler(int err) { int ret; @@ -44,3 +46,8 @@ void plat_error_handler(int err) for (;;) wfi(); } + +void __dead2 plat_error_handler(int err) +{ + plat_arm_error_handler(err); +} diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk index 29dd01d1..984c1da0 100644 --- a/plat/arm/css/common/css_common.mk +++ b/plat/arm/css/common/css_common.mk @@ -85,3 +85,12 @@ endif # Process CSS_USE_SCMI_SDS_DRIVER flag $(eval $(call assert_boolean,CSS_USE_SCMI_SDS_DRIVER)) $(eval $(call add_define,CSS_USE_SCMI_SDS_DRIVER)) + +# Process CSS_NON_SECURE_UART flag +# This undocumented build option is only to enable debug access to the UART +# from non secure code, which is useful on some platforms. +# Default (obviously) is off. +CSS_NON_SECURE_UART := 0 +$(eval $(call assert_boolean,CSS_NON_SECURE_UART)) +$(eval $(call add_define,CSS_NON_SECURE_UART)) + diff --git a/plat/arm/soc/common/soc_css_security.c b/plat/arm/soc/common/soc_css_security.c index 19bd76f8..f2296796 100644 --- a/plat/arm/soc/common/soc_css_security.c +++ b/plat/arm/soc/common/soc_css_security.c @@ -23,7 +23,7 @@ void soc_css_init_nic400(void) /* * Allow non-secure access to some SOC regions, excluding UART1, which - * remains secure. + * remains secure (unless CSS_NON_SECURE_UART is set). * Note: This is the NIC-400 device on the SOC */ mmio_write_32(SOC_CSS_NIC400_BASE + @@ -36,9 +36,15 @@ void soc_css_init_nic400(void) NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_PL354_SMC), ~0); mmio_write_32(SOC_CSS_NIC400_BASE + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_APB4_BRIDGE), ~0); +#if CSS_NON_SECURE_UART + /* Configure UART for non-secure access */ + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_BOOTSEC_BRIDGE), ~0); +#else mmio_write_32(SOC_CSS_NIC400_BASE + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_BOOTSEC_BRIDGE), ~SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1); +#endif /* CSS_NON_SECURE_UART */ } diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c index 9b78d7fb..990d0287 100644 --- a/services/std_svc/sdei/sdei_main.c +++ b/services/std_svc/sdei/sdei_main.c @@ -81,6 +81,17 @@ static void *sdei_cpu_on_init(const void *arg) return NULL; } +/* CPU initialisation after wakeup from suspend */ +static void *sdei_cpu_wakeup_init(const void *arg) +{ + SDEI_LOG("Events masked on %lx\n", read_mpidr_el1()); + + /* All PEs wake up with SDEI events masked */ + sdei_pe_mask(); + + return 0; +} + /* Initialise an SDEI class */ static void sdei_class_init(sdei_class_t class) { @@ -1075,3 +1086,6 @@ uint64_t sdei_smc_handler(uint32_t smc_fid, /* Subscribe to PSCI CPU on to initialize per-CPU SDEI configuration */ SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, sdei_cpu_on_init); + +/* Subscribe to PSCI CPU suspend finisher for per-CPU configuration */ +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, sdei_cpu_wakeup_init); |