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:
Theodore Karatapanis
2025-08-06 02:29:33 +08:00
committed by Xiang Xiao
parent 95ca3e7ca5
commit 707cdaf42e
13 changed files with 1819 additions and 195 deletions
+73 -10
View File
@@ -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.
+4
View File
@@ -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()
+5
View File
@@ -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
+4
View File
@@ -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
+458 -182
View File
File diff suppressed because it is too large Load Diff
+36 -1
View File
@@ -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)
}
+134
View File
@@ -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
View 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
View 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 */
+12 -2
View File
@@ -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;
}
}
File diff suppressed because it is too large Load Diff
+69
View 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 */
+1
View File
@@ -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