FVP: Add dummy configs for BL31, BL32 and BL33

This patch adds soc_fw_config, tos_fw_config and nt_fw_config to the FVP.
The config files are placeholders and do not have any useful bindings
defined. The tos_fw_config is packaged in FIP and loaded by BL2 only
if SPD=tspd. The load address of these configs are specified in tb_fw_config
via new bindings defined for these configs. Currently, in FVP, the
soc_fw_config and tos_fw_config is loaded in the page between BL2_BASE
and ARM_SHARED_RAM. This memory was typically used for BL32 when
ARM_TSP_RAM_LOCATION=tsram but since we cannot fit BL32 in that
space anymore, it should be safe to use this memory for these configs.
There is also a runtime check in arm_bl2_dyn_cfg_init() which ensures
that this overlap doesn't happen.

The previous arm_dyn_get_hwconfig_info() is modified to accept configs
other than hw_config and hence renamed to arm_dyn_get_config_load_info().
The patch also corrects the definition of ARM_TB_FW_CONFIG_LIMIT to be
BL2_BASE.

Change-Id: I03a137d9fa1f92c862c254be808b8330cfd17a5a
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 845f140..ad6b4f8 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -87,7 +87,7 @@
 #if TRUSTED_BOARD_BOOT
 # define PLAT_ARM_MAX_BL2_SIZE		0x1E000
 #else
-# define PLAT_ARM_MAX_BL2_SIZE		0xF000
+# define PLAT_ARM_MAX_BL2_SIZE		0x10000
 #endif
 
 /*
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 4473b53..18390d6 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -317,7 +317,7 @@
  * and limit. Leave enough space of BL2 meminfo.
  */
 #define ARM_TB_FW_CONFIG_BASE		ARM_BL_RAM_BASE + sizeof(meminfo_t)
-#define ARM_TB_FW_CONFIG_LIMIT		BL2_LIMIT
+#define ARM_TB_FW_CONFIG_LIMIT		BL2_BASE
 
 /*******************************************************************************
  * BL1 specific defines.
diff --git a/include/plat/arm/common/arm_dyn_cfg_helpers.h b/include/plat/arm/common/arm_dyn_cfg_helpers.h
index 826924d..382ec60 100644
--- a/include/plat/arm/common/arm_dyn_cfg_helpers.h
+++ b/include/plat/arm/common/arm_dyn_cfg_helpers.h
@@ -9,8 +9,8 @@
 #include <stdint.h>
 
 /* Function declaration */
-int arm_dyn_get_hwconfig_info(void *dtb, int node,
-		uint64_t *hw_config_addr, uint32_t *hw_config_size);
+int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
+		uint64_t *config_addr, uint32_t *config_size);
 int arm_dyn_tb_fw_cfg_init(void *dtb, int *node);
 int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth);
 
diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
new file mode 100644
index 0000000..7ab980b
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts
new file mode 100644
index 0000000..7ab980b
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index fb7e2c5..716b023 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -13,6 +13,18 @@
 		hw_config_addr = <0x0 0x82000000>;
 		hw_config_max_size = <0x01000000>;
 		/* Disable authentication for development */
-		disable_auth = <0x0>;
+		disable_auth = <0x1>;
+		/*
+		 * Load SoC and TOS firmware configs at the base of
+		 * non shared SRAM. The runtime checks ensure we don't
+		 * overlap BL2, BL31 or BL32. The NT firmware config
+		 * is loaded at base of DRAM.
+		 */
+		soc_fw_config_addr = <0x0 0x04001000>;
+		soc_fw_config_max_size = <0x200>;
+		tos_fw_config_addr = <0x0 0x04001200>;
+		tos_fw_config_max_size = <0x200>;
+		nt_fw_config_addr = <0x0 0x80000000>;
+		nt_fw_config_max_size = <0x200>;
 	};
 };
diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
new file mode 100644
index 0000000..7ab980b
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+
+};
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index c5e33d2..f807dc6 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -166,11 +166,30 @@
 # Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
 ifdef UNIX_MK
 FVP_HW_CONFIG_DTS	:=	fdts/${FVP_DT_PREFIX}.dts
