lib: arm_ffa: Add support for sending FFA_MSG_SEND_DIRECT_REQ2 requests

Bug: 391968135
Change-Id: Ibd6638f1c3b52f9ab68539892672487f8ed0b200
diff --git a/lib/arm_ffa/arm_ffa.c b/lib/arm_ffa/arm_ffa.c
index 6fbe3c7..e2c68c4 100644
--- a/lib/arm_ffa/arm_ffa.c
+++ b/lib/arm_ffa/arm_ffa.c
@@ -49,6 +49,7 @@
 static bool supports_ns_bit = false;
 static bool supports_rx_release = false;
 static bool console_log_is_unsupported;
+static bool send_direct_req2_is_unsupported;
 
 static mutex_t ffa_rxtx_buffer_lock = MUTEX_INITIAL_VALUE(ffa_rxtx_buffer_lock);
 
@@ -467,6 +468,69 @@
     return smc8(fid, sender_receiver_id, flags, a0, a1, a2, a3, a4);
 }
 
+status_t arm_ffa_msg_send_direct_req2(uuid_t uuid,
+                                      uint16_t receiver_id,
+                                      uint64_t args[static 14],
+                                      struct smc_ret18* resp) {
+    struct smc_ret18 smc_ret;
+    uint64_t uuid_lo_hi[2];
+    uint32_t fid = SMC_FC64_FFA_MSG_SEND_DIRECT_REQ2;
+    uint32_t sender_receiver_id = ((uint32_t)ffa_local_id << 16) | receiver_id;
+
+    if (send_direct_req2_is_unsupported) {
+        return FFA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (!args || !resp) {
+        return ERR_INVALID_ARGS;
+    }
+
+    uuid_to_le64_pair(uuid, uuid_lo_hi);
+
+    smc_ret = smc18(fid, sender_receiver_id, uuid_lo_hi[0], uuid_lo_hi[1],
+                    args[0], args[1], args[2], args[3], args[4], args[5],
+                    args[6], args[7], args[8], args[9], args[10], args[11],
+                    args[12], args[13]);
+
+    switch ((uint32_t)smc_ret.r0) {
+    case SMC_FC64_FFA_MSG_SEND_DIRECT_RESP2:
+        *resp = smc_ret;
+        return NO_ERROR;
+
+    case SMC_FC_FFA_ERROR:
+        switch ((int32_t)smc_ret.r2) {
+        case FFA_ERROR_NOT_SUPPORTED:
+            send_direct_req2_is_unsupported = true;
+            return ERR_NOT_SUPPORTED;
+        case FFA_ERROR_INVALID_PARAMETERS:
+            dprintf(CRITICAL, "Invalid parameters for direct request2\n");
+            return ERR_INVALID_ARGS;
+        default:
+            return ERR_NOT_VALID;
+        }
+
+    case SMC_UNKNOWN:
+        send_direct_req2_is_unsupported = true;
+        return ERR_NOT_SUPPORTED;
+
+    case SMC_FC_FFA_INTERRUPT:
+        /*
+         * SMC_FC_FFA_INTERRUPT or SMC_FC_FFA_YIELD can be returned per the FF-A
+         * spec but it shouldn't happen when Trusty is the receiver of requests.
+         */
+        panic("Received SMC_FC_FFA_INTERRUPT in response to direct request2");
+
+    case SMC_FC_FFA_YIELD:
+        /* See previous case */
+        panic("Received SMC_FC_FFA_YIELD in response to direct request2");
+
+    default:
+        dprintf(CRITICAL, "Unexpected response (%x) to direct request2\n",
+                (uint32_t)smc_ret.r0);
+        return ERR_NOT_VALID;
+    }
+}
+
 ssize_t arm_ffa_console_log(const char* buf, size_t len) {
     struct smc_ret8 smc_ret;
 
diff --git a/lib/arm_ffa/include/lib/arm_ffa/arm_ffa.h b/lib/arm_ffa/include/lib/arm_ffa/arm_ffa.h
index c33437e..f446b35 100644
--- a/lib/arm_ffa/include/lib/arm_ffa/arm_ffa.h
+++ b/lib/arm_ffa/include/lib/arm_ffa/arm_ffa.h
@@ -26,6 +26,7 @@
 #include <arch/ops.h>
 #include <interface/arm_ffa/arm_ffa.h>
 #include <lib/smc/smc.h>
+#include <lib/trusty/uuid.h>
 #include <stdbool.h>
 
 /**
@@ -177,6 +178,22 @@
         ulong a4);
 
 /**
+ * arm_ffa_msg_send_direct_req2() - Send a direct message request.
+ *
+ * @uuid: Handler UUID.
+ * @receiver_id: Receiver ID.
+ * @args: Contents of message - x4-x17. Must not be %NULL.
+ * @resp: The registers passed back in response to the direct message iff
+ *        the request was successful. Must not be %NULL.
+ *
+ * Return: 0 on success, LK error code on failure.
+ */
+status_t arm_ffa_msg_send_direct_req2(uuid_t uuid,
+                                      uint16_t receiver_id,
+                                      uint64_t args[static REQ2_OTHER_PARAM_REGS],
+                                      struct smc_ret18* resp);
+
+/**
  * arm_ffa_console_log() - Output a buffer using %FFA_CONSOLE_LOG.
  *
  * @buf: The buffer to print.