juno: Revert FWU update detect mechanism

The patch 7b56928 unified the FWU mechanism on FVP and Juno
platforms due to issues with MCC firmware not preserving the
NVFLAGS. With MCCv150 firmware, this issue is resolved. Also
writing to the NOR flash while executing from the same flash
in Bypass mode had some stability issues. Hence, since the
MCC firmware issue is resolved, this patch reverts to the
NVFLAGS mechanism to detect FWU. Also, with the introduction
of SDS (Shared Data Structure) by the SCP, the reset syndrome
needs to queried from the appropriate SDS field.

Change-Id: If9c08f1afaaa4fcf197f3186887068103855f554
Signed-off-by: Sathees Balya <sathees.balya@arm.com>
Signed-off-by: Soby Mathew <Soby.Mathew@arm.com>
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 <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 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 <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 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,8 +83,13 @@
 				${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:
 ERRATA_A53_826319		:=	1
 ERRATA_A53_835769		:=	1
@@ -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 <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 @@
 	for (;;)
 		wfi();
 }
+
+void __dead2 plat_error_handler(int err)
+{
+	plat_arm_error_handler(err);
+}