feat(cactus): ability to send indirect messages

Add cactus test command for it to send indirect message
via FFA_MSG_SEND2 to a designated target FF-A endpoint.

Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: If519c19dd0ff86252fdd1d749baa2308bf64b936
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index 3938c2f..0630753 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -654,4 +654,34 @@
 	return (uint64_t)ret.arg4;
 }
 
+/**
+ * Request SP to send indirect message to FF-A endpoint.
+ *
+ * Command ID is string: MSGREQ.
+ */
+#define CACTUS_REQ_MSG_SEND_CMD U(0x4d5347524551a)
+
+static inline struct ffa_value cactus_req_ind_msg_send_cmd(
+	ffa_id_t source, ffa_id_t dest, ffa_id_t receiver,
+	ffa_id_t sender, uint32_t flags)
+{
+	return cactus_send_cmd(source, dest, CACTUS_REQ_MSG_SEND_CMD,
+			       flags, receiver, sender, 0);
+}
+
+static inline ffa_id_t cactus_msg_send_receiver(struct ffa_value ret)
+{
+	return (ffa_id_t)ret.arg5;
+}
+
+static inline ffa_id_t cactus_msg_send_sender(struct ffa_value ret)
+{
+	return (ffa_id_t)ret.arg6;
+}
+
+static inline uint64_t cactus_msg_send_flags(struct ffa_value ret)
+{
+	return (uint64_t)ret.arg4;
+}
+
 #endif
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index 4e86e3d..0755749 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -51,6 +51,7 @@
 		cactus_message_loop.c			\
 		cactus_test_simd.c		\
 		cactus_test_direct_messaging.c		\
+		cactus_test_indirect_message.c	\
 		cactus_test_interrupts.c		\
 		cactus_test_memory_sharing.c		\
 		cactus_tests_smmuv3.c			\
diff --git a/spm/cactus/cactus_tests/cactus_test_indirect_message.c b/spm/cactus/cactus_tests/cactus_test_indirect_message.c
new file mode 100644
index 0000000..3b8b46c
--- /dev/null
+++ b/spm/cactus/cactus_tests/cactus_test_indirect_message.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "cactus_message_loop.h"
+#include <cactus_test_cmds.h>
+#include "debug.h"
+#include "ffa_helpers.h"
+#include "utils_def.h"
+#include <ffa_endpoints.h>
+#include <spm_common.h>
+
+CACTUS_CMD_HANDLER(req_msg_send, CACTUS_REQ_MSG_SEND_CMD)
+{
+	struct ffa_value ret;
+	const ffa_id_t vm_id = ffa_dir_msg_dest(*args);
+	const ffa_id_t source = ffa_dir_msg_source(*args);
+	const ffa_id_t receiver = cactus_msg_send_receiver(*args);
+	const ffa_id_t sender = cactus_msg_send_sender(*args);
+	const char message[] = "Testing FF-A message.";
+
+	VERBOSE("%x requested to send indirect message to %x as %x(own %x)\n",
+		ffa_dir_msg_source(*args), receiver, sender, vm_id);
+
+	ret = send_indirect_message(sender, receiver, mb->send, message,
+				    ARRAY_SIZE(message), 0);
+
+	if (is_ffa_call_error(ret)) {
+		ERROR("Failed to send indirect message.\n");
+		return cactus_error_resp(vm_id,
+					 source,
+					 CACTUS_ERROR_TEST);
+	}
+
+	return cactus_success_resp(vm_id, source, 0);
+}
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index 3effb39..4d95069 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -27,7 +27,7 @@
 	entrypoint-offset = <0x00002000>;
 	xlat-granule = <0>; /* 4KiB */
 	boot-order = <0>;
-	messaging-method = <3>; /* Direct messaging only */
+	messaging-method = <7>; /* Indirect Messaging and direct messaging. */
 	ns-interrupts-action = <1>; /* Managed exit is supported */
 	notification-support; /* Support receipt of notifications. */
 
diff --git a/spm/cactus/plat/arm/tc/fdts/cactus.dts b/spm/cactus/plat/arm/tc/fdts/cactus.dts
index 31b9e8e..a4c71fe 100644
--- a/spm/cactus/plat/arm/tc/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/tc/fdts/cactus.dts
@@ -25,7 +25,7 @@
 	entrypoint-offset = <0x00002000>;
 	xlat-granule = <0>; /* 4KiB */
 	boot-order = <0>;
-	messaging-method = <3>; /* Direct messaging only */
+	messaging-method = <7>; /* Indirect messaging and direct messaging. */
 	notification-support; /* Support receipt of notifications. */
 	managed-exit; /* Managed exit supported */
 	run-time-model = <1>; /* Run to completion */