drivers/misc/optee: Fix GP API compatibility

Previous implementation was not compatible with GlobalPlatform
API in the following ways:
 - Registered mem IDs would begin from negatives when it should
   have been greater than or equal to 0
 - Register IOCTL would return 0 on success, when it should have
   been returning a file descriptor.
 - Register IOCTL would expect the user-space client to specify
   TEE_SHM_* flags dictating its behaviour when in fact, libteec
   never specifies flags.

This commit fixes all those issues. It uses nuttx/idr.h instead
of a linked list, and it uses `file_allocate` to provide file
descriptors for registered shared memory. Upon close(fd), the
memory is de-registered and freed accordingly. It also updates
the documentation accordingly.

Signed-off-by: George Poulios <gpoulios@census-labs.com>
This commit is contained in:
George Poulios 2025-05-10 14:40:26 +03:00 committed by Xiang Xiao
parent c497ee249b
commit a2a689fee0
5 changed files with 235 additions and 175 deletions

View file

@ -100,8 +100,8 @@ on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``).
future, but until then, please refer to ``include/nuttx/tee.h`` for details.
In short, for shared memory references, ``.a`` is the offset into the
shared memory buffer, ``.b`` is the size of the buffer, and ``.c`` is the
the shared memory identifier (``.addr`` field used in
``TEE_IOC_SHM_REGISTER``).
the shared memory identifier (``.id`` field returned by
``TEE_IOC_SHM_ALLOC`` or ``TEE_IOC_SHM_REGISTER``).
- ``TEE_IOC_CANCEL`` : Cancel a currently invoked command.
@ -113,8 +113,8 @@ on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``).
- Expects a ``struct tee_ioctl_shm_alloc_data`` pointer with the ``.size``
field set, and ignoring the ``.flags`` field. Upon successful return,
it returns the memory file descriptor one can use ``mmap()`` on (with
``MAP_SHARED``). It also returns an identifier for the allocation
in ``.id``.
``MAP_SHARED``). It also returns an identifier for use in memory references
(``tee_ioctl_param.c`` field) in ``.id``.
- ``TEE_IOC_SHM_REGISTER`` : Register a shared memory reference with the secure OS.
@ -126,10 +126,9 @@ on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``).
``TEE_SHM_SEC_REGISTER`` registers the memory with the secure OS for later
use in memrefs and is automatically de-registered during driver close if
``TEE_SHM_REGISTER`` is also specified. ``.addr`` shall point to the (user)
memory to register and ``.size`` shall indicate its size. The identifier
used to register shared memory with the secure OS is the value of the
``.addr`` field (what one needs to specify in ``tee_ioctl_param.c``
during a ``TEE_IOC_INVOKE``).
memory to register and ``.size`` shall indicate its size. One may use the
returned ``.id`` field when specifying shared memory references
(``tee_ioctl_param.c`` field).
Typical usage
=============
@ -167,7 +166,7 @@ Typical usage
return ret;
}
[...check ioc_ver accordingly...]
/* check ioc_ver accordingly */
#. Open a session with a Trusted Application
@ -188,7 +187,7 @@ Typical usage
return ret;
}
[...use ioc_opn.session returned...]
/* use ioc_opn.session returned */
#. Invoke a function of the Trusted Application
@ -222,7 +221,7 @@ Typical usage
goto err_with_args;
}
[...use result (if any) in ioc_args->params...]
/* use result (if any) in ioc_args->params */
#. Allocate shared memory through the driver
@ -253,22 +252,25 @@ Typical usage
.. code-block:: c
/* The following will fail if TEE_GEN_CAP_REG_MEM is not reported in
* the returned `ioc_ver.gen_caps` in step 1 above */
* the returned `ioc_ver.gen_caps` in step 1 above
* Note: user memory used does not have to be allocated through IOCTL
*/
struct tee_ioctl_shm_register_data ioc_reg = { 0 };
ioc_reg.addr = (uintptr_t)ptr;
ioc_reg.length = ioc_alloc.size;
ioc_reg.flags = TEE_SHM_REGISTER | TEE_SHM_SEC_REGISTER;
ioc_reg.addr = (uintptr_t)<some user memory ptr>;
ioc_reg.length = <user memory size>;
ret = ioctl(fd, TEE_IOC_SHM_REGISTER, (unsigned long)&ioc_reg);
if (ret < 0)
memfd = ioctl(fd, TEE_IOC_SHM_REGISTER, (unsigned long)&ioc_reg);
if (memfd < 0)
{
munmap(shm, ioc_alloc.size);
close(memfd);
return ret;
}
/* use ioc_reg.id returned in OP-TEE parameters (e.g. open, invoke) */
close(memfd);
#. Use the registered shared memory in an invocation
.. code-block:: c
@ -292,8 +294,8 @@ Typical usage
ioc_args->num_params = num_params;
ioc_args->params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
ioc_args->params[0].a = 0;
ioc_args->params[0].b = ioc_alloc.size;
ioc_args->params[0].a = (uintptr_t)shm;
ioc_args->params[0].b = ioc_reg.length;
ioc_args->params[0].c = ioc_reg.id;
ioc_buf.buf_ptr = (uintptr_t)ioc_args;
ioc_buf.buf_len = ioc_args_len;
@ -304,4 +306,4 @@ Typical usage
goto err_with_args;
}
[...use result (if any) in ioc_args->params...]
/* use result (if any) in ioc_args->params */

