For secure partition with multi service, tpm_ffa_crb can access tpm
service with direct message request v2 interface according to chapter 3.3,
TPM Service Command Response Buffer Interface Over FF-A specification, v1.0 BET.

This patch reflects this spec to access tpm service over
FF-A direct message request v2 ABI.

Acked-by: Sudeep Holla <sudeep.ho...@arm.com>
Signed-off-by: Yeoreum Yun <yeoreum....@arm.com>
---
Since v2:
    - rewokring commit message
    - https://lore.kernel.org/all/20250411090856.1417021-1-yeoreum....@arm.com/

Since v1:
    - Fix indentation.
    - https://lore.kernel.org/all/20250410110701.1244965-1-yeoreum....@arm.com/
---
 drivers/char/tpm/tpm_crb_ffa.c | 55 ++++++++++++++++++++++++----------
 1 file changed, 40 insertions(+), 15 deletions(-)

diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
index 3169a87a56b6..fed775cf53ab 100644
--- a/drivers/char/tpm/tpm_crb_ffa.c
+++ b/drivers/char/tpm/tpm_crb_ffa.c
@@ -105,7 +105,10 @@ struct tpm_crb_ffa {
        u16 minor_version;
        /* lock to protect sending of FF-A messages: */
        struct mutex msg_data_lock;
-       struct ffa_send_direct_data direct_msg_data;
+       union {
+               struct ffa_send_direct_data direct_msg_data;
+               struct ffa_send_direct_data2 direct_msg_data2;
+       };
 };

 static struct tpm_crb_ffa *tpm_crb_ffa;
@@ -185,18 +188,34 @@ static int __tpm_crb_ffa_send_recieve(unsigned long 
func_id,

        msg_ops = tpm_crb_ffa->ffa_dev->ops->msg_ops;

-       memset(&tpm_crb_ffa->direct_msg_data, 0x00,
-              sizeof(struct ffa_send_direct_data));
-
-       tpm_crb_ffa->direct_msg_data.data1 = func_id;
-       tpm_crb_ffa->direct_msg_data.data2 = a0;
-       tpm_crb_ffa->direct_msg_data.data3 = a1;
-       tpm_crb_ffa->direct_msg_data.data4 = a2;
+       if (ffa_partition_supports_direct_req2_recv(tpm_crb_ffa->ffa_dev)) {
+               memset(&tpm_crb_ffa->direct_msg_data2, 0x00,
+                      sizeof(struct ffa_send_direct_data2));
+
+               tpm_crb_ffa->direct_msg_data2.data[0] = func_id;
+               tpm_crb_ffa->direct_msg_data2.data[1] = a0;
+               tpm_crb_ffa->direct_msg_data2.data[2] = a1;
+               tpm_crb_ffa->direct_msg_data2.data[3] = a2;
+
+               ret = msg_ops->sync_send_receive2(tpm_crb_ffa->ffa_dev,
+                               &tpm_crb_ffa->direct_msg_data2);
+               if (!ret)
+                       ret = 
tpm_crb_ffa_to_linux_errno(tpm_crb_ffa->direct_msg_data2.data[0]);
+       } else {
+               memset(&tpm_crb_ffa->direct_msg_data, 0x00,
+                      sizeof(struct ffa_send_direct_data));
+
+               tpm_crb_ffa->direct_msg_data.data1 = func_id;
+               tpm_crb_ffa->direct_msg_data.data2 = a0;
+               tpm_crb_ffa->direct_msg_data.data3 = a1;
+               tpm_crb_ffa->direct_msg_data.data4 = a2;
+
+               ret = msg_ops->sync_send_receive(tpm_crb_ffa->ffa_dev,
+                               &tpm_crb_ffa->direct_msg_data);
+               if (!ret)
+                       ret = 
tpm_crb_ffa_to_linux_errno(tpm_crb_ffa->direct_msg_data.data1);
+       }

-       ret = msg_ops->sync_send_receive(tpm_crb_ffa->ffa_dev,
-                       &tpm_crb_ffa->direct_msg_data);
-       if (!ret)
-               ret = 
tpm_crb_ffa_to_linux_errno(tpm_crb_ffa->direct_msg_data.data1);

        return ret;
 }
@@ -231,8 +250,13 @@ int tpm_crb_ffa_get_interface_version(u16 *major, u16 
*minor)

        rc = __tpm_crb_ffa_send_recieve(CRB_FFA_GET_INTERFACE_VERSION, 0x00, 
0x00, 0x00);
        if (!rc) {
-               *major = 
CRB_FFA_MAJOR_VERSION(tpm_crb_ffa->direct_msg_data.data2);
-               *minor = 
CRB_FFA_MINOR_VERSION(tpm_crb_ffa->direct_msg_data.data2);
+               if 
(ffa_partition_supports_direct_req2_recv(tpm_crb_ffa->ffa_dev)) {
+                       *major = 
CRB_FFA_MAJOR_VERSION(tpm_crb_ffa->direct_msg_data2.data[1]);
+                       *minor = 
CRB_FFA_MINOR_VERSION(tpm_crb_ffa->direct_msg_data2.data[1]);
+               } else {
+                       *major = 
CRB_FFA_MAJOR_VERSION(tpm_crb_ffa->direct_msg_data.data2);
+                       *minor = 
CRB_FFA_MINOR_VERSION(tpm_crb_ffa->direct_msg_data.data2);
+               }
        }

        return rc;
@@ -277,7 +301,8 @@ static int tpm_crb_ffa_probe(struct ffa_device *ffa_dev)

        tpm_crb_ffa = ERR_PTR(-ENODEV); // set tpm_crb_ffa so we can detect 
probe failure

-       if (!ffa_partition_supports_direct_recv(ffa_dev)) {
+       if (!ffa_partition_supports_direct_recv(ffa_dev) &&
+           !ffa_partition_supports_direct_req2_recv(ffa_dev)) {
                pr_err("TPM partition doesn't support direct message 
receive.\n");
                return -EINVAL;
        }
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}


Reply via email to