diff --git a/drivers/drivers_initialize.c b/drivers/drivers_initialize.c index 082954850d..70b10f257c 100644 --- a/drivers/drivers_initialize.c +++ b/drivers/drivers_initialize.c @@ -47,6 +47,7 @@ #include #include #include +#include /**************************************************************************** * 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(); } diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1552363bd2..8f4a492e12 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -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 diff --git a/drivers/misc/Make.defs b/drivers/misc/Make.defs index 83d2b86f03..55ba2ae92d 100644 --- a/drivers/misc/Make.defs +++ b/drivers/misc/Make.defs @@ -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 diff --git a/drivers/misc/optee.c b/drivers/misc/optee.c new file mode 100644 index 0000000000..1faf7f1126 --- /dev/null +++ b/drivers/misc/optee.c @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/drivers/misc/optee_msg.h b/drivers/misc/optee_msg.h new file mode 100644 index 0000000000..0be2b94224 --- /dev/null +++ b/drivers/misc/optee_msg.h @@ -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 +#include + +/** + * 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 */ diff --git a/include/nuttx/drivers/optee.h b/include/nuttx/drivers/optee.h new file mode 100644 index 0000000000..ab79e773c2 --- /dev/null +++ b/include/nuttx/drivers/optee.h @@ -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 + +/**************************************************************************** + * 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 */ diff --git a/include/nuttx/tee.h b/include/nuttx/tee.h new file mode 100644 index 0000000000..a1ddf711b8 --- /dev/null +++ b/include/nuttx/tee.h @@ -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 +#include + +/**************************************************************************** + * 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 */