diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h index e5f5373..ce436d2 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 0770c0e..53b4a45 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_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 836a672..3dd2a22 100644 --- a/plat/arm/board/juno/juno_bl1_setup.c +++ b/plat/arm/board/juno/juno_bl1_setup.c @@ -5,15 +5,72 @@ */ #include +#include #include #include #include +#include #include #include #include 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 0000000..dd8e278 --- /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 +#include +#include +#include + +/* + * 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 16390fa..481844f 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -22,7 +22,12 @@ 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 @@ 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 @@ ${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 @@ # 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 a4d2b44..d9104ee 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 @@ #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_err.c b/plat/arm/common/arm_err.c index 66568e7..e13e51f 100644 --- a/plat/arm/common/arm_err.c +++ b/plat/arm/common/arm_err.c @@ -13,10 +13,12 @@ #include #include +#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 @@ for (;;) wfi(); } + +void __dead2 plat_error_handler(int err) +{ + plat_arm_error_handler(err); +}