Merge "refactor(ffa-notification): deprecate per-vCPU notification test coverage"
diff --git a/docs/getting_started/requirements.rst b/docs/getting_started/requirements.rst
index eba75a2..40edbc9 100644
--- a/docs/getting_started/requirements.rst
+++ b/docs/getting_started/requirements.rst
@@ -25,7 +25,7 @@
 ======================== =====================
         Name             Version
 ======================== =====================
-Mbed TLS                 3.6.3
+Mbed TLS                 3.6.4
 Transfer List Library    0.0.1
 Event Log Library        0.0.1
 ======================== =====================
diff --git a/ext/mbedtls b/ext/mbedtls
index 22098d4..c765c83 160000
--- a/ext/mbedtls
+++ b/ext/mbedtls
@@ -1 +1 @@
-Subproject commit 22098d41c6620ce07cf8a0134d37302355e1e5ef
+Subproject commit c765c831e5c2a0971410692f92f7a81d6ec65ec2
diff --git a/include/configs/tftf_mbedtls_config.h b/include/configs/tftf_mbedtls_config.h
index 9ad0b71..66ec744 100644
--- a/include/configs/tftf_mbedtls_config.h
+++ b/include/configs/tftf_mbedtls_config.h
@@ -21,8 +21,8 @@
 /* For snprintf function declaration */
 #include <stdio.h>
 
-/* This file is compatible with release 3.6.3 */
-#define MBEDTLS_CONFIG_VERSION         0x03060300
+/* This file is compatible with release 3.6.4 */
+#define MBEDTLS_CONFIG_VERSION         0x03060400
 
 /* Configuration file to build mbed TLS with the required features for TFTF */
 #define MBEDTLS_PLATFORM_MEMORY
diff --git a/include/runtime_services/psci.h b/include/runtime_services/psci.h
index 0e56bdc..e76156b 100644
--- a/include/runtime_services/psci.h
+++ b/include/runtime_services/psci.h
@@ -110,6 +110,13 @@
 #endif /* __ASSEMBLY__ */
 
 /*******************************************************************************
+ * PSCI target CPU defines
+ ******************************************************************************/
+
+#define PSCI_TARGET_CPU_MASK	ULL(0x000000FF00FFFFFF)
+#define psci_target_cpu_from_mpid(mpidr) ((mpidr) & PSCI_TARGET_CPU_MASK)
+
+/*******************************************************************************
  * PSCI Migrate specific defines
  ******************************************************************************/
 #define PSCI_TOS_UP_MIG_CAP	0
