driver/tee: add optee client driver module
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 nttux. The basic function of the driver module is to convert the REE application layer data and send it to the TEE through rpmsg. The main functions include 1 driver registration. we need to register a device driver(/dev/tee0) through optee_register function. 2 open the driver 3 ioctl the driver The ioctl command passes different parameters and commands, and interacts with the TEE through rpmsg. 4 close the driver Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
ed877fd494
commit
0c2cfc767d
@ -47,6 +47,7 @@
|
||||
#include <nuttx/trace.h>
|
||||
#include <nuttx/usrsock/usrsock_rpmsg.h>
|
||||
#include <nuttx/virtio/virtio.h>
|
||||
#include <nuttx/drivers/optee.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -217,5 +218,9 @@ void drivers_initialize(void)
|
||||
virtio_register_drivers();
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DEV_OPTEE_NONE
|
||||
optee_register();
|
||||
#endif
|
||||
|
||||
drivers_trace_end();
|
||||
}
|
||||
|
@ -32,6 +32,28 @@ config DEV_RPMSG_SERVER
|
||||
default n
|
||||
depends on RPTUN
|
||||
|
||||
choice
|
||||
prompt "Select optee dev implementation"
|
||||
default DEV_OPTEE_NONE
|
||||
|
||||
config DEV_OPTEE_LOCAL
|
||||
bool "OPTEE Local Socket Support"
|
||||
depends on NET_LOCAL
|
||||
|
||||
config DEV_OPTEE_RPMSG
|
||||
bool "OPTEE RPMSG Socket Support"
|
||||
depends on NET_RPMSG
|
||||
|
||||
config DEV_OPTEE_NONE
|
||||
bool "Disable optee driver"
|
||||
|
||||
endchoice
|
||||
|
||||
config OPTEE_REMOTE_CPU_NAME
|
||||
string "The cpuname on which the optee server runs"
|
||||
default "tee"
|
||||
depends on DEV_OPTEE_RPMSG
|
||||
|
||||
config DRVR_MKRD
|
||||
bool "RAM disk wrapper (mkrd)"
|
||||
default n
|
||||
|
@ -68,6 +68,10 @@ ifeq ($(CONFIG_BLK_RPMSG_SERVER),y)
|
||||
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)fs$(DELIM)inode
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_DEV_OPTEE_NONE),y)
|
||||
CSRCS += optee.c
|
||||
endif
|
||||
|
||||
# Include build support
|
||||
|
||||
DEPPATH += --dep-path misc
|
||||
|
648
drivers/misc/optee.c
Normal file
648
drivers/misc/optee.c
Normal file
@ -0,0 +1,648 @@
|
||||
/****************************************************************************
|
||||
* drivers/misc/optee.c
|
||||
*
|
||||
* 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/tee.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <netpacket/rpmsg.h>
|
||||
#include <nuttx/drivers/optee.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "optee_msg.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Some GlobalPlatform error codes used in this driver */
|
||||
|
||||
#define TEE_SUCCESS 0x00000000
|
||||
#define TEE_ERROR_BAD_PARAMETERS 0xFFFF0006
|
||||
#define TEE_ERROR_NOT_SUPPORTED 0xFFFF000A
|
||||
#define TEE_ERROR_COMMUNICATION 0xFFFF000E
|
||||
#define TEE_ERROR_OUT_OF_MEMORY 0xFFFF000C
|
||||
#define TEE_ERROR_BUSY 0xFFFF000D
|
||||
#define TEE_ERROR_SHORT_BUFFER 0xFFFF0010
|
||||
|
||||
#define TEE_ORIGIN_COMMS 0x00000002
|
||||
|
||||
#define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_ioctl_param) * (x))
|
||||
|
||||
#define OPTEE_MAX_IOVEC_NUM 7
|
||||
#define OPTEE_MAX_PARAM_NUM 6
|
||||
|
||||
#define OPTEE_SERVER_PATH "optee"
|
||||
#define OPTEE_DEV_PATH "/dev/tee0"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* The file operation functions */
|
||||
|
||||
static int optee_open(FAR struct file *filep);
|
||||
static int optee_close(FAR struct file *filep);
|
||||
static int optee_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* File operations */
|
||||
|
||||
static const struct file_operations g_optee_ops =
|
||||
{
|
||||
optee_open, /* open */
|
||||
optee_close, /* close */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
NULL, /* seek */
|
||||
optee_ioctl, /* ioctl */
|
||||
NULL, /* mmap */
|
||||
NULL, /* truncate */
|
||||
NULL /* poll */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_open
|
||||
*
|
||||
* Description:
|
||||
* optee open operation
|
||||
*
|
||||
* Parameters:
|
||||
* filep - the file instance
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int optee_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
#ifdef CONFIG_DEV_OPTEE_LOCAL
|
||||
struct sockaddr_un addr;
|
||||
#else
|
||||
struct sockaddr_rpmsg addr;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
psock = (FAR struct socket *)kmm_zalloc(sizeof(struct socket));
|
||||
if (psock == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEV_OPTEE_LOCAL
|
||||
ret = psock_socket(AF_UNIX, SOCK_STREAM, 0, psock);
|
||||
#else
|
||||
ret = psock_socket(AF_RPMSG, SOCK_STREAM, 0, psock);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
{
|
||||
kmm_free(psock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
#ifdef CONFIG_DEV_OPTEE_LOCAL
|
||||
addr.sun_family = AF_UNIX;
|
||||
strlcpy(addr.sun_path, OPTEE_SERVER_PATH, sizeof(addr.sun_path));
|
||||
#else
|
||||
addr.rp_family = AF_RPMSG;
|
||||
strlcpy(addr.rp_name, OPTEE_SERVER_PATH, sizeof(addr.rp_name));
|
||||
strlcpy(addr.rp_cpu, CONFIG_OPTEE_REMOTE_CPU_NAME, sizeof(addr.rp_cpu));
|
||||
#endif
|
||||
|
||||
ret = psock_connect(psock, (FAR const struct sockaddr *)&addr,
|
||||
sizeof(addr));
|
||||
if (ret < 0)
|
||||
{
|
||||
psock_close(psock);
|
||||
kmm_free(psock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
filep->f_priv = psock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_close
|
||||
*
|
||||
* Description:
|
||||
* optee close operation
|
||||
*
|
||||
* Parameters:
|
||||
* filep - the file instance
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int optee_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct socket *psock = filep->f_priv;
|
||||
|
||||
psock_close(psock);
|
||||
kmm_free(psock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int optee_to_msg_param(FAR struct optee_msg_param *mparams,
|
||||
size_t num_params,
|
||||
FAR const struct tee_ioctl_param *params)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
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:
|
||||
mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
|
||||
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
|
||||
if (p->c != TEE_MEMREF_NULL)
|
||||
{
|
||||
mp->u.rmem.shm_ref = p->c;
|
||||
}
|
||||
else
|
||||
{
|
||||
mp->u.rmem.shm_ref = 0;
|
||||
}
|
||||
|
||||
mp->u.rmem.size = p->b;
|
||||
mp->u.rmem.offs = p->a;
|
||||
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;
|
||||
|
||||
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_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;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t optee_recv(FAR struct socket *psock, FAR void *msg,
|
||||
size_t size)
|
||||
{
|
||||
size_t remain = size;
|
||||
|
||||
while (remain)
|
||||
{
|
||||
ssize_t n = psock_recv(psock, msg, remain, 0);
|
||||
if (n <= 0)
|
||||
{
|
||||
return remain == size ? n : size - remain;
|
||||
}
|
||||
|
||||
remain -= n;
|
||||
msg = (FAR char *)msg + n;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int optee_send_recv(FAR struct socket *psocket,
|
||||
FAR struct optee_msg_arg *arg)
|
||||
{
|
||||
/* iov[0]: struct opteee_msg_arg + struct optee_msg_param[n]
|
||||
* iov[1 - n+1]: shm_mem
|
||||
* 0 <= n <= 6
|
||||
*/
|
||||
|
||||
size_t arg_size = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
|
||||
size_t shm_size[OPTEE_MAX_PARAM_NUM];
|
||||
size_t shm_addr[OPTEE_MAX_PARAM_NUM];
|
||||
struct iovec iov[OPTEE_MAX_IOVEC_NUM];
|
||||
struct msghdr msghdr;
|
||||
unsigned long iovlen = 1;
|
||||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
memset(iov, 0, sizeof(iov));
|
||||
memset(shm_size, 0, sizeof(shm_size));
|
||||
|
||||
iov[0].iov_base = arg;
|
||||
iov[0].iov_len = arg_size;
|
||||
|
||||
for (i = 0; i < arg->num_params; i++)
|
||||
{
|
||||
if (arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
|
||||
arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_INOUT)
|
||||
{
|
||||
iov[iovlen].iov_base =
|
||||
(FAR void *)(uintptr_t)arg->params[i].u.rmem.shm_ref;
|
||||
iov[iovlen].iov_len = arg->params[i].u.rmem.size;
|
||||
shm_size[i] = arg->params[i].u.rmem.size;
|
||||
shm_addr[i] = arg->params[i].u.rmem.shm_ref;
|
||||
iovlen++;
|
||||
}
|
||||
else if (arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT)
|
||||
{
|
||||
shm_size[i] = arg->params[i].u.rmem.size;
|
||||
shm_addr[i] = arg->params[i].u.rmem.shm_ref;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&msghdr, 0, sizeof(struct msghdr));
|
||||
msghdr.msg_iov = iov;
|
||||
msghdr.msg_iovlen = iovlen;
|
||||
|
||||
ret = psock_sendmsg(psocket, &msghdr, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = optee_recv(psocket, arg, arg_size);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < arg->num_params; i++)
|
||||
{
|
||||
if (arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT ||
|
||||
arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_INOUT)
|
||||
{
|
||||
size_t size = MIN(arg->params[i].u.rmem.size, shm_size[i]);
|
||||
arg->params[i].u.rmem.shm_ref = shm_addr[i];
|
||||
ret = optee_recv(psocket,
|
||||
(FAR void *)(uintptr_t)
|
||||
arg->params[i].u.rmem.shm_ref, size);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int optee_ioctl_open_session(FAR struct socket *psocket,
|
||||
FAR struct tee_ioctl_buf_data *buf)
|
||||
{
|
||||
char msg_buf[OPTEE_MSG_GET_ARG_SIZE(OPTEE_MAX_PARAM_NUM)];
|
||||
FAR struct tee_ioctl_open_session_arg *arg;
|
||||
FAR struct optee_msg_arg *msg;
|
||||
int ret;
|
||||
|
||||
if (buf->buf_len > TEE_MAX_ARG_SIZE ||
|
||||
buf->buf_len < sizeof(struct tee_ioctl_open_session_arg))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arg = (FAR struct tee_ioctl_open_session_arg *)(uintptr_t)buf->buf_ptr;
|
||||
|
||||
if (sizeof(*arg) + TEE_IOCTL_PARAM_SIZE(arg->num_params) !=
|
||||
buf->buf_len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->num_params + 2 > OPTEE_MAX_PARAM_NUM)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->clnt_login >= TEE_IOCTL_LOGIN_REE_KERNEL_MIN &&
|
||||
arg->clnt_login <= TEE_IOCTL_LOGIN_REE_KERNEL_MAX)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
arg->ret = TEE_ERROR_COMMUNICATION;
|
||||
arg->ret_origin = TEE_ORIGIN_COMMS;
|
||||
|
||||
memset(msg_buf, 0, sizeof(msg_buf));
|
||||
msg = (FAR struct optee_msg_arg *)&msg_buf[0];
|
||||
|
||||
msg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
|
||||
msg->cancel_id = arg->cancel_id;
|
||||
msg->num_params = arg->num_params + 2;
|
||||
|
||||
/* Initialize and add the meta parameters needed when opening a
|
||||
* session.
|
||||
*/
|
||||
|
||||
msg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
|
||||
OPTEE_MSG_ATTR_META;
|
||||
msg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
|
||||
OPTEE_MSG_ATTR_META;
|
||||
memcpy(&msg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
|
||||
msg->params[1].u.value.c = arg->clnt_login;
|
||||
|
||||
ret = optee_to_msg_param(msg->params + 2, arg->num_params, arg->params);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = optee_send_recv(psocket, msg);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = optee_from_msg_param(arg->params, arg->num_params,
|
||||
msg->params + 2);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
arg->session = msg->session;
|
||||
arg->ret = msg->ret;
|
||||
arg->ret_origin = msg->ret_origin;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int optee_ioctl_invoke(FAR struct socket *psocket,
|
||||
FAR struct tee_ioctl_buf_data *buf)
|
||||
{
|
||||
char msg_buf[OPTEE_MSG_GET_ARG_SIZE(OPTEE_MAX_PARAM_NUM)];
|
||||
FAR struct tee_ioctl_invoke_arg *arg;
|
||||
FAR struct optee_msg_arg *msg;
|
||||
int ret;
|
||||
|
||||
if (buf->buf_len > TEE_MAX_ARG_SIZE ||
|
||||
buf->buf_len < sizeof(struct tee_ioctl_invoke_arg))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arg = (FAR struct tee_ioctl_invoke_arg *)(uintptr_t)buf->buf_ptr;
|
||||
|
||||
if (sizeof(*arg) + TEE_IOCTL_PARAM_SIZE(arg->num_params) !=
|
||||
buf->buf_len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->num_params > OPTEE_MAX_PARAM_NUM)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arg->ret = TEE_ERROR_COMMUNICATION;
|
||||
arg->ret_origin = TEE_ORIGIN_COMMS;
|
||||
|
||||
memset(msg_buf, 0, sizeof(msg_buf));
|
||||
msg = (FAR struct optee_msg_arg *)&msg_buf[0];
|
||||
|
||||
msg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
|
||||
msg->func = arg->func;
|
||||
msg->session = arg->session;
|
||||
msg->cancel_id = arg->cancel_id;
|
||||
msg->num_params = arg->num_params;
|
||||
|
||||
ret = optee_to_msg_param(msg->params, arg->num_params, arg->params);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = optee_send_recv(psocket, msg);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = optee_from_msg_param(arg->params, arg->num_params, msg->params);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
arg->ret = msg->ret;
|
||||
arg->ret_origin = msg->ret_origin;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
optee_ioctl_close_session(FAR struct socket *psocket,
|
||||
FAR struct tee_ioctl_close_session_arg *arg)
|
||||
{
|
||||
struct optee_msg_arg msg;
|
||||
|
||||
memset(&msg, 0, sizeof(struct optee_msg_arg));
|
||||
msg.cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
|
||||
msg.session = arg->session;
|
||||
msg.num_params = 0;
|
||||
|
||||
return optee_send_recv(psocket, &msg);
|
||||
}
|
||||
|
||||
static int optee_ioctl_version(FAR struct tee_ioctl_version_data *vers)
|
||||
{
|
||||
vers->impl_id = TEE_IMPL_ID_OPTEE;
|
||||
vers->impl_caps = TEE_OPTEE_CAP_TZ;
|
||||
vers->gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_MEMREF_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int optee_ioctl_cancel(FAR struct socket *psocket,
|
||||
FAR struct tee_ioctl_cancel_arg *arg)
|
||||
{
|
||||
struct optee_msg_arg msg;
|
||||
|
||||
memset(&msg, 0, sizeof(struct optee_msg_arg));
|
||||
msg.cmd = OPTEE_MSG_CMD_CANCEL;
|
||||
msg.session = arg->session;
|
||||
msg.cancel_id = arg->cancel_id;
|
||||
return optee_send_recv(psocket, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
optee_ioctl_shm_alloc(FAR struct tee_ioctl_shm_alloc_data *data)
|
||||
{
|
||||
int memfd = memfd_create(OPTEE_SERVER_PATH, O_CREAT);
|
||||
|
||||
if (memfd < 0)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ftruncate(memfd, data->size) < 0)
|
||||
{
|
||||
close(memfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
data->id = (uintptr_t)mmap(NULL, data->size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, memfd, 0);
|
||||
if (data->id == (uintptr_t)MAP_FAILED)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return memfd;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_ioctl
|
||||
*
|
||||
* Description:
|
||||
* optee ioctl operation
|
||||
*
|
||||
* Parameters:
|
||||
* filep - the file instance
|
||||
* cmd - the ioctl command
|
||||
* arg - the ioctl arguments
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int optee_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct socket *psock = filep->f_priv;
|
||||
FAR void *parg = (FAR void *)arg;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case TEE_IOC_VERSION:
|
||||
return optee_ioctl_version(parg);
|
||||
case TEE_IOC_OPEN_SESSION:
|
||||
return optee_ioctl_open_session(psock, parg);
|
||||
case TEE_IOC_INVOKE:
|
||||
return optee_ioctl_invoke(psock, parg);
|
||||
case TEE_IOC_CLOSE_SESSION:
|
||||
return optee_ioctl_close_session(psock, parg);
|
||||
case TEE_IOC_CANCEL:
|
||||
return optee_ioctl_cancel(psock, parg);
|
||||
case TEE_IOC_SHM_ALLOC:
|
||||
return optee_ioctl_shm_alloc(parg);
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_register
|
||||
*
|
||||
* Description:
|
||||
* optee client initialize function, the client cpu should call
|
||||
* this function in the board initialize process.
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int optee_register(void)
|
||||
{
|
||||
return register_driver(OPTEE_DEV_PATH, &g_optee_ops, 0666, NULL);
|
||||
}
|
365
drivers/misc/optee_msg.h
Normal file
365
drivers/misc/optee_msg.h
Normal file
@ -0,0 +1,365 @@
|
||||
/****************************************************************************
|
||||
* drivers/misc/optee_msg.h
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright (c) 2015-2020, Linaro Limited
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_MISC_OPTEE_MSG_H
|
||||
#define __DRIVERS_MISC_OPTEE_MSG_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <nuttx/bits.h>
|
||||
|
||||
/**
|
||||
* This file defines the OP-TEE message protocol (ABI) used to communicate
|
||||
* with an instance of OP-TEE running in secure world.
|
||||
*
|
||||
* This file is divided into two sections.
|
||||
* 1. Formatting of messages.
|
||||
* 2. Requests from normal world
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Part 1 - formatting of messages
|
||||
****************************************************************************/
|
||||
|
||||
#define OPTEE_MSG_ATTR_TYPE_NONE 0x0
|
||||
#define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT 0x1
|
||||
#define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT 0x2
|
||||
#define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT 0x3
|
||||
#define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5
|
||||
#define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6
|
||||
#define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7
|
||||
#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
|
||||
#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
|
||||
#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
|
||||
#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9
|
||||
#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa
|
||||
#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb
|
||||
|
||||
#define OPTEE_MSG_ATTR_TYPE_MASK GENMASK(7, 0)
|
||||
|
||||
/**
|
||||
* Meta parameter to be absorbed by the Secure OS and not passed
|
||||
* to the Trusted Application.
|
||||
*
|
||||
* Currently only used with OPTEE_MSG_CMD_OPEN_SESSION.
|
||||
*/
|
||||
#define OPTEE_MSG_ATTR_META BIT(8)
|
||||
|
||||
/**
|
||||
* Pointer to a list of pages used to register user-defined SHM buffer.
|
||||
* Used with OPTEE_MSG_ATTR_TYPE_TMEM_*.
|
||||
* buf_ptr should point to the beginning of the buffer. Buffer will contain
|
||||
* list of page addresses. OP-TEE core can reconstruct contiguous buffer from
|
||||
* that page addresses list. Page addresses are stored as 64 bit values.
|
||||
* Last entry on a page should point to the next page of buffer.
|
||||
* Every entry in buffer should point to a 4k page beginning (12 least
|
||||
* significant bits must be equal to zero).
|
||||
*
|
||||
* 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold
|
||||
* page offset of user buffer.
|
||||
*
|
||||
* So, entries should be placed like members of this structure:
|
||||
*
|
||||
* struct page_data {
|
||||
* uint64_t pages_array[
|
||||
* OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1];
|
||||
* uint64_t next_page_data;
|
||||
* };
|
||||
*
|
||||
* Structure is designed to exactly fit into the page size
|
||||
* OPTEE_MSG_NONCONTIG_PAGE_SIZE which is a standard 4KB page.
|
||||
*
|
||||
* The size of 4KB is chosen because this is the smallest page size for ARM
|
||||
* architectures. If REE uses larger pages, it should divide them to 4KB
|
||||
* ones.
|
||||
*/
|
||||
#define OPTEE_MSG_ATTR_NONCONTIG BIT(9)
|
||||
|
||||
/**
|
||||
* Memory attributes for caching passed with temp memrefs. The actual value
|
||||
* used is defined outside the message protocol with the exception of
|
||||
* OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already
|
||||
* defined for the memory range should be used. If optee_smc.h is used as
|
||||
* bearer of this protocol OPTEE_SMC_SHM_* is used for values.
|
||||
*/
|
||||
#define OPTEE_MSG_ATTR_CACHE_SHIFT 16
|
||||
#define OPTEE_MSG_ATTR_CACHE_MASK GENMASK(2, 0)
|
||||
#define OPTEE_MSG_ATTR_CACHE_PREDEFINED 0
|
||||
|
||||
/**
|
||||
* Same values as TEE_LOGIN_* from TEE Internal API
|
||||
*/
|
||||
#define OPTEE_MSG_LOGIN_PUBLIC 0x00000000
|
||||
#define OPTEE_MSG_LOGIN_USER 0x00000001
|
||||
#define OPTEE_MSG_LOGIN_GROUP 0x00000002
|
||||
#define OPTEE_MSG_LOGIN_APPLICATION 0x00000004
|
||||
#define OPTEE_MSG_LOGIN_APPLICATION_USER 0x00000005
|
||||
#define OPTEE_MSG_LOGIN_APPLICATION_GROUP 0x00000006
|
||||
|
||||
/**
|
||||
* Page size used in non-contiguous buffer entries
|
||||
*/
|
||||
#define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096
|
||||
|
||||
#define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff
|
||||
|
||||
/**
|
||||
* struct optee_msg_param_tmem - temporary memory reference parameter
|
||||
* @buf_ptr: Address of the buffer
|
||||
* @size: Size of the buffer
|
||||
* @shm_ref: Temporary shared memory reference, pointer to a struct
|
||||
* tee_shm
|
||||
*
|
||||
* Secure and normal world communicates pointers as physical address
|
||||
* instead of the virtual address. This is because secure and normal world
|
||||
* have completely independent memory mapping. Normal world can even have a
|
||||
* hypervisor which need to translate the guest physical address (AKA IPA
|
||||
* in ARM documentation) to a real physical address before passing the
|
||||
* structure to secure world.
|
||||
*/
|
||||
|
||||
struct optee_msg_param_tmem
|
||||
{
|
||||
uint64_t buf_ptr;
|
||||
uint64_t size;
|
||||
uint64_t shm_ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct optee_msg_param_rmem - registered memory reference parameter
|
||||
* @offs: Offset into shared memory reference
|
||||
* @size: Size of the buffer
|
||||
* @shm_ref: Shared memory reference, pointer to a struct tee_shm
|
||||
*/
|
||||
|
||||
struct optee_msg_param_rmem
|
||||
{
|
||||
uint64_t offs;
|
||||
uint64_t size;
|
||||
uint64_t shm_ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct optee_msg_param_fmem - ffa memory reference parameter
|
||||
* @offs_lower: Lower bits of offset into shared memory reference
|
||||
* @offs_upper: Upper bits of offset into shared memory reference
|
||||
* @internal_offs: Internal offset into the first page of shared memory
|
||||
* reference
|
||||
* @size: Size of the buffer
|
||||
* @global_id: Global identifier of Shared memory
|
||||
*/
|
||||
|
||||
struct optee_msg_param_fmem
|
||||
{
|
||||
uint32_t offs_low;
|
||||
uint16_t offs_high;
|
||||
uint16_t internal_offs;
|
||||
uint64_t size;
|
||||
uint64_t global_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct optee_msg_param_value - opaque value parameter
|
||||
*
|
||||
* Value parameters are passed unchecked between normal and secure world.
|
||||
*/
|
||||
|
||||
struct optee_msg_param_value
|
||||
{
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
uint64_t c;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct optee_msg_param - parameter used together with struct optee_msg_arg
|
||||
* @attr: attributes
|
||||
* @tmem: parameter by temporary memory reference
|
||||
* @rmem: parameter by registered memory reference
|
||||
* @fmem: parameter by ffa registered memory reference
|
||||
* @value: parameter by opaque value
|
||||
* @octets: parameter by octet string
|
||||
*
|
||||
* @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used
|
||||
* in the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value or octets,
|
||||
* OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
|
||||
* OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_*
|
||||
* indicates @rmem or @fmem depending on the conduit.
|
||||
* OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
|
||||
*/
|
||||
|
||||
struct optee_msg_param
|
||||
{
|
||||
uint64_t attr;
|
||||
union
|
||||
{
|
||||
struct optee_msg_param_tmem tmem;
|
||||
struct optee_msg_param_rmem rmem;
|
||||
struct optee_msg_param_fmem fmem;
|
||||
struct optee_msg_param_value value;
|
||||
uint8_t octets[24];
|
||||
} u;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct optee_msg_arg - call argument
|
||||
* @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_*
|
||||
* @func: Trusted Application function, specific to the Trusted Application,
|
||||
* used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND
|
||||
* @session: In parameter for all OPTEE_MSG_CMD_* except
|
||||
* OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter
|
||||
* instead
|
||||
* @cancel_id: Cancellation id, a unique value to identify this request
|
||||
* @ret: return value
|
||||
* @ret_origin: origin of the return value
|
||||
* @num_params: number of parameters supplied to the OS Command
|
||||
* @params: the parameters supplied to the OS Command
|
||||
*
|
||||
* All normal calls to Trusted OS uses this struct. If cmd requires further
|
||||
* information than what these fields hold it can be passed as a parameter
|
||||
* tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
|
||||
* attrs field). All parameters tagged as meta have to come first.
|
||||
*/
|
||||
|
||||
struct optee_msg_arg
|
||||
{
|
||||
uint32_t cmd;
|
||||
uint32_t func;
|
||||
uint32_t session;
|
||||
uint32_t cancel_id;
|
||||
uint32_t pad;
|
||||
uint32_t ret;
|
||||
uint32_t ret_origin;
|
||||
uint32_t num_params;
|
||||
|
||||
/* num_params tells the actual number of element in params */
|
||||
|
||||
struct optee_msg_param params[];
|
||||
};
|
||||
|
||||
/**
|
||||
* OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg
|
||||
*
|
||||
* @num_params: Number of parameters embedded in the struct optee_msg_arg
|
||||
*
|
||||
* Returns the size of the struct optee_msg_arg together with the number
|
||||
* of embedded parameters.
|
||||
*/
|
||||
#define OPTEE_MSG_GET_ARG_SIZE(num_params) \
|
||||
(sizeof(struct optee_msg_arg) + \
|
||||
sizeof(struct optee_msg_param) * (num_params))
|
||||
|
||||
/****************************************************************************
|
||||
* Part 2 - requests from normal world
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return the following UID if using API specified in this file without
|
||||
* further extensions:
|
||||
* 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
|
||||
* Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1,
|
||||
* OPTEE_MSG_UID_2, OPTEE_MSG_UID_3.
|
||||
*/
|
||||
#define OPTEE_MSG_UID_0 0x384fb3e0
|
||||
#define OPTEE_MSG_UID_1 0xe7f811e3
|
||||
#define OPTEE_MSG_UID_2 0xaf630002
|
||||
#define OPTEE_MSG_UID_3 0xa5d5c51b
|
||||
#define OPTEE_MSG_FUNCID_CALLS_UID 0xFF01
|
||||
|
||||
/**
|
||||
* Returns 2.0 if using API specified in this file without further
|
||||
* extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR
|
||||
* and OPTEE_MSG_REVISION_MINOR
|
||||
*/
|
||||
#define OPTEE_MSG_REVISION_MAJOR 2
|
||||
#define OPTEE_MSG_REVISION_MINOR 0
|
||||
#define OPTEE_MSG_FUNCID_CALLS_REVISION 0xFF03
|
||||
|
||||
/**
|
||||
* Get UUID of Trusted OS.
|
||||
*
|
||||
* Used by non-secure world to figure out which Trusted OS is installed.
|
||||
* Note that returned UUID is the UUID of the Trusted OS, not of the API.
|
||||
*
|
||||
* Returns UUID in 4 32-bit words in the same way as
|
||||
* OPTEE_MSG_FUNCID_CALLS_UID described above.
|
||||
*/
|
||||
#define OPTEE_MSG_OS_OPTEE_UUID_0 0x486178e0
|
||||
#define OPTEE_MSG_OS_OPTEE_UUID_1 0xe7f811e3
|
||||
#define OPTEE_MSG_OS_OPTEE_UUID_2 0xbc5e0002
|
||||
#define OPTEE_MSG_OS_OPTEE_UUID_3 0xa5d5c51b
|
||||
#define OPTEE_MSG_FUNCID_GET_OS_UUID 0x0000
|
||||
|
||||
/**
|
||||
* Get revision of Trusted OS.
|
||||
*
|
||||
* Used by non-secure world to figure out which version of the Trusted OS
|
||||
* is installed. Note that the returned revision is the revision of the
|
||||
* Trusted OS, not of the API.
|
||||
*
|
||||
* Returns revision in 2 32-bit words in the same way as
|
||||
* OPTEE_MSG_CALLS_REVISION described above.
|
||||
*/
|
||||
#define OPTEE_MSG_FUNCID_GET_OS_REVISION 0x0001
|
||||
|
||||
/**
|
||||
* Do a secure call with struct optee_msg_arg as argument
|
||||
* The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd
|
||||
*
|
||||
* OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application.
|
||||
* The first two parameters are tagged as meta, holding two value
|
||||
* parameters to pass the following information:
|
||||
* param[0].u.value.a-b uuid of Trusted Application
|
||||
* param[1].u.value.a-b uuid of Client
|
||||
* param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_*
|
||||
*
|
||||
* OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened
|
||||
* session to a Trusted Application. struct optee_msg_arg::func is Trusted
|
||||
* Application function, specific to the Trusted Application.
|
||||
*
|
||||
* OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to
|
||||
* Trusted Application.
|
||||
*
|
||||
* OPTEE_MSG_CMD_CANCEL cancels a currently invoked command.
|
||||
*
|
||||
* OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
|
||||
* information is passed as:
|
||||
* [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
|
||||
* [| OPTEE_MSG_ATTR_NONCONTIG]
|
||||
* [in] param[0].u.tmem.buf_ptr physical address (of first fragment)
|
||||
* [in] param[0].u.tmem.size size (of first fragment)
|
||||
* [in] param[0].u.tmem.shm_ref holds shared memory reference
|
||||
*
|
||||
* OPTEE_MSG_CMD_UNREGISTER_SHM unregisters a previously registered shared
|
||||
* memory reference. The information is passed as:
|
||||
* [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
|
||||
* [in] param[0].u.rmem.shm_ref holds shared memory reference
|
||||
* [in] param[0].u.rmem.offs 0
|
||||
* [in] param[0].u.rmem.size 0
|
||||
*
|
||||
* OPTEE_MSG_CMD_DO_BOTTOM_HALF does the scheduled bottom half processing
|
||||
* of a driver.
|
||||
*
|
||||
* OPTEE_MSG_CMD_STOP_ASYNC_NOTIF informs secure world that from now is
|
||||
* normal world unable to process asynchronous notifications. Typically
|
||||
* used when the driver is shut down.
|
||||
*/
|
||||
#define OPTEE_MSG_CMD_OPEN_SESSION 0
|
||||
#define OPTEE_MSG_CMD_INVOKE_COMMAND 1
|
||||
#define OPTEE_MSG_CMD_CLOSE_SESSION 2
|
||||
#define OPTEE_MSG_CMD_CANCEL 3
|
||||
#define OPTEE_MSG_CMD_REGISTER_SHM 4
|
||||
#define OPTEE_MSG_CMD_UNREGISTER_SHM 5
|
||||
#define OPTEE_MSG_CMD_DO_BOTTOM_HALF 6
|
||||
#define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF 7
|
||||
#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
|
||||
|
||||
#endif /* __DRIVERS_MISC_OPTEE_MSG_H */
|
66
include/nuttx/drivers/optee.h
Normal file
66
include/nuttx/drivers/optee.h
Normal file
@ -0,0 +1,66 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/drivers/optee.h
|
||||
*
|
||||
* 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 __INCLUDE_NUTTX_DRIVERS_OPTEE_H
|
||||
#define __INCLUDE_NUTTX_DRIVERS_OPTEE_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: optee_register
|
||||
*
|
||||
* Description:
|
||||
* optee-device client initialize function
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DEV_OPTEE_NONE
|
||||
int optee_register(void);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_DRIVERS_OPTEE_H */
|
479
include/nuttx/tee.h
Normal file
479
include/nuttx/tee.h
Normal file
@ -0,0 +1,479 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/tee.h
|
||||
*
|
||||
* Copyright (c) 2015-2016, Linaro Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_TEE_H
|
||||
#define __INCLUDE_NUTTX_TEE_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* This file describes the API provided by a TEE driver to user space.
|
||||
*
|
||||
* Each TEE driver defines a TEE specific protocol which is used for the
|
||||
* data passed back and forth using TEE_IOC_CMD.
|
||||
*/
|
||||
|
||||
/* Helpers to make the ioctl defines */
|
||||
|
||||
#define TEE_IOC_MAGIC 0xa4
|
||||
#define TEE_IOC_BASE 0
|
||||
|
||||
#define TEE_MAX_ARG_SIZE 1024
|
||||
|
||||
#define TEE_GEN_CAP_GP (1 << 0) /* GlobalPlatform compliant TEE */
|
||||
#define TEE_GEN_CAP_PRIVILEGED (1 << 1) /* Privileged device (for supplicant) */
|
||||
#define TEE_GEN_CAP_REG_MEM (1 << 2) /* Supports registering shared memory */
|
||||
#define TEE_GEN_CAP_MEMREF_NULL (1 << 3) /* NULL MemRef support */
|
||||
|
||||
#define TEE_MEMREF_NULL ((uint64_t)-1) /* NULL MemRef Buffer */
|
||||
|
||||
/**
|
||||
* TEE Implementation ID
|
||||
*/
|
||||
|
||||
#define TEE_IMPL_ID_OPTEE 1
|
||||
#define TEE_IMPL_ID_AMDTEE 2
|
||||
|
||||
/**
|
||||
* OP-TEE specific capabilities
|
||||
*/
|
||||
|
||||
#define TEE_OPTEE_CAP_TZ (1 << 0)
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_version_data - TEE version
|
||||
* @impl_id: [out] TEE implementation id
|
||||
* @impl_caps: [out] Implementation specific capabilities
|
||||
* @gen_caps: [out] Generic capabilities, defined by TEE_GEN_CAPS_* above
|
||||
*
|
||||
* Identifies the TEE implementation, @impl_id is one of TEE_IMPL_ID_* above.
|
||||
* @impl_caps is implementation specific, for example TEE_OPTEE_CAP_*
|
||||
* is valid when @impl_id == TEE_IMPL_ID_OPTEE.
|
||||
*/
|
||||
|
||||
struct tee_ioctl_version_data
|
||||
{
|
||||
uint32_t impl_id;
|
||||
uint32_t impl_caps;
|
||||
uint32_t gen_caps;
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_VERSION - query version of TEE
|
||||
*
|
||||
* Takes a tee_ioctl_version_data struct and returns with the TEE version
|
||||
* data filled in.
|
||||
*/
|
||||
#define TEE_IOC_VERSION _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 0)
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_shm_alloc_data - Shared memory allocate argument
|
||||
* @size: [in/out] Size of shared memory to allocate
|
||||
* @flags: [in/out] Flags to/from allocation.
|
||||
* @id: [out] Identifier of the shared memory
|
||||
*
|
||||
* The flags field should currently be zero as input. Updated by the call
|
||||
* with actual flags as defined by TEE_IOCTL_SHM_* above.
|
||||
* This structure is used as argument for TEE_IOC_SHM_ALLOC below.
|
||||
*/
|
||||
|
||||
struct tee_ioctl_shm_alloc_data
|
||||
{
|
||||
uint64_t size;
|
||||
uint32_t flags;
|
||||
int32_t id;
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_SHM_ALLOC - allocate shared memory
|
||||
*
|
||||
* Allocates shared memory between the user space process and secure OS.
|
||||
*
|
||||
* Returns a file descriptor on success or < 0 on failure
|
||||
*
|
||||
* The returned file descriptor is used to map the shared memory into user
|
||||
* space. The shared memory is freed when the descriptor is closed and the
|
||||
* memory is unmapped.
|
||||
*/
|
||||
|
||||
#define TEE_IOC_SHM_ALLOC _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 1)
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_shm_register_fd_data - Shared memory registering argument
|
||||
* @fd: [in] file descriptor identifying the shared memory
|
||||
* @size: [out] Size of shared memory to allocate
|
||||
* @flags: [in] Flags to/from allocation.
|
||||
* @id: [out] Identifier of the shared memory
|
||||
*
|
||||
* The flags field should currently be zero as input. Updated by the call
|
||||
* with actual flags as defined by TEE_IOCTL_SHM_* above.
|
||||
* This structure is used as argument for TEE_IOC_SHM_ALLOC below.
|
||||
*/
|
||||
|
||||
struct tee_ioctl_shm_register_fd_data
|
||||
{
|
||||
int64_t fd;
|
||||
uint64_t size;
|
||||
uint32_t flags;
|
||||
int32_t id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attributes for struct tee_ioctl_param, selects field in the union
|
||||
*/
|
||||
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_NONE 0 /* parameter not used */
|
||||
|
||||
/**
|
||||
* These defines value parameters (struct tee_ioctl_param_value)
|
||||
*/
|
||||
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT 1
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT 3 /* input and output */
|
||||
|
||||
/**
|
||||
* These defines shared memory reference parameters (struct
|
||||
* tee_ioctl_param_memref)
|
||||
*/
|
||||
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT 5
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT 6
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT 7 /* input and output */
|
||||
|
||||
/**
|
||||
* Mask for the type part of the attribute, leaves room for more types
|
||||
*/
|
||||
|
||||
#define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff
|
||||
|
||||
/* Meta parameter carrying extra information about the message. */
|
||||
|
||||
#define TEE_IOCTL_PARAM_ATTR_META 0x100
|
||||
|
||||
/* Mask of all known attr bits */
|
||||
#define TEE_IOCTL_PARAM_ATTR_MASK \
|
||||
(TEE_IOCTL_PARAM_ATTR_TYPE_MASK | TEE_IOCTL_PARAM_ATTR_META)
|
||||
|
||||
/**
|
||||
* Matches TEEC_LOGIN_* in GP TEE Client API
|
||||
* Are only defined for GP compliant TEEs
|
||||
*/
|
||||
|
||||
#define TEE_IOCTL_LOGIN_PUBLIC 0
|
||||
#define TEE_IOCTL_LOGIN_USER 1
|
||||
#define TEE_IOCTL_LOGIN_GROUP 2
|
||||
#define TEE_IOCTL_LOGIN_APPLICATION 4
|
||||
#define TEE_IOCTL_LOGIN_USER_APPLICATION 5
|
||||
#define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6
|
||||
|
||||
/**
|
||||
* Disallow user-space to use GP implementation specific login
|
||||
* method range (0x80000000 - 0xBFFFFFFF). This range is rather
|
||||
* being reserved for REE kernel clients or TEE implementation.
|
||||
*/
|
||||
|
||||
#define TEE_IOCTL_LOGIN_REE_KERNEL_MIN 0x80000000
|
||||
#define TEE_IOCTL_LOGIN_REE_KERNEL_MAX 0xBFFFFFFF
|
||||
|
||||
/* Private login method for REE kernel clients */
|
||||
|
||||
#define TEE_IOCTL_LOGIN_REE_KERNEL 0x80000000
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_param - parameter
|
||||
* @attr: attributes
|
||||
* @a: if a memref, offset into the shared memory object, else a value
|
||||
* parameter
|
||||
* @b: if a memref, size of the buffer, else a value parameter
|
||||
* @c: if a memref, shared memory identifier, else a value parameter
|
||||
*
|
||||
* @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in
|
||||
* the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and
|
||||
* TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE
|
||||
* indicates that none of the members are used.
|
||||
*
|
||||
* Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an
|
||||
* identifier representing the shared memory object. A memref can reference
|
||||
* a part of a shared memory by specifying an offset (@a) and size (@b) of
|
||||
* the object. To supply the entire shared memory object set the offset
|
||||
* (@a) to 0 and size (@b) to the previously returned size of the object.
|
||||
*/
|
||||
|
||||
struct tee_ioctl_param
|
||||
{
|
||||
uint64_t attr;
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
uint64_t c;
|
||||
};
|
||||
|
||||
#define TEE_IOCTL_UUID_LEN 16
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_open_session_arg - Open session argument
|
||||
* @uuid: [in] UUID of the Trusted Application
|
||||
* @clnt_uuid: [in] UUID of client
|
||||
* @clnt_login: [in] Login class of client, TEE_IOCTL_LOGIN_* above
|
||||
* @cancel_id: [in] Cancellation id, a unique value to identify this request
|
||||
* @session: [out] Session id
|
||||
* @ret: [out] return value
|
||||
* @ret_origin [out] origin of the return value
|
||||
* @num_params [in] number of parameters following this struct
|
||||
*/
|
||||
|
||||
struct tee_ioctl_open_session_arg
|
||||
{
|
||||
uint8_t uuid[TEE_IOCTL_UUID_LEN];
|
||||
uint8_t clnt_uuid[TEE_IOCTL_UUID_LEN];
|
||||
uint32_t clnt_login;
|
||||
uint32_t cancel_id;
|
||||
uint32_t session;
|
||||
uint32_t ret;
|
||||
uint32_t ret_origin;
|
||||
uint32_t num_params;
|
||||
|
||||
/* num_params tells the actual number of element in params */
|
||||
|
||||
struct tee_ioctl_param params[];
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application
|
||||
*
|
||||
* Takes a struct tee_ioctl_buf_data which contains a struct
|
||||
* tee_ioctl_open_session_arg followed by any array of struct
|
||||
* tee_ioctl_param
|
||||
*/
|
||||
|
||||
#define TEE_IOC_OPEN_SESSION _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 2)
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted
|
||||
* Application
|
||||
* @func: [in] Trusted Application function, specific to the TA
|
||||
* @session: [in] Session id
|
||||
* @cancel_id: [in] Cancellation id, a unique value to identify this request
|
||||
* @ret: [out] return value
|
||||
* @ret_origin [out] origin of the return value
|
||||
* @num_params [in] number of parameters following this struct
|
||||
*/
|
||||
|
||||
struct tee_ioctl_invoke_arg
|
||||
{
|
||||
uint32_t func;
|
||||
uint32_t session;
|
||||
uint32_t cancel_id;
|
||||
uint32_t ret;
|
||||
uint32_t ret_origin;
|
||||
uint32_t num_params;
|
||||
|
||||
/* num_params tells the actual number of element in params */
|
||||
|
||||
struct tee_ioctl_param params[];
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_INVOKE - Invokes a function in a Trusted Application
|
||||
*
|
||||
* Takes a struct tee_ioctl_buf_data which contains a struct
|
||||
* tee_invoke_func_arg followed by any array of struct tee_param
|
||||
*/
|
||||
|
||||
#define TEE_IOC_INVOKE _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 3)
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_cancel_arg - Cancels an open session or invoke ioctl
|
||||
* @cancel_id: [in] Cancellation id, a unique value to identify this request
|
||||
* @session: [in] Session id, if the session is opened, else set to 0
|
||||
*/
|
||||
|
||||
struct tee_ioctl_cancel_arg
|
||||
{
|
||||
uint32_t cancel_id;
|
||||
uint32_t session;
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_CANCEL - Cancels an open session or invoke
|
||||
*/
|
||||
|
||||
#define TEE_IOC_CANCEL _IOC(TEE_IOC_MAGIC << 4, TEE_IOC_BASE + 0)
|
||||
/**
|
||||
* struct tee_ioctl_close_session_arg - Closes an open session
|
||||
* @session: [in] Session id
|
||||
*/
|
||||
|
||||
struct tee_ioctl_close_session_arg
|
||||
{
|
||||
uint32_t session;
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_CLOSE_SESSION - Closes a session
|
||||
*/
|
||||
|
||||
#define TEE_IOC_CLOSE_SESSION _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 5)
|
||||
|
||||
/**
|
||||
* struct tee_iocl_supp_recv_arg - Receive a request for a supplicant
|
||||
* function
|
||||
* @func: [in] supplicant function
|
||||
* @num_params [in/out] number of parameters following this struct
|
||||
*
|
||||
* @num_params is the number of params that tee-supplicant has room to
|
||||
* receive when input, @num_params is the number of actual params
|
||||
* tee-supplicant receives when output.
|
||||
*/
|
||||
|
||||
struct tee_iocl_supp_recv_arg
|
||||
{
|
||||
uint32_t func;
|
||||
uint32_t num_params;
|
||||
|
||||
/* num_params tells the actual number of element in params */
|
||||
|
||||
struct tee_ioctl_param params[];
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function
|
||||
*
|
||||
* Takes a struct tee_ioctl_buf_data which contains a struct
|
||||
* tee_iocl_supp_recv_arg followed by any array of struct tee_param
|
||||
*/
|
||||
|
||||
#define TEE_IOC_SUPPL_RECV _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 6)
|
||||
|
||||
/**
|
||||
* struct tee_iocl_supp_send_arg - Send a response to a received request
|
||||
* @ret: [out] return value
|
||||
* @num_params [in] number of parameters following this struct
|
||||
*/
|
||||
|
||||
struct tee_iocl_supp_send_arg
|
||||
{
|
||||
uint32_t ret;
|
||||
uint32_t num_params;
|
||||
|
||||
/* num_params tells the actual number of element in params */
|
||||
|
||||
struct tee_ioctl_param params[];
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function
|
||||
*
|
||||
* Takes a struct tee_ioctl_buf_data which contains a struct
|
||||
* tee_iocl_supp_send_arg followed by any array of struct tee_param
|
||||
*/
|
||||
|
||||
#define TEE_IOC_SUPPL_SEND _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 7)
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_shm_register_data - Shared memory register argument
|
||||
* @addr: [in] Start address of shared memory to register
|
||||
* @length: [in/out] Length of shared memory to register
|
||||
* @flags: [in/out] Flags to/from registration.
|
||||
* @id: [out] Identifier of the shared memory
|
||||
*
|
||||
* The flags field should currently be zero as input. Updated by the call
|
||||
* with actual flags as defined by TEE_IOCTL_SHM_* above.
|
||||
* This structure is used as argument for TEE_IOC_SHM_REGISTER below.
|
||||
*/
|
||||
|
||||
struct tee_ioctl_shm_register_data
|
||||
{
|
||||
uint64_t addr;
|
||||
uint64_t length;
|
||||
uint32_t flags;
|
||||
int32_t id;
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor
|
||||
*
|
||||
* Returns a file descriptor on success or < 0 on failure
|
||||
*
|
||||
* The returned file descriptor refers to the shared memory object in kernel
|
||||
* land. The shared memory is freed when the descriptor is closed.
|
||||
*/
|
||||
|
||||
#define TEE_IOC_SHM_REGISTER_FD _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 8)
|
||||
|
||||
/**
|
||||
* struct tee_ioctl_buf_data - Variable sized buffer
|
||||
* @buf_ptr: [in] A __user pointer to a buffer
|
||||
* @buf_len: [in] Length of the buffer above
|
||||
*
|
||||
* Used as argument for TEE_IOC_OPEN_SESSION, TEE_IOC_INVOKE,
|
||||
* TEE_IOC_SUPPL_RECV, and TEE_IOC_SUPPL_SEND below.
|
||||
*/
|
||||
|
||||
struct tee_ioctl_buf_data
|
||||
{
|
||||
uint64_t buf_ptr;
|
||||
uint64_t buf_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* TEE_IOC_SHM_REGISTER - Register shared memory argument
|
||||
*
|
||||
* Registers shared memory between the user space process and secure OS.
|
||||
*
|
||||
* Returns a file descriptor on success or < 0 on failure
|
||||
*
|
||||
* The shared memory is unregisterred when the descriptor is closed.
|
||||
*/
|
||||
|
||||
#define TEE_IOC_SHM_REGISTER _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 9)
|
||||
/**
|
||||
* Five syscalls are used when communicating with the TEE driver.
|
||||
* open(): opens the device associated with the driver
|
||||
* ioctl(): as described above operating on the file descriptor from open()
|
||||
* close(): two cases
|
||||
* - closes the device file descriptor
|
||||
* - closes a file descriptor connected to allocated shared memory
|
||||
* mmap(): maps shared memory into user space using information from struct
|
||||
* tee_ioctl_shm_alloc_data
|
||||
* munmap(): unmaps previously shared memory
|
||||
*/
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_TEE_H */
|
Loading…
Reference in New Issue
Block a user