From 1d7dccf72e49164d3e46324cfde8c6a114ed87ad Mon Sep 17 00:00:00 2001 From: SahilSonar Date: Mon, 20 Oct 2025 12:20:55 +0530 Subject: [PATCH 1/5] dvrgen.mk: Unset LD_LIBRARY_PATH - Fixes python2: symbol lookup error: python2: undefined symbol: _ZNSt3__122__libcpp_verbose_abortEPKcz --- scripts/drvgen/drvgen.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/drvgen/drvgen.mk b/scripts/drvgen/drvgen.mk index 06f05d5100e3..9983597d817d 100644 --- a/scripts/drvgen/drvgen.mk +++ b/scripts/drvgen/drvgen.mk @@ -67,7 +67,7 @@ $(DRVGEN_FILE_LIST): $(DRVGEN_TOOL) $(DWS_FILE) $(DRVGEN_FIG) $(PROJ_DTS_FILES) dws_path=$(srctree)/$(DRVGEN_PATH)/$$base_prj.dws ;\ if [ -f $$dws_path ] ; then \ mkdir -p $$prj_path ;\ - $(python) $(DRVGEN_TOOL) $$dws_path $$prj_path $$prj_path cust_dtsi;\ + env LD_LIBRARY_PATH="" $(python) $(DRVGEN_TOOL) $$dws_path $$prj_path $$prj_path cust_dtsi;\ fi \ done -- GitLab From 3e86b03d4ceb2e7265d8e2afbd8403ae7e3a548f Mon Sep 17 00:00:00 2001 From: SahilSonar Date: Wed, 5 Nov 2025 08:15:15 +0100 Subject: [PATCH 2/5] teei: Checkout from A11 Change-Id: Ic6ace154a728053b9aefb6861d8b5ce8b1dbc604 --- drivers/tee/teei/300/Makefile | 40 + drivers/tee/teei/300/common/include/fdrv.h | 33 + .../tee/teei/300/common/include/imsg_log.h | 115 + drivers/tee/teei/300/common/include/tee.h | 459 +++ .../teei/300/common/include/tee_client_api.h | 524 ++++ drivers/tee/teei/300/common/include/tee_drv.h | 306 ++ .../tee/teei/300/common/include/teei_ioc.h | 52 + .../teei/300/common/include/teei_secure_api.h | 37 + drivers/tee/teei/300/public/isee_kernel_api.h | 21 + drivers/tee/teei/300/tee/Makefile | 23 + drivers/tee/teei/300/tee/capi_proxy.c | 429 +++ drivers/tee/teei/300/tee/capi_proxy.h | 27 + drivers/tee/teei/300/tee/soter/Makefile | 14 + drivers/tee/teei/300/tee/soter/call.c | 445 +++ drivers/tee/teei/300/tee/soter/core.c | 282 ++ drivers/tee/teei/300/tee/soter/optee_msg.h | 400 +++ .../tee/teei/300/tee/soter/soter_private.h | 66 + drivers/tee/teei/300/tee/soter/soter_smc.h | 53 + drivers/tee/teei/300/tee/tee_client_api.c | 770 +++++ drivers/tee/teei/300/tee/tee_core.c | 1085 +++++++ drivers/tee/teei/300/tee/tee_private.h | 140 + drivers/tee/teei/300/tee/tee_shm.c | 396 +++ drivers/tee/teei/300/tee/tee_shm_pool.c | 153 + drivers/tee/teei/300/teei_fp/Makefile | 17 + drivers/tee/teei/300/teei_fp/fp_func.c | 265 ++ drivers/tee/teei/300/teei_fp/fp_func.h | 22 + drivers/tee/teei/300/teei_fp/teei_fp.h | 16 + drivers/tee/teei/300/tests/Makefile | 19 + drivers/tee/teei/300/tests/main.c | 113 + drivers/tee/teei/300/tests/main.h | 32 + drivers/tee/teei/300/tests/ta_core_api.h | 148 + drivers/tee/teei/300/tests/tee_api_defines.h | 450 +++ .../tee/teei/300/tests/teei_internal_types.h | 102 + .../tee/teei/300/tests/teei_ta_drv_types.h | 96 + drivers/tee/teei/300/tests/xtest_isee_1000.c | 2725 +++++++++++++++++ drivers/tee/teei/300/tests/xtest_isee_3000.c | 415 +++ drivers/tee/teei/300/tests/xtest_main.c | 148 + drivers/tee/teei/300/tests/xtest_main.h | 102 + drivers/tee/teei/300/tz_dcih/Makefile | 15 + drivers/tee/teei/300/tz_dcih/tz_dcih.c | 315 ++ drivers/tee/teei/300/tz_dcih/tz_dcih.h | 39 + drivers/tee/teei/300/tz_dcih/tz_dcih_test.c | 314 ++ drivers/tee/teei/300/tz_dcih/tz_dcih_test.h | 31 + drivers/tee/teei/300/tz_driver/Makefile | 32 + .../tee/teei/300/tz_driver/backward_driver.c | 346 +++ drivers/tee/teei/300/tz_driver/fdrv.c | 159 + drivers/tee/teei/300/tz_driver/include/TEEI.h | 113 + .../300/tz_driver/include/backward_driver.h | 39 + .../teei/300/tz_driver/include/irq_register.h | 27 + .../teei/300/tz_driver/include/notify_queue.h | 45 + .../teei/300/tz_driver/include/nt_smc_call.h | 138 + .../teei/300/tz_driver/include/sched_status.h | 17 + .../tee/teei/300/tz_driver/include/smc_id.h | 48 + .../teei/300/tz_driver/include/switch_queue.h | 28 + .../tee/teei/300/tz_driver/include/sysfs.h | 13 + .../300/tz_driver/include/teei_cancel_cmd.h | 17 + .../teei/300/tz_driver/include/teei_client.h | 126 + .../300/tz_driver/include/teei_client_main.h | 80 + .../include/teei_client_transfer_data.h | 22 + .../teei/300/tz_driver/include/teei_common.h | 186 ++ .../300/tz_driver/include/teei_common_types.h | 11 + .../teei/300/tz_driver/include/teei_debug.h | 40 + .../tee/teei/300/tz_driver/include/teei_fp.h | 13 + .../tee/teei/300/tz_driver/include/teei_id.h | 170 + .../300/tz_driver/include/teei_keymaster.h | 14 + .../teei/300/tz_driver/include/teei_list.h | 164 + .../tee/teei/300/tz_driver/include/teei_log.h | 13 + .../300/tz_driver/include/teei_smc_call.h | 12 + .../300/tz_driver/include/teei_smc_struct.h | 68 + .../300/tz_driver/include/teei_task_link.h | 20 + .../teei/300/tz_driver/include/tz_service.h | 27 + .../tee/teei/300/tz_driver/include/ut_drv.h | 90 + .../teei/300/tz_driver/include/utdriver_irq.h | 23 + .../300/tz_driver/include/utdriver_macro.h | 55 + .../teei/300/tz_driver/include/utos_version.h | 11 + .../teei/300/tz_driver/include/utr_tui_cmd.h | 40 + drivers/tee/teei/300/tz_driver/irq_register.c | 266 ++ drivers/tee/teei/300/tz_driver/log_perf.h | 72 + drivers/tee/teei/300/tz_driver/notify_queue.c | 275 ++ drivers/tee/teei/300/tz_driver/switch_queue.c | 238 ++ drivers/tee/teei/300/tz_driver/sysfs.c | 631 ++++ .../tee/teei/300/tz_driver/teei_cancel_cmd.c | 73 + .../tee/teei/300/tz_driver/teei_client_main.c | 1210 ++++++++ .../300/tz_driver/teei_client_transfer_data.c | 146 + drivers/tee/teei/300/tz_driver/teei_fp.c | 50 + .../tee/teei/300/tz_driver/teei_keymaster.c | 47 + .../tee/teei/300/tz_driver/teei_smc_call.c | 74 + .../tee/teei/300/tz_driver/teei_task_link.c | 99 + drivers/tee/teei/300/tz_driver/tz_log.c | 433 +++ drivers/tee/teei/300/tz_driver/tz_log.h | 66 + drivers/tee/teei/300/tz_driver/utr_tui_cmd.c | 135 + drivers/tee/teei/300/tz_vfs/Makefile | 14 + drivers/tee/teei/300/tz_vfs/TEEI.h | 83 + drivers/tee/teei/300/tz_vfs/VFS.h | 11 + drivers/tee/teei/300/tz_vfs/fp_vendor.c | 65 + drivers/tee/teei/300/tz_vfs/fp_vendor.h | 19 + drivers/tee/teei/300/tz_vfs/teei_id.h | 104 + drivers/tee/teei/300/tz_vfs/vfsFun.c | 340 ++ drivers/tee/teei/300/ut_keymaster/Makefile | 16 + .../tee/teei/300/ut_keymaster/ut_keymaster.c | 206 ++ drivers/tee/teei/300/ut_tester/Makefile | 14 + drivers/tee/teei/300/ut_tester/ut_tester.c | 138 + drivers/tee/teei/Kconfig | 2 +- 103 files changed, 18287 insertions(+), 1 deletion(-) create mode 100644 drivers/tee/teei/300/Makefile create mode 100644 drivers/tee/teei/300/common/include/fdrv.h create mode 100644 drivers/tee/teei/300/common/include/imsg_log.h create mode 100644 drivers/tee/teei/300/common/include/tee.h create mode 100644 drivers/tee/teei/300/common/include/tee_client_api.h create mode 100644 drivers/tee/teei/300/common/include/tee_drv.h create mode 100644 drivers/tee/teei/300/common/include/teei_ioc.h create mode 100644 drivers/tee/teei/300/common/include/teei_secure_api.h create mode 100644 drivers/tee/teei/300/public/isee_kernel_api.h create mode 100644 drivers/tee/teei/300/tee/Makefile create mode 100644 drivers/tee/teei/300/tee/capi_proxy.c create mode 100644 drivers/tee/teei/300/tee/capi_proxy.h create mode 100644 drivers/tee/teei/300/tee/soter/Makefile create mode 100644 drivers/tee/teei/300/tee/soter/call.c create mode 100644 drivers/tee/teei/300/tee/soter/core.c create mode 100644 drivers/tee/teei/300/tee/soter/optee_msg.h create mode 100644 drivers/tee/teei/300/tee/soter/soter_private.h create mode 100644 drivers/tee/teei/300/tee/soter/soter_smc.h create mode 100644 drivers/tee/teei/300/tee/tee_client_api.c create mode 100644 drivers/tee/teei/300/tee/tee_core.c create mode 100644 drivers/tee/teei/300/tee/tee_private.h create mode 100644 drivers/tee/teei/300/tee/tee_shm.c create mode 100644 drivers/tee/teei/300/tee/tee_shm_pool.c create mode 100644 drivers/tee/teei/300/teei_fp/Makefile create mode 100644 drivers/tee/teei/300/teei_fp/fp_func.c create mode 100644 drivers/tee/teei/300/teei_fp/fp_func.h create mode 100644 drivers/tee/teei/300/teei_fp/teei_fp.h create mode 100644 drivers/tee/teei/300/tests/Makefile create mode 100644 drivers/tee/teei/300/tests/main.c create mode 100644 drivers/tee/teei/300/tests/main.h create mode 100644 drivers/tee/teei/300/tests/ta_core_api.h create mode 100644 drivers/tee/teei/300/tests/tee_api_defines.h create mode 100644 drivers/tee/teei/300/tests/teei_internal_types.h create mode 100644 drivers/tee/teei/300/tests/teei_ta_drv_types.h create mode 100644 drivers/tee/teei/300/tests/xtest_isee_1000.c create mode 100644 drivers/tee/teei/300/tests/xtest_isee_3000.c create mode 100644 drivers/tee/teei/300/tests/xtest_main.c create mode 100644 drivers/tee/teei/300/tests/xtest_main.h create mode 100644 drivers/tee/teei/300/tz_dcih/Makefile create mode 100644 drivers/tee/teei/300/tz_dcih/tz_dcih.c create mode 100644 drivers/tee/teei/300/tz_dcih/tz_dcih.h create mode 100644 drivers/tee/teei/300/tz_dcih/tz_dcih_test.c create mode 100644 drivers/tee/teei/300/tz_dcih/tz_dcih_test.h create mode 100644 drivers/tee/teei/300/tz_driver/Makefile create mode 100644 drivers/tee/teei/300/tz_driver/backward_driver.c create mode 100644 drivers/tee/teei/300/tz_driver/fdrv.c create mode 100644 drivers/tee/teei/300/tz_driver/include/TEEI.h create mode 100644 drivers/tee/teei/300/tz_driver/include/backward_driver.h create mode 100644 drivers/tee/teei/300/tz_driver/include/irq_register.h create mode 100644 drivers/tee/teei/300/tz_driver/include/notify_queue.h create mode 100644 drivers/tee/teei/300/tz_driver/include/nt_smc_call.h create mode 100644 drivers/tee/teei/300/tz_driver/include/sched_status.h create mode 100644 drivers/tee/teei/300/tz_driver/include/smc_id.h create mode 100644 drivers/tee/teei/300/tz_driver/include/switch_queue.h create mode 100644 drivers/tee/teei/300/tz_driver/include/sysfs.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_cancel_cmd.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_client.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_client_main.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_client_transfer_data.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_common.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_common_types.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_debug.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_fp.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_id.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_keymaster.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_list.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_log.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_smc_call.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_smc_struct.h create mode 100644 drivers/tee/teei/300/tz_driver/include/teei_task_link.h create mode 100644 drivers/tee/teei/300/tz_driver/include/tz_service.h create mode 100644 drivers/tee/teei/300/tz_driver/include/ut_drv.h create mode 100644 drivers/tee/teei/300/tz_driver/include/utdriver_irq.h create mode 100644 drivers/tee/teei/300/tz_driver/include/utdriver_macro.h create mode 100644 drivers/tee/teei/300/tz_driver/include/utos_version.h create mode 100644 drivers/tee/teei/300/tz_driver/include/utr_tui_cmd.h create mode 100644 drivers/tee/teei/300/tz_driver/irq_register.c create mode 100644 drivers/tee/teei/300/tz_driver/log_perf.h create mode 100644 drivers/tee/teei/300/tz_driver/notify_queue.c create mode 100644 drivers/tee/teei/300/tz_driver/switch_queue.c create mode 100644 drivers/tee/teei/300/tz_driver/sysfs.c create mode 100644 drivers/tee/teei/300/tz_driver/teei_cancel_cmd.c create mode 100644 drivers/tee/teei/300/tz_driver/teei_client_main.c create mode 100644 drivers/tee/teei/300/tz_driver/teei_client_transfer_data.c create mode 100644 drivers/tee/teei/300/tz_driver/teei_fp.c create mode 100644 drivers/tee/teei/300/tz_driver/teei_keymaster.c create mode 100644 drivers/tee/teei/300/tz_driver/teei_smc_call.c create mode 100644 drivers/tee/teei/300/tz_driver/teei_task_link.c create mode 100644 drivers/tee/teei/300/tz_driver/tz_log.c create mode 100644 drivers/tee/teei/300/tz_driver/tz_log.h create mode 100644 drivers/tee/teei/300/tz_driver/utr_tui_cmd.c create mode 100644 drivers/tee/teei/300/tz_vfs/Makefile create mode 100644 drivers/tee/teei/300/tz_vfs/TEEI.h create mode 100644 drivers/tee/teei/300/tz_vfs/VFS.h create mode 100644 drivers/tee/teei/300/tz_vfs/fp_vendor.c create mode 100644 drivers/tee/teei/300/tz_vfs/fp_vendor.h create mode 100644 drivers/tee/teei/300/tz_vfs/teei_id.h create mode 100644 drivers/tee/teei/300/tz_vfs/vfsFun.c create mode 100644 drivers/tee/teei/300/ut_keymaster/Makefile create mode 100644 drivers/tee/teei/300/ut_keymaster/ut_keymaster.c create mode 100644 drivers/tee/teei/300/ut_tester/Makefile create mode 100644 drivers/tee/teei/300/ut_tester/ut_tester.c diff --git a/drivers/tee/teei/300/Makefile b/drivers/tee/teei/300/Makefile new file mode 100644 index 000000000000..61ef3ff3ead2 --- /dev/null +++ b/drivers/tee/teei/300/Makefile @@ -0,0 +1,40 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +$(info "CONFIG_MICROTRUST_TEE_SUPPORT=$(CONFIG_MICROTRUST_TEE_SUPPORT)") +$(info "CONFIG_MICROTRUST_TZ_DRIVER=$(CONFIG_MICROTRUST_TZ_DRIVER)") +$(info "CONFIG_MICROTRUST_VFS_DRIVER=$(CONFIG_MICROTRUST_VFS_DRIVER)") +$(info "CONFIG_MICROTRUST_FP_DRIVER=$(CONFIG_MICROTRUST_FP_DRIVER)") +$(info "CONFIG_MICROTRUST_DEBUG=$(CONFIG_MICROTRUST_DEBUG)") +$(info "CONFIG_MICROTRUST_TEST_DRIVERS=$(CONFIG_MICROTRUST_TEST_DRIVERS)") + +subdir-ccflags-y += -I$(src)/common/include + +subdir-ccflags-y += \ + -I$(src)/tz_dcih \ + -I$(src)/public \ + -I$(src)/tz_driver/include + +ifeq ($(CONFIG_MTPROF), y) +subdir-ccflags-y += -I$(srctree)/include/linux/ +endif + +subdir-ccflags-$(CONFIG_MICROTRUST_DEBUG) += -DDEBUG + +obj-y += tee/ +obj-$(CONFIG_MICROTRUST_TZ_DRIVER) += tz_driver/ +obj-$(CONFIG_MICROTRUST_VFS_DRIVER) += tz_vfs/ +obj-$(CONFIG_MICROTRUST_FP_DRIVER) += teei_fp/ +obj-$(CONFIG_MICROTRUST_KEYMASTER_DRIVER) += ut_keymaster/ +obj-y += tz_dcih/ +obj-$(CONFIG_MICROTRUST_TEST_DRIVERS) += tests/ +obj-$(CONFIG_MICROTRUST_UNITTEST_SUPPORT) += ut_tester/ diff --git a/drivers/tee/teei/300/common/include/fdrv.h b/drivers/tee/teei/300/common/include/fdrv.h new file mode 100644 index 000000000000..09674a1c7bb5 --- /dev/null +++ b/drivers/tee/teei/300/common/include/fdrv.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#ifndef __TEEI_FDRV_H__ +#define __TEEI_FDRV_H__ + +#include +#include +#include + +struct teei_fdrv { + void *buf; + int buff_size; + int call_type; + struct list_head list; +}; + +/* used by fdrv drivers */ +void register_fdrv(struct teei_fdrv *fdrv); + +int create_fdrv(struct teei_fdrv *fdrv); +int fdrv_notify(struct teei_fdrv *fdrv); + +void teei_handle_fdrv_call(struct NQ_entry *entry); + +/* used internally by tz_driver */ +int create_all_fdrv(void); +int __call_fdrv(struct fdrv_call_struct *fdrv_ent); + +#endif diff --git a/drivers/tee/teei/300/common/include/imsg_log.h b/drivers/tee/teei/300/common/include/imsg_log.h new file mode 100644 index 000000000000..185088e4a470 --- /dev/null +++ b/drivers/tee/teei/300/common/include/imsg_log.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef _ISEE_IMSG_LOG_H_ +#define _ISEE_IMSG_LOG_H_ + +#ifndef IMSG_TAG +#define IMSG_TAG "[ISEE DRV]" +#endif + +enum { + IMSG_LV_DISABLE = 0, + IMSG_LV_ERROR, + IMSG_LV_WARN, + IMSG_LV_INFO, + IMSG_LV_DEBUG, + IMSG_LV_TRACE +}; + +#if defined(CONFIG_MICROTRUST_DEBUG) +#define IMSG_LOG_LEVEL IMSG_LV_DEBUG +#define IMSG_PROFILE_LEVEL IMSG_LV_TRACE +#else +/* DO NOT change the log level, this is for production */ +#define IMSG_LOG_LEVEL IMSG_LV_WARN +#define IMSG_PROFILE_LEVEL IMSG_LV_TRACE +#endif + +#include +#include +#include + +uint32_t get_imsg_log_level(void); + +static inline unsigned long now_ms(void) +{ + struct timeval now_time; + + do_gettimeofday(&now_time); + return ((now_time.tv_sec * 1000000) + now_time.tv_usec)/1000; +} + +#define IMSG_PRINTK(fmt, ...) pr_info(fmt, ##__VA_ARGS__) +#define IMSG_PRINTK_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) + +#define IMSG_PRINT_ERROR(fmt, ...) pr_notice(fmt, ##__VA_ARGS__) +#define IMSG_PRINT_WARN(fmt, ...) pr_notice(fmt, ##__VA_ARGS__) +#define IMSG_PRINT_INFO(fmt, ...) pr_info(fmt, ##__VA_ARGS__) +#define IMSG_PRINT_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) +#define IMSG_PRINT_TRACE(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) +#define IMSG_PRINT_ENTER(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) +#define IMSG_PRINT_LEAVE(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) +#define IMSG_PRINT_PROFILE(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) + +#define IMSG_PRINT(level, func, fmt, ...) \ + do { \ + if (level <= get_imsg_log_level()) \ + IMSG_PRINT_##func("%s[%s]: " fmt, IMSG_TAG, \ + #func, ##__VA_ARGS__); \ + } while (0) + +#define IMSG_PRINT_TIME_S(level, fmt, ...) \ + unsigned long start_ms; \ + do { \ + start_ms = now_ms(); \ + IMSG_PRINT(level, PROFILE, fmt " (start:%lu)\n", \ + ##__VA_ARGS__, start_ms); \ + } while (0) + +#define IMSG_PRINT_TIME_E(level, fmt, ...) \ + do { \ + unsigned long end_ms, delta_ms; \ + end_ms = now_ms(); \ + delta_ms = end_ms - start_ms; \ + IMSG_PRINT(level, PROFILE, fmt " (end:%lu, spend:%lu ms)\n", \ + ##__VA_ARGS__, end_ms, delta_ms); \ + } while (0) + +/*************************************************************************/ +/* Declare macros ********************************************************/ +/*************************************************************************/ +#define IMSG_ERROR(fmt, ...) \ + IMSG_PRINT(IMSG_LV_ERROR, ERROR, fmt, ##__VA_ARGS__) +#define IMSG_WARN(fmt, ...) \ + IMSG_PRINT(IMSG_LV_WARN, WARN, fmt, ##__VA_ARGS__) +#define IMSG_INFO(fmt, ...) \ + IMSG_PRINT(IMSG_LV_INFO, INFO, fmt, ##__VA_ARGS__) +#define IMSG_DEBUG(fmt, ...) \ + IMSG_PRINT(IMSG_LV_DEBUG, DEBUG, fmt, ##__VA_ARGS__) +#define IMSG_TRACE(fmt, ...) \ + IMSG_PRINT(IMSG_LV_TRACE, TRACE, fmt, ##__VA_ARGS__) +#define IMSG_ENTER() \ + IMSG_PRINT(IMSG_LV_TRACE, ENTER, "%s\n", __func__) +#define IMSG_LEAVE() \ + IMSG_PRINT(IMSG_LV_TRACE, LEAVE, "%s\n", __func__) + +#define IMSG_PROFILE_S(fmt, ...) \ + IMSG_PRINT_TIME_S(IMSG_PROFILE_LEVEL, fmt, ##__VA_ARGS__) +#define IMSG_PROFILE_E(fmt, ...) \ + IMSG_PRINT_TIME_E(IMSG_PROFILE_LEVEL, fmt, ##__VA_ARGS__) + +/*************************************************************************/ +/* Declare Check Patch ***************************************************/ +/*************************************************************************/ +#define TZ_SEMA_INIT_0(x) sema_init(x, 0) +#define TZ_SEMA_INIT_1(x) sema_init(x, 1) +#define TZ_EMPTY_PARENTHESES(z) z +#define TZ_VOLATILE(x) TZ_EMPTY_PARENTHESES(vola##tile x) +#define TZ_NON_VOLATILE(x) x + +#endif /* _ISEE_IMSG_LOG_H_ */ diff --git a/drivers/tee/teei/300/common/include/tee.h b/drivers/tee/teei/300/common/include/tee.h new file mode 100644 index 000000000000..7e9801520e5b --- /dev/null +++ b/drivers/tee/teei/300/common/include/tee.h @@ -0,0 +1,459 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2016, Linaro Limited + * All rights reserved. + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All rights reserved. + * + */ + +#ifndef __TEE_H +#define __TEE_H + +#include +#include + +/* + * This file describes the API provided by a TEE driver to user space. + * + * Each TEE driver defines a TEE specific protocol which is used for the + * data passed back and forth using TEE_IOC_CMD. + */ + +/* Helpers to make the ioctl defines */ +#define TEE_IOC_MAGIC 0xa4 +#define TEE_IOC_BASE 0 + +/* Flags relating to shared memory */ +#define TEE_IOCTL_SHM_MAPPED 0x1 /* memory mapped in normal world */ +#define TEE_IOCTL_SHM_DMA_BUF 0x2 /* dma-buf handle on shared memory */ + +#define TEE_MAX_ARG_SIZE 1024 +#define TEE_MAX_HOSTNAME_SIZE 16 + +#define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ +#define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ + +/* + * TEE Implementation ID + */ +#define TEE_IMPL_ID_OPTEE 1 + +/* + * OP-TEE specific capabilities + */ +#define TEE_OPTEE_CAP_TZ (1 << 0) + +/** + * struct tee_ioctl_version_data - TEE version + * @impl_id: [out] TEE implementation id + * @impl_caps: [out] Implementation specific capabilities + * @gen_caps: [out] Generic capabilities, defined by TEE_GEN_CAPS_* above + * + * Identifies the TEE implementation, @impl_id is one of TEE_IMPL_ID_* above. + * @impl_caps is implementation specific, for example TEE_OPTEE_CAP_* + * is valid when @impl_id == TEE_IMPL_ID_OPTEE. + */ +struct tee_ioctl_version_data { + __u32 impl_id; + __u32 impl_caps; + __u32 gen_caps; +}; + +/** + * TEE_IOC_VERSION - query version of TEE + * + * Takes a tee_ioctl_version_data struct and returns with the TEE version + * data filled in. + */ +#define TEE_IOC_VERSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 0, \ + struct tee_ioctl_version_data) + +/** + * struct tee_ioctl_shm_alloc_data - Shared memory allocate argument + * @size: [in/out] Size of shared memory to allocate + * @flags: [in/out] Flags to/from allocation. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_ALLOC below. + */ +struct tee_ioctl_shm_alloc_data { + __u64 size; + __u32 flags; + __s32 id; +}; + +/** + * TEE_IOC_SHM_ALLOC - allocate shared memory + * + * Allocates shared memory between the user space process and secure OS. + * + * Returns a file descriptor on success or < 0 on failure + * + * The returned file descriptor is used to map the shared memory into user + * space. The shared memory is freed when the descriptor is closed and the + * memory is unmapped. + */ +#define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \ + struct tee_ioctl_shm_alloc_data) + +/** + * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument + * @fd: [in] file descriptor identifying the shared memory + * @size: [out] Size of shared memory to allocate + * @flags: [in] Flags to/from allocation. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_ALLOC below. + */ +struct tee_ioctl_shm_register_fd_data { + __s64 fd; + __u64 size; + __u32 flags; + __s32 id; +} __aligned(8); + +/** + * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor + * + * Returns a file descriptor on success or < 0 on failure + * + * The returned file descriptor refers to the shared memory object in kernel + * land. The shared memory is freed when the descriptor is closed. + */ +#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \ + struct tee_ioctl_shm_register_fd_data) + +/** + * struct tee_ioctl_buf_data - Variable sized buffer + * @buf_ptr: [in] A __user pointer to a buffer + * @buf_len: [in] Length of the buffer above + * + * Used as argument for TEE_IOC_OPEN_SESSION, TEE_IOC_INVOKE, + * TEE_IOC_SUPPL_RECV, and TEE_IOC_SUPPL_SEND below. + */ +struct tee_ioctl_buf_data { + __u64 buf_ptr; + __u64 buf_len; +}; + +/* + * Attributes for struct tee_ioctl_param, selects field in the union + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_NONE 0 /* parameter not used */ + +/* + * These defines value parameters (struct tee_ioctl_param_value) + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT 1 +#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2 +#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT 3 /* input and output */ + +/* + * These defines shared memory reference parameters (struct + * tee_ioctl_param_memref) + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT 5 +#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT 6 +#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT 7 /* input and output */ + +/* + * Mask for the type part of the attribute, leaves room for more types + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff + +/* Meta parameter carrying extra information about the message. */ +#define TEE_IOCTL_PARAM_ATTR_META 0x100 + +/* Mask of all known attr bits */ +#define TEE_IOCTL_PARAM_ATTR_MASK \ + (TEE_IOCTL_PARAM_ATTR_TYPE_MASK | TEE_IOCTL_PARAM_ATTR_META) + +/* + * Matches TEEC_LOGIN_* in GP TEE Client API + * Are only defined for GP compliant TEEs + */ +#define TEE_IOCTL_LOGIN_PUBLIC 0 +#define TEE_IOCTL_LOGIN_USER 1 +#define TEE_IOCTL_LOGIN_GROUP 2 +#define TEE_IOCTL_LOGIN_APPLICATION 4 +#define TEE_IOCTL_LOGIN_USER_APPLICATION 5 +#define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6 + +/** + * struct tee_ioctl_param - parameter + * @attr: attributes + * @a: if a memref, offset into the shared memory object, else a value parameter + * @b: if a memref, size of the buffer, else a value parameter + * @c: if a memref, shared memory identifier, else a value parameter + * + * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in + * the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and + * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE + * indicates that none of the members are used. + * + * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an + * identifier representing the shared memory object. A memref can reference + * a part of a shared memory by specifying an offset (@a) and size (@b) of + * the object. To supply the entire shared memory object set the offset + * (@a) to 0 and size (@b) to the previously returned size of the object. + */ +struct tee_ioctl_param { + __u64 attr; + union { + __u64 a; + __u64 shm_offs; + }; + union { + __u64 b; + __u64 size; + }; + union { + __u64 c; + __s64 shm_id; + }; +}; + +#define TEE_IOCTL_UUID_LEN 16 + +/** + * struct tee_ioctl_open_session_arg - Open session argument + * @uuid: [in] UUID of the Trusted Application + * @clnt_uuid: [in] UUID of client + * @clnt_login: [in] Login class of client, TEE_IOCTL_LOGIN_* above + * @cancel_id: [in] Cancellation id, a unique value to identify this request + * @session: [out] Session id + * @ret: [out] return value + * @ret_origin [out] origin of the return value + * @num_params [in] number of parameters following this struct + */ +struct tee_ioctl_open_session_arg { + __u8 uuid[TEE_IOCTL_UUID_LEN]; + __u8 clnt_uuid[TEE_IOCTL_UUID_LEN]; + __u32 clnt_login; + __u32 cancel_id; + __u32 session; + __u32 ret; + __u32 ret_origin; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_ioctl_open_session_arg followed by any array of struct + * tee_ioctl_param + */ +#define TEE_IOC_OPEN_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 2, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted + * Application + * @func: [in] Trusted Application function, specific to the TA + * @session: [in] Session id + * @cancel_id: [in] Cancellation id, a unique value to identify this request + * @ret: [out] return value + * @ret_origin [out] origin of the return value + * @num_params [in] number of parameters following this struct + */ +struct tee_ioctl_invoke_arg { + __u32 func; + __u32 session; + __u32 cancel_id; + __u32 ret; + __u32 ret_origin; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_INVOKE - Invokes a function in a Trusted Application + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_invoke_func_arg followed by any array of struct tee_param + */ +#define TEE_IOC_INVOKE _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 3, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_ioctl_cancel_arg - Cancels an open session or invoke ioctl + * @cancel_id: [in] Cancellation id, a unique value to identify this request + * @session: [in] Session id, if the session is opened, else set to 0 + */ +struct tee_ioctl_cancel_arg { + __u32 cancel_id; + __u32 session; +}; + +/** + * TEE_IOC_CANCEL - Cancels an open session or invoke + */ +#define TEE_IOC_CANCEL _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 4, \ + struct tee_ioctl_cancel_arg) + +/** + * struct tee_ioctl_close_session_arg - Closes an open session + * @session: [in] Session id + */ +struct tee_ioctl_close_session_arg { + __u32 session; +}; + +/** + * TEE_IOC_CLOSE_SESSION - Closes a session + */ +#define TEE_IOC_CLOSE_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 5, \ + struct tee_ioctl_close_session_arg) + +/** + * struct tee_iocl_supp_recv_arg - Receive a request for a supplicant function + * @func: [in] supplicant function + * @num_params [in/out] number of parameters following this struct + * + * @num_params is the number of params that tee-supplicant has room to + * receive when input, @num_params is the number of actual params + * tee-supplicant receives when output. + */ +struct tee_iocl_supp_recv_arg { + __u32 func; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_iocl_supp_recv_arg followed by any array of struct tee_param + */ +#define TEE_IOC_SUPPL_RECV _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 6, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_iocl_supp_send_arg - Send a response to a received request + * @ret: [out] return value + * @num_params [in] number of parameters following this struct + */ +struct tee_iocl_supp_send_arg { + __u32 ret; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_iocl_supp_send_arg followed by any array of struct tee_param + */ +#define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_ioctl_set_hostname - Set hostname in context data structure + * @hostname: [in] Hostname + */ +struct tee_ioctl_set_hostname_arg { + __u8 hostname[TEE_MAX_HOSTNAME_SIZE]; +}; + +/** + * TEE_IOC_SET_HOSTNAME - Set hostname in context data structure + */ +#define TEE_IOC_SET_HOSTNAME _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \ + struct tee_ioctl_set_hostname_arg) + +/** + * struct tee_ioctl_shm_kern_op_arg - Kernel operations for shared memory + * @id: [in] Identifier of the shared memory + * @opcode: [in] kernel operation for the specific shared memory + * @paddr: [out] The starting physical address of the shared memory + */ +struct tee_ioctl_shm_kern_op_arg { + __s32 id; + __u32 opcode; + __u64 paddr; +}; + +#define TEE_IOCTL_SHM_KERN_OP_GET_PA 0 +#define TEE_IOCTL_SHM_KERN_OP_FLUSH_CACHE 1 +#define TEE_IOCTL_SHM_KERN_OP_INVALID_CACHE 2 + +/** + * TEE_IOC_SHM_KERN_OP - kernel operations for specific shared memory + */ +#define TEE_IOC_SHM_KERN_OP _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 10, \ + struct tee_ioctl_shm_kern_op_arg) + +struct capi_proxy_param_value { + __u64 a; + __u64 b; + __u64 c; /* reserved */ + __u64 d; /* reserved */ +}; + +struct capi_proxy_param_memref { + __u64 buffer; + __u64 size; + __u64 shm_offset; + __u64 shm_id; +}; + +struct capi_proxy_param { + __u64 attr; + union { + struct capi_proxy_param_value value; + struct capi_proxy_param_memref memref; + }; +}; + +/** + * struct tee_ioctl_capi_proxy_arg - CAPI proxy driver parameter + * @uuid: [in] TA UUID to communication with + * @capi_op: [in] CAPI operation: open_session, invoke_command, etc. + * @session: [in/out] Session for CAPI operations + * @func: [in] command id of invoke_command + * @ret: [out] Return values + * @reg_orig: [out] Function error origins + * @params: [in] TEEC parameters + */ +struct tee_ioctl_capi_proxy_arg { + __u8 uuid[TEE_IOCTL_UUID_LEN]; + __u32 capi_op; + __u32 session; + __u32 func; + __u32 ret; + __u32 ret_orig; + struct capi_proxy_param params[4]; +} __aligned(8); + +/** + * TEE_IOC_CAPI_PROXY - for communication with CAPI proxy driver + */ +#define TEE_IOC_CAPI_PROXY _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 11, \ + struct tee_ioctl_capi_proxy_arg) + +/* + * Five syscalls are used when communicating with the TEE driver. + * open(): opens the device associated with the driver + * ioctl(): as described above operating on the file descriptor from open() + * close(): two cases + * - closes the device file descriptor + * - closes a file descriptor connected to allocated shared memory + * mmap(): maps shared memory into user space using information from struct + * tee_ioctl_shm_alloc_data + * munmap(): unmaps previously shared memory + */ + +#endif /*__TEE_H*/ diff --git a/drivers/tee/teei/300/common/include/tee_client_api.h b/drivers/tee/teei/300/common/include/tee_client_api.h new file mode 100644 index 000000000000..619e6841989c --- /dev/null +++ b/drivers/tee/teei/300/common/include/tee_client_api.h @@ -0,0 +1,524 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All rights reserved. + * + */ +#ifndef TEE_CLIENT_API_H +#define TEE_CLIENT_API_H + +#ifndef __KERNEL__ +#include +#include +#endif /* __KERNEL__ */ + +#include + +/* + * Defines the number of available memory references in an open session or + * invoke command operation payload. + */ +#define TEEC_CONFIG_PAYLOAD_REF_COUNT 4 + +/** + * Defines the maximum size of a single shared memory block, in bytes, of both + * API allocated and API registered memory. The size is currently set to + * 512 * kB (512 * 1024). + */ +#define TEEC_CONFIG_SHAREDMEM_MAX_SIZE 0x8000 + +/** + * Flag constants indicating the type of parameters encoded inside the + * operation payload (TEEC_Operation), Type is uint32_t. + * + * TEEC_NONE The Parameter is not used + * + * TEEC_VALUE_INPUT The Parameter is a TEEC_Value tagged as input. + * + * TEEC_VALUE_OUTPUT The Parameter is a TEEC_Value tagged as output. + * + * TEEC_VALUE_INOUT The Parameter is a TEEC_Value tagged as both as + * input and output, i.e., for which both the + * behaviors of TEEC_VALUE_INPUT and + * TEEC_VALUE_OUTPUT apply. + * + * TEEC_MEMREF_TEMP_INPUT The Parameter is a TEEC_TempMemoryReference + * describing a region of memory which needs to be + * temporarily registered for the duration of the + * Operation and is tagged as input. + * + * TEEC_MEMREF_TEMP_OUTPUT Same as TEEC_MEMREF_TEMP_INPUT, but the Memory + * Reference is tagged as output. The + * Implementation may update the size field to + * reflect the required output size in some use + * cases. + * + * TEEC_MEMREF_TEMP_INOUT A Temporary Memory Reference tagged as both + * input and output, i.e., for which both the + * behaviors of TEEC_MEMREF_TEMP_INPUT and + * TEEC_MEMREF_TEMP_OUTPUT apply. + * + * TEEC_MEMREF_WHOLE The Parameter is a Registered Memory Reference + * that refers to the entirety of its parent Shared + * Memory block. The parameter structure is a + * TEEC_MemoryReference. In this structure, the + * Implementation MUST read only the parent field + * and MAY update the size field when the operation + * completes. + * + * TEEC_MEMREF_PARTIAL_INPUT A Registered Memory Reference structure that + * refers to a partial region of its parent Shared + * Memory block and is tagged as input. + * + * TEEC_MEMREF_PARTIAL_OUTPUT Registered Memory Reference structure that + * refers to a partial region of its parent Shared + * Memory block and is tagged as output. + * + * TEEC_MEMREF_PARTIAL_INOUT The Registered Memory Reference structure that + * refers to a partial region of its parent Shared + * Memory block and is tagged as both input and + * output, i.e., for which both the behaviors of + * TEEC_MEMREF_PARTIAL_INPUT and + * TEEC_MEMREF_PARTIAL_OUTPUT apply. + */ +#define TEEC_NONE 0x00000000 +#define TEEC_VALUE_INPUT 0x00000001 +#define TEEC_VALUE_OUTPUT 0x00000002 +#define TEEC_VALUE_INOUT 0x00000003 +#define TEEC_MEMREF_TEMP_INPUT 0x00000005 +#define TEEC_MEMREF_TEMP_OUTPUT 0x00000006 +#define TEEC_MEMREF_TEMP_INOUT 0x00000007 +#define TEEC_MEMREF_WHOLE 0x0000000C +#define TEEC_MEMREF_PARTIAL_INPUT 0x0000000D +#define TEEC_MEMREF_PARTIAL_OUTPUT 0x0000000E +#define TEEC_MEMREF_PARTIAL_INOUT 0x0000000F + +/** + * Flag constants indicating the data transfer direction of memory in + * TEEC_Parameter. TEEC_MEM_INPUT signifies data transfer direction from the + * client application to the TEE. TEEC_MEM_OUTPUT signifies data transfer + * direction from the TEE to the client application. Type is uint32_t. + * + * TEEC_MEM_INPUT The Shared Memory can carry data from the client + * application to the Trusted Application. + * TEEC_MEM_OUTPUT The Shared Memory can carry data from the Trusted + * Application to the client application. + */ +#define TEEC_MEM_INPUT 0x00000001 +#define TEEC_MEM_OUTPUT 0x00000002 + +/** + * Return values. Type is TEEC_Result + * + * TEEC_SUCCESS The operation was successful. + * TEEC_ERROR_GENERIC Non-specific cause. + * TEEC_ERROR_ACCESS_DENIED Access privileges are not sufficient. + * TEEC_ERROR_CANCEL The operation was canceled. + * TEEC_ERROR_ACCESS_CONFLICT Concurrent accesses caused conflict. + * TEEC_ERROR_EXCESS_DATA Too much data for the requested operation was + * passed. + * TEEC_ERROR_BAD_FORMAT Input data was of invalid format. + * TEEC_ERROR_BAD_PARAMETERS Input parameters were invalid. + * TEEC_ERROR_BAD_STATE Operation is not valid in the current state. + * TEEC_ERROR_ITEM_NOT_FOUND The requested data item is not found. + * TEEC_ERROR_NOT_IMPLEMENTED The requested operation should exist but is not + * yet implemented. + * TEEC_ERROR_NOT_SUPPORTED The requested operation is valid but is not + * supported in this implementation. + * TEEC_ERROR_NO_DATA Expected data was missing. + * TEEC_ERROR_OUT_OF_MEMORY System ran out of resources. + * TEEC_ERROR_BUSY The system is busy working on something else. + * TEEC_ERROR_COMMUNICATION Communication with a remote party failed. + * TEEC_ERROR_SECURITY A security fault was detected. + * TEEC_ERROR_SHORT_BUFFER The supplied buffer is too short for the + * generated output. + * TEEC_ERROR_TARGET_DEAD Trusted Application has panicked + * during the operation. + */ + +/** + * Standard defined error codes. + */ +#define TEEC_SUCCESS 0x00000000 +#define TEEC_ERROR_GENERIC 0xFFFF0000 +#define TEEC_ERROR_ACCESS_DENIED 0xFFFF0001 +#define TEEC_ERROR_CANCEL 0xFFFF0002 +#define TEEC_ERROR_ACCESS_CONFLICT 0xFFFF0003 +#define TEEC_ERROR_EXCESS_DATA 0xFFFF0004 +#define TEEC_ERROR_BAD_FORMAT 0xFFFF0005 +#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 +#define TEEC_ERROR_BAD_STATE 0xFFFF0007 +#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008 +#define TEEC_ERROR_NOT_IMPLEMENTED 0xFFFF0009 +#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A +#define TEEC_ERROR_NO_DATA 0xFFFF000B +#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C +#define TEEC_ERROR_BUSY 0xFFFF000D +#define TEEC_ERROR_COMMUNICATION 0xFFFF000E +#define TEEC_ERROR_SECURITY 0xFFFF000F +#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010 +#define TEEC_ERROR_EXTERNAL_CANCEL 0xFFFF0011 +#define TEEC_ERROR_TARGET_DEAD 0xFFFF3024 + +/** + * Function error origins, of type TEEC_ErrorOrigin. These indicate where in + * the software stack a particular return value originates from. + * + * TEEC_ORIGIN_API The error originated within the TEE Client API + * implementation. + * TEEC_ORIGIN_COMMS The error originated within the underlying + * communications stack linking the rich OS with + * the TEE. + * TEEC_ORIGIN_TEE The error originated within the common TEE code. + * TEEC_ORIGIN_TRUSTED_APP The error originated within the Trusted Application + * code. + */ +#define TEEC_ORIGIN_API 0x00000001 +#define TEEC_ORIGIN_COMMS 0x00000002 +#define TEEC_ORIGIN_TEE 0x00000003 +#define TEEC_ORIGIN_TRUSTED_APP 0x00000004 + +/** + * Session login methods, for use in TEEC_OpenSession() as parameter + * connectionMethod. Type is uint32_t. + * + * TEEC_LOGIN_PUBLIC No login data is provided. + * TEEC_LOGIN_USER Login data about the user running the Client + * Application process is provided. + * TEEC_LOGIN_GROUP Login data about the group running the Client + * Application process is provided. + * TEEC_LOGIN_APPLICATION Login data about the running Client Application + * itself is provided. + * TEEC_LOGIN_USER_APPLICATION Login data about the user and the running + * Client Application itself is provided. + * TEEC_LOGIN_GROUP_APPLICATION Login data about the group and the running + * Client Application itself is provided. + */ +#define TEEC_LOGIN_PUBLIC 0x00000000 +#define TEEC_LOGIN_USER 0x00000001 +#define TEEC_LOGIN_GROUP 0x00000002 +#define TEEC_LOGIN_APPLICATION 0x00000004 +#define TEEC_LOGIN_USER_APPLICATION 0x00000005 +#define TEEC_LOGIN_GROUP_APPLICATION 0x00000006 + +/** + * Encode the paramTypes according to the supplied types. + * + * @param p0 The first param type. + * @param p1 The second param type. + * @param p2 The third param type. + * @param p3 The fourth param type. + */ +#define TEEC_PARAM_TYPES(p0, p1, p2, p3) \ + ((p0) | ((p1) << 4) | ((p2) << 8) | ((p3) << 12)) + +/** + * Get the i_th param type from the paramType. + * + * @param p The paramType. + * @param i The i-th parameter to get the type for. + */ +#define TEEC_PARAM_TYPE_GET(p, i) (((p) >> (i * 4)) & 0xF) + +#define TEEC_Result uint32_t + +/** + * struct TEEC_Context - Represents a connection between a client application + * and a TEE. + */ +struct TEEC_Context { + /* Implementation defined */ + struct file *fd; +}; + +/** + * This type contains a Universally Unique Resource Identifier (UUID) type as + * defined in RFC4122. These UUID values are used to identify Trusted + * Applications. + */ +struct TEEC_UUID { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint8_t clockSeqAndNode[8]; +}; + +/** + * struct TEEC_SharedMemory - Memory to transfer data between a client + * application and trusted code. + * + * @param buffer The memory buffer which is to be, or has been, shared + * with the TEE. + * @param size The size, in bytes, of the memory buffer. + * @param flags Bit-vector which holds properties of buffer. + * The bit-vector can contain either or both of the + * TEEC_MEM_INPUT and TEEC_MEM_OUTPUT flags. + * + * A shared memory block is a region of memory allocated in the context of the + * client application memory space that can be used to transfer data between + * that client application and a trusted application. The user of this struct + * is responsible to populate the buffer pointer. + */ +struct TEEC_SharedMemory { + void *buffer; + size_t size; + uint32_t flags; + /* + * Implementation-Defined + */ + int id; + size_t alloced_size; + void *shadow_buffer; + int registered_fd; + void *priv; +}; + +/** + * struct TEEC_TempMemoryReference - Temporary memory to transfer data between + * a client application and trusted code, only used for the duration of the + * operation. + * + * @param buffer The memory buffer which is to be, or has been shared with + * the TEE. + * @param size The size, in bytes, of the memory buffer. + * + * A memory buffer that is registered temporarily for the duration of the + * operation to be called. + */ +struct TEEC_TempMemoryReference { + void *buffer; + size_t size; +}; + +/** + * struct TEEC_RegisteredMemoryReference - use a pre-registered or + * pre-allocated shared memory block of memory to transfer data between + * a client application and trusted code. + * + * @param parent Points to a shared memory structure. The memory reference + * may utilize the whole shared memory or only a part of it. + * Must not be NULL + * + * @param size The size, in bytes, of the memory buffer. + * + * @param offset The offset, in bytes, of the referenced memory region from + * the start of the shared memory block. + * + */ +struct TEEC_RegisteredMemoryReference { + struct TEEC_SharedMemory *parent; + size_t size; + size_t offset; +}; + +/** + * struct TEEC_Value - Small raw data container + * + * Instead of allocating a shared memory buffer this structure can be used + * to pass small raw data between a client application and trusted code. + * + * @param a The first integer value. + * + * @param b The second second value. + */ +struct TEEC_Value { + uint32_t a; + uint32_t b; +}; + +/** + * union TEEC_Parameter - Memory container to be used when passing data between + * client application and trusted code. + * + * Either the client uses a shared memory reference, parts of it or a small raw + * data container. + * + * @param tmpref A temporary memory reference only valid for the duration + * of the operation. + * + * @param memref The entire shared memory or parts of it. + * + * @param value The small raw data container to use + */ +union TEEC_Parameter { + struct TEEC_TempMemoryReference tmpref; + struct TEEC_RegisteredMemoryReference memref; + struct TEEC_Value value; +}; + +/** + * struct TEEC_Session - Represents a connection between a client application + * and a trusted application. + */ +struct TEEC_Session { + /* Implementation defined */ + struct TEEC_Context *ctx; + uint32_t session_id; +}; + +/** + * struct TEEC_Operation - Holds information and memory references used in + * TEEC_InvokeCommand(). + * + * @param started Client must initialize to zero if it needs to cancel + * an operation about to be performed. + * @param paramTypes Type of data passed. Use TEEC_PARAMS_TYPE macro to + * create the correct flags. + * 0 means TEEC_NONE is passed for all params. + * @param params Array of parameters of type union TEEC_Parameter. + * @param session Internal pointer to the last session used by + * TEEC_InvokeCommand with this operation. + * + */ +struct TEEC_Operation { + uint32_t started; + uint32_t paramTypes; + union TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; + /* Implementation-Defined */ + struct TEEC_Session *session; +}; + +/** + * TEEC_InitializeContext() - Initializes a context holding connection + * information on the specific TEE, designated by the name string. + + * @param name A zero-terminated string identifying the TEE to connect to. + * If name is set to NULL, the default TEE is connected to. NULL + * is the only supported value in this version of the API + * implementation. + * + * @param context The context structure which is to be initialized. + * + * @return TEEC_SUCCESS The initialization was successful. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_InitializeContext(const char *name, + struct TEEC_Context *context); + +/** + * TEEC_FinalizeContext() - Destroys a context holding connection information + * on the specific TEE. + * + * This function destroys an initialized TEE context, closing the connection + * between the client application and the TEE. This function must only be + * called when all sessions related to this TEE context have been closed and + * all shared memory blocks have been released. + * + * @param context The context to be destroyed. + */ +void TEEC_FinalizeContext(struct TEEC_Context *context); + +/** + * TEEC_OpenSession() - Opens a new session with the specified trusted + * application. + * + * @param context The initialized TEE context structure in which + * scope to open the session. + * @param session The session to initialize. + * @param destination A structure identifying the trusted application + * with which to open a session. + * + * @param connectionMethod The connection method to use. + * @param connectionData Any data necessary to connect with the chosen + * connection method. Not supported, should be set to + * NULL. + * @param operation An operation structure to use in the session. May + * be set to NULL to signify no operation structure + * needed. + * + * @param returnOrigin A parameter which will hold the error origin if + * this function returns any value other than + * TEEC_SUCCESS. + * + * @return TEEC_SUCCESS OpenSession successfully opened a new session. + * @return TEEC_Result Something failed. + * + */ +TEEC_Result TEEC_OpenSession(struct TEEC_Context *context, + struct TEEC_Session *session, + const struct TEEC_UUID *destination, + uint32_t connectionMethod, + const void *connectionData, + struct TEEC_Operation *operation, + uint32_t *returnOrigin); + +/** + * TEEC_CloseSession() - Closes the session which has been opened with the + * specific trusted application. + * + * @param session The opened session to close. + */ +void TEEC_CloseSession(struct TEEC_Session *session); + +/** + * TEEC_InvokeCommand() - Executes a command in the specified trusted + * application. + * + * @param session A handle to an open connection to the trusted + * application. + * @param commandID Identifier of the command in the trusted application + * to invoke. + * @param operation An operation structure to use in the invoke command. + * May be set to NULL to signify no operation structure + * needed. + * @param returnOrigin A parameter which will hold the error origin if this + * function returns any value other than TEEC_SUCCESS. + * + * @return TEEC_SUCCESS OpenSession successfully opened a new session. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_InvokeCommand(struct TEEC_Session *session, + uint32_t commandID, + struct TEEC_Operation *operation, + uint32_t *returnOrigin); + +/** + * TEEC_RegisterSharedMemory() - Register a block of existing memory as a + * shared block within the scope of the specified context. + * + * @param context The initialized TEE context structure in which scope to + * open the session. + * @param sharedMem pointer to the shared memory structure to register. + * + * @return TEEC_SUCCESS The registration was successful. + * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_RegisterSharedMemory(struct TEEC_Context *context, + struct TEEC_SharedMemory *sharedMem); + +/** + * TEEC_AllocateSharedMemory() - Allocate shared memory for TEE. + * + * @param context The initialized TEE context structure in which scope to + * open the session. + * @param sharedMem Pointer to the allocated shared memory. + * + * @return TEEC_SUCCESS The registration was successful. + * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_AllocateSharedMemory(struct TEEC_Context *context, + struct TEEC_SharedMemory *sharedMem); + +/** + * TEEC_ReleaseSharedMemory() - Free or deregister the shared memory. + * + * @param sharedMem Pointer to the shared memory to be freed. + */ +void TEEC_ReleaseSharedMemory(struct TEEC_SharedMemory *sharedMemory); + +/** + * TEEC_RequestCancellation() - Request the cancellation of a pending open + * session or command invocation. + * + * @param operation Pointer to an operation previously passed to open session + * or invoke. + */ +void TEEC_RequestCancellation(struct TEEC_Operation *operation); + +#endif diff --git a/drivers/tee/teei/300/common/include/tee_drv.h b/drivers/tee/teei/300/common/include/tee_drv.h new file mode 100644 index 000000000000..29da5deea5a7 --- /dev/null +++ b/drivers/tee/teei/300/common/include/tee_drv.h @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2016, Linaro Limited + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * + */ + +#ifndef __TEE_DRV_H +#define __TEE_DRV_H + +#include +#include +#include +#include +#include "tee.h" + +/* + * The file describes the API provided by the generic TEE driver to the + * specific TEE driver. + */ + +#define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */ +#define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */ +#define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */ + +struct tee_device; +struct tee_shm; +struct tee_shm_pool; + +/** + * struct tee_context - driver specific context on file pointer data + * @teedev: pointer to this drivers struct tee_device + * @list_shm: List of shared memory object owned by this context + * @hostname: to distinguish which TEE subsystem will serving client requests + * @data: driver specific context data, managed by the driver + */ +struct tee_context { + struct tee_device *teedev; + struct list_head list_shm; + u8 hostname[TEE_MAX_HOSTNAME_SIZE]; + void *data; +}; + +struct tee_param_memref { + size_t shm_offs; + size_t size; + struct tee_shm *shm; +}; + +struct tee_param_value { + u64 a; + u64 b; + u64 c; +}; + +struct tee_param { + u64 attr; + union { + struct tee_param_memref memref; + struct tee_param_value value; + } u; +}; + +/** + * struct tee_driver_ops - driver operations vtable + * @get_version: returns version of driver + * @open: called when the device file is opened + * @release: release this open file + * @open_session: open a new session + * @close_session: close a session + * @invoke_func: invoke a trusted function + * @cancel_req: request cancel of an ongoing invoke or open + * @supp_revc: called for supplicant to get a command + * @supp_send: called for supplicant to send a response + */ +struct tee_driver_ops { + void (*get_version)(struct tee_device *teedev, + struct tee_ioctl_version_data *vers); + int (*open)(struct tee_context *ctx); + void (*release)(struct tee_context *ctx); + int (*open_session)(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param); + int (*close_session)(struct tee_context *ctx, u32 session); + int (*invoke_func)(struct tee_context *ctx, + struct tee_ioctl_invoke_arg *arg, + struct tee_param *param); + int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session); + int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params, + struct tee_param *param); + int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params, + struct tee_param *param); +}; + +/** + * struct tee_desc - Describes the TEE driver to the subsystem + * @name: name of driver + * @ops: driver operations vtable + * @owner: module providing the driver + * @flags: Extra properties of driver, defined by TEE_DESC_* below + */ +#define TEE_DESC_PRIVILEGED 0x1 +struct tee_desc { + const char *name; + const struct tee_driver_ops *ops; + struct module *owner; + u32 flags; +}; + +/** + * isee_device_alloc() - Allocate a new struct tee_device instance + * @teedesc: Descriptor for this driver + * @dev: Parent device for this device + * @pool: Shared memory pool, NULL if not used + * @driver_data: Private driver data for this device + * + * Allocates a new struct tee_device instance. The device is + * removed by isee_device_unregister(). + * + * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure + */ +struct tee_device *isee_device_alloc(const struct tee_desc *teedesc, + struct device *dev, + struct tee_shm_pool *pool, + void *driver_data); + +/** + * isee_device_register() - Registers a TEE device + * @teedev: Device to register + * + * isee_device_unregister() need to be called to remove the @teedev if + * this function fails. + * + * @returns < 0 on failure + */ +int isee_device_register(struct tee_device *teedev); + +/** + * isee_device_unregister() - Removes a TEE device + * @teedev: Device to unregister + * + * This function should be called to remove the @teedev even if + * isee_device_register() hasn't been called yet. Does nothing if + * @teedev is NULL. + */ +void isee_device_unregister(struct tee_device *teedev); + +/** + * struct tee_shm_pool_mem_info - holds information needed to create a shared + * memory pool + * @vaddr: Virtual address of start of pool + * @paddr: Physical address of start of pool + * @size: Size in bytes of the pool + */ +struct tee_shm_pool_mem_info { + unsigned long vaddr; + phys_addr_t paddr; + size_t size; +}; + +/** + * isee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved + * memory range + * @priv_info: Information for driver private shared memory pool + * @dmabuf_info: Information for dma-buf shared memory pool + * + * Start and end of pools will must be page aligned. + * + * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied + * in @dmabuf, others will use the range provided by @priv. + * + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. + */ +struct tee_shm_pool * +isee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, + struct tee_shm_pool_mem_info *dmabuf_info); + +/** + * isee_shm_pool_free() - Free a shared memory pool + * @pool: The shared memory pool to free + * + * The must be no remaining shared memory allocated from this pool when + * this function is called. + */ +void isee_shm_pool_free(struct tee_shm_pool *pool); + +/** + * isee_get_drvdata() - Return driver_data pointer + * @returns the driver_data pointer supplied to isee_register(). + */ +void *isee_get_drvdata(struct tee_device *teedev); + +/** + * isee_shm_alloc() - Allocate shared memory + * @ctx: Context that allocates the shared memory + * @size: Requested size of shared memory + * @flags: Flags setting properties for the requested shared memory. + * + * Memory allocated as global shared memory is automatically freed when the + * TEE file pointer is closed. The @flags field uses the bits defined by + * TEE_SHM_* above. TEE_SHM_MAPPED must currently always be set. If + * TEE_SHM_DMA_BUF global shared memory will be allocated and associated + * with a dma-buf handle, else driver private memory. + * + * @returns a pointer to 'struct tee_shm' + */ +struct tee_shm *isee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); + +/** + * isee_shm_free() - Free shared memory + * @shm: Handle to shared memory to free + */ +void isee_shm_free(struct tee_shm *shm); + +/** + * isee_shm_put() - Decrease reference count on a shared memory handle + * @shm: Shared memory handle + */ +void isee_shm_put(struct tee_shm *shm); + +/** + * isee_shm_va2pa() - Get physical address of a virtual address + * @shm: Shared memory handle + * @va: Virtual address to tranlsate + * @pa: Returned physical address + * @returns 0 on success and < 0 on failure + */ +int isee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa); + +/** + * isee_shm_pa2va() - Get virtual address of a physical address + * @shm: Shared memory handle + * @pa: Physical address to tranlsate + * @va: Returned virtual address + * @returns 0 on success and < 0 on failure + */ +int isee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va); + +/** + * isee_shm_get_va() - Get virtual address of a shared memory plus an offset + * @shm: Shared memory handle + * @offs: Offset from start of this shared memory + * @returns virtual address of the shared memory + offs if offs is within + * the bounds of this shared memory, else an ERR_PTR + */ +void *isee_shm_get_va(struct tee_shm *shm, size_t offs); + +/** + * isee_shm_get_pa() - Get physical address of a shared memory plus an offset + * @shm: Shared memory handle + * @offs: Offset from start of this shared memory + * @pa: Physical address to return + * @returns 0 if offs is within the bounds of this shared memory, else an + * error code. + */ +int isee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa); + +/** + * isee_shm_get_id() - Get id of a shared memory object + * @shm: Shared memory handle + * @returns id + */ +int isee_shm_get_id(struct tee_shm *shm); + +/** + * isee_shm_get_from_id() - Find shared memory object and increase reference + * count + * @ctx: Context owning the shared memory + * @id: Id of shared memory object + * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure + */ +struct tee_shm *isee_shm_get_from_id(struct tee_context *ctx, int id); + +static inline bool tee_param_is_memref(struct tee_param *param) +{ + switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + return true; + default: + return false; + } +} + +struct tee_context *tee_client_open_context(struct tee_context *start, + int (*match)(struct tee_ioctl_version_data *, + const void *), + const void *data, struct tee_ioctl_version_data *vers); + +void tee_client_close_context(struct tee_context *ctx); + +void tee_client_get_version(struct tee_context *ctx, + struct tee_ioctl_version_data *vers); + +int tee_client_open_session(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param); + +int tee_client_close_session(struct tee_context *ctx, u32 session); + +int tee_client_invoke_func(struct tee_context *ctx, + struct tee_ioctl_invoke_arg *arg, + struct tee_param *param); + +#endif /*__TEE_DRV_H*/ diff --git a/drivers/tee/teei/300/common/include/teei_ioc.h b/drivers/tee/teei/300/common/include/teei_ioc.h new file mode 100644 index 000000000000..93f39a98b6a5 --- /dev/null +++ b/drivers/tee/teei/300/common/include/teei_ioc.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_IOC_H_ +#define __TEEI_IOC_H_ + +#define TEEI_IOC_MAGIC 'T' + +#define TEEI_CONFIG_IOC_MAGIC TEEI_IOC_MAGIC +#define TEEI_CLIENT_IOC_MAGIC TEEI_IOC_MAGIC +#define UT_TUI_CLIENT_IOC_MAGIC TEEI_IOC_MAGIC + +/* + * /dev/teei_config + */ +#define MAX_DRV_UUIDS 30 +#define UUID_LEN 32 + +struct init_param { + char uuids[MAX_DRV_UUIDS][UUID_LEN+1]; + __u32 uuid_count; + __u32 flag; +}; + +#define TEEI_CONFIG_IOCTL_INIT_TEEI \ + _IOWR(TEEI_CONFIG_IOC_MAGIC, 3, struct init_param) + +#define TEEI_CONFIG_IOCTL_UNLOCK \ + _IOWR(TEEI_CONFIG_IOC_MAGIC, 4, int) +/* + * /dev/ut_keymaster + */ +#define CMD_KM_MEM_CLEAR _IO(TEEI_IOC_MAGIC, 0x1) +#define CMD_KM_MEM_SEND _IO(TEEI_IOC_MAGIC, 0x2) +#define CMD_KM_NOTIFY_UTD _IO(TEEI_IOC_MAGIC, 0x3) +#define CMD_KM_FIRST_TIME_BOOT _IO(TEEI_IOC_MAGIC, 0x4) + +/* + * /dev/teei_fp + */ +#define CMD_FP_MEM_CLEAR _IO(TEEI_IOC_MAGIC, 0x1) +#define CMD_FP_CMD _IO(TEEI_IOC_MAGIC, 0x2) +#define CMD_FP_LOAD_TEE _IO(TEEI_IOC_MAGIC, 0x4) + +#define TEEI_VFS_NOTIFY_DRM _IOWR(TEEI_CONFIG_IOC_MAGIC, 0x75, int) +#define TEEI_VFS_GET_FP_UUID 0x50 + +#endif diff --git a/drivers/tee/teei/300/common/include/teei_secure_api.h b/drivers/tee/teei/300/common/include/teei_secure_api.h new file mode 100644 index 000000000000..8e0990ea6417 --- /dev/null +++ b/drivers/tee/teei/300/common/include/teei_secure_api.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef _TEEI_KERN_API_ +#define _TEEI_KERN_API_ + +#include + +#if defined(__GNUC__) && \ + defined(__GNUC_MINOR__) && \ + defined(__GNUC_PATCHLEVEL__) && \ + ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)) \ + >= 40502 +#define ARCH_EXTENSION_SEC +#endif + +#define TEEI_FC_CPU_ON (0xb4000080) +#define TEEI_FC_CPU_OFF (0xb4000081) +#define TEEI_FC_CPU_DORMANT (0xb4000082) +#define TEEI_FC_CPU_DORMANT_CANCEL (0xb4000083) +#define TEEI_FC_CPU_ERRATA_802022 (0xb4000084) + +static inline long teei_secure_call(u64 function_id, + u64 arg0, u64 arg1, u64 arg2) +{ + struct arm_smccc_res res; + + arm_smccc_smc(function_id, arg0, arg1, arg2, + 0, 0, 0, 0, &res); + + return res.a0; +} +#endif /* _TEEI_KERN_API_ */ diff --git a/drivers/tee/teei/300/public/isee_kernel_api.h b/drivers/tee/teei/300/public/isee_kernel_api.h new file mode 100644 index 000000000000..76c21d2051de --- /dev/null +++ b/drivers/tee/teei/300/public/isee_kernel_api.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef _ISEE_KERNEL_API_H_ + +#include + +int is_teei_ready(void); +unsigned long tz_get_share_buffer(unsigned int driver_id); +int tz_wait_for_notification(unsigned int driver_id); +int tz_notify_driver(unsigned int driver_id); +int tz_create_share_buffer(unsigned int driver_id, unsigned int buff_size); +int tz_free_share_buffer(unsigned int driver_id); +int tz_load_drv(struct TEEC_UUID *uuid); +int tz_unload_drv(struct TEEC_UUID *uuid); + +#endif /* _ISEE_KERNEL_API_H_ */ diff --git a/drivers/tee/teei/300/tee/Makefile b/drivers/tee/teei/300/tee/Makefile new file mode 100644 index 000000000000..395d0efb0871 --- /dev/null +++ b/drivers/tee/teei/300/tee/Makefile @@ -0,0 +1,23 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +obj-y += teeiv3.o +teeiv3-objs += tee_core.o +teeiv3-objs += tee_shm.o +teeiv3-objs += tee_shm_pool.o +teeiv3-objs += tee_client_api.o + +ifeq ($(CONFIG_MICROTRUST_TEST_DRIVERS),y) +teeiv3-objs += capi_proxy.o +endif + +obj-y += soter/ diff --git a/drivers/tee/teei/300/tee/capi_proxy.c b/drivers/tee/teei/300/tee/capi_proxy.c new file mode 100644 index 000000000000..baf067daec22 --- /dev/null +++ b/drivers/tee/teei/300/tee/capi_proxy.c @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#include +#include +#include +#include + +#include +#include "capi_proxy.h" + +#define IMSG_TAG "[tz_capi_proxy]" +#include + +#define HOSTNAME "bta_loader" + +static struct TEEC_Context capi_proxy_ctx; + +#define MAX_CAPI_SESSIONS 10 +#define MAX_CAPI_SHMS 12 + +static struct TEEC_Session capi_session[MAX_CAPI_SESSIONS]; +static struct TEEC_SharedMemory capi_shm[MAX_CAPI_SHMS]; + +struct ida capi_session_ida; +struct ida capi_shm_ida; + +static int alloc_capi_session(void) +{ + return ida_simple_get(&capi_session_ida, 0, + MAX_CAPI_SESSIONS, GFP_KERNEL); +} + +static void free_capi_session(int id) +{ + ida_simple_remove(&capi_session_ida, id); + memset(&capi_session[id], 0, sizeof(struct TEEC_Session)); +} + +static int alloc_capi_shm(void) +{ + return ida_simple_get(&capi_shm_ida, 0, MAX_CAPI_SHMS, GFP_KERNEL); +} + +static void free_capi_shm(int id) +{ + ida_simple_remove(&capi_shm_ida, id); + memset(&capi_shm[id], 0, sizeof(struct TEEC_SharedMemory)); +} + +static int capi_params_to_op(struct capi_proxy_param *params, + struct TEEC_Operation *op) +{ + size_t n; + long ret = 0; + union TEEC_Parameter *op_param; + struct TEEC_SharedMemory *op_shm; + size_t op_shm_off; + struct capi_proxy_param_memref *memref; + + memset(op, 0, sizeof(struct TEEC_Operation)); + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + op->paramTypes |= (uint32_t)params[n].attr << (4 * n); + op_param = &op->params[n]; + + switch (params[n].attr) { + case TEEC_NONE: + break; + case TEEC_VALUE_INPUT: + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + op_param->value.a = params[n].value.a; + op_param->value.b = params[n].value.b; + break; + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + memref = ¶ms[n].memref; + + op_param->tmpref.buffer = + kmalloc(memref->size, GFP_KERNEL); + if (!op_param->tmpref.buffer) { + IMSG_ERROR("failed to allocate buffer\n"); + ret = -ENOMEM; + goto err; + } + op_param->tmpref.size = memref->size; + + ret = copy_from_user( + (void *)(unsigned long) + (op_param->tmpref.buffer), + (void *)(unsigned long)(memref->buffer), + memref->size); + if (ret) { + IMSG_ERROR("failed to copy from user\n"); + ret = -EIO; + goto err; + } + break; + case TEEC_MEMREF_WHOLE: + case TEEC_MEMREF_PARTIAL_INPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + memref = ¶ms[n].memref; + + op_param->memref.parent = + &capi_shm[memref->shm_id]; + + op_param->memref.size = memref->size; + op_param->memref.offset = memref->shm_offset; + + op_shm = op_param->memref.parent; + op_shm_off = op_param->memref.offset; + + ret = copy_from_user( + (char *)(unsigned long)(op_shm->buffer) + + op_shm_off, + (char *)(unsigned long)(memref->buffer) + + op_shm_off, + memref->size); + if (ret) { + IMSG_ERROR("failed to copy from user\n"); + ret = -EIO; + goto err; + } + break; + default: + IMSG_ERROR("unknown param type (0x%llx)\n", + params[n].attr); + ret = -EINVAL; + break; + } + } + +err: + if (ret) { + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + switch (params[n].attr) { + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + kfree(op->params[n].tmpref.buffer); + break; + } + } + } + + return ret; +} + +static void capi_op_to_params(struct capi_proxy_param *params, + struct TEEC_Operation *op) +{ + size_t n; + int ret; + union TEEC_Parameter *op_param; + struct TEEC_SharedMemory *op_shm; + size_t op_shm_off; + struct capi_proxy_param_memref *memref; + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + op_param = &op->params[n]; + + switch (params[n].attr) { + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + params[n].value.a = op_param->value.a; + params[n].value.b = op_param->value.b; + break; + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + memref = ¶ms[n].memref; + + memref->size = op_param->tmpref.size; + + ret = copy_to_user( + (void *)(unsigned long)(memref->buffer), + (void *)(unsigned long) + (op_param->tmpref.buffer), + memref->size); + if (ret) + IMSG_ERROR("failed to copy to user\n"); + + kfree(op->params[n].tmpref.buffer); + break; + case TEEC_MEMREF_WHOLE: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + memref = ¶ms[n].memref; + + memref->size = op_param->memref.size; + + op_shm = op->params[n].memref.parent; + op_shm_off = op->params[n].memref.offset; + ret = copy_to_user( + (char *)(unsigned long)(memref->buffer) + + op_shm_off, + (char *)(unsigned long)(op_shm->buffer) + + op_shm_off, + memref->size); + if (ret) + IMSG_ERROR("failed to copy to user\n"); + break; + default: + break; + } + } +} + +static int do_capi_init_context(struct tee_ioctl_capi_proxy_arg *arg) +{ + arg->ret = TEEC_InitializeContext(HOSTNAME, &capi_proxy_ctx); + + if (arg->ret) + return -1; + + ida_init(&capi_session_ida); + ida_init(&capi_shm_ida); + + return 0; +} + +static int do_capi_final_context(struct tee_ioctl_capi_proxy_arg *arg) +{ + (void)arg; + + TEEC_FinalizeContext(&capi_proxy_ctx); + + ida_destroy(&capi_session_ida); + ida_destroy(&capi_shm_ida); + + return 0; +} + +static int do_capi_open_session(struct tee_ioctl_capi_proxy_arg *arg) +{ + struct TEEC_Session *session; + struct TEEC_Operation op; + struct TEEC_UUID *uuid = (struct TEEC_UUID *)arg->uuid; + int ret = 0; + int sid; + + sid = alloc_capi_session(); + if (sid < 0) { + IMSG_ERROR("no free capi session\n"); + return -ENOMEM; + } + + session = &capi_session[sid]; + + capi_params_to_op(arg->params, &op); + + arg->ret = TEEC_OpenSession(&capi_proxy_ctx, session, uuid, + TEEC_LOGIN_PUBLIC, NULL, &op, &arg->ret_orig); + + capi_op_to_params(arg->params, &op); + + if (arg->ret) { + ret = -EFAULT; + goto err; + } + + arg->session = (__u32)sid; + return 0; + +err: + free_capi_session(sid); + return ret; +} + +static int do_capi_invoke_command(struct tee_ioctl_capi_proxy_arg *arg) +{ + struct TEEC_Session *session; + struct TEEC_Operation op; + + session = &capi_session[arg->session]; + + capi_params_to_op(arg->params, &op); + + arg->ret = TEEC_InvokeCommand(session, arg->func, &op, + &arg->ret_orig); + + capi_op_to_params(arg->params, &op); + + return (arg->ret) ? -EFAULT : 0; +} + +static int do_capi_close_session(struct tee_ioctl_capi_proxy_arg *arg) +{ + struct TEEC_Session *session; + + session = &capi_session[arg->session]; + + TEEC_CloseSession(session); + free_capi_session((int)arg->session); + + return 0; +} + +static int do_capi_register_shm(struct tee_ioctl_capi_proxy_arg *arg) +{ + struct TEEC_SharedMemory *shm; + int ret = 0; + int sid; + + sid = alloc_capi_shm(); + if (sid < 0) { + IMSG_ERROR("no free capi shm\n"); + return -ENOMEM; + } + + shm = &capi_shm[sid]; + shm->flags = arg->params[0].attr; + shm->size = arg->params[0].memref.size; + shm->buffer = kmalloc(shm->size, GFP_KERNEL); + if (!shm->buffer) { + IMSG_ERROR("failed to allocate buffer\n"); + ret = -ENOMEM; + goto err; + } + + arg->ret = TEEC_RegisterSharedMemory(&capi_proxy_ctx, shm); + if (arg->ret) { + ret = -EFAULT; + goto err; + } + + arg->params[0].memref.shm_id = (__u64)sid; + return 0; + +err: + free_capi_shm(sid); + return ret; +} + +static int do_capi_allocate_shm(struct tee_ioctl_capi_proxy_arg *arg) +{ + struct TEEC_SharedMemory *shm; + int ret = 0; + int sid; + + sid = alloc_capi_shm(); + if (sid < 0) { + IMSG_ERROR("no free capi shm\n"); + return -ENOMEM; + } + + shm = &capi_shm[sid]; + + shm->flags = arg->params[0].attr; + shm->size = arg->params[0].memref.size; + + arg->ret = TEEC_AllocateSharedMemory(&capi_proxy_ctx, shm); + if (arg->ret) { + ret = -EFAULT; + goto err; + } + + arg->params[0].memref.shm_id = (__u64)sid; + return 0; + +err: + free_capi_shm(sid); + return ret; +} + +static int do_capi_release_shm(struct tee_ioctl_capi_proxy_arg *arg) +{ + int sid = (int)arg->params[0].memref.shm_id; + struct TEEC_SharedMemory *shm = &capi_shm[sid]; + + if (shm->buffer && shm->shadow_buffer) + kfree(shm->buffer); + + TEEC_ReleaseSharedMemory(shm); + free_capi_shm(sid); + + return 0; +} + +struct capi_op { + int opcode; + int (*callback)(struct tee_ioctl_capi_proxy_arg *arg); +}; + +static struct capi_op capi_ops[] = { + {CAPI_OP_INIT_CONTEXT, do_capi_init_context}, + {CAPI_OP_FINAL_CONTEXT, do_capi_final_context}, + {CAPI_OP_OPEN_SESSION, do_capi_open_session}, + {CAPI_OP_INVOKE_COMMAND, do_capi_invoke_command}, + {CAPI_OP_CLOSE_SESSION, do_capi_close_session}, + {CAPI_OP_REGISTER_SHM, do_capi_register_shm}, + {CAPI_OP_ALLOCATE_SHM, do_capi_allocate_shm}, + {CAPI_OP_RELEASE_SHM, do_capi_release_shm}, +}; + +static const size_t num_capi_ops = sizeof(capi_ops) / sizeof(struct capi_op); + +int tee_ioctl_capi_proxy(struct tee_context *ctx, + struct tee_ioctl_capi_proxy_arg __user *uarg) +{ + struct tee_ioctl_capi_proxy_arg arg; + int ret; + + if (copy_from_user(&arg, uarg, sizeof(arg))) { + IMSG_ERROR("failed to copy from user\n"); + return -EFAULT; + } + + if (arg.capi_op >= num_capi_ops) { + IMSG_ERROR("unknown CAPI operation (%u)\n", + arg.capi_op); + return -EINVAL; + } + + ret = capi_ops[arg.capi_op].callback(&arg); + + if (copy_to_user(uarg, &arg, sizeof(arg))) { + IMSG_ERROR("failed to copy to user\n"); + return -EFAULT; + } + + return ret; +} + diff --git a/drivers/tee/teei/300/tee/capi_proxy.h b/drivers/tee/teei/300/tee/capi_proxy.h new file mode 100644 index 000000000000..c5dadef2d2ab --- /dev/null +++ b/drivers/tee/teei/300/tee/capi_proxy.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef CAPI_PROXY_H +#define CAPI_PROXY_H + +#include + +enum { + CAPI_OP_INIT_CONTEXT, + CAPI_OP_FINAL_CONTEXT, + CAPI_OP_OPEN_SESSION, + CAPI_OP_INVOKE_COMMAND, + CAPI_OP_CLOSE_SESSION, + CAPI_OP_REGISTER_SHM, + CAPI_OP_ALLOCATE_SHM, + CAPI_OP_RELEASE_SHM, +}; + +int tee_ioctl_capi_proxy(struct tee_context *ctx, + struct tee_ioctl_capi_proxy_arg __user *uarg); + +#endif /* end of CAPI_PROXY_H */ diff --git a/drivers/tee/teei/300/tee/soter/Makefile b/drivers/tee/teei/300/tee/soter/Makefile new file mode 100644 index 000000000000..a0ad0e682aef --- /dev/null +++ b/drivers/tee/teei/300/tee/soter/Makefile @@ -0,0 +1,14 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +obj-y += soter.o +soter-objs += core.o call.o diff --git a/drivers/tee/teei/300/tee/soter/call.c b/drivers/tee/teei/300/tee/soter/call.c new file mode 100644 index 000000000000..7544f75ba898 --- /dev/null +++ b/drivers/tee/teei/300/tee/soter/call.c @@ -0,0 +1,445 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMSG_TAG "[tz_driver]" +#include + +#include "soter_private.h" +#include "soter_smc.h" +#include + +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG +unsigned long ree_dynamical_debug; +struct timeval start_val; +struct timeval end_val; +#endif + +static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params, + struct optee_msg_arg **msg_arg, + phys_addr_t *msg_parg) +{ + int rc; + struct tee_shm *shm; + struct optee_msg_arg *ma; + + shm = isee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params), + TEE_SHM_MAPPED); + if (IS_ERR(shm)) + return shm; + + ma = isee_shm_get_va(shm, 0); + if (IS_ERR(ma)) { + rc = PTR_ERR(ma); + goto out; + } + + rc = isee_shm_get_pa(shm, 0, msg_parg); + if (rc) + goto out; + + memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); + ma->num_params = num_params; + *msg_arg = ma; +out: + if (rc) { + isee_shm_free(shm); + return ERR_PTR(rc); + } + + return shm; +} + +/* Requires the filpstate mutex to be held */ +static struct soter_session *find_session(struct soter_context_data *ctxdata, + u32 session_id) +{ + struct soter_session *sess; + + list_for_each_entry(sess, &ctxdata->sess_list, list_node) + if (sess->session_id == session_id) + return sess; + + return NULL; +} + +/** + * isee_from_msg_param() - convert from OPTEE_MSG parameters to + * struct tee_param + * @params: subsystem internal parameter representation + * @num_params: number of elements in the parameter arrays + * @msg_params: OPTEE_MSG parameters + * Returns 0 on success or <0 on failure + */ +int isee_from_msg_param(struct tee_param *params, size_t num_params, + const struct optee_msg_param *msg_params) +{ + int rc; + size_t n; + struct tee_shm *shm; + phys_addr_t pa; + + for (n = 0; n < num_params; n++) { + struct tee_param *p = params + n; + const struct optee_msg_param *mp = msg_params + n; + u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK; + + switch (attr) { + case OPTEE_MSG_ATTR_TYPE_NONE: + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; + memset(&p->u, 0, sizeof(p->u)); + break; + case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT + + attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + p->u.value.a = mp->u.value.a; + p->u.value.b = mp->u.value.b; + p->u.value.c = mp->u.value.c; + break; + case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + + attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; + p->u.memref.size = mp->u.tmem.size; + shm = (struct tee_shm *)(unsigned long) + mp->u.tmem.shm_ref; + if (!shm) { + p->u.memref.shm_offs = 0; + p->u.memref.shm = NULL; + break; + } + rc = isee_shm_get_pa(shm, 0, &pa); + if (rc) + return rc; + p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa; + p->u.memref.shm = shm; + + /* Check that the memref is covered by the shm object */ + if (p->u.memref.size) { + size_t o = p->u.memref.shm_offs + + p->u.memref.size - 1; + + rc = isee_shm_get_pa(shm, o, NULL); + if (rc) + return rc; + } + break; + default: + return -EINVAL; + } + } + return 0; +} + +/** + * isee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters + * @msg_params: OPTEE_MSG parameters + * @num_params: number of elements in the parameter arrays + * @params: subsystem itnernal parameter representation + * Returns 0 on success or <0 on failure + */ +int isee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params, + const struct tee_param *params) +{ + int rc; + size_t n; + phys_addr_t pa; + + for (n = 0; n < num_params; n++) { + const struct tee_param *p = params + n; + struct optee_msg_param *mp = msg_params + n; + + switch (p->attr) { + case TEE_IOCTL_PARAM_ATTR_TYPE_NONE: + mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; + memset(&mp->u, 0, sizeof(mp->u)); + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr - + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; + mp->u.value.a = p->u.value.a; + mp->u.value.b = p->u.value.b; + mp->u.value.c = p->u.value.c; + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + + p->attr - + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm; + mp->u.tmem.size = p->u.memref.size; + if (!p->u.memref.shm) { + mp->u.tmem.buf_ptr = 0; + break; + } + rc = isee_shm_get_pa(p->u.memref.shm, + p->u.memref.shm_offs, &pa); + if (rc) + return rc; + mp->u.tmem.buf_ptr = pa; + mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED << + OPTEE_MSG_ATTR_CACHE_SHIFT; + break; + default: + return -EINVAL; + } + } + return 0; +} + +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG +static int unhexify(char *obuf, __u8 *ibuf, int len) +{ + char *p = NULL; + int i = 0; + + p = obuf; + + for (i = 0; i < len; i++) + p += sprintf(p, "%02x", ibuf[i]); + + return 0; +} +#endif + +int soter_open_session(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param) +{ + struct soter_context_data *ctxdata = ctx->data; + int rc; + struct tee_shm *shm; + struct optee_msg_arg *msg_arg; + phys_addr_t msg_parg; + struct soter_session *sess = NULL; + + while (teei_capi_ready != 1) + msleep(50); + + /* +2 for the meta parameters added below */ + shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION; + msg_arg->cancel_id = arg->cancel_id; + + /* + * Initialize and add the meta parameters needed when opening a + * 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; + memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid)); + memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid)); + msg_arg->params[1].u.value.c = arg->clnt_login; + + rc = isee_to_msg_param(msg_arg->params + 2, arg->num_params, param); + if (rc) + goto out; + + sess = kzalloc(sizeof(*sess), GFP_KERNEL); + if (!sess) { + rc = -ENOMEM; + goto out; + } + + if (soter_do_call_with_arg(ctx, msg_parg)) { + msg_arg->ret = TEEC_ERROR_COMMUNICATION; + msg_arg->ret_origin = TEEC_ORIGIN_COMMS; + } + + if (msg_arg->ret == TEEC_SUCCESS) { + /* A new session has been created, add it to the list. */ + sess->session_id = msg_arg->session; +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG + memset(sess->uuid, 0, TEEI_UUID_MAX_LEN); + unhexify(sess->uuid, arg->uuid, sizeof(arg->uuid)); +#endif + mutex_lock(&ctxdata->mutex); + list_add(&sess->list_node, &ctxdata->sess_list); + mutex_unlock(&ctxdata->mutex); + } else { + kfree(sess); + } + + if (isee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) { + arg->ret = TEEC_ERROR_COMMUNICATION; + arg->ret_origin = TEEC_ORIGIN_COMMS; + /* Close session again to avoid leakage */ + soter_close_session(ctx, msg_arg->session); + } else { + arg->session = msg_arg->session; + arg->ret = msg_arg->ret; + arg->ret_origin = msg_arg->ret_origin; + } +out: + isee_shm_free(shm); + + return rc; +} + +int soter_close_session(struct tee_context *ctx, u32 session) +{ + struct soter_context_data *ctxdata = ctx->data; + struct tee_shm *shm; + struct optee_msg_arg *msg_arg; + phys_addr_t msg_parg; + struct soter_session *sess; + + /* Check that the session is valid and remove it from the list */ + mutex_lock(&ctxdata->mutex); + sess = find_session(ctxdata, session); + if (sess) + list_del(&sess->list_node); + mutex_unlock(&ctxdata->mutex); + if (!sess) + return -EINVAL; + + kfree(sess); + + shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; + msg_arg->session = session; + soter_do_call_with_arg(ctx, msg_parg); + + isee_shm_free(shm); + + return 0; +} + +int soter_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, + struct tee_param *param) +{ + struct soter_context_data *ctxdata = ctx->data; + struct tee_shm *shm; + struct optee_msg_arg *msg_arg; + phys_addr_t msg_parg; + struct soter_session *sess; + int rc; +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG + long time_used; +#endif + + /* Check that the session is valid */ + mutex_lock(&ctxdata->mutex); + sess = find_session(ctxdata, arg->session); + mutex_unlock(&ctxdata->mutex); + if (!sess) + return -EINVAL; + + shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg); + if (IS_ERR(shm)) + return PTR_ERR(shm); + msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND; + msg_arg->func = arg->func; + msg_arg->session = arg->session; + msg_arg->cancel_id = arg->cancel_id; + + rc = isee_to_msg_param(msg_arg->params, arg->num_params, param); + if (rc) + goto out; + +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG + if (tzdriver_dynamical_debug_flag == 1) { + IMSG_PRINTK("TEEI: %s START (TA: %s).\n", + __func__, sess->uuid); + do_gettimeofday(&start_val); + if (likely(ree_dynamical_debug == REE_DYNAMICAL_START)) { + time_used = (start_val.tv_sec - end_val.tv_sec) + * 1000000 + + (start_val.tv_usec - end_val.tv_usec); + IMSG_PRINTK( + "TEEI: TA(%s) CMD_ID: 0x%x REE USED %ld us.\n", + sess->uuid, arg->func, time_used); + } + } +#endif + + if (soter_do_call_with_arg(ctx, msg_parg)) { + msg_arg->ret = TEEC_ERROR_COMMUNICATION; + msg_arg->ret_origin = TEEC_ORIGIN_COMMS; + } + +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG + if (tzdriver_dynamical_debug_flag == 1) { + do_gettimeofday(&end_val); + time_used = (end_val.tv_sec - start_val.tv_sec) * 1000000 + + (end_val.tv_usec - start_val.tv_usec); + + IMSG_PRINTK("TEEI: TA(%s) CMD_ID: 0x%x TEE USED %ld us.\n", + sess->uuid, arg->func, time_used); + if (unlikely(ree_dynamical_debug != REE_DYNAMICAL_START)) + ree_dynamical_debug = REE_DYNAMICAL_START; + } +#endif + + if (isee_from_msg_param(param, arg->num_params, msg_arg->params)) { + msg_arg->ret = TEEC_ERROR_COMMUNICATION; + msg_arg->ret_origin = TEEC_ORIGIN_COMMS; + } + + arg->ret = msg_arg->ret; + arg->ret_origin = msg_arg->ret_origin; +out: + isee_shm_free(shm); + return rc; +} + +struct soter_cancel_struct { + u32 session_id; + u32 cancel_id; +}; + +int soter_cancel_func(struct tee_context *ctx, u32 cancel_id, u32 session) +{ + struct soter_context_data *ctxdata = ctx->data; + struct soter_cancel_struct cancel_param; + struct soter_session *sess = NULL; + + if ((void *)cancel_message_buff == NULL) { + IMSG_ERROR("[%s][%d]cancel_message_buff is NULL!\n", + __func__, __LINE__); + return -EINVAL; + } + + mutex_lock(&ctxdata->mutex); + sess = find_session(ctxdata, session); + mutex_unlock(&ctxdata->mutex); + if (sess == NULL) { + IMSG_ERROR("[%s][%d]session is NULL!\n", + __func__, __LINE__); + return -EINVAL; + } + + cancel_param.session_id = session; + cancel_param.cancel_id = cancel_id; + memcpy((void *)cancel_message_buff, + (void *)&cancel_param, + sizeof(struct soter_cancel_struct)); + + return send_cancel_command(0); +} diff --git a/drivers/tee/teei/300/tee/soter/core.c b/drivers/tee/teei/300/tee/soter/core.c new file mode 100644 index 000000000000..09fcef85a9ac --- /dev/null +++ b/drivers/tee/teei/300/tee/soter/core.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * Copyright (c) 2015, Linaro Limited + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMSG_TAG "[tz_driver]" +#include + +#include "soter_private.h" +#include "soter_smc.h" + +#define SOTER_SHM_NUM_PRIV_PAGES 1 + +static struct reserved_mem *reserved_mem; +static atomic_t is_shm_pool_available = ATOMIC_INIT(0); +static DECLARE_COMPLETION(shm_pool_registered); + +int teei_new_capi_init(void) +{ + if (reserved_mem) { + int ret = soter_register_shm_pool( + reserved_mem->base, reserved_mem->size); + + if (!ret) { + atomic_set(&is_shm_pool_available, 1); + complete_all(&shm_pool_registered); + } + return ret; + } + + IMSG_ERROR("capi reserve memory is NULL!\n"); + + return -ENOMEM; +} + +static void soter_get_version(struct tee_device *teedev, + struct tee_ioctl_version_data *vers) +{ + struct tee_ioctl_version_data v = { + .impl_id = 0x0, + .impl_caps = 0x0, + .gen_caps = TEE_GEN_CAP_GP, + }; + *vers = v; +} + +static int soter_open(struct tee_context *ctx) +{ + struct soter_context_data *ctxdata; + int ret; + + ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL); + if (!ctxdata) + return -ENOMEM; + + mutex_init(&ctxdata->mutex); + INIT_LIST_HEAD(&ctxdata->sess_list); + + ctx->data = ctxdata; + + if (!atomic_read(&is_shm_pool_available)) { + ret = wait_for_completion_interruptible(&shm_pool_registered); + if (ret == -ERESTARTSYS) + return -EINTR; + } + + return 0; +} + +static void soter_release(struct tee_context *ctx) +{ + struct soter_context_data *ctxdata = ctx->data; + struct tee_shm *shm; + struct optee_msg_arg *arg = NULL; + phys_addr_t parg; + struct soter_session *sess; + struct soter_session *sess_tmp; + + if (!ctxdata) + return; + + shm = isee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED); + if (!IS_ERR(shm)) { + arg = isee_shm_get_va(shm, 0); + /* + * If va2pa fails for some reason, we can't call + * soter_close_session(), only free the memory. Secure OS + * will leak sessions and finally refuse more sessions, but + * we will at least let normal world reclaim its memory. + */ + if (!IS_ERR(arg)) + isee_shm_va2pa(shm, arg, &parg); + } + + list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list, + list_node) { + list_del(&sess->list_node); + if (!IS_ERR_OR_NULL(arg)) { + memset(arg, 0, sizeof(*arg)); + arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; + arg->session = sess->session_id; + soter_do_call_with_arg(ctx, parg); + } + kfree(sess); + } + kfree(ctxdata); + + if (!IS_ERR(shm)) + isee_shm_free(shm); + + ctx->data = NULL; +} + +static struct tee_driver_ops soter_ops = { + .get_version = soter_get_version, + .open = soter_open, + .release = soter_release, + .open_session = soter_open_session, + .close_session = soter_close_session, + .invoke_func = soter_invoke_func, + .cancel_req = soter_cancel_func, +}; + +static struct tee_desc soter_desc = { + .name = "soter-clnt", + .ops = &soter_ops, + .owner = THIS_MODULE, +}; + +static struct soter_priv *soter_priv; + +static struct tee_shm_pool * +soter_config_shm_memremap(void **memremaped_shm) +{ + struct tee_shm_pool *pool; + unsigned long vaddr; + phys_addr_t paddr; + size_t size; + void *va; + struct tee_shm_pool_mem_info priv_info; + struct tee_shm_pool_mem_info dmabuf_info; + + if (!reserved_mem) { + IMSG_ERROR("cannot find reserved memory in device tree\n"); + return ERR_PTR(-EINVAL); + } + + paddr = reserved_mem->base; + size = reserved_mem->size; + IMSG_INFO("reserved memory @ 0x%llx, size %zx\n", + (unsigned long long)paddr, size); + + if (size < 2 * SOTER_SHM_NUM_PRIV_PAGES * PAGE_SIZE) { + IMSG_ERROR("too small shared memory area\n"); + return ERR_PTR(-EINVAL); + } + + va = ioremap_cache(paddr, size); + + if (!va) { + IMSG_ERROR("shared memory ioremap failed\n"); + return ERR_PTR(-EINVAL); + } + vaddr = (unsigned long)va; + + priv_info.vaddr = vaddr; + priv_info.paddr = paddr; + priv_info.size = SOTER_SHM_NUM_PRIV_PAGES * PAGE_SIZE; + dmabuf_info.vaddr = vaddr + SOTER_SHM_NUM_PRIV_PAGES * PAGE_SIZE; + dmabuf_info.paddr = paddr + SOTER_SHM_NUM_PRIV_PAGES * PAGE_SIZE; + dmabuf_info.size = size - SOTER_SHM_NUM_PRIV_PAGES * PAGE_SIZE; + + pool = isee_shm_pool_alloc_res_mem(&priv_info, &dmabuf_info); + if (IS_ERR(pool)) + goto out; + + *memremaped_shm = va; +out: + return pool; +} + +static void soter_remove(struct soter_priv *soter) +{ + /* + * The device has to be unregistered before we can free the + * other resources. + */ + isee_device_unregister(soter->teedev); + + isee_shm_pool_free(soter->pool); + mutex_destroy(&soter->call_queue.mutex); + + kfree(soter); +} + +static int __init soter_driver_init(void) +{ + struct tee_shm_pool *pool = NULL; + struct tee_device *teedev = NULL; + void *memremaped_shm = NULL; + int rc; + + soter_priv = kzalloc(sizeof(*soter_priv), GFP_KERNEL); + if (!soter_priv) { + rc = -ENOMEM; + goto err; + } + + pool = soter_config_shm_memremap(&memremaped_shm); + if (IS_ERR(pool)) + return PTR_ERR(pool); + soter_priv->pool = pool; + soter_priv->memremaped_shm = memremaped_shm; + + teedev = isee_device_alloc(&soter_desc, NULL, pool, soter_priv); + if (IS_ERR(teedev)) { + rc = PTR_ERR(teedev); + goto err; + } + soter_priv->teedev = teedev; + + rc = isee_device_register(teedev); + if (rc) + goto err; + + return 0; + +err: + if (soter_priv) { + /* + * isee_device_unregister() is safe to call even if the + * devices hasn't been registered with + * tee_device_register() yet. + */ + isee_device_unregister(soter_priv->teedev); + kfree(soter_priv); + } + if (pool) + isee_shm_pool_free(pool); + return rc; +} +module_init(soter_driver_init); + +static void __exit soter_driver_exit(void) +{ + if (soter_priv) + soter_remove(soter_priv); + soter_priv = NULL; +} +module_exit(soter_driver_exit); + +static int __init shared_mem_pool_setup(struct reserved_mem *rmem) +{ + reserved_mem = rmem; + return 0; +} +RESERVEDMEM_OF_DECLARE(soter_shared_mem, "microtrust,shared_mem", + shared_mem_pool_setup); + +MODULE_AUTHOR("Microtrust"); +MODULE_DESCRIPTION("Soter driver"); +MODULE_SUPPORTED_DEVICE(""); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tee/teei/300/tee/soter/optee_msg.h b/drivers/tee/teei/300/tee/soter/optee_msg.h new file mode 100644 index 000000000000..53e6022443d7 --- /dev/null +++ b/drivers/tee/teei/300/tee/soter/optee_msg.h @@ -0,0 +1,400 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2016, Linaro Limited + * All rights reserved. + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All rights reserved. + * + */ +#ifndef _OPTEE_MSG_H +#define _OPTEE_MSG_H + +#include +#include + +/* + * This file defines the OP-TEE message protocol used to communicate + * with an instance of OP-TEE running in secure world. + * + * This file is divided into three sections. + * 1. Formatting of messages. + * 2. Requests from normal world + * 3. Requests from secure world, Remote Procedure Call (RPC), handled by + * tee-supplicant. + */ + +/***************************************************************************** + * 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 GENMASK(7, 0) + +/* + * Meta parameter to be absorbed by the Secure OS and not passed + * to the Trusted Application. + * + * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION. + */ +#define OPTEE_MSG_ATTR_META BIT(8) + +/* + * The temporary shared memory object is not physically contigous and this + * temp memref is followed by another fragment until the last temp memref + * that doesn't have this bit set. + */ +#define OPTEE_MSG_ATTR_FRAGMENT BIT(9) + +/* + * Memory attributes for caching passed with temp memrefs. The actual value + * used is defined outside the message protocol with the exception of + * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already + * defined for the memory range should be used. If optee_smc.h is used as + * bearer of this protocol OPTEE_SMC_SHM_* is used for values. + */ +#define OPTEE_MSG_ATTR_CACHE_SHIFT 16 +#define OPTEE_MSG_ATTR_CACHE_MASK GENMASK(2, 0) +#define OPTEE_MSG_ATTR_CACHE_PREDEFINED 0 + +/* + * Same values as TEE_LOGIN_* from TEE Internal API + */ +#define OPTEE_MSG_LOGIN_PUBLIC 0x00000000 +#define OPTEE_MSG_LOGIN_USER 0x00000001 +#define OPTEE_MSG_LOGIN_GROUP 0x00000002 +#define OPTEE_MSG_LOGIN_APPLICATION 0x00000004 +#define OPTEE_MSG_LOGIN_APPLICATION_USER 0x00000005 +#define OPTEE_MSG_LOGIN_APPLICATION_GROUP 0x00000006 + +/** + * 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 { + u64 buf_ptr; + u64 size; + u64 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 { + u64 offs; + u64 size; + u64 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 { + u64 a; + u64 b; + u64 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 { + u64 attr; + union { + struct optee_msg_param_tmem tmem; + struct optee_msg_param_rmem rmem; + struct optee_msg_param_value value; + } u; +}; + +/** + * struct optee_msg_arg - call argument + * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_* + * @func: Trusted Application function, specific to the Trusted Application, + * used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND + * @session: In parameter for all OPTEE_MSG_CMD_* except + * OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead + * @cancel_id: Cancellation id, a unique value to identify this request + * @ret: return value + * @ret_origin: origin of the return value + * @num_params: number of parameters supplied to the OS Command + * @params: the parameters supplied to the OS Command + * + * All normal calls to Trusted OS uses this struct. If cmd requires further + * information than what these 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 { + u32 cmd; + u32 func; + u32 session; + u32 cancel_id; + u32 pad; + u32 ret; + u32 ret_origin; + u32 num_params; + + /* num_params tells the actual number of element in params */ + struct optee_msg_param params[0]; +}; + +/** + * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg + * + * @num_params: Number of parameters embedded in the struct optee_msg_arg + * + * Returns the size of the struct optee_msg_arg together with the number + * of embedded parameters. + */ +#define OPTEE_MSG_GET_ARG_SIZE(num_params) \ + (sizeof(struct optee_msg_arg) + \ + sizeof(struct optee_msg_param) * (num_params)) + +/***************************************************************************** + * Part 2 - requests from normal world + *****************************************************************************/ + +/* + * Return the following UID if using API specified in this file without + * further extensions: + * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. + * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1, + * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3. + */ +#define OPTEE_MSG_UID_0 0x384fb3e0 +#define OPTEE_MSG_UID_1 0xe7f811e3 +#define OPTEE_MSG_UID_2 0xaf630002 +#define OPTEE_MSG_UID_3 0xa5d5c51b +#define OPTEE_MSG_FUNCID_CALLS_UID 0xFF01 + +/* + * Returns 2.0 if using API specified in this file without further + * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR + * and OPTEE_MSG_REVISION_MINOR + */ +#define OPTEE_MSG_REVISION_MAJOR 2 +#define OPTEE_MSG_REVISION_MINOR 0 +#define OPTEE_MSG_FUNCID_CALLS_REVISION 0xFF03 + +/* + * Get UUID of Trusted OS. + * + * Used by non-secure world to figure out which Trusted OS is installed. + * Note that returned UUID is the UUID of the Trusted OS, not of the API. + * + * Returns UUID in 4 32-bit words in the same way as + * OPTEE_MSG_FUNCID_CALLS_UID described above. + */ +#define OPTEE_MSG_OS_OPTEE_UUID_0 0x486178e0 +#define OPTEE_MSG_OS_OPTEE_UUID_1 0xe7f811e3 +#define OPTEE_MSG_OS_OPTEE_UUID_2 0xbc5e0002 +#define OPTEE_MSG_OS_OPTEE_UUID_3 0xa5d5c51b +#define OPTEE_MSG_FUNCID_GET_OS_UUID 0x0000 + +/* + * Get revision of Trusted OS. + * + * Used by non-secure world to figure out which version of the Trusted OS + * is installed. Note that the returned revision is the revision of the + * Trusted OS, not of the API. + * + * Returns revision in 2 32-bit words in the same way as + * OPTEE_MSG_CALLS_REVISION described above. + */ +#define OPTEE_MSG_FUNCID_GET_OS_REVISION 0x0001 + +/* + * Do a secure call with struct optee_msg_arg as argument + * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd + * + * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application. + * The first two parameters are tagged as meta, holding two value + * parameters to pass the following information: + * param[0].u.value.a-b uuid of Trusted Application + * param[1].u.value.a-b uuid of Client + * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_* + * + * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened + * session to a Trusted Application. struct optee_msg_arg::func is Trusted + * Application function, specific to the Trusted Application. + * + * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to + * Trusted Application. + * + * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command. + * + * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The + * information is passed as: + * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + * [| OPTEE_MSG_ATTR_FRAGMENT] + * [in] param[0].u.tmem.buf_ptr physical address (of first fragment) + * [in] param[0].u.tmem.size size (of first fragment) + * [in] param[0].u.tmem.shm_ref holds shared memory reference + * ... + * 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].u.rmem.shm_ref holds shared memory reference + * [in] param[0].u.rmem.offs 0 + * [in] param[0].u.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 + +/* + * Reserved + */ +#define OPTEE_MSG_RPC_CMD_RPMB 1 + +/* + * File system access, defined in tee-supplicant + */ +#define OPTEE_MSG_RPC_CMD_FS 2 + +/* + * Get time + * + * Returns number of seconds and nano seconds since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). + * + * [out] param[0].u.value.a Number of seconds + * [out] param[0].u.value.b Number of nano seconds. + */ +#define OPTEE_MSG_RPC_CMD_GET_TIME 3 + +/* + * Wait queue primitive, helper for secure world to implement a wait queue. + * + * If secure world need to wait for a secure world mutex it issues a sleep + * request instead of spinning in secure world. Conversely is a wakeup + * request issued when a secure world mutex with a thread waiting thread is + * unlocked. + * + * Waiting on a key + * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP + * [in] param[0].u.value.b wait key + * + * Waking up a key + * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP + * [in] param[0].u.value.b wakeup key + */ +#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4 +#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0 +#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1 + +/* + * Suspend execution + * + * [in] param[0].value .a number of milliseconds to suspend + */ +#define OPTEE_MSG_RPC_CMD_SUSPEND 5 + +/* + * Allocate a piece of shared memory + * + * Shared memory can optionally be fragmented, to support that additional + * spare param entries are allocated to make room for eventual fragments. + * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when + * unused. All returned temp memrefs except the last should have the + * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field. + * + * [in] param[0].u.value.a type of memory one of + * OPTEE_MSG_RPC_SHM_TYPE_* below + * [in] param[0].u.value.b requested size + * [in] param[0].u.value.c required alignment + * + * [out] param[0].u.tmem.buf_ptr physical address (of first fragment) + * [out] param[0].u.tmem.size size (of first fragment) + * [out] param[0].u.tmem.shm_ref shared memory reference + * ... + * [out] param[n].u.tmem.buf_ptr physical address + * [out] param[n].u.tmem.size size + * [out] param[n].u.tmem.shm_ref shared memory reference (same value + * as in param[n-1].u.tmem.shm_ref) + */ +#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6 +/* Memory that can be shared with a non-secure user space application */ +#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0 +/* Memory only shared with non-secure kernel */ +#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1 + +/* + * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC + * + * [in] param[0].u.value.a type of memory one of + * OPTEE_MSG_RPC_SHM_TYPE_* above + * [in] param[0].u.value.b value of shared memory reference + * returned in param[0].u.tmem.shm_ref + * above + */ +#define OPTEE_MSG_RPC_CMD_SHM_FREE 7 + +#endif /* _OPTEE_MSG_H */ diff --git a/drivers/tee/teei/300/tee/soter/soter_private.h b/drivers/tee/teei/300/tee/soter/soter_private.h new file mode 100644 index 000000000000..a570130641c3 --- /dev/null +++ b/drivers/tee/teei/300/tee/soter/soter_private.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef SOTER_PRIVATE_H +#define SOTER_PRIVATE_H + +#include +#include +#include + +#define TEEI_UUID_MAX_LEN 128 + +/* Some Global Platform error codes used in this driver */ +#define TEEC_SUCCESS 0x00000000 +#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 +#define TEEC_ERROR_COMMUNICATION 0xFFFF000E +#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C + +#define TEEC_ORIGIN_COMMS 0x00000002 + +struct call_queue { + /* Serializes access to this struct */ + struct mutex mutex; + struct list_head waiters; +}; + +struct soter_priv { + struct tee_device *teedev; + struct call_queue call_queue; + struct tee_shm_pool *pool; + void *memremaped_shm; +}; + +struct soter_session { + struct list_head list_node; + u32 session_id; + char uuid[TEEI_UUID_MAX_LEN]; +}; + +struct soter_context_data { + /* Serializes access to this struct */ + struct mutex mutex; + struct list_head sess_list; +}; + +int soter_open_session(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param); +int soter_close_session(struct tee_context *ctx, u32 session); +int soter_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, + struct tee_param *param); +int soter_cancel_func(struct tee_context *ctx, u32 cancel_id, u32 session); + +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG +extern uint32_t tzdriver_dynamical_debug_flag; +#define REE_DYNAMICAL_START 1 +#define REE_DYNAMICAL_STOP 2 +#endif + +extern unsigned long teei_capi_ready; + +#endif diff --git a/drivers/tee/teei/300/tee/soter/soter_smc.h b/drivers/tee/teei/300/tee/soter/soter_smc.h new file mode 100644 index 000000000000..708a7b9bf166 --- /dev/null +++ b/drivers/tee/teei/300/tee/soter/soter_smc.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef SOTER_SMC_H +#define SOTER_SMC_H + +#include + +/* Let's reuse optee's message format */ +#include "optee_msg.h" + +enum { + NQ_CMD_CLIENT_API_REQUEST, + NQ_CMD_GPTEE_CLIENT_API_REQUEST, + NQ_CMD_REGISTER_SHM_POOL, +}; + +extern struct semaphore keymaster_api_lock; + +int teei_forward_call(unsigned long long cmd, unsigned long long cmd_addr, + unsigned long long size); + +static inline int soter_do_call_with_arg(struct tee_context *ctx, + phys_addr_t parg) +{ + if (strncmp(ctx->hostname, "bta_loader", TEE_MAX_HOSTNAME_SIZE) == 0) + return teei_forward_call(NQ_CMD_CLIENT_API_REQUEST, parg, + sizeof(struct optee_msg_arg)); + + if (strncmp(ctx->hostname, "tta", TEE_MAX_HOSTNAME_SIZE) == 0) + return teei_forward_call(NQ_CMD_GPTEE_CLIENT_API_REQUEST, parg, + sizeof(struct optee_msg_arg)); + + IMSG_ERROR("Unrecognized hostname: '%s'\n", ctx->hostname); + + return -EINVAL; +} + +static inline int soter_register_shm_pool(phys_addr_t shm_pa, int shm_size) +{ + int retVal = 0; + + retVal = teei_forward_call(NQ_CMD_REGISTER_SHM_POOL, shm_pa, shm_size); + + return retVal; + +} + +#endif diff --git a/drivers/tee/teei/300/tee/tee_client_api.c b/drivers/tee/teei/300/tee/tee_client_api.c new file mode 100644 index 000000000000..ffd0b6196328 --- /dev/null +++ b/drivers/tee/teei/300/tee/tee_client_api.c @@ -0,0 +1,770 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2016, Linaro Limited + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define IMSG_TAG "[tz_driver]" +#include + +#include "tee_private.h" +#include "tee.h" + +/* How many device sequence numbers will be tried before giving up */ +#define TEEC_MAX_DEV_SEQ 10 +#define DEFAULT_CAPABILITY "bta_loader" + +static inline long ioctl(struct file *filp, unsigned int cmd, void *arg) +{ + long ret; + mm_segment_t old_fs; + + if (!filp) + return -EBADF; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + +#ifdef CONFIG_COMPAT + ret = filp->f_op->compat_ioctl(filp, cmd, (unsigned long)arg); +#else + ret = filp->f_op->unlocked_ioctl(filp, cmd, (unsigned long)arg); +#endif + set_fs(old_fs); + + return ret; +} + +static inline int close(int fd) +{ + return __close_fd(current->files, fd); +} + +static DEFINE_MUTEX(teec_mutex); + +static inline void teec_mutex_lock(struct mutex *mu) +{ + mutex_lock(mu); +} + +static inline void teec_mutex_unlock(struct mutex *mu) +{ + mutex_unlock(mu); +} + +static struct file *teec_open_dev(const char *devname, const char *capabilities) +{ + mm_segment_t old_fs; + struct file *file; + struct tee_ioctl_set_hostname_arg arg; + int err; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + file = filp_open(devname, O_RDWR, 0); + set_fs(old_fs); + + if (IS_ERR_OR_NULL(file)) + return file; + + memset(&arg, 0, sizeof(arg)); + + if (capabilities && (strcmp(capabilities, "tta") == 0)) { + IMSG_DEBUG("client request serviced by GPTEE\n"); + strncpy((char *)arg.hostname, capabilities, + TEE_MAX_HOSTNAME_SIZE-1); + } else { + IMSG_DEBUG("client request serviced by BTA Loader\n"); + strncpy((char *)arg.hostname, DEFAULT_CAPABILITY, + TEE_MAX_HOSTNAME_SIZE-1); + } + + err = ioctl(file, TEE_IOC_SET_HOSTNAME, &arg); + if (err) { + IMSG_ERROR("TEE_IOC_SET_HOSTNAME failed\n"); + goto exit; + } + + return file; + +exit: + filp_close(file, NULL); + return ERR_PTR(err); +} + +static int teec_shm_alloc(struct file *fd, size_t size, int *id) +{ + int shm_fd; + struct tee_ioctl_shm_alloc_data data; + + memset(&data, 0, sizeof(data)); + data.size = size; + shm_fd = ioctl(fd, TEE_IOC_SHM_ALLOC, &data); + if (shm_fd < 0) + return -1; + *id = data.id; + return shm_fd; +} + +TEEC_Result TEEC_InitializeContext(const char *name, struct TEEC_Context *ctx) +{ + char devname[128]; + struct file *fd; + size_t n; + + if (!ctx) + return TEEC_ERROR_BAD_PARAMETERS; + + for (n = 0; n < TEEC_MAX_DEV_SEQ; n++) { + snprintf(devname, sizeof(devname), "/dev/isee_tee%zu", n); + fd = teec_open_dev(devname, name); + if (!IS_ERR_OR_NULL(fd)) { + ctx->fd = fd; + return TEEC_SUCCESS; + } + } + + return TEEC_ERROR_ITEM_NOT_FOUND; +} +EXPORT_SYMBOL(TEEC_InitializeContext); + +void TEEC_FinalizeContext(struct TEEC_Context *ctx) +{ + if (ctx) + filp_close(ctx->fd, NULL); +} +EXPORT_SYMBOL(TEEC_FinalizeContext); + +static TEEC_Result teec_pre_process_tmpref(struct TEEC_Context *ctx, + uint32_t param_type, + struct TEEC_TempMemoryReference *tmpref, + struct tee_ioctl_param *param, + struct TEEC_SharedMemory *shm) +{ + TEEC_Result res; + + switch (param_type) { + case TEEC_MEMREF_TEMP_INPUT: + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + shm->flags = TEEC_MEM_INPUT; + break; + case TEEC_MEMREF_TEMP_OUTPUT: + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + shm->flags = TEEC_MEM_OUTPUT; + break; + case TEEC_MEMREF_TEMP_INOUT: + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; + shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + shm->size = tmpref->size; + + res = TEEC_AllocateSharedMemory(ctx, shm); + if (res != TEEC_SUCCESS) + return res; + + memcpy(shm->buffer, tmpref->buffer, tmpref->size); + param->size = tmpref->size; + param->shm_id = shm->id; + return TEEC_SUCCESS; +} + +static TEEC_Result teec_pre_process_whole( + struct TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + const uint32_t inout = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + uint32_t flags = memref->parent->flags & inout; + struct TEEC_SharedMemory *shm; + + if (flags == inout) + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; + else if (flags & TEEC_MEM_INPUT) + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + else if (flags & TEEC_MEM_OUTPUT) + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + else + return TEEC_ERROR_BAD_PARAMETERS; + + shm = memref->parent; + /* + * We're using a shadow buffer in this reference, copy the real buffer + * into the shadow buffer if needed. We'll copy it back once we've + * returned from the call to secure world. + */ + if (shm->shadow_buffer && (flags & TEEC_MEM_INPUT)) + memcpy(shm->shadow_buffer, shm->buffer, shm->size); + + param->shm_id = shm->id; + param->size = shm->size; + return TEEC_SUCCESS; +} + +static TEEC_Result teec_pre_process_partial(uint32_t param_type, + struct TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + uint32_t req_shm_flags; + struct TEEC_SharedMemory *shm; + + switch (param_type) { + case TEEC_MEMREF_PARTIAL_INPUT: + req_shm_flags = TEEC_MEM_INPUT; + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + break; + case TEEC_MEMREF_PARTIAL_OUTPUT: + req_shm_flags = TEEC_MEM_OUTPUT; + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + break; + case TEEC_MEMREF_PARTIAL_INOUT: + req_shm_flags = TEEC_MEM_OUTPUT | TEEC_MEM_INPUT; + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + + shm = memref->parent; + + if ((shm->flags & req_shm_flags) != req_shm_flags) + return TEEC_ERROR_BAD_PARAMETERS; + + /* + * We're using a shadow buffer in this reference, copy the real buffer + * into the shadow buffer if needed. We'll copy it back once we've + * returned from the call to secure world. + */ + if (shm->shadow_buffer && param_type != TEEC_MEMREF_PARTIAL_OUTPUT) + memcpy((char *)shm->shadow_buffer + memref->offset, + (char *)shm->buffer + memref->offset, memref->size); + + param->shm_id = shm->id; + param->shm_offs = memref->offset; + param->size = memref->size; + return TEEC_SUCCESS; +} + +static TEEC_Result teec_pre_process_operation(struct TEEC_Context *ctx, + struct TEEC_Operation *operation, + struct tee_ioctl_param *params, + struct TEEC_SharedMemory *shms) +{ + TEEC_Result res; + size_t n; + + memset(shms, 0, sizeof(struct TEEC_SharedMemory) * + TEEC_CONFIG_PAYLOAD_REF_COUNT); + if (!operation) { + memset(params, 0, sizeof(struct tee_ioctl_param) * + TEEC_CONFIG_PAYLOAD_REF_COUNT); + return TEEC_SUCCESS; + } + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + uint32_t param_type; + + param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n); + switch (param_type) { + case TEEC_NONE: + params[n].attr = param_type; + break; + case TEEC_VALUE_INPUT: + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + params[n].attr = param_type; + params[n].a = operation->params[n].value.a; + params[n].b = operation->params[n].value.b; + break; + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + res = teec_pre_process_tmpref(ctx, param_type, + &operation->params[n].tmpref, params + n, + shms + n); + if (res != TEEC_SUCCESS) + return res; + break; + case TEEC_MEMREF_WHOLE: + res = teec_pre_process_whole( + &operation->params[n].memref, + params + n); + if (res != TEEC_SUCCESS) + return res; + break; + case TEEC_MEMREF_PARTIAL_INPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + res = teec_pre_process_partial(param_type, + &operation->params[n].memref, params + n); + if (res != TEEC_SUCCESS) + return res; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + } + + return TEEC_SUCCESS; +} + +static void teec_post_process_tmpref(uint32_t param_type, + struct TEEC_TempMemoryReference *tmpref, + struct tee_ioctl_param *param, + struct TEEC_SharedMemory *shm) +{ + if (param_type != TEEC_MEMREF_TEMP_INPUT) { + if (param->size <= tmpref->size && tmpref->buffer) + memcpy(tmpref->buffer, shm->buffer, + param->size); + + tmpref->size = param->size; + } +} + +static void teec_post_process_whole( + struct TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + struct TEEC_SharedMemory *shm = memref->parent; + + if (shm->flags & TEEC_MEM_OUTPUT) { + + /* + * We're using a shadow buffer in this reference, copy back + * the shadow buffer into the real buffer now that we've + * returned from secure world. + */ + if (shm->shadow_buffer && param->size <= shm->size) + memcpy(shm->buffer, shm->shadow_buffer, + param->size); + + memref->size = param->size; + } +} + +static void teec_post_process_partial(uint32_t param_type, + struct TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + if (param_type != TEEC_MEMREF_PARTIAL_INPUT) { + struct TEEC_SharedMemory *shm = memref->parent; + + /* + * We're using a shadow buffer in this reference, copy back + * the shadow buffer into the real buffer now that we've + * returned from secure world. + */ + if (shm->shadow_buffer && param->size <= memref->size) + memcpy((char *)shm->buffer + memref->offset, + (char *)shm->shadow_buffer + memref->offset, + param->size); + + memref->size = param->size; + } +} + +static void teec_post_process_operation(struct TEEC_Operation *operation, + struct tee_ioctl_param *params, + struct TEEC_SharedMemory *shms) +{ + size_t n; + + if (!operation) + return; + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + uint32_t param_type; + + param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n); + switch (param_type) { + case TEEC_VALUE_INPUT: + break; + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + operation->params[n].value.a = params[n].a; + operation->params[n].value.b = params[n].b; + break; + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + teec_post_process_tmpref(param_type, + &operation->params[n].tmpref, params + n, + shms + n); + break; + case TEEC_MEMREF_WHOLE: + teec_post_process_whole(&operation->params[n].memref, + params + n); + break; + case TEEC_MEMREF_PARTIAL_INPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + teec_post_process_partial(param_type, + &operation->params[n].memref, params + n); + default: + break; + } + } +} + +static void teec_free_temp_refs(struct TEEC_Operation *operation, + struct TEEC_SharedMemory *shms) +{ + size_t n; + + if (!operation) + return; + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + switch (TEEC_PARAM_TYPE_GET(operation->paramTypes, n)) { + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + TEEC_ReleaseSharedMemory(shms + n); + break; + default: + break; + } + } +} + +static TEEC_Result ioctl_errno_to_res(int err) +{ + switch (err) { + case -ENOMEM: + return TEEC_ERROR_OUT_OF_MEMORY; + default: + return TEEC_ERROR_GENERIC; + } +} + +static void uuid_to_octets(uint8_t d[TEE_IOCTL_UUID_LEN], + const struct TEEC_UUID *s) +{ + d[0] = s->timeLow >> 24; + d[1] = s->timeLow >> 16; + d[2] = s->timeLow >> 8; + d[3] = s->timeLow; + d[4] = s->timeMid >> 8; + d[5] = s->timeMid; + d[6] = s->timeHiAndVersion >> 8; + d[7] = s->timeHiAndVersion; + memcpy(d + 8, s->clockSeqAndNode, sizeof(s->clockSeqAndNode)); +} + +TEEC_Result TEEC_OpenSession(struct TEEC_Context *ctx, + struct TEEC_Session *session, + const struct TEEC_UUID *destination, + uint32_t connection_method, + const void *connection_data, + struct TEEC_Operation *operation, + uint32_t *ret_origin) +{ + uint64_t buf[(sizeof(struct tee_ioctl_open_session_arg) + + TEEC_CONFIG_PAYLOAD_REF_COUNT * + sizeof(struct tee_ioctl_param)) / + sizeof(uint64_t)] = { 0 }; + struct tee_ioctl_buf_data buf_data; + struct tee_ioctl_open_session_arg *arg; + struct tee_ioctl_param *params; + TEEC_Result res; + uint32_t eorig; + struct TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; + int rc; + + (void)&connection_data; + + if (!ctx || !session) { + eorig = TEEC_ORIGIN_API; + res = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + + buf_data.buf_ptr = (uintptr_t)buf; + buf_data.buf_len = sizeof(buf); + + arg = (struct tee_ioctl_open_session_arg *)buf; + arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; + params = (struct tee_ioctl_param *)(arg + 1); + + uuid_to_octets(arg->uuid, destination); + arg->clnt_login = connection_method; + + res = teec_pre_process_operation(ctx, operation, params, shm); + if (res != TEEC_SUCCESS) { + eorig = TEEC_ORIGIN_API; + goto out_free_temp_refs; + } + + rc = ioctl(ctx->fd, TEE_IOC_OPEN_SESSION, &buf_data); + if (rc) { + IMSG_ERROR("TEE_IOC_OPEN_SESSION failed"); + eorig = TEEC_ORIGIN_COMMS; + res = ioctl_errno_to_res(rc); + goto out_free_temp_refs; + } + res = arg->ret; + eorig = arg->ret_origin; + if (res == TEEC_SUCCESS) { + session->ctx = ctx; + session->session_id = arg->session; + } + teec_post_process_operation(operation, params, shm); + +out_free_temp_refs: + teec_free_temp_refs(operation, shm); +out: + if (ret_origin) + *ret_origin = eorig; + return res; +} +EXPORT_SYMBOL(TEEC_OpenSession); + +void TEEC_CloseSession(struct TEEC_Session *session) +{ + struct tee_ioctl_close_session_arg arg; + + if (!session) + return; + + arg.session = session->session_id; + if (ioctl(session->ctx->fd, TEE_IOC_CLOSE_SESSION, &arg)) + IMSG_ERROR("Failed to close session 0x%x", + session->session_id); +} +EXPORT_SYMBOL(TEEC_CloseSession); + +TEEC_Result TEEC_InvokeCommand(struct TEEC_Session *session, uint32_t cmd_id, + struct TEEC_Operation *operation, uint32_t *error_origin) +{ + uint64_t buf[(sizeof(struct tee_ioctl_invoke_arg) + + TEEC_CONFIG_PAYLOAD_REF_COUNT * + sizeof(struct tee_ioctl_param)) / + sizeof(uint64_t)] = { 0 }; + struct tee_ioctl_buf_data buf_data; + struct tee_ioctl_invoke_arg *arg; + struct tee_ioctl_param *params; + TEEC_Result res; + uint32_t eorig; + struct TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; + int rc; + + if (!session) { + eorig = TEEC_ORIGIN_API; + res = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + + buf_data.buf_ptr = (uintptr_t)buf; + buf_data.buf_len = sizeof(buf); + + arg = (struct tee_ioctl_invoke_arg *)buf; + arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; + params = (struct tee_ioctl_param *)(arg + 1); + + arg->session = session->session_id; + arg->func = cmd_id; + + if (operation) { + teec_mutex_lock(&teec_mutex); + operation->session = session; + teec_mutex_unlock(&teec_mutex); + } + + res = teec_pre_process_operation(session->ctx, operation, params, shm); + if (res != TEEC_SUCCESS) { + eorig = TEEC_ORIGIN_API; + goto out_free_temp_refs; + } + + rc = ioctl(session->ctx->fd, TEE_IOC_INVOKE, &buf_data); + if (rc) { + IMSG_ERROR("TEE_IOC_INVOKE failed"); + eorig = TEEC_ORIGIN_COMMS; + res = ioctl_errno_to_res(rc); + goto out_free_temp_refs; + } + + res = arg->ret; + eorig = arg->ret_origin; + teec_post_process_operation(operation, params, shm); + +out_free_temp_refs: + teec_free_temp_refs(operation, shm); +out: + if (error_origin) + *error_origin = eorig; + return res; +} +EXPORT_SYMBOL(TEEC_InvokeCommand); + +void TEEC_RequestCancellation(struct TEEC_Operation *operation) +{ + struct tee_ioctl_cancel_arg arg; + struct TEEC_Session *session; + int ret; + + if (!operation) + return; + + teec_mutex_lock(&teec_mutex); + session = operation->session; + teec_mutex_unlock(&teec_mutex); + + if (!session) + return; + + arg.session = session->session_id; + arg.cancel_id = 0; + + ret = ioctl(session->ctx->fd, TEE_IOC_CANCEL, &arg); + if (ret) + IMSG_ERROR("TEE_IOC_CANCEL: %d", ret); +} +EXPORT_SYMBOL(TEEC_RequestCancellation); + +TEEC_Result TEEC_RegisterSharedMemory(struct TEEC_Context *ctx, + struct TEEC_SharedMemory *shm) +{ + int fd; + size_t s; + struct dma_buf *dma_buf; + struct tee_shm *tee_shm; + + if (!ctx || !shm) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + return TEEC_ERROR_BAD_PARAMETERS; + + s = shm->size; + if (!s) + s = 8; + + fd = teec_shm_alloc(ctx->fd, s, &shm->id); + if (fd < 0) + return TEEC_ERROR_OUT_OF_MEMORY; + dma_buf = dma_buf_get(fd); + close(fd); + + if (!dma_buf) { + shm->id = -1; + return TEEC_ERROR_OUT_OF_MEMORY; + } + + tee_shm = dma_buf->priv; + + shm->priv = dma_buf; + shm->shadow_buffer = tee_shm->kaddr; + shm->alloced_size = s; + shm->registered_fd = -1; + return TEEC_SUCCESS; +} +EXPORT_SYMBOL(TEEC_RegisterSharedMemory); + +TEEC_Result TEEC_RegisterSharedMemoryFileDescriptor(struct TEEC_Context *ctx, + struct TEEC_SharedMemory *shm, + int fd) +{ + struct tee_ioctl_shm_register_fd_data data; + int rfd; + + if (!ctx || !shm || fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + return TEEC_ERROR_BAD_PARAMETERS; + + memset(&data, 0, sizeof(data)); + data.fd = fd; + rfd = ioctl(ctx->fd, TEE_IOC_SHM_REGISTER_FD, &data); + if (rfd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + shm->priv = NULL; + shm->buffer = NULL; + shm->shadow_buffer = NULL; + shm->registered_fd = rfd; + shm->id = data.id; + shm->size = data.size; + return TEEC_SUCCESS; +} +EXPORT_SYMBOL(TEEC_RegisterSharedMemoryFileDescriptor); + +TEEC_Result TEEC_AllocateSharedMemory(struct TEEC_Context *ctx, + struct TEEC_SharedMemory *shm) +{ + int fd; + size_t s; + struct dma_buf *dma_buf; + struct tee_shm *tee_shm; + + if (!ctx || !shm) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + return TEEC_ERROR_BAD_PARAMETERS; + + s = shm->size; + if (!s) + s = 8; + + fd = teec_shm_alloc(ctx->fd, s, &shm->id); + if (fd < 0) + return TEEC_ERROR_OUT_OF_MEMORY; + dma_buf = dma_buf_get(fd); + close(fd); + + if (!dma_buf) { + shm->id = -1; + return TEEC_ERROR_OUT_OF_MEMORY; + } + + tee_shm = dma_buf->priv; + + shm->priv = dma_buf; + shm->buffer = tee_shm->kaddr; + shm->shadow_buffer = NULL; + shm->alloced_size = s; + shm->registered_fd = -1; + return TEEC_SUCCESS; +} +EXPORT_SYMBOL(TEEC_AllocateSharedMemory); + +void TEEC_ReleaseSharedMemory(struct TEEC_SharedMemory *shm) +{ + if (!shm || shm->id == -1) + return; + + if (shm->priv) { + struct dma_buf *dma_buf = shm->priv; + + dma_buf_put(dma_buf); + } + + if (shm->registered_fd >= 0) + close(shm->registered_fd); + + shm->id = -1; + shm->priv = NULL; + if (shm->shadow_buffer == NULL) + shm->buffer = NULL; + shm->shadow_buffer = NULL; + shm->registered_fd = -1; +} +EXPORT_SYMBOL(TEEC_ReleaseSharedMemory); diff --git a/drivers/tee/teei/300/tee/tee_core.c b/drivers/tee/teei/300/tee/tee_core.c new file mode 100644 index 000000000000..edda8520a249 --- /dev/null +++ b/drivers/tee/teei/300/tee/tee_core.c @@ -0,0 +1,1085 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2016, Linaro Limited + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tee_private.h" +#include "capi_proxy.h" +#include "teei_id.h" + +#define TEE_NUM_DEVICES 32 + +#define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x)) + +/* + * Unprivileged devices in the lower half range and privileged devices in + * the upper half range. + */ +static DECLARE_BITMAP(dev_mask, TEE_NUM_DEVICES); +static DEFINE_SPINLOCK(driver_lock); + +static struct class *tee_class; +static dev_t tee_devt; + +/* helper to convert user pointers passed inside __aligned_u64 fields */ +#ifndef u64_to_user_ptr +static void __user *u64_to_user_ptr(__u64 val) +{ + return (void __user *) (unsigned long) val; +} +#endif + +static struct tee_context *teedev_open(struct tee_device *teedev) +{ + int rc; + struct tee_context *ctx; + + if (!isee_device_get(teedev)) + return ERR_PTR(-EINVAL); + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + rc = -ENOMEM; + goto err; + } + + ctx->teedev = teedev; + INIT_LIST_HEAD(&ctx->list_shm); + rc = teedev->desc->ops->open(ctx); + if (rc) + goto err; + + return ctx; +err: + kfree(ctx); + isee_device_put(teedev); + return ERR_PTR(rc); + +} + +static void teedev_close_context(struct tee_context *ctx) +{ + struct tee_shm *shm; + + ctx->teedev->desc->ops->release(ctx); + mutex_lock(&ctx->teedev->mutex); + list_for_each_entry(shm, &ctx->list_shm, link) + shm->ctx = NULL; + mutex_unlock(&ctx->teedev->mutex); + isee_device_put(ctx->teedev); + kfree(ctx); +} + +static int tee_open(struct inode *inode, struct file *filp) +{ + struct tee_context *ctx; + + ctx = teedev_open(container_of(inode->i_cdev, struct tee_device, cdev)); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + filp->private_data = ctx; + return 0; +} + +static int tee_release(struct inode *inode, struct file *filp) +{ + teedev_close_context(filp->private_data); + return 0; +} + +static int tee_ioctl_version(struct tee_context *ctx, + struct tee_ioctl_version_data __user *uvers) +{ + struct tee_ioctl_version_data vers; + + ctx->teedev->desc->ops->get_version(ctx->teedev, &vers); + + if (ctx->teedev->desc->flags & TEE_DESC_PRIVILEGED) + vers.gen_caps |= TEE_GEN_CAP_PRIVILEGED; + + if (copy_to_user(uvers, &vers, sizeof(vers))) + return -EFAULT; + + return 0; +} + +static int tee_ioctl_shm_alloc(struct tee_context *ctx, + struct tee_ioctl_shm_alloc_data __user *udata) +{ + long ret; + struct tee_ioctl_shm_alloc_data data; + struct tee_shm *shm; + + if (copy_from_user(&data, udata, sizeof(data))) + return -EFAULT; + + /* Currently no input flags are supported */ + if (data.flags) + return -EINVAL; + + data.id = -1; + + shm = isee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + data.id = shm->id; + data.flags = shm->flags; + data.size = shm->size; + + if (copy_to_user(udata, &data, sizeof(data))) + ret = -EFAULT; + else + ret = isee_shm_get_fd(shm); + + /* + * When user space closes the file descriptor the shared memory + * should be freed or if isee_shm_get_fd() failed then it will + * be freed immediately. + */ + isee_shm_put(shm); + return ret; +} + +#ifdef CONFIG_MICROTRUST_TEST_DRIVERS + +static inline void flush_shm_dcache(void *start, size_t len) +{ +#ifdef CONFIG_ARM64 + __flush_dcache_area(start, len); +#else + __cpuc_flush_dcache_area(start, len); +#endif +} + +static inline void invalid_shm_dcache(void *start, size_t len) +{ + __Invalidate_Dcache_By_Area((unsigned long)start, + (unsigned long)(start + len)); +} + +static int tee_ioctl_shm_kern_op(struct tee_context *ctx, + struct tee_ioctl_shm_kern_op_arg __user *udata) +{ + long ret = 0; + + struct tee_ioctl_shm_kern_op_arg data; + struct tee_shm *shm; + + if (copy_from_user(&data, udata, sizeof(data))) + return -EFAULT; + + + shm = isee_shm_get_from_id(ctx, data.id); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + switch (data.opcode) { + case TEE_IOCTL_SHM_KERN_OP_GET_PA: + data.paddr = shm->paddr; + break; + case TEE_IOCTL_SHM_KERN_OP_FLUSH_CACHE: + flush_shm_dcache(shm->kaddr, shm->size); + break; + case TEE_IOCTL_SHM_KERN_OP_INVALID_CACHE: + invalid_shm_dcache(shm->kaddr, shm->size); + break; + default: + ret = -EINVAL; + goto out; + } + + if (copy_to_user(udata, &data, sizeof(data))) + ret = -EFAULT; + + /* + * When user space closes the file descriptor the shared memory + * should be freed or if isee_shm_get_fd() failed then it will + * be freed immediately. + */ +out: + isee_shm_put(shm); + + return ret; +} + +#endif + +static int params_from_user(struct tee_context *ctx, struct tee_param *params, + size_t num_params, + struct tee_ioctl_param __user *uparams) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + struct tee_shm *shm; + struct tee_ioctl_param ip; + + if (copy_from_user(&ip, uparams + n, sizeof(ip))) + return -EFAULT; + + /* All unused attribute bits has to be zero */ + if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_MASK) + return -EINVAL; + + params[n].attr = ip.attr; + switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_NONE: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + params[n].u.value.a = ip.a; + params[n].u.value.b = ip.b; + params[n].u.value.c = ip.c; + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + /* + * If we fail to get a pointer to a shared memory + * object (and increase the ref count) from an + * identifier we return an error. All pointers that + * has been added in params have an increased ref + * count. It's the callers responibility to do + * isee_shm_put() on all resolved pointers. + */ + shm = isee_shm_get_from_id(ctx, ip.c); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + params[n].u.memref.shm_offs = ip.a; + params[n].u.memref.size = ip.b; + params[n].u.memref.shm = shm; + break; + default: + /* Unknown attribute */ + return -EINVAL; + } + } + return 0; +} + +static int params_to_user(struct tee_ioctl_param __user *uparams, + size_t num_params, struct tee_param *params) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + struct tee_ioctl_param __user *up = uparams + n; + struct tee_param *p = params + n; + + switch (p->attr) { + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + if (put_user(p->u.value.a, &up->a) || + put_user(p->u.value.b, &up->b) || + put_user(p->u.value.c, &up->c)) + return -EFAULT; + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + if (put_user((u64)p->u.memref.size, &up->b)) + return -EFAULT; + default: + break; + } + } + return 0; +} + +static int tee_ioctl_open_session(struct tee_context *ctx, + struct tee_ioctl_buf_data __user *ubuf) +{ + int rc; + size_t n; + struct tee_ioctl_buf_data buf; + struct tee_ioctl_open_session_arg __user *uarg; + struct tee_ioctl_open_session_arg arg; + struct tee_ioctl_param __user *uparams = NULL; + struct tee_param *params = NULL; + bool have_session = false; + + if (!ctx->teedev->desc->ops->open_session) + return -EINVAL; + + if (copy_from_user(&buf, ubuf, sizeof(buf))) + return -EFAULT; + + if (buf.buf_len > TEE_MAX_ARG_SIZE || + buf.buf_len < sizeof(struct tee_ioctl_open_session_arg)) + return -EINVAL; + + uarg = u64_to_user_ptr(buf.buf_ptr); + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len) + return -EINVAL; + + if (arg.num_params) { + params = kcalloc(arg.num_params, sizeof(struct tee_param), + GFP_KERNEL); + if (!params) + return -ENOMEM; + uparams = uarg->params; + rc = params_from_user(ctx, params, arg.num_params, uparams); + if (rc) + goto out; + } + + rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params); + if (rc) + goto out; + have_session = true; + + if (put_user(arg.session, &uarg->session) || + put_user(arg.ret, &uarg->ret) || + put_user(arg.ret_origin, &uarg->ret_origin)) { + rc = -EFAULT; + goto out; + } + rc = params_to_user(uparams, arg.num_params, params); +out: + /* + * If we've succeeded to open the session but failed to communicate + * it back to user space, close the session again to avoid leakage. + */ + if (rc && have_session && ctx->teedev->desc->ops->close_session) + ctx->teedev->desc->ops->close_session(ctx, arg.session); + + if (params) { + /* Decrease ref count for all valid shared memory pointers */ + for (n = 0; n < arg.num_params; n++) + if (tee_param_is_memref(params + n) && + params[n].u.memref.shm) + isee_shm_put(params[n].u.memref.shm); + kfree(params); + } + + return rc; +} + +static int tee_ioctl_invoke(struct tee_context *ctx, + struct tee_ioctl_buf_data __user *ubuf) +{ + int rc; + size_t n; + struct tee_ioctl_buf_data buf; + struct tee_ioctl_invoke_arg __user *uarg; + struct tee_ioctl_invoke_arg arg; + struct tee_ioctl_param __user *uparams = NULL; + struct tee_param *params = NULL; + + if (!ctx->teedev->desc->ops->invoke_func) + return -EINVAL; + + if (copy_from_user(&buf, ubuf, sizeof(buf))) + return -EFAULT; + + if (buf.buf_len > TEE_MAX_ARG_SIZE || + buf.buf_len < sizeof(struct tee_ioctl_invoke_arg)) + return -EINVAL; + + uarg = u64_to_user_ptr(buf.buf_ptr); + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len) + return -EINVAL; + + if (arg.num_params) { + params = kcalloc(arg.num_params, sizeof(struct tee_param), + GFP_KERNEL); + if (!params) + return -ENOMEM; + uparams = uarg->params; + rc = params_from_user(ctx, params, arg.num_params, uparams); + if (rc) + goto out; + } + + rc = ctx->teedev->desc->ops->invoke_func(ctx, &arg, params); + if (rc) + goto out; + + if (put_user(arg.ret, &uarg->ret) || + put_user(arg.ret_origin, &uarg->ret_origin)) { + rc = -EFAULT; + goto out; + } + rc = params_to_user(uparams, arg.num_params, params); +out: + if (params) { + /* Decrease ref count for all valid shared memory pointers */ + for (n = 0; n < arg.num_params; n++) + if (tee_param_is_memref(params + n) && + params[n].u.memref.shm) + isee_shm_put(params[n].u.memref.shm); + kfree(params); + } + return rc; +} + +static int tee_ioctl_cancel(struct tee_context *ctx, + struct tee_ioctl_cancel_arg __user *uarg) +{ + struct tee_ioctl_cancel_arg arg; + + if (!ctx->teedev->desc->ops->cancel_req) + return -EINVAL; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + return ctx->teedev->desc->ops->cancel_req(ctx, arg.cancel_id, + arg.session); +} + +static int +tee_ioctl_close_session(struct tee_context *ctx, + struct tee_ioctl_close_session_arg __user *uarg) +{ + struct tee_ioctl_close_session_arg arg; + + if (!ctx->teedev->desc->ops->close_session) + return -EINVAL; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + return ctx->teedev->desc->ops->close_session(ctx, arg.session); +} + +static int params_to_supp(struct tee_context *ctx, + struct tee_ioctl_param __user *uparams, + size_t num_params, struct tee_param *params) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + struct tee_ioctl_param ip; + struct tee_param *p = params + n; + + ip.attr = p->attr; + switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + ip.a = p->u.value.a; + ip.b = p->u.value.b; + ip.c = p->u.value.c; + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + ip.b = p->u.memref.size; + if (!p->u.memref.shm) { + ip.a = 0; + ip.c = (u64)-1; /* invalid shm id */ + break; + } + ip.a = p->u.memref.shm_offs; + ip.c = p->u.memref.shm->id; + break; + default: + ip.a = 0; + ip.b = 0; + ip.c = 0; + break; + } + + if (copy_to_user(uparams + n, &ip, sizeof(ip))) + return -EFAULT; + } + + return 0; +} + +static int tee_ioctl_supp_recv(struct tee_context *ctx, + struct tee_ioctl_buf_data __user *ubuf) +{ + int rc; + struct tee_ioctl_buf_data buf; + struct tee_iocl_supp_recv_arg __user *uarg; + struct tee_param *params; + u32 num_params; + u32 func; + + if (!ctx->teedev->desc->ops->supp_recv) + return -EINVAL; + + if (copy_from_user(&buf, ubuf, sizeof(buf))) + return -EFAULT; + + if (buf.buf_len > TEE_MAX_ARG_SIZE || + buf.buf_len < sizeof(struct tee_iocl_supp_recv_arg)) + return -EINVAL; + + uarg = u64_to_user_ptr(buf.buf_ptr); + if (get_user(num_params, &uarg->num_params)) + return -EFAULT; + + if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) != buf.buf_len) + return -EINVAL; + + params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL); + if (!params) + return -ENOMEM; + + rc = params_from_user(ctx, params, num_params, uarg->params); + if (rc) + goto out; + + rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params); + if (rc) + goto out; + + if (put_user(func, &uarg->func) || + put_user(num_params, &uarg->num_params)) { + rc = -EFAULT; + goto out; + } + + rc = params_to_supp(ctx, uarg->params, num_params, params); +out: + kfree(params); + return rc; +} + +static int params_from_supp(struct tee_param *params, size_t num_params, + struct tee_ioctl_param __user *uparams) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + struct tee_param *p = params + n; + struct tee_ioctl_param ip; + + if (copy_from_user(&ip, uparams + n, sizeof(ip))) + return -EFAULT; + + /* All unused attribute bits has to be zero */ + if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_MASK) + return -EINVAL; + + p->attr = ip.attr; + switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + /* Only out and in/out values can be updated */ + p->u.value.a = ip.a; + p->u.value.b = ip.b; + p->u.value.c = ip.c; + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + /* + * Only the size of the memref can be updated. + * Since we don't have access to the original + * parameters here, only store the supplied size. + * The driver will copy the updated size into the + * original parameters. + */ + p->u.memref.shm = NULL; + p->u.memref.shm_offs = 0; + p->u.memref.size = ip.b; + break; + default: + memset(&p->u, 0, sizeof(p->u)); + break; + } + } + return 0; +} + +static int tee_ioctl_supp_send(struct tee_context *ctx, + struct tee_ioctl_buf_data __user *ubuf) +{ + long rc; + struct tee_ioctl_buf_data buf; + struct tee_iocl_supp_send_arg __user *uarg; + struct tee_param *params; + u32 num_params; + u32 ret; + + /* Not valid for this driver */ + if (!ctx->teedev->desc->ops->supp_send) + return -EINVAL; + + if (copy_from_user(&buf, ubuf, sizeof(buf))) + return -EFAULT; + + if (buf.buf_len > TEE_MAX_ARG_SIZE || + buf.buf_len < sizeof(struct tee_iocl_supp_send_arg)) + return -EINVAL; + + uarg = u64_to_user_ptr(buf.buf_ptr); + if (get_user(ret, &uarg->ret) || + get_user(num_params, &uarg->num_params)) + return -EFAULT; + + if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) > buf.buf_len) + return -EINVAL; + + params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL); + if (!params) + return -ENOMEM; + + rc = params_from_supp(params, num_params, uarg->params); + if (rc) + goto out; + + rc = ctx->teedev->desc->ops->supp_send(ctx, ret, num_params, params); +out: + kfree(params); + return rc; +} + +static int tee_ioctl_set_hostname(struct tee_context *ctx, + struct tee_ioctl_close_session_arg __user *uarg) +{ + struct tee_ioctl_set_hostname_arg arg; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + memcpy(ctx->hostname, arg.hostname, TEE_MAX_HOSTNAME_SIZE-1); + + return 0; +} + +static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct tee_context *ctx = filp->private_data; + void __user *uarg = (void __user *)arg; + + switch (cmd) { + case TEE_IOC_VERSION: + return tee_ioctl_version(ctx, uarg); + case TEE_IOC_SHM_ALLOC: + return tee_ioctl_shm_alloc(ctx, uarg); +#ifdef CONFIG_MICROTRUST_TEST_DRIVERS + case TEE_IOC_SHM_KERN_OP: + return tee_ioctl_shm_kern_op(ctx, uarg); + case TEE_IOC_CAPI_PROXY: + return tee_ioctl_capi_proxy(ctx, uarg); +#endif + case TEE_IOC_OPEN_SESSION: + return tee_ioctl_open_session(ctx, uarg); + case TEE_IOC_INVOKE: + return tee_ioctl_invoke(ctx, uarg); + case TEE_IOC_CANCEL: + return tee_ioctl_cancel(ctx, uarg); + case TEE_IOC_CLOSE_SESSION: + return tee_ioctl_close_session(ctx, uarg); + case TEE_IOC_SUPPL_RECV: + return tee_ioctl_supp_recv(ctx, uarg); + case TEE_IOC_SUPPL_SEND: + return tee_ioctl_supp_send(ctx, uarg); + case TEE_IOC_SET_HOSTNAME: + return tee_ioctl_set_hostname(ctx, uarg); + default: + return -EINVAL; + } +} + +static const struct file_operations tee_fops = { + .owner = THIS_MODULE, + .open = tee_open, + .release = tee_release, + .unlocked_ioctl = tee_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tee_ioctl, +#endif +}; + +static void tee_release_device(struct device *dev) +{ + struct tee_device *teedev = container_of(dev, struct tee_device, dev); + + spin_lock(&driver_lock); + clear_bit(teedev->id, dev_mask); + spin_unlock(&driver_lock); + mutex_destroy(&teedev->mutex); + idr_destroy(&teedev->idr); + kfree(teedev); +} + +/** + * isee_device_alloc() - Allocate a new struct tee_device instance + * @teedesc: Descriptor for this driver + * @dev: Parent device for this device + * @pool: Shared memory pool, NULL if not used + * @driver_data: Private driver data for this device + * + * Allocates a new struct tee_device instance. The device is + * removed by isee_device_unregister(). + * + * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure + */ +struct tee_device *isee_device_alloc(const struct tee_desc *teedesc, + struct device *dev, + struct tee_shm_pool *pool, + void *driver_data) +{ + struct tee_device *teedev; + void *ret; + int rc; + int offs = 0; + + if (!teedesc || !teedesc->name || !teedesc->ops || + !teedesc->ops->get_version || !teedesc->ops->open || + !teedesc->ops->release || !pool) + return ERR_PTR(-EINVAL); + + teedev = kzalloc(sizeof(*teedev), GFP_KERNEL); + if (!teedev) { + ret = ERR_PTR(-ENOMEM); + goto err; + } + + if (teedesc->flags & TEE_DESC_PRIVILEGED) + offs = TEE_NUM_DEVICES / 2; + + spin_lock(&driver_lock); + teedev->id = find_next_zero_bit(dev_mask, TEE_NUM_DEVICES, offs); + if (teedev->id < TEE_NUM_DEVICES) + set_bit(teedev->id, dev_mask); + spin_unlock(&driver_lock); + + if (teedev->id >= TEE_NUM_DEVICES) { + ret = ERR_PTR(-ENOMEM); + goto err; + } + + snprintf(teedev->name, sizeof(teedev->name), "isee_tee%s%d", + teedesc->flags & TEE_DESC_PRIVILEGED ? "priv" : "", + teedev->id - offs); + + teedev->dev.class = tee_class; + teedev->dev.release = tee_release_device; + teedev->dev.parent = dev; + + teedev->dev.devt = MKDEV(MAJOR(tee_devt), teedev->id); + + rc = dev_set_name(&teedev->dev, "%s", teedev->name); + if (rc) { + ret = ERR_PTR(rc); + goto err_devt; + } + + cdev_init(&teedev->cdev, &tee_fops); + teedev->cdev.owner = teedesc->owner; + teedev->cdev.kobj.parent = &teedev->dev.kobj; + + dev_set_drvdata(&teedev->dev, driver_data); + device_initialize(&teedev->dev); + + /* 1 as isee_device_unregister() does one final isee_device_put() */ + teedev->num_users = 1; + init_completion(&teedev->c_no_users); + mutex_init(&teedev->mutex); + idr_init(&teedev->idr); + + teedev->desc = teedesc; + teedev->pool = pool; + + return teedev; +err_devt: + unregister_chrdev_region(teedev->dev.devt, 1); +err: + IMSG_ERROR("could not register %s driver\n", + teedesc->flags & TEE_DESC_PRIVILEGED ? "privileged" : "client"); + if (teedev && teedev->id < TEE_NUM_DEVICES) { + spin_lock(&driver_lock); + clear_bit(teedev->id, dev_mask); + spin_unlock(&driver_lock); + } + kfree(teedev); + return ret; +} +EXPORT_SYMBOL_GPL(isee_device_alloc); + +static ssize_t implementation_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tee_device *teedev = container_of(dev, struct tee_device, dev); + struct tee_ioctl_version_data vers; + + teedev->desc->ops->get_version(teedev, &vers); + return scnprintf(buf, PAGE_SIZE, "%d\n", vers.impl_id); +} +static DEVICE_ATTR_RO(implementation_id); + +static struct attribute *tee_dev_attrs[] = { + &dev_attr_implementation_id.attr, + NULL +}; + +static const struct attribute_group tee_dev_group = { + .attrs = tee_dev_attrs, +}; + +/** + * isee_device_register() - Registers a TEE device + * @teedev: Device to register + * + * isee_device_unregister() need to be called to remove the @teedev if + * this function fails. + * + * @returns < 0 on failure + */ +int isee_device_register(struct tee_device *teedev) +{ + int rc; + + if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) { + IMSG_ERROR("attempt to register twice\n"); + return -EINVAL; + } + + rc = cdev_add(&teedev->cdev, teedev->dev.devt, 1); + if (rc) { + IMSG_ERROR( + "unable to cdev_add() %s, major %d, minor %d, err=%d\n", + teedev->name, MAJOR(teedev->dev.devt), + MINOR(teedev->dev.devt), rc); + return rc; + } + + rc = device_add(&teedev->dev); + if (rc) { + IMSG_ERROR( + "unable to device_add() %s, major %d, minor %d, err=%d\n", + teedev->name, MAJOR(teedev->dev.devt), + MINOR(teedev->dev.devt), rc); + goto err_device_add; + } + + rc = sysfs_create_group(&teedev->dev.kobj, &tee_dev_group); + if (rc) { + IMSG_ERROR( + "failed to create sysfs attributes, err=%d\n", rc); + goto err_sysfs_create_group; + } + + teedev->flags |= TEE_DEVICE_FLAG_REGISTERED; + return 0; + +err_sysfs_create_group: + device_del(&teedev->dev); +err_device_add: + cdev_del(&teedev->cdev); + return rc; +} +EXPORT_SYMBOL_GPL(isee_device_register); + +void isee_device_put(struct tee_device *teedev) +{ + mutex_lock(&teedev->mutex); + /* Shouldn't put in this state */ + if (!WARN_ON(!teedev->desc)) { + teedev->num_users--; + if (!teedev->num_users) { + teedev->desc = NULL; + complete(&teedev->c_no_users); + } + } + mutex_unlock(&teedev->mutex); +} + +bool isee_device_get(struct tee_device *teedev) +{ + mutex_lock(&teedev->mutex); + if (!teedev->desc) { + mutex_unlock(&teedev->mutex); + return false; + } + teedev->num_users++; + mutex_unlock(&teedev->mutex); + return true; +} + +/** + * isee_device_unregister() - Removes a TEE device + * @teedev: Device to unregister + * + * This function should be called to remove the @teedev even if + * isee_device_register() hasn't been called yet. Does nothing if + * @teedev is NULL. + */ +void isee_device_unregister(struct tee_device *teedev) +{ + if (!teedev) + return; + + if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) { + sysfs_remove_group(&teedev->dev.kobj, &tee_dev_group); + cdev_del(&teedev->cdev); + device_del(&teedev->dev); + } + + isee_device_put(teedev); + wait_for_completion(&teedev->c_no_users); + + /* + * No need to take a mutex any longer now since teedev->desc was + * set to NULL before teedev->c_no_users was completed. + */ + + teedev->pool = NULL; + + put_device(&teedev->dev); +} +EXPORT_SYMBOL_GPL(isee_device_unregister); + +/** + * isee_get_drvdata() - Return driver_data pointer + * @teedev: Device containing the driver_data pointer + * @returns the driver_data pointer supplied to tee_register(). + */ +void *isee_get_drvdata(struct tee_device *teedev) +{ + return dev_get_drvdata(&teedev->dev); +} +EXPORT_SYMBOL_GPL(isee_get_drvdata); + +struct match_dev_data { + struct tee_ioctl_version_data *vers; + const void *data; + int (*match)(struct tee_ioctl_version_data *vars, const void *data); +}; + +static int match_dev(struct device *dev, const void *data) +{ + const struct match_dev_data *match_data = data; + struct tee_device *teedev = container_of(dev, struct tee_device, dev); + + teedev->desc->ops->get_version(teedev, match_data->vers); + return match_data->match(match_data->vers, match_data->data); +} + +struct tee_context *tee_client_open_context(struct tee_context *start, + int (*match)(struct tee_ioctl_version_data *, + const void *), + const void *data, struct tee_ioctl_version_data *vers) +{ + struct device *dev = NULL; + struct device *put_dev = NULL; + struct tee_context *ctx = NULL; + struct tee_ioctl_version_data v; + struct match_dev_data match_data = { vers ? vers : &v, data, match }; + + if (start) + dev = &start->teedev->dev; + + do { + dev = class_find_device(tee_class, dev, &match_data, match_dev); + if (!dev) { + ctx = ERR_PTR(-ENOENT); + break; + } + + put_device(put_dev); + put_dev = dev; + + ctx = teedev_open(container_of(dev, struct tee_device, dev)); + } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM); + + put_device(put_dev); + return ctx; +} +EXPORT_SYMBOL_GPL(tee_client_open_context); + +void tee_client_close_context(struct tee_context *ctx) +{ + teedev_close_context(ctx); +} +EXPORT_SYMBOL_GPL(tee_client_close_context); + +void tee_client_get_version(struct tee_context *ctx, + struct tee_ioctl_version_data *vers) +{ + ctx->teedev->desc->ops->get_version(ctx->teedev, vers); +} +EXPORT_SYMBOL_GPL(tee_client_get_version); + + +int tee_client_open_session(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param) +{ + if (!ctx->teedev->desc->ops->open_session) + return -EINVAL; + return ctx->teedev->desc->ops->open_session(ctx, arg, param); +} +EXPORT_SYMBOL_GPL(tee_client_open_session); + +int tee_client_close_session(struct tee_context *ctx, u32 session) +{ + if (!ctx->teedev->desc->ops->close_session) + return -EINVAL; + return ctx->teedev->desc->ops->close_session(ctx, session); +} +EXPORT_SYMBOL_GPL(tee_client_close_session); + +int tee_client_invoke_func(struct tee_context *ctx, + struct tee_ioctl_invoke_arg *arg, + struct tee_param *param) +{ + if (!ctx->teedev->desc->ops->invoke_func) + return -EINVAL; + return ctx->teedev->desc->ops->invoke_func(ctx, arg, param); +} +EXPORT_SYMBOL_GPL(tee_client_invoke_func); + +static int __init tee_init(void) +{ + int rc; + + tee_class = class_create(THIS_MODULE, "isee_tee"); + if (IS_ERR(tee_class)) { + IMSG_ERROR("couldn't create class\n"); + return PTR_ERR(tee_class); + } + + rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "isee_tee"); + if (rc) { + IMSG_ERROR("failed to allocate char dev region\n"); + class_destroy(tee_class); + tee_class = NULL; + } + + return rc; +} + +static void __exit tee_exit(void) +{ + class_destroy(tee_class); + tee_class = NULL; + unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); +} + +subsys_initcall(tee_init); +module_exit(tee_exit); + +MODULE_AUTHOR("MICROTRUST"); +MODULE_DESCRIPTION("TEE Driver"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tee/teei/300/tee/tee_private.h b/drivers/tee/teei/300/tee/tee_private.h new file mode 100644 index 000000000000..d96e0b4c9aae --- /dev/null +++ b/drivers/tee/teei/300/tee/tee_private.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2016, Linaro Limited + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * + */ +#ifndef TEE_PRIVATE_H +#define TEE_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +struct tee_device; + +/** + * struct tee_shm - shared memory object + * @teedev: device used to allocate the object + * @ctx: context using the object, if NULL the context is gone + * @link link element + * @paddr: physical address of the shared memory + * @kaddr: virtual address of the shared memory + * @size: size of shared memory + * @dmabuf: dmabuf used to for exporting to user space + * @flags: defined by TEE_SHM_* in tee_drv.h + * @id: unique id of a shared memory object on this device + */ +struct tee_shm { + struct tee_device *teedev; + struct tee_context *ctx; + struct list_head link; + phys_addr_t paddr; + void *kaddr; + size_t size; + struct dma_buf *dmabuf; + u32 flags; + int id; +}; + +struct tee_shm_pool_mgr; + +/** + * struct tee_shm_pool_mgr_ops - shared memory pool manager operations + * @alloc: called when allocating shared memory + * @free: called when freeing shared memory + */ +struct tee_shm_pool_mgr_ops { + int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm, + size_t size); + void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm); +}; + +/** + * struct tee_shm_pool_mgr - shared memory manager + * @ops: operations + * @private_data: private data for the shared memory manager + */ +struct tee_shm_pool_mgr { + const struct tee_shm_pool_mgr_ops *ops; + void *private_data; +}; + +/** + * struct tee_shm_pool - shared memory pool + * @private_mgr: pool manager for shared memory only between kernel + * and secure world + * @dma_buf_mgr: pool manager for shared memory exported to user space + * @destroy: called when destroying the pool + * @private_data: private data for the pool + */ +struct tee_shm_pool { + struct tee_shm_pool_mgr private_mgr; + struct tee_shm_pool_mgr dma_buf_mgr; + void (*destroy)(struct tee_shm_pool *pool); + void *private_data; +}; + +#define TEE_DEVICE_FLAG_REGISTERED 0x1 +#define TEE_MAX_DEV_NAME_LEN 32 + +/** + * struct tee_device - TEE Device representation + * @name: name of device + * @desc: description of device + * @id: unique id of device + * @flags: represented by TEE_DEVICE_FLAG_REGISTERED above + * @dev: embedded basic device structure + * @cdev: embedded cdev + * @num_users: number of active users of this device + * @c_no_user: completion used when unregistering the device + * @mutex: mutex protecting @num_users and @idr + * @idr: register of shared memory object allocated on this device + * @pool: shared memory pool + */ +struct tee_device { + char name[TEE_MAX_DEV_NAME_LEN]; + const struct tee_desc *desc; + int id; + unsigned int flags; + + struct device dev; + struct cdev cdev; + + size_t num_users; + struct completion c_no_users; + struct mutex mutex; /* protects num_users and idr */ + + struct idr idr; + struct tee_shm_pool *pool; +}; + +int tee_shm_init(void); + +int isee_shm_get_fd(struct tee_shm *shm); + +bool isee_device_get(struct tee_device *teedev); +void isee_device_put(struct tee_device *teedev); + +extern void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, + struct sg_table *sg_table, + enum dma_data_direction direction); + +extern void dma_buf_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attach); + +extern void dma_buf_put(struct dma_buf *dmabuf); + +#if KERNEL_VERSION(4, 4, 1) <= LINUX_VERSION_CODE +extern struct dma_buf *dma_buf_export( + const struct dma_buf_export_info *exp_info); +#endif + +extern int dma_buf_fd(struct dma_buf *dmabuf, int flags); + +#endif /*TEE_PRIVATE_H*/ diff --git a/drivers/tee/teei/300/tee/tee_shm.c b/drivers/tee/teei/300/tee/tee_shm.c new file mode 100644 index 000000000000..2385b0d8d888 --- /dev/null +++ b/drivers/tee/teei/300/tee/tee_shm.c @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2016, Linaro Limited + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tee_private.h" + +/* extra references appended to shm object for registered shared memory */ +struct tee_shm_dmabuf_ref { + struct tee_shm shm; + struct dma_buf *dmabuf; + struct dma_buf_attachment *attach; + struct sg_table *sgt; +}; + +static void tee_shm_release(struct tee_shm *shm) +{ + struct tee_device *teedev = shm->teedev; + + mutex_lock(&teedev->mutex); + idr_remove(&teedev->idr, shm->id); + if (shm->ctx) + list_del(&shm->link); + mutex_unlock(&teedev->mutex); + + if (shm->flags & TEE_SHM_EXT_DMA_BUF) { + struct tee_shm_dmabuf_ref *ref; + + ref = container_of(shm, struct tee_shm_dmabuf_ref, shm); + dma_buf_unmap_attachment(ref->attach, ref->sgt, + DMA_BIDIRECTIONAL); + dma_buf_detach(shm->dmabuf, ref->attach); + dma_buf_put(ref->dmabuf); + } else { + struct tee_shm_pool_mgr *poolm; + + if (shm->flags & TEE_SHM_DMA_BUF) + poolm = &teedev->pool->dma_buf_mgr; + else + poolm = &teedev->pool->private_mgr; + + poolm->ops->free(poolm, shm); + } + + kfree(shm); + isee_device_put(teedev); +} + +static struct sg_table *tee_shm_op_map_dma_buf(struct dma_buf_attachment + *attach, enum dma_data_direction dir) +{ + return NULL; +} + +static void tee_shm_op_unmap_dma_buf(struct dma_buf_attachment *attach, + struct sg_table *table, + enum dma_data_direction dir) +{ +} + +static void tee_shm_op_release(struct dma_buf *dmabuf) +{ + struct tee_shm *shm = dmabuf->priv; + + tee_shm_release(shm); +} + +#if KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE +static void *tee_shm_op_kmap_atomic(struct dma_buf *dmabuf, unsigned long pgnum) +{ + return NULL; +} +#endif + +static void *tee_shm_op_kmap(struct dma_buf *dmabuf, unsigned long pgnum) +{ + return NULL; +} + +static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct tee_shm *shm = dmabuf->priv; + size_t size = vma->vm_end - vma->vm_start; + + if (size > shm->size) { + IMSG_INFO("Invalid memory mapping size.\n"); + return -EINVAL; + } + + return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT, + size, vma->vm_page_prot); +} + +static struct dma_buf_ops tee_shm_dma_buf_ops = { + .map_dma_buf = tee_shm_op_map_dma_buf, + .unmap_dma_buf = tee_shm_op_unmap_dma_buf, + .release = tee_shm_op_release, +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + .map = tee_shm_op_kmap, +#elif KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + .map_atomic = tee_shm_op_kmap_atomic, + .map = tee_shm_op_kmap, +#else + .kmap_atomic = tee_shm_op_kmap_atomic, + .kmap = tee_shm_op_kmap, +#endif + .mmap = tee_shm_op_mmap, +}; + +/** + * isee_shm_alloc() - Allocate shared memory + * @ctx: Context that allocates the shared memory + * @size: Requested size of shared memory + * @flags: Flags setting properties for the requested shared memory. + * + * Memory allocated as global shared memory is automatically freed when the + * TEE file pointer is closed. The @flags field uses the bits defined by + * TEE_SHM_* in . TEE_SHM_MAPPED must currently always be + * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and + * associated with a dma-buf handle, else driver private memory. + */ +struct tee_shm *isee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) +{ + struct tee_device *teedev = ctx->teedev; + struct tee_shm_pool_mgr *poolm = NULL; + struct tee_shm *shm; + void *ret; + int rc; + + if (!(flags & TEE_SHM_MAPPED)) { + IMSG_ERROR( + "only mapped allocations supported\n"); + return ERR_PTR(-EINVAL); + } + + if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) { + IMSG_ERROR("invalid shm flags 0x%x", flags); + return ERR_PTR(-EINVAL); + } + + if (!isee_device_get(teedev)) + return ERR_PTR(-EINVAL); + + if (!teedev->pool) { + /* teedev has been detached from driver */ + ret = ERR_PTR(-EINVAL); + goto err_dev_put; + } + + shm = kzalloc(sizeof(*shm), GFP_KERNEL); + if (!shm) { + ret = ERR_PTR(-ENOMEM); + goto err_dev_put; + } + + shm->flags = flags; + shm->teedev = teedev; + shm->ctx = ctx; + if (flags & TEE_SHM_DMA_BUF) + poolm = &teedev->pool->dma_buf_mgr; + else + poolm = &teedev->pool->private_mgr; + + rc = poolm->ops->alloc(poolm, shm, size); + if (rc) { + ret = ERR_PTR(rc); + goto err_kfree; + } + + mutex_lock(&teedev->mutex); + shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); + mutex_unlock(&teedev->mutex); + if (shm->id < 0) { + ret = ERR_PTR(shm->id); + goto err_pool_free; + } + + if (flags & TEE_SHM_DMA_BUF) { +#if KERNEL_VERSION(4, 4, 1) <= LINUX_VERSION_CODE + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + exp_info.ops = &tee_shm_dma_buf_ops; + exp_info.size = shm->size; + exp_info.flags = O_RDWR; + exp_info.priv = shm; + + shm->dmabuf = dma_buf_export(&exp_info); +#else + shm->dmabuf = dma_buf_export(shm, &tee_shm_dma_buf_ops, + shm->size, O_RDWR, NULL); +#endif + if (IS_ERR(shm->dmabuf)) { + ret = ERR_CAST(shm->dmabuf); + goto err_rem; + } + } + mutex_lock(&teedev->mutex); + list_add_tail(&shm->link, &ctx->list_shm); + mutex_unlock(&teedev->mutex); + + return shm; +err_rem: + mutex_lock(&teedev->mutex); + idr_remove(&teedev->idr, shm->id); + mutex_unlock(&teedev->mutex); +err_pool_free: + poolm->ops->free(poolm, shm); +err_kfree: + kfree(shm); +err_dev_put: + isee_device_put(teedev); + return ret; +} +EXPORT_SYMBOL_GPL(isee_shm_alloc); + +/** + * isee_shm_get_fd() - Increase reference count and return file descriptor + * @shm: Shared memory handle + * @returns user space file descriptor to shared memory + */ +int isee_shm_get_fd(struct tee_shm *shm) +{ + int fd; + + if (!(shm->flags & TEE_SHM_DMA_BUF)) + return -EINVAL; + + fd = dma_buf_fd(shm->dmabuf, O_CLOEXEC); + if (fd >= 0) + get_dma_buf(shm->dmabuf); + return fd; +} + +/** + * isee_shm_free() - Free shared memory + * @shm: Handle to shared memory to free + */ +void isee_shm_free(struct tee_shm *shm) +{ + /* + * dma_buf_put() decreases the dmabuf reference counter and will + * call tee_shm_release() when the last reference is gone. + * + * In the case of driver private memory we call tee_shm_release + * directly instead as it doesn't have a reference counter. + */ + if (shm->flags & TEE_SHM_DMA_BUF) + dma_buf_put(shm->dmabuf); + else + tee_shm_release(shm); +} +EXPORT_SYMBOL_GPL(isee_shm_free); + +/** + * isee_shm_va2pa() - Get physical address of a virtual address + * @shm: Shared memory handle + * @va: Virtual address to tranlsate + * @pa: Returned physical address + * @returns 0 on success and < 0 on failure + */ +int isee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa) +{ + if (!(shm->flags & TEE_SHM_MAPPED)) + return -EINVAL; + /* Check that we're in the range of the shm */ + if ((char *)va < (char *)shm->kaddr) + return -EINVAL; + if ((char *)va >= ((char *)shm->kaddr + shm->size)) + return -EINVAL; + + return isee_shm_get_pa( + shm, (unsigned long)va - (unsigned long)shm->kaddr, pa); +} +EXPORT_SYMBOL_GPL(isee_shm_va2pa); + +/** + * isee_shm_pa2va() - Get virtual address of a physical address + * @shm: Shared memory handle + * @pa: Physical address to tranlsate + * @va: Returned virtual address + * @returns 0 on success and < 0 on failure + */ +int isee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va) +{ + if (!(shm->flags & TEE_SHM_MAPPED)) + return -EINVAL; + /* Check that we're in the range of the shm */ + if (pa < shm->paddr) + return -EINVAL; + if (pa >= (shm->paddr + shm->size)) + return -EINVAL; + + if (va) { + void *v = isee_shm_get_va(shm, pa - shm->paddr); + + if (IS_ERR(v)) + return PTR_ERR(v); + *va = v; + } + return 0; +} +EXPORT_SYMBOL_GPL(isee_shm_pa2va); + +/** + * isee_shm_get_va() - Get virtual address of a shared memory plus an offset + * @shm: Shared memory handle + * @offs: Offset from start of this shared memory + * @returns virtual address of the shared memory + offs if offs is within + * the bounds of this shared memory, else an ERR_PTR + */ +void *isee_shm_get_va(struct tee_shm *shm, size_t offs) +{ + if (!(shm->flags & TEE_SHM_MAPPED)) + return ERR_PTR(-EINVAL); + if (offs >= shm->size) + return ERR_PTR(-EINVAL); + return (char *)shm->kaddr + offs; +} +EXPORT_SYMBOL_GPL(isee_shm_get_va); + +/** + * isee_shm_get_pa() - Get physical address of a shared memory plus an offset + * @shm: Shared memory handle + * @offs: Offset from start of this shared memory + * @pa: Physical address to return + * @returns 0 if offs is within the bounds of this shared memory, else an + * error code. + */ +int isee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa) +{ + if (offs >= shm->size) + return -EINVAL; + if (pa) + *pa = shm->paddr + offs; + return 0; +} +EXPORT_SYMBOL_GPL(isee_shm_get_pa); + +/** + * isee_shm_get_from_id() - Find shared memory object and increase reference + * count + * @ctx: Context owning the shared memory + * @id: Id of shared memory object + * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure + */ +struct tee_shm *isee_shm_get_from_id(struct tee_context *ctx, int id) +{ + struct tee_device *teedev; + struct tee_shm *shm; + + if (!ctx) + return ERR_PTR(-EINVAL); + + teedev = ctx->teedev; + mutex_lock(&teedev->mutex); + shm = idr_find(&teedev->idr, id); + if (!shm || shm->ctx != ctx) + shm = ERR_PTR(-EINVAL); + else if (shm->flags & TEE_SHM_DMA_BUF) + get_dma_buf(shm->dmabuf); + mutex_unlock(&teedev->mutex); + return shm; +} +EXPORT_SYMBOL_GPL(isee_shm_get_from_id); + +/** + * isee_shm_get_id() - Get id of a shared memory object + * @shm: Shared memory handle + * @returns id + */ +int isee_shm_get_id(struct tee_shm *shm) +{ + return shm->id; +} +EXPORT_SYMBOL_GPL(isee_shm_get_id); + +/** + * isee_shm_put() - Decrease reference count on a shared memory handle + * @shm: Shared memory handle + */ +void isee_shm_put(struct tee_shm *shm) +{ + if (shm->flags & TEE_SHM_DMA_BUF) + dma_buf_put(shm->dmabuf); +} +EXPORT_SYMBOL_GPL(isee_shm_put); diff --git a/drivers/tee/teei/300/tee/tee_shm_pool.c b/drivers/tee/teei/300/tee/tee_shm_pool.c new file mode 100644 index 000000000000..3c364d378176 --- /dev/null +++ b/drivers/tee/teei/300/tee/tee_shm_pool.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * + */ +#include +#include +#include +#include +#include +#include +#include "tee_private.h" + +static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm, + struct tee_shm *shm, size_t size) +{ + unsigned long va; + struct gen_pool *genpool = poolm->private_data; + size_t s = roundup(size, 1 << genpool->min_alloc_order); + + va = gen_pool_alloc(genpool, s); + if (!va) + return -ENOMEM; + + memset((void *)va, 0, s); + shm->kaddr = (void *)va; + shm->paddr = gen_pool_virt_to_phys(genpool, va); + shm->size = s; + return 0; +} + +static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm, + struct tee_shm *shm) +{ + gen_pool_free(poolm->private_data, (unsigned long)shm->kaddr, + shm->size); + shm->kaddr = NULL; +} + +static const struct tee_shm_pool_mgr_ops pool_ops_generic = { + .alloc = pool_op_gen_alloc, + .free = pool_op_gen_free, +}; + +static void pool_res_mem_destroy(struct tee_shm_pool *pool) +{ + gen_pool_destroy(pool->private_mgr.private_data); + gen_pool_destroy(pool->dma_buf_mgr.private_data); +} + +static int pool_res_mem_mgr_init(struct tee_shm_pool_mgr *mgr, + struct tee_shm_pool_mem_info *info, + int min_alloc_order) +{ + size_t page_mask = PAGE_SIZE - 1; + struct gen_pool *genpool = NULL; + int rc; + + /* + * Start and end must be page aligned + */ + if ((info->vaddr & page_mask) || (info->paddr & page_mask) || + (info->size & page_mask)) + return -EINVAL; + + genpool = gen_pool_create(min_alloc_order, -1); + if (!genpool) + return -ENOMEM; + + gen_pool_set_algo(genpool, gen_pool_best_fit, NULL); + rc = gen_pool_add_virt(genpool, info->vaddr, info->paddr, info->size, + -1); + if (rc) { + gen_pool_destroy(genpool); + return rc; + } + + mgr->private_data = genpool; + mgr->ops = &pool_ops_generic; + return 0; +} + +/** + * isee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved + * memory range + * @priv_info: Information for driver private shared memory pool + * @dmabuf_info: Information for dma-buf shared memory pool + * + * Start and end of pools will must be page aligned. + * + * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied + * in @dmabuf, others will use the range provided by @priv. + * + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. + */ +struct tee_shm_pool * +isee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, + struct tee_shm_pool_mem_info *dmabuf_info) +{ + struct tee_shm_pool *pool = NULL; + int ret; + + pool = kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) { + ret = -ENOMEM; + goto err; + } + + /* + * Create the pool for driver private shared memory + */ + ret = pool_res_mem_mgr_init(&pool->private_mgr, priv_info, + 3 /* 8 byte aligned */); + if (ret) + goto err; + + /* + * Create the pool for dma_buf shared memory + */ + ret = pool_res_mem_mgr_init(&pool->dma_buf_mgr, dmabuf_info, + PAGE_SHIFT); + if (ret) + goto err; + + pool->destroy = pool_res_mem_destroy; + return pool; +err: + if (ret == -ENOMEM) + IMSG_ERROR("%s: can't allocate memory for shm pool\n", + __func__); + + if (pool && pool->private_mgr.private_data) + gen_pool_destroy(pool->private_mgr.private_data); + + kfree(pool); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(isee_shm_pool_alloc_res_mem); + +/** + * isee_shm_pool_free() - Free a shared memory pool + * @pool: The shared memory pool to free + * + * There must be no remaining shared memory allocated from this pool when + * this function is called. + */ +void isee_shm_pool_free(struct tee_shm_pool *pool) +{ + pool->destroy(pool); + kfree(pool); +} +EXPORT_SYMBOL_GPL(isee_shm_pool_free); diff --git a/drivers/tee/teei/300/teei_fp/Makefile b/drivers/tee/teei/300/teei_fp/Makefile new file mode 100644 index 000000000000..d62f0c525ce1 --- /dev/null +++ b/drivers/tee/teei/300/teei_fp/Makefile @@ -0,0 +1,17 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +obj-$(CONFIG_MICROTRUST_TZ_DRIVER) += fp_func.o +ccflags-y += -D DEBUG_DO -fno-pic + +MTK_PLATFORM := $(shell echo $(CONFIG_MTK_PLATFORM) | grep -o "[0-9]\+") +ccflags-y += -D MTK_PLATFORM=$(MTK_PLATFORM) diff --git a/drivers/tee/teei/300/teei_fp/fp_func.c b/drivers/tee/teei/300/teei_fp/fp_func.c new file mode 100644 index 000000000000..63f2fd4c18d8 --- /dev/null +++ b/drivers/tee/teei/300/teei_fp/fp_func.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fp_func.h" +#include "../tz_driver/include/teei_fp.h" +#include "../tz_driver/include/teei_id.h" +#include "../tz_driver/include/nt_smc_call.h" +#include "../tz_driver/include/utdriver_macro.h" +#include "../tz_driver/include/teei_client_main.h" + +#define IMSG_TAG "[teei_fp]" +#include + +struct fp_dev { + struct cdev cdev; + struct semaphore sem; +}; + +static int fp_major = FP_MAJOR; +static dev_t devno; + +static int wait_teei_config_flag = 1; +static struct class *driver_class; +struct semaphore fp_api_lock; +struct fp_dev *fp_devp; +struct semaphore daulOS_rd_sem; +EXPORT_SYMBOL_GPL(daulOS_rd_sem); +struct semaphore daulOS_wr_sem; +EXPORT_SYMBOL_GPL(daulOS_wr_sem); +DECLARE_WAIT_QUEUE_HEAD(__fp_open_wq); +DECLARE_WAIT_QUEUE_HEAD(__wait_spi_wq); + + +int fp_open(struct inode *inode, struct file *filp) +{ + if (wait_teei_config_flag == 1) { + int ret; + + IMSG_INFO("[I]%s : Teei_config_flag = %lu\n", + __func__, teei_config_flag); + + ret = wait_event_timeout(__fp_open_wq, (teei_config_flag == 1), + msecs_to_jiffies(1000 * 10)); + if (ret == 0) { + IMSG_ERROR("[E] Tees's loading is not finished.\n"); + return -1; + } + if (ret < 0) { + IMSG_ERROR("[E] Wait_event_timeout error.\n"); + return -1; + } + + IMSG_INFO("[I]%s : Load tees finished, and wait for %u msecs\n", + __func__, (1000 * 10 - jiffies_to_msecs(ret))); + + ret = wait_event_timeout(__wait_spi_wq, (spi_ready_flag == 1), + msecs_to_jiffies(1000 * 10)); + if (ret == 0) { + IMSG_ERROR("[E] Spi's loading is not finished.\n"); + return -1; + } + if (ret < 0) { + IMSG_ERROR("[E] Wait_event_timeout error.\n"); + return -1; + } + + IMSG_INFO("[I]%s : Load spi finished, and wait for %u msecs\n", + __func__, (1000 * 10 - jiffies_to_msecs(ret))); + + wait_teei_config_flag = 0; + } + +#ifdef FP_DEBUG + IMSG_DEBUG("say hello from fp!\n"); +#endif + filp->private_data = fp_devp; + + return 0; +} + +int fp_release(struct inode *inode, struct file *filp) +{ + filp->private_data = NULL; + return 0; +} + +static long fp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + unsigned int args_len = 0; + unsigned char args[16] = {0}; + int ret = 0; + + down(&fp_api_lock); + switch (cmd) { + case CMD_FP_MEM_CLEAR: + IMSG_INFO("CMD FP MEM CLEAR.\n"); + break; + case CMD_FP_CMD: + if (copy_from_user((void *)args, (void *)arg, 16)) { + IMSG_ERROR("copy args from user failed.\n"); + up(&fp_api_lock); + return -EFAULT; + } + /* TODO compute args length */ + /* [11-15] is the length of data */ + args_len = *((unsigned int *)(args + 12)); + + if (args_len + 16 > MICROTRUST_FP_SIZE) { + IMSG_ERROR("args_len=%d is invalid!.\n", args_len); + up(&fp_api_lock); + return -EFAULT; + } + + ret = send_fp_command((void *)arg, args_len + 16); + if (ret) { + IMSG_ERROR("transfer data to ta failed.\n"); + up(&fp_api_lock); + return -EFAULT; + } + + break; + case CMD_FP_LOAD_TEE: +#ifdef FP_DEBUG + IMSG_DEBUG("case CMD_FP_LOAD_TEE\n"); +#endif + complete(&boot_decryto_lock); + break; + default: + up(&fp_api_lock); + return -EINVAL; + } + up(&fp_api_lock); + return 0; +} + +static ssize_t fp_read(struct file *filp, char __user *buf, + size_t size, loff_t *ppos) +{ + int ret = 0; + return ret; +} + +static ssize_t fp_write(struct file *filp, const char __user *buf, + size_t size, loff_t *ppos) +{ + return 0; +} + +static loff_t fp_llseek(struct file *filp, loff_t offset, int orig) +{ + return 0; +} +static const struct file_operations fp_fops = { + .owner = THIS_MODULE, + .llseek = fp_llseek, + .read = fp_read, + .write = fp_write, + .unlocked_ioctl = fp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = fp_ioctl, +#endif + .open = fp_open, + .release = fp_release, +}; + +static void fp_setup_cdev(struct fp_dev *dev, int index) +{ + int err = 0; + int devno = MKDEV(fp_major, index); + + cdev_init(&dev->cdev, &fp_fops); + dev->cdev.owner = fp_fops.owner; + err = cdev_add(&dev->cdev, devno, 1); + if (err) + IMSG_ERROR("Error %d adding fp %d.\n", err, index); +} + +int fp_init(void) +{ + int result = 0; + struct device *class_dev = NULL; + + devno = MKDEV(fp_major, 0); + result = alloc_chrdev_region(&devno, 0, 1, DEV_NAME); + fp_major = MAJOR(devno); + TZ_SEMA_INIT_1(&(fp_api_lock)); + if (result < 0) + return result; + + driver_class = NULL; + driver_class = class_create(THIS_MODULE, DEV_NAME); + if (IS_ERR(driver_class)) { + result = -ENOMEM; + IMSG_ERROR("class_create failed %d.\n", result); + goto unregister_chrdev_region; + } + + class_dev = device_create(driver_class, NULL, devno, NULL, DEV_NAME); + if (!class_dev) { + result = -ENOMEM; + IMSG_ERROR("class_device_create failed %d.\n", result); + goto class_destroy; + } + fp_devp = NULL; + fp_devp = vmalloc(sizeof(struct fp_dev)); + if (fp_devp == NULL) { + result = -ENOMEM; + goto class_device_destroy; + } + memset(fp_devp, 0, sizeof(struct fp_dev)); + fp_setup_cdev(fp_devp, 0); + TZ_SEMA_INIT_1(&fp_devp->sem); + TZ_SEMA_INIT_0(&daulOS_rd_sem); + TZ_SEMA_INIT_0(&daulOS_wr_sem); + + IMSG_DEBUG("[%s][%d]create the teei_fp device node successfully!\n", + __func__, __LINE__); + goto return_fn; + +class_device_destroy: + device_destroy(driver_class, devno); +class_destroy: + class_destroy(driver_class); +unregister_chrdev_region: + unregister_chrdev_region(devno, 1); +return_fn: + return result; +} + +void fp_exit(void) +{ + device_destroy(driver_class, devno); + class_destroy(driver_class); + cdev_del(&fp_devp->cdev); + vfree(fp_devp); + unregister_chrdev_region(MKDEV(fp_major, 0), 1); +} + +MODULE_AUTHOR("Microtrust"); +MODULE_LICENSE("Dual BSD/GPL"); + +module_param(fp_major, int, 0444); + +module_init(fp_init); +module_exit(fp_exit); diff --git a/drivers/tee/teei/300/teei_fp/fp_func.h b/drivers/tee/teei/300/teei_fp/fp_func.h new file mode 100644 index 000000000000..3ebd90e7057f --- /dev/null +++ b/drivers/tee/teei/300/teei_fp/fp_func.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_FUNC_H +#define TEEI_FUNC_H + +#include +#define MICROTRUST_FP_SIZE 0x80000 +#define FP_MAJOR 254 +#define DEV_NAME "teei_fp" + +extern struct semaphore fp_api_lock; +extern wait_queue_head_t __fp_open_wq; +extern wait_queue_head_t __wait_spi_wq; +extern unsigned long teei_config_flag; + +int send_fp_command(void *buffer, unsigned long size); +#endif /* end of TEEI_FUNC_H */ diff --git a/drivers/tee/teei/300/teei_fp/teei_fp.h b/drivers/tee/teei/300/teei_fp/teei_fp.h new file mode 100644 index 000000000000..9e09ba35f576 --- /dev/null +++ b/drivers/tee/teei/300/teei_fp/teei_fp.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_FP_H +#define TEEI_FP_H + +#define fp_buffer_size 2048 + +#define ARGS_BLOCK_SIZE 1024 + +int send_fp_command(unsigned long share_memory_size); +#endif diff --git a/drivers/tee/teei/300/tests/Makefile b/drivers/tee/teei/300/tests/Makefile new file mode 100644 index 000000000000..f3b961333d57 --- /dev/null +++ b/drivers/tee/teei/300/tests/Makefile @@ -0,0 +1,19 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +ccflags-y += -I$(src) +ccflags-y += -Wno-error + +obj-y += xtest_isee_3000.o +obj-y += xtest_isee_1000.o +obj-y += xtest_main.o +obj-y += main.o diff --git a/drivers/tee/teei/300/tests/main.c b/drivers/tee/teei/300/tests/main.c new file mode 100644 index 000000000000..b50cb6c8ba58 --- /dev/null +++ b/drivers/tee/teei/300/tests/main.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#define IMSG_TAG "[tz_test]" +#include +#include + +static int tz_test_open(struct inode *inode, struct file *file) +{ + if (!is_teei_ready()) + return -EBUSY; + return 0; +} + +static int tz_test_release(struct inode *inode, struct file *file) +{ + if (!is_teei_ready()) + return -EBUSY; + return 0; +} + +static long tz_test_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int err = 0; + struct tzdrv_test_data param; + + IMSG_TRACE("invoke command '%d' from '%s'\n", + _IOC_NR(cmd), current->comm); + + if (!is_teei_ready()) + return -EBUSY; + if (_IOC_TYPE(cmd) != TZDRV_IOC_MAGIC) + return -EFAULT; + if (_IOC_NR(cmd) > TZDRV_IOC_MAXNR) + return -EFAULT; + + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, + (void __user *)arg, _IOC_SIZE(cmd)); + if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, + (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EPERM; + + if (IFASSIGN(err, copy_from_user(¶m, (void *)arg, sizeof(param)))) + return -EINVAL; + + switch (cmd) { + case TZDRV_CMD_KERNEL_CA_TEST: + err = kernel_ca_test(¶m); + break; + case TZDRV_CMD_SECURE_DRV_TEST: + err = secure_drv_test(¶m); + break; + default: + return -ENODEV; + } + + if (copy_to_user((void *)arg, ¶m, sizeof(param))) + IMSG_ERROR("copy data to user failed!\n"); + + return err; +} + +static const struct file_operations tz_test_fops = { + .owner = THIS_MODULE, + .open = tz_test_open, + .release = tz_test_release, + .unlocked_ioctl = tz_test_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tz_test_ioctl, +#endif + .write = NULL, + .read = NULL, +}; + +static int __init tz_test_init(void) +{ +#define TZ_PERMISSION 0666 + + /* S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH */ + proc_create("tz_test0", TZ_PERMISSION, NULL, &tz_test_fops); + return 0; +} +late_initcall(tz_test_init); diff --git a/drivers/tee/teei/300/tests/main.h b/drivers/tee/teei/300/tests/main.h new file mode 100644 index 000000000000..a6411eaab1ac --- /dev/null +++ b/drivers/tee/teei/300/tests/main.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TZ_TEST_MAIN_H +#define TZ_TEST_MAIN_H + +#define TZ_TEST_NAME "tz_test" + +struct tzdrv_test_data { + unsigned int params[32]; + unsigned char error_info[128]; + int tee_error_code; + int tee_spend_time_ms; +}; + +#define TZDRV_IOC_MAGIC 'T' +#define TZDRV_CMD_KERNEL_CA_TEST _IOWR(TZDRV_IOC_MAGIC, 2,\ + struct tzdrv_test_data) +#define TZDRV_CMD_SECURE_DRV_TEST _IOWR(TZDRV_IOC_MAGIC, 3,\ + struct tzdrv_test_data) + +#define TZDRV_IOC_MAXNR (10) + +extern int kernel_ca_test(struct tzdrv_test_data *param); +extern int secure_drv_test(struct tzdrv_test_data *param); +#define IFASSIGN(a, b) (a = b) + +#endif /* end of TZ_TEST_MAIN_H */ diff --git a/drivers/tee/teei/300/tests/ta_core_api.h b/drivers/tee/teei/300/tests/ta_core_api.h new file mode 100644 index 000000000000..8b8ccbac8d38 --- /dev/null +++ b/drivers/tee/teei/300/tests/ta_core_api.h @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#ifndef TA_CORE_API_H +#define TA_CORE_API_H + +#include + +/* errors defined and used by TA/DRV test cases only */ +#include "teei_internal_types.h" +#include "teei_ta_drv_types.h" + +#define DRM_01_UUID \ + { \ + 0x08110000, 0x0000, 0x0000, \ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } \ + } + +/* TA Commands */ +#define TA_CORE_API_CMD_PRINT 0x1 +#define TA_CORE_API_CMD_RET_VALUE 0x2 +#define TA_CORE_API_CMD_READ_CNTVCT 0x3 +#define TA_CORE_API_CMD_PARAM_TYPE_VALUE_INPUT 0x10 +#define TA_CORE_API_CMD_PARAM_TYPE_VALUE_OUTPUT 0x11 +#define TA_CORE_API_CMD_PARAM_TYPE_VALUE_INOUT 0x12 +#define TA_CORE_API_CMD_PARAM_TYPE_VALUE_MIX 0x13 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_INPUT 0x20 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_OUTPUT 0x21 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_INOUT 0x22 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_MIX 0x23 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_INPUT 0x30 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_OUTPUT 0x31 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_INOUT 0x32 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_MIX 0x33 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_INPUT 0x40 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_OUTPUT 0x41 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_INOUT 0x42 +#define TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_MIX 0x43 +#define TA_CORE_API_CMD_RPMB_WRITE 0x101 +#define TA_CORE_API_CMD_RPMB_READ 0x102 +#define TA_CORE_API_CMD_Get_System_Time 0x103 +#define TA_CORE_API_CMD_INVOKE_COMMAND_ENTRY_POINT 0x500 +#define TA_CORE_API_CMD_ALLOCATE_TRANSIENT_OBJECT 0x501 +#define TA_CORE_API_CMD_POPULATE_TRANSIENT_OBJECT 0x503 +#define TA_CORE_API_CMD_ALLOCATE_OPERATION 0x504 +#define TA_CORE_API_CMD_SET_OPERATION_KEY 0x506 +#define TA_CORE_API_CMD_GENERATE_RANDOM 0x507 +#define TA_CORE_API_CMD_CHECK_MEMORY_ACCESS_RIGHTS 0x508 +#define TA_CORE_API_CMD_MALLOC 0x509 +#define TA_CORE_API_CMD_REALLOC 0x510 +#define TA_CORE_API_CMD_MEM_MOVE 0x512 +#define TA_CORE_API_CMD_MEM_COMPARE 0x513 +#define TA_CORE_API_CMD_MEM_FILL 0x514 +#define TA_CORE_API_CMD_GET_PROPERTY_AS_UUID 0x515 +#define TA_CORE_API_CMD_LOG_VPRINTF 0x516 +#define TA_CORE_API_CMD_LOG_PRINTF 0x517 +#define TA_CORE_API_CMD_DBG_PRINTF 0x518 +#define TA_CORE_API_CMD_DBG_VPRINTF 0x519 +#define TA_CRYPTO_API_CMD_AES_ECB 0x1300 +#define TA_CRYPTO_API_CMD_AES_CBC 0x1301 +#define TA_CRYPTO_API_CMD_AES_CTR 0x1302 +#define TA_CRYPTO_API_CMD_SHA1 0x1303 +#define TA_CRYPTO_API_CMD_SHA256 0x1304 +#define TA_CRYPTO_API_CMD_HMAC_SHA256 0x1305 +#define TA_CRYPTO_API_CMD_HMAC_SHA1 0x1306 +#define TA_CRYPTO_API_CMD_RSA_PKCS1_PSS_MGF1_SHA1 0x1307 +#define TA_CRYPTO_API_CMD_RSA_NOPAD 0x1308 +#define TA_CRYPTO_API_CMD_ASYMMETRIC_ENCRYPT 0x1400 +#define TA_CRYPTO_API_CMD_ASYMMETRIC_DECRYPT 0x1401 +#define TA_CRYPTO_API_CMD_ASYMMETRIC_SIGN_DIGEST 0x1402 +#define TA_CRYPTO_API_CMD_ASYMMETRIC_VERIFY_DIGEST 0x1403 +#define TA_CRYPTO_API_CMD_DIGEST_UPDATE 0x1404 +#define TA_CRYPTO_API_CMD_DIGEST_DO_FINAL 0x1405 +#define TA_CRYPTO_API_CMD_CIPHER_INIT 0x1406 +#define TA_CRYPTO_API_CMD_CIPHER_UPDATE 0x1407 +#define TA_CRYPTO_API_CMD_CIPHER_DO_FINAL 0x1408 +#define TA_CRYPTO_API_CMD_MAC_INIT 0x1409 +#define TA_CRYPTO_API_CMD_MAC_UPDATE 0x1410 +#define TA_CRYPTO_API_CMD_MAC_COMPUTE_FINAL 0x1411 +#define TA_CRYPTO_API_CMD_MAC_COMPARE_FINAL 0x1412 +#define TA_CORE_API_UNSUPPORTED_CMD 0xFFFFFFF1 + +/* Param Type Test Values */ +#define TA_CORE_API_PARAM_TYPE_Test_Pattern0 0x12345678 +#define TA_CORE_API_PARAM_TYPE_Test_Pattern1 0x90ABCEDF +#define TA_CORE_API_PARAM_TYPE_Test_Pattern2 0x87654321 +#define TA_CORE_API_PARAM_TYPE_Test_Pattern3 0xFDECBA09 +#define TA_CORE_API_PARAM_TYPE_Test_Pattern4 0x55667788 +#define TA_CORE_API_PARAM_TYPE_Test_Pattern5 0x33441122 +#define TA_CORE_API_PARAM_TYPE_Test_Pattern6 0xAAAACCCC +#define TA_CORE_API_PARAM_TYPE_Test_Pattern7 0xBBBBDDDD +#define TA_CORE_API_PARAM_TYPE_Test_Pattern8 0x11111111 +#define TA_CORE_API_PARAM_TYPE_Test_Pattern9 0x22222222 +#define TA_CORE_API_PARAM_TYPE_Test_PatternA 0x33333333 +#define TA_CORE_API_PARAM_TYPE_Test_PatternB 0x44444444 +#define TA_CORE_API_PARAM_TYPE_Test_PatternC 0x55555555 +#define TA_CORE_API_PARAM_TYPE_Test_PatternD 0x66666666 +#define TA_CORE_API_PARAM_TYPE_Test_PatternE 0x77777777 +#define TA_CORE_API_PARAM_TYPE_Test_PatternF 0xFFFFFFFF +#define TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO 0x00000000 + +/* Error Code */ +#define TA_CORE_API_SPECIFIC_RET_VALUE 0x23457896 +#define TA_CORE_API_PARAM_TYPE_TEST_SUCCESS 0xABCD5555 +#define TA_CORE_API_PARAM_TYPE_TEST_FAIL 0xDEAD9999 +#define TA_CORE_API_PARAM_TYPE_BUFFER0_TEST_FAIL 0xDEAD0000 +#define TA_CORE_API_PARAM_TYPE_BUFFER1_TEST_FAIL 0xDEAD1111 +#define TA_CORE_API_PARAM_TYPE_BUFFER2_TEST_FAIL 0xDEAD2222 +#define TA_CORE_API_PARAM_TYPE_BUFFER3_TEST_FAIL 0xDEAD3333 +#define TA_CORE_API_PARAM_TYPE_PATTERN_MATCH 0x1 +#define TA_CORE_API_PARAM_TYPE_PATTERN_NOT_MATCH 0x0 + +extern unsigned int xtest_teec_open_session(struct TEEC_Context *context, + struct TEEC_Session *session, + const struct TEEC_UUID *uuid, + struct TEEC_Operation *op, + uint32_t *ret_orig); +extern const char *ADBG_GetFileBase(const char *const FileName_p); +extern bool Do_ADBG_Expect(const char *const FileName_p, + const int LineNumber, + const int Expected, + const int Got); +#define ADBG_EXPECT_ENUM(Expected, Got) \ + Do_ADBG_Expect(__FILE__, __LINE__, Expected, Got) +#define ADBG_EXPECT_TEEC_SUCCESS(got) ADBG_EXPECT_ENUM(TEEC_SUCCESS, got) +#define ADBG_EXPECT_TEEC_RESULT(exp, got) ADBG_EXPECT_ENUM(exp, got) + +extern int compare_array_with_pattern(unsigned char *buffer, + unsigned int pattern, + unsigned int size_in_byte); +#define ARRAY_MATCH_PATTERN(buffer, pattern, size_in_byte) \ + compare_array_with_pattern(buffer, pattern, size_in_byte) + +#define malloc(size) kmalloc(size, GFP_KERNEL | GFP_ATOMIC) +#define free kfree +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) +#define tz_malloc(size) __get_free_pages(GFP_KERNEL, \ + get_order(ROUND_UP(size, SZ_4K))) +#define tz_free(addr, size) free_pages((unsigned long)addr, \ + get_order(ROUND_UP(size, SZ_4K))) +extern int case_res; + +#define UNUSED(x) (void)(x) + +#endif diff --git a/drivers/tee/teei/300/tests/tee_api_defines.h b/drivers/tee/teei/300/tests/tee_api_defines.h new file mode 100644 index 000000000000..20c4400aec53 --- /dev/null +++ b/drivers/tee/teei/300/tests/tee_api_defines.h @@ -0,0 +1,450 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#ifndef TEE_API_DEFINES_H +#define TEE_API_DEFINES_H + +#define TEE_INT_CORE_API_SPEC_VERSION 0x0000000A + +#define TEE_HANDLE_NULL 0 + +#define TEE_TIMEOUT_INFINITE 0xFFFFFFFF + +/* API Error Codes */ +#define TEE_SUCCESS 0x00000000 +#define TEE_ERROR_CORRUPT_OBJECT 0xF0100001 +#define TEE_ERROR_CORRUPT_OBJECT_2 0xF0100002 +#define TEE_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003 +#define TEE_ERROR_STORAGE_NOT_AVAILABLE_2 0xF0100004 +#define TEE_ERROR_GENERIC 0xFFFF0000 +#define TEE_ERROR_ACCESS_DENIED 0xFFFF0001 +#define TEE_ERROR_CANCEL 0xFFFF0002 +#define TEE_ERROR_ACCESS_CONFLICT 0xFFFF0003 +#define TEE_ERROR_EXCESS_DATA 0xFFFF0004 +#define TEE_ERROR_BAD_FORMAT 0xFFFF0005 +#define TEE_ERROR_BAD_PARAMETERS 0xFFFF0006 +#define TEE_ERROR_BAD_STATE 0xFFFF0007 +#define TEE_ERROR_ITEM_NOT_FOUND 0xFFFF0008 +#define TEE_ERROR_NOT_IMPLEMENTED 0xFFFF0009 +#define TEE_ERROR_NOT_SUPPORTED 0xFFFF000A +#define TEE_ERROR_NO_DATA 0xFFFF000B +#define TEE_ERROR_OUT_OF_MEMORY 0xFFFF000C +#define TEE_ERROR_BUSY 0xFFFF000D +#define TEE_ERROR_COMMUNICATION 0xFFFF000E +#define TEE_ERROR_SECURITY 0xFFFF000F +#define TEE_ERROR_SHORT_BUFFER 0xFFFF0010 +/*#define TEE_ERROR_EXTERNAL_CANCEL 0xFFFF0011*/ +/*#define TEE_ERROR_OVERFLOW 0xFFFF300F*/ +#define TEE_ERROR_TARGET_DEAD 0xFFFF3024 +/*#define TEE_ERROR_STORAGE_NO_SPACE 0xFFFF3041*/ +/*#define TEE_ERROR_MAC_INVALID 0xFFFF3071*/ +/*#define TEE_ERROR_SIGNATURE_INVALID 0xFFFF3072*/ +/*#define TEE_ERROR_TIME_NOT_SET 0xFFFF5000*/ +/*#define TEE_ERROR_TIME_NEEDS_RESET 0xFFFF5001*/ + +/* Parameter Type Constants */ +#define TEE_PARAM_TYPE_NONE 0 +#define TEE_PARAM_TYPE_VALUE_INPUT 1 +#define TEE_PARAM_TYPE_VALUE_OUTPUT 2 +#define TEE_PARAM_TYPE_VALUE_INOUT 3 +#define TEE_PARAM_TYPE_MEMREF_INPUT 5 +#define TEE_PARAM_TYPE_MEMREF_OUTPUT 6 +#define TEE_PARAM_TYPE_MEMREF_INOUT 7 + +/* Login Type Constants */ +#define TEE_LOGIN_PUBLIC 0x00000000 +#define TEE_LOGIN_USER 0x00000001 +#define TEE_LOGIN_GROUP 0x00000002 +#define TEE_LOGIN_APPLICATION 0x00000004 +#define TEE_LOGIN_APPLICATION_USER 0x00000005 +#define TEE_LOGIN_APPLICATION_GROUP 0x00000006 +#define TEE_LOGIN_TRUSTED_APP 0xF0000000 + +/* Origin Code Constants */ +#define TEE_ORIGIN_API 0x00000001 +#define TEE_ORIGIN_COMMS 0x00000002 +#define TEE_ORIGIN_TEE 0x00000003 +#define TEE_ORIGIN_TRUSTED_APP 0x00000004 + +/* Property Sets pseudo handles */ +#define TEE_PROPSET_TEE_IMPLEMENTATION ((TEE_PropSetHandle)0xFFFFFFFD) +#define TEE_PROPSET_CURRENT_CLIENT ((TEE_PropSetHandle)0xFFFFFFFE) +#define TEE_PROPSET_CURRENT_TA ((TEE_PropSetHandle)0xFFFFFFFF) + +/* Memory Access Rights Constants */ +#define TEE_MEMORY_ACCESS_READ 0x00000001 +#define TEE_MEMORY_ACCESS_WRITE 0x00000002 +#define TEE_MEMORY_ACCESS_ANY_OWNER 0x00000004 + +/* Memory Management Constant */ +#define TEE_MALLOC_FILL_ZERO 0x00000000 + +/* Other constants */ +#define TEE_STORAGE_PRIVATE 0x00000001 + +#define TEE_DATA_FLAG_ACCESS_READ 0x00000001 +#define TEE_DATA_FLAG_ACCESS_WRITE 0x00000002 +#define TEE_DATA_FLAG_ACCESS_WRITE_META 0x00000004 +#define TEE_DATA_FLAG_SHARE_READ 0x00000010 +#define TEE_DATA_FLAG_SHARE_WRITE 0x00000020 +#define TEE_DATA_FLAG_OVERWRITE 0x00000400 +#define TEE_DATA_MAX_POSITION 0xFFFFFFFF +#define TEE_OBJECT_ID_MAX_LEN 64 +#define TEE_USAGE_EXTRACTABLE 0x00000001 +#define TEE_USAGE_ENCRYPT 0x00000002 +#define TEE_USAGE_DECRYPT 0x00000004 +#define TEE_USAGE_MAC 0x00000008 +#define TEE_USAGE_SIGN 0x00000010 +#define TEE_USAGE_VERIFY 0x00000020 +#define TEE_USAGE_DERIVE 0x00000040 +#define TEE_HANDLE_FLAG_PERSISTENT 0x00010000 +#define TEE_HANDLE_FLAG_INITIALIZED 0x00020000 +#define TEE_HANDLE_FLAG_KEY_SET 0x00040000 +#define TEE_HANDLE_FLAG_EXPECT_TWO_KEYS 0x00080000 +#define TEE_OPERATION_CIPHER 1 +#define TEE_OPERATION_MAC 3 +#define TEE_OPERATION_AE 4 +#define TEE_OPERATION_DIGEST 5 +#define TEE_OPERATION_ASYMMETRIC_CIPHER 6 +#define TEE_OPERATION_ASYMMETRIC_SIGNATURE 7 +#define TEE_OPERATION_KEY_DERIVATION 8 +#define TEE_OPERATION_STATE_INITIAL 0x00000000 +#define TEE_OPERATION_STATE_ACTIVE 0x00000001 + +/* Algorithm Identifiers */ +#define TEE_ALG_AES_ECB_NOPAD 0x10000010 +#define TEE_ALG_AES_CBC_NOPAD 0x10000110 +#define TEE_ALG_AES_CTR 0x10000210 +#define TEE_ALG_AES_CTS 0x10000310 +#define TEE_ALG_AES_XTS 0x10000410 +#define TEE_ALG_AES_CBC_MAC_NOPAD 0x30000110 +#define TEE_ALG_AES_CBC_MAC_PKCS5 0x30000510 +#define TEE_ALG_AES_CMAC 0x30000610 +#define TEE_ALG_AES_CCM 0x40000710 +#define TEE_ALG_AES_GCM 0x40000810 +#define TEE_ALG_DES_ECB_NOPAD 0x10000011 +#define TEE_ALG_DES_CBC_NOPAD 0x10000111 +#define TEE_ALG_DES_CBC_MAC_NOPAD 0x30000111 +#define TEE_ALG_DES_CBC_MAC_PKCS5 0x30000511 +#define TEE_ALG_DES3_ECB_NOPAD 0x10000013 +#define TEE_ALG_DES3_CBC_NOPAD 0x10000113 +#define TEE_ALG_DES3_CBC_MAC_NOPAD 0x30000113 +#define TEE_ALG_DES3_CBC_MAC_PKCS5 0x30000513 +#define TEE_ALG_RSASSA_PKCS1_V1_5_MD5 0x70001830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 0x70002830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 0x70003830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 0x70004830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 0x70005830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 0x70006830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1 0x7000F830 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 0x70212930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 0x70313930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 0x70414930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 0x70515930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 0x70616930 +#define TEE_ALG_RSAES_PKCS1_V1_5 0x60000130 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1 0x60210230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224 0x60310230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256 0x60410230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384 0x60510230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512 0x60610230 +#define TEE_ALG_RSA_NOPAD 0x60000030 +#define TEE_ALG_DSA_SHA1 0x70002131 +#define TEE_ALG_DSA_SHA224 0x70003131 +#define TEE_ALG_DSA_SHA256 0x70004131 +#define TEE_ALG_DH_DERIVE_SHARED_SECRET 0x80000032 +#define TEE_ALG_MD5 0x50000001 +#define TEE_ALG_SHA1 0x50000002 +#define TEE_ALG_SHA224 0x50000003 +#define TEE_ALG_SHA256 0x50000004 +#define TEE_ALG_SHA384 0x50000005 +#define TEE_ALG_SHA512 0x50000006 +#define TEE_ALG_MD5SHA1 0x5000000F +#define TEE_ALG_HMAC_MD5 0x30000001 +#define TEE_ALG_HMAC_SHA1 0x30000002 +#define TEE_ALG_HMAC_SHA224 0x30000003 +#define TEE_ALG_HMAC_SHA256 0x30000004 +#define TEE_ALG_HMAC_SHA384 0x30000005 +#define TEE_ALG_HMAC_SHA512 0x30000006 +/* + * Fix GP Internal Core API v1.1 + * "Table 6-12: Structure of Algorithm Identifier" + * indicates ECDSA have the algorithm "0x41" and ECDH "0x42" + * whereas + * "Table 6-11: List of Algorithm Identifiers" defines + * TEE_ALG_ECDSA_P192 as 0x70001042 + * + * We chose to define TEE_ALG_ECDSA_P192 as 0x70001041 (conform to table 6-12) + */ +#define TEE_ALG_ECDSA_P192 0x70001041 +#define TEE_ALG_ECDSA_P224 0x70002041 +#define TEE_ALG_ECDSA_P256 0x70003041 +#define TEE_ALG_ECDSA_P384 0x70004041 +#define TEE_ALG_ECDSA_P521 0x70005041 +#define TEE_ALG_ECDH_P192 0x80001042 +#define TEE_ALG_ECDH_P224 0x80002042 +#define TEE_ALG_ECDH_P256 0x80003042 +#define TEE_ALG_ECDH_P384 0x80004042 +#define TEE_ALG_ECDH_P521 0x80005042 + +/* Object Types */ + +#define TEE_TYPE_AES 0xA0000010 +#define TEE_TYPE_DES 0xA0000011 +#define TEE_TYPE_DES3 0xA0000013 +#define TEE_TYPE_HMAC_MD5 0xA0000001 +#define TEE_TYPE_HMAC_SHA1 0xA0000002 +#define TEE_TYPE_HMAC_SHA224 0xA0000003 +#define TEE_TYPE_HMAC_SHA256 0xA0000004 +#define TEE_TYPE_HMAC_SHA384 0xA0000005 +#define TEE_TYPE_HMAC_SHA512 0xA0000006 +#define TEE_TYPE_RSA_PUBLIC_KEY 0xA0000030 +#define TEE_TYPE_RSA_KEYPAIR 0xA1000030 +#define TEE_TYPE_DSA_PUBLIC_KEY 0xA0000031 +#define TEE_TYPE_DSA_KEYPAIR 0xA1000031 +#define TEE_TYPE_DH_KEYPAIR 0xA1000032 +#define TEE_TYPE_ECDSA_PUBLIC_KEY 0xA0000041 +#define TEE_TYPE_ECDSA_KEYPAIR 0xA1000041 +#define TEE_TYPE_ECDH_PUBLIC_KEY 0xA0000042 +#define TEE_TYPE_ECDH_KEYPAIR 0xA1000042 +#define TEE_TYPE_GENERIC_SECRET 0xA0000000 +#define TEE_TYPE_CORRUPTED_OBJECT 0xA00000BE +#define TEE_TYPE_DATA 0xA00000BF + +/* List of Object or Operation Attributes */ + +#define TEE_ATTR_SECRET_VALUE 0xC0000000 +#define TEE_ATTR_RSA_MODULUS 0xD0000130 +#define TEE_ATTR_RSA_PUBLIC_EXPONENT 0xD0000230 +#define TEE_ATTR_RSA_PRIVATE_EXPONENT 0xC0000330 +#define TEE_ATTR_RSA_PRIME1 0xC0000430 +#define TEE_ATTR_RSA_PRIME2 0xC0000530 +#define TEE_ATTR_RSA_EXPONENT1 0xC0000630 +#define TEE_ATTR_RSA_EXPONENT2 0xC0000730 +#define TEE_ATTR_RSA_COEFFICIENT 0xC0000830 +#define TEE_ATTR_DSA_PRIME 0xD0001031 +#define TEE_ATTR_DSA_SUBPRIME 0xD0001131 +#define TEE_ATTR_DSA_BASE 0xD0001231 +#define TEE_ATTR_DSA_PUBLIC_VALUE 0xD0000131 +#define TEE_ATTR_DSA_PRIVATE_VALUE 0xC0000231 +#define TEE_ATTR_DH_PRIME 0xD0001032 +#define TEE_ATTR_DH_SUBPRIME 0xD0001132 +#define TEE_ATTR_DH_BASE 0xD0001232 +#define TEE_ATTR_DH_X_BITS 0xF0001332 +#define TEE_ATTR_DH_PUBLIC_VALUE 0xD0000132 +#define TEE_ATTR_DH_PRIVATE_VALUE 0xC0000232 +#define TEE_ATTR_RSA_OAEP_LABEL 0xD0000930 +#define TEE_ATTR_RSA_PSS_SALT_LENGTH 0xF0000A30 +#define TEE_ATTR_ECC_PUBLIC_VALUE_X 0xD0000141 +#define TEE_ATTR_ECC_PUBLIC_VALUE_Y 0xD0000241 +#define TEE_ATTR_ECC_PRIVATE_VALUE 0xC0000341 +#define TEE_ATTR_ECC_CURVE 0xF0000441 + +#define TEE_ATTR_BIT_PROTECTED (1 << 28) +#define TEE_ATTR_BIT_VALUE (1 << 29) + +/* List of Supported ECC Curves */ +#define TEE_ECC_CURVE_NIST_P192 0x00000001 +#define TEE_ECC_CURVE_NIST_P224 0x00000002 +#define TEE_ECC_CURVE_NIST_P256 0x00000003 +#define TEE_ECC_CURVE_NIST_P384 0x00000004 +#define TEE_ECC_CURVE_NIST_P521 0x00000005 + +/* Panicked Functions Identification */ +/* TA Interface */ +#define TEE_PANIC_ID_TA_CLOSESESSIONENTRYPOINT 0x00000101 +#define TEE_PANIC_ID_TA_CREATEENTRYPOINT 0x00000102 +#define TEE_PANIC_ID_TA_DESTROYENTRYPOINT 0x00000103 +#define TEE_PANIC_ID_TA_INVOKECOMMANDENTRYPOINT 0x00000104 +#define TEE_PANIC_ID_TA_OPENSESSIONENTRYPOINT 0x00000105 +/* Property Access */ +#define TEE_PANIC_ID_TEE_ALLOCATEPROPERTYENUMERATOR 0x00000201 +#define TEE_PANIC_ID_TEE_FREEPROPERTYENUMERATOR 0x00000202 +#define TEE_PANIC_ID_TEE_GETNEXTPROPERTY 0x00000203 +#define TEE_PANIC_ID_TEE_GETPROPERTYASBINARYBLOCK 0x00000204 +#define TEE_PANIC_ID_TEE_GETPROPERTYASBOOL 0x00000205 +#define TEE_PANIC_ID_TEE_GETPROPERTYASIDENTITY 0x00000206 +#define TEE_PANIC_ID_TEE_GETPROPERTYASSTRING 0x00000207 +#define TEE_PANIC_ID_TEE_GETPROPERTYASU32 0x00000208 +#define TEE_PANIC_ID_TEE_GETPROPERTYASUUID 0x00000209 +#define TEE_PANIC_ID_TEE_GETPROPERTYNAME 0x0000020A +#define TEE_PANIC_ID_TEE_RESETPROPERTYENUMERATOR 0x0000020B +#define TEE_PANIC_ID_TEE_STARTPROPERTYENUMERATOR 0x0000020C +/* Panic Function */ +#define TEE_PANIC_ID_TEE_PANIC 0x00000301 +/* Internal Client API */ +#define TEE_PANIC_ID_TEE_CLOSETASESSION 0x00000401 +#define TEE_PANIC_ID_TEE_INVOKETACOMMAND 0x00000402 +#define TEE_PANIC_ID_TEE_OPENTASESSION 0x00000403 +/* Cancellation */ +#define TEE_PANIC_ID_TEE_GETCANCELLATIONFLAG 0x00000501 +#define TEE_PANIC_ID_TEE_MASKCANCELLATION 0x00000502 +#define TEE_PANIC_ID_TEE_UNMASKCANCELLATION 0x00000503 +/* Memory Management */ +#define TEE_PANIC_ID_TEE_CHECKMEMORYACCESSRIGHTS 0x00000601 +#define TEE_PANIC_ID_TEE_FREE 0x00000602 +#define TEE_PANIC_ID_TEE_GETINSTANCEDATA 0x00000603 +#define TEE_PANIC_ID_TEE_MALLOC 0x00000604 +#define TEE_PANIC_ID_TEE_MEMCOMPARE 0x00000605 +#define TEE_PANIC_ID_TEE_MEMFILL 0x00000606 +#define TEE_PANIC_ID_TEE_MEMMOVE 0x00000607 +#define TEE_PANIC_ID_TEE_REALLOC 0x00000608 +#define TEE_PANIC_ID_TEE_SETINSTANCEDATA 0x00000609 +/* Generic Object */ +#define TEE_PANIC_ID_TEE_CLOSEOBJECT 0x00000701 +#define TEE_PANIC_ID_TEE_GETOBJECTBUFFERATTRIBUTE 0x00000702 +/* deprecated */ +#define TEE_PANIC_ID_TEE_GETOBJECTINFO 0x00000703 +#define TEE_PANIC_ID_TEE_GETOBJECTVALUEATTRIBUTE 0x00000704 +/* deprecated */ +#define TEE_PANIC_ID_TEE_RESTRICTOBJECTUSAGE 0x00000705 +#define TEE_PANIC_ID_TEE_GETOBJECTINFO1 0x00000706 +#define TEE_PANIC_ID_TEE_RESTRICTOBJECTUSAGE1 0x00000707 +/* Transient Object */ +#define TEE_PANIC_ID_TEE_ALLOCATETRANSIENTOBJECT 0x00000801 +/* deprecated */ +#define TEE_PANIC_ID_TEE_COPYOBJECTATTRIBUTES 0x00000802 +#define TEE_PANIC_ID_TEE_FREETRANSIENTOBJECT 0x00000803 +#define TEE_PANIC_ID_TEE_GENERATEKEY 0x00000804 +#define TEE_PANIC_ID_TEE_INITREFATTRIBUTE 0x00000805 +#define TEE_PANIC_ID_TEE_INITVALUEATTRIBUTE 0x00000806 +#define TEE_PANIC_ID_TEE_POPULATETRANSIENTOBJECT 0x00000807 +#define TEE_PANIC_ID_TEE_RESETTRANSIENTOBJECT 0x00000808 +#define TEE_PANIC_ID_TEE_COPYOBJECTATTRIBUTES1 0x00000809 +/* Persistent Object */ +/* deprecated */ +#define TEE_PANIC_ID_TEE_CLOSEANDDELETEPERSISTENTOBJECT 0x00000901 +#define TEE_PANIC_ID_TEE_CREATEPERSISTENTOBJECT 0x00000902 +#define TEE_PANIC_ID_TEE_OPENPERSISTENTOBJECT 0x00000903 +#define TEE_PANIC_ID_TEE_RENAMEPERSISTENTOBJECT 0x00000904 +#define TEE_PANIC_ID_TEE_CLOSEANDDELETEPERSISTENTOBJECT1 0x00000905 +/* Persistent Object Enumeration */ +#define TEE_PANIC_ID_TEE_ALLOCATEPERSISTENTOBJECTENUMERATOR 0x00000A01 +#define TEE_PANIC_ID_TEE_FREEPERSISTENTOBJECTENUMERATOR 0x00000A02 +#define TEE_PANIC_ID_TEE_GETNEXTPERSISTENTOBJECT 0x00000A03 +#define TEE_PANIC_ID_TEE_RESETPERSISTENTOBJECTENUMERATOR 0x00000A04 +#define TEE_PANIC_ID_TEE_STARTPERSISTENTOBJECTENUMERATOR 0x00000A05 +/* Data Stream Access */ +#define TEE_PANIC_ID_TEE_READOBJECTDATA 0x00000B01 +#define TEE_PANIC_ID_TEE_SEEKOBJECTDATA 0x00000B02 +#define TEE_PANIC_ID_TEE_TRUNCATEOBJECTDATA 0x00000B03 +#define TEE_PANIC_ID_TEE_WRITEOBJECTDATA 0x00000B04 +/* Generic Operation */ +#define TEE_PANIC_ID_TEE_ALLOCATEOPERATION 0x00000C01 +#define TEE_PANIC_ID_TEE_COPYOPERATION 0x00000C02 +#define TEE_PANIC_ID_TEE_FREEOPERATION 0x00000C03 +#define TEE_PANIC_ID_TEE_GETOPERATIONINFO 0x00000C04 +#define TEE_PANIC_ID_TEE_RESETOPERATION 0x00000C05 +#define TEE_PANIC_ID_TEE_SETOPERATIONKEY 0x00000C06 +#define TEE_PANIC_ID_TEE_SETOPERATIONKEY2 0x00000C07 +#define TEE_PANIC_ID_TEE_GETOPERATIONINFOMULTIPLE 0x00000C08 +/* Message Digest */ +#define TEE_PANIC_ID_TEE_DIGESTDOFINAL 0x00000D01 +#define TEE_PANIC_ID_TEE_DIGESTUPDATE 0x00000D02 +/* Symmetric Cipher */ +#define TEE_PANIC_ID_TEE_CIPHERDOFINAL 0x00000E01 +#define TEE_PANIC_ID_TEE_CIPHERINIT 0x00000E02 +#define TEE_PANIC_ID_TEE_CIPHERUPDATE 0x00000E03 +/* MAC */ +#define TEE_PANIC_ID_TEE_MACCOMPAREFINAL 0x00000F01 +#define TEE_PANIC_ID_TEE_MACCOMPUTEFINAL 0x00000F02 +#define TEE_PANIC_ID_TEE_MACINIT 0x00000F03 +#define TEE_PANIC_ID_TEE_MACUPDATE 0x00000F04 +/* Authenticated Encryption */ +#define TEE_PANIC_ID_TEE_AEDECRYPTFINAL 0x00001001 +#define TEE_PANIC_ID_TEE_AEENCRYPTFINAL 0x00001002 +#define TEE_PANIC_ID_TEE_AEINIT 0x00001003 +#define TEE_PANIC_ID_TEE_AEUPDATE 0x00001004 +#define TEE_PANIC_ID_TEE_AEUPDATEAAD 0x00001005 +/* Asymmetric */ +#define TEE_PANIC_ID_TEE_ASYMMETRICDECRYPT 0x00001101 +#define TEE_PANIC_ID_TEE_ASYMMETRICENCRYPT 0x00001102 +#define TEE_PANIC_ID_TEE_ASYMMETRICSIGNDIGEST 0x00001103 +#define TEE_PANIC_ID_TEE_ASYMMETRICVERIFYDIGEST 0x00001104 +/* Key Derivation */ +#define TEE_PANIC_ID_TEE_DERIVEKEY 0x00001201 +/* Random Data Generation */ +#define TEE_PANIC_ID_TEE_GENERATERANDOM 0x00001301 +/* Time */ +#define TEE_PANIC_ID_TEE_GETREETIME 0x00001401 +#define TEE_PANIC_ID_TEE_GETSYSTEMTIME 0x00001402 +#define TEE_PANIC_ID_TEE_GETTAPERSISTENTTIME 0x00001403 +#define TEE_PANIC_ID_TEE_SETTAPERSISTENTTIME 0x00001404 +#define TEE_PANIC_ID_TEE_WAIT 0x00001405 +/* Memory Allocation and Size of Objects */ +#define TEE_PANIC_ID_TEE_BIGINTFMMCONTEXTSIZEINU32 0x00001501 +#define TEE_PANIC_ID_TEE_BIGINTFMMSIZEINU32 0x00001502 +/* Initialization */ +#define TEE_PANIC_ID_TEE_BIGINTINIT 0x00001601 +#define TEE_PANIC_ID_TEE_BIGINTINITFMM 0x00001602 +#define TEE_PANIC_ID_TEE_BIGINTINITFMMCONTEXT 0x00001603 +/* Converter */ +#define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMOCTETSTRING 0x00001701 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMS32 0x00001702 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTTOOCTETSTRING 0x00001703 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTTOS32 0x00001704 +/* Logical Operation */ +#define TEE_PANIC_ID_TEE_BIGINTCMP 0x00001801 +#define TEE_PANIC_ID_TEE_BIGINTCMPS32 0x00001802 +#define TEE_PANIC_ID_TEE_BIGINTGETBIT 0x00001803 +#define TEE_PANIC_ID_TEE_BIGINTGETBITCOUNT 0x00001804 +#define TEE_PANIC_ID_TEE_BIGINTSHIFTRIGHT 0x00001805 +/* Basic Arithmetic */ +#define TEE_PANIC_ID_TEE_BIGINTADD 0x00001901 +#define TEE_PANIC_ID_TEE_BIGINTDIV 0x00001902 +#define TEE_PANIC_ID_TEE_BIGINTMUL 0x00001903 +#define TEE_PANIC_ID_TEE_BIGINTNEG 0x00001904 +#define TEE_PANIC_ID_TEE_BIGINTSQUARE 0x00001905 +#define TEE_PANIC_ID_TEE_BIGINTSUB 0x00001906 +/* Modular Arithmetic */ +#define TEE_PANIC_ID_TEE_BIGINTADDMOD 0x00001A01 +#define TEE_PANIC_ID_TEE_BIGINTINVMOD 0x00001A02 +#define TEE_PANIC_ID_TEE_BIGINTMOD 0x00001A03 +#define TEE_PANIC_ID_TEE_BIGINTMULMOD 0x00001A04 +#define TEE_PANIC_ID_TEE_BIGINTSQUAREMOD 0x00001A05 +#define TEE_PANIC_ID_TEE_BIGINTSUBMOD 0x00001A06 +/* Other Arithmetic */ +#define TEE_PANIC_ID_TEE_BIGINTCOMPUTEEXTENDEDGCD 0x00001B01 +#define TEE_PANIC_ID_TEE_BIGINTISPROBABLEPRIME 0x00001B02 +#define TEE_PANIC_ID_TEE_BIGINTRELATIVEPRIME 0x00001B03 +/* Fast Modular Multiplication */ +#define TEE_PANIC_ID_TEE_BIGINTCOMPUTEFMM 0x00001C01 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMFMM 0x00001C02 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTTOFMM 0x00001C03 + +/* + * The macro TEE_PARAM_TYPES can be used to construct a value that you can + * compare against an incoming paramTypes to check the type of all the + * parameters in one comparison, like in the following example: + * if (paramTypes != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + * TEE_PARAM_TYPE_MEMREF_OUTPUT, + * TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { + * return TEE_ERROR_BAD_PARAMETERS; + * } + */ +#define TEE_PARAM_TYPES(t0, t1, t2, t3) \ + ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12)) + +/* + * The macro TEE_PARAM_TYPE_GET can be used to extract the type of a given + * parameter from paramTypes if you need more fine-grained type checking. + */ +#define TEE_PARAM_TYPE_GET(t, i) ((((uint32_t)t) >> ((i)*4)) & 0xF) + +/* + * The macro TEE_PARAM_TYPE_SET can be used to load the type of a given + * parameter from paramTypes without specifying all types (TEE_PARAM_TYPES) + */ +#define TEE_PARAM_TYPE_SET(t, i) (((uint32_t)(t)&0xF) << ((i)*4)) + +/* Not specified in the standard */ +#define TEE_NUM_PARAMS 4 + +/* TEE Arithmetical APIs */ + +#define TEE_BigIntSizeInU32(n) ((((n) + 31) / 32) + 2) + +#endif /* TEE_API_DEFINES_H */ diff --git a/drivers/tee/teei/300/tests/teei_internal_types.h b/drivers/tee/teei/300/tests/teei_internal_types.h new file mode 100644 index 000000000000..f2a94fc45dc4 --- /dev/null +++ b/drivers/tee/teei/300/tests/teei_internal_types.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_INTERNAL_API_TYPES_H +#define TEEI_INTERNAL_API_TYPES_H + +#define TEE_ERROR_UNKNOWN_COMMAND 0xFFFF0009 +#define TEE_ERROR_ALLOCATE_TRANSIENT_OBJECT 0xFFFF1000 +#define TEE_ERROR_GENERATEKEY 0xFFFF1001 +#define TEE_ERROR_ALLOCATE_OPERATION 0xFFFF1002 +#define TEE_ERROR_SET_OPERATION_KEY 0xFFFF1003 +#define TEE_ERROR_MAC_COMPUTE_FINAL 0xFFFF1004 +#define TEE_ERROR_ASYMMETRIC_SIGN_DIGEST 0xFFFF1005 +#define TEE_ERROR_ASYMMETRIC_VERIFY_DIGEST 0xFFFF1006 +#define TEE_ERROR_CIPHER_UPDATE 0xFFFF1007 +#define TEE_ERROR_CIPHER_DO_FINAL 0xFFFF1008 +#define TEE_ERROR_MEM_COMPARE 0xFFFF1009 +#define TEE_ERROR_ASYMMETRIC_ENCRYPT 0xFFFF1010 +#define TEE_ERROR_ASYMMETRIC_DECRYPT 0xFFFF1011 +#define TEE_ERROR_DIGEST_DO_FINAL 0xFFFF1012 +#define TEE_ERROR_POPULATE_TRANSIENT_OBJECT 0xFFFF1013 +#define TEE_ERROR_CHECK_MEMORY_ACCESS_RIGHTS 0xFFFF1014 +#define TEE_ERROR_MALLOC 0xFFFF1015 +#define TEE_ERROR_REALLOC 0xFFFF1016 +#define TEE_ERROR_MEM_FILL 0xFFFF1017 +#define TEE_ERROR_MEM_MOVE 0xFFFF1018 +#define TEE_ERROR_GET_PROPERTY_AS_UUID 0xFFFF1019 +#define TEE_ERROR_MDRV_OPEN 0xFFFF1020 +#define TEE_ERROR_MDRV_IOCTL 0xFFFF1021 +#define TEE_ERROR_MDRV_CLOSE 0xFFFF1022 +#define TEE_ERROR_MAC_COMPARE_FINAL 0xFFFF1023 +#define TEE_ERROR_GENERATE_RANDOM 0xFFFF1024 +#define TEE_ERROR_REALLOC_COMPARE1 0xFFFF1025 +#define TEE_ERROR_REALLOC_COMPARE2 0xFFFF1026 +#define TEE_ERROR_MALLOC_COMPARE1 0xFFFF1027 +#define TEE_ERROR_NULL_PARAMETERSS 0xFFFF1028 +#define TEE_ERROR_REGISTER_SHARED_MEMORY_CONTENT 0xFFFF1029 +#define TEE_ERROR_REGISTER_SHARED_MEMORY_SIZE 0xFFFF1030 +#define TEE_ERROR_MDRV_OPEN_56 0xFFFF1031 +#define TEE_ERROR_MDRV_IOCTL_56 0xFFFF1032 +#define TEE_ERROR_MDRV_OPEN_57 0xFFFF1033 +#define TEE_ERROR_MDRV_IOCTL_57 0xFFFF1034 +#define TEE_ERROR_REGISTER_SHARED_MEMORY_CONTENT1 0xFFFF1035 +#define TEE_ERROR_REGISTER_SHARED_MEMORY_SIZE1 0xFFFF1036 +#define TEE_ERROR_REGISTER_SHARED_MEMORY_CONTENT2 0xFFFF1037 +#define TEE_ERROR_REGISTER_SHARED_MEMORY_SIZE2 0xFFFF1038 +#define TEE_ERROR_BAD_PARAMETER_TYPE 0xFFFF1039 + +#define DRV_ERROR_UNKNOWN_COMMAND 0xFFFF1999 +#define DRV_ERROR_BAD_PARAMETERS 0xFFFF2000 +#define DRV_ERROR_NOT_IMPLEMENTED 0xFFFF2001 +#define DRV_ERROR_NO_NEED 0xFFFF2002 +#define DRV_ERROR_MTK_SUPPORTED 0xFFFF2003 +#define DRV_ERROR_MSEE_MAP_USER_LV1 0xFFFF2004 +#define DRV_ERROR_MSEE_MAP_USER_LV2 0xFFFF2005 +#define DRV_ERROR_MSEE_MAP_USER_LV2_16K 0xFFFF2006 +#define DRV_ERROR_MSEE_MAP_USER_LV1_COMPARE 0xFFFF2007 +#define DRV_ERROR_MSEE_MAP_USER_LV2_COMPARE 0xFFFF2008 +#define DRV_ERROR_MSEE_MAP_USER_LV2_16K_COMPARE 0xFFFF2009 +#define DRV_ERROR_MSEE_UNMAP_USER_LV1 0xFFFF2010 +#define DRV_ERROR_MSEE_UNMAP_USER_LV2 0xFFFF2011 +#define DRV_ERROR_MSEE_UNMAP_USER_LV2_16K 0xFFFF2012 +#define DRV_ERROR_MSEE_MAP_REGION 0xFFFF2013 +#define DRV_ERROR_MSEE_UNMAP_REGION 0xFFFF2014 +#define DRV_ERROR_MSEE_MALLOC 0xFFFF2015 +#define DRV_ERROR_MSEE_MALLOC_COMPARE1 0xFFFF2016 +#define DRV_ERROR_MSEE_REALLOC 0xFFFF2017 +#define DRV_ERROR_MSEE_REALLOC_COMPARE1 0xFFFF2018 +#define DRV_ERROR_MSEE_REALLOC_COMPARE2 0xFFFF2019 +#define DRV_ERROR_MSEE_STRNCPY 0xFFFF2020 +#define DRV_ERROR_MSEE_STRNCPY_COMPARE1 0xFFFF2021 +#define DRV_ERROR_MSEE_STRLEN 0xFFFF2022 +#define DRV_ERROR_MSEE_MEMCPY 0xFFFF2023 +#define DRV_ERROR_MSEE_MEMCPY_COMPARE1 0xFFFF2024 +#define DRV_ERROR_MSEE_MEMSET 0xFFFF2025 +#define DRV_ERROR_MSEE_MEMSET_COMPARE1 0xFFFF2026 +#define DRV_ERROR_MSEE_GET_SYSTEM_TIME 0xFFFF2027 +#define DRV_ERROR_MSEE_REQUEST_IRQ 0xFFFF2028 +#define DRV_ERROR_MSEE_WAIT_FOR_IRQ_COMPLETE 0xFFFF2029 +#define DRV_ERROR_NULL_PARAMETERS 0xFFFF2030 +#define DRV_ERROR_MSEE_REALLOC1 0xFFFF2031 +#define DRV_ERROR_REGISTER_SHARED_MEMORY_CONTENT_56 0xFFFF2032 +#define DRV_ERROR_REGISTER_SHARED_MEMORY_SIZE_56 0xFFFF2033 +#define DRV_ERROR_REGISTER_SHARED_MEMORY_CONTENT_57 0xFFFF2034 +#define DRV_ERROR_REGISTER_SHARED_MEMORY_SIZE_57 0xFFFF2035 +#define DRV_ERROR_BAD_PARAMETER_TYPE 0xFFFF2036 +#define DRV_ERROR_MSEE_CLEAN_DCACHE_RANGE 0xFFFF2037 +#define DRV_ERROR_MSEE_CLEAN_INVALIDATE_DCACHE_RANGE 0xFFFF2038 +#define DRV_ERROR_MSEE_MAP_REGION_TEST1 0xFFFF2039 +#define DRV_ERROR_MSEE_MAP_REGION_TEST2 0xFFFF2040 +#define DRV_ERROR_MSEE_MAP_REGION_TEST3 0xFFFF2041 +#define DRV_ERROR_MSEE_MAP_REGION_TEST4 0xFFFF2042 + +#define MDRV_OPEN_ERROR (~0UL << (12UL - 1)) + +#define TEEC_MEM_INOUT 0x00000003 + +#endif diff --git a/drivers/tee/teei/300/tests/teei_ta_drv_types.h b/drivers/tee/teei/300/tests/teei_ta_drv_types.h new file mode 100644 index 000000000000..c02e44afe541 --- /dev/null +++ b/drivers/tee/teei/300/tests/teei_ta_drv_types.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_TA_DRV_TYPES_H +#define TEEI_TA_DRV_TYPES_H + +/* TA to DRV Commands */ +#define TA_CORE_API_CMD_MDRV_OPEN 0x3000 +#define TA_CORE_API_CMD_MDRV_IOCTL 0x3001 +#define TA_CORE_API_CMD_MDRV_CLOSE 0x3002 +#define TA_CORE_API_CMD_MSEE_TA_PRINTF 0x3003 +/* DRV Commands */ +#define DRV_CORE_API_CMD_MSEE_CLEAN_DCACHE_ALL 0x3006 +#define DRV_CORE_API_CMD_MSEE_CLEAN_INVALIDATE_DCACHE_ALL 0x3007 +#define DRV_CORE_API_CMD_MSEE_CLEAN_DCACHE_RANGE 0x3008 +#define DRV_CORE_API_CMD_MSEE_CLEAN_INVALIDATE_DCACHE_RANGE 0x3009 +#define DRV_CORE_API_CMD_MSEE_MAP_USER 0x3010 +#define DRV_CORE_API_CMD_MSEE_MALLOC 0x3012 +#define DRV_CORE_API_CMD_MSEE_REALLOC 0x3013 +#define DRV_CORE_API_CMD_MSEE_REQUEST_IRQ 0x3014 +#define DRV_CORE_API_CMD_MSEE_PRINTF 0x3015 +#define DRV_CORE_API_CMD_MSEE_GET_SYSTEM_TIME 0x3016 +#define DRV_CORE_API_CMD_MSEE_STRNCPY 0x3017 +#define DRV_CORE_API_CMD_MSEE_STRLEN 0x3018 +#define DRV_CORE_API_CMD_MSEE_MEMCPY 0x3019 +#define DRV_CORE_API_CMD_MSEE_MEMSET 0x3020 +#define DRV_CORE_API_CMD_MSEE_GET_CHIP_HW_CODE 0x3021 +#define DRV_CORE_API_CMD_MSEE_SET_EMI_MPU_PROTECTION 0x3022 +#define DRV_CORE_API_CMD_MSEE_4G_ENABLED 0x3023 +#define DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST1 0x3024 +#define DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST2 0x3025 +#define DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST3 0x3026 +#define DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST4 0x3027 +/* Shared Memory Commands */ +#define CORE_API_CMD_REGISTER_SHARED_MEMORY_01 0x5000 +#define CORE_API_CMD_REGISTER_SHARED_MEMORY_02 0x5001 +#define CORE_API_CMD_REGISTER_SHARED_MEMORY_03 0x5002 + +/* Shared Memory Test Data */ +#define SHARE_MEMORY_TEST_DATA_0 0x111 +#define SHARE_MEMORY_TEST_DATA_1 0x222 +#define SHARE_MEMORY_TEST_DATA_2 0x333 +#define SHARE_MEMORY_TEST_DATA_3 0x444 +#define SHARE_MEMORY_TEST_DATA_4 0x555 +#define SHARE_MEMORY_TEST_DATA_5 0x666 +#define SHARE_MEMORY_TEST_DATA_6 0x777 +#define SHARE_MEMORY_TEST_DATA_7 0x888 +#define SHARE_MEMORY_TEST_DATA_10 0xAAA +#define SHARE_MEMORY_TEST_DATA_11 0xBBB +#define SHARE_MEMORY_TEST_DATA_12 0xCCC +#define SHARE_MEMORY_TEST_DATA_13 0xDDD +#define SHARE_MEMORY_TEST_DATA_14 0xEEE +#define SHARE_MEMORY_TEST_DATA_15 0xFFF +#define SHARE_MEMORY_TEST_DATA_16 0x000 +#define SHARE_MEMORY_TEST_DATA_17 0x999 +#define SHARE_MEMORY_TEST_DATA_20 0x888 +#define SHARE_MEMORY_TEST_DATA_21 0x777 +#define SHARE_MEMORY_TEST_DATA_22 0x666 +#define SHARE_MEMORY_TEST_DATA_23 0x555 +#define SHARE_MEMORY_TEST_DATA_24 0x444 +#define SHARE_MEMORY_TEST_DATA_25 0x333 +#define SHARE_MEMORY_TEST_DATA_26 0x222 +#define SHARE_MEMORY_TEST_DATA_27 0x111 + +/* MTK Commands */ +#define MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE1 0x8000 +#define MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE2 0x8001 +#define MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE3 0x8002 +#define MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE4 0x8003 + +#define DRV_CORE_API_UNSUPPORTED_CMD 0xFFFFFFF2 + +/* Error Code */ +#define DRV_CORE_API_SPECIFIC_RET_VALUE 0x34578900 + +#define DRV_SUCCESS 0x0 + +#define MEMSET_UINT32(buffer, pattern, size_in_byte) \ + { \ + unsigned char *buffer_ptr = (unsigned char *)buffer; \ + unsigned int test_pattern = (unsigned int)pattern; \ + unsigned char *pattern_ptr = (unsigned char *)&test_pattern; \ + unsigned int j = 0; \ + for (j = 0; j < size_in_byte; j += 4) { \ + buffer_ptr[j] = pattern_ptr[0]; \ + buffer_ptr[j + 1] = pattern_ptr[1]; \ + buffer_ptr[j + 2] = pattern_ptr[2]; \ + buffer_ptr[j + 3] = pattern_ptr[3]; \ + } \ + } + +#endif diff --git a/drivers/tee/teei/300/tests/xtest_isee_1000.c b/drivers/tee/teei/300/tests/xtest_isee_1000.c new file mode 100644 index 000000000000..3c2734f99301 --- /dev/null +++ b/drivers/tee/teei/300/tests/xtest_isee_1000.c @@ -0,0 +1,2725 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMSG_TAG "[tz_test_ca]" +#include +#include "ta_core_api.h" +unsigned int xtest_teec_open_session(struct TEEC_Context *context, + struct TEEC_Session *session, + const struct TEEC_UUID *uuid, + struct TEEC_Operation *op, + uint32_t *ret_orig) +{ + return TEEC_OpenSession(context, session, uuid, TEEC_LOGIN_PUBLIC, + NULL, op, ret_orig); +} +const char *ADBG_GetFileBase(const char *const FileName_p) +{ + const char *Ch_p = FileName_p; + const char *Base_p = FileName_p; + + while (*Ch_p != '\0') { + if (*Ch_p == '\\') + Base_p = Ch_p + 1; + + Ch_p++; + } + + return Base_p; +} +int case_res; +bool Do_ADBG_Expect(const char *const FileName_p, const int LineNumber, + const int Expected, const int Got) +{ + if (Expected == Got) + return true; + + IMSG_WARN("%s:%d: unexpected value: 0x%x, expected 0x%x\n", + ADBG_GetFileBase(FileName_p), + LineNumber, Got, Expected); + + case_res = -EINVAL; + return false; +} + +struct TEEC_Context xtest_isee_ctx_1000; +const struct TEEC_UUID isee_test_ta_uuid = DRM_01_UUID; + +int compare_array_with_pattern(unsigned char *buffer, unsigned int pattern, + unsigned int size_in_byte) +{ + unsigned char *buffer_ptr = (unsigned char *)buffer; + unsigned char *pattern_ptr = (unsigned char *)&pattern; + unsigned int i; + unsigned int *got; + + for (i = 0; i < size_in_byte; i += 4) { + if (buffer_ptr[i] != pattern_ptr[0]) + goto exit; + if (buffer_ptr[i + 1] != pattern_ptr[1]) + goto exit; + if (buffer_ptr[i + 2] != pattern_ptr[2]) + goto exit; + if (buffer_ptr[i + 3] != pattern_ptr[3]) + goto exit; + } + return TA_CORE_API_PARAM_TYPE_PATTERN_MATCH; +exit: + got = (unsigned int *)(&buffer_ptr[i]); + IMSG_DEBUG("[%s]expect=0x%x, got[%d]=0x%x\n", __func__, + pattern, i, *got); + return TA_CORE_API_PARAM_TYPE_PATTERN_NOT_MATCH; +} + +int xtest_isee_test_1001(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PRINT, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1002(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_SPECIFIC_RET_VALUE, + TEEC_InvokeCommand(&session, TA_CORE_API_CMD_RET_VALUE, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1003(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_RESULT(TEE_ERROR_UNKNOWN_COMMAND, + TEEC_InvokeCommand(&session, TA_CORE_API_UNSUPPORTED_CMD, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1004(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + uint64_t time_start, time_end, time_freq, time_ms; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + op.params[0].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.params[0].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.params[1].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.params[1].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.params[2].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.params[2].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.params[3].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.params[3].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, + TEEC_VALUE_INOUT, + TEEC_VALUE_INOUT, + TEEC_VALUE_INOUT); + + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_InvokeCommand(&session, TA_CORE_API_CMD_READ_CNTVCT, + &op, &ret_orig)); + + time_start = (uint64_t)op.params[0].value.b << 32 + & 0xFFFFFFFF00000000lu; + time_start |= op.params[0].value.a; + time_end = (uint64_t)op.params[1].value.b << 32 + & 0xFFFFFFFF00000000lu; + time_end |= op.params[1].value.a; + time_freq = (uint64_t)op.params[2].value.b << 32 + & 0xFFFFFFFF00000000lu; + time_freq |= op.params[2].value.a; + time_ms = (uint64_t)op.params[3].value.b << 32 + & 0xFFFFFFFF00000000lu; + time_ms |= op.params[3].value.a; + + (void)ADBG_EXPECT_TEEC_RESULT(1, time_start != + TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO); + (void)ADBG_EXPECT_TEEC_RESULT(1, time_end != + TA_CORE_API_PARAM_TYPE_Test_Pattern_ZERO); + (void)ADBG_EXPECT_TEEC_RESULT(1, time_end > time_start); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1005(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + uint32_t loop_count = 1000, i = 0; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < loop_count; i++) + res |= TEEC_InvokeCommand(&session, TA_CORE_API_CMD_RET_VALUE, + NULL, &ret_orig); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_SPECIFIC_RET_VALUE, res); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1010(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + int ta_verify_ret = 0; + + UNUSED(ta_verify_ret); + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + op.params[0].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern1; + op.params[0].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern2; + op.params[1].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern3; + op.params[1].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern4; + op.params[2].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern5; + op.params[2].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern6; + op.params[3].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern7; + op.params[3].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern8; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_VALUE_INPUT, + &op, &ret_orig)); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1011(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + int ta_verify_ret = 0; + + UNUSED(ta_verify_ret); + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_VALUE_OUTPUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern8, + op.params[0].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern7, + op.params[0].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern6, + op.params[1].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern5, + op.params[1].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern4, + op.params[2].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern3, + op.params[2].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern2, + op.params[3].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern1, + op.params[3].value.b); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1012(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + op.params[0].value.a = TA_CORE_API_PARAM_TYPE_Test_PatternA; + op.params[0].value.b = TA_CORE_API_PARAM_TYPE_Test_PatternB; + op.params[1].value.a = TA_CORE_API_PARAM_TYPE_Test_PatternC; + op.params[1].value.b = TA_CORE_API_PARAM_TYPE_Test_PatternD; + op.params[2].value.a = TA_CORE_API_PARAM_TYPE_Test_PatternA; + op.params[2].value.b = TA_CORE_API_PARAM_TYPE_Test_PatternB; + op.params[3].value.a = TA_CORE_API_PARAM_TYPE_Test_PatternC; + op.params[3].value.b = TA_CORE_API_PARAM_TYPE_Test_PatternD; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, + TEEC_VALUE_INOUT, + TEEC_VALUE_INOUT, + TEEC_VALUE_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_VALUE_INOUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternF, + op.params[0].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternF, + op.params[0].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternF, + op.params[1].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternF, + op.params[1].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternE, + op.params[2].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternE, + op.params[2].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternE, + op.params[3].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternE, + op.params[3].value.b); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1013(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + op.params[0].value.a = TA_CORE_API_PARAM_TYPE_Test_Pattern0; + op.params[0].value.b = TA_CORE_API_PARAM_TYPE_Test_Pattern0; + op.params[2].value.a = TA_CORE_API_PARAM_TYPE_Test_PatternA; + op.params[2].value.b = TA_CORE_API_PARAM_TYPE_Test_PatternA; + op.params[3].value.a = TA_CORE_API_PARAM_TYPE_Test_PatternB; + op.params[3].value.b = TA_CORE_API_PARAM_TYPE_Test_PatternB; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_OUTPUT, + TEEC_VALUE_INOUT, + TEEC_VALUE_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT( + TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, TA_CORE_API_CMD_PARAM_TYPE_VALUE_MIX, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternC, + op.params[1].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternC, + op.params[1].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternD, + op.params[2].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_PatternD, + op.params[2].value.b); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern1, + op.params[3].value.a); + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_Test_Pattern1, + op.params[3].value.b); + + TEEC_CloseSession(&session); + return case_res; +} + +#define TEMP_BUFFER_COUNT 4 +#define SIZE_1M (1024 * 1024) +#define TEMP_BUFFER_TEST_SIZE SIZE_1M +int xtest_isee_test_1020(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern0, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + TA_CORE_API_PARAM_TYPE_Test_Pattern3}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + MEMSET_UINT32(temp_buffer[i], temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + + op.params[i].tmpref.buffer = temp_buffer[i]; + op.params[i].tmpref.size = sizeof(temp_buffer_pattern[i]); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_INPUT, + &op, &ret_orig)); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1021(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = {0}; + uint32_t ret_orig; + int i; + + UNUSED(temp_buffer_pattern); + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + op.params[i].tmpref.buffer = temp_buffer[i]; + op.params[i].tmpref.size = sizeof(unsigned int); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_OUTPUT, + &op, &ret_orig)); + + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[0].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern4, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[1].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern5, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[2].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[3].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + sizeof(unsigned int))); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1022(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern8, + TA_CORE_API_PARAM_TYPE_Test_Pattern9, + TA_CORE_API_PARAM_TYPE_Test_PatternA, + TA_CORE_API_PARAM_TYPE_Test_PatternB}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + MEMSET_UINT32(temp_buffer[i], temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + + op.params[i].tmpref.buffer = temp_buffer[i]; + op.params[i].tmpref.size = sizeof(temp_buffer_pattern[i]); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_INOUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[0].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternC, + op.params[0].tmpref.size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[1].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternD, + op.params[1].tmpref.size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[2].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternE, + op.params[2].tmpref.size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[3].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternF, + op.params[3].tmpref.size)); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1023(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern8, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + TA_CORE_API_PARAM_TYPE_Test_Pattern5}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + MEMSET_UINT32(temp_buffer[i], temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + + op.params[i].tmpref.buffer = temp_buffer[i]; + op.params[i].tmpref.size = sizeof(temp_buffer_pattern[i]); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_TMEP_MIX, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[1].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern3, + op.params[1].tmpref.size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[2].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + op.params[2].tmpref.size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(op.params[3].tmpref.buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + op.params[3].tmpref.size)); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1030(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern0, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + TA_CORE_API_PARAM_TYPE_Test_Pattern3}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + shared_mem[i].size = sizeof(temp_buffer_pattern[i]); + shared_mem[i].flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_allocate_failed; + } + b_shared_mem_registered[i] = 1; + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(temp_buffer_pattern[i]); + + MEMSET_UINT32(shared_mem[i].buffer, temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_INPUT, + &op, &ret_orig)); + +share_mem_allocate_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1031(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + shared_mem[i].size = sizeof(unsigned int); + shared_mem[i].flags = TEEC_MEM_OUTPUT; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_allocate_failed; + } + b_shared_mem_registered[i] = 1; + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(unsigned int); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_OUTPUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[0].buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern4, + shared_mem[0].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[1].buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern5, + shared_mem[1].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[2].buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + shared_mem[2].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[3].buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + shared_mem[3].size)); + +share_mem_allocate_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1032(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern8, + TA_CORE_API_PARAM_TYPE_Test_Pattern9, + TA_CORE_API_PARAM_TYPE_Test_PatternA, + TA_CORE_API_PARAM_TYPE_Test_PatternB}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + shared_mem[i].size = sizeof(temp_buffer_pattern[i]); + shared_mem[i].flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_allocate_failed; + } + b_shared_mem_registered[i] = 1; + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(temp_buffer_pattern[i]); + + MEMSET_UINT32(shared_mem[i].buffer, temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_INOUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[0].buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternC, + shared_mem[0].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[1].buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternD, + shared_mem[1].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[2].buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternE, + shared_mem[2].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[3].buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternF, + shared_mem[3].size)); + +share_mem_allocate_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1033(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + unsigned int shared_mem_flags[TEMP_BUFFER_COUNT] = { + TEEC_MEM_INPUT, TEEC_MEM_OUTPUT, + TEEC_MEM_INPUT | TEEC_MEM_OUTPUT, + TEEC_MEM_INPUT | TEEC_MEM_OUTPUT}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern8, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + TA_CORE_API_PARAM_TYPE_Test_Pattern5}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + shared_mem[i].size = sizeof(temp_buffer_pattern[i]); + shared_mem[i].flags = shared_mem_flags[i]; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_allocate_failed; + } + b_shared_mem_registered[i] = 1; + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(temp_buffer_pattern[i]); + + MEMSET_UINT32(shared_mem[i].buffer, temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_MIX, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[1].buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern3, + shared_mem[1].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[2].buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + shared_mem[2].size)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_mem[3].buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + shared_mem[3].size)); + +share_mem_allocate_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1034(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern0, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + TA_CORE_API_PARAM_TYPE_Test_Pattern3}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + MEMSET_UINT32(temp_buffer[i], temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + + shared_mem[i].buffer = temp_buffer[i]; + shared_mem[i].size = sizeof(temp_buffer_pattern[i]); + shared_mem[i].flags = TEEC_MEM_INPUT; + + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + b_shared_mem_registered[i] = 1; + + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(temp_buffer_pattern[i]); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_INPUT, + &op, &ret_orig)); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1035(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + shared_mem[i].buffer = temp_buffer[i]; + shared_mem[i].size = sizeof(unsigned int); + shared_mem[i].flags = TEEC_MEM_OUTPUT; + + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + b_shared_mem_registered[i] = 1; + + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(unsigned int); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_OUTPUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[0], + TA_CORE_API_PARAM_TYPE_Test_Pattern4, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[1], + TA_CORE_API_PARAM_TYPE_Test_Pattern5, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[2], + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[3], + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + sizeof(unsigned int))); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1036(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern8, + TA_CORE_API_PARAM_TYPE_Test_Pattern9, + TA_CORE_API_PARAM_TYPE_Test_PatternA, + TA_CORE_API_PARAM_TYPE_Test_PatternB}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + MEMSET_UINT32(temp_buffer[i], temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + + shared_mem[i].buffer = temp_buffer[i]; + shared_mem[i].size = sizeof(temp_buffer_pattern[i]); + shared_mem[i].flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + b_shared_mem_registered[i] = 1; + + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(temp_buffer_pattern[i]); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_INOUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[0], + TA_CORE_API_PARAM_TYPE_Test_PatternC, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[1], + TA_CORE_API_PARAM_TYPE_Test_PatternD, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[2], + TA_CORE_API_PARAM_TYPE_Test_PatternE, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[3], + TA_CORE_API_PARAM_TYPE_Test_PatternF, + sizeof(unsigned int))); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1037(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem[TEMP_BUFFER_COUNT] = { {0} }; + unsigned int b_shared_mem_registered[TEMP_BUFFER_COUNT] = {0}; + unsigned int shared_mem_flags[TEMP_BUFFER_COUNT] = { + TEEC_MEM_INPUT, TEEC_MEM_OUTPUT, + TEEC_MEM_INPUT | TEEC_MEM_OUTPUT, + TEEC_MEM_INPUT | TEEC_MEM_OUTPUT}; + unsigned char *temp_buffer[TEMP_BUFFER_COUNT] = {0}; + unsigned int temp_buffer_pattern[TEMP_BUFFER_COUNT] = { + TA_CORE_API_PARAM_TYPE_Test_Pattern8, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + TA_CORE_API_PARAM_TYPE_Test_Pattern5}; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + temp_buffer[i] = (unsigned char *)malloc( + TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer[i]) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + MEMSET_UINT32(temp_buffer[i], temp_buffer_pattern[i], + sizeof(temp_buffer_pattern[i])); + + shared_mem[i].buffer = temp_buffer[i]; + shared_mem[i].size = sizeof(temp_buffer_pattern[i]); + shared_mem[i].flags = shared_mem_flags[i]; + + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, + &shared_mem[i]); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS( + TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + b_shared_mem_registered[i] = 1; + + op.params[i].memref.parent = &shared_mem[i]; + op.params[i].memref.size = sizeof(temp_buffer_pattern[i]); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_WHOLE_MIX, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[1], + TA_CORE_API_PARAM_TYPE_Test_Pattern3, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[2], + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + sizeof(unsigned int))); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer[3], + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + sizeof(unsigned int))); + +buffer_alloc_failed: + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + if (temp_buffer[i]) + free(temp_buffer[i]); + if (b_shared_mem_registered[i]) + TEEC_ReleaseSharedMemory(&shared_mem[i]); + } + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1040(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *shared_buf_ptr = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + shared_buf_ptr = shared_mem.buffer; + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern0, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern3, TEMP_BUFFER_TEST_SIZE); + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_INPUT, + &op, &ret_orig)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1041(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *shared_buf_ptr = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_OUTPUT; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + shared_buf_ptr = shared_mem.buffer; + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_OUTPUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern4, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern5, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + TEMP_BUFFER_TEST_SIZE)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1042(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *shared_buf_ptr = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + shared_buf_ptr = shared_mem.buffer; + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern8, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern9, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_PatternA, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_PatternB, TEMP_BUFFER_TEST_SIZE); + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_INOUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_PatternC, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_PatternD, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_PatternE, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_PatternF, + TEMP_BUFFER_TEST_SIZE)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1043(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *shared_buf_ptr = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + res = TEEC_AllocateSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + shared_buf_ptr = shared_mem.buffer; + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern8, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern5, TEMP_BUFFER_TEST_SIZE); + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_MIX, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern3, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(shared_buf_ptr + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + TEMP_BUFFER_TEST_SIZE)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1044(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *temp_buffer = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE * 4); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern0, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern3, TEMP_BUFFER_TEST_SIZE); + + shared_mem.buffer = temp_buffer; + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_INPUT; + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_INPUT, + &op, &ret_orig)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + if (temp_buffer) + free(temp_buffer); +buffer_alloc_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1045(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *temp_buffer = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE * 4); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + shared_mem.buffer = temp_buffer; + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_OUTPUT; + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_OUTPUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern4, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern5, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, + TEMP_BUFFER_TEST_SIZE)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + if (temp_buffer) + free(temp_buffer); +buffer_alloc_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1046(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *temp_buffer = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE * 4); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern8, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern9, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_PatternA, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_PatternB, TEMP_BUFFER_TEST_SIZE); + + shared_mem.buffer = temp_buffer; + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_INOUT, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_PatternC, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_PatternD, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_PatternE, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_PatternF, + TEMP_BUFFER_TEST_SIZE)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + if (temp_buffer) + free(temp_buffer); +buffer_alloc_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1047(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + struct TEEC_SharedMemory shared_mem = {0}; + unsigned char *temp_buffer = NULL; + uint32_t ret_orig; + int i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)malloc(TEMP_BUFFER_TEST_SIZE * 4); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 0, + TA_CORE_API_PARAM_TYPE_Test_Pattern8, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern7, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern6, TEMP_BUFFER_TEST_SIZE); + MEMSET_UINT32(temp_buffer + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern5, TEMP_BUFFER_TEST_SIZE); + + shared_mem.buffer = temp_buffer; + shared_mem.size = TEMP_BUFFER_TEST_SIZE * 4; + shared_mem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + res = TEEC_RegisterSharedMemory(&xtest_isee_ctx_1000, &shared_mem); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto share_mem_reg_failed; + } + + for (i = 0; i < TEMP_BUFFER_COUNT; i++) { + op.params[i].memref.parent = &shared_mem; + op.params[i].memref.offset = TEMP_BUFFER_TEST_SIZE * i; + op.params[i].memref.size = TEMP_BUFFER_TEST_SIZE; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_TEST_SUCCESS, + TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_PARAM_TYPE_MEMREF_PARTIAL_MIX, + &op, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 1, + TA_CORE_API_PARAM_TYPE_Test_Pattern3, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 2, + TA_CORE_API_PARAM_TYPE_Test_Pattern2, + TEMP_BUFFER_TEST_SIZE)); + + (void)ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer + TEMP_BUFFER_TEST_SIZE * 3, + TA_CORE_API_PARAM_TYPE_Test_Pattern1, + TEMP_BUFFER_TEST_SIZE)); + + TEEC_ReleaseSharedMemory(&shared_mem); +share_mem_reg_failed: + if (temp_buffer) + free(temp_buffer); +buffer_alloc_failed: + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1100(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + unsigned char *rpmb_buffer = NULL; + int rpmb_access_ret = 0; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + +#define RPMB_TEST_SIZE 128 +#define RPMB_TEST_PATTERN 0xFA + rpmb_buffer = (unsigned char *)malloc(RPMB_TEST_SIZE); + if (!rpmb_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + return case_res; + } + memset(rpmb_buffer, RPMB_TEST_PATTERN, RPMB_TEST_SIZE); + + op.params[0].tmpref.buffer = rpmb_buffer; + op.params[0].tmpref.size = RPMB_TEST_SIZE; + op.params[1].value.a = RPMB_TEST_SIZE; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_RPMB_WRITE, &op, &ret_orig)); + + rpmb_access_ret = op.params[1].value.a; + (void)ADBG_EXPECT_TEEC_SUCCESS(rpmb_access_ret); + + free(rpmb_buffer); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1101(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + unsigned char *rpmb_buffer = NULL; + int rpmb_access_ret = 0, i; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + +#define RPMB_TEST_SIZE 128 +#define RPMB_TEST_PATTERN 0xFA + rpmb_buffer = (unsigned char *)malloc(RPMB_TEST_SIZE); + if (!rpmb_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + return case_res; + } + memset(rpmb_buffer, 0x00, RPMB_TEST_SIZE); + + op.params[0].tmpref.buffer = rpmb_buffer; + op.params[0].tmpref.size = RPMB_TEST_SIZE; + op.params[1].value.a = RPMB_TEST_SIZE; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_RPMB_READ, &op, &ret_orig)); + + rpmb_access_ret = op.params[1].value.a; + (void)ADBG_EXPECT_TEEC_SUCCESS(rpmb_access_ret); + + for (i = 0; i < RPMB_TEST_SIZE; i++) { + if (rpmb_buffer[i] != RPMB_TEST_PATTERN) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_BAD_FORMAT); + break; + } + } + + free(rpmb_buffer); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1102(void) +{ + unsigned int res; + struct TEEC_Session session; + struct TEEC_Operation op; + uint32_t ret_orig; + uint32_t sys_time_s, sys_time_ms; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + +#define SYSTEM_NON_ZERO_CHECK_VALUE 0x12345678 + op.params[0].value.a = SYSTEM_NON_ZERO_CHECK_VALUE; + op.params[1].value.a = SYSTEM_NON_ZERO_CHECK_VALUE; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_VALUE_INOUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_Get_System_Time, &op, &ret_orig)); + + sys_time_s = op.params[0].value.a; + sys_time_ms = op.params[1].value.a; + (void)ADBG_EXPECT_TEEC_SUCCESS(sys_time_s == + SYSTEM_NON_ZERO_CHECK_VALUE); + (void)ADBG_EXPECT_TEEC_SUCCESS(sys_time_ms == + SYSTEM_NON_ZERO_CHECK_VALUE); + (void)ADBG_EXPECT_TEEC_SUCCESS(sys_time_s == 0x0 && + sys_time_ms == 0x0); + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1200(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_INVOKE_COMMAND_ENTRY_POINT, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1201(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_ALLOCATE_TRANSIENT_OBJECT, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1203(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_POPULATE_TRANSIENT_OBJECT, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1204(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_ALLOCATE_OPERATION, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1206(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_SET_OPERATION_KEY, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1207(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_GENERATE_RANDOM, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1208(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_CHECK_MEMORY_ACCESS_RIGHTS, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1209(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_MALLOC, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1210(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_REALLOC, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1212(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_MEM_MOVE, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1213(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_MEM_COMPARE, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1214(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_MEM_FILL, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1215(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_GET_PROPERTY_AS_UUID, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1216(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_LOG_VPRINTF, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1217(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_LOG_PRINTF, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1218(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_DBG_PRINTF, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1219(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CORE_API_CMD_DBG_VPRINTF, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1300(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_AES_ECB, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1301(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_AES_CBC, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1302(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_AES_CTR, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1303(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_SHA1, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1304(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_SHA256, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1305(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_HMAC_SHA256, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1306(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_HMAC_SHA1, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1307(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_RSA_PKCS1_PSS_MGF1_SHA1, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1308(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_RSA_NOPAD, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1400(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_ASYMMETRIC_ENCRYPT, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1401(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_ASYMMETRIC_DECRYPT, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1402(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_ASYMMETRIC_SIGN_DIGEST, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1403(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_ASYMMETRIC_VERIFY_DIGEST, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1404(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_DIGEST_UPDATE, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1405(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_DIGEST_DO_FINAL, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1406(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_CIPHER_INIT, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1407(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_CIPHER_UPDATE, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1408(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_CIPHER_DO_FINAL, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1409(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_MAC_INIT, NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1410(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_MAC_UPDATE, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1411(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_MAC_COMPUTE_FINAL, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1412(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + TA_CRYPTO_API_CMD_MAC_COMPARE_FINAL, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1800(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE1, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1801(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE2, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1802(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE3, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_1803(void) +{ + unsigned int res; + struct TEEC_Session session; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_1000, &session, + &isee_test_ta_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + MTK_TEST_CRYPTO_AES_ECB_PERFORMANCE4, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} diff --git a/drivers/tee/teei/300/tests/xtest_isee_3000.c b/drivers/tee/teei/300/tests/xtest_isee_3000.c new file mode 100644 index 000000000000..d5683fc1c2d6 --- /dev/null +++ b/drivers/tee/teei/300/tests/xtest_isee_3000.c @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include + +#define IMSG_TAG "[tz_test_drv]" +#include +#include "ta_core_api.h" + +#define DRM_04_UUID \ + { 0x09010000, 0x0000, 0x0000, \ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} } +struct TEEC_Context xtest_isee_ctx_3000; +const struct TEEC_UUID isee_test_ta_uuid_3000 = DRM_04_UUID; + +#define Cache_line_size 32 +static inline void Flush_Dcache_By_Area(unsigned long start, unsigned long end) +{ +#ifdef CONFIG_ARM64 + __flush_dcache_area((void *)start, (end - start)); +#else + __cpuc_flush_dcache_area((void *)start, (end - start)); +#endif +} +static inline void Invalidate_Dcache_By_Area(unsigned long start, + unsigned long end) +{ +#ifdef CONFIG_ARM64 + uint64_t temp[2]; + + temp[0] = start; + temp[1] = end; + __asm__ volatile( + "ldr x0, [%[temp], #0]\n\t" + "ldr x1, [%[temp], #8]\n\t" + "mrs x3, ctr_el0\n\t" + "ubfm x3, x3, #16, #19\n\t" + "mov x2, #4\n\t" + "lsl x2, x2, x3\n\t" + "dsb sy\n\t" + "sub x3, x2, #1\n\t" + "bic x0, x0, x3\n\t" + /* invalidate D line / unified line */ + "1: dc ivac, x0\n\t" + "add x0, x0, x2\n\t" + "cmp x0, x1\n\t" + "b.lo 1b\n\t" + "dsb sy\n\t" + : : + [temp] "r" (temp) + : "x0", "x1", "x2", "x3", "memory"); +#else + __asm__ __volatile__ ("dsb" : : : "memory"); /* dsb */ + __asm__ __volatile__ ( + /* Invalidate Data Cache Line (using MVA) Register */ + "1: mcr p15, 0, %[i], c7, c6, 1\n" + " add %[i], %[i], %[clsz]\n" + " cmp %[i], %[end]\n" + " blo 1b\n" + : + [i] "=&r" (start) + : "0" ((unsigned long)start & (~(Cache_line_size - 1))), + [end] "r" (end), + [clsz] "i" (Cache_line_size) + : "memory"); + + /* invalidate btc */ + asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0) : "memory"); + __asm__ __volatile__ ("dsb" : : : "memory"); /* dsb */ + +#endif +} + +int xtest_isee_test_3030(void) +{ + uint32_t TEMP_BUFFER_TEST_SIZE = 4096; + unsigned int res; + struct TEEC_Session session = {0}; + struct TEEC_Operation op = {0}; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_3000, &session, + &isee_test_ta_uuid_3000, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + op.params[1].value.a = TEMP_BUFFER_TEST_SIZE; + op.params[1].value.b = 0; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_NONE, + TEEC_NONE); + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + DRV_CORE_API_CMD_MSEE_CLEAN_INVALIDATE_DCACHE_RANGE, + &op, &ret_orig)); + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_3040(void) +{ + uint32_t TEMP_BUFFER_TEST_SIZE = 4096; + unsigned int res; + struct TEEC_Session session = {0}; + unsigned char *temp_buffer = 0; + uint64_t temp_buffer_paddr = 0; + struct TEEC_Operation op = {0}; + uint32_t ret_orig; + uint32_t x[2]; + unsigned long addr_start; + + res = xtest_teec_open_session(&xtest_isee_ctx_3000, &session, + &isee_test_ta_uuid_3000, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)tz_malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto buffer_alloc_failed; + } + + MEMSET_UINT32(temp_buffer, TA_CORE_API_PARAM_TYPE_Test_PatternF, + TEMP_BUFFER_TEST_SIZE); + addr_start = (unsigned long)(temp_buffer); + Flush_Dcache_By_Area(addr_start, addr_start+TEMP_BUFFER_TEST_SIZE); + temp_buffer_paddr = virt_to_phys((void *)temp_buffer); + memcpy(x, &temp_buffer_paddr, sizeof(temp_buffer_paddr)); + op.params[0].value.a = x[0]; + op.params[0].value.b = x[1]; + op.params[1].value.a = TEMP_BUFFER_TEST_SIZE; + op.params[1].value.b = 0; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_NONE, + TEEC_NONE); + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + if (!ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + DRV_CORE_API_CMD_MSEE_CLEAN_DCACHE_RANGE, + &op, &ret_orig))) + goto buffer_alloc_failed; + + Invalidate_Dcache_By_Area(addr_start, + addr_start + TEMP_BUFFER_TEST_SIZE); + if (!ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer, + TA_CORE_API_PARAM_TYPE_Test_Pattern5, + TEMP_BUFFER_TEST_SIZE))) + case_res = DRV_ERROR_MSEE_CLEAN_DCACHE_RANGE; + +buffer_alloc_failed: + TEEC_CloseSession(&session); + if (temp_buffer) + tz_free(temp_buffer, TEMP_BUFFER_TEST_SIZE); + return case_res; +} + +int xtest_isee_test_3050(void) +{ + unsigned int res; + struct TEEC_Session session = {0}; + struct TEEC_Operation op = {0}; + uint32_t ret_orig; + + res = xtest_teec_open_session(&xtest_isee_ctx_3000, &session, + &isee_test_ta_uuid_3000, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + /* + * 1. map register 0x08000000 + * 2. read offset 0x0, 0x4, 0x8, 0xC + */ + if (!ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST1, + &op, &ret_orig))) + return DRV_ERROR_MSEE_MAP_REGION_TEST1; + + case_res = TEEC_SUCCESS; + + TEEC_CloseSession(&session); + return case_res; +} + +int xtest_isee_test_3051(void) +{ + uint32_t TEMP_BUFFER_TEST_SIZE = 4096; + unsigned int res; + struct TEEC_Session session = {0}; + unsigned char *temp_buffer = 0; + uint64_t temp_buffer_paddr = 0; + struct TEEC_Operation op = {0}; + uint32_t ret_orig; + uint32_t x[2]; + unsigned long addr_start; + + res = xtest_teec_open_session(&xtest_isee_ctx_3000, &session, + &isee_test_ta_uuid_3000, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)tz_malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto exit; + } + + /* + * 1. kernel CA alloc memory and write data + * 2. pass physical address to ta/drv + * 3. map read only + * 4. compare data + */ + MEMSET_UINT32(temp_buffer, TA_CORE_API_PARAM_TYPE_Test_PatternF, + TEMP_BUFFER_TEST_SIZE); + addr_start = (unsigned long)(temp_buffer); + Flush_Dcache_By_Area(addr_start, addr_start+TEMP_BUFFER_TEST_SIZE); + memset(&op, 0, sizeof(op)); + temp_buffer_paddr = virt_to_phys((void *)temp_buffer); + memcpy(x, &temp_buffer_paddr, sizeof(temp_buffer_paddr)); + op.params[0].value.a = x[0]; + op.params[0].value.b = x[1]; + op.params[1].value.a = TEMP_BUFFER_TEST_SIZE; + op.params[1].value.b = 0; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_NONE, + TEEC_NONE); + + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST2, + &op, &ret_orig))) + goto exit; + + case_res = TEEC_SUCCESS; +exit: + TEEC_CloseSession(&session); + if (temp_buffer) + tz_free(temp_buffer, TEMP_BUFFER_TEST_SIZE); + return case_res; +} + +int xtest_isee_test_3052(void) +{ + uint32_t TEMP_BUFFER_TEST_SIZE = 4096; + unsigned int res; + struct TEEC_Session session = {0}; + unsigned char *temp_buffer = 0; + uint64_t temp_buffer_paddr = 0; + struct TEEC_Operation op = {0}; + uint32_t ret_orig; + uint32_t x[2]; + unsigned long addr_start; + + res = xtest_teec_open_session(&xtest_isee_ctx_3000, &session, + &isee_test_ta_uuid_3000, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)tz_malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto exit; + } + + /* + * 1. kernel CA alloc memory and write data + * 2. pass physical address to ta/drv + * 3. map write only + * 4. compare should NOT match + */ + MEMSET_UINT32(temp_buffer, TA_CORE_API_PARAM_TYPE_Test_PatternE, + TEMP_BUFFER_TEST_SIZE); + + addr_start = (unsigned long)(temp_buffer); + Flush_Dcache_By_Area(addr_start, addr_start+TEMP_BUFFER_TEST_SIZE); + memset(&op, 0, sizeof(op)); + temp_buffer_paddr = virt_to_phys((void *)temp_buffer); + memcpy(x, &temp_buffer_paddr, sizeof(temp_buffer_paddr)); + op.params[0].value.a = x[0]; + op.params[0].value.b = x[1]; + op.params[1].value.a = TEMP_BUFFER_TEST_SIZE; + op.params[1].value.b = 0; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_NONE, + TEEC_NONE); + + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST3, + &op, &ret_orig))) + goto exit; + + case_res = TEEC_SUCCESS; +exit: + TEEC_CloseSession(&session); + if (temp_buffer) + tz_free(temp_buffer, TEMP_BUFFER_TEST_SIZE); + return case_res; +} + +int xtest_isee_test_3053(void) +{ + uint32_t TEMP_BUFFER_TEST_SIZE = 4096; + unsigned int res; + struct TEEC_Session session = {0}; + unsigned char *temp_buffer = 0; + uint64_t temp_buffer_paddr = 0; + struct TEEC_Operation op = {0}; + uint32_t ret_orig; + uint32_t x[2]; + unsigned long addr_start; + + res = xtest_teec_open_session(&xtest_isee_ctx_3000, &session, + &isee_test_ta_uuid_3000, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(res)) + return res; + + temp_buffer = (unsigned char *)tz_malloc(TEMP_BUFFER_TEST_SIZE); + if (!temp_buffer) { + (void)ADBG_EXPECT_TEEC_SUCCESS(TEEC_ERROR_OUT_OF_MEMORY); + goto exit; + } + + /* + * 1. kernel CA alloc memory + * 2. pass physical address to ta/drv + * 3. map write only and write data + * 4. kernel CA compare data + */ + MEMSET_UINT32(temp_buffer, TA_CORE_API_PARAM_TYPE_Test_PatternD, + TEMP_BUFFER_TEST_SIZE); + addr_start = (unsigned long)(temp_buffer); + Flush_Dcache_By_Area(addr_start, addr_start+TEMP_BUFFER_TEST_SIZE); + memset(&op, 0, sizeof(op)); + temp_buffer_paddr = virt_to_phys((void *)temp_buffer); + memcpy(x, &temp_buffer_paddr, sizeof(temp_buffer_paddr)); + op.params[0].value.a = x[0]; + op.params[0].value.b = x[1]; + op.params[1].value.a = TEMP_BUFFER_TEST_SIZE; + op.params[1].value.b = 0; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_NONE, + TEEC_NONE); + + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]temp_buffer_paddr=0x%llx\n", + __func__, temp_buffer_paddr); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + IMSG_DEBUG("[%s]TEMP_BUFFER_TEST_SIZE=0x%x\n", + __func__, TEMP_BUFFER_TEST_SIZE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(TEEC_InvokeCommand(&session, + DRV_CORE_API_CMD_MSEE_MMAP_REGION_TEST4, + &op, &ret_orig))) + goto exit; + + Invalidate_Dcache_By_Area(addr_start, + addr_start + TEMP_BUFFER_TEST_SIZE); + + if (!ADBG_EXPECT_TEEC_RESULT(TA_CORE_API_PARAM_TYPE_PATTERN_MATCH, + ARRAY_MATCH_PATTERN(temp_buffer, + TA_CORE_API_PARAM_TYPE_Test_PatternC, + TEMP_BUFFER_TEST_SIZE))) + case_res = DRV_ERROR_MSEE_MAP_REGION_TEST4; + + case_res = TEEC_SUCCESS; +exit: + TEEC_CloseSession(&session); + if (temp_buffer) + tz_free(temp_buffer, TEMP_BUFFER_TEST_SIZE); + return case_res; +} + diff --git a/drivers/tee/teei/300/tests/xtest_main.c b/drivers/tee/teei/300/tests/xtest_main.c new file mode 100644 index 000000000000..4478572bcd0f --- /dev/null +++ b/drivers/tee/teei/300/tests/xtest_main.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMSG_TAG "[tz_test_x]" +#include +/* errors defined and used by TA/DRV test cases only */ +#include "teei_internal_types.h" +#include +#include "xtest_main.h" +int my_run_case(int id) +{ +#define JECASE(src, tgt) \ +{ \ + if (src == tgt) { \ + ret = _CASE(tgt)(); \ + } \ +} + + int ret = TEE_ERROR_UNKNOWN_COMMAND; + + case_res = 0; + JECASE(id, 1001); + JECASE(id, 1002); + JECASE(id, 1003); + JECASE(id, 1004); + JECASE(id, 1005); + JECASE(id, 1010); + JECASE(id, 1011); + JECASE(id, 1012); + JECASE(id, 1013); + JECASE(id, 1020); + JECASE(id, 1021); + JECASE(id, 1022); + JECASE(id, 1023); + JECASE(id, 1030); + JECASE(id, 1031); + JECASE(id, 1032); + JECASE(id, 1033); + JECASE(id, 1034); + JECASE(id, 1035); + JECASE(id, 1036); + JECASE(id, 1037); + JECASE(id, 1040); + JECASE(id, 1041); + JECASE(id, 1042); + JECASE(id, 1043); + JECASE(id, 1044); + JECASE(id, 1045); + JECASE(id, 1046); + JECASE(id, 1047); + JECASE(id, 1100); + JECASE(id, 1101); + JECASE(id, 1102); + JECASE(id, 1200); + JECASE(id, 1201); + JECASE(id, 1203); + JECASE(id, 1204); + JECASE(id, 1206); + JECASE(id, 1207); + JECASE(id, 1208); + JECASE(id, 1209); + JECASE(id, 1210); + JECASE(id, 1212); + JECASE(id, 1213); + JECASE(id, 1214); + JECASE(id, 1215); + JECASE(id, 1216); + JECASE(id, 1217); + JECASE(id, 1218); + JECASE(id, 1219); + JECASE(id, 1300); + JECASE(id, 1301); + JECASE(id, 1302); + JECASE(id, 1303); + JECASE(id, 1304); + JECASE(id, 1305); + JECASE(id, 1306); + JECASE(id, 1307); + JECASE(id, 1308); + JECASE(id, 1400); + JECASE(id, 1401); + JECASE(id, 1402); + JECASE(id, 1403); + JECASE(id, 1404); + JECASE(id, 1405); + JECASE(id, 1406); + JECASE(id, 1407); + JECASE(id, 1408); + JECASE(id, 1409); + JECASE(id, 1410); + JECASE(id, 1411); + JECASE(id, 1412); + JECASE(id, 1800); + JECASE(id, 1801); + JECASE(id, 1802); + JECASE(id, 1803); + JECASE(id, 3030); + JECASE(id, 3040); + JECASE(id, 3050); + JECASE(id, 3051); + JECASE(id, 3052); + JECASE(id, 3053); + return ret; +} + +#define BTA_LOADER_HOSTNAME "bta_loader" + +int kernel_ca_test(struct tzdrv_test_data *param) +{ + int ret; + int cmd = param->params[0]; + + TEEC_InitializeContext(BTA_LOADER_HOSTNAME, &xtest_isee_ctx_1000); + ret = my_run_case(cmd - 1000); + TEEC_FinalizeContext(&xtest_isee_ctx_1000); + IMSG_INFO("%s (%d)=(0x%x)\n", __func__, cmd, ret); + return ret; +} + +int secure_drv_test(struct tzdrv_test_data *param) +{ + int ret; + int cmd = param->params[0]; + + TEEC_InitializeContext(BTA_LOADER_HOSTNAME, &xtest_isee_ctx_3000); + ret = my_run_case(cmd); + TEEC_FinalizeContext(&xtest_isee_ctx_3000); + IMSG_INFO("%s (%d)=(0x%x)\n", __func__, cmd, ret); + return ret; +} diff --git a/drivers/tee/teei/300/tests/xtest_main.h b/drivers/tee/teei/300/tests/xtest_main.h new file mode 100644 index 000000000000..97d60ba18bc4 --- /dev/null +++ b/drivers/tee/teei/300/tests/xtest_main.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#ifndef TZ_XTEST_MAIN_H +#define TZ_XTEST_MAIN_H + +#include "main.h" + +extern int case_res; +extern struct TEEC_Context xtest_isee_ctx_1000; +extern struct TEEC_Context xtest_isee_ctx_3000; +#define _CASECMDSTR(prefix_cmd) #prefix_cmd +#define _CASECMD(prefix, cmd) prefix##cmd +#define _CASE(cmd) _CASECMD(xtest_isee_test_, cmd) +#define DECLARECASE(id) int _CASE(id)(void) +DECLARECASE(1001); +DECLARECASE(1002); +DECLARECASE(1003); +DECLARECASE(1004); +DECLARECASE(1005); +DECLARECASE(1010); +DECLARECASE(1011); +DECLARECASE(1012); +DECLARECASE(1013); +DECLARECASE(1020); +DECLARECASE(1021); +DECLARECASE(1022); +DECLARECASE(1023); +DECLARECASE(1030); +DECLARECASE(1031); +DECLARECASE(1032); +DECLARECASE(1033); +DECLARECASE(1034); +DECLARECASE(1035); +DECLARECASE(1036); +DECLARECASE(1037); +DECLARECASE(1040); +DECLARECASE(1041); +DECLARECASE(1042); +DECLARECASE(1043); +DECLARECASE(1044); +DECLARECASE(1045); +DECLARECASE(1046); +DECLARECASE(1047); +DECLARECASE(1100); +DECLARECASE(1101); +DECLARECASE(1102); +DECLARECASE(1200); +DECLARECASE(1201); +DECLARECASE(1203); +DECLARECASE(1204); +DECLARECASE(1206); +DECLARECASE(1207); +DECLARECASE(1208); +DECLARECASE(1209); +DECLARECASE(1210); +DECLARECASE(1212); +DECLARECASE(1213); +DECLARECASE(1214); +DECLARECASE(1215); +DECLARECASE(1216); +DECLARECASE(1217); +DECLARECASE(1218); +DECLARECASE(1219); +DECLARECASE(1300); +DECLARECASE(1301); +DECLARECASE(1302); +DECLARECASE(1303); +DECLARECASE(1304); +DECLARECASE(1305); +DECLARECASE(1306); +DECLARECASE(1307); +DECLARECASE(1308); +DECLARECASE(1400); +DECLARECASE(1401); +DECLARECASE(1402); +DECLARECASE(1403); +DECLARECASE(1404); +DECLARECASE(1405); +DECLARECASE(1406); +DECLARECASE(1407); +DECLARECASE(1408); +DECLARECASE(1409); +DECLARECASE(1410); +DECLARECASE(1411); +DECLARECASE(1412); +DECLARECASE(1800); +DECLARECASE(1801); +DECLARECASE(1802); +DECLARECASE(1803); + +DECLARECASE(3030); +DECLARECASE(3040); +DECLARECASE(3050); +DECLARECASE(3051); +DECLARECASE(3052); +DECLARECASE(3053); + +#endif diff --git a/drivers/tee/teei/300/tz_dcih/Makefile b/drivers/tee/teei/300/tz_dcih/Makefile new file mode 100644 index 000000000000..09ccf9befb32 --- /dev/null +++ b/drivers/tee/teei/300/tz_dcih/Makefile @@ -0,0 +1,15 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +obj-$(CONFIG_MICROTRUST_VFS_DRIVER) += tz_dcih.o +obj-$(CONFIG_MICROTRUST_VFS_DRIVER) += tz_dcih_test.o +ccflags-y += -D DEBUG_DO -fno-pic -Werror diff --git a/drivers/tee/teei/300/tz_dcih/tz_dcih.c b/drivers/tee/teei/300/tz_dcih/tz_dcih.c new file mode 100644 index 000000000000..bbef69bb9a4f --- /dev/null +++ b/drivers/tee/teei/300/tz_dcih/tz_dcih.c @@ -0,0 +1,315 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include + +#include +#include "tz_dcih.h" +#include + +#define IMSG_TAG "[tz_dcih]" +#include + +static LIST_HEAD(dcih_register_list); + + +static struct dcih_reg_info *find_dcih_reg_info(unsigned int driver_id) +{ + struct dcih_reg_info *info; + + list_for_each_entry(info, &dcih_register_list, list) { + if (info->drv_info->driver_id == driver_id) + return info; + } + + return NULL; +} + +static int register_share_buffer_to_driver(struct dcih_reg_info *info) +{ + struct TEEC_Operation op = {0}; + unsigned int returnOrigin; + int res; + struct ut_drv_entry *ut_drv = info->drv_info; + struct ut_drv_param driver_param; + + driver_param.cmd_id = UT_DRV_REGISTER_DCI_BUFFER; + driver_param.u.reg_dci_buf.phy_addr = info->phy_addr; + driver_param.u.reg_dci_buf.buf_size = info->buf_size; + + IMSG_DEBUG("register dci buffer, phy_addr 0x%lx size 0x%x\n", + info->phy_addr, info->buf_size); + + prepare_params(&op, (void *)&driver_param, sizeof(struct ut_drv_param)); + + res = TEEC_InvokeCommand(&ut_drv->session, driver_param.cmd_id, + &op, &returnOrigin); + if (res != TEEC_SUCCESS) { + int ret = get_result(&op); + + IMSG_ERROR("failed to register dci buffer, res 0x%x ret 0x%x\n", + res, ret); + return ret; + } + + return 0; +} + +static int noitfy_driver_to_free_share_buffer(struct dcih_reg_info *info) +{ + struct TEEC_Operation op = {0}; + unsigned int returnOrigin; + int res; + struct ut_drv_entry *ut_drv = info->drv_info; + struct ut_drv_param driver_param; + + driver_param.cmd_id = UT_DRV_FREE_DCI_BUFFER; + driver_param.u.reg_dci_buf.phy_addr = info->phy_addr; + driver_param.u.reg_dci_buf.buf_size = info->buf_size; + + IMSG_DEBUG("free dci buffer, phy_addr 0x%lx size 0x%x\n", + info->phy_addr, info->buf_size); + + prepare_params(&op, (void *)&driver_param, sizeof(struct ut_drv_param)); + + res = TEEC_InvokeCommand(&ut_drv->session, driver_param.cmd_id, + &op, &returnOrigin); + if (res != TEEC_SUCCESS) { + int ret = get_result(&op); + + IMSG_ERROR("failed to free dci buffer, res 0x%x ret 0x%x\n", + res, ret); + return ret; + } + + return 0; +} + +int tz_create_share_buffer(unsigned int driver_id, unsigned int buff_size) +{ + struct dcih_reg_info *info; + struct ut_drv_entry *drv_info; + unsigned long tmp_addr; + int ret; + + if (buff_size > MAX_DCIH_BUF_SIZE) { + IMSG_ERROR("buffer size too large!\n"); + return -EINVAL; + } + + info = find_dcih_reg_info(driver_id); + if (info) { + IMSG_INFO("share buffer already exist, driver_id 0x%x\n", + driver_id); + return 0; + } + + drv_info = find_ut_drv_entry_by_driver_id(driver_id); + if (!drv_info) { + IMSG_ERROR("driver (0x%x) does not exist\n", driver_id); + return -EINVAL; + } + + info = kzalloc(sizeof(struct dcih_reg_info), GFP_KERNEL); + if (!info) { + IMSG_ERROR("failed to allocate memory for dcih_reg_info\n"); + return -ENOMEM; + } + +#ifdef UT_DMA_ZONE + tmp_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(ROUND_UP(buff_size, SZ_4K))); +#else + tmp_addr = __get_free_pages(GFP_KERNEL, + get_order(ROUND_UP(buff_size, SZ_4K))); +#endif + if ((void *)tmp_addr == NULL) { + IMSG_ERROR("failed to get free pages from linux kernel\n"); + ret = -ENOMEM; + goto fail; + } + + info->drv_info = drv_info; + /* will dynamically assign this value by dcih behavior */ + info->mode = DCIH_MODE_INVALID; + info->virt_addr = tmp_addr; + info->phy_addr = virt_to_phys((void *)tmp_addr); + info->buf_size = buff_size; + init_completion(&info->wait_notify); + init_completion(&info->wait_result); + + ret = register_share_buffer_to_driver(info); + if (ret < 0) + goto fail; + + list_add_tail(&info->list, &dcih_register_list); + + return 0; + +fail: + if (tmp_addr) + free_pages(tmp_addr, get_order(ROUND_UP(buff_size, SZ_4K))); + + kfree(info); + return ret; +} + +int tz_free_share_buffer(unsigned int driver_id) +{ + struct dcih_reg_info *info; + int ret; + + info = find_dcih_reg_info(driver_id); + if (!info) { + IMSG_ERROR("driver_id (0x%x) does not exist\n", driver_id); + return -EINVAL; + } + + ret = noitfy_driver_to_free_share_buffer(info); + if (ret < 0) + return ret; + + if (info->virt_addr) + free_pages(info->virt_addr, + get_order(ROUND_UP(info->buf_size, SZ_4K))); + + list_del(&info->list); + kfree(info); + + return 0; +} + +unsigned long tz_get_share_buffer(unsigned int driver_id) +{ + struct dcih_reg_info *info; + + info = find_dcih_reg_info(driver_id); + if (!info) { + IMSG_ERROR("driver_id (0x%x) does not exist\n", driver_id); + return (unsigned long)NULL; + } + + return info->virt_addr; +} + +int tz_notify_driver(unsigned int driver_id) +{ + struct dcih_reg_info *info; + + info = find_dcih_reg_info(driver_id); + if (!info) { + IMSG_ERROR("driver_id (0x%x) does not exist\n", driver_id); + return -EINVAL; + } + + /* + * If DCI handler call tz_notify_driver() + * before tz_wait_for_notification(), + * we will treat it as the master of the DCI channel. + */ + if (info->mode == DCIH_MODE_INVALID) + info->mode = DCIH_MODE_MASTER; + + if (info->mode == DCIH_MODE_MASTER) { + struct TEEC_Operation op = {0}; + unsigned int returnOrigin; + struct ut_drv_entry *ut_drv = info->drv_info; + struct ut_drv_param driver_param; + int res; + + driver_param.cmd_id = UT_DRV_NOTIFY_FROM_REE; + /* TODO: parameter 'notify_from_ree' does not support yet */ + driver_param.u.notify_from_ree.cmd = 0; + driver_param.u.notify_from_ree.data = 0; + + prepare_params(&op, (void *)&driver_param, + sizeof(struct ut_drv_param)); + + IMSG_DEBUG("dci master: start notify TEE driver\n"); + res = TEEC_InvokeCommand(&ut_drv->session, driver_param.cmd_id, + &op, &returnOrigin); + if (res != TEEC_SUCCESS) { + int ret = get_result(&op); + + IMSG_ERROR("failed to notify TEE driver\n"); + IMSG_ERROR("(0x%x)res 0x%x ret 0x%x\n", + driver_id, res, ret); + return ret; + } + } else { + IMSG_DEBUG("dci slave: handler is done"); + complete(&info->wait_result); + } + + return 0; +} + +int tz_wait_for_notification(unsigned int driver_id) +{ + struct dcih_reg_info *info; + int ret; + + info = find_dcih_reg_info(driver_id); + if (!info) { + IMSG_ERROR("driver_id (0x%x) does not exist\n", driver_id); + return -EINVAL; + } + + IMSG_DEBUG("wait for notify by TEE driver\n"); + /* + * If DCI handler call tz_wait_for_notification() + * before tz_notify_driver(), + * we will treat it as the slave of the DCI channel. + */ + if (info->mode == DCIH_MODE_INVALID) + info->mode = DCIH_MODE_SLAVE; + + if (info->mode == DCIH_MODE_SLAVE) { + IMSG_DEBUG("dci slave: wait for TEE driver notification\n"); + ret = wait_for_completion_interruptible(&info->wait_notify); + if (ret) { + IMSG_INFO("interrupted by signal\n"); + return ret; + } + + IMSG_DEBUG("dci slave:received notification from TEE driver\n"); + return 0; + } + + IMSG_ERROR("dci master: no need to wait for notification\n"); + return -EINVAL; +} + +int tz_notify_ree_handler(unsigned int driver_id) +{ + struct dcih_reg_info *info; + int ret; + + info = find_dcih_reg_info(driver_id); + if (!info) { + IMSG_ERROR("driver_id (0x%x) does not exist\n", driver_id); + return -EINVAL; + } + + complete(&info->wait_notify); + + ret = wait_for_completion_interruptible_timeout(&info->wait_result, + msecs_to_jiffies(5000)); + if (ret == -ERESTARTSYS) { + IMSG_WARN("TEE driver: interrupted by signal\n"); + return ret; + } else if (ret == 0) { + IMSG_WARN("TEE driver: wait for result timeout\n"); + return -EAGAIN; + } + + IMSG_DEBUG("TEE driver: dci handler is done\n"); + + return 0; +} diff --git a/drivers/tee/teei/300/tz_dcih/tz_dcih.h b/drivers/tee/teei/300/tz_dcih/tz_dcih.h new file mode 100644 index 000000000000..d082e29535b1 --- /dev/null +++ b/drivers/tee/teei/300/tz_dcih/tz_dcih.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef _TZ_DCIH_H_ +#define _TZ_DCIH_H_ + +#include + +#include + +#define MAX_DCIH_BUF_SIZE SZ_4K + +enum { + DCIH_MODE_SLAVE, + DCIH_MODE_MASTER, + DCIH_MODE_INVALID, +}; + +struct dcih_reg_info { + struct ut_drv_entry *drv_info; + uint32_t mode; + uint32_t buf_size; + unsigned long virt_addr; + unsigned long phy_addr; + struct completion wait_notify; /* only for slave mode */ + struct completion wait_result; /* only for slave mode */ + struct list_head list; +}; + +void init_dcih_service(void); +int tz_create_share_buffer(unsigned int driver_id, unsigned int buff_size); +int tz_free_share_buffer(unsigned int driver_id); +int tz_notify_ree_handler(unsigned int driver_id); + +#endif diff --git a/drivers/tee/teei/300/tz_dcih/tz_dcih_test.c b/drivers/tee/teei/300/tz_dcih/tz_dcih_test.c new file mode 100644 index 000000000000..b20bc53129c3 --- /dev/null +++ b/drivers/tee/teei/300/tz_dcih/tz_dcih_test.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tz_dcih.h" +#include "tz_dcih_test.h" +#define IMSG_TAG "[tz_dcih_test]" +#include +#include + +static struct task_struct *test_notify_thread; +bool start_notify_test; +static struct task_struct *test_wait_notify_thread; +bool start_wait_notify_test; +static DEFINE_MUTEX(test_status_mutex); + +static DECLARE_COMPLETION(thread_start); +static DECLARE_COMPLETION(thread_finish); + +static int dci_greeting_test(uint32_t driver_id) +{ + struct dci_message *msg; + uint32_t tmp_value; + int ret; + int num_item = 0; + + msg = (struct dci_message *)tz_get_share_buffer(driver_id); + + memset(msg, 0, sizeof(struct dci_message)); + + msg->cmd = GREETING; + snprintf(msg->req_data, sizeof(msg->req_data), + "Say Hello to 0x%x", driver_id); + + ret = tz_notify_driver(driver_id); + if (ret < 0) { + IMSG_ERROR("failed to notify secure driver, ret %d\n", ret); + goto exit; + } + + num_item = sscanf(msg->res_data, "Hello 0x%x", &tmp_value); + if (num_item != 1 || tmp_value != driver_id) { + IMSG_ERROR("return unexpected data, res_data [%s]\n", + msg->res_data); + ret = -EINVAL; + } + +exit: + return ret; +} + +static int dci_bit_op_not_test(uint32_t driver_id) +{ + struct dci_message *msg; + int ret; + int i; + + msg = (struct dci_message *)tz_get_share_buffer(driver_id); + + memset(msg, 0, sizeof(struct dci_message)); + + msg->cmd = BIT_OP_NOT; + for (i = 0; i < MAX_BUF_SIZE; i++) + msg->req_data[i] = (uint8_t)(i & 0xff); + + ret = tz_notify_driver(driver_id); + if (ret < 0) { + IMSG_ERROR("failed to notify secure driver, ret %d\n", ret); + goto exit; + } + + for (i = 0; i < MAX_BUF_SIZE; i++) { + if (msg->res_data[i] != (uint8_t)(~msg->req_data[i])) { + IMSG_ERROR("return unexpected data:\n"); + IMSG_ERROR("res_data[%d] expect 0x%02x actual 0x%02x\n", + i, (uint8_t)(~msg->req_data[i]), + msg->res_data[i]); + ret = -EINVAL; + break; + } + } + +exit: + return ret; +} + +static int notify_driver_test(void *data) +{ + uint32_t driver_id = (uintptr_t)data; + int ret; + + IMSG_DEBUG("starting notify test thread, driver_id 0x%x\n", driver_id); + + allow_signal(SIGTERM); + + ret = tz_create_share_buffer(driver_id, MAX_DCIH_BUF_SIZE); + if (ret < 0) { + IMSG_ERROR("failed to create dci share buffer\n"); + goto exit; + } + + ret = dci_greeting_test(driver_id); + if (ret) + goto exit; + + ret = dci_bit_op_not_test(driver_id); + +exit: + tz_free_share_buffer(driver_id); + + complete(&thread_finish); + + IMSG_DEBUG("notify test is finished, wait for terminate signal...\n"); + while (!kthread_should_stop()) + msleep(50); + + IMSG_DEBUG("Got terminate signal, going to stop thread\n"); + return ret; +} + +static int process_dci_msg(uint32_t driver_id) +{ + struct dci_message *msg = NULL; + uint32_t tmp_value; + int i; + int num_item; + int ret = 0; + + msg = (struct dci_message *)tz_get_share_buffer(driver_id); + + IMSG_DEBUG("cmd %d\n", msg->cmd); + + switch (msg->cmd) { + case GREETING: + num_item = sscanf(msg->req_data, "Say Hello to 0x%x", + &tmp_value); + if (num_item != 1) { + IMSG_ERROR("no item found in sscanf\n"); + ret = -EINVAL; + break; + } + snprintf(msg->res_data, sizeof(msg->res_data), + "Hello 0x%x", tmp_value); + break; + case BIT_OP_NOT: + for (i = 0; i < MAX_BUF_SIZE; i++) + msg->res_data[i] = (uint8_t)(~msg->req_data[i]); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int wait_driver_notify_test(void *data) +{ + uint32_t driver_id = (uintptr_t)data; + int ret; + + IMSG_DEBUG("starting wait notify test thread, driver_id 0x%x\n", + driver_id); + + allow_signal(SIGTERM); + + ret = tz_create_share_buffer(driver_id, MAX_DCIH_BUF_SIZE); + if (ret < 0) { + IMSG_ERROR("failed to create dci share buffer\n"); + complete(&thread_start); + goto exit; + } + + complete(&thread_start); + + while (!kthread_should_stop()) { + ret = tz_wait_for_notification(driver_id); + if (ret < 0) { + if (ret == -ERESTARTSYS) { + IMSG_INFO("waiting was interrupted\n"); + ret = 0; + } else + IMSG_ERROR("failed to waiting, ret %d\n", ret); + break; + } + + ret = process_dci_msg(driver_id); + if (ret < 0) + IMSG_ERROR("failed to process dci message, %d\n", ret); + + ret = tz_notify_driver(driver_id); + if (ret < 0) { + IMSG_ERROR("failed to notify secure driver, %d\n", ret); + break; + } + } + +exit: + tz_free_share_buffer(driver_id); + + IMSG_DEBUG("Got terminate signal, going to stop thread\n"); + return ret; +} + +void start_dcih_notify_test(uint32_t driver_id) +{ + uintptr_t data = driver_id; + + mutex_lock(&test_status_mutex); + + if (start_notify_test) { + IMSG_ERROR("test thread is still running\n"); + goto exit; + } + + start_notify_test = true; + + test_notify_thread = kthread_run(notify_driver_test, + (void *)data, "dcih_notify_test_thread"); + if (IS_ERR(test_notify_thread)) { + IMSG_ERROR("failed to create dcih test notify thread\n"); + test_notify_thread = NULL; + start_notify_test = false; + goto exit; + } + + wait_for_completion(&thread_finish); + +exit: + mutex_unlock(&test_status_mutex); +} + +int get_dcih_notify_test_result(void) +{ + int ret = -EINVAL; + + mutex_lock(&test_status_mutex); + + start_notify_test = false; + if (test_notify_thread) { + send_sig(SIGTERM, test_notify_thread, 0); + ret = kthread_stop(test_notify_thread); + test_notify_thread = NULL; + } + + mutex_unlock(&test_status_mutex); + + return ret; +} + +void start_dcih_wait_notify_test(uint32_t driver_id) +{ + uintptr_t data = driver_id; + + mutex_lock(&test_status_mutex); + + if (start_wait_notify_test) { + IMSG_ERROR("test thread is still running\n"); + goto exit; + } + + start_wait_notify_test = true; + + test_wait_notify_thread = kthread_run(wait_driver_notify_test, + (void *)data, "dcih_wait_notify_test_thread"); + if (IS_ERR(test_wait_notify_thread)) { + IMSG_ERROR("create dcih test wait notify thread failed\n"); + test_wait_notify_thread = NULL; + start_wait_notify_test = false; + goto exit; + } + + wait_for_completion(&thread_start); + +exit: + mutex_unlock(&test_status_mutex); + +} + +int get_dcih_wait_notify_test_result(void) +{ + int ret = -EINVAL; + + mutex_lock(&test_status_mutex); + + start_wait_notify_test = false; + if (test_wait_notify_thread) { + send_sig(SIGTERM, test_wait_notify_thread, 0); + ret = kthread_stop(test_wait_notify_thread); + test_wait_notify_thread = NULL; + } + + mutex_unlock(&test_status_mutex); + + return ret; +} diff --git a/drivers/tee/teei/300/tz_dcih/tz_dcih_test.h b/drivers/tee/teei/300/tz_dcih/tz_dcih_test.h new file mode 100644 index 000000000000..0435fe563961 --- /dev/null +++ b/drivers/tee/teei/300/tz_dcih/tz_dcih_test.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef _TZ_DCIH_TEST_H_ +#define _TZ_DCIH_TEST_H_ + +#define MAX_BUF_SIZE 512 + +enum { + GREETING, + BIT_OP_NOT, +}; + +struct dci_message { + uint32_t cmd; + uint8_t req_data[MAX_BUF_SIZE]; + uint8_t res_data[MAX_BUF_SIZE]; +}; + +void start_dcih_notify_test(uint32_t driver_id); +int get_dcih_notify_test_result(void); +void start_dcih_wait_notify_test(uint32_t driver_id); +int get_dcih_wait_notify_test_result(void); + +extern int send_sig(int sig, struct task_struct *p, int priv); + +#endif diff --git a/drivers/tee/teei/300/tz_driver/Makefile b/drivers/tee/teei/300/tz_driver/Makefile new file mode 100644 index 000000000000..01a6100dc108 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/Makefile @@ -0,0 +1,32 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +#include $(srctree)/drivers/misc/mediatek/Makefile.custom + +ccflags-y += -I$(src) -I$(src)/include +ccflags-y += -I$(srctree) + +ifeq ($(CONFIG_MTK_TEE_SANITY),y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/tee_sanity/ +endif + +teei-objs += teei_client_main.o +teei-objs += fdrv.o +teei-objs += backward_driver.o irq_register.o notify_queue.o teei_fp.o teei_smc_call.o tz_log.o switch_queue.o teei_keymaster.o teei_cancel_cmd.o teei_client_transfer_data.o +teei-objs += sysfs.o teei_task_link.o + +obj-$(CONFIG_MICROTRUST_TZ_DRIVER) += teei.o + +ccflags-$(CONFIG_MTK_ENG_BUILD) += -DENABLED_TEEI_BOOT_LOG + +ccflags-y += -Wno-error +ccflags-y += -D UT_DMA_ZONE diff --git a/drivers/tee/teei/300/tz_driver/backward_driver.c b/drivers/tee/teei/300/tz_driver/backward_driver.c new file mode 100644 index 000000000000..ffa9a25b8a6a --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/backward_driver.c @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include "nt_smc_call.h" +#include "backward_driver.h" +#include "teei_id.h" +#include "sched_status.h" +#include "utdriver_macro.h" +#include "teei_log.h" +#include "teei_common.h" +#include "switch_queue.h" +#include "teei_client_main.h" +#include +#include +#include +#include "teei_task_link.h" + +#define IMSG_TAG "[tz_driver]" +#include + +#define GET_UPTIME (1) +#define GET_SYSTIME (0) + +struct bdrv_call_struct { + int bdrv_call_type; + struct service_handler *handler; + int retVal; +}; + +static long register_shared_param_buf(struct service_handler *handler); +unsigned char *daulOS_VFS_share_mem; +unsigned char *vfs_flush_address; +struct service_handler reetime; +struct service_handler vfs_handler; +static struct completion teei_bdrv_comp; + + +static long register_shared_param_buf(struct service_handler *handler) +{ + long retVal = 0; + + if (handler->size > VDRV_MAX_SIZE) { + IMSG_ERROR("[%s][%d]: The vDrv buffer is too large.\n", + __FILE__, __LINE__); + return -EINVAL; + } + +#ifdef UT_DMA_ZONE + handler->param_buf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(ROUND_UP(handler->size, SZ_4K))); +#else + handler->param_buf = (void *)__get_free_pages(GFP_KERNEL, + get_order(ROUND_UP(handler->size, SZ_4K))); +#endif + if ((unsigned char *)(handler->param_buf) == NULL) { + IMSG_ERROR("[%s][%d]: kmalloc vdrv_buffer failed.\n", + __FILE__, __LINE__); + return -ENOMEM; + } + + retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__); + goto free_memory; + } + + retVal = add_nq_entry(TEEI_CREAT_BDRV, handler->sysno, + (unsigned long long)(&boot_sema), + virt_to_phys((void *)(handler->param_buf)), + handler->size, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add one nq to n_t_buffer\n"); + goto free_memory; + } + + teei_notify_switch_fn(); + + down(&boot_sema); + + return 0; + +free_memory: + /* Release the resource and return. */ + free_pages((unsigned long)(handler->param_buf), + get_order(ROUND_UP(handler->size, SZ_4K))); + handler->param_buf = NULL; + + return retVal; +} + +/******************************TIME**************************************/ +static long reetime_init(struct service_handler *handler) +{ + return 0; +} + +static void reetime_deinit(struct service_handler *handler) +{ +} + +static int reetime_handle(struct NQ_entry *entry) +{ + struct timespec tp; + struct timeval tv; + int tv_sec; + int tv_usec; + unsigned long long block_p = 0; + unsigned long long time_type = 0; + int retVal = 0; + + time_type = entry->param[0]; + block_p = entry->block_p; + + if (time_type == GET_UPTIME) { + get_monotonic_boottime(&tp); + tv_sec = tp.tv_sec; + tv_usec = tp.tv_nsec/1000; + } else { + do_gettimeofday(&tv); + tv_sec = tv.tv_sec; + tv_usec = tv.tv_usec; + } + + retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__); + return retVal; + } + + retVal = add_bdrv_nq_entry(TEEI_BDRV_CALL, reetime.sysno, + block_p, time_type, + tv_sec, tv_usec); + if (retVal != 0) + IMSG_ERROR("TEEI: Failed to add_nq_entry[%s]\n", __func__); + + teei_notify_switch_fn(); + + return retVal; +} + +/******************************************************************** + * VFS functions * + ********************************************************************/ + + + +int vfs_thread_function(unsigned long virt_addr, + unsigned long para_vaddr, unsigned long buff_vaddr) +{ + int retVal = 0; + + daulOS_VFS_share_mem = (unsigned char *)virt_addr; + + retVal = notify_vfs_handle(); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Can NOT notify the tz_vfs node!\n", + __func__, __LINE__); + return retVal; + } + + retVal = wait_for_vfs_done(); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Failed to waiting for the tz_vfs node!\n", + __func__, __LINE__); + return retVal; + } + + return 0; +} + +static long vfs_init(struct service_handler *handler) /*! init service */ +{ + long retVal = 0; + + retVal = register_shared_param_buf(handler); + vfs_flush_address = handler->param_buf; + + return retVal; +} + +static void vfs_deinit(struct service_handler *handler) /*! stop service */ +{ +} + +static int vfs_handle(struct NQ_entry *entry) +{ + unsigned long long block_p = 0; + int retVal = 0; + + block_p = entry->block_p; + + vfs_thread_function((unsigned long)(vfs_handler.param_buf), 0, 0); + + retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__); + return retVal; + } + + retVal = add_bdrv_nq_entry(TEEI_BDRV_CALL, vfs_handler.sysno, + block_p, 0, 0, 0); + if (retVal != 0) + IMSG_ERROR("TEEI: Failed to add_nq_entry[%s]\n", __func__); + + teei_notify_switch_fn(); + + return retVal; +} + +static int handle_bdrv_call(struct bdrv_work_struct *entry) +{ + struct NQ_entry *NQ_entry_p = entry->param_p; + + if (NQ_entry_p->sub_cmd_ID == reetime.sysno) + reetime.handle(NQ_entry_p); + else if (NQ_entry_p->sub_cmd_ID == vfs_handler.sysno) + vfs_handler.handle(NQ_entry_p); + + kfree(NQ_entry_p); + + return 0; +} + +static int handle_load_img_call(struct bdrv_work_struct *entry) +{ + int retVal = 0; + + vfs_thread_function(boot_vfs_addr, 0, 0); + + retVal = add_work_entry(SMC_CALL_TYPE, N_ACK_T_LOAD_IMG, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add N_ACK_T_LOAD_IMG!\n"); + return retVal; + } + + teei_notify_switch_fn(); + + return 0; +} + + +static int handle_bdrv_entry(struct bdrv_work_struct *entry) +{ + unsigned long long call_type = 0; + int retVal = 0; + + call_type = entry->bdrv_work_type; + + switch (call_type) { + + case TEEI_BDRV_TYPE: + retVal = handle_bdrv_call(entry); + break; + case TEEI_LOAD_IMG_TYPE: + retVal = handle_load_img_call(entry); + break; + default: + retVal = -EINVAL; + break; + } + + kfree(entry); + + return retVal; +} + +void teei_notify_bdrv_fn(void) +{ + complete(&teei_bdrv_comp); +} + +int teei_bdrv_fn(void *work) +{ + struct bdrv_work_struct *bdrv_entry = NULL; + int retVal = 0; + + while (1) { + retVal = wait_for_completion_interruptible(&teei_bdrv_comp); + if (retVal != 0) + continue; + + bdrv_entry = teei_get_bdrv_from_link(); + if (bdrv_entry == NULL) { + IMSG_ERROR("TEEI: Can NOT get the bdrv entry!\n"); + continue; + } + + retVal = handle_bdrv_entry(bdrv_entry); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to handle the bdrv entry\n"); + return retVal; + } + } + + return 0; +} + +int init_bdrv_comp_fn(void) +{ + init_completion(&teei_bdrv_comp); + + return 0; +} + +int init_all_service_handlers(void) +{ + long retVal = 0; + + reetime.init = reetime_init; + reetime.deinit = reetime_deinit; + reetime.handle = reetime_handle; + reetime.size = 0x1000; + reetime.sysno = 7; + + vfs_handler.init = vfs_init; + vfs_handler.deinit = vfs_deinit; + vfs_handler.handle = vfs_handle; + vfs_handler.size = 0x80000; + vfs_handler.sysno = 8; + + retVal = reetime.init(&reetime); + if (retVal < 0) { + IMSG_ERROR("[%s][%d] init reetime service failed!\n", + __func__, __LINE__); + return retVal; + } + + retVal = vfs_handler.init(&vfs_handler); + if (retVal < 0) { + IMSG_ERROR("[%s][%d] init vfs service failed!\n", + __func__, __LINE__); + return retVal; + } + + return 0; +} diff --git a/drivers/tee/teei/300/tz_driver/fdrv.c b/drivers/tee/teei/300/tz_driver/fdrv.c new file mode 100644 index 000000000000..a675bea32e2e --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/fdrv.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include "teei_id.h" +#include "sched_status.h" +#include "nt_smc_call.h" +#include "teei_log.h" +#include "teei_common.h" +#include "switch_queue.h" +#include "teei_client_main.h" +#include "backward_driver.h" +#include "utdriver_macro.h" + +#include + +#define IMSG_TAG "[tz_driver]" +#include + +static LIST_HEAD(fdrv_list); + +int create_fdrv(struct teei_fdrv *fdrv) +{ + unsigned long temp_addr = 0; + long retVal = 0; + + if (fdrv->buff_size > VDRV_MAX_SIZE) { + IMSG_ERROR("[%s][%d]: FDrv buffer size is too large.\n", + __FILE__, __LINE__); + return -EINVAL; + } + +#ifdef UT_DMA_ZONE + temp_addr = (unsigned long) __get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(ROUND_UP(fdrv->buff_size, SZ_4K))); +#else + temp_addr = (unsigned long) __get_free_pages(GFP_KERNEL, + get_order(ROUND_UP(fdrv->buff_size, SZ_4K))); +#endif + if ((unsigned char *)temp_addr == NULL) { + IMSG_ERROR("[%s][%d]: Faile to alloc fdrv buffer failed.\n", + __FILE__, __LINE__); + return -ENOMEM; + } + + retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__); + goto free_memory; + } + + retVal = add_nq_entry(TEEI_CREAT_FDRV, fdrv->call_type, + (unsigned long long)(&boot_sema), + virt_to_phys((void *)temp_addr), + fdrv->buff_size, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add one nq to n_t_buffer\n"); + goto free_memory; + } + + teei_notify_switch_fn(); + + down(&boot_sema); + + fdrv->buf = (void *)temp_addr; + + return 0; + +free_memory: + free_pages((unsigned long)temp_addr, + get_order(ROUND_UP(fdrv->buff_size, SZ_4K))); + + return retVal; +} + +void register_fdrv(struct teei_fdrv *fdrv) +{ + list_add_tail(&fdrv->list, &fdrv_list); +} +EXPORT_SYMBOL(register_fdrv); + +int fdrv_notify(struct teei_fdrv *fdrv) +{ + struct completion *wait_completion = NULL; + int retVal = 0; + + wait_completion = kmalloc(sizeof(struct completion), GFP_KERNEL); + + init_completion(wait_completion); + + cpus_read_lock(); + + retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__); + cpus_read_unlock(); + kfree(wait_completion); + return retVal; + } + + retVal = add_nq_entry(TEEI_FDRV_CALL, fdrv->call_type, + (unsigned long long)(wait_completion), + fdrv->buff_size, 0, 0); + + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add one nq to n_t_buffer\n"); + cpus_read_unlock(); + kfree(wait_completion); + return retVal; + } + + teei_notify_switch_fn(); + + wait_for_completion(wait_completion); + + cpus_read_unlock(); + + kfree(wait_completion); + + return 0; +} +EXPORT_SYMBOL(fdrv_notify); + +void teei_handle_fdrv_call(struct NQ_entry *entry) +{ + struct completion *bp = NULL; + + bp = (struct completion *)(entry->block_p); + if (bp == NULL) { + IMSG_ERROR("The block_p of entry is NULL!\n"); + return; + } + + complete(bp); +} + +int create_all_fdrv(void) +{ + struct teei_fdrv *fdrv; + int retVal = 0; + + list_for_each_entry(fdrv, &fdrv_list, list) { + retVal = create_fdrv(fdrv); + + if (retVal != 0) + return retVal; + } + + return 0; +} diff --git a/drivers/tee/teei/300/tz_driver/include/TEEI.h b/drivers/tee/teei/300/tz_driver/include/TEEI.h new file mode 100644 index 000000000000..e9a4abfe6208 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/TEEI.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TZ_TEEI_H__ +#define __TZ_TEEI_H__ + +#define socket_buffer_size 2048 +#define ARGS_BLOCK_SIZE 1024 + +struct sockaddr { + unsigned short sa_family; + char sa_data[14]; +}; + +struct in_addr { + unsigned long s_addr; /* that¡¦s a 32-bit long, or 4 bytes */ +}; + +struct sockaddr_in { + short int sin_family; + unsigned short int sin_port; + struct in_addr sin_addr; + unsigned char sin_zero[8]; +}; + +struct TEEI_socket_command { + int func; + int cmd_size; + + union func_arg { + char raw[ARGS_BLOCK_SIZE]; + + struct func_socket { + int af; + int type; + int protocol; + } func_socket_args; + + struct func_connect { + int sockfd; + struct sockaddr ob_addr; + int addrlen; + } func_connect_args; + + struct func_bind { + int sockfd; + struct sockaddr ob_addr; + int addrlen; + } func_bind_args; + + struct func_listen { + int sockfd; + int backlog; + } func_listen_args; + + struct func_accept { + int sockfd; + struct sockaddr ob_addr; + int addrlen; + } func_accept_args; + + struct func_send { + int sockfd; + void *buf; + int len; + int flags; + } func_send_args; + +#define func_recv func_send +#define func_recv_args func_send_args +#define func_recv_send func_send +#define func_recv_send_args func_send_args + struct func_close { + int sockfd; + } func_close_args; + + struct func_inet_addr { + char ip_addr[17]; + } func_inet_addr_args; + + struct func_htons { + unsigned short portnum; + } func_htons_args; + struct func_setsockopt { + int fd; + int level; + int optname; + struct timeval; + int optlen; + } func_setsockopt_args; + + } args; + +}; + + +union TEEI_socket_response_type { + int value; + uint32_t addr; + bool hasError; + unsigned short portnum; + unsigned int transSize; + struct response_func_recv { + void *buf; + unsigned int size; + } recv; +}; + +#endif /* __TZ_TEEI_H_ */ diff --git a/drivers/tee/teei/300/tz_driver/include/backward_driver.h b/drivers/tee/teei/300/tz_driver/include/backward_driver.h new file mode 100644 index 000000000000..2c321ae33618 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/backward_driver.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef BACKWARD_DRIVER_H +#define BACKWARD_DRIVER_H + +#include + +#include "teei_common.h" + +#define TEEI_BDRV_TYPE (0x10) +#define TEEI_LOAD_IMG_TYPE (0x20) + +struct bdrv_work_struct { + unsigned long long bdrv_work_type; + void *param_p; + struct list_head c_link; +}; + +extern struct service_handler reetime; +extern struct service_handler vfs_handler; +extern unsigned char *daulOS_VFS_share_mem; + +int notify_vfs_handle(void); +int wait_for_vfs_done(void); + +int init_all_service_handlers(void); +int vfs_thread_function(unsigned long virt_addr, + unsigned long para_vaddr, unsigned long buff_vaddr); + +int init_bdrv_comp_fn(void); +void teei_notify_bdrv_fn(void); +int teei_bdrv_fn(void *work); + +#endif /* end of BACKWARD_DRIVER_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/irq_register.h b/drivers/tee/teei/300/tz_driver/include/irq_register.h new file mode 100644 index 000000000000..64616a340cdb --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/irq_register.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef IRQ_REGISTER_H +#define IRQ_REGISTER_H + +#define SCHED_ENT_CNT 10 + +struct load_soter_entry { + unsigned long vfs_addr; + struct work_struct work; +}; + +int register_ut_irq_handler(int irq); +int register_switch_irq_handler(void); +void load_func(struct work_struct *entry); +void work_func(struct work_struct *entry); +void secondary_load_func(void); + +int teei_smc(unsigned long long smc_id, unsigned long long p1, + unsigned long long p2, unsigned long long p3); + +#endif /* end of IRQ_REGISTER_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/notify_queue.h b/drivers/tee/teei/300/tz_driver/include/notify_queue.h new file mode 100644 index 000000000000..bc64203412ed --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/notify_queue.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef NOTIFY_QUEUE_H +#define NOTIFY_QUEUE_H + +#include + +struct NQ_head { + unsigned long long nq_type; + unsigned long long max_count; + unsigned long long put_index; + unsigned long long reserve[5]; +}; + +struct NQ_entry { + unsigned long long cmd_ID; + unsigned long long sub_cmd_ID; + unsigned long long block_p; + unsigned long long param[5]; +}; + +int add_nq_entry(unsigned long long cmd_ID, unsigned long long sub_cnd_ID, + unsigned long long block_p, unsigned long long p0, + unsigned long long p1, unsigned long long p2); + +int add_bdrv_nq_entry(unsigned long long cmd_ID, unsigned long long sub_cnd_ID, + unsigned long long block_p, unsigned long long p0, + unsigned long long p1, unsigned long long p2); + +struct NQ_entry *get_nq_entry(void); + +int create_nq_buffer(void); +int set_soter_version(void); +void secondary_init_cmdbuf(void *info); +int show_t_nt_queue(void); + +extern unsigned long long switch_input_index; +extern unsigned long long switch_output_index; + +#endif /* end of NOTIFY_QUEUE_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/nt_smc_call.h b/drivers/tee/teei/300/tz_driver/include/nt_smc_call.h new file mode 100644 index 000000000000..6cc55a85b964 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/nt_smc_call.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef SMC_CALL_H_ +#define SMC_CALL_H_ + +#include +#include + +/*This field id is fixed by arm*/ +#define ID_FIELD_F_FAST_SMC_CALL 1 +#define ID_FIELD_F_STANDARD_SMC_CALL 0 +#define ID_FIELD_W_64 1 +#define ID_FIELD_W_32 0 + +#define ID_FIELD_T_ARM_SERVICE 0 +#define ID_FIELD_T_CPU_SERVICE 1 +#define ID_FIELD_T_SIP_SERVICE 2 +#define ID_FIELD_T_OEM_SERVICE 3 +#define ID_FIELD_T_STANDARD_SERVICE 4 +/*TA Call 48-49*/ +#define ID_FIELD_T_TA_SERVICE0 48 +#define ID_FIELD_T_TA_SERVICE1 49 +/*TOS Call 50-63*/ +#define ID_FIELD_T_TRUSTED_OS_SERVICE0 50 +#define ID_FIELD_T_TRUSTED_OS_SERVICE1 51 +#define ID_FIELD_T_TRUSTED_OS_SERVICE2 52 +#define ID_FIELD_T_TRUSTED_OS_SERVICE3 53 + +#define MAKE_SMC_CALL_ID(F, W, T, FN) (((F)<<31)|((W)<<30)|((T)<<24)|(FN)) + +#define SMC_CALL_RTC_OK 0x0 +#define SMC_CALL_RTC_UNKNOWN_FUN 0xFFFFFFFF +#define SMC_CALL_RTC_MONITOR_NOT_READY 0xFFFFFFFE + +#define SMC_CALL_INTERRUPTED_IRQ 0x54 +#define SMC_CALL_DONE 0x45 + +#define N_GET_T_FP_DEVICE_ID \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_64, ID_FIELD_T_TRUSTED_OS_SERVICE2, 11) +/*Child type command type for soter to recognize*/ +#define N_ACK_T_INVOKE_DRV_CMD \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_64, ID_FIELD_T_TRUSTED_OS_SERVICE3, 5) +#define N_INVOKE_T_LOAD_TEE_CMD \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_64, ID_FIELD_T_TRUSTED_OS_SERVICE3, 6) +#define N_INVOKE_T_NQ_CMD \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_64, ID_FIELD_T_TRUSTED_OS_SERVICE3, 2) + +/*For non-secure side Fast Call*/ +#define N_SWITCH_TO_T_OS_STAGE2 \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 0) +#define N_GET_PARAM_IN \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 1) +#define N_INIT_T_FC_BUF \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 2) +#define N_INVOKE_T_FAST_CALL \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 3) +#define NT_DUMP_STATE \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 4) +#define N_ACK_T_FOREGROUND \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 5) +#define N_ACK_T_BACKSTAGE \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 6) +#define N_INIT_T_BOOT_STAGE1 \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 7) +#define N_SWITCH_CORE \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 8) +#define N_GET_NON_IRQ_NUM \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 9) +#define N_GET_SE_OS_STATE \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 10) +#define N_GET_T_FP_DEVICE_ID_32 \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 11) +#define N_ADD_TRIGGER_IRQ_COUNT \ + MAKE_SMC_CALL_ID(ID_FIELD_F_FAST_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE2, 12) + +/*For non-secure side Standard Call*/ +#define NT_SCHED_T \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 0) +#define N_INVOKE_T_SYS_CTL \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 1) +#define N_INVOKE_T_NQ \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 2) +#define N_INVOKE_T_DRV \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 3) +#define N_RAISE_T_EVENT \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 4) +#define N_ACK_T_INVOKE_DRV \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 5) +#define N_INVOKE_T_LOAD_TEE \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 6) +#define N_ACK_T_LOAD_IMG \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 7) +#define NT_SCHED_T_FIQ \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 8) +#define NT_CANCEL_T_TUI \ + MAKE_SMC_CALL_ID(ID_FIELD_F_STANDARD_SMC_CALL, \ + ID_FIELD_W_32, ID_FIELD_T_TRUSTED_OS_SERVICE3, 9) + +static inline void get_t_device_id(uint64_t *p0) +{ + struct arm_smccc_res res; + + arm_smccc_smc(N_GET_T_FP_DEVICE_ID_32, 0, 0, 0, + 0, 0, 0, 0, &res); + *p0 = res.a0; +} +#endif /* SMC_CALL_H_ */ diff --git a/drivers/tee/teei/300/tz_driver/include/sched_status.h b/drivers/tee/teei/300/tz_driver/include/sched_status.h new file mode 100644 index 000000000000..d81de0163053 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/sched_status.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef SCHED_STATUS_H +#define SCHED_STATUS_H + +#define GLSCH_NONE (0x00) +#define GLSCH_LOW (0x01) +#define GLSCH_HIGH (0x02) +#define GLSCH_NEG (0x03) +#define GLSCH_FOR_SOTER (0x04) + +#endif /* end of SCHED_STATUS_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/smc_id.h b/drivers/tee/teei/300/tz_driver/include/smc_id.h new file mode 100644 index 000000000000..65a5f5972240 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/smc_id.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_SMC_ID_H__ +#define __TEEI_SMC_ID_H__ + + +/* SMC Identifiers for non-secure world functions */ +#define CALL_TRUSTZONE_API 0x1 +#if defined(CONFIG_S5PV310_BOARD) || defined(CONFIG_MVV4412_BOARD) +/* Based arch/arm/mach-exynos/include/mach/smc.h */ +#define SMC_CMD_INIT (-1) +#define SMC_CMD_INFO (-2) +/* For Power Management */ +#define SMC_CMD_SLEEP (-3) +#define SMC_CMD_CPU1BOOT (-4) +#define SMC_CMD_CPU0AFTR (-5) +/* For CP15 Access */ +#define SMC_CMD_C15RESUME (-11) +/* For L2 Cache Access */ +#define SMC_CMD_L2X0CTRL (-21) +#define SMC_CMD_L2X0SETUP1 (-22) +#define SMC_CMD_L2X0SETUP2 (-23) +#define SMC_CMD_L2X0INVALL (-24) +#define SMC_CMD_L2X0DEBUG (-25) +#define SMC_CMD_L2X0FLUSHALL (-26) +#define SMC_CMD_L2X0CLEANALL (-27) +#define SMC_CMD_L2X0FLUSHRANGE (-28) +/* For Framebuffer */ +#define SMC_CMD_INIT_SECURE_WINDOW (-29) + +#define SMC_CP15_REG (-102) +#define SMC_CP15_AUX_CTRL 0x1 +#define SMC_CP15_L2_PREFETCH 0x2 +#define SMC_CACHE_CTRL 0x3 +#endif + +#ifdef CONFIG_ZYNQ7_BOARD +#define SMC_CMD_CPU1BOOT (-4) +#define SMC_CMD_SECURE_READ (-30) +#define SMC_CMD_SECURE_WRITE (-31) +#endif + +#endif /* __TEEI_SMC_ID__ */ diff --git a/drivers/tee/teei/300/tz_driver/include/switch_queue.h b/drivers/tee/teei/300/tz_driver/include/switch_queue.h new file mode 100644 index 000000000000..ddac891cfbb7 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/switch_queue.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef SWITCH_QUEUE_H +#define SWITCH_QUEUE_H + +struct task_entry_struct { + unsigned long long work_type; + unsigned long long x0; + unsigned long long x1; + unsigned long long x2; + unsigned long long x3; + struct list_head c_link; +}; + +int add_work_entry(unsigned long long work_type, unsigned long long x0, + unsigned long long x1, unsigned long long x2, + unsigned long long x3); + +int teei_notify_switch_fn(void); +int init_teei_switch_comp(void); +int teei_switch_fn(void *work); + +#endif /* end of SWITCH_QUEUE_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/sysfs.h b/drivers/tee/teei/300/tz_driver/include/sysfs.h new file mode 100644 index 000000000000..314c089efd6d --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/sysfs.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_SYS_FS_H__ +#define __TEEI_SYS_FS_H__ +int init_sysfs(struct platform_device *pdev); +void remove_sysfs(struct platform_device *pdev); + +#endif diff --git a/drivers/tee/teei/300/tz_driver/include/teei_cancel_cmd.h b/drivers/tee/teei/300/tz_driver/include/teei_cancel_cmd.h new file mode 100644 index 000000000000..c4f42f2fec07 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_cancel_cmd.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_CANCEL_CMD_H +#define TEEI_CANCEL_CMD_H + +extern unsigned long cancel_message_buff; +extern struct semaphore fp_lock; + +unsigned long create_cancel_fdrv(int buff_size); +int send_cancel_command(unsigned long share_memory_size); + +#endif /* end of TEEI_CANCEL_CMD_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_client.h b/drivers/tee/teei/300/tz_driver/include/teei_client.h new file mode 100644 index 000000000000..ed189d079182 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_client.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_CLIENT_H_ +#define __TEEI_CLIENT_H_ + +#include +#include +#define TEEI_CLIENT_FULL_PATH_DEV_NAME "/dev/teei_client" +#define TEEI_CLIENT_DEV "teei_client" + + +/** IOCTL request */ + + +/** + * @brief Encode command structure + */ +struct teei_client_encode_cmd { + unsigned int len; + unsigned long long data; + int offset; + int flags; + int param_type; + + int encode_id; + int session_id; + unsigned int cmd_id; + int value_flag; + int param_pos; + int param_pos_type; + int return_value; + int return_origin; +}; + +/** + * @brief Session details structure + */ +struct ser_ses_id { + /* int service_id; */ + int session_id; + struct TEEC_UUID uuid; + int return_value; + int return_origin; + int paramtype; + int params[8]; +}; +/** + * @brief Session details structure + */ +struct user_ses_init { + int session_id; +}; + +struct ctx_data { + char name[255]; /* context name */ + int ctx_ret; /* context return */ +}; + +/** + * @brief Shared memory information for the session + */ +struct teei_session_shared_mem_info { + /* unsigned long service_id; */ + unsigned int session_id; + u64 user_mem_addr; +}; + +/** + * @brief Shared memory used for smc processing + */ +struct teei_smc_cdata { + int cmd_addr; + int size; + int valid_flag; + int ret_val; +}; + +/* For general service */ +#define TEEI_CLIENT_IOCTL_SEND_CMD_REQ \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 3, struct teei_client_encode_cmd) +#define TEEI_CLIENT_IOCTL_SES_OPEN_REQ \ + _IOW(TEEI_CLIENT_IOC_MAGIC, 4, struct ser_ses_id) +#define TEEI_CLIENT_IOCTL_SES_CLOSE_REQ \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 5, struct ser_ses_id) +#define TEEI_CLIENT_IOCTL_SHR_MEM_FREE_REQ \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 6, struct teei_session_shared_mem_info) + +#define TEEI_CLIENT_IOCTL_ENC_UINT32 \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 7, struct teei_client_encode_cmd) +#define TEEI_CLIENT_IOCTL_ENC_ARRAY \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 8, struct teei_client_encode_cmd) +#define TEEI_CLIENT_IOCTL_ENC_ARRAY_SPACE \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 9, struct teei_client_encode_cmd) +#define TEEI_CLIENT_IOCTL_ENC_MEM_REF \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 10, struct teei_client_encode_cmd) + +#define TEEI_CLIENT_IOCTL_DEC_UINT32 \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 11, struct teei_client_encode_cmd) +#define TEEI_CLIENT_IOCTL_DEC_ARRAY_SPACE \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 12, struct teei_client_encode_cmd) +#define TEEI_CLIENT_IOCTL_OPERATION_RELEASE \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 13, struct teei_client_encode_cmd) +#define TEEI_CLIENT_IOCTL_SHR_MEM_ALLOCATE_REQ \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 14, struct teei_session_shared_mem_info) +#define TEEI_CLIENT_IOCTL_GET_DECODE_TYPE \ + _IOWR(TEEI_CLIENT_IOC_MAGIC, 15, struct teei_client_encode_cmd) +/* add by lodovico */ +#define TEEI_CLIENT_IOCTL_INITCONTEXT_REQ \ + _IOW(TEEI_CLIENT_IOC_MAGIC, 16, struct ctx_data) +#define TEEI_CLIENT_IOCTL_CLOSECONTEXT_REQ \ + _IOW(TEEI_CLIENT_IOC_MAGIC, 17, struct ctx_data) +/* add end */ +#define TEEI_CLIENT_IOCTL_SES_INIT_REQ \ + _IOW(TEEI_CLIENT_IOC_MAGIC, 18, struct user_ses_init) + +#define TEEI_GET_TEEI_CONFIG_STAT \ + _IOW(TEEI_CLIENT_IOC_MAGIC, 0x1001, struct ctx_data) + +#define TEEI_CANCEL_COMMAND \ + _IOW(TEEI_CLIENT_IOC_MAGIC, 0x1002, struct ctx_data) +#endif /* __TEEI_CLIENT_H_ */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_client_main.h b/drivers/tee/teei/300/tz_driver/include/teei_client_main.h new file mode 100644 index 000000000000..8848babd0d46 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_client_main.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_CLIENT_MAIN_H__ +#define __TEEI_CLIENT_MAIN_H__ + +#include + +#include +#include "teei_smc_struct.h" +#include "teei_client.h" +/* #define UT_DEBUG */ +#define CANCEL_BUFF_SIZE (4096) +#define TEEI_CONFIG_FULL_PATH_DEV_NAME "/dev/teei_config" +#define TEEI_CONFIG_DEV "teei_config" +#define MIN_BC_NUM (4) +#define MAX_LC_NUM (3) +#define TEEI_CPU_0 + +#define TEEI_TA 0x01 +#define TEEI_DRV 0x00 + +enum { + TZ_CALL_PREPARE, + TZ_CALL_RETURNED, +}; + +struct tz_driver_state { + struct mutex smc_lock; + struct atomic_notifier_head notifier; + struct platform_device *tz_log_pdev; +}; + +struct tz_driver_state *get_tz_drv_state(void); + +extern unsigned int soter_error_flag; + +extern struct workqueue_struct *secure_wq; +extern struct semaphore boot_sema; +extern struct smc_call_struct smc_call_entry; +extern unsigned long boot_vfs_addr; +extern unsigned long boot_soter_flag; +extern int keymaster_call_flag; +extern struct completion boot_decryto_lock; +extern struct task_struct *teei_switch_task; +extern struct kthread_worker ut_fastcall_worker; +extern unsigned long spi_ready_flag; +extern struct list_head g_block_link; + +extern struct task_struct *teei_switch_task; + +void set_current_cpuid(int cpu); +int get_current_cpuid(void); + +void *tz_malloc_shared_mem(size_t size, int flags); +void tz_free_shared_mem(void *addr, size_t size); +void *tz_malloc(size_t size, int flags); + +int handle_switch_core(int cpu); + +int is_teei_ready(void); +int teei_new_capi_init(void); +int handle_new_capi_call(void *args); + +int tz_load_drv_by_str(const char *buf); +int tz_load_ta_by_str(const char *buf); + +int teei_handle_move_core(int cpu); +int teei_move_cpu_context(int target_cpu_id, int original_cpu_id); + +void teei_cpus_read_lock(void); +void teei_cpus_read_unlock(void); +void teei_cpus_write_lock(void); +void teei_cpus_write_unlock(void); + +#endif /* __TEEI_CLIENT_MAIN_H__ */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_client_transfer_data.h b/drivers/tee/teei/300/tz_driver/include/teei_client_transfer_data.h new file mode 100644 index 000000000000..2d690b341523 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_client_transfer_data.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_CLIENT_TRANSFER_DATA_H +#define TEEI_CLIENT_TRANSFER_DATA_H + +#include +#include + +int ut_pf_gp_initialize_context(struct TEEC_Context *context); +int ut_pf_gp_finalize_context(struct TEEC_Context *context); +int ut_pf_gp_transfer_data(struct TEEC_Context *context, struct TEEC_UUID *uuid, + unsigned int command, void *buffer, unsigned long size); +int ut_pf_gp_transfer_user_data(struct TEEC_Context *context, + struct TEEC_UUID *uuid, + unsigned int command, void *buffer, unsigned long size); + +#endif /* end of TEEI_CLIENT_TRANSFER_DATA_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_common.h b/drivers/tee/teei/300/tz_driver/include/teei_common.h new file mode 100644 index 000000000000..ad4aad9624b6 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_common.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_COMMON_H_ +#define __TEEI_COMMON_H_ + +#include +#include + +#ifdef CONFIG_MICROTRUST_TZ_DRIVER_MTK_TRACING +#include +#endif + +#define TEEI_MAX_REQ_PARAMS 12 +#define TEEI_MAX_RES_PARAMS 8 +#define TEEI_1K_SIZE 1024 + +/** + * @brief Command status + */ +enum teei_cmd_status { + TEEI_STATUS_INCOMPLETE = 0, + TEEI_STATUS_COMPLETE, + TEEI_STATUS_MAX = 0x7FFFFFFF +}; + + +/** + * @brief Parameters type + */ +enum teeic_param_type { + TEEIC_PARAM_IN = 0, + TEEIC_PARAM_OUT +}; + +/** + * @brief Shared memory for Notification + */ +struct teeic_notify_data { + int dev_file_id; + int service_id; + int client_pid; + int session_id; + int enc_id; +}; + + +enum teeic_param_value { + TEEIC_PARAM_A = 0, + TEEIC_PARAM_B +}; + +enum teeic_param_pos { + TEEIC_PARAM_1ST = 0, + TEEIC_PARAM_2ND, + TEEIC_PARAM_3TD, + TEEIC_PARAM_4TH +}; + + +/** + * @brief Metadata used for encoding/decoding + */ +struct teei_encode_meta { + int type; + int len; /* data length */ + unsigned long long usr_addr; /* data address in user space */ + int ret_len; /* return sizeof data */ + int value_flag; /* value of a or b */ + int param_pos; /* param order */ + int param_pos_type; /* param type */ +}; + +/** + * @brief SMC command structure + */ +#pragma pack(1) +struct teei_smc_cmd { + u32 teei_cmd_type; + u32 id; + u32 context; + u32 enc_id; + + u32 src_id; + u32 src_context; + + u32 req_buf_len; + u32 resp_buf_len; + u32 ret_resp_buf_len; + u32 info_buf_len; + u32 cmd_status; + u64 req_buf_phys; + u64 resp_buf_phys; + u64 meta_data_phys; + u64 info_buf_phys; + u32 dev_file_id; + u32 error_code; + u64 teei_sema; +}; +#pragma pack() + +struct message_head { + unsigned int invalid_flag; + unsigned int message_type; + unsigned int child_type; + unsigned int param_length; +}; + +struct fdrv_message_head { + unsigned int driver_type; + unsigned int fdrv_param_length; +}; + +#pragma pack(1) +struct create_fdrv_struct { + u32 fdrv_type; + u64 fdrv_phy_addr; + u32 fdrv_size; +}; +#pragma pack() + +struct ack_fast_call_struct { + int retVal; +}; + +struct fdrv_call_struct { + int fdrv_call_type; + int fdrv_call_buff_size; + int retVal; +}; + +struct service_handler { + unsigned int sysno; + void *param_buf; + unsigned int size; + long (*init)(struct service_handler *handler); + void (*deinit)(struct service_handler *handler); + int (*handle)(struct NQ_entry *handler); +}; + +/* [KTRACE] Begin-End */ +#ifdef CONFIG_MICROTRUST_TZ_DRIVER_MTK_TRACING +#define KATRACE_MESSAGE_LENGTH 1024 +#define BEGINED_PID (current->tgid) + +static inline void tracing_mark_write(const char *buf) +{ + TRACE_PUTS(buf); +} + +#define WRITE_MSG(format, pid, name) { \ + char buf[KATRACE_MESSAGE_LENGTH]; \ + int len = snprintf(buf, sizeof(buf), format, pid, name); \ + if (len >= (int) sizeof(buf)) { \ + int name_len = strlen(name) - (len - sizeof(buf)) - 1; \ + len = snprintf(buf, sizeof(buf), "B|%d|%.*s", BEGINED_PID, \ + name_len, name); \ + } \ + tracing_mark_write(buf); \ +} + +#define KATRACE_BEGIN(name) katrace_begin_body(name) +static inline void katrace_begin_body(const char *name) +{ + WRITE_MSG("B|%d|%s", BEGINED_PID, name); +} + +#define KATRACE_END(name) katrace_end(name) +static inline void katrace_end(const char *name) +{ + WRITE_MSG("E|%d|%s", BEGINED_PID, name); +} +#else +#define KATRACE_BEGIN(name) \ + do { \ + } while (0) +#define KATRACE_END(name) \ + do { \ + } while (0) +#endif + +#endif /* __TEEI_COMMON_H_ */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_common_types.h b/drivers/tee/teei/300/tz_driver/include/teei_common_types.h new file mode 100644 index 000000000000..7ac7f26457c7 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_common_types.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef SW_COMMON_TYPES_H +#define SW_COMMON_TYPES_H +#define size_t (unsigned long) +#endif diff --git a/drivers/tee/teei/300/tz_driver/include/teei_debug.h b/drivers/tee/teei/300/tz_driver/include/teei_debug.h new file mode 100644 index 000000000000..82ccd60b497a --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_debug.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_DEBUG_H_ +#define __TEEI_DEBUG_H_ + +/* #define TEEI_DEBUG */ +/* #define TEEI_INFO */ + +#undef TDEBUG +#undef TINFO +#undef TERR + +#define TZDebug(fmt, args...) \ + pr_info("\033[;34m[TZDriver]"fmt"\033[0m\n", ##args) +#ifdef TEEI_DEBUG +/* + * #define TDEBUG(fmt, args...) pr_info("%s(%i, %s): " fmt "\n", \ + * __func__, current->pid, current->comm, ##args) + */ +#define TDEBUG(fmt, args...) pr_info("tz driver"fmt"\n", ##args) +#else +#define TDEBUG(fmt, args...) +#endif + +#ifdef TEEI_INFO +#define TINFO(fmt, args...) pr_info("%s(%i, %s): " fmt "\n", \ + __func__, current->pid, current->comm, ##args) +#else +#define TINFO(fmt, args...) +#endif + +#define TERR(fmt, args...) pr_notice("%s(%i, %s): " fmt "\n", \ + __func__, current->pid, current->comm, ##args) + +#endif diff --git a/drivers/tee/teei/300/tz_driver/include/teei_fp.h b/drivers/tee/teei/300/tz_driver/include/teei_fp.h new file mode 100644 index 000000000000..7ba7db92cf96 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_fp.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_FP_H +#define TEEI_FP_H + +extern struct TEEC_UUID uuid_fp; + +#endif /* end of TEEI_FP_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_id.h b/drivers/tee/teei/300/tz_driver/include/teei_id.h new file mode 100644 index 000000000000..cba8b28019cc --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_id.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_ID_H_ +#define __TEEI_ID_H_ +#include + +#define SMC_ENOMEM 7 +#define SMC_EOPNOTSUPP 6 +#define SMC_EINVAL_ADDR 5 +#define SMC_EINVAL_ARG 4 +#define SMC_ERROR 3 +#define SMC_INTERRUPTED 2 +#define SMC_PENDING 1 +#define SMC_SUCCESS 0 +/*extern void __flush_dcache_area(void *addr, size_t len);*/ +extern unsigned long boot_soter_flag; +#define START_STATUS (0) + +/** + * @brief Encoding data type + */ +enum teei_enc_data_type { + TEEI_ENC_INVALID_TYPE = 0, + TEEI_ENC_UINT32, + TEEI_ENC_ARRAY, + TEEI_MEM_REF, + TEEI_SECURE_MEM_REF +}; +/** + * @brief Command ID's for global service + */ +enum _global_cmd_id { + TEEI_GLOBAL_CMD_ID_INVALID = 0x0, + TEEI_GLOBAL_CMD_ID_BOOT_ACK, + /* add by lodovico */ + TEEI_GLOBAL_CMD_ID_INIT_CONTEXT, + /* add end */ + TEEI_GLOBAL_CMD_ID_OPEN_SESSION, + TEEI_GLOBAL_CMD_ID_CLOSE_SESSION, + TEEI_GLOBAL_CMD_ID_RESUME_ASYNC_TASK, + TEEI_GLOBAL_CMD_ID_UNKNOWN = 0x7FFFFFFE, + TEEI_GLOBAL_CMD_ID_MAX = 0x7FFFFFFF +}; + +/* add by lodovico */ +/* void printff(); */ + + +int service_smc_call(u32 teei_cmd_type, u32 dev_file_id, u32 svc_id, + u32 cmd_id, u32 context, u32 enc_id, + const void *cmd_buf, + size_t cmd_len, + void *resp_buf, + size_t resp_len, + const void *meta_data, + int *ret_resp_len, + void *wq, + void *arg_lock, int *error_code); + + +enum teei_cmd_type { + TEEI_CMD_TYPE_INVALID = 0x0, + TEEI_CMD_TYPE_SOCKET_INIT, + TEEI_CMD_TYPE_INITIALIZE_CONTEXT, + TEEI_CMD_TYPE_FINALIZE_CONTEXT, + TEEI_CMD_TYPE_OPEN_SESSION, + TEEI_CMD_TYPE_CLOSE_SESSION, + TEEI_CMD_TYPE_INVOKE_COMMAND, + TEEI_CMD_TYPE_UNKNOWN = 0x7FFFFFFE, + TEEI_CMD_TYPE_MAX = 0x7FFFFFFF +}; + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + +#define Cache_line_size 32 +/**************************************************************** + * @brief: + * Flush_Dcache_By_Area + * @param: + * start - mva start + * end - mva end + * @return: + * ***************************************************************/ +static inline void Flush_Dcache_By_Area(unsigned long start, unsigned long end) +{ + if (boot_soter_flag == START_STATUS) { +#ifdef CONFIG_ARM64 + __flush_dcache_area((void *)start, (end - start)); +#else + __cpuc_flush_dcache_area((void *)start, (end - start)); +#endif + } + + +} + +/****************************************************************** + * @brief: + * Invalidate_Dcache_By_Area + * @param: + * start - mva start + * end - mva end + * @return: + * *****************************************************************/ + +static inline void __Invalidate_Dcache_By_Area(unsigned long start, + unsigned long end) +{ +#ifdef CONFIG_ARM64 + uint64_t temp[2]; + + temp[0] = start; + temp[1] = end; + __asm__ volatile( + "ldr x0, [%[temp], #0]\n\t" + "ldr x1, [%[temp], #8]\n\t" + "mrs x3, ctr_el0\n\t" + "ubfm x3, x3, #16, #19\n\t" + "mov x2, #4\n\t" + "lsl x2, x2, x3\n\t" + "dsb sy\n\t" + "sub x3, x2, #1\n\t" + "bic x0, x0, x3\n\t" + /* invalidate D line / unified line */ + "1: dc ivac, x0\n\t" + "add x0, x0, x2\n\t" + "cmp x0, x1\n\t" + "b.lo 1b\n\t" + "dsb sy\n\t" + : : + [temp] "r" (temp) + : "x0", "x1", "x2", "x3", "memory"); +#else + __asm__ __volatile__ ("dsb" : : : "memory"); /* dsb */ + __asm__ __volatile__ ( + /* Invalidate Data Cache Line (using MVA) Register */ + "1: mcr p15, 0, %[i], c7, c6, 1\n" + " add %[i], %[i], %[clsz]\n" + " cmp %[i], %[end]\n" + " blo 1b\n" + : + [i] "=&r" (start) + : "0" ((unsigned long)start & (~(Cache_line_size - 1))), + [end] "r" (end), + [clsz] "i" (Cache_line_size) + : "memory"); + + /* invalidate btc */ + asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0) : "memory"); + __asm__ __volatile__ ("dsb" : : : "memory"); /* dsb */ + + +#endif +} + + +static inline void Invalidate_Dcache_By_Area(unsigned long start, + unsigned long end) +{ + if (boot_soter_flag == START_STATUS) + __Invalidate_Dcache_By_Area(start, end); +} + +/* add end */ +#endif /* __OPEN_OTZ_ID_H_ */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_keymaster.h b/drivers/tee/teei/300/tz_driver/include/teei_keymaster.h new file mode 100644 index 000000000000..2fdd92bc60ce --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_keymaster.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_KEYMASTER_H +#define TEEI_KEYMASTER_H + +extern struct semaphore keymaster_api_lock; + +int send_keymaster_command(void *buffer, unsigned long size); +#endif /* end of TEEI_KEYMASTER_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_list.h b/drivers/tee/teei/300/tz_driver/include/teei_list.h new file mode 100644 index 000000000000..42726d5429a2 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_list.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __LIB_LIST_H__ +#define __LIB_LIST_H__ + +#define LIST_POISON_PREV 0xDEADBEEF +#define LIST_POISON_NEXT 0xFADEBABE + +/** + * @brief + */ +struct list { + struct list *next, *prev; +}; + +#define INIT_HEAD(__lname) { &(__lname), &(__lname) } +#define LIST_HEAD(_lname) struct list _lname = INIT_HEAD(_lname) +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = ptr; (ptr)->prev = ptr; \ + } while (0) + +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +#define list_for_each(curr, head) \ + for (curr = (head)->next; curr != head; curr = (curr)->next) + +#define list_for_each_entry(ptr, head, member) \ + for (ptr = list_entry((head)->next, typeof(*ptr), member); \ + &ptr->member != (head); \ + ptr = list_entry(ptr->member.next, typeof(*ptr), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type + * safe against removal of list entry + * @param pos: the type * to use as a loop cursor. + * @param n: another type * to use as temporary storage + * @param head: the head for your list. + * @param member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * @brief + * + * @param prev + * @param next + * @param new + */ +static inline void __list_add(struct list *prev, + struct list *next, struct list *new) +{ + new->prev = prev; + new->next = next; + prev->next = new; + next->prev = new; +} + +/** + * @brief + * Adds the new node after the given head. + * @param head: List head after which the "new" node should be added. + * @param new: New node that needs to be added to list. + * @note Please note that new node is added after the head. + */ +static inline void list_add(struct list *head, struct list *new) +{ + __list_add(head, head->next, new); +} + +/** + * Adds a node at the tail where tnode points to tail node. + * @param tnode: The current tail node. + * @param new: The new node to be added before tail. + * @note: Please note that new node is added before tail node. + */ +static inline void list_add_tail(struct list *tnode, struct list *new) +{ + __list_add(tnode->prev, tnode, new); +} + +/** + * @brief + * + * @param node + * @param prev + * @param next + */ +static inline void __list_del(struct list *node, + struct list *prev, struct list *next) +{ + prev->next = node->next; + next->prev = node->prev; + node->next = (void *)LIST_POISON_NEXT; + node->prev = (void *)LIST_POISON_PREV; +} + +/** + * @brief + * Deletes a given node from list. + * @param node: Node to be deleted. + * + * @param node + */ +static inline void list_del(struct list *node) +{ + __list_del(node, node->prev, node->next); +} + +/** + * @brief + * + * @param head + * + * @return + */ +static inline struct list *list_pop_tail(struct list *head) +{ + struct list *dnode = head->prev; + + list_del(head->prev); + return dnode; +} + +/** + * @brief + * + * @param head + * + * @return + */ +static inline struct list *list_pop(struct list *head) +{ + struct list *dnode = head->next; + + list_del(head->next); + return dnode; +} + +/** + * @brief + * + * @param head + * + * @return + */ +static inline int list_empty(struct list *head) +{ + if (head->next == head) + return 1; + else + return 0; +} + +#endif /* __LIB_LIST_H__ */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_log.h b/drivers/tee/teei/300/tz_driver/include/teei_log.h new file mode 100644 index 000000000000..80d9a218563d --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_log.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_LOG_H +#define TEEI_LOG_H + +#define LOG_BUF_LEN (256 * 1024) + +#endif /* TEEI_LOG_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_smc_call.h b/drivers/tee/teei/300/tz_driver/include/teei_smc_call.h new file mode 100644 index 000000000000..e0711c21b779 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_smc_call.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_SMC_CALL_H +#define TEEI_SMC_CALL_H +#include + +#endif /* end of TEEI_SMC_CALL_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/teei_smc_struct.h b/drivers/tee/teei/300/tz_driver/include/teei_smc_struct.h new file mode 100644 index 000000000000..3d30d07fedc3 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_smc_struct.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TEEI_SMC_STRUCT_H__ +#define __TEEI_SMC_STRUCT_H__ + +#include +#define TEE_NAME_SIZE (255) + +struct teei_encode { + struct list_head head; + int encode_id; + void *ker_req_data_addr; + void *ker_res_data_addr; + u32 enc_req_offset; + u32 enc_res_offset; + u32 enc_req_pos; + u32 enc_res_pos; + u32 dec_res_pos; + u32 dec_offset; + struct teei_encode_meta *meta; +}; + +struct teei_shared_mem { + struct list_head head; + struct list_head s_head; + void *index; + void *k_addr; + void *u_addr; + u32 len; +}; + +struct teei_context { + /* ID */ + unsigned long cont_id; + /* Name */ + char tee_name[TEE_NAME_SIZE]; + /* session counter */ + unsigned long sess_cnt; + /* share memory counter */ + unsigned long shared_mem_cnt; + /* link list for teei_context */ + struct list_head link; + /* link list for the sessions of this context */ + struct list_head sess_link; + /* link list for the share memory of this context */ + struct list_head shared_mem_list; + struct semaphore cont_lock; +}; + +struct teei_session { + /* ID */ + int sess_id; + /* the teei_context pointer of this session */ + struct teei_context *parent_cont; + /* link list for teei_session */ + struct list_head link; + /* link list for the encode of this session */ + struct list_head encode_list; + /* link list for the share memory of this session */ + struct list_head shared_mem_list; +}; + +#endif diff --git a/drivers/tee/teei/300/tz_driver/include/teei_task_link.h b/drivers/tee/teei/300/tz_driver/include/teei_task_link.h new file mode 100644 index 000000000000..5a8813dfe459 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/teei_task_link.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TEEI_TASK_LINK_H +#define TEEI_TASK_LINK_H + +int teei_init_task_link(void); +int teei_add_to_task_link(struct list_head *entry); +struct task_entry_struct *teei_get_task_from_link(void); +int is_teei_task_link_empty(void); + +int teei_add_to_bdrv_link(struct list_head *entry); +struct bdrv_work_struct *teei_get_bdrv_from_link(void); + +#endif /* end of TEEI_TASK_LINK_H */ + diff --git a/drivers/tee/teei/300/tz_driver/include/tz_service.h b/drivers/tee/teei/300/tz_driver/include/tz_service.h new file mode 100644 index 000000000000..991f8c84993c --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/tz_service.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef TZ_SERVICE_H +#define TZ_SERVICE_H + +#ifdef VFS_RDWR_SEM +extern struct semaphore VFS_rd_sem; +extern struct semaphore VFS_wr_sem; +#else +extern struct completion VFS_rd_comp; +extern struct completion VFS_wr_comp; +#endif + +int wait_for_service_done(void); +int register_switch_irq_handler(void); +int teei_service_init(void); + +void set_sch_nq_cmd(void); +void set_sch_load_img_cmd(void); +long create_cmd_buff(void); +void set_cancel_command(unsigned long memory_size); +#endif diff --git a/drivers/tee/teei/300/tz_driver/include/ut_drv.h b/drivers/tee/teei/300/tz_driver/include/ut_drv.h new file mode 100644 index 000000000000..b80d1e6646f9 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/ut_drv.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef _UT_DRV_H_ +#define _UT_DRV_H_ + +#include + +struct ut_drv_entry { + struct TEEC_UUID uuid; + struct TEEC_Session session; + uint32_t driver_id; + struct list_head list; +}; + +struct param_get_drv_id { + unsigned long dummy; +}; + +struct param_reg_dci_buf { + uint64_t phy_addr; + uint32_t buf_size; +}; + +struct param_notify_from_ree { + unsigned long data; + uint32_t cmd; +}; + +struct param_drv_open { + unsigned long data; +}; + +struct param_drv_ioctl { + unsigned long data; + uint32_t cmd; +}; + +struct param_drv_close { + unsigned long dummy; +}; + +struct ut_drv_param { + uint32_t cmd_id; + union { + struct param_get_drv_id get_drv_id; + struct param_reg_dci_buf reg_dci_buf; + struct param_notify_from_ree notify_from_ree; + struct param_drv_open drv_open; + struct param_drv_ioctl drv_ioctl; + struct param_drv_close drv_close; + } u; +}; + +enum { + UT_DRV_GET_DRIVER_ID, + UT_DRV_REGISTER_DCI_BUFFER, + UT_DRV_FREE_DCI_BUFFER, + UT_DRV_NOTIFY_FROM_REE, + UT_DRV_OPEN, + UT_DRV_IOCTL, + UT_DRV_CLOSE, +}; + +static inline void prepare_params(struct TEEC_Operation *op, + void *data, size_t size) +{ + op->params[0].tmpref.buffer = data; + op->params[0].tmpref.size = size; + op->params[1].value.a = 0; + + op->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_OUTPUT, + TEEC_NONE, + TEEC_NONE); +} + +static inline uint32_t get_result(struct TEEC_Operation *op) +{ + return op->params[1].value.a; +} + +struct ut_drv_entry *find_ut_drv_entry_by_uuid(struct TEEC_UUID *uuid); +struct ut_drv_entry *find_ut_drv_entry_by_driver_id(uint32_t driver_id); + +#endif diff --git a/drivers/tee/teei/300/tz_driver/include/utdriver_irq.h b/drivers/tee/teei/300/tz_driver/include/utdriver_irq.h new file mode 100644 index 000000000000..261ba84e29f8 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/utdriver_irq.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef UTDRIVER_IRQ_H +#define UTDRIVER_IRQ_H + +#define LOAD_IMG_IRQ (281) +#define SWITCH_IRQ (282) +#define BOOT_IRQ (283) +#define SCHED_IRQ (284) +#define SOTER_IRQ (285) +#define FP_ACK_IRQ (287) +#define BDRV_IRQ (278) +#define TEEI_LOG_IRQ (277) +#define SOTER_ERROR_IRQ (276) + +#define UT_DRV_IRQ (284) + +#endif /* end if UTDRIVER_IRQ_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/utdriver_macro.h b/drivers/tee/teei/300/tz_driver/include/utdriver_macro.h new file mode 100644 index 000000000000..3c8f6006c5aa --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/utdriver_macro.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef UTDRIVER_MACRO_H +#define UTDRIVER_MACRO_H + +/* define TEEI_MUTIL_TA_DEBUG */ + +#define START_STATUS (0) +#define END_STATUS (1) + + +#define VFS_SIZE (0x80000) +#define VDRV_MAX_SIZE (0x80000) +#define KEYMASTER_BUFF_SIZE (512 * 1024) + +/* Command ID in the notify queue entry */ +#define TEEI_CREAT_FDRV (0x40) +#define TEEI_CREAT_BDRV (0x41) +#define TEEI_LOAD_TEE (0x42) +#define NEW_CAPI_CALL (0x43) +#define TEEI_BDRV_CALL (0x44) +#define TEEI_FDRV_CALL (0x45) +#define TEEI_SCHED_CALL (0x46) +/* Command ID in the notify queue entry END */ + + + +/* Switch function ID */ +#define SMC_CALL_TYPE (0x10) +#define SWITCH_CORE_TYPE (0x11) +/* Switch function ID END */ + +#define VFS_SYS_NO 0x08 +#define REETIME_SYS_NO 0x07 +#define SCHED_SYS_NO 0x09 +#define CANCEL_SYS_NO (110) + + +#define MAX_BUFF_SIZE (0x2000) + +#define NQ_SIZE (0x1000) +#define NQ_BUFF_SIZE (0x1000) +#define NQ_BLOCK_SIZE (64) +#define BLOCK_MAX_COUNT (NQ_BUFF_SIZE / NQ_BLOCK_SIZE - 1) + +#define CTL_BUFF_SIZE (0x1000) + +#define MESSAGE_LENGTH (0x1000) +#define MESSAGE_SIZE (0x1000) +#endif /* end of UTDRIVER_MACRO_H */ diff --git a/drivers/tee/teei/300/tz_driver/include/utos_version.h b/drivers/tee/teei/300/tz_driver/include/utos_version.h new file mode 100644 index 000000000000..9845080af008 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/utos_version.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __UTOS_VERSION_H__ +#define __UTOS_VERSION_H__ +#define UTOS_VERSION "tag.base.dbg.2.5.3" +#endif diff --git a/drivers/tee/teei/300/tz_driver/include/utr_tui_cmd.h b/drivers/tee/teei/300/tz_driver/include/utr_tui_cmd.h new file mode 100644 index 000000000000..4dbc6305251e --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/include/utr_tui_cmd.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __UT_TUI_H_ +#define __UT_TUI_H_ + +#include + +enum disp_pwm_id_t { + DISP_PWM0 = 0x1, + DISP_PWM1 = 0x2, + DISP_PWM_ALL = (DISP_PWM0 | DISP_PWM1) +}; +#define disp_pwm_id_t enum disp_pwm_id_t + +extern int mtkfb_set_backlight_level(unsigned int level); +extern int disp_pwm_set_backlight(disp_pwm_id_t id, int level_1024); +extern void disp_aal_notify_backlight_changed(int bl_1024); +extern void ut_down_low(struct semaphore *sema); + +extern int enter_tui_flag; +extern int power_down_flag; +extern unsigned long tui_display_message_buff; +extern unsigned long tui_notice_message_buff; +extern struct semaphore tui_notify_sema; + +int try_send_tui_command(void); +int send_tui_display_command(unsigned long share_memory_size); +int send_tui_notice_command(unsigned long share_memory_size); +unsigned long create_tui_buff(int buff_size, unsigned int fdrv_type); +int wait_for_power_down(void); +int tui_notify_reboot(struct notifier_block *this, unsigned long code, void *x); +int __send_tui_display_command(unsigned long share_memory_size); +int __send_tui_notice_command(unsigned long share_memory_size); + +#endif /* end of __UT_TUI_H_ */ diff --git a/drivers/tee/teei/300/tz_driver/irq_register.c b/drivers/tee/teei/300/tz_driver/irq_register.c new file mode 100644 index 000000000000..43c92896bc2d --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/irq_register.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "teei_id.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "teei_task_link.h" + +#define IMSG_TAG "[tz_driver]" +#include + +#define TEEI_BACK_SW (0x01) +#define TEEI_WORK_DONE (0x02) +#define TEEI_UNKNOWN_WORK (0x03) + +static int nt_sched_irq_handler(void) +{ + return TEEI_BACK_SW; +} + +static int nt_error_irq_handler(void) +{ + unsigned long error_num = 0; + + error_num = teei_secure_call(N_GET_SE_OS_STATE, 0, 0, 0); + IMSG_ERROR("secure system ERROR ! error_num = %ld\n", + (error_num)); + soter_error_flag = 1; + + up(&(boot_sema)); + + WARN_ON(1); + + return TEEI_WORK_DONE; +} + + +static int nt_boot_irq_handler(void) +{ + if (boot_soter_flag == START_STATUS) + boot_soter_flag = END_STATUS; + + up(&(boot_sema)); + + return TEEI_WORK_DONE; +} + +void teei_handle_bdrv_call(struct NQ_entry *entry) +{ + struct bdrv_work_struct *work_ent = NULL; + struct NQ_entry *bdrv_ent = NULL; + + work_ent = kmalloc(sizeof(struct bdrv_work_struct), GFP_KERNEL); + if (work_ent == NULL) { + IMSG_ERROR("NO enough memory for work in %s!\n", __func__); + return; + } + + bdrv_ent = kmalloc(sizeof(struct NQ_entry), GFP_KERNEL); + if (bdrv_ent == NULL) { + IMSG_ERROR("NO enough memory for bdrv in %s!\n", __func__); + kfree(work_ent); + return; + } + + INIT_LIST_HEAD(&(work_ent->c_link)); + + memcpy(bdrv_ent, entry, sizeof(struct NQ_entry)); + + work_ent->bdrv_work_type = TEEI_BDRV_TYPE; + work_ent->param_p = bdrv_ent; + + teei_add_to_bdrv_link(&(work_ent->c_link)); + + teei_notify_bdrv_fn(); +} + +void teei_handle_schedule_call(struct NQ_entry *entry) +{ +} + +void teei_handle_capi_call(struct NQ_entry *entry) +{ + struct completion *bp = NULL; + + bp = (struct completion *)(entry->block_p); + if (bp == NULL) { + IMSG_ERROR("The block_p of entry is NULL!\n"); + return; + } + + complete(bp); +} + +static int nt_switch_irq_handler(void) +{ + struct NQ_entry *entry = NULL; + unsigned long long cmd_id = 0; + int retVal = 0; + + entry = get_nq_entry(); + if (entry == NULL) { + IMSG_ERROR("Can NOT get entry from t_nt_buffer!\n"); + return TEEI_UNKNOWN_WORK; + } + + cmd_id = entry->cmd_ID; + + switch (cmd_id) { + case TEEI_CREAT_FDRV: + case TEEI_CREAT_BDRV: + case TEEI_LOAD_TEE: + switch_output_index = + ((unsigned long)switch_output_index + 1) % 10000; + up(&boot_sema); + retVal = TEEI_WORK_DONE; + break; + case TEEI_FDRV_CALL: + switch_output_index = + ((unsigned long)switch_output_index + 1) % 10000; + teei_handle_fdrv_call(entry); + retVal = TEEI_WORK_DONE; + break; + case NEW_CAPI_CALL: + switch_output_index = + ((unsigned long)switch_output_index + 1) % 10000; + teei_handle_capi_call(entry); + retVal = TEEI_WORK_DONE; + break; + case TEEI_BDRV_CALL: + teei_handle_bdrv_call(entry); + retVal = TEEI_WORK_DONE; + break; + case TEEI_SCHED_CALL: + teei_handle_schedule_call(entry); + retVal = TEEI_BACK_SW; + break; + default: + IMSG_ERROR("[%s][%d] Unknown command ID!\n", + __func__, __LINE__); + retVal = TEEI_UNKNOWN_WORK; + } + + return retVal; +} + +static int nt_load_img_handler(void) +{ + struct bdrv_work_struct *work_ent = NULL; + + work_ent = kmalloc(sizeof(struct bdrv_work_struct), GFP_KERNEL); + if (work_ent == NULL) { + IMSG_ERROR("NO enough memory for work in %s!\n", __func__); + return TEEI_WORK_DONE; + } + + INIT_LIST_HEAD(&(work_ent->c_link)); + + work_ent->bdrv_work_type = TEEI_LOAD_IMG_TYPE; + + teei_add_to_bdrv_link(&(work_ent->c_link)); + + teei_notify_bdrv_fn(); + + return TEEI_WORK_DONE; +} + + +static int ut_smc_handler(void) +{ + int irq_id = 0; + int retVal = 0; + + /* Get the interrupt ID */ + irq_id = teei_secure_call(N_GET_NON_IRQ_NUM, 0, 0, 0); + + switch (irq_id) { + case SCHED_IRQ: + retVal = nt_sched_irq_handler(); + break; + case LOAD_IMG_IRQ: + retVal = nt_load_img_handler(); + break; + case SWITCH_IRQ: + retVal = nt_switch_irq_handler(); + break; + case SOTER_ERROR_IRQ: + retVal = nt_error_irq_handler(); + break; + case BOOT_IRQ: + switch_output_index = + ((unsigned long)switch_output_index + 1) % 10000; + retVal = nt_boot_irq_handler(); + break; + default: + retVal = TEEI_UNKNOWN_WORK; + IMSG_ERROR("get undefine IRQ from secure OS!\n"); + } + + return retVal; +} + +int teei_smc(unsigned long long smc_id, unsigned long long p1, + unsigned long long p2, unsigned long long p3) +{ + unsigned long long smc_type = 2; + int retVal = 0; + + smc_type = teei_secure_call(smc_id, p1, p2, p3); + while (1) { + if (smc_type == SMC_CALL_INTERRUPTED_IRQ) + smc_type = teei_secure_call(NT_SCHED_T, 0, 0, 0); + else { + retVal = ut_smc_handler(); + if (retVal == TEEI_BACK_SW) { + smc_type = teei_secure_call( + NT_SCHED_T, 0, 0, 0); + continue; + } else if (retVal == TEEI_WORK_DONE) + break; + + IMSG_ERROR("ut_smc_handler return %d!\n", retVal); + break; + } + } + + return 0; +} + +static irqreturn_t ut_drv_irq_handler(int irq, void *dev) +{ + return IRQ_HANDLED; +} + +int register_ut_irq_handler(int irq) +{ + return request_irq(irq, ut_drv_irq_handler, + 0, "tz_drivers_service", NULL); +} + + diff --git a/drivers/tee/teei/300/tz_driver/log_perf.h b/drivers/tee/teei/300/tz_driver/log_perf.h new file mode 100644 index 000000000000..f5d31142dc4b --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/log_perf.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * + */ + + +#define ENABLE_LOG_PERF 0 + +static inline uint64_t read_cntvct(void) +{ + uint64_t val; + + asm volatile("mrs %0, cntvct_el0" : "=r" (val)); + return val; +} + + +#if ENABLE_LOG_PERF == 1 + +#define LOG_MEASURE_START 0x7c40407c /* |@@| */ +#define LOG_MEASURE_END 0x7c2d2d7c /* |--| */ + +static unsigned int received_tz_log_chars; +static unsigned int received_tz_log_lines; +static bool tz_log_timer_started; +static uint64_t start_log_timer_counter, end_log_timer_counter; + +static void reset_tz_log_counter(void) +{ + received_tz_log_chars = 0; + received_tz_log_lines = 0; +} + +static void add_tz_log_counter(unsigned int num_chars) +{ + received_tz_log_chars += num_chars; + received_tz_log_lines++; +} + +static void measure_log_perf(const char *tag, int log_len, uint32_t log_prefix) +{ + if (log_len > 0) { + if (log_prefix == LOG_MEASURE_START) { + if (!tz_log_timer_started) { + start_log_timer_counter = read_cntvct(); + tz_log_timer_started = true; + reset_tz_log_counter(); + } + add_tz_log_counter(log_len-1); + } + + if (log_prefix == LOG_MEASURE_END) { + if (!tz_log_timer_started) + IMSG_WARN("[BUG] log timer not start yet!\n"); + else { + end_log_timer_counter = read_cntvct(); + tz_log_timer_started = false; + + IMSG_PRINTK("%s[RLOG] Recv Log (%u)/(%u)\n", + tag, received_tz_log_chars, + received_tz_log_lines); + + IMSG_PRINTK("%s[RLOG] (%llu)~(%llu)/(%llu)\n", + tag, start_log_timer_counter, + end_log_timer_counter, + end_log_timer_counter - start_log_timer_counter); + } + } + } +} +#endif diff --git a/drivers/tee/teei/300/tz_driver/notify_queue.c b/drivers/tee/teei/300/tz_driver/notify_queue.c new file mode 100644 index 000000000000..147796287e03 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/notify_queue.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include "notify_queue.h" +#include "teei_id.h" +#include "teei_log.h" +#include "utdriver_macro.h" +#include "teei_common.h" +#include "teei_client_main.h" +#include "backward_driver.h" +#include +#include +#include +#include "irq_register.h" +#define IMSG_TAG "[tz_driver]" +#include + +struct teei_queue_stat { + struct mutex nq_stat_mutex; + unsigned long long get; + struct mutex nt_t_mutex; + struct mutex nt_t_bdrv_mutex; +}; + +static struct teei_queue_stat g_nq_stat; + +static unsigned long nt_t_buffer; +static unsigned long t_nt_buffer; +static unsigned long nt_t_bdrv_buffer; + +unsigned long long switch_input_index; +unsigned long long switch_output_index; + +static unsigned long create_notify_queue(unsigned long size) +{ + unsigned long buff_addr = 0; + long retVal = 0; + + /* Create the double NQ buffer. */ +#ifdef UT_DMA_ZONE + buff_addr = (unsigned long) __get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(ROUND_UP(size, SZ_4K))); +#else + buff_addr = (unsigned long) __get_free_pages(GFP_KERNEL, + get_order(ROUND_UP(size, SZ_4K))); +#endif + if ((unsigned char *)buff_addr == NULL) { + IMSG_ERROR("[%s][%d]: Alloc queue buffer failed.\n", + __func__, __LINE__); + retVal = -ENOMEM; + goto return_fn; + } + + switch_input_index = ((unsigned long)switch_input_index + 1) % 10000; + + /* Call the smc_fast_call */ + retVal = add_work_entry(SMC_CALL_TYPE, N_INIT_T_FC_BUF, + virt_to_phys((void *)buff_addr), size, 0); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Failed to call the add_work_entry!\n", + __func__, __LINE__); + goto Destroy_buffer; + + } + + teei_notify_switch_fn(); + + down(&(boot_sema)); + + return buff_addr; + +Destroy_buffer: + free_pages(buff_addr, get_order(ROUND_UP(size, SZ_4K))); +return_fn: + return 0; +} + +static void NQ_init(unsigned long NQ_buff) +{ + memset((char *)NQ_buff, 0, NQ_BUFF_SIZE); +} + +static int init_nq_head(unsigned long buffer_addr, unsigned int type) +{ + struct NQ_head *temp_head = NULL; + + temp_head = (struct NQ_head *)buffer_addr; + + memset(temp_head, 0, NQ_BLOCK_SIZE); + temp_head->nq_type = type; + temp_head->max_count = BLOCK_MAX_COUNT; + temp_head->put_index = 0; + + return 0; +} + +int add_nq_entry(unsigned long long cmd_ID, unsigned long long sub_cmd_ID, + unsigned long long block_p, unsigned long long p0, + unsigned long long p1, unsigned long long p2) +{ + static unsigned long long check_index; + struct NQ_head *temp_head = NULL; + struct NQ_entry *temp_entry = NULL; + + mutex_lock(&(g_nq_stat.nt_t_mutex)); + + temp_head = (struct NQ_head *)nt_t_buffer; + temp_entry = (struct NQ_entry *)(nt_t_buffer + NQ_BLOCK_SIZE + + temp_head->put_index * NQ_BLOCK_SIZE); + + temp_entry->cmd_ID = cmd_ID; + temp_entry->sub_cmd_ID = sub_cmd_ID; + temp_entry->block_p = block_p; + temp_entry->param[0] = p0; + temp_entry->param[1] = p1; + temp_entry->param[2] = p2; + temp_entry->param[3] = block_p; + temp_entry->param[4] = check_index; + + check_index = ((unsigned long)check_index + 1) % 10000; + + /* Call the smp_mb() to make sure setting entry before setting head */ + smp_mb(); + + switch_input_index = ((unsigned long)switch_input_index + 1) % 10000; + + temp_head->put_index = ((unsigned long)temp_head->put_index + 1) + % (unsigned long)temp_head->max_count; + + /* Call the rmb() to make sure setting entry before setting head */ + rmb(); + + teei_secure_call(N_ADD_TRIGGER_IRQ_COUNT, 0, 0, 0); + + mutex_unlock(&(g_nq_stat.nt_t_mutex)); + + return 0; +} + +int add_bdrv_nq_entry(unsigned long long cmd_ID, unsigned long long sub_cmd_ID, + unsigned long long block_p, unsigned long long p0, + unsigned long long p1, unsigned long long p2) +{ + static unsigned long long check_index; + struct NQ_head *temp_head = NULL; + struct NQ_entry *temp_entry = NULL; + + mutex_lock(&(g_nq_stat.nt_t_mutex)); + + temp_head = (struct NQ_head *)nt_t_bdrv_buffer; + temp_entry = (struct NQ_entry *)(nt_t_bdrv_buffer + NQ_BLOCK_SIZE + + temp_head->put_index * NQ_BLOCK_SIZE); + + temp_entry->cmd_ID = cmd_ID; + temp_entry->sub_cmd_ID = sub_cmd_ID; + temp_entry->block_p = block_p; + temp_entry->param[0] = p0; + temp_entry->param[1] = p1; + temp_entry->param[2] = p2; + temp_entry->param[3] = block_p; + temp_entry->param[4] = check_index; + + check_index = ((unsigned long)check_index + 1) % 10000; + + /* Call the smp_mb() to make sure setting entry before setting head */ + smp_mb(); + + temp_head->put_index = ((unsigned long)temp_head->put_index + 1) + % (unsigned long)temp_head->max_count; + + /* Call the rmb() to make sure setting entry before setting head */ + rmb(); + + teei_secure_call(N_ADD_TRIGGER_IRQ_COUNT, 0, 0, 0); + + mutex_unlock(&(g_nq_stat.nt_t_mutex)); + + return 0; +} + +struct NQ_entry *get_nq_entry(void) +{ + struct NQ_head *temp_head = NULL; + struct NQ_entry *temp_entry = NULL; + unsigned long long put = 0; + unsigned long long get = 0; + + temp_head = (struct NQ_head *)t_nt_buffer; + + put = temp_head->put_index; + + /* mutex_lock(&(g_nq_stat.nq_stat_mutex)); */ + + get = g_nq_stat.get; + + if (put != get) { + temp_entry = (struct NQ_entry *)(t_nt_buffer + NQ_BLOCK_SIZE + + get * NQ_BLOCK_SIZE); + + get = ((unsigned long)get + 1) + % (unsigned long)temp_head->max_count; + + g_nq_stat.get = get; + } + + /* mutex_unlock(&(g_nq_stat.nq_stat_mutex)); */ + + return temp_entry; +} + +int create_nq_buffer(void) +{ + unsigned long nq_addr = 0; + + nq_addr = create_notify_queue(NQ_SIZE * 3); + if (nq_addr == 0) { + IMSG_ERROR("[%s][%d]:create_notify_queue failed.\n", + __func__, __LINE__); + return -ENOMEM; + } + + nt_t_buffer = nq_addr; + t_nt_buffer = nq_addr + NQ_SIZE; + nt_t_bdrv_buffer = nq_addr + NQ_SIZE * 2; + + /* Get the Soter version from notify queue shared memory */ + set_soter_version(); + + NQ_init(nt_t_buffer); + NQ_init(t_nt_buffer); + NQ_init(nt_t_bdrv_buffer); + + init_nq_head(nt_t_buffer, 0x00); + init_nq_head(t_nt_buffer, 0x01); + init_nq_head(nt_t_bdrv_buffer, 0x03); + + memset(&g_nq_stat, 0, sizeof(g_nq_stat)); + mutex_init(&(g_nq_stat.nq_stat_mutex)); + mutex_init(&(g_nq_stat.nt_t_mutex)); + mutex_init(&(g_nq_stat.nt_t_bdrv_mutex)); + + return 0; +} + +int set_soter_version(void) +{ + unsigned int versionlen = 0; + char *version = NULL; + + memcpy(&versionlen, (void *)nt_t_buffer, sizeof(unsigned int)); + if (versionlen > 0 && versionlen < 100) { + version = kmalloc(versionlen + 1, GFP_KERNEL); + if (version == NULL) + return -ENOMEM; + + memset(version, 0, versionlen + 1); + memcpy(version, (void *)(nt_t_buffer + sizeof(unsigned int)), + versionlen); + } else + return -EINVAL; + + IMSG_PRINTK("%s\n", version); + kfree(version); + + return 0; +} diff --git a/drivers/tee/teei/300/tz_driver/switch_queue.c b/drivers/tee/teei/300/tz_driver/switch_queue.c new file mode 100644 index 000000000000..9d478f3cf468 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/switch_queue.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "switch_queue.h" +#include "utdriver_macro.h" +#include "sched_status.h" +#include "teei_log.h" +#include "teei_common.h" +#include "teei_client_main.h" +#include "backward_driver.h" +#include "irq_register.h" +#include "teei_smc_call.h" +#include "teei_cancel_cmd.h" +#include "tz_log.h" + +#include "teei_task_link.h" + +#include +#include + +#define IMSG_TAG "[tz_driver]" +#include + +struct completion teei_switch_comp; + +#ifdef CONFIG_MICROTRUST_DYNAMIC_CORE +static int last_cpu_id; +#endif + +static int add_entry_to_task_link(struct task_entry_struct *entry) +{ + int retVal = 0; + + retVal = teei_add_to_task_link(&(entry->c_link)); + + return retVal; +} + + +int add_work_entry(unsigned long long work_type, unsigned long long x0, + unsigned long long x1, unsigned long long x2, + unsigned long long x3) +{ + struct task_entry_struct *task_entry = NULL; + int retVal = 0; + + task_entry = vmalloc(sizeof(struct task_entry_struct)); + if (task_entry == NULL) { + IMSG_ERROR("Failed to vmalloc task_entry_struct!\n"); + return -ENOMEM; + } + + memset(task_entry, 0, sizeof(struct task_entry_struct)); + + task_entry->work_type = work_type; + task_entry->x0 = x0; + task_entry->x1 = x1; + task_entry->x2 = x2; + task_entry->x3 = x3; + + INIT_LIST_HEAD(&(task_entry->c_link)); + + retVal = add_entry_to_task_link(task_entry); + if (retVal != 0) { + IMSG_ERROR("Failed to insert the entry to link!\n"); + vfree(task_entry); + return retVal; + } + + return retVal; +} + +#ifdef CONFIG_MICROTRUST_DYNAMIC_CORE +static int teei_bind_current_cpu(void) +{ + struct cpumask mask = { CPU_BITS_NONE }; + int cpu_id = 0; + + /* Get current CPU ID */ + cpu_id = smp_processor_id(); + + cpumask_clear(&mask); + cpumask_set_cpu(cpu_id, &mask); + set_cpus_allowed_ptr(teei_switch_task, &mask); + + set_current_cpuid(cpu_id); + + if (last_cpu_id != cpu_id) { + teei_move_cpu_context(cpu_id, last_cpu_id); + last_cpu_id = cpu_id; + } + + return 0; +} + +static int teei_bind_all_cpu(void) +{ + struct cpumask mask = { CPU_BITS_NONE }; + + /* Set the affinity of teei_switch_task to all CPUs */ + + if (switch_input_index == switch_output_index) { + cpumask_clear(&mask); + cpumask_setall(&mask); + set_cpus_allowed_ptr(teei_switch_task, &mask); + } + + return 0; +} +#endif + +static int handle_one_switch_task(struct task_entry_struct *entry) +{ + int retVal = 0; + + switch (entry->work_type) { + case SMC_CALL_TYPE: + retVal = teei_smc(entry->x0, entry->x1, entry->x2, entry->x3); + break; +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE + case SWITCH_CORE_TYPE: + retVal = handle_switch_core((int)(entry->x0)); + break; +#endif + default: + retVal = -EINVAL; + break; + } + + return retVal; +} + + +static int handle_all_switch_task(void) +{ + struct task_entry_struct *entry = NULL; + struct tz_driver_state *s = get_tz_drv_state(); + int retVal = 0; + + while (1) { + entry = teei_get_task_from_link(); + if (entry == NULL) + return 0; + + retVal = handle_one_switch_task(entry); + if (retVal != 0) { + IMSG_ERROR("Failed to handle the task %d\n", retVal); + return retVal; + } + + vfree(entry); + + teei_notify_log_fn(); + } + + return 0; +} + +int teei_switch_fn(void *work) +{ + int retVal = 0; + + while (1) { + /* + * Block the switch thread and + * wait for the new task + */ + retVal = wait_for_completion_interruptible(&teei_switch_comp); + if (retVal != 0) + continue; + + /* + * Check if the task link is empty + */ + retVal = is_teei_task_link_empty(); + if (retVal == 1) + continue; + +#ifdef CONFIG_MICROTRUST_DYNAMIC_CORE + /* Bind the teei switch thread to current CPU */ + retVal = teei_bind_current_cpu(); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to bind current CPU!\n"); + return retVal; + } +#endif + + retVal = handle_all_switch_task(); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to handle the task link!\n"); + return retVal; + } + +#ifdef CONFIG_MICROTRUST_DYNAMIC_CORE + retVal = teei_bind_all_cpu(); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to bind all CPUs!\n"); + return retVal; + } +#endif + } + + IMSG_PRINTK("TEEI: teei_switch_thread will be exit! (%d)\n", retVal); + + return retVal; +} + +int teei_notify_switch_fn(void) +{ + complete(&teei_switch_comp); + + return 0; +} + +int init_teei_switch_comp(void) +{ + init_completion(&teei_switch_comp); + + return 0; +} diff --git a/drivers/tee/teei/300/tz_driver/sysfs.c b/drivers/tee/teei/300/tz_driver/sysfs.c new file mode 100644 index 000000000000..960a324fa15e --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/sysfs.c @@ -0,0 +1,631 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define IMSG_TAG "[tz_driver]" + +#include + +#include +#include "../teei_fp/fp_func.h" + + +static uint32_t imsg_log_level = IMSG_LOG_LEVEL; +static DEFINE_MUTEX(drv_load_mutex); +unsigned long spi_ready_flag; + +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG +uint32_t tzdriver_dynamical_debug_flag; +#endif + +static ssize_t imsg_log_test_show(struct device *cd, + struct device_attribute *attr, char *buf) +{ + IMSG_PROFILE_S("LOG_TEST"); + + IMSG_ENTER(); + + IMSG_TRACE("Trace message\n"); + IMSG_DEBUG("Debug message\n"); + IMSG_INFO("Information message\n"); + IMSG_WARN("Warning message\n"); + IMSG_ERROR("Error message\n"); + + IMSG_LEAVE(); + + IMSG_PROFILE_E("LOG_TEST"); + + return 0; +} + +static DEVICE_ATTR_RO(imsg_log_test); + +uint32_t get_imsg_log_level(void) +{ + return imsg_log_level; +} + +static ssize_t imsg_log_level_show(struct device *cd, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", get_imsg_log_level()); +} + +#if defined(CONFIG_MICROTRUST_DEBUG) +static void set_imsg_log_level(uint32_t lv) +{ + imsg_log_level = lv; +} + +static ssize_t imsg_log_level_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + unsigned long new; + int ret; + + ret = kstrtoul(buf, 0, &new); + if (ret < 0) + return ret; + + set_imsg_log_level(new); + return len; +} + +static DEVICE_ATTR_RW(imsg_log_level); +#else +static DEVICE_ATTR_RO(imsg_log_level); +#endif + +#define DRIVER_LOADER_HOSTNAME "bta_loader" +#define UUID_STRING_LENGTH 32 + +static struct TEEC_Context ut_drv_context; +static bool is_context_init; +static LIST_HEAD(ut_drv_list); + +/* + * This function is a workaround solution to fix sscanf() parsing string issue. + * sscanf() cannot correctly parsing an UUID string directly. + * We need to separate the UUID string into chunks and then deal with them. + */ +static size_t hex_str_to_value(const char *s, size_t bytes, void *val) +{ + char tmp_buf[10] = {0}; + int ret = 0; + + memcpy(tmp_buf, s, bytes); + + switch (bytes) { + case 8: + ret = sscanf(tmp_buf, "%08x", (uint32_t *)val); + break; + case 4: + ret = sscanf(tmp_buf, "%04hx", (uint16_t *)val); + break; + case 2: + ret = sscanf(tmp_buf, "%02hhx", (uint8_t *)val); + break; + } + + if (ret != 1) + return 0; + + return bytes; +} + +static void str_to_uuid(struct TEEC_UUID *uuid, const char *buf) +{ + int i = 0; + const char *s = buf; + + s += hex_str_to_value(s, 8, &uuid->timeLow); + s += hex_str_to_value(s, 4, &uuid->timeMid); + s += hex_str_to_value(s, 4, &uuid->timeHiAndVersion); + + for (i = 0; i < 8; i++) + s += hex_str_to_value(s, 2, &uuid->clockSeqAndNode[i]); +} + +static inline void uuid_to_str(struct TEEC_UUID *uuid, char *buf) +{ + snprintf(buf, UUID_STRING_LENGTH, + "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x", + uuid->timeLow, uuid->timeMid, + uuid->timeHiAndVersion, + uuid->clockSeqAndNode[0], uuid->clockSeqAndNode[1], + uuid->clockSeqAndNode[2], uuid->clockSeqAndNode[3], + uuid->clockSeqAndNode[4], uuid->clockSeqAndNode[5], + uuid->clockSeqAndNode[6], uuid->clockSeqAndNode[7]); +} + +static inline void print_uuid(struct TEEC_UUID *uuid) +{ + IMSG_DEBUG("uuid: %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x\n", + uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, + uuid->clockSeqAndNode[0], uuid->clockSeqAndNode[1], + uuid->clockSeqAndNode[2], uuid->clockSeqAndNode[3], + uuid->clockSeqAndNode[4], uuid->clockSeqAndNode[5], + uuid->clockSeqAndNode[6], uuid->clockSeqAndNode[7]); +} + +static bool is_uuid_equal(const struct TEEC_UUID *uuid1, + const struct TEEC_UUID *uuid2) +{ + return !memcmp(uuid1, uuid2, sizeof(struct TEEC_UUID)); +} + +struct ut_drv_entry *find_ut_drv_entry_by_uuid(struct TEEC_UUID *uuid) +{ + struct ut_drv_entry *tmp_entry; + + list_for_each_entry(tmp_entry, &ut_drv_list, list) + if (is_uuid_equal(&tmp_entry->uuid, uuid)) + return tmp_entry; + + return NULL; +} + +struct ut_drv_entry *find_ut_drv_entry_by_driver_id(uint32_t driver_id) +{ + struct ut_drv_entry *tmp_entry; + + list_for_each_entry(tmp_entry, &ut_drv_list, list) + if (tmp_entry->driver_id == driver_id) + return tmp_entry; + + return NULL; +} + +static int open_driver_session(struct ut_drv_entry *ut_drv) +{ + struct TEEC_UUID *driver_uuid = &ut_drv->uuid; + struct TEEC_Session *session = &ut_drv->session; + unsigned int res; + + res = TEEC_OpenSession(&ut_drv_context, session, + driver_uuid, TEEC_LOGIN_PUBLIC, + NULL, NULL, NULL); + + if (res != TEEC_SUCCESS) { + IMSG_DEBUG("failed to load driver, res 0x%0x\n", res); + return -EINVAL; + } + + return 0; +} + +static int get_driver_id(struct ut_drv_entry *ut_drv) +{ + struct TEEC_Operation op = {0}; + struct ut_drv_param driver_param; + unsigned int res; + + driver_param.cmd_id = UT_DRV_GET_DRIVER_ID; + + prepare_params(&op, (void *)&driver_param, + sizeof(struct ut_drv_param)); + + res = TEEC_InvokeCommand(&ut_drv->session, + driver_param.cmd_id, &op, NULL); + if (res != TEEC_SUCCESS) { + int ret = get_result(&op); + + IMSG_ERROR("failed to get id by UUID %08x res 0x%x ret 0x%x\n", + ut_drv->uuid.timeLow, res, ret); + return ret; + } + + ut_drv->driver_id = get_result(&op); + + return 0; +} + +static int load_ut_drv(struct TEEC_UUID *uuid, unsigned int flags) +{ + int res; + int ret = 0; + struct ut_drv_entry *new_entry, *tmp_entry; + struct TEEC_UUID spi_uuid = { 0x93feffcc, 0xd8ca, 0x11e7, + { 0x96, 0xc7, 0xc7, 0xa2, + 0x1a, 0xcb, 0x49, 0x32 } }; + + if (!is_teei_ready()) { + IMSG_WARN("TEE is not ready\n"); + return -EBUSY; + } + + mutex_lock(&drv_load_mutex); + + if (!is_context_init) { + res = TEEC_InitializeContext(DRIVER_LOADER_HOSTNAME, + &ut_drv_context); + if (res != TEEC_SUCCESS) { + IMSG_ERROR("failed to initialize context 0x%x\n", res); + ret = -EINVAL; + goto exit; + } + + is_context_init = true; + } + + tmp_entry = find_ut_drv_entry_by_uuid(uuid); + if (tmp_entry) { + IMSG_INFO("driver already loaded\n"); + goto exit; + } + + new_entry = kzalloc(sizeof(struct ut_drv_entry), GFP_KERNEL); + if (!new_entry) { + IMSG_ERROR("failed to allocate memory for ut_drv_entry\n"); + ret = -ENOMEM; + goto exit; + } + + memcpy(&new_entry->uuid, uuid, sizeof(struct TEEC_UUID)); + new_entry->driver_id = 0; + + res = open_driver_session(new_entry); + if (res != TEEC_SUCCESS) { + ret = -EIO; + goto fail; + } + if (flags == TEEI_DRV) { + res = get_driver_id(new_entry); + if (res != TEEC_SUCCESS) { + ret = -EIO; + goto fail_get_driver_id; + } + + IMSG_DEBUG("load driver successfully, driver_id 0x%x\n", + new_entry->driver_id); + } + list_add_tail(&new_entry->list, &ut_drv_list); + + if (is_uuid_equal(&new_entry->uuid, &spi_uuid)) { + IMSG_DEBUG("spi driver is loaded successful!\n"); + spi_ready_flag = 1; + wake_up(&__wait_spi_wq); + } + + goto exit; + +fail_get_driver_id: + TEEC_CloseSession(&new_entry->session); +fail: + kfree(new_entry); +exit: + mutex_unlock(&drv_load_mutex); + return ret; +} + +int tz_load_drv(struct TEEC_UUID *uuid) +{ + return load_ut_drv(uuid, TEEI_DRV); +} +int tz_load_ta_by_str(const char *buf) +{ + struct TEEC_UUID uuid; + size_t len = strlen(buf); + int res; + + if (len < UUID_STRING_LENGTH) { + IMSG_ERROR("bad UUID length, buf '%s' len %zd\n", + buf, len); + return -EINVAL; + } + + str_to_uuid(&uuid, buf); + print_uuid(&uuid); + + res = load_ut_drv(&uuid, TEEI_TA); + if (res) + IMSG_DEBUG("load secure ta failed(uuid: %s)\n", + buf); + + return res; +} +int tz_load_drv_by_str(const char *buf) +{ + struct TEEC_UUID uuid; + size_t len = strlen(buf); + int res; + + if (len < UUID_STRING_LENGTH) { + IMSG_ERROR("bad UUID length, buf '%s' len %zd\n", + buf, len); + return -EINVAL; + } + + str_to_uuid(&uuid, buf); + print_uuid(&uuid); + + res = load_ut_drv(&uuid, TEEI_DRV); + if (res) + IMSG_DEBUG("load secure driver failed(uuid: %s)\n", + buf); + + return res; +} + +static ssize_t load_ut_drv_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + int ret; + struct TEEC_UUID uuid; + + if (len < UUID_STRING_LENGTH) { + IMSG_ERROR("bad UUID length, buf '%s' len %zd\n", buf, len); + return len; + } + + str_to_uuid(&uuid, buf); + print_uuid(&uuid); + + ret = load_ut_drv(&uuid, TEEI_DRV); + if (ret) + IMSG_ERROR("failed to load ut driver, ret %d\n", ret); + + return len; +} + +static DEVICE_ATTR_WO(load_ut_drv); + +static int unload_ut_drv(struct TEEC_UUID *uuid) +{ + struct ut_drv_entry *entry; + + mutex_lock(&drv_load_mutex); + + entry = find_ut_drv_entry_by_uuid(uuid); + if (!entry) { + IMSG_INFO("driver not found\n"); + goto exit; + } + + TEEC_CloseSession(&entry->session); + + list_del(&entry->list); + + IMSG_DEBUG("unload driver successfully, driver_id 0x%x\n", + entry->driver_id); + + kfree(entry); + +exit: + mutex_unlock(&drv_load_mutex); + return 0; +} + +int tz_unload_drv(struct TEEC_UUID *uuid) +{ + return unload_ut_drv(uuid); +} + +static ssize_t unload_ut_drv_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct TEEC_UUID uuid; + int ret; + + if (len < UUID_STRING_LENGTH) { + IMSG_ERROR("bad UUID length, buf '%s' len %zd\n", buf, len); + return len; + } + + str_to_uuid(&uuid, buf); + + ret = unload_ut_drv(&uuid); + if (ret) + IMSG_ERROR("failed to unload ut driver, ret %d\n", ret); + + return len; +} +static DEVICE_ATTR_WO(unload_ut_drv); + +static ssize_t list_ut_drv_show(struct device *cd, + struct device_attribute *attr, char *buf) +{ + struct ut_drv_entry *entry; + char uuid_str[UUID_STRING_LENGTH] = {0}; + char *s = buf; + + list_for_each_entry(entry, &ut_drv_list, list) { + uuid_to_str(&entry->uuid, uuid_str); + s += sprintf(s, "%s\n", uuid_str); + } + + return (ssize_t)(s - buf); +} +static DEVICE_ATTR_RO(list_ut_drv); + +#ifdef CONFIG_MICROTRUST_TEST_DRIVERS + +#define TEST_DRIVER_ID 0x77000012 + +static ssize_t dcih_notify_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char *s = buf; + int ret; + + ret = get_dcih_notify_test_result(); + + s += sprintf(s, "%d", ret); + + return (ssize_t)(s - buf); +} + +static ssize_t dcih_notify_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + start_dcih_notify_test(TEST_DRIVER_ID); + + return len; +} +static DEVICE_ATTR_RW(dcih_notify_test); + +static ssize_t dcih_wait_notify_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char *s = buf; + int ret; + + ret = get_dcih_wait_notify_test_result(); + + s += sprintf(s, "%d", ret); + + return (ssize_t)(s - buf); +} + +static ssize_t dcih_wait_notify_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + start_dcih_wait_notify_test(TEST_DRIVER_ID); + + return len; +} +static DEVICE_ATTR_RW(dcih_wait_notify_test); + +#endif + +static int notify_ree_result = -EINVAL; +static DEFINE_MUTEX(notify_ree_result_mutex); + +static ssize_t notify_ree_dci_handler_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char *s = buf; + + mutex_lock(¬ify_ree_result_mutex); + IMSG_DEBUG("notify_ree_result %d\n", notify_ree_result); + s += sprintf(s, "%d\n", notify_ree_result); + notify_ree_result = -EINVAL; + mutex_unlock(¬ify_ree_result_mutex); + + return (ssize_t)(s - buf); +} + +static ssize_t notify_ree_dci_handler_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + uint32_t driver_id; + + hex_str_to_value(buf, 8, &driver_id); + IMSG_DEBUG("driver_id: 0x%x\n", driver_id); + + mutex_lock(¬ify_ree_result_mutex); + notify_ree_result = tz_notify_ree_handler(driver_id); + mutex_unlock(¬ify_ree_result_mutex); + + return len; +} +static DEVICE_ATTR_RW(notify_ree_dci_handler); + +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE +static ssize_t current_bind_cpu_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char *s = buf; + int cpu = get_current_cpuid(); + + s += sprintf(s, "%d\n", cpu); + return (ssize_t)(s - buf); +} +static DEVICE_ATTR_RO(current_bind_cpu); +#endif + +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG +static ssize_t tzdriver_dynamical_debug_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char *s = buf; + + s += sprintf(s, "%d\n", tzdriver_dynamical_debug_flag); + return (ssize_t)(s - buf); +} + +static ssize_t tzdriver_dynamical_debug_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + uint32_t value; + + hex_str_to_value(buf, 8, &value); + + if ((value == 0) || (value == 1)) + tzdriver_dynamical_debug_flag = value; + + return len; +} +static DEVICE_ATTR_RW(tzdriver_dynamical_debug); +#endif + +static struct device_attribute *attr_list[] = { + &dev_attr_imsg_log_level, + &dev_attr_imsg_log_test, + &dev_attr_load_ut_drv, + &dev_attr_unload_ut_drv, + &dev_attr_list_ut_drv, +#ifdef CONFIG_MICROTRUST_TEST_DRIVERS + &dev_attr_dcih_notify_test, + &dev_attr_dcih_wait_notify_test, +#endif + &dev_attr_notify_ree_dci_handler, +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE + &dev_attr_current_bind_cpu, +#endif +#ifdef CONFIG_MICROTRUST_TZDRIVER_DYNAMICAL_DEBUG + &dev_attr_tzdriver_dynamical_debug, +#endif + NULL +}; + +void remove_sysfs(struct platform_device *pdev) +{ + int i; + + if (is_context_init) + TEEC_FinalizeContext(&ut_drv_context); + + for (i = 0; attr_list[i]; i++) + device_remove_file(&pdev->dev, attr_list[i]); +} + +int init_sysfs(struct platform_device *pdev) +{ + int res; + int i; + + for (i = 0; attr_list[i]; i++) { + res = device_create_file(&pdev->dev, attr_list[i]); + if (res) { + IMSG_ERROR("failed to create sysfs entry: %s\n", + attr_list[i]->attr.name); + break; + } + } + + if (res) + remove_sysfs(pdev); + + return res; +} diff --git a/drivers/tee/teei/300/tz_driver/teei_cancel_cmd.c b/drivers/tee/teei/300/tz_driver/teei_cancel_cmd.c new file mode 100644 index 000000000000..b6d1d072730a --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/teei_cancel_cmd.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include "teei_cancel_cmd.h" +#include "teei_id.h" +#include "sched_status.h" +#include "nt_smc_call.h" +#include "teei_log.h" +#include "teei_common.h" +#include "utdriver_macro.h" +#include "switch_queue.h" +#include "teei_client_main.h" +#include "backward_driver.h" +#include + +#define IMSG_TAG "[tz_driver]" +#include +#include + +struct cancel_command_struct { + unsigned long mem_size; + int retVal; +}; + +struct cancel_command_struct cancel_command_entry; +unsigned long cancel_message_buff; + +int send_cancel_command(unsigned long share_memory_size) +{ + struct teei_fdrv fdrv; + int retVal = 0; + + fdrv.call_type = CANCEL_SYS_NO; + fdrv.buff_size = share_memory_size; + + + retVal = fdrv_notify(&fdrv); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Failed to call the fdrv_notify [%d]!\n", + __func__, __LINE__, retVal); + return retVal; + } + + return 0; +} + + +unsigned long create_cancel_fdrv(int buff_size) +{ + struct teei_fdrv fdrv; + long retVal = 0; + + fdrv.call_type = CANCEL_SYS_NO; + fdrv.buff_size = buff_size; + + retVal = create_fdrv(&fdrv); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] TEEI: Failed to call the create_fdrv!\n", + __func__, __LINE__); + return 0; + } + + return (unsigned long)fdrv.buf; +} diff --git a/drivers/tee/teei/300/tz_driver/teei_client_main.c b/drivers/tee/teei/300/tz_driver/teei_client_main.c new file mode 100644 index 000000000000..bbc81e2464ce --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/teei_client_main.c @@ -0,0 +1,1210 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#define IMSG_TAG "[tz_driver]" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEEI_SWITCH_BIG_CORE + +#ifdef TEEI_FIND_PREFER_CORE_AUTO +#include +#endif + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +#include +#endif + +#ifdef CONFIG_MTPROF +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +#include +#else +#include "bootprof.h" +#endif /* KERNEL_VERSION */ +#endif /* CONFIG_MTPROF */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../teei_fp/fp_func.h> + +#if (CONFIG_MICROTRUST_TZ_DRIVER_MTK_BOOTPROF && CONFIG_MTPROF) + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +#define TEEI_BOOT_FOOTPRINT(str) bootprof_log_boot(str) +#else +#define TEEI_BOOT_FOOTPRINT(str) log_boot(str) +#endif + +#else +#define TEEI_BOOT_FOOTPRINT(str) IMSG_PRINTK("%s\n", str) +#endif + +#define DECLARE_SEMA(name, init_value) \ + struct semaphore name = __SEMAPHORE_INITIALIZER(name, init_value) + +#define DECLARE_RW_SEMA(name) \ + struct rw_semaphore name = __RWSEM_INITIALIZER(name) + +DECLARE_RW_SEMA(teei_cpus_lock); +DECLARE_SEMA(boot_sema, 0); +DECLARE_SEMA(pm_sema, 0); + +DECLARE_COMPLETION(boot_decryto_lock); + +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE +#define TZ_PREFER_BIND_CORE (6) +#endif + +/* ARMv8.2 for CA55, CA75 etc */ +static int teei_cpu_id_arm82[] = { + 0x81000000, 0x81000100, 0x81000200, 0x81000300, + 0x81000400, 0x81000500, 0x81000600, 0x81000700, + 0x81000800, 0x81000900, 0x81000a00, 0x81000b00}; + +/* ARMv8 */ +static int teei_cpu_id_arm80[] = { + 0x0000, 0x0001, 0x0002, 0x0003, + 0x0100, 0x0101, 0x0102, 0x0103, + 0x0200, 0x0201, 0x0202, 0x0203}; + +static int *teei_cpu_id; + +enum { + TEEI_BOOT_OK = 0, + TEEI_BOOT_ERROR_CREATE_TLOG_BUF = 1, + TEEI_BOOT_ERROR_CREATE_TLOG_THREAD = 2, + TEEI_BOOT_ERROR_CREATE_VFS_ADDR = 3, + TEEI_BOOT_ERROR_LOAD_SOTER_FAILED = 4, + TEEI_BOOT_ERROR_INIT_CMD_BUFF_FAILED = 5, + TEEI_BOOT_ERROR_INIT_UTGATE_FAILED = 6, + TEEI_BOOT_ERROR_INIT_SERVICE1_FAILED = 7, + TEEI_BOOT_ERROR_INIT_CAPI_FAILED = 8, + TEEI_BOOT_ERROR_INIT_SERVICE2_FAILED = 9, + TEEI_BOOT_ERROR_LOAD_TA_FAILED = 10, +}; + +struct teei_boot_error_item { + unsigned int id; + char *str; +}; +struct teei_boot_error_item teei_boot_error_items[] = { + { TEEI_BOOT_OK, "TEEI_BOOT_OK"}, + { TEEI_BOOT_ERROR_CREATE_TLOG_BUF, + "TEEI_BOOT_ERROR_CREATE_TLOG_BUF" }, + { TEEI_BOOT_ERROR_CREATE_TLOG_THREAD, + "TEEI_BOOT_ERROR_CREATE_TLOG_THREAD" }, + { TEEI_BOOT_ERROR_CREATE_VFS_ADDR, + "TEEI_BOOT_ERROR_CREATE_VFS_ADDR" }, + { TEEI_BOOT_ERROR_LOAD_SOTER_FAILED, + "TEEI_BOOT_ERROR_LOAD_SOTER_FAILED" }, + { TEEI_BOOT_ERROR_INIT_CMD_BUFF_FAILED, + "TEEI_BOOT_ERROR_INIT_CMD_BUFF_FAILED" }, + { TEEI_BOOT_ERROR_INIT_UTGATE_FAILED, + "TEEI_BOOT_ERROR_INIT_UTGATE_FAILED" }, + { TEEI_BOOT_ERROR_INIT_SERVICE1_FAILED, + "TEEI_BOOT_ERROR_INIT_SERVICE1_FAILED" }, + { TEEI_BOOT_ERROR_INIT_CAPI_FAILED, + "TEEI_BOOT_ERROR_INIT_CAPI_FAILED" }, + { TEEI_BOOT_ERROR_INIT_SERVICE2_FAILED, + "TEEI_BOOT_ERROR_INIT_SERVICE2_FAILED" }, + { TEEI_BOOT_ERROR_LOAD_TA_FAILED, + "TEEI_BOOT_ERROR_LOAD_TA_FAILED" } +}; + +char *teei_boot_error_to_string(uint32_t id) +{ + int i = 0; + + for (i = 0; i < (sizeof(teei_boot_error_items) + / sizeof(struct teei_boot_error_item)); i++) { + if (id == teei_boot_error_items[i].id) + return teei_boot_error_items[i].str; + } + + return "TEEI_BOOT_ERROR_NDEFINED"; +} + +struct workqueue_struct *secure_wq; + +static int current_cpu_id; + +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE +#if KERNEL_VERSION(4, 14, 0) >= LINUX_VERSION_CODE +static int tz_driver_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu); +static struct notifier_block tz_driver_cpu_notifer = { + .notifier_call = tz_driver_cpu_callback, +}; +#endif +#endif + +unsigned long teei_config_flag; +unsigned int soter_error_flag; +unsigned long boot_vfs_addr; +unsigned long boot_soter_flag; +unsigned long device_file_cnt; + +struct list_head g_block_link; + +/* For keymaster */ +unsigned long teei_capi_ready; + + + +static unsigned int teei_flags; +static dev_t teei_config_device_no; +static struct cdev teei_config_cdev; +static struct class *config_driver_class; + +struct timeval stime; +struct timeval etime; +struct task_struct *teei_switch_task; +struct task_struct *teei_bdrv_task; +struct task_struct *teei_log_task; +static struct cpumask mask = { CPU_BITS_NONE }; +static struct class *driver_class; +static dev_t teei_client_device_no; +static struct cdev teei_client_cdev; + +DEFINE_KTHREAD_WORKER(ut_fastcall_worker); + + +static struct tz_driver_state *tz_drv_state; + +struct tz_driver_state *get_tz_drv_state(void) +{ + return tz_drv_state; +} + +void *tz_malloc(size_t size, int flags) +{ + void *ptr = kmalloc(size, flags | GFP_ATOMIC); + return ptr; +} + +void *tz_malloc_shared_mem(size_t size, int flags) +{ +#ifdef UT_DMA_ZONE + return (void *) __get_free_pages(flags | GFP_DMA, + get_order(ROUND_UP(size, SZ_4K))); +#else + return (void *) __get_free_pages(flags, + get_order(ROUND_UP(size, SZ_4K))); +#endif +} + +void tz_free_shared_mem(void *addr, size_t size) +{ + free_pages((unsigned long)addr, get_order(ROUND_UP(size, SZ_4K))); +} + +int teei_move_cpu_context(int target_cpu_id, int original_cpu_id) +{ + teei_secure_call(N_SWITCH_CORE, teei_cpu_id[target_cpu_id], + teei_cpu_id[original_cpu_id], 0); + + return 0; +} + +void set_current_cpuid(int cpu) +{ + current_cpu_id = cpu; +} + +int get_current_cpuid(void) +{ + return current_cpu_id; +} + +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE + +static bool is_prefer_core(int cpu) +{ + /* bind to a specific core */ + if (cpu == TZ_PREFER_BIND_CORE) + return true; + + return false; +} + +static int find_prefer_core(int excluded_cpu) +{ + int i = 0; + int prefer_core = -1; + + /* search for prefer cpu firstly */ + for_each_online_cpu(i) { + if (i == excluded_cpu) + continue; + + if (is_prefer_core(i)) { + prefer_core = i; + break; + } + } + + /* if prefer is found, return directly */ + if (prefer_core != -1) + return prefer_core; + + /* if not found, then search for other online cpu */ + for_each_online_cpu(i) { + if (i == excluded_cpu) + continue; + + prefer_core = i; + /* break when next active cpu has been selected */ + break; + } + + return prefer_core; +} + +static bool is_prefer_core_binded(void) +{ + unsigned int curr = get_current_cpuid(); + + if (is_prefer_core(curr)) + return true; + + return false; +} + +static bool is_prefer_core_onlined(void) +{ + int i = 0; + + for_each_online_cpu(i) { + if (is_prefer_core(i)) + return true; + } + + return false; +} + +int handle_switch_core(int cpu) +{ + int switch_to_cpu_id = 0; + + switch_to_cpu_id = find_prefer_core(cpu); + + IMSG_PRINTK("[%s][%d]before cpumask set cpu, find %d\n", + __func__, __LINE__, switch_to_cpu_id); + + set_cpus_allowed_ptr(teei_switch_task, cpumask_of(switch_to_cpu_id)); + + teei_secure_call(N_SWITCH_CORE, + teei_cpu_id[switch_to_cpu_id], teei_cpu_id[cpu], 0); + + current_cpu_id = switch_to_cpu_id; + + IMSG_PRINTK("change cpu id from %d(0x%lx) to %d(0x%lx)\n", + cpu, teei_cpu_id[cpu], + switch_to_cpu_id, teei_cpu_id[switch_to_cpu_id]); + + up(&pm_sema); + + return 0; +} + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +static int nq_cpu_up_prep(unsigned int cpu) +{ +#ifdef TEEI_SWITCH_BIG_CORE + int retVal = 0; + unsigned int sched_cpu = get_current_cpuid(); + + IMSG_DEBUG("current_cpu_id = %d power on %d\n", + sched_cpu, cpu); + + if (cpu == TZ_PREFER_BIND_CORE) { + IMSG_DEBUG("cpu up: prepare for changing %d to %d\n", + sched_cpu, cpu); + + retVal = add_work_entry(SWITCH_CORE_TYPE, + (unsigned long)sched_cpu, 0, 0, 0); + + teei_notify_switch_fn(); + + down(&pm_sema); + } + return retVal; +#else + return 0; +#endif +} + + +static int nq_cpu_down_prep(unsigned int cpu) +{ + int retVal = 0; + unsigned int sched_cpu = get_current_cpuid(); + + if (cpu == sched_cpu) { + IMSG_PRINTK("cpu down prepare for %d.\n", cpu); + retVal = add_work_entry(SWITCH_CORE_TYPE, (unsigned long)cpu, + 0, 0, 0); + teei_notify_switch_fn(); + down(&pm_sema); + } else if (is_prefer_core(cpu)) + IMSG_DEBUG("cpu down prepare for prefer %d.\n", cpu); + else if (!is_prefer_core_binded() + && is_prefer_core_onlined()) { + IMSG_PRINTK("cpu down prepare for changing %d %d.\n", + sched_cpu, cpu); + retVal = add_work_entry(SWITCH_CORE_TYPE, + (unsigned long)sched_cpu, 0, 0, 0); + teei_notify_switch_fn(); + down(&pm_sema); + } + return retVal; +} + +#elif KERNEL_VERSION(3, 18, 0) <= LINUX_VERSION_CODE + +static int tz_driver_cpu_callback(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + unsigned int sched_cpu = get_current_cpuid(); + + switch (action) { + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + if (cpu == sched_cpu) { + IMSG_DEBUG("cpu down prepare for %d.\n", cpu); + add_work_entry(SWITCH_CORE_TYPE, (unsigned long)cpu, + 0, 0, 0); + teei_notify_switch_fn(); + down(&pm_sema); + } else if (is_prefer_core(cpu)) + IMSG_DEBUG("cpu down prepare for prefer %d.\n", cpu); + else if (!is_prefer_core_binded() + && is_prefer_core_onlined()) { + IMSG_DEBUG("cpu down prepare for changing %d %d.\n", + sched_cpu, cpu); + add_work_entry(SWITCH_CORE_TYPE, + (unsigned long)sched_cpu, 0, 0, 0); + teei_notify_switch_fn(); + down(&pm_sema); + } + break; + +#ifdef TEEI_SWITCH_BIG_CORE + case CPU_ONLINE: + if (cpu == TZ_PREFER_BIND_CORE) { + IMSG_DEBUG("cpu up: prepare for changing %d to %d.\n", + sched_cpu, cpu); + add_work_entry(SWITCH_CORE_TYPE, + (unsigned long)sched_cpu, 0, 0, 0); + teei_notify_switch_fn(); + down(&pm_sema); + } + + break; +#endif + + default: + break; + } + return NOTIFY_OK; +} + +#endif +#endif /* CONFIG_MICROTRUST_DYNAMIC_CORE */ + + +int t_os_load_image(void) +{ + int retVal = 0; + + retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Failed to call the add_work_entry!\n", + __func__, __LINE__); + } + + retVal = add_nq_entry(TEEI_LOAD_TEE, 0, + (unsigned long long)(&boot_sema), + 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Failed to call the add_nq_entry!\n", + __func__, __LINE__); + } + + teei_notify_switch_fn(); + + down(&boot_sema); + + return retVal; +} + +static void boot_stage1(unsigned long vfs_addr, unsigned long tlog_addr) +{ + int retVal = 0; + + switch_input_index = ((unsigned long)switch_input_index + 1) % 10000; + + retVal = add_work_entry(SMC_CALL_TYPE, N_INIT_T_BOOT_STAGE1, + vfs_addr, tlog_addr, 0); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] TEEI: Failed to call add_work_entry!\n", + __func__, __LINE__); + return; + } + + teei_notify_switch_fn(); + + down(&(boot_sema)); +} + +long teei_create_drv_shm(void) +{ + long retVal = 0; + + retVal = create_all_fdrv(); + if (retVal < 0) { + IMSG_ERROR("[%s][%d] create_all_fdrv failed!\n", + __func__, __LINE__); + return -1; + } + if (soter_error_flag == 1) + return -1; + + /** + * init service handler + */ + retVal = init_all_service_handlers(); + if (retVal < 0) { + IMSG_ERROR("[%s][%d] init_all_service_handlers failed!\n", + __func__, __LINE__); + return -1; + } + if (soter_error_flag == 1) + return -1; + + return 0; +} + +long teei_service_init_second(void) +{ + IMSG_DEBUG("[%s][%d] begin to create fp buffer!\n", + __func__, __LINE__); + + if (soter_error_flag == 1) + return -1; + + return 0; +} + +/** + * @brief init TEEI Framework + * init Soter OS + * init Global Schedule + * init Forward Call Service + * init CallBack Service + * @return + */ + +struct notifier_block ut_smc_nb; + +static int init_teei_framework(void) +{ + long retVal = 0; + struct tz_log_state *s = dev_get_platdata( + &tz_drv_state->tz_log_pdev->dev); + + phys_addr_t tz_log_buf_pa = page_to_phys(s->log_pages); + + boot_soter_flag = START_STATUS; + + secure_wq = create_workqueue("Secure Call"); + TEEI_BOOT_FOOTPRINT("TEEI WorkQueue Created"); + +#ifdef UT_DMA_ZONE + boot_vfs_addr = (unsigned long)__get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(ROUND_UP(VFS_SIZE, SZ_4K))); +#else + boot_vfs_addr = (unsigned long) __get_free_pages(GFP_KERNEL, + get_order(ROUND_UP(VFS_SIZE, SZ_4K))); +#endif + if ((unsigned char *)boot_vfs_addr == NULL) + return TEEI_BOOT_ERROR_CREATE_VFS_ADDR; + + TEEI_BOOT_FOOTPRINT("TEEI VFS Buffer Created"); + + cpus_read_lock(); + + boot_stage1((unsigned long)virt_to_phys((void *)boot_vfs_addr), + (unsigned long)tz_log_buf_pa); + + cpus_read_unlock(); + + TEEI_BOOT_FOOTPRINT("TEEI BOOT Stage1 Completed"); + + free_pages(boot_vfs_addr, get_order(ROUND_UP(VFS_SIZE, SZ_4K))); + + boot_soter_flag = END_STATUS; + if (soter_error_flag == 1) + return TEEI_BOOT_ERROR_LOAD_SOTER_FAILED; + + cpus_read_lock(); + + retVal = create_nq_buffer(); + + cpus_read_unlock(); + + if (retVal < 0) + return TEEI_BOOT_ERROR_INIT_CMD_BUFF_FAILED; + + TEEI_BOOT_FOOTPRINT("TEEI BOOT CREATE NQ DONE"); + + cpus_read_lock(); + + retVal = teei_create_drv_shm(); + + cpus_read_unlock(); + + if (retVal == -1) + return TEEI_BOOT_ERROR_INIT_SERVICE1_FAILED; + + TEEI_BOOT_FOOTPRINT("TEEI BOOT CREATE DRV SHM DONE"); + + retVal = teei_new_capi_init(); + + if (retVal < 0) + return TEEI_BOOT_ERROR_INIT_CAPI_FAILED; + + TEEI_BOOT_FOOTPRINT("TEEI NEW CAPI Inited"); + + /* waiting for keymaster shm ready and anable the keymaster IOCTL */ + teei_capi_ready = 1; + up(&keymaster_api_lock); + + TEEI_BOOT_FOOTPRINT("TEEI BOOT Keymaster Unlocked"); + + /* android notify the uTdriver that the TAs is ready !*/ + wait_for_completion(&boot_decryto_lock); + TEEI_BOOT_FOOTPRINT("TEEI BOOT Decrypt Unlocked"); + + cpus_read_lock(); + + retVal = teei_service_init_second(); + + cpus_read_unlock(); + + TEEI_BOOT_FOOTPRINT("TEEI BOOT Service2 Inited"); + if (retVal == -1) + return TEEI_BOOT_ERROR_INIT_SERVICE2_FAILED; + + cpus_read_lock(); + + t_os_load_image(); + + cpus_read_unlock(); + + TEEI_BOOT_FOOTPRINT("TEEI BOOT Load TEES Completed"); + if (soter_error_flag == 1) + return TEEI_BOOT_ERROR_LOAD_TA_FAILED; + + teei_config_flag = 1; + +#ifdef CONFIG_MICROTRUST_FP_DRIVER + wake_up(&__fp_open_wq); +#endif + TEEI_BOOT_FOOTPRINT("TEEI BOOT All Completed"); + + return TEEI_BOOT_OK; +} + +/** + * @brief + * + * @param file + * @param cmd + * @param arg + * + * @return + */ + +int is_teei_ready(void) +{ + return teei_flags; +} +EXPORT_SYMBOL(is_teei_ready); + +#ifdef TEEI_FIND_PREFER_CORE_AUTO +int teei_get_max_freq(int cpu_index) +{ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + return arch_max_cpu_freq(NULL, cpu_index); +#elif KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + return arch_scale_get_max_freq(cpu_index); +#endif + return 0; +} +#endif + +static long teei_config_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int retVal = 0; + struct init_param param; + unsigned int teei_ta_flags; + + switch (cmd) { + + case TEEI_CONFIG_IOCTL_INIT_TEEI: + if (teei_flags != 1) { + long res; + int i; + + res = copy_from_user(¶m, (void *)arg, + sizeof(struct init_param)); + if (res) { + IMSG_ERROR("failed to copy from user\n"); + retVal = -EINVAL; + goto err; + } + + retVal = init_teei_framework(); + + TEEI_BOOT_FOOTPRINT( + teei_boot_error_to_string(retVal)); + + teei_flags = 1; + + TEEI_BOOT_FOOTPRINT("TEEI start to load driver TAs"); + if (param.uuid_count > MAX_DRV_UUIDS) { + IMSG_ERROR("TEEI uuid_count is invalid(%u)!\n", + (unsigned int)(param.uuid_count)); + return -EINVAL; + } + + teei_ta_flags = param.flag; + for (i = 0; i < param.uuid_count; i++) { + if ((teei_ta_flags >> i) & (0x01)) + tz_load_ta_by_str(param.uuids[i]); + else + tz_load_drv_by_str(param.uuids[i]); + } + + param.flag = teei_flags; + + TEEI_BOOT_FOOTPRINT("TEEI end of load driver TAs"); + + res = copy_to_user((void *)arg, ¶m, + sizeof(struct init_param)); + if (res) + IMSG_ERROR("failed to copy to user\n"); + } + + break; + case TEEI_CONFIG_IOCTL_UNLOCK: + complete(&boot_decryto_lock); + break; + + default: + retVal = -EINVAL; + } + +err: + return retVal; +} + +/** + * @brief The open operation of /dev/teei_config device node. + * + * @param inode + * @param file + * + * @return ENOMEM: no enough memory in the linux kernel + * 0: on success + */ + +static int teei_config_open(struct inode *inode, struct file *file) +{ + return 0; +} + +/** + * @brief The release operation of /dev/teei_config device node. + * + * @param inode: device inode structure + * @param file: struct file + * + * @return 0: on success + */ +static int teei_config_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t teei_config_read(struct file *filp, + char __user *buf, size_t size, loff_t *ppos) +{ + char *file_context = NULL; + int retVal = 0; + + file_context = kmalloc(size, GFP_KERNEL); + if (file_context == NULL) + return -ENOMEM; + + retVal = tz_driver_read_logs(file_context, (unsigned long)size); + if (retVal < 0) { + IMSG_ERROR("Failed to call the %s! retVal = %d\n", + __func__, retVal); + kfree(file_context); + return (ssize_t)retVal; + } + + if (copy_to_user(buf, file_context, retVal)) { + IMSG_ERROR("copy to user failed.\n"); + kfree(file_context); + return -EFAULT; + } + + kfree(file_context); + return (ssize_t)retVal; +} + +/** + * @brief + */ +static const struct file_operations teei_config_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = teei_config_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = teei_config_ioctl, +#endif + .open = teei_config_open, + .read = teei_config_read, + .release = teei_config_release +}; + +/** + * @brief TEEI Agent Driver initialization + * initialize Microtrust Tee environment + * @return + **/ + + +static int teei_config_init(void) +{ + int retVal = 0; + struct device *class_dev = NULL; + + retVal = alloc_chrdev_region(&teei_config_device_no, + 0, 1, TEEI_CONFIG_DEV); + + if (retVal < 0) { + IMSG_ERROR("alloc_chrdev_region failed %x.\n", retVal); + return retVal; + } + + config_driver_class = class_create(THIS_MODULE, TEEI_CONFIG_DEV); + if (IS_ERR(config_driver_class)) { + retVal = -ENOMEM; + IMSG_ERROR("class_create failed %x\n", retVal); + goto unregister_chrdev_region; + } + + class_dev = device_create(config_driver_class, NULL, + teei_config_device_no, NULL, TEEI_CONFIG_DEV); + + if (class_dev == NULL) { + IMSG_ERROR("class_device_create failed %x\n", retVal); + retVal = -ENOMEM; + goto class_destroy; + } + + cdev_init(&teei_config_cdev, &teei_config_fops); + teei_config_cdev.owner = THIS_MODULE; + + retVal = cdev_add(&teei_config_cdev, + MKDEV(MAJOR(teei_config_device_no), 0), 1); + + if (retVal < 0) { + IMSG_ERROR("cdev_add failed %x\n", retVal); + goto class_device_destroy; + } + + goto return_fn; + +class_device_destroy: + device_destroy(driver_class, teei_config_device_no); +class_destroy: + class_destroy(driver_class); +unregister_chrdev_region: + unregister_chrdev_region(teei_config_device_no, 1); +return_fn: + return retVal; +} + +/** + * @brief The open operation of /dev/teei_client device node. + * + * @param inode + * @param file + * + * @return ENOMEM: no enough memory in the linux kernel + * 0: on success + */ + +static int teei_client_open(struct inode *inode, struct file *file) +{ + return 0; +} + +void show_utdriver_lock_status(void) +{ + int retVal = 0; + + IMSG_PRINTK("[%s][%d] how_utdriver_lock_status begin.\n", + __func__, __LINE__); +#ifdef CONFIG_MICROTRUST_FP_DRIVER + retVal = down_trylock(&fp_api_lock); + if (retVal == 1) + IMSG_PRINTK("[%s][%d] fp_api_lock is down\n", + __func__, __LINE__); + else { + IMSG_PRINTK("[%s][%d] fp_api_lock is up\n", + __func__, __LINE__); + up(&fp_api_lock); + } +#endif + + retVal = down_trylock(&keymaster_api_lock); + if (retVal == 1) + IMSG_PRINTK("[%s][%d] keymaster_api_lock is down\n", + __func__, __LINE__); + else { + IMSG_PRINTK("[%s][%d] keymaster_api_lock is up\n", + __func__, __LINE__); + up(&keymaster_api_lock); + } + + + IMSG_PRINTK("[%s][%d] how_utdriver_lock_status end.\n", + __func__, __LINE__); + return; + +} + + +static ssize_t teei_client_dump(struct file *filp, + char __user *buf, size_t size, loff_t *ppos) +{ + IMSG_PRINTK("[%s][%d] begin.....\n", __func__, __LINE__); + + show_utdriver_lock_status(); + + IMSG_PRINTK("[%s][%d] finished.....\n", __func__, __LINE__); + + return 0; +} + +/** + * @brief The release operation of /dev/teei_client device node. + * + * @param inode: device inode structure + * @param file: struct file + * + * @return 0: on success + */ +static int teei_client_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/** + * @brief + */ +static const struct file_operations teei_client_fops = { + .owner = THIS_MODULE, + .open = teei_client_open, + .read = teei_client_dump, + .release = teei_client_release +}; + +static int teei_probe(struct platform_device *pdev) +{ + int ut_irq = 0; + + ut_irq = platform_get_irq(pdev, 0); + IMSG_INFO("teei device ut_irq is %d\n", ut_irq); + + if (init_sysfs(pdev) < 0) { + IMSG_ERROR("failed to init tz_driver sysfs\n"); + return -1; + } + + if (register_ut_irq_handler(ut_irq) < 0) { + IMSG_ERROR("teei_device can't register irq %d\n", ut_irq); + return -1; + } + + return 0; +} + +static int teei_remove(struct platform_device *pdev) +{ + remove_sysfs(pdev); + return 0; +} + +static const struct of_device_id teei_of_ids[] = { + { .compatible = "microtrust,utos", }, + {} +}; + +static struct platform_driver teei_driver = { + .probe = teei_probe, + .remove = teei_remove, + .suspend = NULL, + .resume = NULL, + .driver = { + .name = "utos", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = teei_of_ids, +#endif + }, +}; + +/** + * @brief TEEI Agent Driver initialization + * initialize service framework + * @return + */ +static int teei_client_init(void) +{ + int ret_code = 0; + struct device *class_dev = NULL; + + /* struct sched_param param = {.sched_priority = 50 }; */ + + /* IMSG_DEBUG("TEEI Agent Driver Module Init ...\n"); */ + + IMSG_DEBUG("=====================================================\n\n"); + IMSG_DEBUG("~~~~~~~uTos version [%s]~~~~~~~\n", UTOS_VERSION); + IMSG_DEBUG("=====================================================\n\n"); + + ret_code = alloc_chrdev_region(&teei_client_device_no, + 0, 1, TEEI_CLIENT_DEV); + + if (ret_code < 0) { + IMSG_ERROR("alloc_chrdev_region failed %x\n", ret_code); + return ret_code; + } + + ret_code = platform_driver_register(&teei_driver); + if (ret_code) { + IMSG_ERROR("unable to register teei driver(%d)\n", ret_code); + return ret_code; + } + + tz_drv_state = kzalloc(sizeof(struct tz_driver_state), GFP_KERNEL); + if (!tz_drv_state) + return -ENOMEM; + + mutex_init(&tz_drv_state->smc_lock); + ATOMIC_INIT_NOTIFIER_HEAD(&tz_drv_state->notifier); + + tz_drv_state->tz_log_pdev = platform_device_alloc("tz_log", 0); + if (!tz_drv_state->tz_log_pdev) + goto failed_alloc_dev; + + platform_device_add(tz_drv_state->tz_log_pdev); + + ret_code = tz_log_probe(tz_drv_state->tz_log_pdev); + if (ret_code) { + IMSG_ERROR("failed to initial tz_log driver (%d)\n", ret_code); + goto del_pdev; + } + + driver_class = class_create(THIS_MODULE, TEEI_CLIENT_DEV); + if (IS_ERR(driver_class)) { + ret_code = -ENOMEM; + IMSG_ERROR("class_create failed %x\n", ret_code); + goto unregister_chrdev_region; + } + + class_dev = device_create(driver_class, NULL, + teei_client_device_no, NULL, TEEI_CLIENT_DEV); + + if (class_dev == NULL) { + IMSG_ERROR("class_device_create failed %x\n", ret_code); + ret_code = -ENOMEM; + goto class_destroy; + } + + cdev_init(&teei_client_cdev, &teei_client_fops); + teei_client_cdev.owner = THIS_MODULE; + + ret_code = cdev_add(&teei_client_cdev, + MKDEV(MAJOR(teei_client_device_no), 0), 1); + + if (ret_code < 0) { + IMSG_ERROR("cdev_add failed %x\n", ret_code); + goto class_device_destroy; + } + + init_teei_switch_comp(); + teei_init_task_link(); + + if (read_cpuid_mpidr() & MPIDR_MT_BITMASK) + teei_cpu_id = teei_cpu_id_arm82; + else + teei_cpu_id = teei_cpu_id_arm80; + + IMSG_DEBUG("begin to create sub_thread.\n"); + + /* create the switch thread */ + teei_switch_task = kthread_create(teei_switch_fn, + NULL, "teei_switch_thread"); + + if (IS_ERR(teei_switch_task)) { + IMSG_ERROR("create switch thread failed: %ld\n", + PTR_ERR(teei_switch_task)); + teei_switch_task = NULL; + goto class_device_destroy; + } + +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE +#ifdef TEEI_SWITCH_BIG_CORE + if (cpu_online(TZ_PREFER_BIND_CORE)) { + current_cpu_id = TZ_PREFER_BIND_CORE; + teei_move_cpu_context(current_cpu_id, 0); + } +#endif + cpumask_set_cpu(get_current_cpuid(), &mask); + set_cpus_allowed_ptr(teei_switch_task, &mask); +#endif + + /* sched_setscheduler_nocheck(teei_switch_task, SCHED_FIFO, ¶m); */ + wake_up_process(teei_switch_task); + +#ifndef CONFIG_MICROTRUST_DYNAMIC_CORE + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "tee/teei:online", + nq_cpu_up_prep, nq_cpu_down_prep); +#elif KERNEL_VERSION(3, 18, 0) <= LINUX_VERSION_CODE + register_cpu_notifier(&tz_driver_cpu_notifer); + IMSG_DEBUG("after register cpu notify\n"); +#endif +#endif /* CONFIG_MICROTRUST_DYNAMIC_CORE */ + + init_bdrv_comp_fn(); + + /* create the backward handler thread */ + teei_bdrv_task = kthread_create(teei_bdrv_fn, + NULL, "teei_bdrv_thread"); + + if (IS_ERR(teei_bdrv_task)) { + IMSG_ERROR("create bdrv thread failed: %ld\n", + PTR_ERR(teei_bdrv_task)); + teei_bdrv_task = NULL; + goto class_device_destroy; + } + + wake_up_process(teei_bdrv_task); + + init_tlog_comp_fn(); + + /* create the teei log thread */ + teei_log_task = kthread_create(teei_log_fn, NULL, "teei_log_thread"); + if (IS_ERR(teei_log_task)) { + IMSG_ERROR("create teei log thread failed: %ld\n", + PTR_ERR(teei_log_task)); + teei_log_task = NULL; + goto class_device_destroy; + } + + wake_up_process(teei_log_task); + + IMSG_DEBUG("create the sub_thread successfully!\n"); + + + teei_config_init(); + + goto return_fn; + +class_device_destroy: + device_destroy(driver_class, teei_client_device_no); +class_destroy: + class_destroy(driver_class); +unregister_chrdev_region: + unregister_chrdev_region(teei_client_device_no, 1); + tz_log_remove(tz_drv_state->tz_log_pdev); +del_pdev: + platform_device_del(tz_drv_state->tz_log_pdev); +failed_alloc_dev: + platform_device_put(tz_drv_state->tz_log_pdev); + mutex_destroy(&tz_drv_state->smc_lock); + kfree(tz_drv_state); +return_fn: + return ret_code; +} + +/** + * @brief + */ +static void teei_client_exit(void) +{ + IMSG_INFO("teei_client exit"); + device_destroy(driver_class, teei_client_device_no); + class_destroy(driver_class); + unregister_chrdev_region(teei_client_device_no, 1); + platform_driver_unregister(&teei_driver); + if (tz_drv_state) { + tz_log_remove(tz_drv_state->tz_log_pdev); + platform_device_del(tz_drv_state->tz_log_pdev); + platform_device_put(tz_drv_state->tz_log_pdev); + mutex_destroy(&tz_drv_state->smc_lock); + kfree(tz_drv_state); + } +} + + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("TEEI "); +MODULE_DESCRIPTION("TEEI Agent"); +MODULE_VERSION("1.00"); + +module_init(teei_client_init); + +module_exit(teei_client_exit); diff --git a/drivers/tee/teei/300/tz_driver/teei_client_transfer_data.c b/drivers/tee/teei/300/tz_driver/teei_client_transfer_data.c new file mode 100644 index 000000000000..fbafee6f540c --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/teei_client_transfer_data.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include "teei_client_transfer_data.h" +#define IMSG_TAG "[tz_driver]" +#include +#include +#include + +int ut_pf_gp_initialize_context(struct TEEC_Context *context) +{ + const char *hostname = "bta_loader"; + TEEC_Result ret = 0; + + if (context == NULL) + return -1; + + memset(context, 0, sizeof(struct TEEC_Context)); + ret = TEEC_InitializeContext(hostname, context); + if (ret != TEEC_SUCCESS) + IMSG_ERROR("Failed to initialize context,err: %x", ret); + + return ret; +} + +int ut_pf_gp_finalize_context(struct TEEC_Context *context) +{ + if (context) + TEEC_FinalizeContext(context); + return 0; +} + +int ut_pf_gp_transfer_data(struct TEEC_Context *context, struct TEEC_UUID *uuid, + unsigned int command, void *buffer, unsigned long size) +{ + struct TEEC_Session session; + struct TEEC_Operation operation; + struct TEEC_SharedMemory sharedmem; + TEEC_Result result; + uint32_t returnOrigin = 0; + + if (NULL == context || NULL == uuid || NULL == buffer || size < 1) + return -1; + + memset(&session, 0, sizeof(session)); + result = TEEC_OpenSession(context, &session, uuid, TEEC_LOGIN_PUBLIC, + NULL, NULL, &returnOrigin); + if (result != TEEC_SUCCESS) { + IMSG_ERROR("Failed to open session:%x size = %lu\n", + result, size); + goto release_1; + } + + sharedmem.buffer = buffer; + sharedmem.size = size; + sharedmem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + result = TEEC_RegisterSharedMemory(context, &sharedmem); + if (result != TEEC_SUCCESS) { + IMSG_ERROR("Failed to register kernel %d shared memory,err: %x", + (unsigned int)size, result); + goto release_2; + } + memset(&operation, 0x00, sizeof(operation)); + operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + operation.started = 1; + operation.params[0].memref.parent = &sharedmem; + operation.params[0].memref.offset = 0; + operation.params[0].memref.size = sharedmem.size; + result = TEEC_InvokeCommand(&session, command, &operation, NULL); + if (result != TEEC_SUCCESS) { + IMSG_ERROR("Failed to invoke command,err: %x", result); + goto release_3; + } + +release_3: + TEEC_ReleaseSharedMemory(&sharedmem); +release_2: + TEEC_CloseSession(&session); +release_1: + return result; +} + + +int ut_pf_gp_transfer_user_data(struct TEEC_Context *context, + struct TEEC_UUID *uuid, + unsigned int command, void *buffer, unsigned long size) +{ + struct TEEC_Session session; + struct TEEC_Operation operation; + struct TEEC_SharedMemory sharedmem; + TEEC_Result result; + uint32_t returnOrigin = 0; + + if (NULL == context || NULL == uuid || NULL == buffer || size < 1) + return -1; + + memset(&session, 0, sizeof(session)); + result = TEEC_OpenSession(context, &session, uuid, TEEC_LOGIN_PUBLIC, + NULL, NULL, &returnOrigin); + if (result != TEEC_SUCCESS) { + IMSG_ERROR("Failed to open session,err: %x", result); + goto release_1; + } + + sharedmem.size = size; + sharedmem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + result = TEEC_AllocateSharedMemory(context, &sharedmem); + if (result != TEEC_SUCCESS) { + IMSG_ERROR("Failed to register user %d shared memory,err: %x", + (unsigned int)size, result); + goto release_2; + } + + if (copy_from_user((void *)sharedmem.buffer, buffer, size)) { + IMSG_ERROR("Failed to copy_from_user!\n"); + goto release_3; + }; + + memset(&operation, 0x00, sizeof(operation)); + operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + operation.started = 1; + operation.params[0].memref.parent = &sharedmem; + operation.params[0].memref.offset = 0; + operation.params[0].memref.size = sharedmem.size; + result = TEEC_InvokeCommand(&session, command, &operation, NULL); + if (result != TEEC_SUCCESS) { + IMSG_ERROR("Failed to invoke command,err: %x", result); + goto release_3; + } + + if (copy_to_user(buffer, (void *)sharedmem.buffer, size)) + IMSG_ERROR("Failed to copy_to_user!\n"); + +release_3: + TEEC_ReleaseSharedMemory(&sharedmem); +release_2: + TEEC_CloseSession(&session); +release_1: + return result; +} diff --git a/drivers/tee/teei/300/tz_driver/teei_fp.c b/drivers/tee/teei/300/tz_driver/teei_fp.c new file mode 100644 index 000000000000..41b3a21c2340 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/teei_fp.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ +#include +#include "teei_fp.h" +#include "teei_client_transfer_data.h" +#define IMSG_TAG "[tz_driver]" +#include +#include + +static struct TEEC_Context context; +static int context_initialized; +struct TEEC_UUID uuid_fp = { 0x7778c03f, 0xc30c, 0x4dd0, +{ 0xa3, 0x19, 0xea, 0x29, 0x64, 0x3d, 0x4d, 0x4b } }; +int send_fp_command(void *buffer, unsigned long size) +{ + int ret = 0; + + IMSG_INFO("TEEI start %s\n", __func__); + + if (buffer == NULL || size < 1) + return -1; + + if (context_initialized == 0) { + memset(&context, 0, sizeof(context)); + ret = ut_pf_gp_initialize_context(&context); + if (ret) { + IMSG_ERROR("Failed to initialize fp context ,err: %x", + ret); + goto release_1; + } + context_initialized = 1; + } + ret = ut_pf_gp_transfer_user_data(&context, &uuid_fp, 1, buffer, size); + if (ret) { + IMSG_ERROR("Failed to transfer data,err: %x", ret); + goto release_2; + } +release_2: + if (ret) { + ut_pf_gp_finalize_context(&context); + context_initialized = 0; + } +release_1: + IMSG_INFO("TEEI end of %s\n", __func__); + return ret; +} diff --git a/drivers/tee/teei/300/tz_driver/teei_keymaster.c b/drivers/tee/teei/300/tz_driver/teei_keymaster.c new file mode 100644 index 000000000000..7f4131d26b25 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/teei_keymaster.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include "teei_keymaster.h" +#include "teei_client_transfer_data.h" +#define IMSG_TAG "[tz_driver]" +#include +#include + +#define KM_COMMAND_MAGIC 'X' + +int send_keymaster_command(void *buffer, unsigned long size) +{ + int ret = 0; + struct TEEC_Context context; + struct TEEC_UUID uuid_ta = { 0xc09c9c5d, 0xaa50, 0x4b78, + { 0xb0, 0xe4, 0x6e, 0xda, 0x61, 0x55, 0x6c, 0x3a } }; + + /* IMSG_INFO("TEEI start send_keymaster_command\n"); */ + + if (buffer == NULL || size < 1) + return -1; + + memset(&context, 0, sizeof(context)); + ret = ut_pf_gp_initialize_context(&context); + if (ret) { + IMSG_ERROR("Failed to initialize keymaster context ,err: %x", + ret); + goto release_1; + } + ret = ut_pf_gp_transfer_user_data(&context, &uuid_ta, KM_COMMAND_MAGIC, + buffer, size); + if (ret) { + IMSG_ERROR("Failed to transfer data,err: %x", ret); + goto release_2; + } +release_2: + ut_pf_gp_finalize_context(&context); +release_1: + /* IMSG_INFO("TEEI end of send_keymaster_command\n"); */ + return ret; +} diff --git a/drivers/tee/teei/300/tz_driver/teei_smc_call.c b/drivers/tee/teei/300/tz_driver/teei_smc_call.c new file mode 100644 index 000000000000..8baf419ffb7b --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/teei_smc_call.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include "teei_smc_call.h" +#include "utdriver_macro.h" +#include "notify_queue.h" +#include "switch_queue.h" +#include "teei_common.h" +#include "nt_smc_call.h" +#include "teei_client_main.h" + +#define IMSG_TAG "[tz_driver]" + +int teei_forward_call(unsigned long long cmd, unsigned long long cmd_addr, + unsigned long long size) +{ + struct completion *wait_completion = NULL; + int retVal = 0; + + KATRACE_BEGIN("teei_forward_call"); + + cpus_read_lock(); + + wait_completion = kmalloc(sizeof(struct completion), GFP_KERNEL); + if (wait_completion == NULL) { + IMSG_ERROR("TEEI: Failed to alloc completion[%s]\n", __func__); + return -ENOMEM; + } + + init_completion(wait_completion); + + retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__); + kfree(wait_completion); + cpus_read_unlock(); + KATRACE_END("teei_forward_call"); + return retVal; + } + + retVal = add_nq_entry(NEW_CAPI_CALL, cmd, + (unsigned long long)(wait_completion), + cmd_addr, size, 0); + if (retVal != 0) { + IMSG_ERROR("TEEI: Failed to add one nq to n_t_buffer\n"); + kfree(wait_completion); + cpus_read_unlock(); + KATRACE_END("teei_forward_call"); + return retVal; + } + + teei_notify_switch_fn(); + + wait_for_completion(wait_completion); + + kfree(wait_completion); + + cpus_read_unlock(); + + KATRACE_END("teei_forward_call"); + + return 0; +} +EXPORT_SYMBOL(teei_forward_call); diff --git a/drivers/tee/teei/300/tz_driver/teei_task_link.c b/drivers/tee/teei/300/tz_driver/teei_task_link.c new file mode 100644 index 000000000000..1a7a173845d8 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/teei_task_link.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include "switch_queue.h" +#include "backward_driver.h" + +static struct list_head g_teei_task_link; +static struct list_head g_bdrv_task_link; +static struct mutex task_link_mutex; +static struct mutex bdrv_link_mutex; + +int teei_init_task_link(void) +{ + mutex_init(&task_link_mutex); + INIT_LIST_HEAD(&g_teei_task_link); + + mutex_init(&bdrv_link_mutex); + INIT_LIST_HEAD(&g_bdrv_task_link); + + return 0; +} + +int teei_add_to_task_link(struct list_head *entry) +{ + + mutex_lock(&task_link_mutex); + list_add_tail(entry, &g_teei_task_link); + mutex_unlock(&task_link_mutex); + + return 0; +} + +int is_teei_task_link_empty(void) +{ + int retVal = 0; + + mutex_lock(&task_link_mutex); + retVal = list_empty(&g_teei_task_link); + mutex_unlock(&task_link_mutex); + + return retVal; +} + +struct task_entry_struct *teei_get_task_from_link(void) +{ + struct task_entry_struct *entry = NULL; + int retVal = 0; + + retVal = is_teei_task_link_empty(); + if (retVal == 1) + return NULL; + + mutex_lock(&task_link_mutex); + entry = list_first_entry(&g_teei_task_link, + struct task_entry_struct, c_link); + + list_del(&(entry->c_link)); + mutex_unlock(&task_link_mutex); + + return entry; +} + +int teei_add_to_bdrv_link(struct list_head *entry) +{ + + mutex_lock(&bdrv_link_mutex); + list_add_tail(entry, &g_bdrv_task_link); + mutex_unlock(&bdrv_link_mutex); + + return 0; +} + +struct bdrv_work_struct *teei_get_bdrv_from_link(void) +{ + struct bdrv_work_struct *entry = NULL; + int retVal = 0; + + retVal = list_empty(&g_bdrv_task_link); + if (retVal == 1) + return NULL; + + mutex_lock(&bdrv_link_mutex); + entry = list_first_entry(&g_bdrv_task_link, + struct bdrv_work_struct, c_link); + + list_del(&(entry->c_link)); + mutex_unlock(&bdrv_link_mutex); + + return entry; +} diff --git a/drivers/tee/teei/300/tz_driver/tz_log.c b/drivers/tee/teei/300/tz_driver/tz_log.c new file mode 100644 index 000000000000..5cacefa07f2c --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/tz_log.c @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * Copyright (C) 2015 Google, Inc. + * + */ + +#define IMSG_TAG "[tz_log]" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef CONFIG_MTK_TEE_SANITY +#include +#endif +#include "tz_log.h" + +#include "log_perf.h" + +struct tz_log_state *g_tz_log_state; +static struct completion teei_log_comp; + +int init_tlog_comp_fn(void) +{ + init_completion(&teei_log_comp); + + return 0; +} + +void teei_notify_log_fn(void) +{ + complete(&teei_log_comp); +} + +static int __tz_driver_read_logs(struct tz_log_state *s, char *buffer, + uint32_t get, unsigned int cnt) +{ + struct log_rb *log = s->log; + int i = 0; + size_t mask = log->sz - 1; + + for (i = 0; i < cnt;) + buffer[i++] = log->data[get++ & mask]; + + return i; +} + +int tz_driver_read_logs(char *buffer, unsigned long count) +{ + struct tz_log_state *local_s = NULL; + uint32_t get = 0; + uint32_t put = 0; + uint32_t alloc = 0; + int read_chars = 0; + struct log_rb *log = NULL; + unsigned int real_cnt = 0; + + local_s = g_tz_log_state; + log = local_s->log; + + get = local_s->read_get; + put = log->put; + + if (put != get) { + + alloc = log->alloc; + + if ((alloc - get) > log->sz) { + IMSG_INFO("log overflow.\n"); + get = alloc - log->sz; + } + + if ((put - get) > (unsigned int)count) + real_cnt = (unsigned int)count; + else + real_cnt = put - get; + + read_chars = __tz_driver_read_logs(local_s, + buffer, get, real_cnt); + + get += read_chars; + } + + local_s->read_get = get; + return read_chars; + +} + +static int log_read_line(struct tz_log_state *s, int put, int get) +{ + struct log_rb *log = s->log; + int i; + char c = '\0'; + size_t max_to_read = min((size_t)(put - get), + sizeof(s->line_buffer) - 1); + size_t mask = log->sz - 1; + + for (i = 0; i < max_to_read && c != '\n';) + s->line_buffer[i++] = c = log->data[get++ & mask]; + s->line_buffer[i] = '\0'; + + return i; +} + +static void tz_driver_dump_logs(struct tz_log_state *s) +{ + struct log_rb *log = s->log; + struct boot_log_rb *boot_log = s->boot_log; + uint32_t get, put, alloc; + int read_chars; + static DEFINE_RATELIMIT_STATE(_rs, + TZ_LOG_RATELIMIT_INTERVAL, + TZ_LOG_RATELIMIT_BURST); + + if (unlikely(log->put == 0)) { + IMSG_DEBUG("TEE log buffer not ready yet\n"); + return; + } + + WARN_ON(!is_power_of_2(log->sz)); + + /* + * For this ring buffer, at any given point, alloc >= put >= get. + * The producer side of the buffer is not locked, so the put and alloc + * pointers must be read in a defined order (put before alloc) so + * that the above condition is maintained. A read barrier is needed + * to make sure the hardware and compiler keep the reads ordered. + */ + get = s->get; + while ((put = log->put) != get) { + /* Make sure that the read of put occurs */ + /* before the read of log data */ + rmb(); + + /* Read a line from the log */ + read_chars = log_read_line(s, put, get); + + /* Force the loads from log_read_line to complete. */ + rmb(); + alloc = log->alloc; + + /* + * Discard the line that was just read if the data could + * have been corrupted by the producer. + */ + if (alloc - get > log->sz) { + IMSG_ERROR("log overflow."); + get = alloc - log->sz; + continue; + } + + /* + * Due to UART speed is slow, printing large number of + * messages to UART will cause system reset by watchdog. + * It can prevent from printing message to uart by using + * KERN_DEBUG log level if with default print setting. + * (default setting is print message to uart + * if log level >= KERN_INFO) + */ + + if (likely(is_teei_ready())) { +#ifdef CONFIG_MTK_TEE_SANITY + if (mtk_tee_log_tracing(get_current_cpuid(), 0, + s->line_buffer, read_chars)) +#endif + IMSG_PRINTK("[TZ_LOG] %s", s->line_buffer); + } else + IMSG_PRINTK("[TZ_LOG] %s", s->line_buffer); + + /* + * Dump early log to boot log buffer + * until boot log buffer is full + */ + if (boot_log->put + read_chars < boot_log->sz) { + char *log_buf = &boot_log->data[boot_log->put]; + + memcpy(log_buf, s->line_buffer, read_chars); + boot_log->put += read_chars; + } + + /* Print warning message */ + /* if log output frequency is over rate limit */ + __ratelimit(&_rs); + + get += read_chars; + +#if ENABLE_LOG_PERF == 1 + measure_log_perf(IMSG_TAG, read_chars, + *(uint32_t *)(s->line_buffer)); +#endif + } + s->get = get; +} + +int teei_log_fn(void *work) +{ + int retVal = 0; +#ifdef CONFIG_MICROTRUST_TZ_LOG + struct tz_log_state *s; + unsigned long flags; + + s = g_tz_log_state; +#endif + + while (1) { + retVal = wait_for_completion_interruptible(&teei_log_comp); + if (retVal != 0) + continue; +#ifdef CONFIG_MICROTRUST_TZ_LOG + spin_lock_irqsave(&s->lock, flags); + tz_driver_dump_logs(s); + spin_unlock_irqrestore(&s->lock, flags); +#endif + } + + return NOTIFY_OK; +} + +static int tz_log_panic_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct tz_log_state *s; + + /* + * Don't grab the spin lock to hold up the panic notifier, even + * though this is racy. + */ + s = container_of(nb, struct tz_log_state, panic_notifier); + IMSG_INFO("tz log panic notifier\n"); + tz_driver_dump_logs(s); + return NOTIFY_OK; +} + +#ifdef ENABLED_TEEI_BOOT_LOG +static struct tz_log_state *get_tz_log_state(void) +{ + struct tz_driver_state *drv_state = get_tz_drv_state(); + struct platform_device *pdev = drv_state->tz_log_pdev; + + return pdev->dev.platform_data; +} + +static void *boot_log_seq_start(struct seq_file *f, loff_t *pos) +{ + struct tz_log_state *s = get_tz_log_state(); + struct boot_log_rb *log = s->boot_log; + + if (*pos >= log->put) + return NULL; + + return (void *)log; +} + +static void *boot_log_seq_next(struct seq_file *f, void *v, loff_t *pos) +{ + struct boot_log_rb *log = v; + + if (*pos >= log->put) + return NULL; + + *pos = log->get; + return v; +} + +static void boot_log_seq_stop(struct seq_file *f, void *v) +{ +} + +static int boot_log_read_line(struct boot_log_rb *log, char *out) +{ + int put = log->put; + int get = log->get; + int i; + char c = '\0'; + size_t max_to_read = min((size_t)(put - get), + (size_t)TZ_LINE_BUFFER_SIZE - 1); + + size_t mask = log->sz - 1; + + for (i = 0; i < max_to_read && c != '\n';) + out[i++] = c = log->data[get++ & mask]; + out[i] = '\0'; + + return i; +} + +static int boot_log_seq_show(struct seq_file *f, void *v) +{ + struct boot_log_rb *log = v; + char line_buffer[TZ_LINE_BUFFER_SIZE]; + uint32_t read_chars; + + read_chars = boot_log_read_line(log, line_buffer); + + if (read_chars) { + seq_printf(f, "%s", line_buffer); + log->get += read_chars; + } + + return 0; +} + +static const struct seq_operations boot_log_seq_ops = { + .start = boot_log_seq_start, + .next = boot_log_seq_next, + .stop = boot_log_seq_stop, + .show = boot_log_seq_show +}; + +static int boot_log_open(struct inode *inode, struct file *file) +{ + struct tz_log_state *s = get_tz_log_state(); + struct boot_log_rb *log = s->boot_log; + + log->get = 0; + + return seq_open(file, &boot_log_seq_ops); +}; + +static const struct file_operations boot_log_fops = { + .open = boot_log_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +static struct dentry *root_entry; +static int tz_log_debugfs_init(void) +{ + root_entry = debugfs_create_dir("tz_log", NULL); + if (!root_entry) { + IMSG_WARN("Can not create tz_log debugfs\n"); + return -1; + } + + debugfs_create_file("boot_log", 0444, root_entry, NULL, &boot_log_fops); + + return 0; +} + + +#endif + +int tz_log_probe(struct platform_device *pdev) +{ + struct tz_log_state *s; + int result; + + IMSG_DEBUG("%s\n", __func__); + + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) { + result = -ENOMEM; + goto error_alloc_state; + } + + g_tz_log_state = s; + + spin_lock_init(&s->lock); + s->dev = &pdev->dev; + s->get = 0; + s->read_get = 0; + s->log_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO | GFP_DMA, + get_order(TZ_LOG_SIZE)); + if (!s->log_pages) { + result = -ENOMEM; + goto error_alloc_log; + } + s->log = page_address(s->log_pages); + + s->boot_log_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO | GFP_DMA, + get_order(TZ_LOG_SIZE)); + if (!s->boot_log_pages) { + result = -ENOMEM; + goto error_alloc_boot_log; + } + s->boot_log = page_address(s->boot_log_pages); + + s->boot_log->put = 0; + s->boot_log->sz = rounddown_pow_of_two( + TZ_LOG_SIZE - sizeof(struct boot_log_rb)); + + s->panic_notifier.notifier_call = tz_log_panic_notify; + result = atomic_notifier_chain_register(&panic_notifier_list, + &s->panic_notifier); + if (result < 0) { + IMSG_ERROR("failed to register panic notifier\n"); + goto error_panic_notifier; + } + platform_device_add_data(pdev, s, sizeof(struct tz_log_state)); + +#ifdef ENABLED_TEEI_BOOT_LOG + tz_log_debugfs_init(); +#endif + + return 0; + +error_panic_notifier: + __free_pages(s->boot_log_pages, get_order(TZ_LOG_SIZE)); +error_alloc_boot_log: + __free_pages(s->log_pages, get_order(TZ_LOG_SIZE)); +error_alloc_log: + kfree(s); + g_tz_log_state = NULL; +error_alloc_state: + return result; +} + +int tz_log_remove(struct platform_device *pdev) +{ + struct tz_log_state *s = dev_get_platdata(&pdev->dev); + + IMSG_DEBUG("%s\n", __func__); + + atomic_notifier_chain_unregister(&panic_notifier_list, + &s->panic_notifier); + + __free_pages(s->log_pages, get_order(TZ_LOG_SIZE)); + __free_pages(s->boot_log_pages, get_order(TZ_LOG_SIZE)); + kfree(s); + g_tz_log_state = NULL; + + return 0; +} + diff --git a/drivers/tee/teei/300/tz_driver/tz_log.h b/drivers/tee/teei/300/tz_driver/tz_log.h new file mode 100644 index 000000000000..40eb9b0487d3 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/tz_log.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * Copyright (C) 2015 Google, Inc. + * + */ + +#ifndef _TRUSTY_LOG_H_ +#define _TRUSTY_LOG_H_ + +#include + +#define TZ_LOG_SIZE (PAGE_SIZE * 64) +#define TZ_LINE_BUFFER_SIZE 256 + +#define TZ_LOG_RATELIMIT_INTERVAL (1 * HZ) +#define TZ_LOG_RATELIMIT_BURST 200 + +/* + * Ring buffer that supports one secure producer thread and one + * linux side consumer thread. + */ +struct log_rb { + TZ_VOLATILE(uint32_t alloc); + TZ_VOLATILE(uint32_t put); + TZ_NON_VOLATILE(uint32_t sz); + TZ_VOLATILE(char data[0]); +} __packed; + +struct boot_log_rb { + uint32_t get; + uint32_t put; + uint32_t sz; + char data[0]; +} __packed; + +struct tz_log_state { + struct device *dev; + + /* + * This lock is here to ensure only one consumer will read + * from the log ring buffer at a time. + */ + spinlock_t lock; + struct log_rb *log; + struct boot_log_rb *boot_log; + uint32_t get; + uint32_t read_get; + + struct page *log_pages; + struct page *boot_log_pages; + + struct notifier_block call_notifier; + struct notifier_block panic_notifier; + char line_buffer[TZ_LINE_BUFFER_SIZE]; +}; + + +int tz_log_probe(struct platform_device *pdev); +int tz_log_remove(struct platform_device *pdev); +int tz_driver_read_logs(char *buffer, unsigned long count); +int teei_log_fn(void *work); +int init_tlog_comp_fn(void); +void teei_notify_log_fn(void); +#endif + diff --git a/drivers/tee/teei/300/tz_driver/utr_tui_cmd.c b/drivers/tee/teei/300/tz_driver/utr_tui_cmd.c new file mode 100644 index 000000000000..4ecfe1d966c1 --- /dev/null +++ b/drivers/tee/teei/300/tz_driver/utr_tui_cmd.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "teei_id.h" +#include "sched_status.h" +#include "nt_smc_call.h" +#include "utr_tui_cmd.h" +#include "tpd.h" +#include +#include "teei_common.h" +#include "switch_queue.h" +#include "teei_client_main.h" +#include "backward_driver.h" +#include "utdriver_macro.h" +#include "../teei_fp/fp_func.h" +#include + +#define IMSG_TAG "[tz_driver]" +#include + +unsigned long tui_display_message_buff; +unsigned long tui_notice_message_buff; + +unsigned long create_tui_buff(int buff_size, unsigned int fdrv_type) +{ + struct teei_fdrv fdrv; + long retVal = 0; + + fdrv.call_type = fdrv_type; + fdrv.buff_size = buff_size; + + retVal = create_fdrv(&fdrv); + if (retVal != 0) { + IMSG_ERROR("[%s][%d] TEEI: Failed to call the create_fdrv!\n", + __func__, __LINE__); + return 0; + } + + return fdrv.buf; +} + +int send_tui_display_command(unsigned long type) +{ + struct teei_fdrv fdrv; + int retVal = 0; + + fdrv.call_type = TUI_DISPLAY_SYS_NO; + fdrv.buff_size = type; + + retVal = fdrv_notify(&fdrv); + + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Failed to call the fdrv_notify [%d]!\n", + __func__, __LINE__, retVal); + return retVal; + } + + return 0; +} + + +int send_tui_notice_command(unsigned long share_memory_size) +{ + struct teei_fdrv fdrv; + int retVal = 0; + + fdrv.call_type = TUI_NOTICE_SYS_NO; + fdrv.buff_size = share_memory_size; + + retVal = fdrv_notify(&fdrv); + + if (retVal != 0) { + IMSG_ERROR("[%s][%d] Failed to call the fdrv_notify [%d]!\n", + __func__, __LINE__, retVal); + return retVal; + } + + return 0; +} + + +/* TODO */ +int send_power_down_cmd(void) +{ + int retVal = 0; + + return retVal; +} + +int wait_for_power_down(void) +{ + struct sched_param param = { .sched_priority = 4 }; + + sched_setscheduler(current, SCHED_RR, ¶m); + + do { + set_current_state(TASK_INTERRUPTIBLE); + if ((power_down_flag == 1) && (enter_tui_flag)) { + mtkfb_set_backlight_level(0); + send_power_down_cmd(); + IMSG_DEBUG("[%s][%d]catch a power_down_flag!!!\n", + __func__, __LINE__); + } + power_down_flag = 0; + msleep_interruptible(30); + set_current_state(TASK_RUNNING); + } while (!kthread_should_stop()); + + return 0; +} + +int tui_notify_reboot(struct notifier_block *this, unsigned long code, void *x) +{ + if ((code == SYS_RESTART) && enter_tui_flag) { + mtkfb_set_backlight_level(0); + send_power_down_cmd(); + IMSG_DEBUG("[%s][%d]catch a ree_reboot_signal!!!\n", + __func__, __LINE__); + } + return NOTIFY_OK; +} diff --git a/drivers/tee/teei/300/tz_vfs/Makefile b/drivers/tee/teei/300/tz_vfs/Makefile new file mode 100644 index 000000000000..b4100bb5513f --- /dev/null +++ b/drivers/tee/teei/300/tz_vfs/Makefile @@ -0,0 +1,14 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +obj-$(CONFIG_MICROTRUST_VFS_DRIVER) += vfsFun.o fp_vendor.o +ccflags-y += -D DEBUG_DO -fno-pic diff --git a/drivers/tee/teei/300/tz_vfs/TEEI.h b/drivers/tee/teei/300/tz_vfs/TEEI.h new file mode 100644 index 000000000000..bbc2950770a7 --- /dev/null +++ b/drivers/tee/teei/300/tz_vfs/TEEI.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __VFS_TEEI_H_ +#define __VFS_TEEI_H_ + +#define RPMB_IOCTL_SOTER_WRITE_DATA 5 +#define RPMB_IOCTL_SOTER_READ_DATA 6 +#define RPMB_IOCTL_SOTER_GET_CNT 7 + +#define RPMB_BUFF_SIZE 512 +#define PAGE_SIZE_4K (0x1000) + + +struct TEEI_vfs_command { + int func; + int cmd_size; + + union func_arg { + struct func_open { + int flags; + int mode; + } func_open_args; + + struct func_send { + int fd; + int count; + } func_read_args; + + struct func_recv { + int fd; + int count; + } func_write_args; + + struct func_ioctl { + int fd; + int cmd; + int arg; + } func_ioctl_args; + + struct func_close { + int fd; + } func_close_args; + + struct func_trunc { + int fd; + int length; + } func_trunc_args; + + struct func_lseek { + int fd; + int offset; + int origin; + } func_lseek_args; + + struct func_mkdir { + int mode; + } func_mkdir_args; + + struct func_readdir { + unsigned long p_dir; + unsigned int read_count; + } func_readdir_args; + + struct func_closedir { + unsigned long p_dir; + } func_closedir_args; + + } args; + +}; + +union TEEI_vfs_response { + int value; + unsigned long p_dir; +}; + +extern char *daulOS_VFS_write_share_mem; +#endif diff --git a/drivers/tee/teei/300/tz_vfs/VFS.h b/drivers/tee/teei/300/tz_vfs/VFS.h new file mode 100644 index 000000000000..0604e481e66b --- /dev/null +++ b/drivers/tee/teei/300/tz_vfs/VFS.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __TZ_VFS_H__ +#define __TZ_VFS_H__ + +#endif /* __TZ_VFS_H__ */ diff --git a/drivers/tee/teei/300/tz_vfs/fp_vendor.c b/drivers/tee/teei/300/tz_vfs/fp_vendor.c new file mode 100644 index 000000000000..f36a11bbc5dc --- /dev/null +++ b/drivers/tee/teei/300/tz_vfs/fp_vendor.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include "fp_vendor.h" +#include +#include "../tz_driver/include/nt_smc_call.h" +#include +#include +#include +#include + +#define IMSG_TAG "[tz_driver]" +#include + +#define FPC_VENDOR_ID 0x12 +#define GOODIX_VENDOR_ID 0x13 + +int fp_vendor_active; +int fp_vendor = FP_VENDOR_INVALID; +static DEFINE_MUTEX(fp_vendor_lock); + +int get_fp_vendor(void) +{ + uint64_t fp_vendor_id_64 = 0; + uint32_t *p_temp = NULL; + uint32_t fp_vendor_id_32 = 0; + + mutex_lock(&fp_vendor_lock); + + if (fp_vendor_active) { + mutex_unlock(&fp_vendor_lock); + return fp_vendor; + } + + get_t_device_id(&fp_vendor_id_64); + + p_temp = (uint32_t *)&fp_vendor_id_64; + fp_vendor_id_32 = *p_temp; + fp_vendor_id_32 = (fp_vendor_id_32 >> 8) & 0xff; + + IMSG_INFO("%s:%d->0x%x\n", __func__, __LINE__, fp_vendor_id_32); + + switch (fp_vendor_id_32) { + case FPC_VENDOR_ID: + fp_vendor = FPC_VENDOR; + break; + + case GOODIX_VENDOR_ID: + fp_vendor = GOODIX_VENDOR; + break; + + default: + fp_vendor = FP_VENDOR_INVALID; + break; + } + + fp_vendor_active = 1; + mutex_unlock(&fp_vendor_lock); + + return fp_vendor; +} diff --git a/drivers/tee/teei/300/tz_vfs/fp_vendor.h b/drivers/tee/teei/300/tz_vfs/fp_vendor.h new file mode 100644 index 000000000000..2884141fcdc3 --- /dev/null +++ b/drivers/tee/teei/300/tz_vfs/fp_vendor.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __FP_VENDOR_H__ +#define __FP_VENDOR_H__ + +enum { + FP_VENDOR_INVALID = 0, + FPC_VENDOR, + GOODIX_VENDOR, +}; + +int get_fp_vendor(void); + +#endif /*__FP_VENDOR_H__*/ diff --git a/drivers/tee/teei/300/tz_vfs/teei_id.h b/drivers/tee/teei/300/tz_vfs/teei_id.h new file mode 100644 index 000000000000..46adf10f602d --- /dev/null +++ b/drivers/tee/teei/300/tz_vfs/teei_id.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#ifndef __VFS_TEEI_ID_H_ +#define __VFS_TEEI_ID_H_ + +#include + +#define SMC_ENOMEM 7 +#define SMC_EOPNOTSUPP 6 +#define SMC_EINVAL_ADDR 5 +#define SMC_EINVAL_ARG 4 +#define SMC_ERROR 3 +#define SMC_INTERRUPTED 2 +#define SMC_PENDING 1 +#define SMC_SUCCESS 0 +/*extern void __flush_dcache_area(void *addr, size_t len);*/ +/** + * @brief Encoding data type + */ +enum teei_enc_data_type { + TEEI_ENC_INVALID_TYPE = 0, + TEEI_ENC_UINT32, + TEEI_ENC_ARRAY, + TEEI_MEM_REF, + TEEI_SECURE_MEM_REF +}; +/** + * @brief Command ID's for global service + */ +enum _global_cmd_id { + TEEI_GLOBAL_CMD_ID_INVALID = 0x0, + TEEI_GLOBAL_CMD_ID_BOOT_ACK, + /* add by lodovico */ + TEEI_GLOBAL_CMD_ID_INIT_CONTEXT, + /* add end */ + TEEI_GLOBAL_CMD_ID_OPEN_SESSION, + TEEI_GLOBAL_CMD_ID_CLOSE_SESSION, + TEEI_GLOBAL_CMD_ID_RESUME_ASYNC_TASK, + TEEI_GLOBAL_CMD_ID_UNKNOWN = 0x7FFFFFFE, + TEEI_GLOBAL_CMD_ID_MAX = 0x7FFFFFFF +}; + +/* add by lodovico */ +/* void printff(); */ + +int service_smc_call(u32 teei_cmd_type, u32 dev_file_id, u32 svc_id, + u32 cmd_id, u32 context, u32 enc_id, + const void *cmd_buf, + size_t cmd_len, + void *resp_buf, + size_t resp_len, + const void *meta_data, + int *ret_resp_len, + void *wq, + void *arg_lock, int *error_code); + +enum teei_cmd_type { + TEEI_CMD_TYPE_INVALID = 0x0, + TEEI_CMD_TYPE_SOCKET_INIT, + TEEI_CMD_TYPE_INITIALIZE_CONTEXT, + TEEI_CMD_TYPE_FINALIZE_CONTEXT, + TEEI_CMD_TYPE_OPEN_SESSION, + TEEI_CMD_TYPE_CLOSE_SESSION, + TEEI_CMD_TYPE_INVOKE_COMMAND, + TEEI_CMD_TYPE_UNKNOWN = 0x7FFFFFFE, + TEEI_CMD_TYPE_MAX = 0x7FFFFFFF +}; + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + +#define Cache_line_size 32 +/**************************************************************** + * @brief: + * Flush_Dcache_By_Area + * @param: + * start - mva start + * end - mva end + * @return: + * ***************************************************************/ +static inline void Flush_Dcache_By_Area(unsigned long start, unsigned long end) +{ + +} +/****************************************************************** + * @brief: + * Invalidate_Dcache_By_Area + * @param: + * start - mva start + * end - mva end + * @return: + * *****************************************************************/ +static inline void Invalidate_Dcache_By_Area(unsigned long start, + unsigned long end) +{ + +} + +/* add end */ +#endif /* __OPEN_OTZ_ID_H_ */ diff --git a/drivers/tee/teei/300/tz_vfs/vfsFun.c b/drivers/tee/teei/300/tz_vfs/vfsFun.c new file mode 100644 index 000000000000..6b7364bbd1d6 --- /dev/null +++ b/drivers/tee/teei/300/tz_vfs/vfsFun.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TEEI.h" +#include "teei_id.h" +#include "fp_vendor.h" +#include +#include "VFS.h" +#include "../tz_driver/include/backward_driver.h" +#include "../tz_driver/include/teei_client_main.h" +#include "../common/include/tee_client_api.h" +#include "../tz_driver/include/teei_fp.h" + +#define IMSG_TAG "[tz_vfs]" +#include + +#define VFS_SIZE 0x80000 +#define MEM_CLEAR 0x1 +#define VFS_MAJOR 253 + +#define GET_FP_VENDOR_CMD _IOWR(TEEI_CONFIG_IOC_MAGIC, 0x80, int) + +int enter_tui_flag = 1; + +static int vfs_major = VFS_MAJOR; +static struct class *driver_class; +static dev_t devno; + +struct vfs_dev { + struct cdev cdev; + struct semaphore sem; +}; + +#ifdef VFS_RDWR_SEM +struct semaphore VFS_rd_sem; +struct semaphore VFS_wr_sem; +#else +DECLARE_COMPLETION(VFS_rd_comp); +DECLARE_COMPLETION(VFS_wr_comp); +#endif + +struct vfs_dev *vfs_devp; + +int wait_for_vfs_done(void) +{ +#ifdef VFS_RDWR_SEM + down_interruptible(&VFS_wr_sem); +#else + wait_for_completion_interruptible(&VFS_wr_comp); +#endif + return 0; +} + +int notify_vfs_handle(void) +{ +#ifdef VFS_RDWR_SEM + up(&VFS_rd_sem); +#else + complete(&VFS_rd_comp); +#endif + return 0; +} + + +static int tz_vfs_open(struct inode *inode, struct file *filp) +{ + if (vfs_devp == NULL) + return -EINVAL; + + if (filp == NULL) + return -EINVAL; + + if (strcmp("teei_daemon", current->comm) != 0) + return -EINVAL; + + filp->private_data = vfs_devp; + return 0; +} + +static int tz_vfs_release(struct inode *inode, struct file *filp) +{ + filp->private_data = NULL; + return 0; +} + +static long tz_vfs_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + int fp_vendor; + + switch (cmd) { + case GET_FP_VENDOR_CMD: + fp_vendor = get_fp_vendor(); + ret = copy_to_user((void *)arg, &fp_vendor, sizeof(int)); + break; + case TEEI_VFS_GET_FP_UUID: + ret = copy_to_user((void *)arg, &uuid_fp, + sizeof(struct TEEC_UUID)); + break; + default: + return -EINVAL; + } + + return ret; +} + +static ssize_t tz_vfs_read(struct file *filp, char __user *buf, + size_t size, loff_t *ppos) +{ + struct TEEI_vfs_command *vfs_p = NULL; + int length = 0; + int ret = 0; + + if (buf == NULL) + return -EINVAL; + + if ((size < 0) || (size > VFS_SIZE)) + return -EINVAL; + + /*IMSG_DEBUG("read begin cpu[%d]\n",cpu_id);*/ +#ifdef VFS_RDWR_SEM + down_interruptible(&VFS_rd_sem); +#else + ret = wait_for_completion_interruptible(&VFS_rd_comp); + + if (ret == -ERESTARTSYS) { + IMSG_ERROR("[%s][%d] wait_for_completion was interrupt\n", + __func__, __LINE__); + return ret; + } +#endif + + if (daulOS_VFS_share_mem == NULL) + return -EINVAL; + + vfs_p = (struct TEEI_vfs_command *)daulOS_VFS_share_mem; + + if (vfs_p->cmd_size > size) + length = size; + else + length = vfs_p->cmd_size; + + length = size; + + if (copy_to_user(buf, (void *)vfs_p, length)) + ret = -EFAULT; + else + ret = length; + return ret; +} + +static ssize_t tz_vfs_write(struct file *filp, const char __user *buf, + size_t size, loff_t *ppos) +{ + if (buf == NULL) + return -EINVAL; + + if (daulOS_VFS_share_mem == NULL) + return -EINVAL; + + if ((size < 0) || (size > VFS_SIZE)) + return -EINVAL; + + /*IMSG_DEBUG("write begin cpu_id[%d]\n",cpu_id);*/ + if (copy_from_user((void *)daulOS_VFS_share_mem, buf, size)) + return -EFAULT; + + Flush_Dcache_By_Area((unsigned long)daulOS_VFS_share_mem, + (unsigned long)daulOS_VFS_share_mem + size); + +#ifdef VFS_RDWR_SEM + up(&VFS_wr_sem); +#else + complete(&VFS_wr_comp); +#endif + return 0; +} + +static loff_t tz_vfs_llseek(struct file *filp, loff_t offset, int orig) +{ + loff_t ret = 0; + + switch (orig) { + case 0: + if (offset < 0) { + ret = -EINVAL; + break; + } + + if ((unsigned int)offset > VFS_SIZE) { + ret = -EINVAL; + break; + } + + filp->f_pos = (unsigned int)offset; + ret = filp->f_pos; + break; + + case 1: + if ((filp->f_pos + offset) > VFS_SIZE) { + ret = -EINVAL; + break; + } + + if ((filp->f_pos + offset) < 0) { + ret = -EINVAL; + break; + } + + filp->f_pos += offset; + ret = filp->f_pos; + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const struct file_operations vfs_fops = { + .owner = THIS_MODULE, + .llseek = tz_vfs_llseek, + .read = tz_vfs_read, + .write = tz_vfs_write, + .unlocked_ioctl = tz_vfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tz_vfs_ioctl, +#endif + .open = tz_vfs_open, + .release = tz_vfs_release, +}; + +static void vfs_setup_cdev(struct vfs_dev *dev, int index) +{ + int err = 0; + int devno = MKDEV(vfs_major, index); + + cdev_init(&dev->cdev, &vfs_fops); + dev->cdev.owner = vfs_fops.owner; + err = cdev_add(&dev->cdev, devno, 1); + + if (err) + IMSG_ERROR("Error %d adding socket %d.\n", err, index); +} + +static int vfs_init(void) +{ + int result = 0; + struct device *class_dev = NULL; + + devno = MKDEV(vfs_major, 0); + + result = alloc_chrdev_region(&devno, 0, 1, "tz_vfs"); + vfs_major = MAJOR(devno); + + if (result < 0) + return result; + + driver_class = class_create(THIS_MODULE, "tz_vfs"); + + if (IS_ERR(driver_class)) { + result = -ENOMEM; + IMSG_ERROR("class_create failed %d.\n", result); + goto unregister_chrdev_region; + } + + class_dev = device_create(driver_class, NULL, devno, NULL, "tz_vfs"); + + if (!class_dev) { + result = -ENOMEM; + IMSG_ERROR("class_device_create failed %d.\n", result); + goto class_destroy; + } + + vfs_devp = vmalloc(sizeof(struct vfs_dev)); + + if (vfs_devp == NULL) { + result = -ENOMEM; + goto class_device_destroy; + } + + memset(vfs_devp, 0, sizeof(struct vfs_dev)); + vfs_setup_cdev(vfs_devp, 0); + TZ_SEMA_INIT_1(&vfs_devp->sem); + +#ifdef VFS_RDWR_SEM + TZ_SEMA_INIT_0(&VFS_rd_sem); + TZ_SEMA_INIT_0(&VFS_wr_sem); +#endif + goto return_fn; + +class_device_destroy: + device_destroy(driver_class, devno); +class_destroy: + class_destroy(driver_class); +unregister_chrdev_region: + unregister_chrdev_region(devno, 1); +return_fn: + return result; +} + +static void vfs_exit(void) +{ + device_destroy(driver_class, devno); + class_destroy(driver_class); + cdev_del(&vfs_devp->cdev); + vfree(vfs_devp); + unregister_chrdev_region(MKDEV(vfs_major, 0), 1); +} + +MODULE_AUTHOR("MicroTrust"); +MODULE_LICENSE("Dual BSD/GPL"); + +module_param(vfs_major, int, 0444); + +module_init(vfs_init); +module_exit(vfs_exit); diff --git a/drivers/tee/teei/300/ut_keymaster/Makefile b/drivers/tee/teei/300/ut_keymaster/Makefile new file mode 100644 index 000000000000..ce352b45008e --- /dev/null +++ b/drivers/tee/teei/300/ut_keymaster/Makefile @@ -0,0 +1,16 @@ +# Copyright (c) 2015-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +obj-$(CONFIG_MICROTRUST_KEYMASTER_DRIVER) += ut_keymaster.o +#EXTRA_CFLAGS += -D DEBUG_DO -fno-pic +ccflags-y += -D DEBUG_DO +ccflags-y += -Wno-error diff --git a/drivers/tee/teei/300/ut_keymaster/ut_keymaster.c b/drivers/tee/teei/300/ut_keymaster/ut_keymaster.c new file mode 100644 index 000000000000..94c46874c5c4 --- /dev/null +++ b/drivers/tee/teei/300/ut_keymaster/ut_keymaster.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../tz_driver/include/teei_id.h" +#include "../tz_driver/include/nt_smc_call.h" +#include "../tz_driver/include/teei_keymaster.h" +#include "../tz_driver/include/teei_client_main.h" + +#define IMSG_TAG "[ut_km]" +#include + +#define KEYMASTER_DRIVER_ID 101 +#define KEYMASTER_MAJOR 254 +#define KEYMASTER_SIZE (128 * 1024) +#define DEV_NAME "ut_keymaster" + +static int keymaster_major = KEYMASTER_MAJOR; +static struct class *driver_class; +static dev_t devno; +struct semaphore keymaster_api_lock; + +struct keymaster_dev { + struct cdev cdev; + struct semaphore sem; +}; +struct keymaster_dev *keymaster_devp; + +int keymaster_open(struct inode *inode, struct file *filp) +{ + + IMSG_DEBUG("!!!!!microtrust kernel open keymaster dev operation!!!\n"); + + if (keymaster_devp != NULL) + filp->private_data = keymaster_devp; + else { + IMSG_ERROR("microtrust keymaster_devp is NULL\n"); + return -EINVAL; + } + return 0; +} + +int keymaster_release(struct inode *inode, struct file *filp) +{ + filp->private_data = NULL; + return 0; +} +static long keymaster_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + + down(&keymaster_api_lock); + + switch (cmd) { + + case CMD_KM_MEM_CLEAR: + IMSG_DEBUG("microtrust keymaster mem clear.\n"); + break; + case CMD_KM_MEM_SEND: + if (send_keymaster_command((void *)arg, + KEYMASTER_SIZE)) { + IMSG_ERROR("keymaster transfer_data failed.\n"); + up(&keymaster_api_lock); + return -EFAULT; + } + break; + case CMD_KM_NOTIFY_UTD: + complete(&boot_decryto_lock); + break; + + default: + up(&keymaster_api_lock); + return -EINVAL; + } + + up(&keymaster_api_lock); + return 0; +} +static ssize_t keymaster_read(struct file *filp, char __user *buf, + size_t size, loff_t *ppos) +{ + int ret = 0; + return ret; +} + +static ssize_t keymaster_write(struct file *filp, const char __user *buf, + size_t size, loff_t *ppos) +{ + return 0; +} + +static loff_t keymaster_llseek(struct file *filp, loff_t offset, int orig) +{ + return 0; +} + + +static const struct file_operations keymaster_fops = { + .owner = THIS_MODULE, + .llseek = keymaster_llseek, + .read = keymaster_read, + .write = keymaster_write, + .unlocked_ioctl = keymaster_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = keymaster_ioctl, +#endif + .open = keymaster_open, + .release = keymaster_release, +}; + +static void keymaster_setup_cdev(struct keymaster_dev *dev, int index) +{ + int err = 0; + int devno = MKDEV(keymaster_major, index); + + cdev_init(&dev->cdev, &keymaster_fops); + dev->cdev.owner = keymaster_fops.owner; + err = cdev_add(&dev->cdev, devno, 1); + if (err) + IMSG_ERROR("Error %d adding keymaster %d.\n", err, index); +} + +int keymaster_init(void) +{ + int result = 0; + struct device *class_dev = NULL; + + devno = MKDEV(keymaster_major, 0); + result = alloc_chrdev_region(&devno, 0, 1, DEV_NAME); + keymaster_major = MAJOR(devno); + TZ_SEMA_INIT_0(&(keymaster_api_lock)); + if (result < 0) + return result; + + driver_class = NULL; + driver_class = class_create(THIS_MODULE, DEV_NAME); + if (IS_ERR(driver_class)) { + result = -ENOMEM; + IMSG_ERROR("ut_keymaster class_create failed %d.\n", result); + goto unregister_chrdev_region; + } + + class_dev = device_create(driver_class, NULL, devno, NULL, DEV_NAME); + if (!class_dev) { + result = -ENOMEM; + IMSG_ERROR("keymaster device_create failed %d.\n", result); + goto class_destroy; + } + keymaster_devp = NULL; + keymaster_devp = vmalloc(sizeof(struct keymaster_dev)); + if (keymaster_devp == NULL) { + result = -ENOMEM; + goto class_device_destroy; + } + memset(keymaster_devp, 0, sizeof(struct keymaster_dev)); + keymaster_setup_cdev(keymaster_devp, 0); + TZ_SEMA_INIT_1(&keymaster_devp->sem); + + IMSG_DEBUG("[%s][%d]create ut_keymaster device node successfully!\n", + __func__, __LINE__); + goto return_fn; + +class_device_destroy: + device_destroy(driver_class, devno); +class_destroy: + class_destroy(driver_class); +unregister_chrdev_region: + unregister_chrdev_region(devno, 1); +return_fn: + return result; +} + +void keymaster_exit(void) +{ + device_destroy(driver_class, devno); + class_destroy(driver_class); + cdev_del(&keymaster_devp->cdev); + vfree(keymaster_devp); + unregister_chrdev_region(MKDEV(keymaster_major, 0), 1); +} + +MODULE_AUTHOR("Microtrust"); +MODULE_LICENSE("Dual BSD/GPL"); +module_init(keymaster_init); +module_exit(keymaster_exit); diff --git a/drivers/tee/teei/300/ut_tester/Makefile b/drivers/tee/teei/300/ut_tester/Makefile new file mode 100644 index 000000000000..80aa1a94e4da --- /dev/null +++ b/drivers/tee/teei/300/ut_tester/Makefile @@ -0,0 +1,14 @@ +# Copyright (c) 2016-2020, MICROTRUST Incorporated +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +obj-y += ut_tester.o +ccflags-y += -Werror diff --git a/drivers/tee/teei/300/ut_tester/ut_tester.c b/drivers/tee/teei/300/ut_tester/ut_tester.c new file mode 100644 index 000000000000..b3986c3443c2 --- /dev/null +++ b/drivers/tee/teei/300/ut_tester/ut_tester.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2019, MICROTRUST Incorporated + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMSG_TAG "[ut_tester]" +#include + +static struct teei_fdrv ut_tester_fdrv = { + .buff_size = PAGE_SIZE, + .call_type = 200, +}; + +static ssize_t run_tests_show(struct device *cd, struct device_attribute *attr, + char *buf) +{ + if (!ut_tester_fdrv.buf) { + IMSG_WARN("ut_tester driver is not init\n"); + return 0; + } + + /* compatible for old trigger method */ + strcpy(ut_tester_fdrv.buf, "all"); + fdrv_notify(&ut_tester_fdrv); + + return 0; +} +static ssize_t run_tests_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + if (!ut_tester_fdrv.buf) { + IMSG_WARN("ut_tester driver is not init\n"); + return len; + } + + memset(ut_tester_fdrv.buf, 0, ut_tester_fdrv.buff_size); + + if (len > 0) + if (sscanf(buf, "%64s\n", (char *)ut_tester_fdrv.buf) < 0) + IMSG_WARN("sscanf failed\n"); + + IMSG_DEBUG("buf '%s', len %zd, fdrv_buf '%s'\n", + buf, len, (const char *)ut_tester_fdrv.buf); + + fdrv_notify(&ut_tester_fdrv); + + return len; +} +static DEVICE_ATTR_RW(run_tests); + +static struct device_attribute *tester_attrs[] = { + &dev_attr_run_tests, + NULL +}; + +static void remove_sysfs(struct platform_device *pdev) +{ + int i; + + for (i = 0; tester_attrs[i]; i++) + device_remove_file(&pdev->dev, tester_attrs[i]); +} + +static int create_sysfs(struct platform_device *pdev) +{ + int res = 0; + int i; + + for (i = 0; tester_attrs[i]; i++) { + res = device_create_file(&pdev->dev, tester_attrs[i]); + if (res) { + IMSG_ERROR("failed to create sysfs entry: %s\n", + tester_attrs[i]->attr.name); + break; + } + } + + if (res) + remove_sysfs(pdev); + + return res; +} + +static int ut_tester_probe(struct platform_device *pdev) +{ + int res; + + res = create_sysfs(pdev); + if (res) + return -EFAULT; + + register_fdrv(&ut_tester_fdrv); + + return 0; +} + +static int ut_tester_remove(struct platform_device *pdev) +{ + remove_sysfs(pdev); + return 0; +} + +static const struct of_device_id ut_tester_of_match[] = { + { .compatible = "microtrust,tester-v1", }, + {}, +}; + +static struct platform_driver ut_tester_driver = { + .probe = ut_tester_probe, + .remove = ut_tester_remove, + .driver = { + .name = "ut-tester", + .owner = THIS_MODULE, + .of_match_table = ut_tester_of_match, + }, +}; + +module_platform_driver(ut_tester_driver); diff --git a/drivers/tee/teei/Kconfig b/drivers/tee/teei/Kconfig index b06143b01817..283bf723283a 100644 --- a/drivers/tee/teei/Kconfig +++ b/drivers/tee/teei/Kconfig @@ -37,7 +37,7 @@ config MICROTRUST_TEE_SUPPORT config MICROTRUST_TEE_VERSION string "MICROTRUST TEE Version" depends on MICROTRUST_TEE_SUPPORT || MICROTRUST_TEE_LITE_SUPPORT - default "400" + default "300" help Enables the support of Microtrust new version. All Microtrust related TEE drivers will depend on this option. -- GitLab From f43330c6ea25547b9089e4f0f85475a45f8baa9e Mon Sep 17 00:00:00 2001 From: SahilSonar Date: Wed, 5 Nov 2025 10:04:16 +0100 Subject: [PATCH 3/5] arm64: dts: Extend cpu dvfs base address shift for full microtrust tee - Allows booting older fw Change-Id: Iec415fd9d2d69c0cb1fa7b7816cbbb25fcdf078a --- arch/arm64/boot/dts/mediatek/mt6765.dts | 36 +++++++++---------- .../src/mach/mt6765/mtk_cpufreq_platform.h | 6 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt6765.dts b/arch/arm64/boot/dts/mediatek/mt6765.dts index 06cb369f8734..cc54d251cc4f 100755 --- a/arch/arm64/boot/dts/mediatek/mt6765.dts +++ b/arch/arm64/boot/dts/mediatek/mt6765.dts @@ -664,16 +664,16 @@ firmware_class.path=/vendor/firmware"; #clock-cells = <1>; }; -#if defined(CONFIG_MICROTRUST_TEE_LITE_SUPPORT) - mcdi@0010fc00 { - compatible = "mediatek,mt6765-mcdi"; - reg = <0 0x0010fc00 0 0x800>; - }; -#else +#if defined(CONFIG_TRUSTKERNEL_TEE_SUPPORT) mcdi@00110100 { compatible = "mediatek,mt6765-mcdi"; reg = <0 0x00110100 0 0x800>; }; +#else + mcdi@0010fc00 { + compatible = "mediatek,mt6765-mcdi"; + reg = <0 0x0010fc00 0 0x800>; + }; #endif scpsys: scpsys@10001000 { @@ -1107,16 +1107,16 @@ firmware_class.path=/vendor/firmware"; compatible = "mediatek,mt6765-dvfsrc-met"; }; -#if defined(CONFIG_MICROTRUST_TEE_LITE_SUPPORT) - qos@00110780 { - compatible = "mediatek,mt6765-qos"; - reg = <0 0x00110780 0 0x80>; - }; -#else +#if defined(CONFIG_TRUSTKERNEL_TEE_SUPPORT) qos@00110b80 { compatible = "mediatek,mt6765-qos"; reg = <0 0x00110b80 0 0x80>; }; +#else + qos@00110780 { + compatible = "mediatek,mt6765-qos"; + reg = <0 0x00110780 0 0x80>; + }; #endif }; @@ -1485,16 +1485,16 @@ firmware_class.path=/vendor/firmware"; reg = <0 0x10227000 0 0x1000>; }; -#if defined(CONFIG_MICROTRUST_TEE_LITE_SUPPORT) - dvfsp@00110800 { - compatible = "mediatek,mt6765-dvfsp"; - reg = <0 0x00110800 0 0x1400>, - <0 0x00110800 0 0x1400>; -#else +#if defined(CONFIG_TRUSTKERNEL_TEE_SUPPORT) dvfsp@00110c00 { compatible = "mediatek,mt6765-dvfsp"; reg = <0 0x00110c00 0 0x1400>, <0 0x00110c00 0 0x1400>; +#else + dvfsp@00110800 { + compatible = "mediatek,mt6765-dvfsp"; + reg = <0 0x00110800 0 0x1400>, + <0 0x00110800 0 0x1400>; #endif state = <1>; change_flag = <0>; diff --git a/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/mt6765/mtk_cpufreq_platform.h b/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/mt6765/mtk_cpufreq_platform.h index 806c5e60e00b..951fcc9313dc 100644 --- a/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/mt6765/mtk_cpufreq_platform.h +++ b/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/mt6765/mtk_cpufreq_platform.h @@ -41,10 +41,10 @@ #define DVFSP_DT_NODE "mediatek,mt6765-dvfsp" -#ifdef CONFIG_MICROTRUST_TEE_LITE_SUPPORT -#define CSRAM_BASE 0x00110800 -#else +#ifdef CONFIG_TRUSTKERNEL_TEE_SUPPORT #define CSRAM_BASE 0x00110C00 +#else +#define CSRAM_BASE 0x00110800 #endif #define CSRAM_SIZE 0x1400 /* 5K bytes */ -- GitLab From 0767347dfd11ec90867dd08a56698af6b887d941 Mon Sep 17 00:00:00 2001 From: bengris32 Date: Thu, 6 Nov 2025 12:30:05 +0530 Subject: [PATCH 4/5] gen4m: Add NL80211_WPA_VERSION_3 enumeration Signed-off-by: bengris32 Change-Id: I9fe0aa9d6420380b727532ae054d75097bacd07f --- .../wlan/core/gen4m/os/linux/gl_cfg80211.c | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c index a2c5bf434d1b..4c7982b077ce 100644 --- a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c @@ -94,6 +94,7 @@ * D A T A T Y P E S ******************************************************************************* */ +#define IW_AUTH_WPA_VERSION_WPA3 0x00000008 /******************************************************************************* * P U B L I C D A T A @@ -1386,6 +1387,9 @@ int mtk_cfg80211_connect(struct wiphy *wiphy, else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) prWpaInfo->u4WpaVersion = IW_AUTH_WPA_VERSION_WPA2; + else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_WPA3; else prWpaInfo->u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; @@ -1587,6 +1591,21 @@ int mtk_cfg80211_connect(struct wiphy *wiphy, sme->crypto.akm_suites[0]); return -EINVAL; } + } else if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA3) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_SAE: + if (sme->auth_type == NL80211_AUTHTYPE_SAE) + eAuthMode = AUTH_MODE_WPA3_SAE; + else + eAuthMode = AUTH_MODE_OPEN; + u4AkmSuite = RSN_AKM_SUITE_SAE; + break; + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%d)\n", + sme->crypto.akm_suites[0]); + return -EINVAL; + } } } @@ -2319,6 +2338,9 @@ int mtk_cfg80211_set_rekey_data(struct wiphy *wiphy, prGtkData->u4Proto = NL80211_WPA_VERSION_2; if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA3) + prGtkData->u4Proto = NL80211_WPA_VERSION_3; + else if (prWpaInfo->u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) prGtkData->u4Proto = NL80211_WPA_VERSION_1; -- GitLab From 69c439a2b24e1ea5b2e8994d4f59b2149564a4b1 Mon Sep 17 00:00:00 2001 From: Chung-Hsien Hsu Date: Thu, 9 May 2019 09:49:05 +0000 Subject: [PATCH 5/5] nl80211: add WPA3 definition for SAE authentication Add definition of WPA version 3 for SAE authentication. Change-Id: I19ca34b8965168f011cc1352eba420f2d54b0258 Signed-off-by: Chung-Hsien Hsu Signed-off-by: Chi-Hsien Lin Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 1 + net/wireless/nl80211.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index e98d90b5e6a4..95cb23895b39 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4387,6 +4387,7 @@ enum nl80211_mfp { enum nl80211_wpa_versions { NL80211_WPA_VERSION_1 = 1 << 0, NL80211_WPA_VERSION_2 = 1 << 1, + NL80211_WPA_VERSION_3 = 1 << 2, }; /** diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ffdb538c441e..994d62e24fbc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -8524,7 +8524,8 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) static bool nl80211_valid_wpa_versions(u32 wpa_versions) { return !(wpa_versions & ~(NL80211_WPA_VERSION_1 | - NL80211_WPA_VERSION_2)); + NL80211_WPA_VERSION_2 | + NL80211_WPA_VERSION_3)); } static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) -- GitLab