[PATCH v1 08/14] tee: optee: add registered shared parameters handling
From: Volodymyr Babchuk
Date: Fri Oct 13 2017 - 15:34:14 EST
From: Volodymyr Babchuk <vlad.babchuk@xxxxxxxxx>
Now, when client applications can register own shared buffers in OP-TEE,
we need to extend ABI for parameter passing to/from OP-TEE.
So, if OP-TEE core detects that parameter belongs to registered shared
memory, it will use corresponding parameter attribute.
Signed-off-by: Volodymyr Babchuk <vlad.babchuk@xxxxxxxxx>
---
* Removed check on u.memref.size at optee_from_msg_param(), because
it caused fail on some tests. According to GlobalPlatform specs,
we don't need to check returned SHM size, because in this case
TA can indicate desired buffer size.
---
drivers/tee/optee/core.c | 78 ++++++++++++++++++++++++++++++++++++++----------
1 file changed, 63 insertions(+), 15 deletions(-)
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 4d448bf..3729ebb 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -97,6 +97,25 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
return rc;
}
break;
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+ attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ p->u.memref.size = mp->u.rmem.size;
+ shm = (struct tee_shm *)(unsigned long)
+ mp->u.rmem.shm_ref;
+
+ if (!shm) {
+ p->u.memref.shm_offs = 0;
+ p->u.memref.shm = NULL;
+ break;
+ }
+ p->u.memref.shm_offs = mp->u.rmem.offs;
+ p->u.memref.shm = shm;
+
+ break;
+
default:
return -EINVAL;
}
@@ -104,6 +123,46 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
return 0;
}
+static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
+ const struct tee_param *p)
+{
+ int rc;
+ phys_addr_t pa;
+
+ mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+
+ mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
+ mp->u.tmem.size = p->u.memref.size;
+
+ if (!p->u.memref.shm) {
+ mp->u.tmem.buf_ptr = 0;
+ return 0;
+ }
+
+ rc = tee_shm_get_pa(p->u.memref.shm, p->u.memref.shm_offs, &pa);
+ if (rc)
+ return rc;
+
+ mp->u.tmem.buf_ptr = pa;
+ mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
+ OPTEE_MSG_ATTR_CACHE_SHIFT;
+
+ return 0;
+}
+
+static int to_msg_param_reg_mem(struct optee_msg_param *mp,
+ const struct tee_param *p)
+{
+ mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+
+ mp->u.rmem.shm_ref = (unsigned long)p->u.memref.shm;
+ mp->u.rmem.size = p->u.memref.size;
+ mp->u.rmem.offs = p->u.memref.shm_offs;
+ return 0;
+}
+
/**
* optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
* @msg_params: OPTEE_MSG parameters
@@ -116,7 +175,6 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
{
int rc;
size_t n;
- phys_addr_t pa;
for (n = 0; n < num_params; n++) {
const struct tee_param *p = params + n;
@@ -139,22 +197,12 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
- mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT +
- p->attr -
- TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
- mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
- mp->u.tmem.size = p->u.memref.size;
- if (!p->u.memref.shm) {
- mp->u.tmem.buf_ptr = 0;
- break;
- }
- rc = tee_shm_get_pa(p->u.memref.shm,
- p->u.memref.shm_offs, &pa);
+ if (tee_shm_is_registered(p->u.memref.shm))
+ rc = to_msg_param_reg_mem(mp, p);
+ else
+ rc = to_msg_param_tmp_mem(mp, p);
if (rc)
return rc;
- mp->u.tmem.buf_ptr = pa;
- mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
- OPTEE_MSG_ATTR_CACHE_SHIFT;
break;
default:
return -EINVAL;
--
2.7.4