[dm][tee] support Trusted Execution Environment (TEE)

Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
GuEe-GUI
2026-07-27 17:53:20 +08:00
committed by Rbb666
parent b26ae7d8d9
commit a7b0182817
14 changed files with 2908 additions and 0 deletions
+1
View File
@@ -35,6 +35,7 @@ rsource "block/Kconfig"
rsource "scsi/Kconfig"
rsource "ufs/Kconfig"
rsource "firmware/Kconfig"
rsource "tee/Kconfig"
rsource "hwcache/Kconfig"
rsource "dvfs/Kconfig"
rsource "regulator/Kconfig"
+187
View File
@@ -0,0 +1,187 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-23 GuEe-GUI first version
*/
#ifndef __TEE_H__
#define __TEE_H__
#include <rtthread.h>
#include <drivers/misc.h>
#define RT_TEE_SUCCESS 0x00000000
#define RT_TEE_ERROR_STORAGE_NOT_AVAILABLE 0xf0100003
#define RT_TEE_ERROR_GENERIC 0xffff0000
#define RT_TEE_ERROR_EXCESS_DATA 0xffff0004
#define RT_TEE_ERROR_BAD_PARAMETERS 0xffff0006
#define RT_TEE_ERROR_ITEM_NOT_FOUND 0xffff0008
#define RT_TEE_ERROR_NOT_IMPLEMENTED 0xffff0009
#define RT_TEE_ERROR_NOT_SUPPORTED 0xffff000a
#define RT_TEE_ERROR_COMMUNICATION 0xffff000e
#define RT_TEE_ERROR_SECURITY 0xffff000f
#define RT_TEE_ERROR_SHORT_BUFFER 0xffff0010
#define RT_TEE_ERROR_OUT_OF_MEMORY 0xffff000c
#define RT_TEE_ERROR_OVERFLOW 0xffff300f
#define RT_TEE_ERROR_TARGET_DEAD 0xffff3024
#define RT_TEE_ERROR_STORAGE_NO_SPACE 0xffff3041
#define RT_TEE_ORIGIN_COMMS 0x00000002
#define RT_TEE_ORIGIN_TEE 0x00000003
#define RT_TEE_ORIGIN_TRUSTED_APP 0x00000004
struct rt_tee_ops;
struct rt_tee_device
{
struct rt_device parent;
rt_list_t shm_nodes;
const struct rt_tee_ops *ops;
struct rt_mutex mutex;
};
#define rt_device_to_tee_device(dev) rt_container_of(dev, struct rt_tee_device, parent)
struct rt_tee_version
{
#define TEE_IMPL_ID_OPTEE 1
#define TEE_IMPL_ID_AMDTEE 2
/* TEE implementation id */
rt_uint32_t impl_id;
#define TEE_OPTEE_CAP_TZ RT_BIT(0)
/* Implementation specific capabilities */
rt_uint32_t impl_caps;
#define TEE_GEN_CAP_GP RT_BIT(0) /* GlobalPlatform compliant TEE */
#define TEE_GEN_CAP_PRIVILEGED RT_BIT(1) /* Privileged device (for supplicant) */
#define TEE_GEN_CAP_REG_MEM RT_BIT(2) /* Supports registering shared memory */
#define TEE_GEN_CAP_MEMREF_NULL RT_BIT(3) /* NULL MemRef support */
/* Generic capabilities */
rt_uint32_t gen_caps;
};
struct rt_tee_shm
{
rt_list_t list;
struct rt_tee_device *tdev;
void *vaddr;
rt_ubase_t paddr;
rt_size_t size;
rt_size_t align;
#define TEE_SHM_DRV RT_BIT(0) /* Memory allocated from pool */
#define TEE_SHM_SYS RT_BIT(1) /* Memory allocated from system */
#define TEE_SHM_USER RT_BIT(2) /* Memory from user */
rt_uint32_t flags;
};
struct rt_tee_param_memref
{
rt_off_t shm_offs;
rt_size_t size;
struct rt_tee_shm *shm;
};
struct rt_tee_param_value
{
rt_uint64_t a;
rt_uint64_t b;
rt_uint64_t c;
};
struct rt_tee_param
{
#define TEE_PARAM_ATTR_TYPE_NONE 0
#define TEE_PARAM_ATTR_TYPE_VALUE_IN 1
#define TEE_PARAM_ATTR_TYPE_VALUE_OUT 2
#define TEE_PARAM_ATTR_TYPE_VALUE_IN_OUT 3
#define TEE_PARAM_ATTR_TYPE_MEMREF_IN 5
#define TEE_PARAM_ATTR_TYPE_MEMREF_OUT 6
#define TEE_PARAM_ATTR_TYPE_MEMREF_IN_OUT 7
rt_uint64_t attr;
union
{
struct rt_tee_param_memref memref;
struct rt_tee_param_value value;
};
};
rt_packed(struct rt_tee_uuid
{
rt_uint32_t time_low;
rt_uint16_t time_mid;
rt_uint16_t time_hi_and_version;
rt_uint8_t clock_seq_and_node[8];
});
struct rt_tee_open_session_arg
{
rt_uint8_t uuid[16];
rt_uint8_t clnt_uuid[16];
rt_uint32_t clnt_login;
rt_uint32_t cancel_id;
rt_uint32_t session;
rt_uint32_t ret;
rt_uint32_t ret_origin;
rt_uint32_t params_nr;
struct rt_tee_param params[];
};
struct rt_tee_invoke_arg
{
rt_uint32_t func;
rt_uint32_t session;
rt_uint32_t cancel_id;
rt_uint32_t ret;
rt_uint32_t ret_origin;
rt_uint32_t params_nr;
struct rt_tee_param params[];
};
struct rt_tee_ops
{
rt_err_t (*get_version)(struct rt_tee_device *tdev,
struct rt_tee_version *out_version);
rt_err_t (*open_session)(struct rt_tee_device *tdev,
struct rt_tee_open_session_arg *arg);
rt_err_t (*close_session)(struct rt_tee_device *tdev, rt_uint32_t session);
rt_err_t (*invoke)(struct rt_tee_device *tdev,
struct rt_tee_invoke_arg *arg);
rt_err_t (*cancel)(struct rt_tee_device *tdev,
rt_uint32_t session, rt_uint32_t cancel_id);
rt_err_t (*shm_register)(struct rt_tee_device *tdev, struct rt_tee_shm *shm);
rt_err_t (*shm_unregister)(struct rt_tee_device *tdev, struct rt_tee_shm *shm);
};
rt_err_t rt_tee_device_register(struct rt_tee_device *tdev);
rt_err_t rt_tee_device_unregister(struct rt_tee_device *tdev);
rt_err_t rt_tee_get_version(struct rt_tee_device *tdev,
struct rt_tee_version *out_version);
rt_err_t rt_tee_open_session(struct rt_tee_device *tdev,
struct rt_tee_open_session_arg *arg);
rt_err_t rt_tee_close_session(struct rt_tee_device *tdev, rt_uint32_t session);
rt_err_t rt_tee_invoke(struct rt_tee_device *tdev,
struct rt_tee_invoke_arg *arg);
rt_err_t rt_tee_cancel(struct rt_tee_device *tdev,
rt_uint32_t session, rt_uint32_t cancel_id);
rt_err_t rt_tee_shm_alloc_helper(struct rt_tee_shm *shm);
rt_err_t rt_tee_shm_free_helper(struct rt_tee_shm *shm);
rt_err_t rt_tee_shm_register(struct rt_tee_device *tdev, struct rt_tee_shm *shm);
rt_err_t rt_tee_shm_unregister(struct rt_tee_device *tdev, struct rt_tee_shm *shm);
#endif /* __TEE_H__ */
+4
View File
@@ -153,6 +153,10 @@ extern "C" {
#endif /* RT_FIRMWARE_ARM_SCMI */
#endif /* RT_USING_FIRMWARE */
#ifdef RT_USING_TEE
#include "drivers/tee.h"
#endif /* RT_USING_TEE */
#ifdef RT_USING_HWCACHE
#include "drivers/hwcache.h"
#endif /* RT_USING_HWCACHE */
+9
View File
@@ -0,0 +1,9 @@
menuconfig RT_USING_TEE
bool "Using Trusted Execution Environment (TEE) support"
depends on RT_USING_DM
default n
if RT_USING_TEE
rsource "optee/Kconfig"
osource "$(SOC_DM_TEE_DIR)/Kconfig"
endif
+21
View File
@@ -0,0 +1,21 @@
from building import *
group = []
if not GetDepend(['RT_USING_TEE']):
Return('group')
cwd = GetCurrentDir()
list = os.listdir(cwd)
CPPPATH = [cwd + '/../include']
src = ['tee.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')
+11
View File
@@ -0,0 +1,11 @@
menuconfig RT_TEE_OPTEE
bool "OP-TEE"
depends on ARCH_ARM_CORTEX_A || ARCH_ARMV8
default n
config RT_TEE_OPTEE_EXAMPLES
bool "Examples"
depends on RT_TEE_OPTEE
depends on RT_USING_CONSOLE
depends on RT_USING_FINSH
default y
+18
View File
@@ -0,0 +1,18 @@
from building import *
group = []
if not GetDepend(['RT_TEE_OPTEE']):
Return('group')
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../../include']
src = ['optee.c']
if GetDepend(['RT_TEE_OPTEE_EXAMPLES']):
src += ['optee_examples.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
File diff suppressed because it is too large Load Diff
+178
View File
@@ -0,0 +1,178 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-23 GuEe-GUI first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "optee.examples"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
/*
* Build the OP-TEE for your platform with the hwrng TA:
* https://optee.readthedocs.io/en/latest/building/devices/qemu.html#qemu-v8
*/
static void optee_uuid_copy(rt_uint8_t *d, struct rt_tee_uuid *s)
{
d[0] = s->time_low >> 24;
d[1] = s->time_low >> 16;
d[2] = s->time_low >> 8;
d[3] = s->time_low;
d[4] = s->time_mid >> 8;
d[5] = s->time_mid;
d[6] = s->time_hi_and_version >> 8;
d[7] = s->time_hi_and_version;
rt_memcpy(d + 8, s->clock_seq_and_node, sizeof(s->clock_seq_and_node));
}
static struct rt_tee_open_session_arg *open_session_arg_alloc(rt_uint32_t params_nr)
{
return rt_calloc(1, sizeof(struct rt_tee_open_session_arg) +
sizeof(struct rt_tee_param) * params_nr);
}
static void open_session_arg_free(struct rt_tee_open_session_arg *arg)
{
rt_free(arg);
}
static struct rt_tee_invoke_arg *invoke_arg_alloc(rt_uint32_t params_nr)
{
return rt_calloc(1, sizeof(struct rt_tee_invoke_arg) +
sizeof(struct rt_tee_param) * params_nr);
}
static void invoke_arg_free(struct rt_tee_invoke_arg *arg)
{
rt_free(arg);
}
static struct rt_tee_device *open_tee_device(char *name)
{
struct rt_device *dev = rt_device_find(name ? : "tee0");
if (dev && !rt_device_open(dev, 0))
{
return rt_container_of(dev, struct rt_tee_device, parent);
}
return RT_NULL;
}
static void close_tee_device(struct rt_tee_device *tdev)
{
rt_device_close(&tdev->parent);
}
/*
* This UUID is generated with uuidgen
* the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html
*/
static int optee_example_rng(int argc, char**argv)
{
rt_err_t err;
struct rt_tee_shm shm;
struct rt_tee_device *tdev;
struct rt_tee_invoke_arg *invoke;
struct rt_tee_open_session_arg *open;
struct rt_tee_uuid uuid =
{
0xab7a617c, 0xb8e7, 0x4d8f,
{ 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64 }
};
if (!(tdev = open_tee_device(RT_NULL)))
{
return -RT_EIO;
}
if (!(open = open_session_arg_alloc(0)))
{
err = -RT_ENOMEM;
goto _close_tee;
}
optee_uuid_copy(open->uuid, &uuid);
if ((err = rt_tee_open_session(tdev, open)) ||
open->ret != RT_TEE_SUCCESS)
{
if (!err)
{
err = -RT_ERROR;
}
goto _free_args;
}
shm.size = 32;
shm.align = RT_MM_PAGE_SIZE;
shm.flags = TEE_SHM_SYS;
if ((err = rt_tee_shm_register(tdev, &shm)))
{
goto _close_session;
}
rt_memset(shm.vaddr, 0, shm.size);
if (!(invoke = invoke_arg_alloc(1)))
{
err = -RT_ENOMEM;
goto _free_shm;
}
/* TA_CMD_GET_ENTROPY */
invoke->func = 0x0;
invoke->session = open->session;
invoke->cancel_id = 0;
invoke->params_nr = 1;
invoke->params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUT;
invoke->params[0].memref.size = shm.size;
invoke->params[0].memref.shm = &shm;
invoke->params[0].memref.shm_offs = 0;
err = rt_tee_invoke(tdev, invoke);
if (!err && invoke->ret == RT_TEE_SUCCESS)
{
rt_uint8_t *rng = shm.vaddr;
for (int i = 0; i < shm.size; ++i)
{
rt_kprintf("RNG[%02d]: %02x\n", i, rng[i]);
}
}
else
{
rt_kprintf("Failed to read RNG: err=%x origin=%x\n", invoke->ret, invoke->ret_origin);
}
invoke_arg_free(invoke);
_free_shm:
rt_tee_shm_unregister(tdev, &shm);
rt_tee_shm_free_helper(&shm);
_close_session:
rt_tee_close_session(tdev, open->session);
_free_args:
open_session_arg_free(open);
_close_tee:
close_tee_device(tdev);
return (int)err;
}
MSH_CMD_EXPORT(optee_example_rng, optee example rng);
+422
View File
@@ -0,0 +1,422 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-23 GuEe-GUI first version
*/
#ifndef __OPTEE_MSG_H__
#define __OPTEE_MSG_H__
#include <drivers/misc.h>
/*****************************************************************************
* 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_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 RT_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 RT_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 bints of optee_msg_param.tmem.buf_ptr should hold page
* offset of the 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 RT_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 RT_GENMASK(2, 0)
#define OPTEE_MSG_ATTR_CACHE_PREDEFINED 0
/*
* Page size used in non-contiguous buffer entries
*/
#define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096
/**
* 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
{
rt_uint64_t buf_ptr;
rt_uint64_t size;
rt_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
{
rt_uint64_t offs;
rt_uint64_t size;
rt_uint64_t shm_ref;
};
/**
* struct optee_msg_param_value - opaque value parameter
*
* Value parameters are passed unchecked between normal and secure world.
*/
struct optee_msg_param_value
{
rt_uint64_t a;
rt_uint64_t b;
rt_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
* @value: parameter by opaque value
*
* @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
* the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
* OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
* OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
* OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
*/
struct optee_msg_param
{
rt_uint64_t attr;
union
{
struct optee_msg_param_tmem tmem;
struct optee_msg_param_rmem rmem;
struct optee_msg_param_value value;
};
};
/**
* 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
* @params_nr: 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 field holds 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 has to come first.
*
* Temp memref parameters can be fragmented if supported by the Trusted OS
* (when optee_smc.h is bearer of this protocol this is indicated with
* OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
* fragmented then has all but the last fragment the
* OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
* it will still be presented as a single logical memref to the Trusted
* Application.
*/
struct optee_msg_arg
{
rt_uint32_t cmd;
rt_uint32_t func;
rt_uint32_t session;
rt_uint32_t cancel_id;
rt_uint32_t pad;
rt_uint32_t ret;
rt_uint32_t ret_origin;
rt_uint32_t params_nr;
struct optee_msg_param params[0];
};
/**
* OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg
*
* @params_nr: 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(params_nr) \
(sizeof(struct optee_msg_arg) + sizeof(struct optee_msg_param) * (params_nr))
/*****************************************************************************
* 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].value.a-b uuid of Trusted Application
* param[1].value.a-b uuid of Client
* param[1].value.c Login class of client TEE_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_FRAGMENT]
* [in] param[0].tmem.buf_ptr physical address (of first fragment)
* [in] param[0].tmem.size size (of first fragment)
* [in] param[0].tmem.shm_ref holds shared memory reference
* ...
* The shared memory can optionally be fragmented, temp memrefs can follow
* each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
*
* OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
* memory reference. The information is passed as:
* [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
* [in] param[0].rmem.shm_ref holds shared memory reference
* [in] param[0].rmem.offs 0
* [in] param[0].rmem.size 0
*/
#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_FUNCID_CALL_WITH_ARG 0x0004
/*****************************************************************************
* Part 3 - Requests from secure world, RPC
*****************************************************************************/
/*
* All RPC is done with a struct optee_msg_arg as bearer of information,
* struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
*
* RPC communication with tee-supplicant is reversed compared to normal
* client communication desribed above. The supplicant receives requests
* and sends responses.
*/
/*
* Load a TA into memory, defined in tee-supplicant
*/
#define OPTEE_MSG_RPC_CMD_LOAD_TA 0
/*
* Get time
*
* Returns number of seconds and nano seconds since the Epoch,
* 1970-01-01 00:00:00 +0000 (UTC).
*
* [out] param[0].value.a Number of seconds
* [out] param[0].value.b Number of nano seconds.
*/
#define OPTEE_MSG_RPC_CMD_GET_TIME 3
/*
* Wait queue primitive, helper for secure world to implement a wait queue.
*
* If secure world need to wait for a secure world mutex it issues a sleep
* request instead of spinning in secure world. Conversely is a wakeup
* request issued when a secure world mutex with a thread waiting thread is
* unlocked.
*
* Waiting on a key
* [in] param[0].value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
* [in] param[0].value.b wait key
*
* Waking up a key
* [in] param[0].value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
* [in] param[0].value.b wakeup key
*/
#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4
#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1
/*
* Suspend execution
*
* [in] param[0].value .a number of milliseconds to suspend
*/
#define OPTEE_MSG_RPC_CMD_SUSPEND 5
/*
* Allocate a piece of shared memory
*
* Shared memory can optionally be fragmented, to support that additional
* spare param entries are allocated to make room for eventual fragments.
* The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
* unused. All returned temp memrefs except the last should have the
* OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
*
* [in] param[0].value.a type of memory one of
* OPTEE_MSG_RPC_SHM_TYPE_* below
* [in] param[0].value.b requested size
* [in] param[0].value.c required alignment
*
* [out] param[0].tmem.buf_ptr physical address (of first fragment)
* [out] param[0].tmem.size size (of first fragment)
* [out] param[0].tmem.shm_ref shared memory reference
* ...
* [out] param[n].tmem.buf_ptr physical address
* [out] param[n].tmem.size size
* [out] param[n].tmem.shm_ref shared memory reference (same value
* as in param[n-1].tmem.shm_ref)
*/
#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6
/* Memory that can be shared with a non-secure user space application */
#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0
/* Memory only shared with non-secure kernel */
#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1
/*
* Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
*
* [in] param[0].value.a type of memory one of
* OPTEE_MSG_RPC_SHM_TYPE_* above
* [in] param[0].value.b value of shared memory reference
* returned in param[0].tmem.shm_ref
* above
*/
#define OPTEE_MSG_RPC_CMD_SHM_FREE 7
/*
* Access a device on an i2c bus
*
* [in] param[0].value.a mode: RD(0), WR(1)
* [in] param[0].value.b i2c adapter
* [in] param[0].value.c i2c chip
*
* [in] param[1].value.a i2c control flags
*
* [in/out] memref[2] buffer to exchange the transfer data
* with the secure world
*
* [out] param[3].value.a bytes transferred by the driver
*/
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER 21
/* I2C master transfer modes */
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1
/* I2C master control flags */
#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT RT_BIT(0)
#endif /* __OPTEE_MSG_H__ */
+476
View File
@@ -0,0 +1,476 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-23 GuEe-GUI first version
*/
#ifndef __OPTEE_SMC_H__
#define __OPTEE_SMC_H__
#include <drivers/misc.h>
#ifndef ARM_SMCCC
#define ARM_SMCCC_STD_CALL 0U
#define ARM_SMCCC_FAST_CALL 1U
#define ARM_SMCCC_TYPE_SHIFT 31
#define ARM_SMCCC_SMC_32 0
#define ARM_SMCCC_SMC_64 1
#define ARM_SMCCC_CALL_CONV_SHIFT 30
#define ARM_SMCCC_OWNER_MASK 0x3f
#define ARM_SMCCC_OWNER_SHIFT 24
#define ARM_SMCCC_FUNC_MASK 0xffff
#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
(((type) << ARM_SMCCC_TYPE_SHIFT) | \
((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
(((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
((func_num) & ARM_SMCCC_FUNC_MASK))
#define ARM_SMCCC_OWNER_ARCH 0
#define ARM_SMCCC_OWNER_CPU 1
#define ARM_SMCCC_OWNER_SIP 2
#define ARM_SMCCC_OWNER_OEM 3
#define ARM_SMCCC_OWNER_STANDARD 4
#define ARM_SMCCC_OWNER_TRUSTED_APP 48
#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
#define ARM_SMCCC_OWNER_TRUSTED_OS 50
#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
#endif /* ARM_SMCCC */
#define OPTEE_SMC_STD_CALL_VAL(func_num) \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_TRUSTED_OS, \
(func_num))
#define OPTEE_SMC_FAST_CALL_VAL(func_num) \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_TRUSTED_OS, \
(func_num))
/*
* Function specified by SMC Calling convention.
*/
#define OPTEE_SMC_FUNCID_CALLS_COUNT 0xff00
#define OPTEE_SMC_CALLS_COUNT \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_TRUSTED_OS_END, \
OPTEE_SMC_FUNCID_CALLS_COUNT)
/*
* Normal cached memory (write-back), shareable for SMP systems and not
* shareable for UP systems.
*/
#define OPTEE_SMC_SHM_CACHED 1
/*
* a0..a7 is used as register names in the descriptions below, on arm32
* that translates to r0..r7 and on arm64 to w0..w7. In both cases it's
* 32-bit registers.
*/
/*
* Function specified by SMC Calling convention
*
* Return one of the following UIDs if using API specified in this file
* without further extentions:
* 65cb6b93-af0c-4617-8ed6-644a8d1140f8
* see also OPTEE_SMC_UID_* in optee_msg.h
*/
#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
#define OPTEE_SMC_CALLS_UID \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_TRUSTED_OS_END, \
OPTEE_SMC_FUNCID_CALLS_UID)
/*
* Function specified by SMC Calling convention
*
* Returns 2.0 if using API specified in this file without further extentions.
* see also OPTEE_MSG_REVISION_* in optee_msg.h
*/
#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
#define OPTEE_SMC_CALLS_REVISION \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_TRUSTED_OS_END, \
OPTEE_SMC_FUNCID_CALLS_REVISION)
struct optee_smc_calls_revision_result
{
unsigned long major;
unsigned long minor;
unsigned long reserved0;
unsigned long reserved1;
};
/*
* 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 a0-4 in the same way as OPTEE_SMC_CALLS_UID
* described above.
*/
#define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID
#define OPTEE_SMC_CALL_GET_OS_UUID OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID)
/*
* 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 a0-1 in the same way as OPTEE_SMC_CALLS_REVISION
* described above. May optionally return a 32-bit build identifier in a2,
* with zero meaning unspecified.
*/
#define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION
#define OPTEE_SMC_CALL_GET_OS_REVISION OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION)
struct optee_smc_call_get_os_revision_result
{
unsigned long major;
unsigned long minor;
unsigned long build_id;
unsigned long reserved1;
};
/*
* Call with struct optee_msg_arg as argument
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
* a1 Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
* a2 Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
* a3 Cache settings, not used if physical pointer is in a predefined shared
* memory area else per OPTEE_SMC_SHM_*
* a4-6 Not used
* a7 Hypervisor Client ID register
*
* Normal return register usage:
* a0 Return value, OPTEE_SMC_RETURN_*
* a1-3 Not used
* a4-7 Preserved
*
* OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage:
* a0 Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT
* a1-3 Preserved
* a4-7 Preserved
*
* RPC return register usage:
* a0 Return value, OPTEE_SMC_RETURN_IS_RPC(val)
* a1-2 RPC parameters
* a3-7 Resume information, must be preserved
*
* Possible return values:
* OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this
* function.
* OPTEE_SMC_RETURN_OK Call completed, result updated in
* the previously supplied struct
* optee_msg_arg.
* OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded,
* try again later.
* OPTEE_SMC_RETURN_EBADADDR Bad physcial pointer to struct
* optee_msg_arg.
* OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg
* OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal
* world.
*/
#define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG
#define OPTEE_SMC_CALL_WITH_ARG OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG)
/*
* Get Shared Memory Config
*
* Returns the Secure/Non-secure shared memory config.
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG
* a1-6 Not used
* a7 Hypervisor Client ID register
*
* Have config return register usage:
* a0 OPTEE_SMC_RETURN_OK
* a1 Physical address of start of SHM
* a2 Size of of SHM
* a3 Cache settings of memory, as defined by the
* OPTEE_SMC_SHM_* values above
* a4-7 Preserved
*
* Not available register usage:
* a0 OPTEE_SMC_RETURN_ENOTAVAIL
* a1-3 Not used
* a4-7 Preserved
*/
#define OPTEE_SMC_FUNCID_GET_SHM_CONFIG 7
#define OPTEE_SMC_GET_SHM_CONFIG OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG)
struct optee_smc_get_shm_config_result
{
unsigned long status;
unsigned long start;
unsigned long size;
unsigned long settings;
};
/*
* Exchanges capabilities between normal world and secure world
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES
* a1 bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_*
* a2-6 Not used
* a7 Hypervisor Client ID register
*
* Normal return register usage:
* a0 OPTEE_SMC_RETURN_OK
* a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
* a2-7 Preserved
*
* Error return register usage:
* a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world
* a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
* a2-7 Preserved
*/
/* Normal world works as a uniprocessor system */
#define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR RT_BIT(0)
/* Secure world has reserved shared memory for normal world to use */
#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM RT_BIT(0)
/* Secure world can communicate via previously unregistered shared memory */
#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM RT_BIT(1)
/*
* Secure world supports commands "register/unregister shared memory",
* secure world accepts command buffers located in any parts of non-secure RAM
*/
#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM RT_BIT(2)
#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
#define OPTEE_SMC_EXCHANGE_CAPABILITIES OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
struct optee_smc_exchange_capabilities_result
{
unsigned long status;
unsigned long capabilities;
unsigned long reserved0;
unsigned long reserved1;
};
/*
* Disable and empties cache of shared memory objects
*
* Secure world can cache frequently used shared memory objects, for
* example objects used as RPC arguments. When secure world is idle this
* function returns one shared memory reference to free. To disable the
* cache and free all cached objects this function has to be called until
* it returns OPTEE_SMC_RETURN_ENOTAVAIL.
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE
* a1-6 Not used
* a7 Hypervisor Client ID register
*
* Normal return register usage:
* a0 OPTEE_SMC_RETURN_OK
* a1 Upper 32bit of a 64bit Shared memory cookie
* a2 Lower 32bit of a 64bit Shared memory cookie
* a3-7 Preserved
*
* Cache empty return register usage:
* a0 OPTEE_SMC_RETURN_ENOTAVAIL
* a1-7 Preserved
*
* Not idle return register usage:
* a0 OPTEE_SMC_RETURN_EBUSY
* a1-7 Preserved
*/
#define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE 10
#define OPTEE_SMC_DISABLE_SHM_CACHE OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE)
struct optee_smc_disable_shm_cache_result
{
unsigned long status;
unsigned long shm_upper32;
unsigned long shm_lower32;
unsigned long reserved0;
};
/*
* Enable cache of shared memory objects
*
* Secure world can cache frequently used shared memory objects, for
* example objects used as RPC arguments. When secure world is idle this
* function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If
* secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned.
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE
* a1-6 Not used
* a7 Hypervisor Client ID register
*
* Normal return register usage:
* a0 OPTEE_SMC_RETURN_OK
* a1-7 Preserved
*
* Not idle return register usage:
* a0 OPTEE_SMC_RETURN_EBUSY
* a1-7 Preserved
*/
#define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE 11
#define OPTEE_SMC_ENABLE_SHM_CACHE OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
/*
* Resume from RPC (for example after processing a foreign interrupt)
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
* a1-3 Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned
* OPTEE_SMC_RETURN_RPC in a0
*
* Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above.
*
* Possible return values
* OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this
* function.
* OPTEE_SMC_RETURN_OK Original call completed, result
* updated in the previously supplied.
* struct optee_msg_arg
* OPTEE_SMC_RETURN_RPC Call suspended by RPC call to normal
* world.
* OPTEE_SMC_RETURN_ERESUME Resume failed, the opaque resume
* information was corrupt.
*/
#define OPTEE_SMC_FUNCID_RETURN_FROM_RPC 3
#define OPTEE_SMC_CALL_RETURN_FROM_RPC OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC)
#define OPTEE_SMC_RETURN_RPC_PREFIX_MASK 0xffff0000
#define OPTEE_SMC_RETURN_RPC_PREFIX 0xffff0000
#define OPTEE_SMC_RETURN_RPC_FUNC_MASK 0x0000ffff
#define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) ((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK)
#define OPTEE_SMC_RPC_VAL(func) ((func) | OPTEE_SMC_RETURN_RPC_PREFIX)
/*
* Allocate memory for RPC parameter passing. The memory is used to hold a
* struct optee_msg_arg.
*
* "Call" register usage:
* a0 This value, OPTEE_SMC_RETURN_RPC_ALLOC
* a1 Size in bytes of required argument memory
* a2 Not used
* a3 Resume information, must be preserved
* a4-5 Not used
* a6-7 Resume information, must be preserved
*
* "Return" register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
* a1 Upper 32bits of 64bit physical pointer to allocated
* memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
* be allocated.
* a2 Lower 32bits of 64bit physical pointer to allocated
* memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
* be allocated
* a3 Preserved
* a4 Upper 32bits of 64bit Shared memory cookie used when freeing
* the memory or doing an RPC
* a5 Lower 32bits of 64bit Shared memory cookie used when freeing
* the memory or doing an RPC
* a6-7 Preserved
*/
#define OPTEE_SMC_RPC_FUNC_ALLOC 0
#define OPTEE_SMC_RETURN_RPC_ALLOC OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC)
/*
* Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC
*
* "Call" register usage:
* a0 This value, OPTEE_SMC_RETURN_RPC_FREE
* a1 Upper 32bits of 64bit shared memory cookie belonging to this
* argument memory
* a2 Lower 32bits of 64bit shared memory cookie belonging to this
* argument memory
* a3-7 Resume information, must be preserved
*
* "Return" register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
* a1-2 Not used
* a3-7 Preserved
*/
#define OPTEE_SMC_RPC_FUNC_FREE 2
#define OPTEE_SMC_RETURN_RPC_FREE OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
/*
* Deliver foreign interrupt to normal world.
*
* "Call" register usage:
* a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
* a1-7 Resume information, must be preserved
*
* "Return" register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
* a1-7 Preserved
*/
#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
/*
* Do an RPC request. The supplied struct optee_msg_arg tells which
* request to do and the parameters for the request. The following fields
* are used (the rest are unused):
* - cmd the Request ID
* - ret return value of the request, filled in by normal world
* - num_params number of parameters for the request
* - params the parameters
* - param_attrs attributes of the parameters
*
* "Call" register usage:
* a0 OPTEE_SMC_RETURN_RPC_CMD
* a1 Upper 32bit of a 64bit Shared memory cookie holding a
* struct optee_msg_arg, must be preserved, only the data should
* be updated
* a2 Lower 32bit of a 64bit Shared memory cookie holding a
* struct optee_msg_arg, must be preserved, only the data should
* be updated
* a3-7 Resume information, must be preserved
*
* "Return" register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
* a1-2 Not used
* a3-7 Preserved
*/
#define OPTEE_SMC_RPC_FUNC_CMD 5
#define OPTEE_SMC_RETURN_RPC_CMD OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD)
/* Returned in a0 */
#define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xffffffff
/* Returned in a0 only from Trusted OS functions */
#define OPTEE_SMC_RETURN_OK 0x0
#define OPTEE_SMC_RETURN_ETHREAD_LIMIT 0x1
#define OPTEE_SMC_RETURN_EBUSY 0x2
#define OPTEE_SMC_RETURN_ERESUME 0x3
#define OPTEE_SMC_RETURN_EBADADDR 0x4
#define OPTEE_SMC_RETURN_EBADCMD 0x5
#define OPTEE_SMC_RETURN_ENOMEM 0x6
#define OPTEE_SMC_RETURN_ENOTAVAIL 0x7
#define OPTEE_SMC_RETURN_IS_RPC(ret) \
({ \
ret != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION && \
(ret & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) == \
OPTEE_SMC_RETURN_RPC_PREFIX; \
})
#endif /* __OPTEE_SMC_H__ */
+331
View File
@@ -0,0 +1,331 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-23 GuEe-GUI first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "rtdm.tee"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <mm_aspace.h>
#include <mm_page.h>
static struct rt_dm_ida tee_ida = RT_DM_IDA_INIT(TEE);
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops _tee_ops =
{
};
#endif
rt_err_t rt_tee_device_register(struct rt_tee_device *tdev)
{
rt_err_t err;
int device_id;
const char *dev_name;
if (!tdev || !tdev->ops)
{
return -RT_EINVAL;
}
if ((device_id = rt_dm_ida_alloc(&tee_ida)) < 0)
{
return -RT_EFULL;
}
rt_dm_dev_set_name(&tdev->parent, "tee%u", device_id);
dev_name = rt_dm_dev_get_name(&tdev->parent);
rt_list_init(&tdev->shm_nodes);
rt_mutex_init(&tdev->mutex, dev_name, RT_IPC_FLAG_PRIO);
/* Just make a search interface */
tdev->parent.type = RT_Device_Class_Char;
#ifdef RT_USING_DEVICE_OPS
tdev->parent.ops = tdev->parent.ops ? : &_tee_ops;
#endif
tdev->parent.master_id = tee_ida.master_id;
tdev->parent.device_id = device_id;
if ((err = rt_device_register(&tdev->parent, dev_name, RT_DEVICE_FLAG_DEACTIVATE)))
{
goto _fail;
}
return RT_EOK;
_fail:
rt_dm_ida_free(&tee_ida, device_id);
rt_mutex_detach(&tdev->mutex);
return err;
}
rt_err_t rt_tee_device_unregister(struct rt_tee_device *tdev)
{
rt_err_t err;
struct rt_tee_shm *shm, *shm_next;
if (!tdev)
{
return -RT_EINVAL;
}
if (tdev->parent.ref_count)
{
LOG_E("%s: there is %u user",
rt_dm_dev_get_name(&tdev->parent), tdev->parent.ref_count);
return -RT_EINVAL;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
if (!rt_list_isempty(&tdev->shm_nodes))
{
LOG_W("%s: shm not unregister", rt_dm_dev_get_name(&tdev->parent));
rt_list_for_each_entry_safe(shm, shm_next, &tdev->shm_nodes, list)
{
if (!tdev->ops->shm_unregister(tdev, shm))
{
rt_list_remove(&shm->list);
}
}
}
rt_mutex_release(&tdev->mutex);
rt_dm_ida_free(&tee_ida, tdev->parent.device_id);
if (!(err = rt_device_unregister(&tdev->parent)))
{
rt_mutex_detach(&tdev->mutex);
}
return err;
}
rt_err_t rt_tee_get_version(struct rt_tee_device *tdev,
struct rt_tee_version *out_version)
{
rt_err_t err;
if (!tdev || !out_version)
{
return -RT_EINVAL;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
err = tdev->ops->get_version(tdev, out_version);
rt_mutex_release(&tdev->mutex);
return err;
}
rt_err_t rt_tee_open_session(struct rt_tee_device *tdev,
struct rt_tee_open_session_arg *arg)
{
rt_err_t err;
if (!tdev || !arg)
{
return -RT_EINVAL;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
err = tdev->ops->open_session(tdev, arg);
rt_mutex_release(&tdev->mutex);
return err;
}
rt_err_t rt_tee_close_session(struct rt_tee_device *tdev, rt_uint32_t session)
{
rt_err_t err;
if (!tdev)
{
return -RT_EINVAL;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
err = tdev->ops->close_session(tdev, session);
rt_mutex_release(&tdev->mutex);
return err;
}
rt_err_t rt_tee_invoke(struct rt_tee_device *tdev,
struct rt_tee_invoke_arg *arg)
{
rt_err_t err;
if (!tdev || !arg)
{
return -RT_EINVAL;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
err = tdev->ops->invoke(tdev, arg);
rt_mutex_release(&tdev->mutex);
return err;
}
rt_err_t rt_tee_cancel(struct rt_tee_device *tdev,
rt_uint32_t session, rt_uint32_t cancel_id)
{
rt_err_t err;
if (!tdev)
{
return -RT_EINVAL;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
err = tdev->ops->cancel(tdev, session, cancel_id);
rt_mutex_release(&tdev->mutex);
return err;
}
rt_err_t rt_tee_shm_alloc_helper(struct rt_tee_shm *shm)
{
if (!shm || !shm->size)
{
return -RT_EINVAL;
}
if (shm->align && shm->align != RT_MM_PAGE_SIZE)
{
shm->vaddr = rt_malloc_align(shm->size, shm->align);
}
else
{
shm->vaddr = rt_pages_alloc(rt_page_bits(shm->size));
}
if (!shm->vaddr)
{
return -RT_ENOMEM;
}
if (!shm->paddr)
{
shm->paddr = (rt_ubase_t)rt_kmem_v2p(shm->vaddr);
}
return RT_EOK;
}
rt_err_t rt_tee_shm_free_helper(struct rt_tee_shm *shm)
{
if (!shm || !shm->size)
{
return -RT_EINVAL;
}
if (shm->align && shm->align != RT_MM_PAGE_SIZE)
{
rt_free_align(shm->vaddr);
}
else
{
rt_pages_free(shm->vaddr, rt_page_bits(shm->size));
}
return RT_EOK;
}
rt_err_t rt_tee_shm_register(struct rt_tee_device *tdev, struct rt_tee_shm *shm)
{
rt_err_t err;
rt_bool_t allocated = RT_FALSE;
if (!tdev || !shm || !shm->size)
{
return -RT_EINVAL;
}
if (shm->flags & TEE_SHM_USER)
{
if (!shm->vaddr)
{
return -RT_EINVAL;
}
if (!shm->paddr)
{
shm->paddr = (rt_ubase_t)rt_kmem_v2p(shm->vaddr);
}
}
else if ((shm->flags & TEE_SHM_SYS) && !(shm->flags & TEE_SHM_DRV))
{
if ((err = rt_tee_shm_alloc_helper(shm)))
{
return err;
}
allocated = RT_TRUE;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
if (!(err = tdev->ops->shm_register(tdev, shm)))
{
rt_list_init(&shm->list);
rt_list_insert_before(&tdev->shm_nodes, &shm->list);
}
rt_mutex_release(&tdev->mutex);
if (err && allocated)
{
rt_tee_shm_free_helper(shm);
shm->vaddr = RT_NULL;
shm->paddr = 0;
}
return err;
}
rt_err_t rt_tee_shm_unregister(struct rt_tee_device *tdev, struct rt_tee_shm *shm)
{
rt_err_t err;
if (!tdev || !shm)
{
return -RT_EINVAL;
}
rt_mutex_take(&tdev->mutex, RT_WAITING_FOREVER);
if (!(err = tdev->ops->shm_unregister(tdev, shm)))
{
rt_list_remove(&shm->list);
}
rt_mutex_release(&tdev->mutex);
return err;
}