View file

@ -144,6 +144,8 @@ static int optee_close(FAR struct file *filep);
static int optee_ioctl(FAR struct file *filep, int cmd,
unsigned long arg);
static int optee_shm_close(FAR struct file *filep);
/****************************************************************************
* Private Data
****************************************************************************/
@ -152,15 +154,35 @@ static int optee_ioctl(FAR struct file *filep, int cmd,
static const struct file_operations g_optee_ops =
{
optee_open, /* open */
optee_close, /* close */
NULL, /* read */
NULL, /* write */
NULL, /* seek */
optee_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
optee_open, /* open */
optee_close, /* close */
NULL, /* read */
NULL, /* write */
NULL, /* seek */
optee_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
};
static const struct file_operations g_optee_shm_ops =
{
NULL, /* open */
optee_shm_close, /* close */
NULL, /* read */
NULL, /* write */
NULL, /* seek */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
};
static struct inode g_optee_shm_inode =
{
.i_flags = FSNODEFLAG_TYPE_SHM, /* could also be DRIVER; doesn't matter */
.i_crefs = 1, /* inode never to be released */
.u.i_ops = &g_optee_shm_ops
};
/****************************************************************************
@ -246,41 +268,6 @@ static bool optee_is_valid_range(FAR const void *va, size_t size)
# define optee_is_valid_range(addr, size) (true)
#endif
/****************************************************************************
* Name: optee_shm_next_id
*
* Description:
* Return a unique ID for adding a new entry to the list of shared memory
* chunks registered with the driver. This function assumes all new items
* in the list are added to the head. It is NOT thread-safe.
*
* Parameters:
* priv - The driver's private data structure
*
* Returned Values:
* A unique ID for the next shared memory list entry to be added.
*
****************************************************************************/
static inline int32_t optee_shm_next_id(FAR struct optee_priv_data *priv)
{
FAR struct optee_shm_entry *shme;
int32_t next_id;
if (list_is_empty(&priv->shm_list))
{
next_id = INT32_MIN;
}
else
{
shme = list_first_entry(&priv->shm_list, struct optee_shm_entry,
node);
next_id = shme->shm.id + 1;
}
return next_id;
}
/****************************************************************************
* Name: optee_shm_to_page_list
*
@ -323,8 +310,8 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
uint32_t list_size;
uint32_t i = 0;
pgoff = shme->shm.addr & (pgsize - 1);
total_pages = (uint32_t)div_round_up(pgoff + shme->shm.length, pgsize);
pgoff = shme->addr & (pgsize - 1);
total_pages = (uint32_t)div_round_up(pgoff + shme->length, pgsize);
list_size = div_round_up(total_pages, OPTEE_PAGES_ARRAY_LEN)
* sizeof(struct optee_page_list_entry);
@ -340,7 +327,7 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
}
list_entry = (FAR struct optee_page_list_entry *)list;
page = ALIGN_DOWN(shme->shm.addr, pgsize);
page = ALIGN_DOWN(shme->addr, pgsize);
while (total_pages)
{
list_entry->pages_array[i++] = optee_va_to_pa((FAR const void *)page);
@ -364,7 +351,7 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
}
/****************************************************************************
* Name: optee_shm_sec_register
* Name: optee_shm_register
*
* Description:
* Register specified shared memory entry with OP-TEE.
@ -380,8 +367,8 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
*
****************************************************************************/
static int optee_shm_sec_register(FAR struct optee_priv_data *priv,
FAR struct optee_shm_entry *shme)
static int optee_shm_register(FAR struct optee_priv_data *priv,
FAR struct optee_shm_entry *shme)
{
FAR struct optee_msg_arg *msg;
uintptr_t page_list_pa;
@ -404,8 +391,8 @@ static int optee_shm_sec_register(FAR struct optee_priv_data *priv,
msg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
OPTEE_MSG_ATTR_NONCONTIG;
msg->params[0].u.tmem.buf_ptr = page_list_pa;
msg->params[0].u.tmem.shm_ref = shme->shm.addr;
msg->params[0].u.tmem.size = shme->shm.length;
msg->params[0].u.tmem.shm_ref = (uintptr_t)shme;
msg->params[0].u.tmem.size = shme->length;
ret = optee_transport_call(priv, msg);
if (ret < 0)
@ -426,7 +413,7 @@ errout_with_msg:
}
/****************************************************************************
* Name: optee_shm_sec_unregister
* Name: optee_shm_unregister
*
* Description:
* Unregister specified shared memory entry with OP-TEE.
@ -442,8 +429,8 @@ errout_with_msg:
*
****************************************************************************/
static int optee_shm_sec_unregister(FAR struct optee_priv_data *priv,
FAR struct optee_shm_entry *shme)
static int optee_shm_unregister(FAR struct optee_priv_data *priv,
FAR struct optee_shm_entry *shme)
{
FAR struct optee_msg_arg *msg;
int ret = 0;
@ -456,7 +443,7 @@ static int optee_shm_sec_unregister(FAR struct optee_priv_data *priv,
msg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
msg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
msg->params[0].u.rmem.shm_ref = shme->shm.addr;
msg->params[0].u.rmem.shm_ref = (uintptr_t)shme;
ret = optee_transport_call(priv, msg);
if (ret < 0)
@ -474,6 +461,29 @@ errout_with_msg:
return ret;
}
/****************************************************************************
* Name: optee_shm_close
*
* Description:
* shm close operation
*
* Parameters:
* filep - the file instance
*
* Returned Values:
* Always OK.
*
****************************************************************************/
static int optee_shm_close(FAR struct file *filep)
{
FAR struct optee_shm_entry *shme = filep->f_priv;
optee_shm_free(shme);
filep->f_priv = NULL;
return 0;
}
/****************************************************************************
* Name: optee_open
*
@ -499,8 +509,7 @@ static int optee_open(FAR struct file *filep)
return ret;
}
list_initialize(&priv->shm_list);
spin_lock_init(&priv->lock);
priv->shms = idr_init();
filep->f_priv = priv;
return 0;
}
@ -515,7 +524,7 @@ static int optee_open(FAR struct file *filep)
* filep - the file instance
*
* Returned Values:
* OK on success; A negated errno value is returned on any failure.
* Always OK.
*
****************************************************************************/
@ -523,23 +532,75 @@ static int optee_close(FAR struct file *filep)
{
FAR struct optee_priv_data *priv = filep->f_priv;
FAR struct optee_shm_entry *shme;
FAR struct optee_shm_entry *tmp;
int id = 0;
list_for_every_entry_safe(&priv->shm_list, shme, tmp,
struct optee_shm_entry, node)
idr_for_each_entry(priv->shms, shme, id)
{
optee_shm_free(priv, shme);
optee_shm_free(shme);
}
idr_destroy(priv->shms);
optee_transport_close(priv);
return 0;
}
static int optee_to_msg_param(FAR struct optee_msg_param *mparams,
static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
FAR struct optee_msg_param *mp,
FAR const struct tee_ioctl_param *p)
{
FAR struct optee_shm_entry *shme;
/* Warning: the case for non-registered memrefs below is a hack to work
* with openvela. Normally, non-registered memory should be specified as
* OPTEE_MSG_ATTR_TYPE_TMEM_* (note the 'T') and `buf_ptr` should be set
* to the physical address of buffer.
*
* Related openvela patches:
* - external_optee_optee_os@1a29df42 core/tee/entry_std.c#L160
* - frameworks_security_optee_vela@54b377d5c compat/mobj_dyn_shm.c#L25
*
* Ideally, in the future, this should be wrapped around some
* CONFIG_OPTEE_OPENVELA_COMPAT guard.
*/
mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
if (p->c != TEE_MEMREF_NULL)
{
shme = idr_find(priv->shms, p->c);
if (shme == NULL)
{
return -EINVAL;
}
if (shme->flags & TEE_SHM_REGISTER)
{
mp->u.rmem.shm_ref = (uintptr_t)shme;
}
else
{
/* hack to comply with openvela */
mp->u.rmem.shm_ref = shme->addr;
}
}
else
{
mp->u.rmem.shm_ref = 0;
}
mp->u.rmem.size = p->b;
mp->u.rmem.offs = p->a;
return 0;
}
static int optee_to_msg_param(FAR struct optee_priv_data *priv,
FAR struct optee_msg_param *mparams,
size_t num_params,
FAR const struct tee_ioctl_param *params)
{
size_t n;
int ret;
for (n = 0; n < num_params; n++)
{
@ -568,19 +629,11 @@ static int optee_to_msg_param(FAR struct optee_msg_param *mparams,
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_RMEM_INPUT + p->attr -
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
if (p->c != TEE_MEMREF_NULL)
ret = optee_memref_to_msg_param(priv, mp, p);
if (ret < 0)
{
mp->u.rmem.shm_ref = p->c;
return ret;
}
else
{
mp->u.rmem.shm_ref = 0;
}
mp->u.rmem.size = p->b;
mp->u.rmem.offs = p->a;
break;
default:
return -EINVAL;
@ -719,7 +772,8 @@ static int optee_ioctl_open_session(FAR struct optee_priv_data *priv,
memcpy(&msg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
msg->params[1].u.value.c = arg->clnt_login;
ret = optee_to_msg_param(msg->params + 2, arg->num_params, arg->params);
ret = optee_to_msg_param(priv, msg->params + 2, arg->num_params,
arg->params);
if (ret < 0)
{
goto errout_with_msg;
@ -731,8 +785,7 @@ static int optee_ioctl_open_session(FAR struct optee_priv_data *priv,
goto errout_with_msg;
}
ret = optee_from_msg_param(arg->params, arg->num_params,
msg->params + 2);
ret = optee_from_msg_param(arg->params, arg->num_params, msg->params + 2);
if (ret < 0)
{
optee_close_session(priv, msg->session);
@ -798,7 +851,7 @@ static int optee_ioctl_invoke(FAR struct optee_priv_data *priv,
msg->session = arg->session;
msg->cancel_id = arg->cancel_id;
ret = optee_to_msg_param(msg->params, arg->num_params, arg->params);
ret = optee_to_msg_param(priv, msg->params, arg->num_params, arg->params);
if (ret < 0)
{
goto errout_with_msg;
@ -873,9 +926,13 @@ static int optee_ioctl_cancel(FAR struct optee_priv_data *priv,
}
static int
optee_ioctl_shm_alloc(FAR struct tee_ioctl_shm_alloc_data *data)
optee_ioctl_shm_alloc(FAR struct optee_priv_data *priv,
FAR struct tee_ioctl_shm_alloc_data *data)
{
FAR struct optee_shm_entry *shme;
FAR void *addr;
int memfd;
int ret;
if (!optee_is_valid_range(data, sizeof(*data)))
{
@ -890,21 +947,32 @@ optee_ioctl_shm_alloc(FAR struct tee_ioctl_shm_alloc_data *data)
if (ftruncate(memfd, data->size) < 0)
{
ret = get_errno();
goto err;
}
data->id = (uintptr_t)mmap(NULL, data->size, PROT_READ | PROT_WRITE,
MAP_SHARED, memfd, 0);
if (data->id == (uintptr_t)MAP_FAILED)
addr = mmap(NULL, data->size, PROT_READ | PROT_WRITE, MAP_SHARED,
memfd, 0);
if (addr == MAP_FAILED)
{
ret = get_errno();
goto err;
}
ret = optee_shm_alloc(priv, addr, data->size, 0, &shme);
if (ret < 0)
{
goto err_with_mmap;
}
data->id = shme->id;
return memfd;
err_with_mmap:
munmap(addr, data->size);
err:
close(memfd);
return get_errno();
return ret;
}
static int
@ -925,20 +993,27 @@ optee_ioctl_shm_register(FAR struct optee_priv_data *priv,
return -EFAULT;
}
if (rdata->flags & TEE_SHM_ALLOC)
if (rdata->flags)
{
return -EINVAL;
}
ret = optee_shm_alloc(priv, (FAR void *)(uintptr_t)rdata->addr,
rdata->length, rdata->flags, &shme);
if (ret)
rdata->length, TEE_SHM_REGISTER, &shme);
if (ret < 0)
{
return ret;
}
rdata->id = shme->shm.id;
return 0;
ret = file_allocate(&g_optee_shm_inode, O_CLOEXEC, 0, shme, 0, true);
if (ret < 0)
{
optee_shm_free(shme);
return ret;
}
rdata->id = shme->id;
return ret;
}
/****************************************************************************
@ -975,7 +1050,7 @@ static int optee_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case TEE_IOC_CANCEL:
return optee_ioctl_cancel(priv, parg);
case TEE_IOC_SHM_ALLOC:
return optee_ioctl_shm_alloc(parg);
return optee_ioctl_shm_alloc(priv, parg);
case TEE_IOC_SHM_REGISTER:
return optee_ioctl_shm_register(priv, parg);
default:
@ -1031,7 +1106,7 @@ uintptr_t optee_va_to_pa(FAR const void *va)
* Name: optee_shm_alloc
*
* Description:
* Allocate, register and/or add shared memory for use with OP-TEE calls.
* Allocate and/or register shared memory with the OP-TEE OS.
* Shared memory entry suitable for use in shared memory linked list
* returned in pass-by-reference `shmep` pointer. This function always
* allocates a shared memory entry, regardless of flags. The rest of this
@ -1040,12 +1115,9 @@ uintptr_t optee_va_to_pa(FAR const void *va)
* be allocated. In this case `addr` will be ignored. The allocated
* buffer will be aligned to `priv->alignment`. `TEE_SHM_ALLOC` flag
* is reserved for kernel use only.
* - If `TEE_SHM_SEC_REGISTER` is specified, then the memory specified by
* - If `TEE_SHM_REGISTER` is specified, then the memory specified by
* `addr` or allocated through `TEE_SHM_ALLOC`, will be registered with
* OP-TEE as dynamic shared memory.
* - If `TEE_SHM_REGISTER` is specified, then the memory specified by
* `addr` or allocated through `TEE_SHM_ALLOC`, will be added to the
* driver's private data structure linked list of shared memory chunks.
*
* Use `optee_shm_free()` to undo this operation, i.e. to free,
* unregister, and/or remove from the list the entry returned in `shmep`
@ -1071,14 +1143,13 @@ int optee_shm_alloc(FAR struct optee_priv_data *priv, FAR void *addr,
FAR struct optee_shm_entry **shmep)
{
FAR struct optee_shm_entry *shme;
irqstate_t irqstate;
FAR void *ptr;
int ret;
int ret = -ENOMEM;
shme = kmm_zalloc(sizeof(struct optee_shm_entry));
if (shme == NULL)
{
return -ENOMEM;
return ret;
}
if (flags & TEE_SHM_ALLOC)
@ -1099,36 +1170,34 @@ int optee_shm_alloc(FAR struct optee_priv_data *priv, FAR void *addr,
if (ptr == NULL)
{
ret = -ENOMEM;
goto err;
}
shme->shm.addr = (uintptr_t)ptr;
shme->shm.length = size;
shme->shm.flags = flags;
shme->priv = priv;
shme->addr = (uintptr_t)ptr;
shme->length = size;
shme->flags = flags;
shme->id = idr_alloc(priv->shms, shme, 0, 0);
if (flags & TEE_SHM_SEC_REGISTER)
if (shme->id < 0)
{
ret = optee_shm_sec_register(priv, shme);
if (ret < 0)
{
goto err;
}
goto err;
}
if (flags & TEE_SHM_REGISTER)
{
irqstate = spin_lock_irqsave(&priv->lock);
shme->shm.id = optee_shm_next_id(priv);
list_add_head(&priv->shm_list, &shme->node);
spin_unlock_irqrestore(&priv->lock, irqstate);
ret = optee_shm_register(priv, shme);
if (ret < 0)
{
goto err_with_idr;
}
}
*shmep = shme;
return 0;
err_with_idr:
idr_remove(priv->shms, shme->id);
err:
kmm_free(shme);
if (flags & TEE_SHM_ALLOC)
@ -1146,7 +1215,6 @@ err:
* Free and/or unregister shared memory allocated by `optee_shm_alloc()`.
*
* Parameters:
* priv - The driver's private data structure
* shme - Pointer to shared memory entry to free. Can be NULL, in which
* case, this is a no-op.
*
@ -1155,38 +1223,31 @@ err:
*
****************************************************************************/
void optee_shm_free(FAR struct optee_priv_data *priv,
FAR struct optee_shm_entry *shme)
void optee_shm_free(FAR struct optee_shm_entry *shme)
{
irqstate_t irqstate;
if (!shme)
{
return;
}
if (shme->shm.flags & TEE_SHM_SEC_REGISTER)
if (shme->flags & TEE_SHM_REGISTER)
{
optee_shm_sec_unregister(priv, shme);
optee_shm_unregister(shme->priv, shme);
}
if (shme->shm.flags & TEE_SHM_REGISTER)
if (shme->flags & TEE_SHM_ALLOC)
{
irqstate = spin_lock_irqsave(&priv->lock);
if (list_in_list(&shme->node))
{
list_delete(&shme->node);
}
spin_unlock_irqrestore(&priv->lock, irqstate);
kmm_free((FAR void *)(uintptr_t)shme->addr);
}
if (shme->shm.flags & TEE_SHM_ALLOC)
if (!(shme->flags & (TEE_SHM_ALLOC | TEE_SHM_REGISTER)))
{
kmm_free((FAR void *)(uintptr_t)shme->shm.addr);
/* allocated by optee_ioctl_shm_alloc(), need to unmap */
munmap((FAR void *)(uintptr_t)shme->addr, shme->length);
}
idr_remove(shme->priv->shms, shme->id);
kmm_free(shme);
}

View file

@ -30,8 +30,7 @@
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <nuttx/tee.h>
#include <nuttx/list.h>
#include <nuttx/spinlock.h>
#include <nuttx/idr.h>
#include "optee_msg.h"
@ -46,17 +45,19 @@
* Public Types
****************************************************************************/
struct optee_shm_entry
{
struct list_node node;
struct tee_ioctl_shm_register_data shm;
};
struct optee_priv_data
{
uintptr_t alignment; /* Transport-specified message alignment */
struct list_node shm_list; /* A list of all shm registered */
spinlock_t lock; /* Lock used to guard list accesses */
FAR struct idr_s *shms; /* An RB tree of all shm entries */
};
struct optee_shm_entry
{
FAR struct optee_priv_data *priv;
int32_t id;
uint64_t addr;
uint64_t length;
uint32_t flags;
};
/****************************************************************************
@ -80,8 +81,7 @@ uintptr_t optee_va_to_pa(FAR const void *va);
int optee_shm_alloc(FAR struct optee_priv_data *priv, FAR void *addr,
size_t size, uint32_t flags,
FAR struct optee_shm_entry **shmep);
void optee_shm_free(FAR struct optee_priv_data *priv,
FAR struct optee_shm_entry *shme);
void optee_shm_free(FAR struct optee_shm_entry *shme);
int optee_transport_init(void);
int optee_transport_open(FAR struct optee_priv_data **priv);
void optee_transport_close(FAR struct optee_priv_data *priv);

View file

@ -187,10 +187,9 @@ static void optee_smc_handle_rpc(FAR struct optee_priv_data *priv_,
switch (rpc_func)
{
case OPTEE_SMC_RPC_FUNC_ALLOC:
if (!optee_shm_alloc(priv_, NULL, par->a1,
TEE_SHM_ALLOC | TEE_SHM_REGISTER, &shme))
if (!optee_shm_alloc(priv_, NULL, par->a1, TEE_SHM_ALLOC, &shme))
{
shme_pa = optee_va_to_pa((FAR void *)(uintptr_t)shme->shm.addr);
shme_pa = optee_va_to_pa((FAR void *)(uintptr_t)shme->addr);
reg_pair_from_64(shme_pa, &par->a1, &par->a2);
reg_pair_from_64((uintptr_t)shme, &par->a4, &par->a5);
}
@ -204,7 +203,7 @@ static void optee_smc_handle_rpc(FAR struct optee_priv_data *priv_,
case OPTEE_SMC_RPC_FUNC_FREE:
shme = (FAR struct optee_shm_entry *)
reg_pair_to_uintptr(par->a1, par->a2);
optee_shm_free(priv_, shme);
optee_shm_free(shme);
break;
case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:

View file

@ -378,12 +378,10 @@ struct tee_iocl_supp_send_arg
#define TEE_IOC_SUPPL_SEND _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 7)
/* Shared memory specific defines */
/* Shared memory-specific defines */
#define TEE_SHM_REGISTER (1 << 0) /* In list of shared memory */
#define TEE_SHM_SEC_REGISTER (1 << 1) /* TEE notified of this memory */
#define TEE_SHM_ALLOC (1 << 2) /* The memory is malloced() and must
* be freed() */
#define TEE_SHM_ALLOC (1 << 0) /* Kernel-malloced and must freed */
#define TEE_SHM_REGISTER (1 << 1) /* Registered with TEE OS */
/* struct tee_ioctl_shm_register_data - Shared memory register argument
* addr: [in] Start address of shared memory to register