Merge changes from topic "sb/smc-tests-tos"

* changes:
  Relax SMC tests when Trusted OS is present
  Make UUID buffer optional for is_trusted_os_present()
diff --git a/include/runtime_services/trusted_os.h b/include/runtime_services/trusted_os.h
index f480c6b..2947882 100644
--- a/include/runtime_services/trusted_os.h
+++ b/include/runtime_services/trusted_os.h
@@ -24,10 +24,8 @@
  * Detect whether a Trusted OS is present in the software stack.
  * This is implemented using the Trusted OS UID SMC call.
  *
- * If a Trusted OS is detected then this function returns 1
- * and populates 'tos_uuid' with the UUID of the detected Trusted OS.
- * Otherwise, this function returns 0 and the value pointed by 'tos_uuid'
- * should be ignored.
+ * Return 1 if a Trusted OS is detected, else 0. Additionally, the caller may
+ * get the UUID of the Trusted OS if he passes a non-null 'tos_uuid' pointer.
  */
 unsigned int is_trusted_os_present(uuid_t *tos_uuid);
 
diff --git a/lib/trusted_os/trusted_os.c b/lib/trusted_os/trusted_os.c
index b24c3d3..ac6a681 100644
--- a/lib/trusted_os/trusted_os.c
+++ b/lib/trusted_os/trusted_os.c
@@ -14,7 +14,6 @@
 {
 	smc_args tos_uid_args = { SMC_TOS_UID };
 	smc_ret_values ret;
-	uint32_t *tos_uuid32;
 
 	ret = tftf_smc(&tos_uid_args);
 
@@ -23,11 +22,13 @@
 	     (ret.ret3 == 0)))
 		return 0;
 
-	tos_uuid32 = (uint32_t *) tos_uuid;
-	tos_uuid32[0] = ret.ret0;
-	tos_uuid32[1] = ret.ret1;
-	tos_uuid32[2] = ret.ret2;
-	tos_uuid32[3] = ret.ret3;
+	if (tos_uuid != NULL) {
+		uint32_t *tos_uuid32 = (uint32_t *) tos_uuid;
+		tos_uuid32[0] = ret.ret0;
+		tos_uuid32[1] = ret.ret1;
+		tos_uuid32[2] = ret.ret2;
+		tos_uuid32[3] = ret.ret3;
+	}
 
 	return 1;
 }
diff --git a/tftf/tests/runtime_services/generic/generic_smc.c b/tftf/tests/runtime_services/generic/generic_smc.c
index 901b448..366509b 100644
--- a/tftf/tests/runtime_services/generic/generic_smc.c
+++ b/tftf/tests/runtime_services/generic/generic_smc.c
@@ -7,8 +7,10 @@
 #include <psci.h>
 #include <smccc.h>
 #include <std_svc.h>
+#include <stdio.h>
 #include <string.h>
 #include <tftf_lib.h>
+#include <trusted_os.h>
 #include <tsp.h>
 #include <utils_def.h>
 
@@ -63,6 +65,49 @@
 	}
 }
 
+/*
+ * Send an SMC with the specified arguments.
+ * Check that the values it returns match the expected ones. The do_check[]
+ * array indicates which ones should be checked and provides some flexibility
+ * to ignore some of them.
+ * If the values do not match, write an error message in the test report.
+ */
+static bool smc_check_match(const smc_args *args, const smc_ret_values *expect,
+			    const bool do_check[4])
+{
+	smc_ret_values ret = tftf_smc(args);
+
+	if ((do_check[0] && (ret.ret0 != expect->ret0)) ||
+	    (do_check[1] && (ret.ret1 != expect->ret1)) ||
+	    (do_check[2] && (ret.ret2 != expect->ret2)) ||
+	    (do_check[3] && (ret.ret3 != expect->ret3))) {
+		/*
+		 * Build an error message where unchecked SMC return values are
+		 * displayed as '*'.
+		 */
+		char expect_str[4][20];
+#define BUILD_STR(_buf, _do_check, _expect)			\
+		if (_do_check) {				\
+			snprintf(_buf, 20, "0x%lx", _expect);	\
+		} else {					\
+			strncpy(_buf, "*", 2);			\
+		}
+		BUILD_STR(expect_str[0], do_check[0], expect->ret0);
+		BUILD_STR(expect_str[1], do_check[1], expect->ret1);
+		BUILD_STR(expect_str[2], do_check[2], expect->ret2);
+		BUILD_STR(expect_str[3], do_check[3], expect->ret3);
+#undef BUILD_STR
+		tftf_testcase_printf(
+			"Got {0x%lx,0x%lx,0x%lx,0x%lx}, expected {%s,%s,%s,%s}.\n",
+			ret.ret0, ret.ret1, ret.ret2, ret.ret3,
+			expect_str[0], expect_str[1], expect_str[2], expect_str[3]);
+
+		return false;
+	} else {
+		return true;
+	}
+}
+
 /* Exercise SMC32 calling convention with fast SMC calls. */
 test_result_t smc32_fast(void)
 {
@@ -118,9 +163,20 @@
 	const smc_args args3 = {
 		make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_TOS_START, INVALID_FN),
 		0x44444444, 0x55555555, 0x66666666 };
-	const smc_ret_values ret3
-		= { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
-	FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+	if (is_trusted_os_present(NULL)) {
+		/*
+		 * The Trusted OS is free to return any error code in x0 but it
+		 * should at least preserve the values of x1-x3.
+		 */
+		const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666 };
+		const bool check[4] = { false, true, true, true };
+		FAIL_IF(!smc_check_match(&args3, &ret3, check));
+	} else {
+		const smc_ret_values ret3
+			= { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+		FAIL_IF(!smc_check_eq(&args3, &ret3));
+	}
 
 	return TEST_RESULT_SUCCESS;
 }
@@ -218,9 +274,20 @@
 	const smc_args args3 = {
 		make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_TOS_START, INVALID_FN),
 		0x44444444, 0x55555555, 0x66666666 };
-	const smc_ret_values ret3
-		= { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
-	FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+	if (is_trusted_os_present(NULL)) {
+		/*
+		 * The Trusted OS is free to return any error code in x0 but it
+		 * should at least preserve the values of x1-x3.
+		 */
+		const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666 };
+		const bool check[4] = { false, true, true, true };
+		FAIL_IF(!smc_check_match(&args3, &ret3, check));
+	} else {
+		const smc_ret_values ret3
+			= { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+		FAIL_IF(!smc_check_eq(&args3, &ret3));
+	}
 
 	return TEST_RESULT_SUCCESS;
 }