drivers/misc/optee: Expanded RPC support.
This commit expands RPC support for the OP-TEE driver using 2 files:
1) drivers/misc/optee_rpc.c
* Add support for RPCs that can be handled directly by the kernel.
* Can delegate RPC handling to optee_supplicant.c for RPCs that
need userspace interaction.
2) drivers/misc/optee_supplicant.c
* Enable communication between the userspace TEE supplicant and the
kernel driver.
Additional changes were needed to the following files:
1) drivers/misc/optee.c
* Add ioctls used SOLELY by the userspace TEE supplicant.
* Register /dev/teepriv0 if the supplicant is enabled in Kconfig
* Add OPTEE_ROLE_CA and OPTEE_ROLE_SUPPLICANT conditionals to
differentiate paths, between a normal Client Application (CA)
and the TEE supplicant.
* Change some functions from static to "public" to reuse them
in other C files.
* Adjust optee_to/from_msg_param() to work with RPCs.
2) drivers/misc/optee_smc.c
* Call the RPC handler from optee_rpc.c
3) drivers/misc/optee_msg.h
* Add definition needed for RPCs
4) drivers/misc/tee.h
* Add ioctl definitions
* Add TEE_SHM_SUPP flag, checked when unregistering supplicant
memory.
5) Documentation/guides/optee.rs
* Add documentation for RPCs and the supplicant.
6) drivers/misc/{CMakeLists.txt, Make.defs}
* Account for the new files.
7) drivers/misc/Kconfig
* Add DEV_OPTEE_SUPPLICANT option to enable/disable the supplicant
driver.
Signed-off-by: Theodore Karatapanis <tkaratapanis@census-labs.com>
This commit is contained in:
parent
95ca3e7ca5
commit
707cdaf42e
13 changed files with 1819 additions and 195 deletions
|
|
@ -14,8 +14,16 @@ not officially supported by NuttX, and is out of the scope of this guide.
|
|||
|
||||
The driver supports opening and closing sessions, allocating and registering
|
||||
shared memory, and invoking functions on OP-TEE Trusted Applications (TAs).
|
||||
It does not (yet) support reverse direction commands (TA -> Normal World)
|
||||
to something like a TEE supplicant.
|
||||
The driver also supports, reverse direction commands called RPCs
|
||||
(TA -> Normal World). Some of the RPCs are handled completely by the kernel
|
||||
driver while others require the TEE supplicant userspace process to be running
|
||||
by having opened (``/dev/teepriv#``). Similarly to libteec, the supplicant
|
||||
is not officially supported.
|
||||
|
||||
.. note::
|
||||
``/dev/teepriv#`` is reserved solely for the supplicant and shouldn't be
|
||||
used by any other NuttX application.
|
||||
|
||||
|
||||
Enabling the OP-TEE Driver
|
||||
==========================
|
||||
|
|
@ -27,16 +35,14 @@ The driver is enabled using one of:
|
|||
- ``CONFIG_DEV_OPTEE_SMC``
|
||||
|
||||
All of the above require also ``CONFIG_ALLOW_BSD_COMPONENTS`` and
|
||||
``CONFIG_LIBC_MEMFD_SHMFS``, which in turn requires ``CONFIG_FS_SHMFS``. So,
|
||||
at a bare minimum, to enable the driver one would need something like the
|
||||
following:
|
||||
``CONFIG_FS_ANONMAP``. So, at a bare minimum, to enable the driver
|
||||
one would need something like the following:
|
||||
|
||||
.. code-block::
|
||||
|
||||
CONFIG_ALLOW_BSD_COMPONENTS=y
|
||||
CONFIG_DEV_OPTEE_SMC=y
|
||||
CONFIG_FS_SHMFS=y
|
||||
CONFIG_LIBC_MEMFD_SHMFS=y
|
||||
CONFIG_FS_ANONMAP=y
|
||||
|
||||
Each implementation (local, RPMsg, or SMC) may have further dependencies
|
||||
(e.g. RPMsg requires ``CONFIG_NET_RPMSG`` and more) and may have further
|
||||
|
|
@ -49,10 +55,13 @@ parameters to configure (e.g. RPMsg remote CPU name through
|
|||
encounter issues with shared memory depending on the state of the data
|
||||
cache in Secure World.
|
||||
|
||||
If ``CONFIG_DEV_OPTEE_SMC`` is enabled we can also enable the kernel driver
|
||||
for the TEE supplicant by using ``CONFIG_DEV_OPTEE_SUPPLICANT``.
|
||||
|
||||
Successful registration of the driver can be verified by looking into
|
||||
``/dev/tee0``. For instance, incompatibility with the TEE OS running in the
|
||||
system, will prevent the ``/dev/tee0`` character device from being
|
||||
registered.
|
||||
``/dev/tee0`` and ``/dev/teepriv0`` (for the supplicant). For instance,
|
||||
incompatibility with the TEE OS running in the system, will prevent the
|
||||
``/dev/tee0`` character device from being registered.
|
||||
|
||||
IOCTLs supported
|
||||
================
|
||||
|
|
@ -130,6 +139,26 @@ on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``).
|
|||
returned ``.id`` field when specifying shared memory references
|
||||
(``tee_ioctl_param.c`` field).
|
||||
|
||||
- ``TEE_IOC_SUPPL_RECV`` : Receive an RPC request from the OP-TEE that needs userspace interaction from the supplicant.
|
||||
|
||||
- Expects a pointer to a ``struct tee_ioctl_buf_data`` instance where the
|
||||
``.buf_ptr`` field points to a user allocated buffer that must hold a
|
||||
``struct tee_iocl_supp_send/recv_arg`` followed by a number of
|
||||
``struct tee_ioctl_param`` parameters. The ``.buf_len`` field communicates
|
||||
to the kernel the length of that buffer. If the user passes a bigger number
|
||||
of parameters than ``OPTEE_MAX_PARAM_NUM`` or smaller number of parameters than
|
||||
the number sent by OP-TEE, the ioctl will fail. The TEE supplicant by default
|
||||
uses 5 ``struct tee_ioctl_param`` parameters.
|
||||
|
||||
- ``TEE_IOC_SUPPL_SEND`` : Respond to an RPC request from the OP-TEE that needed userspace interaction from the supplicant.
|
||||
|
||||
- Expects a pointer to a ``struct tee_ioctl_buf_data`` instance where the
|
||||
``.buf_ptr`` field points to a user allocated buffer that must hold a
|
||||
``struct tee_iocl_supp_send/recv_arg`` followed by a number of
|
||||
``struct tee_ioctl_param`` parameters. The ``.buf_len`` field communicates
|
||||
to the kernel the length of that buffer. The number of parameters depends on
|
||||
the size of expected RPC response by the OP-TEE.
|
||||
|
||||
Typical usage
|
||||
=============
|
||||
|
||||
|
|
@ -307,3 +336,37 @@ Typical usage
|
|||
}
|
||||
|
||||
/* use result (if any) in ioc_args->params */
|
||||
|
||||
#. OP-TEE secure storage support through TEE supplicant
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
optee_supplicant -f /data/tee > /dev/null &
|
||||
|
||||
This runs the OP-TEE supplicant in the background, using ``/data/tee`` as the
|
||||
directory for the TEE file system. Output is redirected to ``/dev/null`` to
|
||||
suppress standard output. Make sure that the userspace support for the
|
||||
supplicant is enabled and that ``/data`` is mounted as read/write.
|
||||
|
||||
With the supplicant running, secure storage objects can be created, retrieved,
|
||||
and managed by Trusted Applications (TAs). In a typical workflow, a Client
|
||||
Application (CA) running on NuttX invokes a command in a TA that may need to
|
||||
read from or create persistent objects. In such cases, certain RPCs generated
|
||||
by OP-TEE are routed from the CA to the TEE supplicant for handling (provided
|
||||
the supplicant is running in the background). Once the supplicant has processed
|
||||
the request, it responds using ``TEE_IOC_SUPPL_SEND``, and the kernel driver
|
||||
delivers this response back to the CA in its context.
|
||||
|
||||
#. OP-TEE REE time request
|
||||
|
||||
In this scenario, the userspace supplicant isn't needed, as the response can be
|
||||
handled directly by the kernel driver.
|
||||
|
||||
An OP-TEE application can request the current time from the NuttX clock using:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
TEE_GetREETime(&t);
|
||||
|
||||
The NuttX kernel driver will respond to the TA with the ``CLOCK_REALTIME``
|
||||
which represents the machine's best-guess as to the current wall-clock.
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ if(NOT CONFIG_DEV_OPTEE_NONE)
|
|||
list(APPEND SRCS optee.c)
|
||||
if(CONFIG_DEV_OPTEE_SMC)
|
||||
list(APPEND SRCS optee_smc.c)
|
||||
list(APPEND SRCS optee_rpc.c)
|
||||
if(CONFIG_DEV_OPTEE_SUPPLICANT)
|
||||
list(APPEND SRCS optee_supplicant.c)
|
||||
endif()
|
||||
else()
|
||||
list(APPEND SRCS optee_socket.c)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -73,6 +73,11 @@ config DEV_OPTEE_NONE
|
|||
|
||||
endchoice
|
||||
|
||||
config DEV_OPTEE_SUPPLICANT
|
||||
bool "Enables kernel driver for TEE supplicant"
|
||||
default n
|
||||
depends on DEV_OPTEE_SMC
|
||||
|
||||
if DEV_OPTEE_RPMSG
|
||||
|
||||
config OPTEE_REMOTE_CPU_NAME
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ ifneq ($(CONFIG_DEV_OPTEE_NONE),y)
|
|||
CSRCS += optee.c
|
||||
ifeq ($(CONFIG_DEV_OPTEE_SMC),y)
|
||||
CSRCS += optee_smc.c
|
||||
CSRCS += optee_rpc.c
|
||||
ifeq ($(CONFIG_DEV_OPTEE_SUPPLICANT),y)
|
||||
CSRCS += optee_supplicant.c
|
||||
endif
|
||||
else
|
||||
CSRCS += optee_socket.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@
|
|||
|
||||
#include "optee.h"
|
||||
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
# include "optee_supplicant.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* The driver's main purpose is to support the porting of the open source
|
||||
* component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
|
||||
|
|
@ -55,23 +59,8 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Some GlobalPlatform error codes used in this driver */
|
||||
|
||||
#define TEE_SUCCESS 0x00000000
|
||||
#define TEE_ERROR_ACCESS_DENIED 0xFFFF0001
|
||||
#define TEE_ERROR_BAD_FORMAT 0xFFFF0005
|
||||
#define TEE_ERROR_BAD_PARAMETERS 0xFFFF0006
|
||||
#define TEE_ERROR_NOT_SUPPORTED 0xFFFF000A
|
||||
#define TEE_ERROR_OUT_OF_MEMORY 0xFFFF000C
|
||||
#define TEE_ERROR_BUSY 0xFFFF000D
|
||||
#define TEE_ERROR_COMMUNICATION 0xFFFF000E
|
||||
#define TEE_ERROR_SECURITY 0xFFFF000F
|
||||
#define TEE_ERROR_SHORT_BUFFER 0xFFFF0010
|
||||
#define TEE_ERROR_TIMEOUT 0xFFFF3001
|
||||
|
||||
#define TEE_ORIGIN_COMMS 0x00000002
|
||||
|
||||
#define OPTEE_DEV_PATH "/dev/tee0"
|
||||
#define OPTEE_SUPPLICANT_DEV_PATH "/dev/teepriv0"
|
||||
|
||||
/* According to optee_msg.h#OPTEE_MSG_ATTR_NONCONTIG */
|
||||
|
||||
|
|
@ -187,35 +176,6 @@ static struct inode g_optee_shm_inode =
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int optee_convert_error(uint32_t oterr)
|
||||
{
|
||||
switch (oterr)
|
||||
{
|
||||
case TEE_SUCCESS:
|
||||
return 0;
|
||||
case TEE_ERROR_ACCESS_DENIED:
|
||||
case TEE_ERROR_SECURITY:
|
||||
return -EACCES;
|
||||
case TEE_ERROR_BAD_FORMAT:
|
||||
case TEE_ERROR_BAD_PARAMETERS:
|
||||
return -EINVAL;
|
||||
case TEE_ERROR_NOT_SUPPORTED:
|
||||
return -EOPNOTSUPP;
|
||||
case TEE_ERROR_OUT_OF_MEMORY:
|
||||
return -ENOMEM;
|
||||
case TEE_ERROR_BUSY:
|
||||
return -EBUSY;
|
||||
case TEE_ERROR_COMMUNICATION:
|
||||
return -ECOMM;
|
||||
case TEE_ERROR_SHORT_BUFFER:
|
||||
return -ENOBUFS;
|
||||
case TEE_ERROR_TIMEOUT:
|
||||
return -ETIMEDOUT;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_is_valid_range
|
||||
*
|
||||
|
|
@ -401,7 +361,7 @@ static int optee_shm_register(FAR struct optee_priv_data *priv,
|
|||
|
||||
if (msg->ret)
|
||||
{
|
||||
ret = optee_convert_error(msg->ret);
|
||||
ret = optee_convert_to_errno(msg->ret);
|
||||
}
|
||||
|
||||
errout_with_list:
|
||||
|
|
@ -452,7 +412,7 @@ static int optee_shm_unregister(FAR struct optee_priv_data *priv,
|
|||
|
||||
if (msg->ret)
|
||||
{
|
||||
ret = optee_convert_error(msg->ret);
|
||||
ret = optee_convert_to_errno(msg->ret);
|
||||
}
|
||||
|
||||
errout_with_msg:
|
||||
|
|
@ -481,7 +441,6 @@ static int optee_shm_close(FAR struct file *filep)
|
|||
if (shm != NULL && shm->id > -1)
|
||||
{
|
||||
filep->f_priv = NULL;
|
||||
shm->fd = -1;
|
||||
optee_shm_free(shm);
|
||||
}
|
||||
|
||||
|
|
@ -559,6 +518,7 @@ static int optee_shm_mmap(FAR struct file *filep,
|
|||
static int optee_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct optee_priv_data *priv;
|
||||
enum optee_role_e role = (uintptr_t)filep->f_inode->i_private;
|
||||
int ret;
|
||||
|
||||
ret = optee_transport_open(&priv);
|
||||
|
|
@ -567,7 +527,30 @@ static int optee_open(FAR struct file *filep)
|
|||
return ret;
|
||||
}
|
||||
|
||||
priv->shms = idr_init();
|
||||
priv->role = role;
|
||||
|
||||
if (role == OPTEE_ROLE_CA)
|
||||
{
|
||||
priv->shms = idr_init();
|
||||
}
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
else if (role == OPTEE_ROLE_SUPPLICANT)
|
||||
{
|
||||
/* Allow only one process to open the device. */
|
||||
|
||||
if (filep->f_inode->i_crefs > 2)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
optee_supplicant_init(&priv->shms);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
filep->f_priv = priv;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -590,26 +573,29 @@ static int optee_close(FAR struct file *filep)
|
|||
{
|
||||
FAR struct optee_priv_data *priv = filep->f_priv;
|
||||
FAR struct optee_shm *shm;
|
||||
FAR struct file *shm_filep;
|
||||
int id = 0;
|
||||
|
||||
idr_for_each_entry(priv->shms, shm, id)
|
||||
{
|
||||
if (shm->fd > -1 && file_get(shm->fd, &shm_filep) >= 0)
|
||||
/* Here, we only free, unfreed kernel allocations, the rest will be
|
||||
* done by optee_shm_close().
|
||||
*/
|
||||
|
||||
if (shm->fd == -1)
|
||||
{
|
||||
/* The user did not call close(), prevent vfs auto-close from
|
||||
* double-freeing our SHM
|
||||
*/
|
||||
|
||||
shm_filep->f_priv = NULL;
|
||||
file_put(shm_filep);
|
||||
optee_shm_free(shm);
|
||||
}
|
||||
|
||||
optee_shm_free(shm);
|
||||
}
|
||||
|
||||
idr_destroy(priv->shms);
|
||||
optee_transport_close(priv);
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
if (priv->role == OPTEE_ROLE_SUPPLICANT)
|
||||
{
|
||||
optee_supplicant_uninit();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -619,6 +605,7 @@ static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
|
|||
{
|
||||
FAR struct optee_shm *shm;
|
||||
uintptr_t page_list_pa;
|
||||
bool external_vm_context = false;
|
||||
|
||||
if (p->c == TEE_MEMREF_NULL)
|
||||
{
|
||||
|
|
@ -633,7 +620,17 @@ static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
|
|||
shm = idr_find(priv->shms, p->c);
|
||||
if (shm == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
/* Search also the shared memory registered by the supplicant. */
|
||||
|
||||
shm = optee_supplicant_search_shm(p->c);
|
||||
external_vm_context = true;
|
||||
|
||||
if (shm == NULL)
|
||||
#endif
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (shm->flags & TEE_SHM_REGISTER)
|
||||
|
|
@ -654,6 +651,15 @@ static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
|
|||
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
|
||||
mp->attr |= OPTEE_MSG_ATTR_NONCONTIG;
|
||||
|
||||
/* This shouldn't happen, we can't translate vmas from
|
||||
* another vm context.
|
||||
*/
|
||||
|
||||
if (external_vm_context)
|
||||
{
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
shm->page_list = optee_shm_to_page_list(shm, &page_list_pa);
|
||||
if (shm->page_list == NULL)
|
||||
{
|
||||
|
|
@ -662,7 +668,7 @@ static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
|
|||
|
||||
mp->u.tmem.buf_ptr = page_list_pa;
|
||||
mp->u.tmem.shm_ref = (uintptr_t)shm;
|
||||
mp->u.tmem.size = shm->length;
|
||||
mp->u.tmem.size = p->b;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARCH_USE_MMU
|
||||
|
|
@ -672,121 +678,6 @@ static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
|
|||
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++)
|
||||
{
|
||||
FAR const struct tee_ioctl_param *p = params + n;
|
||||
FAR struct optee_msg_param *mp = mparams + n;
|
||||
|
||||
if (p->attr & ~TEE_IOCTL_PARAM_ATTR_MASK)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK)
|
||||
{
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
|
||||
mp->attr = OPTEE_MSG_ATTR_TYPE_NONE;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
|
||||
mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
|
||||
TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
|
||||
mp->u.value.a = p->a;
|
||||
mp->u.value.b = p->b;
|
||||
mp->u.value.c = p->c;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
|
||||
ret = optee_memref_to_msg_param(priv, mp, p);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int optee_from_msg_param(FAR struct tee_ioctl_param *params,
|
||||
size_t num_params,
|
||||
FAR const struct optee_msg_param *mparams)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
for (n = 0; n < num_params; n++)
|
||||
{
|
||||
FAR const struct optee_msg_param *mp = mparams + n;
|
||||
FAR struct tee_ioctl_param *p = params + n;
|
||||
FAR struct optee_shm *shm = NULL;
|
||||
|
||||
switch (mp->attr & OPTEE_MSG_ATTR_TYPE_MASK)
|
||||
{
|
||||
case OPTEE_MSG_ATTR_TYPE_NONE:
|
||||
p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
|
||||
p->a = 0;
|
||||
p->b = 0;
|
||||
p->c = 0;
|
||||
break;
|
||||
case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
|
||||
p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
|
||||
mp->attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
|
||||
p->a = mp->u.value.a;
|
||||
p->b = mp->u.value.b;
|
||||
p->c = mp->u.value.c;
|
||||
break;
|
||||
case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
|
||||
p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
|
||||
mp->attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
|
||||
p->b = mp->u.tmem.size;
|
||||
|
||||
shm = (FAR struct optee_shm *)(uintptr_t)mp->u.tmem.shm_ref;
|
||||
if (shm && shm->page_list)
|
||||
{
|
||||
kmm_free(shm->page_list);
|
||||
shm->page_list = NULL;
|
||||
}
|
||||
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 +
|
||||
mp->attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
|
||||
p->b = mp->u.rmem.size;
|
||||
shm = (FAR struct optee_shm *)(uintptr_t)mp->u.tmem.shm_ref;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARCH_USE_MMU
|
||||
if (shm)
|
||||
{
|
||||
up_invalidate_dcache(shm->vaddr, shm->vaddr + shm->length);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int optee_close_session(FAR struct optee_priv_data *priv,
|
||||
uint32_t session)
|
||||
{
|
||||
|
|
@ -1047,8 +938,6 @@ optee_ioctl_shm_alloc(FAR struct optee_priv_data *priv,
|
|||
ret = file_allocate_from_inode(&g_optee_shm_inode,
|
||||
O_CLOEXEC | O_RDOK, 0, shm, 0);
|
||||
|
||||
/* Will free automatically the shm once the descriptor is closed. */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
optee_shm_free(shm);
|
||||
|
|
@ -1061,6 +950,43 @@ optee_ioctl_shm_alloc(FAR struct optee_priv_data *priv,
|
|||
return shm->fd;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
static int
|
||||
optee_shm_register_supplicant(FAR struct optee_priv_data *priv,
|
||||
uintptr_t addr, uint64_t length,
|
||||
FAR struct optee_shm **shmp)
|
||||
{
|
||||
FAR struct optee_shm *shm;
|
||||
uintptr_t page_list_pa;
|
||||
int ret = 0;
|
||||
|
||||
shm = kmm_zalloc(sizeof(struct optee_shm));
|
||||
*shmp = shm;
|
||||
if (shm == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
shm->fd = -1;
|
||||
shm->priv = priv;
|
||||
shm->vaddr = addr;
|
||||
shm->length = length;
|
||||
shm->flags = TEE_SHM_REGISTER | TEE_SHM_SUPP;
|
||||
shm->page_list = optee_shm_to_page_list(shm, &page_list_pa);
|
||||
shm->paddr = page_list_pa;
|
||||
shm->id = idr_alloc(priv->shms, shm, 0, 0);
|
||||
|
||||
if (shm->id < 0)
|
||||
{
|
||||
kmm_free(shm->page_list);
|
||||
kmm_free(shm);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
optee_ioctl_shm_register(FAR struct optee_priv_data *priv,
|
||||
FAR struct tee_ioctl_shm_register_data *rdata)
|
||||
|
|
@ -1084,8 +1010,25 @@ optee_ioctl_shm_register(FAR struct optee_priv_data *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = optee_shm_alloc(priv, (FAR void *)(uintptr_t)rdata->addr,
|
||||
rdata->length, TEE_SHM_REGISTER, &shm);
|
||||
if (priv->role == OPTEE_ROLE_CA)
|
||||
{
|
||||
ret = optee_shm_alloc(priv, (FAR void *)(uintptr_t)rdata->addr,
|
||||
rdata->length, TEE_SHM_REGISTER, &shm);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
else if (priv->role == OPTEE_ROLE_SUPPLICANT)
|
||||
{
|
||||
ret = optee_shm_register_supplicant(priv, (uintptr_t)rdata->addr,
|
||||
rdata->length, &shm);
|
||||
rdata->flags = shm->flags;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
|
@ -1103,6 +1046,114 @@ optee_ioctl_shm_register(FAR struct optee_priv_data *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
static int
|
||||
optee_ioctl_supplicant_recv(FAR struct optee_priv_data *priv,
|
||||
FAR struct tee_ioctl_buf_data *data)
|
||||
{
|
||||
int n;
|
||||
int ret;
|
||||
FAR struct tee_iocl_supp_recv_arg *arg;
|
||||
|
||||
if (!optee_is_valid_range(data, sizeof(*data)))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!optee_is_valid_range((FAR void *)data->buf_ptr, data->buf_len))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (data->buf_len > TEE_MAX_ARG_SIZE ||
|
||||
data->buf_len < sizeof(struct tee_iocl_supp_recv_arg))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arg = (FAR struct tee_iocl_supp_recv_arg *)(uintptr_t)data->buf_ptr;
|
||||
|
||||
if (sizeof(*arg) + TEE_IOCTL_PARAM_SIZE(arg->num_params) !=
|
||||
data->buf_len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->num_params > OPTEE_MAX_PARAM_NUM)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = optee_supplicant_recv(&arg->func, &arg->num_params, arg->params);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (n = 0; n < arg->num_params; n++)
|
||||
{
|
||||
FAR struct tee_ioctl_param *p = arg->params + n;
|
||||
|
||||
switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK)
|
||||
{
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
|
||||
if (!p->b)
|
||||
{
|
||||
p->a = 0;
|
||||
p->c = (uint64_t)-1; /* Invalid shm id. */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
optee_ioctl_supplicant_send(FAR struct optee_priv_data *priv,
|
||||
FAR struct tee_ioctl_buf_data *data)
|
||||
{
|
||||
FAR struct tee_iocl_supp_send_arg *arg;
|
||||
|
||||
if (!optee_is_valid_range(data, sizeof(*data)))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!optee_is_valid_range((FAR void *)data->buf_ptr, data->buf_len))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (data->buf_len > TEE_MAX_ARG_SIZE ||
|
||||
data->buf_len < sizeof(struct tee_iocl_supp_send_arg))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arg = (FAR struct tee_iocl_supp_send_arg *)(uintptr_t)data->buf_ptr;
|
||||
|
||||
if (sizeof(*arg) + TEE_IOCTL_PARAM_SIZE(arg->num_params) !=
|
||||
data->buf_len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->num_params > OPTEE_MAX_PARAM_NUM)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return optee_supplicant_send(arg->ret, arg->num_params, arg->params);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_ioctl
|
||||
*
|
||||
|
|
@ -1140,6 +1191,12 @@ static int optee_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
return optee_ioctl_shm_alloc(priv, parg);
|
||||
case TEE_IOC_SHM_REGISTER:
|
||||
return optee_ioctl_shm_register(priv, parg);
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
case TEE_IOC_SUPPL_RECV:
|
||||
return optee_ioctl_supplicant_recv(priv, parg);
|
||||
case TEE_IOC_SUPPL_SEND:
|
||||
return optee_ioctl_supplicant_send(priv, parg);
|
||||
#endif
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
|
@ -1151,6 +1208,49 @@ static int optee_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_convert_to_errno
|
||||
*
|
||||
* Description:
|
||||
* Convert TEE errors to errno values
|
||||
*
|
||||
* Parameters:
|
||||
* oterr - TEE error code.
|
||||
*
|
||||
* Returned Values:
|
||||
* The converted errno value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int optee_convert_to_errno(uint32_t oterr)
|
||||
{
|
||||
switch (oterr)
|
||||
{
|
||||
case TEE_SUCCESS:
|
||||
return 0;
|
||||
case TEE_ERROR_ACCESS_DENIED:
|
||||
case TEE_ERROR_SECURITY:
|
||||
return -EACCES;
|
||||
case TEE_ERROR_BAD_FORMAT:
|
||||
case TEE_ERROR_BAD_PARAMETERS:
|
||||
return -EINVAL;
|
||||
case TEE_ERROR_NOT_SUPPORTED:
|
||||
return -EOPNOTSUPP;
|
||||
case TEE_ERROR_OUT_OF_MEMORY:
|
||||
return -ENOMEM;
|
||||
case TEE_ERROR_BUSY:
|
||||
return -EBUSY;
|
||||
case TEE_ERROR_COMMUNICATION:
|
||||
return -ECOMM;
|
||||
case TEE_ERROR_SHORT_BUFFER:
|
||||
return -ENOBUFS;
|
||||
case TEE_ERROR_TIMEOUT:
|
||||
return -ETIMEDOUT;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_va_to_pa
|
||||
*
|
||||
|
|
@ -1318,7 +1418,7 @@ void optee_shm_free(FAR struct optee_shm *shm)
|
|||
return;
|
||||
}
|
||||
|
||||
if (shm->flags & TEE_SHM_REGISTER)
|
||||
if (!(shm->flags & TEE_SHM_SUPP) && (shm->flags & TEE_SHM_REGISTER))
|
||||
{
|
||||
optee_shm_unregister(shm->priv, shm);
|
||||
}
|
||||
|
|
@ -1354,5 +1454,181 @@ int optee_register(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return register_driver(OPTEE_DEV_PATH, &g_optee_ops, 0666, NULL);
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
ret = register_driver(OPTEE_SUPPLICANT_DEV_PATH, &g_optee_ops, 0666,
|
||||
(FAR void *)OPTEE_ROLE_SUPPLICANT);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return register_driver(OPTEE_DEV_PATH, &g_optee_ops, 0666,
|
||||
(FAR void *)OPTEE_ROLE_CA);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_from_msg_param
|
||||
*
|
||||
* Description:
|
||||
* Converts and copies the message parameters received by OP-TEE to buffer
|
||||
* for processing by nuttx.
|
||||
*
|
||||
* Parameters:
|
||||
* params - Pointer, to copy the received parameters after some processing.
|
||||
* num_params - Number of these parameters.
|
||||
* mparams - Pointer to the message parameters received by OP-TEE.
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int optee_from_msg_param(FAR struct tee_ioctl_param *params,
|
||||
size_t num_params,
|
||||
FAR const struct optee_msg_param *mparams)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
for (n = 0; n < num_params; n++)
|
||||
{
|
||||
FAR const struct optee_msg_param *mp = mparams + n;
|
||||
FAR struct tee_ioctl_param *p = params + n;
|
||||
FAR struct optee_shm *shm = NULL;
|
||||
|
||||
switch (mp->attr & OPTEE_MSG_ATTR_TYPE_MASK)
|
||||
{
|
||||
case OPTEE_MSG_ATTR_TYPE_NONE:
|
||||
p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
|
||||
p->a = 0;
|
||||
p->b = 0;
|
||||
p->c = 0;
|
||||
break;
|
||||
case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
|
||||
p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
|
||||
mp->attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
|
||||
p->a = mp->u.value.a;
|
||||
p->b = mp->u.value.b;
|
||||
p->c = mp->u.value.c;
|
||||
break;
|
||||
case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
|
||||
case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
|
||||
p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
|
||||
mp->attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
|
||||
p->b = mp->u.tmem.size;
|
||||
|
||||
shm = (FAR struct optee_shm *)(uintptr_t)mp->u.tmem.shm_ref;
|
||||
if (shm && shm->page_list)
|
||||
{
|
||||
kmm_free(shm->page_list);
|
||||
shm->page_list = NULL;
|
||||
p->c = shm->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->c = TEE_MEMREF_NULL;
|
||||
}
|
||||
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 +
|
||||
mp->attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
|
||||
p->b = mp->u.rmem.size;
|
||||
p->a = mp->u.rmem.offs;
|
||||
shm = (FAR struct optee_shm *)(uintptr_t)mp->u.tmem.shm_ref;
|
||||
if (shm)
|
||||
{
|
||||
p->c = shm->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->c = TEE_MEMREF_NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARCH_USE_MMU
|
||||
if (shm)
|
||||
{
|
||||
up_invalidate_dcache(shm->vaddr, shm->vaddr + shm->length);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_to_msg_param
|
||||
*
|
||||
* Description:
|
||||
* Converts and copies the processed by nuttx parameters to the shared
|
||||
* memory area containing the message to/from the OP-TEE.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - pointer to the driver's optee_priv_data struct
|
||||
* mparams - Pointer to the message parameters provided by OP-TEE.
|
||||
* params - Pointer, of the processed by nuttx parameters containing the
|
||||
* response.
|
||||
* num_params - Number of these parameters.
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
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++)
|
||||
{
|
||||
FAR const struct tee_ioctl_param *p = params + n;
|
||||
FAR struct optee_msg_param *mp = mparams + n;
|
||||
|
||||
if (p->attr & ~TEE_IOCTL_PARAM_ATTR_MASK)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK)
|
||||
{
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
|
||||
mp->attr = OPTEE_MSG_ATTR_TYPE_NONE;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
|
||||
mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
|
||||
TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
|
||||
mp->u.value.a = p->a;
|
||||
mp->u.value.b = p->b;
|
||||
mp->u.value.c = p->c;
|
||||
break;
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
|
||||
ret = optee_memref_to_msg_param(priv, mp, p);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,23 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Some GlobalPlatform error codes used in this driver */
|
||||
|
||||
#define TEE_SUCCESS 0x00000000
|
||||
#define TEE_ERROR_ACCESS_DENIED 0xFFFF0001
|
||||
#define TEE_ERROR_BAD_FORMAT 0xFFFF0005
|
||||
#define TEE_ERROR_BAD_PARAMETERS 0xFFFF0006
|
||||
#define TEE_ERROR_GENERIC 0xFFFF0000
|
||||
#define TEE_ERROR_NOT_SUPPORTED 0xFFFF000A
|
||||
#define TEE_ERROR_OUT_OF_MEMORY 0xFFFF000C
|
||||
#define TEE_ERROR_BUSY 0xFFFF000D
|
||||
#define TEE_ERROR_COMMUNICATION 0xFFFF000E
|
||||
#define TEE_ERROR_SECURITY 0xFFFF000F
|
||||
#define TEE_ERROR_SHORT_BUFFER 0xFFFF0010
|
||||
#define TEE_ERROR_TIMEOUT 0xFFFF3001
|
||||
|
||||
#define TEE_ORIGIN_COMMS 0x00000002
|
||||
|
||||
#define OPTEE_SERVER_PATH "optee"
|
||||
#define OPTEE_MAX_PARAM_NUM 6
|
||||
|
||||
|
|
@ -45,10 +62,17 @@
|
|||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
enum optee_role_e
|
||||
{
|
||||
OPTEE_ROLE_CA, /* /dev/tee0 */
|
||||
OPTEE_ROLE_SUPPLICANT, /* /dev/tee-supp0 */
|
||||
};
|
||||
|
||||
struct optee_priv_data
|
||||
{
|
||||
uintptr_t alignment; /* Transport-specified message alignment */
|
||||
FAR struct idr_s *shms; /* An RB tree of all shm entries */
|
||||
FAR struct idr_s *shms; /* An RB tree of process local shm entries */
|
||||
enum optee_role_e role;
|
||||
};
|
||||
|
||||
struct optee_shm
|
||||
|
|
@ -88,9 +112,20 @@ void optee_shm_free(FAR struct optee_shm *shm);
|
|||
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);
|
||||
|
||||
int optee_transport_call(FAR struct optee_priv_data *priv,
|
||||
FAR struct optee_msg_arg *arg);
|
||||
|
||||
int optee_from_msg_param(FAR struct tee_ioctl_param *params,
|
||||
size_t num_params,
|
||||
FAR const struct optee_msg_param *mparams);
|
||||
|
||||
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);
|
||||
|
||||
int optee_convert_to_errno(uint32_t oterr);
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
* This file is divided into two sections.
|
||||
* 1. Formatting of messages.
|
||||
* 2. Requests from normal world
|
||||
* 3. Requests from secure world, Remote Procedure Call (RPC), handled by
|
||||
* tee-supplicant
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -352,4 +354,136 @@ struct optee_msg_arg
|
|||
#define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF 7
|
||||
#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
|
||||
|
||||
/****************************************************************************
|
||||
* Part 3 - Requests from secure world, RPC
|
||||
****************************************************************************/
|
||||
|
||||
/* All RPC is done with a struct optee_msg_arg as bearer of information,
|
||||
* struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_*
|
||||
* below
|
||||
*
|
||||
* RPC communication with tee-supplicant is reversed compared to normal
|
||||
* client communication described above. The supplicant receives requests
|
||||
* and sends responses.
|
||||
*
|
||||
* Load a TA into memory, defined in tee-supplicant
|
||||
*/
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_LOAD_TA 0
|
||||
|
||||
/* Reserved */
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_RPMB 1
|
||||
|
||||
/* File system access, defined in tee-supplicant */
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_FS 2
|
||||
|
||||
/* Get time
|
||||
*
|
||||
* Returns number of seconds and nano seconds since the Epoch,
|
||||
* 1970-01-01 00:00:00 +0000 (UTC).
|
||||
*
|
||||
* [out] param[0].u.value.a Number of seconds
|
||||
* [out] param[0].u.value.b Number of nano seconds.
|
||||
*/
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_GET_TIME 3
|
||||
|
||||
/* Wait queue primitive, helper for secure world to implement a wait queue.
|
||||
*
|
||||
* If secure world need to wait for a secure world mutex it issues a sleep
|
||||
* request instead of spinning in secure world. Conversely is a wakeup
|
||||
* request issued when a secure world mutex with a thread waiting thread is
|
||||
* unlocked.
|
||||
*
|
||||
* Waiting on a key
|
||||
* [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
|
||||
* [in] param[0].u.value.b wait key
|
||||
*
|
||||
* Waking up a key
|
||||
* [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
|
||||
* [in] param[0].u.value.b wakeup key
|
||||
*/
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4
|
||||
#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
|
||||
#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1
|
||||
|
||||
/* Suspend execution
|
||||
*
|
||||
* [in] param[0].value .a number of milliseconds to suspend
|
||||
*/
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_SUSPEND 5
|
||||
|
||||
/* Allocate a piece of shared memory
|
||||
*
|
||||
* Shared memory can optionally be fragmented, to support that additional
|
||||
* spare param entries are allocated to make room for eventual fragments.
|
||||
* The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
|
||||
* unused. All returned temp memrefs except the last should have the
|
||||
* OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
|
||||
*
|
||||
* [in] param[0].u.value.a type of memory one of
|
||||
* OPTEE_MSG_RPC_SHM_TYPE_* below
|
||||
* [in] param[0].u.value.b requested size
|
||||
* [in] param[0].u.value.c required alignment
|
||||
*
|
||||
* [out] param[0].u.tmem.buf_ptr physical address (of first fragment)
|
||||
* [out] param[0].u.tmem.size size (of first fragment)
|
||||
* [out] param[0].u.tmem.shm_ref shared memory reference
|
||||
* ...
|
||||
* [out] param[n].u.tmem.buf_ptr physical address
|
||||
* [out] param[n].u.tmem.size size
|
||||
* [out] param[n].u.tmem.shm_ref shared memory reference (same value
|
||||
* as in param[n-1].u.tmem.shm_ref)
|
||||
*/
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6
|
||||
|
||||
/* Memory that can be shared with a non-secure user space application */
|
||||
|
||||
#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0
|
||||
|
||||
/* Memory only shared with non-secure kernel */
|
||||
|
||||
#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1
|
||||
|
||||
/* Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
|
||||
*
|
||||
* [in] param[0].u.value.a type of memory one of
|
||||
* OPTEE_MSG_RPC_SHM_TYPE_* above
|
||||
* [in] param[0].u.value.b value of shared memory reference
|
||||
* returned in param[0].u.tmem.shm_ref
|
||||
* above
|
||||
*/
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_SHM_FREE 7
|
||||
|
||||
/* Access a device on an i2c bus
|
||||
*
|
||||
* [in] param[0].u.value.a mode: RD(0), WR(1)
|
||||
* [in] param[0].u.value.b i2c adapter
|
||||
* [in] param[0].u.value.c i2c chip
|
||||
*
|
||||
* [in] param[1].u.value.a i2c control flags
|
||||
*
|
||||
* [in/out] memref[2] buffer to exchange the transfer data
|
||||
* with the secure world
|
||||
*
|
||||
* [out] param[3].u.value.a bytes transferred by the driver
|
||||
*/
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER 21
|
||||
|
||||
/* I2C master transfer modes */
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1
|
||||
|
||||
/* I2C master control flags */
|
||||
|
||||
#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT BIT(0)
|
||||
|
||||
#endif /* __DRIVERS_MISC_OPTEE_MSG_H */
|
||||
|
|
|
|||
359
drivers/misc/optee_rpc.c
Normal file
359
drivers/misc/optee_rpc.c
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/****************************************************************************
|
||||
* drivers/misc/optee_rpc.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/signal.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "optee.h"
|
||||
#include "optee_msg.h"
|
||||
#include "optee_rpc.h"
|
||||
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
# include "optee_supplicant.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_rpc_cmd_get_time
|
||||
*
|
||||
* Description:
|
||||
* Return REE wall-clock time (seconds + nanoseconds) to secure world.
|
||||
*
|
||||
* Parameters:
|
||||
* arg - Pointer to the RPC message argument located in shared memory by
|
||||
* the secure world. The answer will be placed in the same argument.
|
||||
*
|
||||
* Returned Value:
|
||||
* The time is written to:
|
||||
* arg->params[0].u.value.a containing seconds since epoch
|
||||
* arg->params[0].u.value.b containing nanoseconds
|
||||
* Result code is written to arg->ret.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void optee_rpc_cmd_get_time(FAR struct optee_msg_arg *arg)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
/* OP-TEE parameter validation. */
|
||||
|
||||
if (arg->num_params != 1 ||
|
||||
(arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK)
|
||||
!= OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
return;
|
||||
}
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
|
||||
{
|
||||
/* Should not happen unless the RTC driver is missing */
|
||||
|
||||
arg->ret = TEE_ERROR_GENERIC;
|
||||
return;
|
||||
}
|
||||
|
||||
arg->params[0].u.value.a = (uint32_t)ts.tv_sec; /* Seconds since epoch. */
|
||||
arg->params[0].u.value.b = (uint32_t)ts.tv_nsec; /* Nanoseconds. */
|
||||
|
||||
arg->ret = TEE_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_rpc_cmd_suspend
|
||||
*
|
||||
* Description:
|
||||
* Request from OP-TEE to suspend the current nuttx process.
|
||||
*
|
||||
* Parameters:
|
||||
* arg - Pointer to the RPC message argument, located in a shared page, by
|
||||
* the secure world, containing the time in msec to sleep.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. Result codes are written into arg->ret.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void optee_rpc_cmd_suspend(FAR struct optee_msg_arg *arg)
|
||||
{
|
||||
useconds_t usec_to_wait;
|
||||
|
||||
/* OP-TEE parameter validation. */
|
||||
|
||||
if (arg->num_params != 1 ||
|
||||
(arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
|
||||
OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
return;
|
||||
}
|
||||
|
||||
usec_to_wait = arg->params[0].u.value.a * 1000;
|
||||
|
||||
if (usec_to_wait)
|
||||
{
|
||||
int ret = nxsig_usleep(usec_to_wait);
|
||||
|
||||
if (ret < 0 && ret != -EINTR)
|
||||
{
|
||||
arg->ret = TEE_ERROR_GENERIC;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
arg->ret = TEE_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_rpc_cmd_shm_alloc
|
||||
*
|
||||
* Description:
|
||||
* Handle OP-TEE's RPC to allocate shared memory.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Pointer to the driver's optee_priv_data struct.
|
||||
* arg - Pointer to the RPC message argument, located in a shared page
|
||||
* by the secure world. A copy of this message might be sent to the
|
||||
* supplicant process that runs in userspace for further processing.
|
||||
* last_page_list - Passes by reference a pointer that will be updated with
|
||||
* the virtual address of the page list.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. Result codes are written into arg->ret.
|
||||
* Information about the shared memory is passed through arg->params
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void optee_rpc_cmd_shm_alloc(FAR struct optee_priv_data *priv,
|
||||
FAR struct optee_msg_arg *arg,
|
||||
FAR void **last_page_list)
|
||||
{
|
||||
FAR struct optee_shm *shm;
|
||||
size_t n;
|
||||
size_t size;
|
||||
int32_t ret = -EINVAL;
|
||||
|
||||
arg->ret_origin = TEE_ORIGIN_COMMS;
|
||||
|
||||
/* OP-TEE parameter validation. */
|
||||
|
||||
if (arg->num_params == 0 ||
|
||||
arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
return;
|
||||
}
|
||||
|
||||
for (n = 1; n < arg->num_params; n++)
|
||||
{
|
||||
if (arg->params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE)
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
size = arg->params[0].u.value.b;
|
||||
switch (arg->params[0].u.value.a)
|
||||
{
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_APPL:
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
ret = optee_supplicant_alloc(priv, size, &shm);
|
||||
break;
|
||||
#else
|
||||
arg->ret = TEE_ERROR_NOT_SUPPORTED;
|
||||
return;
|
||||
#endif
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
|
||||
ret = optee_shm_alloc(priv, NULL, size, TEE_SHM_ALLOC, &shm);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == -ENOMEM)
|
||||
{
|
||||
arg->ret = TEE_ERROR_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
else if (ret == -ECOMM)
|
||||
{
|
||||
arg->ret = TEE_ERROR_COMMUNICATION;
|
||||
return;
|
||||
}
|
||||
else if (ret == -EINVAL)
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
return;
|
||||
}
|
||||
else if (ret != OK)
|
||||
{
|
||||
arg->ret = TEE_ERROR_GENERIC;
|
||||
return;
|
||||
}
|
||||
|
||||
if (shm->flags & TEE_SHM_REGISTER)
|
||||
{
|
||||
arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
|
||||
OPTEE_MSG_ATTR_NONCONTIG;
|
||||
arg->params[0].u.tmem.buf_ptr = shm->paddr;
|
||||
arg->params[0].u.tmem.size = shm->length;
|
||||
arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
|
||||
*last_page_list = shm->page_list;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
|
||||
arg->params[0].u.tmem.buf_ptr = shm->paddr;
|
||||
arg->params[0].u.tmem.size = size;
|
||||
arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
|
||||
}
|
||||
|
||||
arg->ret = TEE_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_rpc_cmd_shm_free
|
||||
*
|
||||
* Description:
|
||||
* RPC Request from OP-TEE to free shared memory allocated by nuttx.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Pointer to the driver's optee_priv_data struct.
|
||||
* arg - Pointer to the RPC message argument, located in a shared page
|
||||
* by the secure world. A copy of this message might be sent to the
|
||||
* supplicant process that runs in userspace for further processing.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. Result codes are written into arg->ret.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void optee_rpc_cmd_shm_free(FAR struct optee_priv_data *priv,
|
||||
FAR struct optee_msg_arg *arg)
|
||||
{
|
||||
FAR struct optee_shm *shm;
|
||||
|
||||
arg->ret_origin = TEE_ORIGIN_COMMS;
|
||||
|
||||
/* OP-TEE parameter validation. */
|
||||
|
||||
if (arg->num_params != 1 ||
|
||||
arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
return;
|
||||
}
|
||||
|
||||
shm = (FAR struct optee_shm *)(unsigned long)arg->params[0].u.value.b;
|
||||
|
||||
switch (arg->params[0].u.value.a)
|
||||
{
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_APPL:
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
arg->ret = optee_supplicant_free(shm->id);
|
||||
if (arg->ret)
|
||||
{
|
||||
/* The supplicant either failed or isn't running. */
|
||||
|
||||
return;
|
||||
}
|
||||
#else
|
||||
arg->ret = TEE_ERROR_NOT_SUPPORTED;
|
||||
return;
|
||||
#endif
|
||||
break;
|
||||
case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
|
||||
optee_shm_free(shm);
|
||||
arg->ret = TEE_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_rpc_handle_cmd
|
||||
*
|
||||
* Description:
|
||||
* Handler of RPC requests.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Pointer to the driver's optee_priv_data struct.
|
||||
* shm - Contains a pointer to the RPC message argument, located in a
|
||||
* shared page, by the secure world. A copy of this message
|
||||
* might be sent to the supplicant process that runs in userspace
|
||||
* for further processing.
|
||||
* last_page_list - Passes by reference a pointer to the virtual address
|
||||
* of a page list. The page list can be freed by a
|
||||
* caller or by this function, depending on the response
|
||||
* of the OP-TEE to the next SMC.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. The response to OP-TEE will passed through the shared memory.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void optee_rpc_handle_cmd(FAR struct optee_priv_data *priv,
|
||||
FAR struct optee_shm *shm,
|
||||
FAR void **last_page_list)
|
||||
{
|
||||
FAR struct optee_msg_arg *arg;
|
||||
|
||||
DEBUGASSERT(shm != NULL);
|
||||
|
||||
arg = (FAR struct optee_msg_arg *)shm->vaddr;
|
||||
|
||||
switch (arg->cmd)
|
||||
{
|
||||
case OPTEE_MSG_RPC_CMD_GET_TIME:
|
||||
optee_rpc_cmd_get_time(arg);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_SUSPEND:
|
||||
optee_rpc_cmd_suspend(arg);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
|
||||
kmm_free(*last_page_list);
|
||||
*last_page_list = NULL;
|
||||
optee_rpc_cmd_shm_alloc(priv, arg, last_page_list);
|
||||
break;
|
||||
case OPTEE_MSG_RPC_CMD_SHM_FREE:
|
||||
optee_rpc_cmd_shm_free(priv, arg);
|
||||
break;
|
||||
default:
|
||||
#ifdef CONFIG_DEV_OPTEE_SUPPLICANT
|
||||
optee_supplicant_cmd(priv, arg);
|
||||
#else
|
||||
arg->ret = TEE_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
53
drivers/misc/optee_rpc.h
Normal file
53
drivers/misc/optee_rpc.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/****************************************************************************
|
||||
* drivers/misc/optee_rpc.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_MISC_OPTEE_RPC_H
|
||||
#define __DRIVERS_MISC_OPTEE_RPC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "optee.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
void optee_rpc_handle_cmd(FAR struct optee_priv_data *priv,
|
||||
FAR struct optee_shm *shm,
|
||||
FAR void **last_page_list);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* __DRIVERS_MISC_OPTEE_RPC_H */
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "optee.h"
|
||||
#include "optee_smc.h"
|
||||
#include "optee_rpc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
@ -177,7 +178,8 @@ static bool optee_smc_is_compatible(optee_smc_fn smc_fn)
|
|||
}
|
||||
|
||||
static void optee_smc_handle_rpc(FAR struct optee_priv_data *priv_,
|
||||
FAR smccc_res_t *par)
|
||||
FAR smccc_res_t *par,
|
||||
FAR void **last_page_list)
|
||||
{
|
||||
FAR struct optee_shm *shm;
|
||||
uint32_t rpc_func;
|
||||
|
|
@ -211,6 +213,10 @@ static void optee_smc_handle_rpc(FAR struct optee_priv_data *priv_,
|
|||
|
||||
sched_yield();
|
||||
break;
|
||||
case OPTEE_SMC_RPC_FUNC_CMD:
|
||||
shm = reg_pair_to_ptr(par->a1, par->a2);
|
||||
optee_rpc_handle_cmd(priv_, shm, last_page_list);
|
||||
break;
|
||||
|
||||
default:
|
||||
syslog(LOG_ERR, "OP-TEE: RPC 0x%04x not implemented\n", rpc_func);
|
||||
|
|
@ -323,6 +329,7 @@ int optee_transport_call(FAR struct optee_priv_data *priv_,
|
|||
|
||||
up_clean_dcache((uintptr_t)arg, (uintptr_t)arg + arg_size);
|
||||
#endif
|
||||
FAR void *last_page_list = NULL;
|
||||
|
||||
memset(&par, 0, sizeof(smccc_res_t));
|
||||
|
||||
|
|
@ -341,13 +348,16 @@ int optee_transport_call(FAR struct optee_priv_data *priv_,
|
|||
if (OPTEE_SMC_RETURN_IS_RPC(res.a0))
|
||||
{
|
||||
memcpy(&par, &res, 4 * sizeof(unsigned long));
|
||||
optee_smc_handle_rpc(priv_, &par);
|
||||
optee_smc_handle_rpc(priv_, &par, &last_page_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef CONFIG_ARCH_USE_MMU
|
||||
up_invalidate_dcache((uintptr_t)arg, (uintptr_t)arg + arg_size);
|
||||
#endif
|
||||
|
||||
kmm_free(last_page_list);
|
||||
last_page_list = NULL;
|
||||
return (int)res.a0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
611
drivers/misc/optee_supplicant.c
Normal file
611
drivers/misc/optee_supplicant.c
Normal file
|
|
@ -0,0 +1,611 @@
|
|||
/****************************************************************************
|
||||
* drivers/misc/optee_supplicant.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/queue.h>
|
||||
#include <nuttx/idr.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "optee.h"
|
||||
#include "optee_supplicant.h"
|
||||
#include "optee_msg.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Request structure for RPCs serviced by the supplicant. */
|
||||
|
||||
struct optee_supplicant_req
|
||||
{
|
||||
sq_entry_t link;
|
||||
uint32_t func;
|
||||
uint32_t ret;
|
||||
uint32_t num_params;
|
||||
FAR struct tee_ioctl_param *params;
|
||||
sem_t c;
|
||||
};
|
||||
|
||||
struct optee_supplicant
|
||||
{
|
||||
mutex_t mutex;
|
||||
int req_id;
|
||||
struct sq_queue_s reqs;
|
||||
FAR struct idr_s *idr;
|
||||
FAR struct idr_s *shm_idr;
|
||||
sem_t reqs_c;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct optee_supplicant g_optee_supp;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pop_entry
|
||||
*
|
||||
* Description:
|
||||
* Pop the first request from the request queue, and create unique id.
|
||||
*
|
||||
* Parameters:
|
||||
* num_params - Number of parameters passed.
|
||||
* id - Pointer to the unique request id.
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the request on success or NULL.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct optee_supplicant_req *pop_entry(uint32_t num_params,
|
||||
FAR int *id)
|
||||
{
|
||||
FAR struct optee_supplicant_req *req;
|
||||
|
||||
if (g_optee_supp.req_id != -1)
|
||||
{
|
||||
/* Mixing sync/async not supported */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sq_empty(&g_optee_supp.reqs))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
req = (FAR struct optee_supplicant_req *)sq_remfirst(&g_optee_supp.reqs);
|
||||
|
||||
/* The request can't fit in the supplicant's supplied parameter buffer. */
|
||||
|
||||
if (num_params < req->num_params)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*id = idr_alloc(g_optee_supp.idr, req, 0, INT32_MAX);
|
||||
if (*id < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_request
|
||||
*
|
||||
* Description:
|
||||
* Create a request with the received parameters from the OP-TEE, add it to
|
||||
* the supplicant's request queue and then wait on the request's semaphore
|
||||
* until it is serviced.
|
||||
*
|
||||
* Parameters:
|
||||
* func - Requested function for the supplicant to perform
|
||||
* params - Pointer pointer to parameter data.
|
||||
* num_params - Number of parameters passed.
|
||||
*
|
||||
* Returned Value:
|
||||
* TEE_SUCCESS on success or a global platform api error code on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t optee_supplicant_request(uint32_t func, uint32_t num_params,
|
||||
FAR struct tee_ioctl_param *params)
|
||||
{
|
||||
FAR struct optee_supplicant_req req;
|
||||
uint32_t ret;
|
||||
|
||||
/* The supplicant isn't running if the shm_idr == NULL. */
|
||||
|
||||
if (NULL == g_optee_supp.shm_idr)
|
||||
{
|
||||
return TEE_ERROR_COMMUNICATION;
|
||||
}
|
||||
|
||||
sem_init(&req.c, 0, 0);
|
||||
req.func = func;
|
||||
req.num_params = num_params;
|
||||
req.params = params;
|
||||
|
||||
nxmutex_lock(&g_optee_supp.mutex);
|
||||
sq_addlast(&req.link, &g_optee_supp.reqs);
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
|
||||
/* Wake supplicant receiver */
|
||||
|
||||
sem_post(&g_optee_supp.reqs_c);
|
||||
|
||||
/* Wait for completion if supplicant is running. */
|
||||
|
||||
while (sem_wait(&req.c) < 0)
|
||||
{
|
||||
}
|
||||
|
||||
ret = req.ret;
|
||||
sem_destroy(&req.c);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_init
|
||||
*
|
||||
* Description:
|
||||
* Initialize supplicant data.
|
||||
*
|
||||
* Parameters:
|
||||
* shm_idr - A pointer, passed by reference, to the optee driver's shm_idr.
|
||||
* The destruction of the shm_idr will be handled by
|
||||
* optee_close(), so we only need to initialize it in this
|
||||
* context.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void optee_supplicant_init(FAR struct idr_s **shm_idr)
|
||||
{
|
||||
memset(&g_optee_supp, 0, sizeof(g_optee_supp));
|
||||
nxmutex_init(&g_optee_supp.mutex);
|
||||
nxsem_init(&g_optee_supp.reqs_c, 0, 0);
|
||||
sq_init(&g_optee_supp.reqs);
|
||||
g_optee_supp.idr = idr_init();
|
||||
g_optee_supp.shm_idr = idr_init();
|
||||
g_optee_supp.req_id = -1;
|
||||
|
||||
/* Pass .shm_idr to the caller. */
|
||||
|
||||
*shm_idr = g_optee_supp.shm_idr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_uninit
|
||||
*
|
||||
* Description:
|
||||
* Uninitialize supplicant data.
|
||||
*
|
||||
* Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void optee_supplicant_uninit(void)
|
||||
{
|
||||
/* The destruction of the idr_s is performed by optee_close(). */
|
||||
|
||||
g_optee_supp.shm_idr = NULL;
|
||||
nxmutex_destroy(&g_optee_supp.mutex);
|
||||
nxsem_destroy(&g_optee_supp.reqs_c);
|
||||
idr_destroy(g_optee_supp.idr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_recv
|
||||
*
|
||||
* Description:
|
||||
* This function is invoked by an ioctl, used only by the supplicant. It
|
||||
* will obtain the function to be performed and the parameters passed by
|
||||
* OP-TEE.
|
||||
*
|
||||
* Parameters:
|
||||
* func - Pointer to obtain the function to be performed by the supplicant.
|
||||
* params - Pointer to the parameter data passed to supplicant.
|
||||
* num_params - Pointer with the number of parameters the supplicant can
|
||||
* process, and later updated with the number of parameters
|
||||
* of the OP-TEE's RPC request.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success, a negated errno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int optee_supplicant_recv(FAR uint32_t *func, FAR uint32_t *num_params,
|
||||
FAR struct tee_ioctl_param *params)
|
||||
{
|
||||
FAR struct optee_supplicant_req *req = NULL;
|
||||
int id;
|
||||
int n;
|
||||
uint8_t num_meta = (params->attr == TEE_IOCTL_PARAM_ATTR_META);
|
||||
|
||||
if (0 == num_params)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (n = 0; n < *num_params; n++)
|
||||
{
|
||||
if (params[n].attr &&
|
||||
params[n].attr != TEE_IOCTL_PARAM_ATTR_META)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
nxmutex_lock(&g_optee_supp.mutex);
|
||||
req = pop_entry(*num_params - num_meta, &id);
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
|
||||
if (req)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (sem_wait(&g_optee_supp.reqs_c) < 0)
|
||||
{
|
||||
return -EINTR;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_meta)
|
||||
{
|
||||
params->attr |= TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
|
||||
params->a = id;
|
||||
params->b = 0;
|
||||
params->c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nxmutex_lock(&g_optee_supp.mutex);
|
||||
g_optee_supp.req_id = id;
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
}
|
||||
|
||||
/* Setup parameters */
|
||||
|
||||
*func = req->func;
|
||||
*num_params = req->num_params + num_meta;
|
||||
|
||||
memcpy(params + num_meta, req->params,
|
||||
req->num_params * sizeof(params[0]));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_send
|
||||
*
|
||||
* Description:
|
||||
* This function is invoked by an ioctl, used only by the supplicant. It
|
||||
* will update the parameters of the OP-TEE request with the response from
|
||||
* the supplicant.
|
||||
*
|
||||
* Parameters:
|
||||
* ret - The return value to send to OP-TEE.
|
||||
* params - Contains the response parameters from nuttx.
|
||||
* num_params - Number of parameters.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success, a negated errno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int optee_supplicant_send(uint32_t ret, uint32_t num_params,
|
||||
FAR struct tee_ioctl_param *params)
|
||||
{
|
||||
FAR struct optee_supplicant_req *req;
|
||||
int id;
|
||||
uint8_t num_meta = 0;
|
||||
const uint32_t async_attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
|
||||
TEE_IOCTL_PARAM_ATTR_META;
|
||||
|
||||
nxmutex_lock(&g_optee_supp.mutex);
|
||||
|
||||
/* Check the parameters and obtain the request from the idr. */
|
||||
|
||||
if (!num_params)
|
||||
{
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Async. */
|
||||
|
||||
if (g_optee_supp.req_id == -1)
|
||||
{
|
||||
if (params->attr != async_attr)
|
||||
{
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
id = params->a;
|
||||
num_meta = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sync. */
|
||||
|
||||
id = g_optee_supp.req_id;
|
||||
num_meta = 0;
|
||||
}
|
||||
|
||||
req = idr_find(g_optee_supp.idr, id);
|
||||
if (!req)
|
||||
{
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if ((num_params - num_meta) != req->num_params)
|
||||
{
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
idr_remove(g_optee_supp.idr, id);
|
||||
g_optee_supp.req_id = -1;
|
||||
|
||||
nxmutex_unlock(&g_optee_supp.mutex);
|
||||
|
||||
if (!req)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Update output and in/out parameters. */
|
||||
|
||||
for (size_t n = 0; n < req->num_params; n++)
|
||||
{
|
||||
FAR struct tee_ioctl_param *p = &req->params[n];
|
||||
FAR struct tee_ioctl_param *r = ¶ms[n + num_meta];
|
||||
|
||||
switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK)
|
||||
{
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
|
||||
p->a = r->a;
|
||||
p->b = r->b;
|
||||
p->c = r->c;
|
||||
break;
|
||||
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
|
||||
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
|
||||
p->b = r->b;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
req->ret = ret;
|
||||
sem_post(&req->c);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_alloc
|
||||
*
|
||||
* Description:
|
||||
* Prepares and creates a request for userspace memory allocation that was
|
||||
* requested by the OP-TEE through an RPC.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Pointer to the driver's optee_priv_data struct.
|
||||
* size - Size to allocate.
|
||||
* shm - Passed by reference pointer to shared memory. On success it will
|
||||
* be updated with the shared memory the supplicant allocated.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success, a negated errno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int optee_supplicant_alloc(FAR struct optee_priv_data *priv,
|
||||
size_t size, FAR struct optee_shm **shm)
|
||||
{
|
||||
uint32_t ret;
|
||||
struct tee_ioctl_param param;
|
||||
|
||||
param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
|
||||
param.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
|
||||
param.b = size;
|
||||
param.c = 0;
|
||||
|
||||
ret = optee_supplicant_request(OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, ¶m);
|
||||
if (ret)
|
||||
{
|
||||
return optee_convert_to_errno(ret);
|
||||
}
|
||||
|
||||
if (NULL == g_optee_supp.shm_idr)
|
||||
{
|
||||
return -ECOMM;
|
||||
}
|
||||
|
||||
*shm = idr_find(g_optee_supp.shm_idr, param.c);
|
||||
|
||||
if (NULL == *shm)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_free
|
||||
*
|
||||
* Description:
|
||||
* Handles freeing of shared memory allocated by the TEE supplicant.
|
||||
*
|
||||
* Parameters:
|
||||
* shm_id - The id of the shared memory to be freed.
|
||||
*
|
||||
* Returned Value:
|
||||
* TEE_SUCCESS on success or a global platform api error code on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t optee_supplicant_free(int32_t shm_id)
|
||||
{
|
||||
struct tee_ioctl_param param;
|
||||
uint32_t ret;
|
||||
|
||||
param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
|
||||
param.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
|
||||
param.b = shm_id;
|
||||
param.c = 0;
|
||||
|
||||
ret = optee_supplicant_request(OPTEE_MSG_RPC_CMD_SHM_FREE, 1, ¶m);
|
||||
|
||||
if (ret != TEE_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (NULL == g_optee_supp.shm_idr)
|
||||
{
|
||||
ret = TEE_ERROR_COMMUNICATION;
|
||||
return ret;
|
||||
}
|
||||
|
||||
idr_remove(g_optee_supp.shm_idr, shm_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_cmd
|
||||
*
|
||||
* Description:
|
||||
* Copy the parameters from OP-TEE's message and then create a request to
|
||||
* supplicant to service this RPC request.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Pointer to the driver's optee_priv_data struct.
|
||||
* arg - Pointer to the RPC message argument, located in a shared page, by
|
||||
* by the secure world. A copy of this message will be sent to the
|
||||
* supplicant process that runs in userspace for further processing.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. Result codes are written into arg->ret.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void optee_supplicant_cmd(FAR struct optee_priv_data *priv,
|
||||
FAR struct optee_msg_arg *arg)
|
||||
{
|
||||
FAR struct tee_ioctl_param *params;
|
||||
int ret = 0;
|
||||
|
||||
arg->ret_origin = TEE_ORIGIN_COMMS;
|
||||
|
||||
params = kmm_zalloc(TEE_IOCTL_PARAM_SIZE(arg->num_params));
|
||||
if (!params)
|
||||
{
|
||||
arg->ret = TEE_ERROR_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
if (optee_from_msg_param(params, arg->num_params, arg->params))
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
arg->ret = optee_supplicant_request(arg->cmd, arg->num_params, params);
|
||||
|
||||
if ((ret = optee_to_msg_param(priv, arg->params, arg->num_params, params)))
|
||||
{
|
||||
if (ret == -ENOMEM)
|
||||
{
|
||||
arg->ret = TEE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
else if (ret == -EPROTO)
|
||||
{
|
||||
arg->ret = TEE_ERROR_COMMUNICATION;
|
||||
}
|
||||
else if (ret == -EINVAL)
|
||||
{
|
||||
arg->ret = TEE_ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg->ret = TEE_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
kmm_free(params);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_supplicant_search_shm
|
||||
*
|
||||
* Description:
|
||||
* Search the supplicant's idr_s for a specific id and return a pointer to
|
||||
* that shared memory if found.
|
||||
*
|
||||
* Parameters:
|
||||
* id - Shared memory id to search for, in the supplicant's idr_s.
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to the shm with the specified id or NULL.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct optee_shm *optee_supplicant_search_shm(uint32_t id)
|
||||
{
|
||||
return idr_find(g_optee_supp.shm_idr, id);
|
||||
}
|
||||
69
drivers/misc/optee_supplicant.h
Normal file
69
drivers/misc/optee_supplicant.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/****************************************************************************
|
||||
* drivers/misc/optee_supplicant.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_MISC_OPTEE_SUPPLICANT_H
|
||||
#define __DRIVERS_MISC_OPTEE_SUPPLICANT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "optee.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
void optee_supplicant_init(FAR struct idr_s **shm_idr);
|
||||
void optee_supplicant_uninit(void);
|
||||
|
||||
FAR struct optee_shm *optee_supplicant_search_shm(uint32_t id);
|
||||
|
||||
uint32_t optee_supplicant_free(int32_t shm_id);
|
||||
int optee_supplicant_alloc(FAR struct optee_priv_data *priv,
|
||||
size_t sz, FAR struct optee_shm **shm);
|
||||
|
||||
void optee_supplicant_cmd(FAR struct optee_priv_data *priv,
|
||||
FAR struct optee_msg_arg *arg);
|
||||
|
||||
int optee_supplicant_send(uint32_t ret, uint32_t num_params,
|
||||
FAR struct tee_ioctl_param *param);
|
||||
|
||||
int optee_supplicant_recv(FAR uint32_t *func, FAR uint32_t *num_params,
|
||||
FAR struct tee_ioctl_param *params);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* __DRIVERS_MISC_OPTEE_SUPPLICANT_H */
|
||||
|
|
@ -383,6 +383,7 @@ struct tee_iocl_supp_send_arg
|
|||
#define TEE_SHM_ALLOC (1 << 0) /* Kernel-malloced and must freed */
|
||||
#define TEE_SHM_REGISTER (1 << 1) /* Registered with TEE OS */
|
||||
#define TEE_SHM_USER_MAP (1 << 2) /* Will be used by userspace after mmap */
|
||||
#define TEE_SHM_SUPP (1 << 4) /* Registered by supplicant */
|
||||
|
||||
/* struct tee_ioctl_shm_register_data - Shared memory register argument
|
||||
* addr: [in] Start address of shared memory to register
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue