feat(arm): support FW handoff b/w BL2 & BL31

Add support for the firmware handoff framework between BL2 and BL31.
Create a transfer list in trusted SRAM, leveraging the larger SRAM sizes
in recent models. Load the HW_CONFIG as a TE along with entry point
parameters for BL31 execution.

Change-Id: I7c4c6e8353ca978a13520fb3e15fb2803f0f1d0e
Signed-off-by: Harrison Mutai <harrison.mutai@arm.com>
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 33043b7..206f4a5 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -13,13 +13,18 @@
 #include <drivers/console.h>
 #include <lib/debugfs.h>
 #include <lib/extensions/ras.h>
+#include <lib/fconf/fconf.h>
 #include <lib/gpt_rme/gpt_rme.h>
 #include <lib/mmio.h>
+#if TRANSFER_LIST
+#include <lib/transfer_list.h>
+#endif
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
+static struct transfer_list_header *secure_tl __unused;
 /*
  * Placeholder variables for copying the arguments that have been passed to
  * BL31 from BL2.
@@ -35,8 +40,12 @@
  * Check that BL31_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
  * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
  */
+#if TRANSFER_LIST
+CASSERT(BL31_BASE >= PLAT_ARM_EL3_FW_HANDOFF_LIMIT, assert_bl31_base_overflows);
+#else
 CASSERT(BL31_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
-#endif
+#endif /* TRANSFER_LIST */
+#endif /* RESET_TO_BL31 */
 
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak bl31_early_platform_setup2
@@ -115,6 +124,44 @@
  * while creating page tables. BL2 has flushed this information to memory, so
  * we are guaranteed to pick up good data.
  ******************************************************************************/
+#if TRANSFER_LIST
+void __init arm_bl31_early_platform_setup(u_register_t arg0, u_register_t arg1,
+					  u_register_t arg2, u_register_t arg3)
+{
+	struct transfer_list_entry *te = NULL;
+	struct entry_point_info *ep;
+
+	secure_tl = (struct transfer_list_header *)arg3;
+
+	/*
+	 * Populate the global entry point structures used to execute subsequent
+	 * images.
+	 */
+	while ((te = transfer_list_next(secure_tl, te)) != NULL) {
+		ep = transfer_list_entry_data(te);
+
+		if (te->tag_id == TL_TAG_EXEC_EP_INFO64) {
+			switch (GET_SECURITY_STATE(ep->h.attr)) {
+			case NON_SECURE:
+				bl33_image_ep_info = *ep;
+				break;
+#if ENABLE_RME
+			case REALM:
+				rmm_image_ep_info = *ep;
+				break;
+#endif
+			case SECURE:
+				bl32_image_ep_info = *ep;
+				break;
+			default:
+				ERROR("Unrecognized Image Security State %lu\n",
+				      GET_SECURITY_STATE(ep->h.attr));
+				panic();
+			}
+		}
+	}
+}
+#else
 void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config,
 				uintptr_t hw_config, void *plat_params_from_bl2)
 {
@@ -258,11 +305,16 @@
 	bl33_image_ep_info.args.arg3 = 0U;
 # endif
 }
+#endif
 
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 		u_register_t arg2, u_register_t arg3)
 {
+#if TRANSFER_LIST
+	arm_bl31_early_platform_setup(arg0, arg1, arg2, arg3);
+#else
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+#endif
 
 	/*
 	 * Initialize Interconnect for this cluster during cold boot.
@@ -448,5 +500,15 @@
 
 void __init bl31_plat_arch_setup(void)
 {
+	struct transfer_list_entry *te __unused;
+
 	arm_bl31_plat_arch_setup();
+
+#if TRANSFER_LIST
+	te = transfer_list_find(secure_tl, TL_TAG_FDT);
+	assert(te != NULL);
+
+	/* Populate HW_CONFIG device tree with the mapped address */
+	fconf_populate("HW_CONFIG", (uintptr_t)transfer_list_entry_data(te));
+#endif
 }