mirror of
https://github.com/apache/nuttx.git
synced 2026-08-18 10:07:28 +08:00
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:
committed by
Xiang Xiao
parent
95ca3e7ca5
commit
707cdaf42e
@@ -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
|
||||
|
||||
+458
-182
File diff suppressed because it is too large
Load Diff
+36
-1
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user