feat(indirect message): send and receive messages
Added helpers to receive and send indirect messages, respectively:
- `receive_indirect_message`;
- `send_indirect_message`;
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: I396870f15172f841167627b14c18b1504e0efbee
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index ad2ba08..fb1f61e 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -150,4 +150,10 @@
ffa_id_t receiver_id,
uint32_t mem_func);
+bool receive_indirect_message(void *buffer, size_t buffer_size, void *recv,
+ ffa_id_t *sender, ffa_id_t receiver,
+ ffa_id_t own_id);
+struct ffa_value send_indirect_message(
+ ffa_id_t from, ffa_id_t to, void *send, const void *payload,
+ size_t payload_size, uint32_t send_flags);
#endif /* SPM_COMMON_H */
diff --git a/tftf/tests/aarch32_tests_to_skip.txt b/tftf/tests/aarch32_tests_to_skip.txt
index 210d465..6913cb1 100644
--- a/tftf/tests/aarch32_tests_to_skip.txt
+++ b/tftf/tests/aarch32_tests_to_skip.txt
@@ -18,3 +18,4 @@
FF-A Notifications
RMI and SPM tests
FF-A SMCCC compliance
+FF-A Indirect Messaging
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 45ab71a..ffd488d 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -10,6 +10,7 @@
#include <cactus_test_cmds.h>
#include <debug.h>
#include <ffa_endpoints.h>
+#include <assert.h>
#include <ffa_svc.h>
#include <lib/extensions/sve.h>
#include <spm_common.h>
@@ -841,3 +842,107 @@
return ffa_memory_access_init(receiver_id, data_access,
instruction_access, 0, NULL);
}
+
+/**
+ * Receives message from the mailbox, copies it into the 'buffer', gets the
+ * pending framework notifications and releases the RX buffer.
+ * Returns false if it fails to copy the message to `buffer`, or true
+ * otherwise.
+ */
+bool receive_indirect_message(void *buffer, size_t buffer_size, void *recv,
+ ffa_id_t *sender, ffa_id_t receiver, ffa_id_t own_id)
+{
+ const struct ffa_partition_msg *message;
+ struct ffa_partition_rxtx_header header;
+ ffa_id_t source_vm_id;
+ const uint32_t *payload;
+ struct ffa_value ret;
+ ffa_notification_bitmap_t fwk_notif;
+
+ if (buffer_size > FFA_MSG_PAYLOAD_MAX) {
+ return false;
+ }
+
+ ret = ffa_notification_get(receiver, 0,
+ FFA_NOTIFICATIONS_FLAG_BITMAP_SPM);
+ if (is_ffa_call_error(ret)) {
+ return false;
+ }
+
+ fwk_notif = ffa_notification_get_from_framework(ret);
+
+ if (fwk_notif == 0U) {
+ ERROR("Expected Rx buffer full notification.");
+ return false;
+ }
+
+ message = (const struct ffa_partition_msg *)recv;
+ memcpy(&header, message, sizeof(struct ffa_partition_rxtx_header));
+
+ source_vm_id = header.sender;
+
+ if (is_ffa_spm_buffer_full_notification(fwk_notif)) {
+ /*
+ * Expect the sender to always have been an SP.
+ */
+ assert(IS_SP_ID(source_vm_id));
+ }
+
+ if (header.size > buffer_size) {
+ ERROR("Error in rxtx header. Message size: %#x; "
+ "buffer size: %lu\n",
+ header.size, buffer_size);
+ return false;
+ }
+
+ payload = (const uint32_t *)message->payload;
+
+ /* Get message to free the RX buffer. */
+ memcpy(buffer, payload, header.size);
+
+ /* Check receiver ID against own ID. */
+ if (receiver != own_id) {
+ ret = ffa_rx_release_with_id(receiver);
+ } else {
+ ret = ffa_rx_release();
+ }
+
+ if (is_ffa_call_error(ret)) {
+ ERROR("Failed to release the rx buffer\n");
+ return false;
+ }
+
+ if (receiver != header.receiver) {
+ ERROR("Header receiver: %x different than expected receiver: %x\n",
+ header.receiver, receiver);
+ return false;
+ }
+
+
+ if (sender != NULL) {
+ *sender = source_vm_id;
+ }
+
+ return true;
+}
+
+/**
+ * Sends an indirect message: initializes the `ffa_rxtx_header`, copies the
+ * payload to the TX buffer.
+ * Uses the `send_flags` if any are provided in the call to FFA_MSG_SEND2.
+ */
+struct ffa_value send_indirect_message(
+ ffa_id_t from, ffa_id_t to, void *send, const void *payload,
+ size_t payload_size, uint32_t send_flags)
+{
+ struct ffa_partition_msg *message = (struct ffa_partition_msg *)send;
+
+ /* Initialize message header. */
+ ffa_rxtx_header_init(from, to, payload_size, &message->header);
+
+ /* Fill TX buffer with payload. */
+ memcpy(message->payload, payload, payload_size);
+
+ /* Send the message. */
+ return ffa_msg_send2(send_flags);
+}