-FDT_SOURCES		+=	plat/arm/board/fvp/fdts/${PLAT}_tb_fw_config.dts
+FDT_SOURCES		+=	$(addprefix plat/arm/board/fvp/fdts/,	\
+					${PLAT}_tb_fw_config.dts	\
+					${PLAT}_soc_fw_config.dts	\
+					${PLAT}_nt_fw_config.dts	\
+				)
+
 FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FVP_SOC_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb
+FVP_NT_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+ifeq (${SPD},tspd)
+FDT_SOURCES		+=	plat/arm/board/fvp/fdts/${PLAT}_tsp_fw_config.dts
+FVP_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_tsp_fw_config.dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
+endif
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
+# Add the SOC_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_SOC_FW_CONFIG},--soc-fw-config))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_NT_FW_CONFIG},--nt-fw-config))
 
 FDT_SOURCES		+=	${FVP_HW_CONFIG_DTS}
 $(eval FVP_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(FVP_HW_CONFIG_DTS)))
diff --git a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
index fef01c9..8e6d00d 100644
--- a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
+++ b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
@@ -91,6 +91,15 @@
 		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
 	    .next_handoff_image_id = INVALID_IMAGE_ID,
     },
+	/* Fill SOC_FW_CONFIG related information */
+    {
+	    .image_id = SOC_FW_CONFIG_ID,
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
 # ifdef BL32_BASE
 	/* Fill BL32 related information */
     {
@@ -144,6 +153,16 @@
 #endif
 	    .next_handoff_image_id = INVALID_IMAGE_ID,
     },
+
+	/* Fill TOS_FW_CONFIG related information */
+    {
+	    .image_id = TOS_FW_CONFIG_ID,
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
 # endif /* BL32_BASE */
 
 	/* Fill BL33 related information */
@@ -166,6 +185,15 @@
 # endif /* PRELOADED_BL33_BASE */
 
 	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+	/* Fill NT_FW_CONFIG related information */
+    {
+	    .image_id = NT_FW_CONFIG_ID,
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, entry_point_info_t, NON_SECURE | NON_EXECUTABLE),
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
     }
 #endif /* EL3_PAYLOAD_BASE */
 };
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 33dc08b..3f0a9b4 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -85,14 +85,25 @@
 
 /*
  * BL2 utility function to initialize dynamic configuration specified by
- * TB_FW_CONFIG. Return early if TB_FW_CONFIG is not found or HW_CONFIG is
- * not specified in TB_FW_CONFIG.
+ * TB_FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if
+ * specified in TB_FW_CONFIG.
  */
 void arm_bl2_dyn_cfg_init(void)
 {
-	int err = 0;
-	int tb_fw_node;
-	bl_mem_params_node_t *hw_cfg_mem_params = NULL;
+	int err = 0, tb_fw_node;
+	unsigned int i;
+	bl_mem_params_node_t *cfg_mem_params = NULL;
+	uint64_t image_base;
+	uint32_t image_size;
+	const unsigned int config_ids[] = {
+			HW_CONFIG_ID,
+			SOC_FW_CONFIG_ID,
+			NT_FW_CONFIG_ID,
+#ifdef SPD_tspd
+			/* Currently tos_fw_config is only present for TSP */
+			TOS_FW_CONFIG_ID
+#endif
+	};
 
 	if (tb_fw_cfg_dtb == NULL) {
 		VERBOSE("No TB_FW_CONFIG specified\n");
@@ -105,23 +116,57 @@
 		panic();
 	}
 
-	/* Get the hw_config load address and size from TB_FW_CONFIG */
-	hw_cfg_mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
-	if (hw_cfg_mem_params == NULL) {
-		VERBOSE("Couldn't find HW_CONFIG in bl_mem_params_node\n");
-		return;
-	}
+	/* Iterate through all the fw config IDs */
+	for (i = 0; i < ARRAY_SIZE(config_ids); i++) {
+		/* Get the config load address and size from TB_FW_CONFIG */
+		cfg_mem_params = get_bl_mem_params_node(config_ids[i]);
+		if (cfg_mem_params == NULL) {
+			VERBOSE("Couldn't find HW_CONFIG in bl_mem_params_node\n");
+			continue;
+		}
 
-	err = arm_dyn_get_hwconfig_info((void *)tb_fw_cfg_dtb, tb_fw_node,
-		(uint64_t *) &hw_cfg_mem_params->image_info.image_base,
-		&hw_cfg_mem_params->image_info.image_max_size);
-	if (err < 0) {
-		VERBOSE("Couldn't find HW_CONFIG load info in TB_FW_CONFIG\n");
-		return;
-	}
+		err = arm_dyn_get_config_load_info((void *)tb_fw_cfg_dtb, tb_fw_node,
+				config_ids[i], &image_base, &image_size);
+		if (err < 0) {
+			VERBOSE("Couldn't find config_id %d load info in TB_FW_CONFIG\n",
+					config_ids[i]);
+			continue;
+		}
+
+		/*
+		 * Do some runtime checks on the load addresses of soc_fw_config,
+		 * tos_fw_config, nt_fw_config. This is not a comprehensive check
+		 * of all invalid addresses but to prevent trivial porting errors.
+		 */
+		if (config_ids[i] != HW_CONFIG_ID) {
 
-	/* Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from HW_CONFIG node */
-	hw_cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+			if (check_uptr_overflow(image_base, image_size) != 0)
+				continue;
+
+			/* Ensure the configs don't overlap with BL2 */
+			if ((image_base > BL2_BASE) || ((image_base + image_size) > BL2_BASE))
+				continue;
+
+			/* Ensure the configs are loaded in a valid address */
+			if (image_base < ARM_BL_RAM_BASE)
+				continue;
+#ifdef BL32_BASE
+			/*
+			 * If BL32 is present, ensure that the configs don't
+			 * overlap with it.
+			 */
+			if (image_base >= BL32_BASE && image_base <= BL32_LIMIT)
+				continue;
+#endif
+		}
+
+
+		cfg_mem_params->image_info.image_base = (uintptr_t)image_base;
+		cfg_mem_params->image_info.image_max_size = image_size;
+
+		/* Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from HW_CONFIG node */
+		cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+	}
 
 #if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH)
 	uint32_t disable_auth = 0;
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index e37e7e7..5a7e20a 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -11,31 +11,57 @@
 #include <libfdt.h>
 #include <plat_arm.h>
 
+
+typedef struct config_load_info_prop {
+	unsigned int config_id;
+	const char *config_addr;
+	const char *config_max_size;
+} config_load_info_prop_t;
+
+static const config_load_info_prop_t prop_names[] = {
+	{HW_CONFIG_ID, "hw_config_addr", "hw_config_max_size"},
+	{SOC_FW_CONFIG_ID, "soc_fw_config_addr", "soc_fw_config_max_size"},
+	{TOS_FW_CONFIG_ID, "tos_fw_config_addr", "tos_fw_config_max_size"},
+	{NT_FW_CONFIG_ID, "nt_fw_config_addr", "nt_fw_config_max_size"}
+};
+
 /*******************************************************************************
- * Helper to read the `hw_config` property in config DTB. This function
- * expects the following properties to be present in the config DTB.
- *	name : hw_config_addr		size : 2 cells
- *	name : hw_config_max_size	size : 1 cell
+ * Helper to read the load information corresponding to the `config_id` in
+ * TB_FW_CONFIG. This function expects the following properties to be defined :
+ *	<config>_addr		size : 2 cells
+ *	<config>_max_size	size : 1 cell
  *
  * Arguments:
  *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
  *	int node		 - The node offset to appropriate node in the
  *					 DTB.
- *	uint64_t *hw_config_addr - Returns the `hw_config` load address if read
+ *	unsigned int config_id	 - The configuration id
+ *	uint64_t *config_addr	 - Returns the `config` load address if read
  *					 is successful.
- *	uint32_t *hw_config_size - Returns the `hw_config` size if read is
+ *	uint32_t *config_size	 - Returns the `config` size if read is
  *					 successful.
  *
  * Returns 0 on success and -1 on error.
  ******************************************************************************/
-int arm_dyn_get_hwconfig_info(void *dtb, int node,
-		uint64_t *hw_config_addr, uint32_t *hw_config_size)
+int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
+		uint64_t *config_addr, uint32_t *config_size)
 {
 	int err;
+	unsigned int i;
 
 	assert(dtb != NULL);
-	assert(hw_config_addr != NULL);
-	assert(hw_config_size != NULL);
+	assert(config_addr != NULL);
+	assert(config_size != NULL);
+
+	for (i = 0; i < ARRAY_SIZE(prop_names); i++) {
+		if (prop_names[i].config_id == config_id)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(prop_names)) {
+		WARN("Invalid config id %d\n", config_id);
+		return -1;
+	}
 
 	/* Check if the pointer to DT is correct */
 	assert(fdt_check_header(dtb) == 0);
@@ -43,22 +69,22 @@
 	/* Assert the node offset point to "arm,tb_fw" compatible property */
 	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
 
-	err = fdtw_read_cells(dtb, node, "hw_config_addr", 2,
-				(void *) hw_config_addr);
+	err = fdtw_read_cells(dtb, node, prop_names[i].config_addr, 2,
+				(void *) config_addr);
 	if (err < 0) {
-		WARN("Read cell failed for hw_config_addr\n");
+		WARN("Read cell failed for %s\n", prop_names[i].config_addr);
 		return -1;
 	}
 
-	err = fdtw_read_cells(dtb, node, "hw_config_max_size", 1,
-				(void *) hw_config_size);
+	err = fdtw_read_cells(dtb, node, prop_names[i].config_max_size, 1,
+				(void *) config_size);
 	if (err < 0) {
-		WARN("Read cell failed for hw_config_max_size\n");
+		WARN("Read cell failed for %s\n", prop_names[i].config_max_size);
 		return -1;
 	}
 
-	VERBOSE("Dyn cfg: Read hw_config address from TB_FW_CONFIG 0x%p %p\n",
-				hw_config_addr, hw_config_size);
+	VERBOSE("Dyn cfg: Read config_id %d load info from TB_FW_CONFIG 0x%llx 0x%x\n",
+				config_id, (unsigned long long)*config_addr, *config_size);
 
 	return 0;
 }
