feat(indirect message): add endpoint RX/TX buffer description structure

Added endpoint RX/TX buffer description structure, used by the
Hypervisor to forward FFA_RXTX_MAP calls to SPMC.

Change-Id: Ib3997dca3015b911ed5748911fcd3cc6d470f13a
Signed-off-by: Federico Recanati <federico.recanati@arm.com>
diff --git a/vmlib/ffa.c b/vmlib/ffa.c
index 984bf02..5cf2fb4 100644
--- a/vmlib/ffa.c
+++ b/vmlib/ffa.c
@@ -17,9 +17,14 @@
 #include <linux/string.h>
 
 #else
+#include "hf/static_assert.h"
 #include "hf/std.h"
 #endif
 
+static_assert(sizeof(struct ffa_endpoint_rx_tx_descriptor) % 16 == 0,
+	      "struct ffa_endpoint_rx_tx_descriptor must be a multiple of 16 "
+	      "bytes long.");
+
 static void ffa_copy_memory_region_constituents(
 	struct ffa_memory_region_constituent *dest,
 	const struct ffa_memory_region_constituent *src)
@@ -309,3 +314,58 @@
 
 	return constituent_count - count_to_copy;
 }
+
+static void ffa_composite_memory_region_init(
+	struct ffa_composite_memory_region *composite, uint64_t address,
+	uint32_t page_count)
+{
+	composite->page_count = page_count;
+	composite->constituent_count = 1;
+	composite->reserved_0 = 0;
+
+	composite->constituents[0].page_count = page_count;
+	composite->constituents[0].address = address;
+	composite->constituents[0].reserved = 0;
+}
+
+/**
+ * Initialises the given `ffa_endpoint_rx_tx_descriptor` to be used for an
+ * `FFA_RXTX_MAP` forwarding.
+ * Each buffer is described by an `ffa_composite_memory_region` containing
+ * one `ffa_memory_region_constituent`.
+ */
+void ffa_endpoint_rx_tx_descriptor_init(
+	struct ffa_endpoint_rx_tx_descriptor *desc, ffa_vm_id_t endpoint_id,
+	uint64_t rx_address, uint64_t tx_address)
+{
+	desc->endpoint_id = endpoint_id;
+	desc->reserved = 0;
+	desc->pad = 0;
+
+	/*
+	 * RX's composite descriptor is allocated after the enpoint descriptor.
+	 * `sizeof(struct ffa_endpoint_rx_tx_descriptor)` is guaranteed to be
+	 * 16-byte aligned.
+	 */
+	desc->rx_offset = sizeof(struct ffa_endpoint_rx_tx_descriptor);
+
+	ffa_composite_memory_region_init(
+		(struct ffa_composite_memory_region *)((uintptr_t)desc +
+						       desc->rx_offset),
+		rx_address, HF_MAILBOX_SIZE / FFA_PAGE_SIZE);
+
+	/*
+	 * TX's composite descriptor is allocated after the RX descriptor.
+	 * `sizeof(struct ffa_composite_memory_region)`  and
+	 * `sizeof(struct ffa_memory_region_constituent)` are guaranteed to be
+	 * 16-byte aligned in ffa_memory.c.
+	 */
+	desc->tx_offset = desc->rx_offset +
+			  sizeof(struct ffa_composite_memory_region) +
+			  sizeof(struct ffa_memory_region_constituent);
+
+	ffa_composite_memory_region_init(
+		(struct ffa_composite_memory_region *)((uintptr_t)desc +
+						       desc->tx_offset),
+		tx_address, HF_MAILBOX_SIZE / FFA_PAGE_SIZE);
+}