stm32mp1: add OP-TEE support

Support booting OP-TEE as BL32 boot stage and secure runtime
service.

OP-TEE executes in internal RAM and uses a secure DDR area to store
the pager pagestore. Memory mapping and TZC are configured accordingly
prior OP-TEE boot. OP-TEE image is expected in OP-TEE v2 format where
a header file describes the effective boot images. This change
post processes header file content to get OP-TEE load addresses
and set OP-TEE boot arguments.

Change-Id: I02ef8b915e4be3e95b27029357d799d70e01cd44
Signed-off-by: Yann Gautier <yann.gautier@st.com>
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 2477954..b54486e 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -22,6 +22,7 @@
 #include <drivers/st/stm32mp1_pwr.h>
 #include <drivers/st/stm32mp1_ram.h>
 #include <lib/mmio.h>
+#include <lib/optee_utils.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
@@ -136,7 +137,13 @@
 		panic();
 	}
 
+#ifdef AARCH32_SP_OPTEE
+	INFO("BL2 runs OP-TEE setup\n");
+	/* Initialize tzc400 after DDR initialization */
+	stm32mp1_security_setup();
+#else
 	INFO("BL2 runs SP_MIN setup\n");
+#endif
 }
 
 void bl2_el3_plat_arch_setup(void)
@@ -154,11 +161,25 @@
 			BL_CODE_END - BL_CODE_BASE,
 			MT_CODE | MT_SECURE);
 
+#ifdef AARCH32_SP_OPTEE
+	/* OP-TEE image needs post load processing: keep RAM read/write */
+	mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() -
+			STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE,
+			STM32MP_DDR_BASE + dt_get_ddr_size() -
+			STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE,
+			STM32MP_DDR_S_SIZE,
+			MT_MEMORY | MT_RW | MT_SECURE);
+
+	mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
+			STM32MP_OPTEE_SIZE,
+			MT_MEMORY | MT_RW | MT_SECURE);
+#else
 	/* Prevent corruption of preloaded BL32 */
 	mmap_add_region(BL32_BASE, BL32_BASE,
 			BL32_LIMIT - BL32_BASE,
 			MT_MEMORY | MT_RO | MT_SECURE);
 
+#endif
 	/* Map non secure DDR for BL33 load and DDR training area restore */
 	mmap_add_region(STM32MP_DDR_BASE,
 			STM32MP_DDR_BASE,
@@ -261,3 +282,69 @@
 
 	stm32mp_io_setup();
 }
+
+#if defined(AARCH32_SP_OPTEE)
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	int err = 0;
+	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+	bl_mem_params_node_t *bl32_mem_params;
+	bl_mem_params_node_t *pager_mem_params;
+	bl_mem_params_node_t *paged_mem_params;
+
+	assert(bl_mem_params != NULL);
+
+	switch (image_id) {
+	case BL32_IMAGE_ID:
+		bl_mem_params->ep_info.pc =
+					bl_mem_params->image_info.image_base;
+
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params != NULL);
+		pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE;
+		pager_mem_params->image_info.image_max_size =
+			STM32MP_OPTEE_SIZE;
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params != NULL);
+		paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+			(dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
+			 STM32MP_DDR_SHMEM_SIZE);
+		paged_mem_params->image_info.image_max_size =
+			STM32MP_DDR_S_SIZE;
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+					 &pager_mem_params->image_info,
+					 &paged_mem_params->image_info);
+		if (err) {
+			ERROR("OPTEE header parse error.\n");
+			panic();
+		}
+
+		/* Set optee boot info from parsed header data */
+		bl_mem_params->ep_info.pc =
+				pager_mem_params->image_info.image_base;
+		bl_mem_params->ep_info.args.arg0 =
+				paged_mem_params->image_info.image_base;
+		bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
+		bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
+		break;
+
+	case BL33_IMAGE_ID:
+		bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
+		assert(bl32_mem_params != NULL);
+		bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
+		break;
+
+	default:
+		/* Do nothing in default case */
+		break;
+	}
+
+	return err;
+}
+#endif