feat(tc): get the parent component provided DPE context_handle

Each client who wants to communicate with the DPE service
must own a valid context handle issued by the DPE service.
A context handle can be used for a single time then it will
be invalidated by the DPE service. In case of calls from
the same component, the next valid context handle is
returned in the response to a DPE command. When a component
finishes their job then the next component in the boot flow
inherits its first context handle from its parent.
How the inheritance is done can be client or
platform-dependent. It can be shared through shared
memory or be part of a DTB object passed to the next
bootloader stage.

Signed-off-by: Tamas Ban <tamas.ban@arm.com>
Signed-off-by: David Vincze <david.vincze@arm.com>
Change-Id: Ic82f074f1c5b15953e78f9fa5404ed7f48674cbb
diff --git a/drivers/measured_boot/rss/dice_prot_env.c b/drivers/measured_boot/rss/dice_prot_env.c
index 67b51a9..3d55ace 100644
--- a/drivers/measured_boot/rss/dice_prot_env.c
+++ b/drivers/measured_boot/rss/dice_prot_env.c
@@ -67,7 +67,7 @@
 		metadata++;
 	}
 
-	/* TODO: Obtain ctx handle and assign it to initial_context_handle */
+	plat_dpe_get_context_handle(&initial_context_handle);
 }
 
 int dpe_measure_and_record(struct dpe_metadata *metadata,
diff --git a/include/drivers/measured_boot/rss/dice_prot_env.h b/include/drivers/measured_boot/rss/dice_prot_env.h
index 8d00d83..b7fcf36 100644
--- a/include/drivers/measured_boot/rss/dice_prot_env.h
+++ b/include/drivers/measured_boot/rss/dice_prot_env.h
@@ -43,5 +43,6 @@
  * How to share context handle is platform specific.
  */
 void plat_dpe_share_context_handle(int *ctx_handle);
+void plat_dpe_get_context_handle(int *ctx_handle);
 
 #endif /* DICE_PROT_ENV_H */
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index bb47b92..cc3d0c7 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -193,7 +193,10 @@
 				${DPE_SOURCES} \
 				plat/arm/board/tc/tc_common_dpe.c \
 				plat/arm/board/tc/tc_bl1_dpe.c \
-				lib/psa/dice_protection_environment.c
+				lib/psa/dice_protection_environment.c \
+				drivers/arm/css/sds/sds.c \
+				drivers/delay_timer/delay_timer.c \
+				drivers/delay_timer/generic_delay_timer.c
 
 	BL2_SOURCES	+=	${QCBOR_SOURCES} \
 				${DPE_SOURCES} \
diff --git a/plat/arm/board/tc/tc_bl1_dpe.c b/plat/arm/board/tc/tc_bl1_dpe.c
index 25fdf95..c206b55 100644
--- a/plat/arm/board/tc/tc_bl1_dpe.c
+++ b/plat/arm/board/tc/tc_bl1_dpe.c
@@ -7,7 +7,10 @@
 #include <stdint.h>
 
 #include <common/debug.h>
+#include <drivers/arm/css/sds.h>
 #include <drivers/arm/rss_comms.h>
+#include <drivers/delay_timer.h>
+#include <drivers/generic_delay_timer.h>
 #include <drivers/measured_boot/metadata.h>
 #include <drivers/measured_boot/rss/dice_prot_env.h>
 #include <plat/arm/common/plat_arm.h>
@@ -44,6 +47,10 @@
 		.id = DPE_INVALID_ID }
 };
 
+/* Effective timeout of 10000 ms */
+#define RSS_DPE_BOOT_10US_RETRIES		1000000
+#define TC2_SDS_DPE_CTX_HANDLE_STRUCT_ID	0x0000000A
+
 /* Context handle is meant to be used by BL2. Sharing it via TB_FW_CONFIG */
 static int new_ctx_handle;
 
@@ -52,6 +59,53 @@
 	new_ctx_handle = *ctx_handle;
 }
 
+void plat_dpe_get_context_handle(int *ctx_handle)
+{
+	int retry = RSS_DPE_BOOT_10US_RETRIES;
+	int ret;
+
+	/* Initialize System level generic or SP804 timer */
+	generic_delay_timer_init();
+
+	/* Check the initialization of the Shared Data Storage area between RSS
+	 * and AP. Since AP_BL1 is executed first then a bit later the RSS
+	 * runtime, which initialize this area, therefore AP needs to check it
+	 * in a loop until it gets written by RSS Secure Runtime.
+	 */
+	VERBOSE("Waiting for DPE service initialization in RSS Secure Runtime\n");
+	while (retry > 0) {
+		ret = sds_init(SDS_RSS_AP_REGION_ID);
+		if (ret != SDS_OK) {
+			udelay(10);
+			retry--;
+		} else {
+			break;
+		}
+	}
+
+	if (retry == 0) {
+		ERROR("DPE init timeout\n");
+		plat_panic_handler();
+	} else {
+		VERBOSE("DPE init succeeded in %dms.\n",
+			(RSS_DPE_BOOT_10US_RETRIES - retry) / 100);
+	}
+
+	/* TODO: call this in a loop to avoid reading unfinished data */
+	ret = sds_struct_read(SDS_RSS_AP_REGION_ID,
+			      TC2_SDS_DPE_CTX_HANDLE_STRUCT_ID,
+			      0,
+			      ctx_handle,
+			      sizeof(*ctx_handle),
+			      SDS_ACCESS_MODE_NON_CACHED);
+	if (ret != SDS_OK) {
+		ERROR("Unable to get DPE context handle from SDS area\n");
+		plat_panic_handler();
+	}
+
+	VERBOSE("Received DPE context handle: 0x%x\n", *ctx_handle);
+}
+
 void bl1_plat_mboot_init(void)
 {
 	/* Initialize the communication channel between AP and RSS */
diff --git a/plat/arm/board/tc/tc_bl2_dpe.c b/plat/arm/board/tc/tc_bl2_dpe.c
index 17a6c30..3742f26 100644
--- a/plat/arm/board/tc/tc_bl2_dpe.c
+++ b/plat/arm/board/tc/tc_bl2_dpe.c
@@ -173,6 +173,24 @@
 	new_ctx_handle = *ctx_handle;
 }
 
+void plat_dpe_get_context_handle(int *ctx_handle)
+{
+	int rc;
+
+	rc = arm_get_tb_fw_info(ctx_handle);
+	if (rc != 0) {
+		ERROR("Unable to get DPE context handle from TB_FW_CONFIG\n");
+		/*
+		 * It is a fatal error because on FVP platform, BL2 software
+		 * assumes that a valid DPE context_handle is passed through
+		 * the DTB object by BL1.
+		 */
+		plat_panic_handler();
+	}
+
+	VERBOSE("Received DPE context handle: 0x%x\n", *ctx_handle);
+}
+
 void bl2_plat_mboot_init(void)
 {
 	/* Initialize the communication channel between AP and RSS */