@@ -98,7 +124,7 @@
 	}
 
 	/* Check if the value is boolean */
-	if (*disable_auth != 0 && *disable_auth != 1) {
+	if ((*disable_auth != 0U) && (*disable_auth != 1U)) {
 		WARN("Invalid value for `disable_auth` cell %d\n", *disable_auth);
 		return -1;
 	}
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index 652f5e9..cd58e45 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -63,6 +63,18 @@
 	.uuid = UUID_HW_CONFIG,
 };
 
+static const io_uuid_spec_t soc_fw_config_uuid_spec = {
+	.uuid = UUID_SOC_FW_CONFIG,
+};
+
+static const io_uuid_spec_t tos_fw_config_uuid_spec = {
+	.uuid = UUID_TOS_FW_CONFIG,
+};
+
+static const io_uuid_spec_t nt_fw_config_uuid_spec = {
+	.uuid = UUID_NT_FW_CONFIG,
+};
+
 #if TRUSTED_BOARD_BOOT
 static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
 	.uuid = UUID_TRUSTED_BOOT_FW_CERT,
@@ -167,6 +179,21 @@
 		(uintptr_t)&hw_config_uuid_spec,
 		open_fip
 	},
+	[SOC_FW_CONFIG_ID] = {
+			&fip_dev_handle,
+			(uintptr_t)&soc_fw_config_uuid_spec,
+			open_fip
+	},
+	[TOS_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tos_fw_config_uuid_spec,
+		open_fip
+	},
+	[NT_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&nt_fw_config_uuid_spec,
+		open_fip
+	},
 #if TRUSTED_BOARD_BOOT
 	[TRUSTED_BOOT_FW_CERT_ID] = {
 		&fip_dev_handle,