tftf: spci: probe if SPMC is OP-TEE at S-EL1

For pre-Armv8.4 platform, the supported model is that SPMC runs at
S-EL1. The candidate is OP-TEE with SPCI protocol adaptation. This patch
performs a version check through direct messaging and determines if
OP-TEE runs as SPMC by checking version responses. If this does not
match, then it assumes SPMC runs at S-EL2 with two Cactus instances
running at S-EL1.

Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: I34194b6e8b3d447a25f2153bbac1be2631cd7a5e
diff --git a/tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c
index 7c0e973..e085226 100644
--- a/tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c
@@ -22,6 +22,11 @@
 #define DIRECT_MSG_TEST_PATTERN2	(0xbbbb0000)
 #define DIRECT_MSG_TEST_PATTERN3	(0xcccc0000)
 
+#define OPTEE_SPCI_GET_API_VERSION	(0)
+#define OPTEE_SPCI_GET_OS_VERSION	(1)
+#define OPTEE_SPCI_GET_OS_VERSION_MAJOR	(3)
+#define OPTEE_SPCI_GET_OS_VERSION_MINOR	(8)
+
 static test_result_t send_receive_direct_msg(unsigned int sp_id,
 					     unsigned int test_pattern)
 {
@@ -52,6 +57,49 @@
 	return TEST_RESULT_SUCCESS;
 }
 
+/*
+ * check_spmc_execution_level
+ *
+ * Attempt sending impdef protocol messages to OP-TEE through direct messaging.
+ * Criteria for detecting OP-TEE presence is that responses match defined
+ * version values. In the case of SPMC running at S-EL2 (and Cactus instances
+ * running at S-EL1) the response will not match the pre-defined version IDs.
+ *
+ * Returns true if SPMC is probed as being OP-TEE at S-EL1.
+ *
+ */
+static bool check_spmc_execution_level(void)
+{
+	unsigned int is_optee_spmc_criteria = 0;
+	smc_ret_values ret_values;
+
+	/*
+	 * Send a first OP-TEE-defined protocol message through
+	 * SPCI direct message.
+	 *
+	 */
+	ret_values = spci_msg_send_direct_req(HYP_ID, SP_ID(1),
+					      OPTEE_SPCI_GET_API_VERSION);
+	if ((ret_values.ret3 == SPCI_VERSION_MAJOR) &&
+	    (ret_values.ret4 == SPCI_VERSION_MINOR)) {
+		is_optee_spmc_criteria++;
+	}
+
+	/*
+	 * Send a second OP-TEE-defined protocol message through
+	 * SPCI direct message.
+	 *
+	 */
+	ret_values = spci_msg_send_direct_req(HYP_ID, SP_ID(1),
+					      OPTEE_SPCI_GET_OS_VERSION);
+	if ((ret_values.ret3 == OPTEE_SPCI_GET_OS_VERSION_MAJOR) &&
+	    (ret_values.ret4 == OPTEE_SPCI_GET_OS_VERSION_MINOR)) {
+		is_optee_spmc_criteria++;
+	}
+
+	return (is_optee_spmc_criteria == 2);
+}
+
 test_result_t test_spci_direct_messaging(void)
 {
 	smc_ret_values ret_values;
@@ -62,6 +110,18 @@
 	 **********************************************************************/
 	SKIP_TEST_IF_SPCI_VERSION_LESS_THAN(0, 9);
 
+	/* Check if SPMC is OP-TEE at S-EL1 */
+	if (check_spmc_execution_level()) {
+		/* Direct messaging is successfully verified for OP-TEE */
+		return TEST_RESULT_SUCCESS;
+	}
+
+	/*
+	 * From this point assume SPMC runs at S-EL2 and two Cactus instances
+	 * are loaded at S-EL1.
+	 *
+	 */
+
 	/**********************************************************************
 	 * Send a message to SP1 through direct messaging
 	 **********************************************************************/