diff --git a/lib/psci/psci.c b/lib/psci/psci.c
index 42e53b9..720d319 100644
--- a/lib/psci/psci.c
+++ b/lib/psci/psci.c
@@ -60,7 +60,7 @@
 {
 	smc_args args = {
 		SMC_PSCI_CPU_ON,
-		target_cpu,
+		psci_target_cpu_from_mpid(target_cpu),
 		entry_point_address,
 		context_id
 	};
@@ -97,7 +97,7 @@
 {
 	smc_args args = {
 		SMC_PSCI_STAT_RESIDENCY,
-		target_cpu,
+		psci_target_cpu_from_mpid(target_cpu),
 		power_state,
 	};
 	smc_ret_values ret_vals;
@@ -111,7 +111,7 @@
 {
 	smc_args args = {
 		SMC_PSCI_STAT_COUNT,
-		target_cpu,
+		psci_target_cpu_from_mpid(target_cpu),
 		power_state,
 	};
 	smc_ret_values ret_vals;
@@ -127,7 +127,7 @@
 
 	smc_args args = {
 			   SMC_PSCI_AFFINITY_INFO,
-			   target_affinity,
+			   psci_target_cpu_from_mpid(target_affinity),
 			   lowest_affinity_level
 			  };
 
@@ -139,7 +139,7 @@
 {
 	smc_args args = {
 		SMC_PSCI_CPU_HW_STATE,
-		target_cpu,
+		psci_target_cpu_from_mpid(target_cpu),
 		power_level
 	};
 	smc_ret_values ret;
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index 951e44b..25e47ae 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -94,6 +94,8 @@
 			FFA_VERSION_1_1},
 		{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_SUCCESS_SMC32,
 			FFA_VERSION_1_0},
+		{"FFA_ABORT_32", FFA_ABORT_32, FFA_SUCCESS_SMC32},
+		{"FFA_ABORT_64", FFA_ABORT_64, FFA_SUCCESS_SMC32},
 	};
 
 	INFO("Test FFA_FEATURES.\n");
diff --git a/tftf/tests/runtime_services/el3/query_ven_el3_svc.c b/tftf/tests/runtime_services/el3/query_ven_el3_svc.c
index 0b3b6e3..50d918a 100644
--- a/tftf/tests/runtime_services/el3/query_ven_el3_svc.c
+++ b/tftf/tests/runtime_services/el3/query_ven_el3_svc.c
@@ -47,6 +47,10 @@
 	ven_el3_svc_args.fid = VEN_EL3_SVC_UID;
 	ret = tftf_smc(&ven_el3_svc_args);
 
+	/* These functions are optional, skip test when not supported. */
+	if (ret.ret0 == SMC_UNKNOWN)
+		return TEST_RESULT_SKIPPED;
+
 	make_uuid_from_4words(&ven_el3_svc_uuid,
 			ret.ret0, ret.ret1, ret.ret2, ret.ret3);
 	if (!uuid_equal(&ven_el3_svc_uuid, &armtf_ven_el3_svc_uuid)) {
diff --git a/tftf/tests/runtime_services/generic/generic_smc.c b/tftf/tests/runtime_services/generic/generic_smc.c
index 6d057a6..1d15dcf 100644
--- a/tftf/tests/runtime_services/generic/generic_smc.c
+++ b/tftf/tests/runtime_services/generic/generic_smc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,10 +17,6 @@
 /* An invalid SMC function number. */
 #define INVALID_FN 0x666
 
-/* PSCI version returned by TF-A. */
-static const uint32_t psci_version = PSCI_VERSION(PSCI_MAJOR_VER,
-						  PSCI_MINOR_VER);
-
 /* UUID of the standard service in TF-A. */
 static const smc_ret_values std_svc_uuid = {
 	0x108d905b, 0x47e8f863, 0xfbc02dae, 0xe2f64156
@@ -46,6 +42,26 @@
 	} while (0)
 
 /*
+ * Check that the values it returns match the expected ones. If not, write an
+ * error message in the test report.
+ */
+static bool smc_check_eq_common(const smc_ret_values *ret,
+				const smc_ret_values *expect)
+{
+	if (memcmp(ret, expect, sizeof(smc_ret_values)) == 0)
+		return true;
+
+	tftf_testcase_printf(
+		"Got {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}, \
+		expected {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}.\n",
+		ret->ret0, ret->ret1, ret->ret2, ret->ret3,
+		ret->ret4, ret->ret5, ret->ret6, ret->ret7,
+		expect->ret0, expect->ret1, expect->ret2, expect->ret3,
+		expect->ret4, expect->ret5, expect->ret6, expect->ret7);
+	return false;
+}
+
+/*
  * Send an SMC with the specified arguments.
  * Check that the values it returns match the expected ones. If not, write an
  * error message in the test report.
@@ -54,18 +70,27 @@
 {
 	smc_ret_values ret = tftf_smc(args);
 
-	if (memcmp(&ret, expect, sizeof(smc_ret_values)) == 0) {
-		return true;
-	} else {
-		tftf_testcase_printf(
-			"Got {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}, \
-			expected {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}.\n",
-			ret.ret0, ret.ret1, ret.ret2, ret.ret3,
-			ret.ret4, ret.ret5, ret.ret6, ret.ret7,
-			expect->ret0, expect->ret1, expect->ret2, expect->ret3,
-			expect->ret4, expect->ret5, expect->ret6, expect->ret7);
-		return false;
-	}
+	return smc_check_eq_common(&ret, expect);
+}
+
+/*
+ * Send an optional SMC with the specified arguments. Treat it as skipped if the
+ * firmware does not support the call and skip further checks.
+ * Otherwise, check that the values it returns match the expected ones. If not,
+ * return a test fail result.
+ */
+static test_result_t smc_check_eq_optional(const smc_args *args, const smc_ret_values *expect)
+{
+	smc_ret_values ret = tftf_smc(args);
+
+	if (ret.ret0 == SMC_UNKNOWN)
+		return TEST_RESULT_SKIPPED;
+
+	if (smc_check_eq_common(&ret, expect))
+		return TEST_RESULT_SUCCESS;
+	else
+		return TEST_RESULT_FAIL;
+
 }
 
 /*
@@ -153,9 +178,14 @@
 /* Exercise SMC32 calling convention with fast SMC calls. */
 test_result_t smc32_fast(void)
 {
+	test_result_t result;
+
 	/* Valid Fast SMC32 using all 4 return values. */
 	const smc_args args1 = { .fid = SMC_STD_SVC_UID };
-	FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+	result = smc_check_eq_optional(&args1, &std_svc_uuid);
+	if (result != TEST_RESULT_SUCCESS) {
+		return result;
+	}
 
 	/* Invalid Fast SMC32. */
 	const smc_args args2 = {
@@ -171,10 +201,15 @@
 	const smc_args args3
 		= { SMC_PSCI_VERSION, 0x44444444, 0x55555555, 0x66666666,
 		0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
-	const smc_ret_values ret3
-		= { psci_version, 0x44444444, 0x55555555, 0x66666666,
+	smc_ret_values ret3
+		= { 0x00000000, 0x44444444, 0x55555555, 0x66666666,
 		0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
-	FAIL_IF(!smc_check_eq(&args3, &ret3));
+
+	const bool check[8] = { false, true, true, true, true, true, true, true };
+	const bool allow_zeros[8] = { false, true, true, true,
+						true, true, true, true };
+
+	FAIL_IF(!smc_check_match(&args3, &ret3, check, allow_zeros));
 
 	return TEST_RESULT_SUCCESS;
 }
@@ -182,9 +217,14 @@
 /* Exercise SMC64 calling convention with yielding SMC calls. */
 test_result_t smc64_yielding(void)
 {
+	test_result_t result;
+
 	/* Valid Fast SMC32 using all 4 return values. */
 	const smc_args args1 = { .fid = SMC_STD_SVC_UID };
-	FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+	result = smc_check_eq_optional(&args1, &std_svc_uuid);
+	if (result != TEST_RESULT_SUCCESS) {
+		return result;
+	}
 
 	/* Invalid function number, SMC64 Yielding. */
 	const smc_args args2 = {
@@ -239,9 +279,14 @@
 #ifndef __aarch64__
 static test_result_t smc64_fast_caller32(void)
 {
+	test_result_t result;
+
 	/* Valid Fast SMC32 using all 4 return values. */
 	smc_args args1 = { .fid = SMC_STD_SVC_UID };
-	FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+	result = smc_check_eq_optional(&args1, &std_svc_uuid);
+	if (result != TEST_RESULT_SUCCESS) {
+		return result;
+	}
 
 	/* Invalid SMC function number, Fast SMC64. */
 	const smc_args args2 = {
@@ -270,9 +315,14 @@
 #else
 static test_result_t smc64_fast_caller64(void)
 {
+	test_result_t result;
+
 	/* Valid Fast SMC32 using all 4 return values. */
 	smc_args args1 = { .fid = SMC_STD_SVC_UID };
-	FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+	result = smc_check_eq_optional(&args1, &std_svc_uuid);
+	if (result != TEST_RESULT_SUCCESS) {
+		return result;
+	}
 
 	/* Invalid function number, Fast SMC64. */
 	const smc_args args2 = {
@@ -310,9 +360,14 @@
 /* Exercise SMC32 calling convention with yielding SMC calls. */
 test_result_t smc32_yielding(void)
 {
+	test_result_t result;
+
 	/* Valid Fast SMC32 using all 4 return values. */
 	const smc_args args1 = { .fid = SMC_STD_SVC_UID };
-	FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
+	result = smc_check_eq_optional(&args1, &std_svc_uuid);
+	if (result != TEST_RESULT_SUCCESS) {
+		return result;
+	}
 
 	/* Invalid function number, SMC32 Yielding. */
 	const smc_args args2 = {
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 92a6644..baf556b 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -200,8 +200,6 @@
 		FFA_SUCCESS_SMC32},
 	{"FFA_NOTIFICATION_INFO_GET_64", FFA_NOTIFICATION_INFO_GET_SMC64,
 		FFA_SUCCESS_SMC32},
-	{"FFA_ABORT_32", FFA_ABORT_32, FFA_ERROR},
-	{"FFA_ABORT_64", FFA_ABORT_64, FFA_ERROR},
 	{"Check non-existent command", 0xFFFF, FFA_ERROR},
 };
 
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
index 1586fe6..2640fb6 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
@@ -97,6 +97,8 @@
 		{"FFA_FEATURE_NPI", FFA_FEATURE_NPI, FFA_ERROR, 0,
 			FFA_VERSION_1_1},
 		{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_ERROR},
+		{"FFA_ABORT_32", FFA_ABORT_32, FFA_ERROR},
+		{"FFA_ABORT_64", FFA_ABORT_64, FFA_ERROR},
 	};
 	size_t test_target_size = get_ffa_feature_test_target(&func_ids_target);
 
diff --git a/tftf/tests/runtime_services/sip_service/test_debugfs.c b/tftf/tests/runtime_services/sip_service/test_debugfs.c
index 39a1bf9..dcc57b2 100644
--- a/tftf/tests/runtime_services/sip_service/test_debugfs.c
+++ b/tftf/tests/runtime_services/sip_service/test_debugfs.c
@@ -360,3 +360,51 @@
 
 	return TEST_RESULT_SUCCESS;
 }
+
+/*
+ * @Test_Aim@ Verify that the I/O layer correctly handles out-of-bounds access.
+ *
+ * This test ensures robustness of seek/read APIs against invalid
+ * offsets and prevents potential memory or file corruption due to invalid
+ * access.
+ */
+test_result_t test_oob_access(void)
+{
+	int ret, fd;
+
+	/* Get debugfs interface version (if implemented)*/
+	ret = version();
+	if (ret != DEBUGFS_VERSION) {
+		/* Likely debugfs feature is not implemented */
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* Open BL2. */
+	fd = open("/fip/bl2.bin", O_READ);
+	if (fd < 0) {
+		tftf_testcase_printf("open failed fd=%d\n", fd);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Rewind to negative offset. */
+	ret = seek(fd, -1000, KSEEK_SET);
+
+	/* Reading with out-of-bounds cursor position should fail */
+	ret = read(fd, read_buffer, 128);
+	if (ret != 0) {
+		tftf_testcase_printf("Out-of-bounds read(%d)\n", __LINE__);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Reset cursor position to valid range. */
+	ret = seek(fd, 0, KSEEK_SET);
+
+	/* Read 128 bytes from start */
+	ret = read(fd, read_buffer, 128);
+	if (ret != 128) {
+		tftf_testcase_printf("read failed(%d) ret=%d\n", __LINE__, ret);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
\ No newline at end of file
diff --git a/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c b/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c
index 43685e4..259ed1d 100644
--- a/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c
+++ b/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c
@@ -75,10 +75,11 @@
 	args.fid = PMF_SMC_GET_VERSION;
 	ret = tftf_smc(&args);
 
+	if (ret.ret0 == SMC_UNKNOWN)
+		return TEST_RESULT_SKIPPED;
+
 	if (ret.ret1 != PMF_SMC_VERSION)
-	{
 		return TEST_RESULT_FAIL;
-	}
 
 	return TEST_RESULT_SUCCESS;
 }
diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c
index 50462d7..a3141a5 100644
--- a/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c
+++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c
@@ -89,7 +89,7 @@
 	 * Pass a valid MPID so that the MIGRATE call doesn't fail because of
 	 * invalid parameters
 	 */
-	args.arg1 = read_mpidr_el1() & MPID_MASK;
+	args.arg1 = psci_target_cpu_from_mpid(read_mpidr_el1());
 	ret = tftf_smc(&args);
 	migrate_ret = (int32_t) ret.ret0;
 
diff --git a/tftf/tests/runtime_services/standard_service/query_std_svc.c b/tftf/tests/runtime_services/standard_service/query_std_svc.c
index c8ce6e9..6debe63 100644
--- a/tftf/tests/runtime_services/standard_service/query_std_svc.c
+++ b/tftf/tests/runtime_services/standard_service/query_std_svc.c
@@ -47,6 +47,10 @@
 	std_svc_args.fid = SMC_STD_SVC_UID;
 	ret = tftf_smc(&std_svc_args);
 
+	/* These functions are optional, skip test when not supported. */
+	if (ret.ret0 == SMC_UNKNOWN)
+		return TEST_RESULT_SKIPPED;
+
 	make_uuid_from_4words(&std_svc_uuid,
 			ret.ret0, ret.ret1, ret.ret2, ret.ret3);
 	if (!uuid_equal(&std_svc_uuid, &armtf_std_svc_uuid)) {
diff --git a/tftf/tests/tests-debugfs.xml b/tftf/tests/tests-debugfs.xml
index 4da3152..61342e8 100644
--- a/tftf/tests/tests-debugfs.xml
+++ b/tftf/tests/tests-debugfs.xml
@@ -12,6 +12,7 @@
   -->
   <testsuite name="DebugFS" description="Test ARM SiP DebugFS service">
     <testcase name="Expose filesystem" function="test_debugfs" />
+    <testcase name="Out-of-bounds accesses" function="test_oob_access" />
   </testsuite>
 
 </testsuites>