summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bl31/bl31_main.c3
-rw-r--r--include/plat/arm/board/common/board_arm_def.h2
-rw-r--r--include/plat/arm/board/common/v2m_def.h3
-rw-r--r--include/plat/arm/common/plat_arm.h2
-rw-r--r--plat/arm/board/juno/juno_bl1_setup.c57
-rw-r--r--plat/arm/board/juno/juno_err.c25
-rw-r--r--plat/arm/board/juno/platform.mk18
-rw-r--r--plat/arm/common/arm_bl1_setup.c13
-rw-r--r--plat/arm/common/arm_dyn_cfg.c29
-rw-r--r--plat/arm/common/arm_dyn_cfg_helpers.c21
-rw-r--r--plat/arm/common/arm_err.c9
-rw-r--r--plat/arm/css/common/css_common.mk9
-rw-r--r--plat/arm/soc/common/soc_css_security.c8
-rw-r--r--services/std_svc/sdei/sdei_main.c14
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);