summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorGuEe-GUI <[email protected]>2026-06-14 11:42:01 +0800
committerRbb666 <[email protected]>2026-07-27 17:53:20 +0800
commita7b0182817059620738779b30f43eaeca10627ff (patch)
tree585617e46cf93d1fd1e168c02bd7ba02b5b4f80c /components
parentb26ae7d8d9417c073999867187056f506086f256 (diff)
[dm][tee] support Trusted Execution Environment (TEE)
Signed-off-by: GuEe-GUI <[email protected]>
Diffstat (limited to 'components')
-rwxr-xr-xcomponents/drivers/Kconfig1
-rwxr-xr-xcomponents/drivers/include/drivers/tee.h187
-rw-r--r--components/drivers/include/rtdevice.h4
-rwxr-xr-xcomponents/drivers/tee/Kconfig9
-rwxr-xr-xcomponents/drivers/tee/SConscript21
-rwxr-xr-xcomponents/drivers/tee/optee/Kconfig11
-rwxr-xr-xcomponents/drivers/tee/optee/SConscript18
-rwxr-xr-xcomponents/drivers/tee/optee/optee.c876
-rwxr-xr-xcomponents/drivers/tee/optee/optee_examples.c178
-rwxr-xr-xcomponents/drivers/tee/optee/optee_msg.h422
-rwxr-xr-xcomponents/drivers/tee/optee/optee_smc.h476
-rwxr-xr-xcomponents/drivers/tee/tee.c331
12 files changed, 2534 insertions, 0 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig
index 7ceb0720b4..58192e98a6 100755
--- a/components/drivers/Kconfig
+++ b/components/drivers/Kconfig
@@ -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"
diff --git a/components/drivers/include/drivers/tee.h b/components/drivers/include/drivers/tee.h
new file mode 100755
index 0000000000..a9cc3a1d2d
--- /dev/null
+++ b/components/drivers/include/drivers/tee.h
@@ -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__ */
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index a9da14d322..1185224304 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -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 */
diff --git a/components/drivers/tee/Kconfig b/components/drivers/tee/Kconfig
new file mode 100755
index 0000000000..3662842b24
--- /dev/null
+++ b/components/drivers/tee/Kconfig
@@ -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
diff --git a/components/drivers/tee/SConscript b/components/drivers/tee/SConscript
new file mode 100755
index 0000000000..18abc56437
--- /dev/null
+++ b/components/drivers/tee/SConscript
@@ -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')
diff --git a/components/drivers/tee/optee/Kconfig b/components/drivers/tee/optee/Kconfig
new file mode 100755
index 0000000000..20e78c726c
--- /dev/null
+++ b/components/drivers/tee/optee/Kconfig
@@ -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
diff --git a/components/drivers/tee/optee/SConscript b/components/drivers/tee/optee/SConscript
new file mode 100755
index 0000000000..6b6478b088
--- /dev/null
+++ b/components/drivers/tee/optee/SConscript
@@ -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')
diff --git a/components/drivers/tee/optee/optee.c b/components/drivers/tee/optee/optee.c
new file mode 100755
index 0000000000..06a87738dd
--- /dev/null
+++ b/components/drivers/tee/optee/optee.c
@@ -0,0 +1,876 @@
+/*
+ * 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 "tee.optee"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <mm_aspace.h>
+#include <smccc.h>
+#include "optee_msg.h"
+#include "optee_smc.h"
+
+#define PAGELIST_ENTRIES_PER_PAGE ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(rt_uint64_t)) - 1)
+
+typedef void (*optee_call_handle)(rt_ubase_t a0, rt_ubase_t a1,
+ rt_ubase_t a2, rt_ubase_t a3, rt_ubase_t a4, rt_ubase_t a5,
+ rt_ubase_t a6, rt_ubase_t a7, struct arm_smccc_res_t *out_res);
+
+struct optee_device
+{
+ struct rt_tee_device parent;
+
+ optee_call_handle call;
+};
+
+#define raw_to_optee(tdev) rt_container_of(tdev, struct optee_device, parent)
+
+static void optee_call_smc(rt_ubase_t a0, rt_ubase_t a1,
+ rt_ubase_t a2, rt_ubase_t a3, rt_ubase_t a4, rt_ubase_t a5,
+ rt_ubase_t a6, rt_ubase_t a7, struct arm_smccc_res_t *out_res)
+{
+ arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, out_res, RT_NULL);
+}
+
+static void optee_call_hvc(rt_ubase_t a0, rt_ubase_t a1,
+ rt_ubase_t a2, rt_ubase_t a3, rt_ubase_t a4, rt_ubase_t a5,
+ rt_ubase_t a6, rt_ubase_t a7, struct arm_smccc_res_t *out_res)
+{
+ arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, out_res, RT_NULL);
+}
+
+static rt_bool_t msg_api_uid_is_optee_api(struct optee_device *optee)
+{
+ struct arm_smccc_res_t res;
+
+ optee->call(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+ return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+ res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
+}
+
+static rt_bool_t exchange_capabilities(struct optee_device *optee,
+ rt_uint32_t *sec_caps)
+{
+ union
+ {
+ struct arm_smccc_res_t smccc;
+ struct optee_smc_exchange_capabilities_result result;
+ } res;
+
+ optee->call(OPTEE_SMC_EXCHANGE_CAPABILITIES,
+ OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+ if (res.result.status != OPTEE_SMC_RETURN_OK)
+ {
+ return RT_FALSE;
+ }
+
+ *sec_caps = res.result.capabilities;
+
+ return RT_TRUE;
+}
+
+static rt_err_t to_msg_param(struct optee_msg_param *msg_params,
+ rt_uint32_t params_nr, const struct rt_tee_param *raw_params)
+{
+ for (int n = 0; n < params_nr; ++n, ++msg_params, ++raw_params)
+ {
+ rt_memset(msg_params, 0, sizeof(*msg_params));
+
+ switch (raw_params->attr)
+ {
+ case TEE_PARAM_ATTR_TYPE_NONE:
+ msg_params->attr = OPTEE_MSG_ATTR_TYPE_NONE;
+ break;
+
+ case TEE_PARAM_ATTR_TYPE_VALUE_IN:
+ case TEE_PARAM_ATTR_TYPE_VALUE_OUT:
+ case TEE_PARAM_ATTR_TYPE_VALUE_IN_OUT:
+ msg_params->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+ msg_params->attr += raw_params->attr - TEE_PARAM_ATTR_TYPE_VALUE_IN;
+ msg_params->value.a = raw_params->value.a;
+ msg_params->value.b = raw_params->value.b;
+ msg_params->value.c = raw_params->value.c;
+ break;
+
+ case TEE_PARAM_ATTR_TYPE_MEMREF_IN:
+ case TEE_PARAM_ATTR_TYPE_MEMREF_OUT:
+ case TEE_PARAM_ATTR_TYPE_MEMREF_IN_OUT:
+ msg_params->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ msg_params->attr += raw_params->attr - TEE_PARAM_ATTR_TYPE_MEMREF_IN;
+ msg_params->rmem.shm_ref = (rt_ubase_t)raw_params->memref.shm;
+ msg_params->rmem.size = raw_params->memref.size;
+ msg_params->rmem.offs = raw_params->memref.shm_offs;
+ break;
+
+ default:
+ return -RT_EINVAL;
+ }
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t from_msg_param(struct rt_tee_param *raw_params,
+ rt_uint32_t params_nr, const struct optee_msg_param *msg_params)
+{
+ for (int n = 0; n < params_nr; ++n, ++raw_params, ++msg_params)
+ {
+ rt_uint32_t attr = msg_params->attr & OPTEE_MSG_ATTR_TYPE_MASK;
+
+ rt_memset(raw_params, 0, sizeof(*raw_params));
+
+ switch (attr)
+ {
+ case OPTEE_MSG_ATTR_TYPE_NONE:
+ raw_params->attr = TEE_PARAM_ATTR_TYPE_NONE;
+ break;
+
+ case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
+ raw_params->attr = TEE_PARAM_ATTR_TYPE_VALUE_IN;
+ raw_params->attr += msg_params->attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+ raw_params->value.a = msg_params->value.a;
+ raw_params->value.b = msg_params->value.b;
+ raw_params->value.c = msg_params->value.c;
+ break;
+
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+ raw_params->attr = TEE_PARAM_ATTR_TYPE_MEMREF_IN;
+ raw_params->attr += msg_params->attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+
+ raw_params->memref.size = msg_params->rmem.size;
+ raw_params->memref.shm = (void *)(rt_ubase_t)msg_params->rmem.shm_ref;
+ raw_params->memref.shm_offs = raw_params->memref.shm ?
+ msg_params->rmem.offs : 0;
+ break;
+
+ default:
+ return -RT_EINVAL;
+ }
+ }
+
+ return RT_EOK;
+}
+
+static void *alloc_page_list(void *buf, rt_size_t len, rt_uint64_t *out_paddr)
+{
+ const rt_size_t page_size = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+ void *page_list;
+ rt_uint8_t *buf_base;
+ unsigned int page_offset, num_pages, list_size;
+ struct
+ {
+ rt_uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+ rt_uint64_t next_page_data;
+ } *pages_data;
+
+ page_offset = (rt_ubase_t)buf & (page_size - 1);
+ num_pages = rt_roundup(page_offset + len, page_size) / page_size;
+ list_size = RT_DIV_ROUND_UP(num_pages, PAGELIST_ENTRIES_PER_PAGE) * page_size;
+
+ if (!(page_list = rt_malloc_align(list_size, page_size)))
+ {
+ return RT_NULL;
+ }
+
+ pages_data = page_list;
+ buf_base = (rt_uint8_t *)rt_rounddown((rt_ubase_t)buf, page_size);
+
+ for (int n = 0; num_pages; --num_pages)
+ {
+ pages_data->pages_list[n++] = (rt_uint64_t)rt_kmem_v2p(buf_base);
+ buf_base += page_size;
+
+ if (n == PAGELIST_ENTRIES_PER_PAGE)
+ {
+ pages_data->next_page_data = (rt_uint64_t)rt_kmem_v2p(pages_data + 1);
+ ++pages_data;
+ n = 0;
+ }
+ }
+
+ *out_paddr = (rt_ubase_t)rt_kmem_v2p(page_list) | page_offset;
+
+ return page_list;
+}
+
+static void free_page_list(void *page_list)
+{
+ rt_free_align(page_list);
+}
+
+static struct optee_msg_arg *alloc_msg_arg(rt_uint32_t params_nr)
+{
+ rt_size_t size;
+ struct optee_msg_arg *msg_arg;
+
+ size = OPTEE_MSG_GET_ARG_SIZE(params_nr);
+ msg_arg = rt_malloc_align(size, OPTEE_MSG_NONCONTIG_PAGE_SIZE);
+
+ if (!msg_arg)
+ {
+ return RT_NULL;
+ }
+
+ rt_memset(msg_arg, 0, size);
+ msg_arg->params_nr = params_nr;
+
+ return msg_arg;
+}
+
+static void free_msg_arg(struct optee_msg_arg *msg_arg)
+{
+ rt_free_align(msg_arg);
+}
+
+static void supplicant_cmd_shm_alloc(struct optee_device *optee,
+ struct optee_msg_arg *msg_arg, void **page_list)
+{
+ rt_err_t err;
+ rt_uint64_t paddr;
+ struct rt_tee_shm *shm;
+
+ msg_arg->ret_origin = RT_TEE_ORIGIN_COMMS;
+
+ if (msg_arg->params_nr != 1 ||
+ msg_arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
+ {
+ msg_arg->ret = RT_TEE_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ if (!(shm = rt_calloc(1, sizeof(*shm))))
+ {
+ msg_arg->ret = RT_TEE_ERROR_OUT_OF_MEMORY;
+ return;
+ }
+
+ shm->size = msg_arg->params[0].value.b;
+ shm->align = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+ shm->flags = TEE_SHM_SYS;
+
+ if ((err = rt_tee_shm_register(&optee->parent, shm)))
+ {
+ if (err == -RT_ENOMEM)
+ {
+ msg_arg->ret = RT_TEE_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ msg_arg->ret = RT_TEE_ERROR_GENERIC;
+ }
+
+ rt_free(shm);
+ return;
+ }
+
+ if (!(*page_list = alloc_page_list(shm->vaddr, shm->size, &paddr)))
+ {
+ msg_arg->ret = RT_TEE_ERROR_OUT_OF_MEMORY;
+
+ rt_tee_shm_unregister(&optee->parent, shm);
+ rt_free(shm);
+ return;
+ }
+
+ msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
+ OPTEE_MSG_ATTR_NONCONTIG;
+ msg_arg->params[0].tmem.buf_ptr = paddr;
+ msg_arg->params[0].tmem.size = shm->size;
+ msg_arg->params[0].tmem.shm_ref = (rt_ubase_t)(void *)shm;
+ msg_arg->ret = RT_TEE_SUCCESS;
+}
+
+static void supplicant_cmd_shm_free(struct optee_device *optee,
+ struct optee_msg_arg *msg_arg)
+{
+ struct rt_tee_shm *shm;
+ rt_err_t err;
+
+ msg_arg->ret_origin = RT_TEE_ORIGIN_COMMS;
+
+ if (msg_arg->params_nr != 1 ||
+ msg_arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
+ {
+ msg_arg->ret = RT_TEE_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ shm = (struct rt_tee_shm *)(rt_ubase_t)msg_arg->params[0].value.b;
+ if (!shm)
+ {
+ msg_arg->ret = RT_TEE_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ if ((err = rt_tee_shm_unregister(&optee->parent, shm)))
+ {
+ msg_arg->ret = RT_TEE_ERROR_GENERIC;
+ return;
+ }
+
+ rt_tee_shm_free_helper(shm);
+ rt_free(shm);
+ msg_arg->ret = RT_TEE_SUCCESS;
+}
+
+static void supplicant_cmd_i2c_transfer(struct optee_msg_arg *msg_arg)
+{
+#ifdef RT_USING_I2C
+ char devname[RT_NAME_MAX];
+ struct rt_tee_shm *shm;
+ struct rt_i2c_msg msg;
+ struct rt_i2c_bus_device *adapter;
+ const rt_uint8_t attr[] =
+ {
+ OPTEE_MSG_ATTR_TYPE_VALUE_INPUT,
+ OPTEE_MSG_ATTR_TYPE_VALUE_INPUT,
+ OPTEE_MSG_ATTR_TYPE_RMEM_INOUT,
+ OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT,
+ };
+
+ if (msg_arg->params_nr != RT_ARRAY_SIZE(attr) ||
+ msg_arg->params[0].attr != attr[0] ||
+ msg_arg->params[1].attr != attr[1] ||
+ msg_arg->params[2].attr != attr[2] ||
+ msg_arg->params[3].attr != attr[3])
+ {
+ msg_arg->ret = RT_TEE_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ shm = (void *)msg_arg->params[2].rmem.shm_ref;
+
+ rt_sprintf(devname, "i2c%u", msg_arg->params[0].value.b);
+
+ if (!(adapter = rt_i2c_bus_device_find(devname)))
+ {
+ goto _not_supp;
+ }
+
+ if (msg_arg->params[1].value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT)
+ {
+ if (!(adapter->flags & RT_I2C_ADDR_10BIT))
+ {
+ goto _not_supp;
+ }
+
+ msg.flags = RT_I2C_ADDR_10BIT;
+ }
+
+ msg.addr = msg_arg->params[0].value.c;
+ msg.len = msg_arg->params[2].rmem.size;
+ msg.buf = shm->vaddr;
+
+ switch (msg_arg->params[0].value.a)
+ {
+ case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD:
+ msg.flags |= RT_I2C_RD;
+ break;
+
+ case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR:
+ break;
+
+ default:
+ goto _not_supp;
+ }
+
+ if (rt_i2c_transfer(adapter, &msg, 1) <= 0)
+ {
+ msg_arg->ret = RT_TEE_ERROR_COMMUNICATION;
+ }
+ else
+ {
+ msg_arg->params[3].value.a = msg.len;
+ msg_arg->ret = RT_TEE_SUCCESS;
+ }
+
+ return;
+
+_not_supp:
+#endif /* RT_USING_I2C */
+ msg_arg->ret = RT_TEE_ERROR_NOT_SUPPORTED;
+}
+
+static void supplicant_cmd(struct optee_device *optee, struct rt_tee_shm *shm,
+ void **page_list)
+{
+ struct optee_msg_arg *msg_arg = shm->vaddr;
+
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, shm->vaddr, shm->size);
+
+ switch (msg_arg->cmd)
+ {
+ case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
+ supplicant_cmd_shm_alloc(optee, msg_arg, page_list);
+ break;
+
+ case OPTEE_MSG_RPC_CMD_SHM_FREE:
+ supplicant_cmd_shm_free(optee, msg_arg);
+ break;
+
+ case OPTEE_MSG_RPC_CMD_I2C_TRANSFER:
+ supplicant_cmd_i2c_transfer(msg_arg);
+ break;
+
+ default:
+ msg_arg->ret = RT_TEE_ERROR_NOT_IMPLEMENTED;
+ }
+}
+
+static rt_err_t call_with_arg(struct optee_device *optee,
+ struct optee_msg_arg *msg_arg)
+{
+ rt_err_t err;
+ void *arg_paddr, *page_list = NULL;
+ rt_ubase_t a0, a1, a2, a4, a5;
+ struct rt_tee_shm *shm;
+ struct arm_smccc_res_t res;
+
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH,
+ msg_arg, OPTEE_MSG_GET_ARG_SIZE(msg_arg->params_nr));
+
+ arg_paddr = rt_kmem_v2p(msg_arg);
+ a0 = OPTEE_SMC_CALL_WITH_ARG;
+ a1 = (rt_ubase_t)arg_paddr >> 32;
+ a2 = (rt_ubase_t)arg_paddr & RT_UINT32_MAX;
+ a4 = 0;
+ a5 = 0;
+
+ while (RT_TRUE)
+ {
+ optee->call(a0, a1, a2, 0, a4, a5, 0, 0, &res);
+ a4 = a5 = 0;
+
+ if (page_list)
+ {
+ free_page_list(page_list);
+ page_list = RT_NULL;
+ }
+
+ if (!OPTEE_SMC_RETURN_IS_RPC(res.a0))
+ {
+ err = res.a0 == OPTEE_SMC_RETURN_OK ? RT_EOK : -RT_EINVAL;
+ break;
+ }
+
+ switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(res.a0))
+ {
+ case OPTEE_SMC_RPC_FUNC_ALLOC:
+ if (!(shm = rt_calloc(1, sizeof(*shm))))
+ {
+ return -RT_ENOMEM;
+ }
+
+ shm->align = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+ shm->size = res.a1;
+
+ if (rt_tee_shm_alloc_helper(shm) == RT_EOK)
+ {
+ arg_paddr = (void *)shm->paddr;
+ a1 = (rt_ubase_t)arg_paddr >> 32;
+ a2 = (rt_ubase_t)arg_paddr & RT_UINT32_MAX;
+
+ /* Cookie */
+ arg_paddr = (void *)shm;
+ a4 = (rt_ubase_t)arg_paddr >> 32;
+ a5 = (rt_ubase_t)arg_paddr & RT_UINT32_MAX;
+ }
+ else
+ {
+ rt_free(shm);
+ a1 = a2 = 0;
+ }
+ break;
+
+ case OPTEE_SMC_RPC_FUNC_FREE:
+ shm = (void *)(((rt_uint64_t)res.a1 << 32) | res.a2);
+
+ rt_tee_shm_free_helper(shm);
+ rt_free(shm);
+ break;
+
+ case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
+ break;
+
+ case OPTEE_SMC_RPC_FUNC_CMD:
+ shm = (void *)(((rt_uint64_t)res.a1 << 32) | res.a2);
+
+ supplicant_cmd(optee, shm, &page_list);
+ break;
+
+ default:
+ break;
+ }
+
+ a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+ }
+
+ return err;
+}
+
+static rt_err_t optee_get_version(struct rt_tee_device *tdev,
+ struct rt_tee_version *out_version)
+{
+ out_version->impl_id = TEE_IMPL_ID_OPTEE;
+ out_version->impl_caps = TEE_OPTEE_CAP_TZ;
+ out_version->gen_caps = TEE_GEN_CAP_GP;
+
+ return RT_EOK;
+}
+
+static rt_err_t optee_open_session(struct rt_tee_device *tdev,
+ struct rt_tee_open_session_arg *arg)
+{
+ rt_err_t err;
+ struct optee_msg_arg *msg_arg;
+ struct optee_device *optee = raw_to_optee(tdev);
+
+ if (!(msg_arg = alloc_msg_arg(arg->params_nr + 2)))
+ {
+ return -RT_ENOMEM;
+ }
+
+ msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
+ msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+ OPTEE_MSG_ATTR_META;
+ msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+ OPTEE_MSG_ATTR_META;
+ rt_memcpy(&msg_arg->params[0].value, arg->uuid, sizeof(arg->uuid));
+ rt_memcpy(&msg_arg->params[1].value, arg->clnt_uuid, sizeof(arg->clnt_uuid));
+ msg_arg->params[1].value.c = arg->clnt_login;
+
+ if ((err = to_msg_param(msg_arg->params + 2, arg->params_nr, arg->params)))
+ {
+ goto _free_msg_arg;
+ }
+
+ if ((err = call_with_arg(optee, msg_arg)))
+ {
+ if (err == -RT_ENOMEM)
+ {
+ arg->ret = RT_TEE_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ arg->ret = RT_TEE_ERROR_GENERIC;
+ }
+ arg->ret_origin = RT_TEE_ORIGIN_COMMS;
+ goto _free_msg_arg;
+ }
+
+ if ((err = from_msg_param(arg->params, arg->params_nr, msg_arg->params + 2)))
+ {
+ arg->ret = RT_TEE_ERROR_COMMUNICATION;
+ arg->ret_origin = RT_TEE_ORIGIN_COMMS;
+ tdev->ops->close_session(tdev, msg_arg->session);
+ goto _free_msg_arg;
+ }
+
+ arg->session = msg_arg->session;
+ arg->ret = msg_arg->ret;
+ arg->ret_origin = msg_arg->ret_origin;
+
+_free_msg_arg:
+ free_msg_arg(msg_arg);
+
+ return err;
+}
+
+static rt_err_t optee_close_session(struct rt_tee_device *tdev,
+ rt_uint32_t session)
+{
+ rt_err_t err;
+ struct optee_msg_arg *msg_arg;
+ struct optee_device *optee = raw_to_optee(tdev);
+
+ if (!(msg_arg = alloc_msg_arg(1)))
+ {
+ return -RT_ENOMEM;
+ }
+
+ msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+ msg_arg->session = session;
+ err = call_with_arg(optee, msg_arg);
+
+ free_msg_arg(msg_arg);
+
+ return err;
+}
+
+static rt_err_t optee_invoke(struct rt_tee_device *tdev,
+ struct rt_tee_invoke_arg *arg)
+{
+ rt_err_t err;
+ struct optee_msg_arg *msg_arg;
+ struct optee_device *optee = raw_to_optee(tdev);
+
+ if (!(msg_arg = alloc_msg_arg(arg->params_nr)))
+ {
+ return -RT_ENOMEM;
+ }
+
+ msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
+ msg_arg->func = arg->func;
+ msg_arg->session = arg->session;
+
+ if ((err = to_msg_param(msg_arg->params, arg->params_nr, arg->params)))
+ {
+ goto _free_msg_arg;
+ }
+
+ if ((err = call_with_arg(optee, msg_arg)))
+ {
+ if (err == -RT_ENOMEM)
+ {
+ arg->ret = RT_TEE_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ arg->ret = RT_TEE_ERROR_GENERIC;
+ }
+ arg->ret_origin = RT_TEE_ORIGIN_COMMS;
+ goto _free_msg_arg;
+ }
+
+ if ((err = from_msg_param(arg->params, arg->params_nr, msg_arg->params)))
+ {
+ arg->ret = RT_TEE_ERROR_COMMUNICATION;
+ arg->ret_origin = RT_TEE_ORIGIN_COMMS;
+ goto _free_msg_arg;
+ }
+
+ arg->ret = msg_arg->ret;
+ arg->ret_origin = msg_arg->ret_origin;
+
+_free_msg_arg:
+ free_msg_arg(msg_arg);
+
+ return err;
+}
+
+static rt_err_t optee_cancel(struct rt_tee_device *tdev,
+ rt_uint32_t session, rt_uint32_t cancel_id)
+{
+ rt_err_t err = RT_EOK;
+ struct optee_msg_arg *msg_arg;
+ struct optee_device *optee = raw_to_optee(tdev);
+
+ if (!(msg_arg = alloc_msg_arg(1)))
+ {
+ return -RT_ENOMEM;
+ }
+
+ msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
+ msg_arg->session = session;
+ msg_arg->cancel_id = cancel_id;
+ err = call_with_arg(optee, msg_arg);
+
+ free_msg_arg(msg_arg);
+
+ return err;
+}
+
+static rt_err_t optee_shm_register(struct rt_tee_device *tdev,
+ struct rt_tee_shm *shm)
+{
+ rt_err_t err;
+ rt_uint64_t paddr;
+ void *page_list;
+ struct optee_msg_arg *msg_arg;
+ struct optee_device *optee = raw_to_optee(tdev);
+
+ if (shm->flags & TEE_SHM_DRV && !shm->vaddr)
+ {
+ return -RT_ENOSYS;
+ }
+
+ if (!(msg_arg = alloc_msg_arg(1)))
+ {
+ return -RT_ENOMEM;
+ }
+
+ page_list = alloc_page_list(shm->vaddr, shm->size, &paddr);
+ if (!page_list)
+ {
+ err = -RT_ENOMEM;
+ goto _free_msg_arg;
+ }
+
+ msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM;
+ msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
+ OPTEE_MSG_ATTR_NONCONTIG;
+ msg_arg->params->tmem.buf_ptr = paddr;
+ msg_arg->params->tmem.shm_ref = (rt_ubase_t)shm;
+ msg_arg->params->tmem.size = shm->size;
+
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH,
+ msg_arg, OPTEE_MSG_GET_ARG_SIZE(msg_arg->params_nr));
+
+ if ((err = call_with_arg(optee, msg_arg)) || msg_arg->ret)
+ {
+ err = err ? : -RT_EINVAL;
+ }
+
+ free_page_list(page_list);
+
+_free_msg_arg:
+ free_msg_arg(msg_arg);
+
+ return err;
+}
+
+static rt_err_t optee_shm_unregister(struct rt_tee_device *tdev,
+ struct rt_tee_shm *shm)
+{
+ rt_err_t err;
+ struct optee_msg_arg *msg_arg;
+ struct optee_device *optee = raw_to_optee(tdev);
+
+ if (!(msg_arg = alloc_msg_arg(1)))
+ {
+ return -RT_ENOMEM;
+ }
+
+ msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
+ msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ msg_arg->params[0].rmem.shm_ref = (rt_ubase_t)shm;
+
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH,
+ msg_arg, OPTEE_MSG_GET_ARG_SIZE(msg_arg->params_nr));
+
+ if ((err = call_with_arg(optee, msg_arg)) || msg_arg->ret)
+ {
+ err = err ? : -RT_EINVAL;
+ }
+
+ free_msg_arg(msg_arg);
+
+ return err;
+}
+
+static struct rt_tee_ops optee_ops =
+{
+ .get_version = optee_get_version,
+ .open_session = optee_open_session,
+ .close_session = optee_close_session,
+ .invoke = optee_invoke,
+ .cancel = optee_cancel,
+ .shm_register = optee_shm_register,
+ .shm_unregister = optee_shm_unregister,
+};
+
+static rt_err_t optee_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ const char *method;
+ rt_uint32_t sec_caps;
+ struct rt_device *dev = &pdev->parent;
+ struct optee_device *optee = rt_calloc(1, sizeof(*optee));
+
+ if (!optee)
+ {
+ return -RT_ENOMEM;
+ }
+
+ if (!rt_dm_dev_prop_read_string(dev, "method", &method))
+ {
+ if (!rt_strcmp(method, "smc"))
+ {
+ optee->call = optee_call_smc;
+ }
+ else if (!rt_strcmp(method, "hvc"))
+ {
+ optee->call = optee_call_hvc;
+ }
+ else
+ {
+ err = -RT_EINVAL;
+ LOG_E("Invalid \"method\" property: %s", method);
+ goto _fail;
+ }
+ }
+ else
+ {
+ optee->call = optee_call_smc;
+ }
+
+ if (!msg_api_uid_is_optee_api(optee))
+ {
+ LOG_E("Not OP-TEE API supported");
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ if (!exchange_capabilities(optee, &sec_caps) ||
+ !(sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM))
+ {
+ LOG_E("Not OP-TEE capabilities supported");
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ optee->parent.ops = &optee_ops;
+
+ if ((err = rt_tee_device_register(&optee->parent)))
+ {
+ goto _fail;
+ }
+
+ dev->user_data = optee;
+
+ /* Enum services here */
+
+ return RT_EOK;
+
+_fail:
+ rt_free(optee);
+
+ return err;
+}
+
+static rt_err_t optee_remove(struct rt_platform_device *pdev)
+{
+ struct optee_device *optee = pdev->parent.user_data;
+
+ if (optee)
+ {
+ rt_tee_device_unregister(&optee->parent);
+ rt_free(optee);
+ pdev->parent.user_data = RT_NULL;
+ }
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id optee_ofw_ids[] =
+{
+ { .compatible = "linaro,optee-tz" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver optee_driver =
+{
+ .name = "optee-smc",
+ .ids = optee_ofw_ids,
+
+ .probe = optee_probe,
+ .remove = optee_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(optee_driver);
diff --git a/components/drivers/tee/optee/optee_examples.c b/components/drivers/tee/optee/optee_examples.c
new file mode 100755
index 0000000000..d383639191
--- /dev/null
+++ b/components/drivers/tee/optee/optee_examples.c
@@ -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);
diff --git a/components/drivers/tee/optee/optee_msg.h b/components/drivers/tee/optee/optee_msg.h
new file mode 100755
index 0000000000..75e3b63831
--- /dev/null
+++ b/components/drivers/tee/optee/optee_msg.h
@@ -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__ */
diff --git a/components/drivers/tee/optee/optee_smc.h b/components/drivers/tee/optee/optee_smc.h
new file mode 100755
index 0000000000..c5a69b6e25
--- /dev/null
+++ b/components/drivers/tee/optee/optee_smc.h
@@ -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__ */
diff --git a/components/drivers/tee/tee.c b/components/drivers/tee/tee.c
new file mode 100755
index 0000000000..368f003250
--- /dev/null
+++ b/components/drivers/tee/tee.c
@@ -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;
+}