From a47d84ef4d9ad8a43b21da16cb9d96c9ed4a6dd2 Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Thu, 13 Jul 2023 16:54:20 +0200 Subject: [PATCH 1/2] tools: exclude ext directory ext directory gathers external files. Disable copyright and tabs check for those external files used for unitary test Signed-off-by: Vincent Guittot --- tools/check_copyright.py | 3 ++- tools/check_tabs.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/check_copyright.py b/tools/check_copyright.py index 59ed56ab1..7c8802b42 100755 --- a/tools/check_copyright.py +++ b/tools/check_copyright.py @@ -28,6 +28,7 @@ from itertools import islice # Exclude all mod_test "mocks" directories UNIT_TEST_MOCKS = glob.glob('module/**/test/**/mocks', recursive=True) +UNIT_TEST_EXT = glob.glob('module/**/test/ext', recursive=True) EXCLUDE_DIRECTORIES = [ '.git', @@ -37,7 +38,7 @@ EXCLUDE_DIRECTORIES = [ "contrib/cmock/git", 'product/rcar/src/CMSIS-FreeRTOS', 'unit_test/unity_mocks', -] + UNIT_TEST_MOCKS +] + UNIT_TEST_MOCKS + UNIT_TEST_EXT # # Supported file types diff --git a/tools/check_tabs.py b/tools/check_tabs.py index dae04175b..2a8c6d110 100755 --- a/tools/check_tabs.py +++ b/tools/check_tabs.py @@ -24,6 +24,7 @@ import glob # Exclude all mod_test "mocks" directories UNIT_TEST_MOCKS = glob.glob('module/**/test/**/mocks', recursive=True) +UNIT_TEST_EXT = glob.glob('module/**/test/ext', recursive=True) EXCLUDE_DIRECTORIES = [ '.git', @@ -33,7 +34,7 @@ EXCLUDE_DIRECTORIES = [ "contrib/cmock/git", 'product/rcar/src/CMSIS-FreeRTOS', 'unit_test/unity_mocks', -] + UNIT_TEST_MOCKS +] + UNIT_TEST_MOCKS + UNIT_TEST_EXT # # Exclude patterns (applied to files only) -- GitLab From 684b70200cda7e9a0a1d4b1f7a6d3ef43ba7eea9 Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Mon, 3 Jul 2023 15:39:29 +0200 Subject: [PATCH 2/2] module/optee/smt: add unitary test Add unitary tests for optee/smt module: 100% code coverage Signed-off-by: Vincent Guittot --- module/optee/smt/test/CMakeLists.txt | 35 + module/optee/smt/test/config_optee_smt.h | 57 ++ module/optee/smt/test/ext/compiler.h | 279 ++++++ module/optee/smt/test/ext/optee_scmi.h | 21 + module/optee/smt/test/ext/tee_api_defines.h | 601 ++++++++++++ module/optee/smt/test/ext/tee_api_types.h | 205 ++++ module/optee/smt/test/ext/types_ext.h | 37 + module/optee/smt/test/fwk_module_idx.h | 25 + module/optee/smt/test/mocks/.clang-format | 4 + .../smt/test/mocks/Mockmod_optee_smt_extra.c | 217 +++++ .../smt/test/mocks/Mockmod_optee_smt_extra.h | 52 + module/optee/smt/test/mod_optee_smt_extra.h | 20 + .../optee/smt/test/mod_optee_smt_unit_test.c | 889 ++++++++++++++++++ unit_test/CMakeLists.txt | 1 + 14 files changed, 2443 insertions(+) create mode 100644 module/optee/smt/test/CMakeLists.txt create mode 100644 module/optee/smt/test/config_optee_smt.h create mode 100644 module/optee/smt/test/ext/compiler.h create mode 100644 module/optee/smt/test/ext/optee_scmi.h create mode 100644 module/optee/smt/test/ext/tee_api_defines.h create mode 100644 module/optee/smt/test/ext/tee_api_types.h create mode 100644 module/optee/smt/test/ext/types_ext.h create mode 100644 module/optee/smt/test/fwk_module_idx.h create mode 100644 module/optee/smt/test/mocks/.clang-format create mode 100644 module/optee/smt/test/mocks/Mockmod_optee_smt_extra.c create mode 100644 module/optee/smt/test/mocks/Mockmod_optee_smt_extra.h create mode 100644 module/optee/smt/test/mod_optee_smt_extra.h create mode 100644 module/optee/smt/test/mod_optee_smt_unit_test.c diff --git a/module/optee/smt/test/CMakeLists.txt b/module/optee/smt/test/CMakeLists.txt new file mode 100644 index 000000000..50d648b8a --- /dev/null +++ b/module/optee/smt/test/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(TEST_SRC mod_optee_smt) +set(TEST_FILE mod_optee_smt) + +# set(UNIT_TEST_TARGET mod_${TEST_MODULE}_unit_test) This setting will not work +# as TEST_MODULE in that case will be optee/mbx which will not be parsed +# correctly. Hence, setting the UNIT_TEST_TARGET explicitly as follows +set(UNIT_TEST_TARGET mod_optee_smt_unit_test) + +set(MODULE_SRC ${MODULE_ROOT}/${TEST_MODULE}/src) +set(MODULE_INC ${MODULE_ROOT}/${TEST_MODULE}/include) +list(APPEND OTHER_MODULE_INC ${MODULE_ROOT}/optee/smt/include) +list(APPEND OTHER_MODULE_INC ${MODULE_ROOT}/optee/mbx/include) +list(APPEND OTHER_MODULE_INC ${MODULE_ROOT}/scmi/include) +set(MODULE_UT_SRC ${CMAKE_CURRENT_LIST_DIR}) +set(MODULE_UT_INC ${CMAKE_CURRENT_LIST_DIR}) +set(MODULE_UT_INC ${CMAKE_CURRENT_LIST_DIR}/ext) +set(MODULE_UT_MOCK_SRC ${CMAKE_CURRENT_LIST_DIR}/mocks) + +list(APPEND MOCK_REPLACEMENTS fwk_module) +list(APPEND MOCK_REPLACEMENTS fwk_id) +list(APPEND MOCK_REPLACEMENTS fwk_core) +list(APPEND MOCK_REPLACEMENTS fwk_mm) +list(APPEND MOCK_REPLACEMENTS fwk_string) + +include(${SCP_ROOT}/unit_test/module_common.cmake) + +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC "BUILD_HAS_MOD_OPTEE_SMT") +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC "BUILD_HAS_MOD_MSG_SMT") diff --git a/module/optee/smt/test/config_optee_smt.h b/module/optee/smt/test/config_optee_smt.h new file mode 100644 index 000000000..d4a7101f2 --- /dev/null +++ b/module/optee/smt/test/config_optee_smt.h @@ -0,0 +1,57 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * This represents index of the channel descriptor within + * element table + */ +enum msg_channel_idx { + FAKE_SCMI_SERVICE_IDX_OSPM_0, + FAKE_SCMI_SERVICE_IDX_COUNT, +}; + +enum scmi_service_channel_idx { + FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0, + FAKE_SCMI_CHANNEL_DEVICE_IDX_COUNT +}; + +#define FAKE_MAILBOX_SIZE 128 +#define FAKE_OSPM0_SMT_MAILBOX_PA 0xDEADBEEF + +/* Provide a fake device info */ +static struct fwk_element smt_element_table[] = { + [FAKE_SCMI_SERVICE_IDX_OSPM_0] = { + .name = "OSPM0", + .data = &((struct mod_optee_smt_channel_config) { + .type = MOD_OPTEE_SMT_CHANNEL_TYPE_REQUESTER, + .mailbox_address = FAKE_OSPM0_SMT_MAILBOX_PA, + .mailbox_size = FAKE_MAILBOX_SIZE, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MBX, + FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MBX, 0), + }) + }, + [FAKE_SCMI_SERVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *smt_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)smt_element_table; +} + +struct fwk_module_config config_fake_optee_smt = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(smt_get_element_table), +}; diff --git a/module/optee/smt/test/ext/compiler.h b/module/optee/smt/test/ext/compiler.h new file mode 100644 index 000000000..c690f5885 --- /dev/null +++ b/module/optee/smt/test/ext/compiler.h @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef COMPILER_H +#define COMPILER_H + +/* + * Macros that should be used instead of using __attribute__ directly to + * ease portability and make the code easier to read. + * + * Some of the defines below is known to sometimes cause conflicts when + * this file is included from xtest in normal world. It is assumed that + * the conflicting defines has the same meaning in that environment. + * Surrounding the troublesome defines with #ifndef should be enough. + */ +#define __deprecated __attribute__((deprecated)) +#ifndef __packed +#define __packed __attribute__((packed)) +#endif +#define __weak __attribute__((weak)) +#define __alias(x) __attribute__((alias(x))) +#ifndef __noreturn +#define __noreturn __attribute__((__noreturn__)) +#endif +#define __pure __attribute__((pure)) +#define __aligned(x) __attribute__((aligned(x))) +#define __printf(a, b) __attribute__((format(printf, a, b))) +#define __noinline __attribute__((noinline)) +#define __attr_const __attribute__((__const__)) +#ifndef __unused +#define __unused __attribute__((unused)) +#endif +#define __maybe_unused __attribute__((unused)) +#ifndef __used +#define __used __attribute__((__used__)) +#endif +#define __must_check __attribute__((warn_unused_result)) +#define __cold __attribute__((__cold__)) +#define __section(x) __attribute__((section(x))) +#define __data __section(".data") +#define __bss __section(".bss") +#ifdef __clang__ +#define __SECTION_FLAGS_RODATA +#else +/* + * Override sections flags/type generated by the C compiler to make sure they + * are: "a",%progbits (thus creating an allocatable, non-writeable, non- + * executable data section). + * The trailing COMMENT_CHAR comments out the flags generated by the compiler. + * This avoids a harmless warning with GCC. + */ +#if defined(__aarch64__) || defined(__arm__) +#define COMMENT_CHAR "//" +#else +#define COMMENT_CHAR "#" +#endif +#define __SECTION_FLAGS_RODATA ",\"a\",%progbits " COMMENT_CHAR +#endif +#define __rodata __section(".rodata" __SECTION_FLAGS_RODATA) +#define __rodata_dummy __section(".rodata.dummy" __SECTION_FLAGS_RODATA) +#define __rodata_unpaged(x) \ + __section(".rodata.__unpaged." x __SECTION_FLAGS_RODATA) +#ifdef CFG_CORE_ASLR +#define __relrodata_unpaged(x) __section(".data.rel.ro.__unpaged." x) +#else +#define __relrodata_unpaged(x) __rodata_unpaged(x) +#endif +#ifdef CFG_VIRTUALIZATION +#define __nex_bss __section(".nex_bss") +#define __nex_data __section(".nex_data") +#else /* CFG_VIRTUALIZATION */ +#define __nex_bss +#define __nex_data +#endif /* CFG_VIRTUALIZATION */ +#define __noprof __attribute__((no_instrument_function)) +#define __nostackcheck __attribute__((no_instrument_function)) + +#define __compiler_bswap64(x) __builtin_bswap64((x)) +#define __compiler_bswap32(x) __builtin_bswap32((x)) +#define __compiler_bswap16(x) __builtin_bswap16((x)) + +#define __GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + \ + __GNUC_PATCHLEVEL__) + +#if __GCC_VERSION >= 50100 && !defined(__CHECKER__) +#define __HAVE_BUILTIN_OVERFLOW 1 +#endif + +#if __GCC_VERSION >= 90100 && !defined(__CHECKER__) +#define __HAVE_SINGLE_ARGUMENT_STATIC_ASSERT 1 +#endif + +#ifdef __HAVE_BUILTIN_OVERFLOW +#define __compiler_add_overflow(a, b, res) \ + __builtin_add_overflow((a), (b), (res)) + +#define __compiler_sub_overflow(a, b, res) \ + __builtin_sub_overflow((a), (b), (res)) + +#define __compiler_mul_overflow(a, b, res) \ + __builtin_mul_overflow((a), (b), (res)) +#else /*!__HAVE_BUILTIN_OVERFLOW*/ + +/* + * Copied/inspired from https://www.fefe.de/intof.html + */ + +#define __INTOF_ASSIGN(dest, src) (__extension__({ \ + typeof(src) __intof_x = (src); \ + typeof(dest) __intof_y = __intof_x; \ + (((uintmax_t)__intof_x == (uintmax_t)__intof_y) && \ + ((__intof_x < 1) == (__intof_y < 1)) ? \ + (void)((dest) = __intof_y) , 0 : 1); \ +})) + +#define __INTOF_ADD(c, a, b) (__extension__({ \ + typeof(a) __intofa_a = (a); \ + typeof(b) __intofa_b = (b); \ + intmax_t __intofa_a_signed = __intofa_a; \ + uintmax_t __intofa_a_unsigned = __intofa_a; \ + intmax_t __intofa_b_signed = __intofa_b; \ + uintmax_t __intofa_b_unsigned = __intofa_b; \ + \ + __intofa_b < 1 ? \ + __intofa_a < 1 ? \ + ((INTMAX_MIN - __intofa_b_signed <= \ + __intofa_a_signed)) ? \ + __INTOF_ASSIGN((c), __intofa_a_signed + \ + __intofa_b_signed) : 1 \ + : \ + ((__intofa_a_unsigned >= (uintmax_t)-__intofa_b) ? \ + __INTOF_ASSIGN((c), __intofa_a_unsigned + \ + __intofa_b_signed) \ + : \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofa_a_unsigned + \ + __intofa_b_signed))) \ + : \ + __intofa_a < 1 ? \ + ((__intofa_b_unsigned >= (uintmax_t)-__intofa_a) ? \ + __INTOF_ASSIGN((c), __intofa_a_signed + \ + __intofa_b_unsigned) \ + : \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofa_a_signed + \ + __intofa_b_unsigned))) \ + : \ + ((UINTMAX_MAX - __intofa_b_unsigned >= \ + __intofa_a_unsigned) ? \ + __INTOF_ASSIGN((c), __intofa_a_unsigned + \ + __intofa_b_unsigned) : 1); \ +})) + +#define __INTOF_SUB(c, a, b) (__extension__({ \ + typeof(a) __intofs_a = a; \ + typeof(b) __intofs_b = b; \ + intmax_t __intofs_a_signed = __intofs_a; \ + uintmax_t __intofs_a_unsigned = __intofs_a; \ + intmax_t __intofs_b_signed = __intofs_b; \ + uintmax_t __intofs_b_unsigned = __intofs_b; \ + \ + __intofs_b < 1 ? \ + __intofs_a < 1 ? \ + ((INTMAX_MAX + __intofs_b_signed >= \ + __intofs_a_signed) ? \ + __INTOF_ASSIGN((c), __intofs_a_signed - \ + __intofs_b_signed) : 1) \ + : \ + (((uintmax_t)(UINTMAX_MAX + __intofs_b_signed) >= \ + __intofs_a_unsigned) ? \ + __INTOF_ASSIGN((c), __intofs_a - \ + __intofs_b) : 1) \ + : \ + __intofs_a < 1 ? \ + (((intmax_t)(INTMAX_MIN + __intofs_b) <= \ + __intofs_a_signed) ? \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofs_a_signed - \ + __intofs_b_unsigned)) : 1) \ + : \ + ((__intofs_b_unsigned <= __intofs_a_unsigned) ? \ + __INTOF_ASSIGN((c), __intofs_a_unsigned - \ + __intofs_b_unsigned) \ + : \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofs_a_unsigned - \ + __intofs_b_unsigned))); \ +})) + +/* + * Dealing with detecting overflow in multiplication of integers. + * + * First step is to remove two corner cases with the minum signed integer + * which can't be represented as a positive integer + sign. + * Multiply with 0 or 1 can't overflow, no checking needed of the operation, + * only if it can be assigned to the result. + * + * After the corner cases are eliminated we convert the two factors to + * positive unsigned values, keeping track of the original in another + * variable which is used at the end to determine the sign of the product. + * + * The two terms (a and b) are divided into upper and lower half (x1 upper + * and x0 lower), so the product is: + * ((a1 << hshift) + a0) * ((b1 << hshift) + b0) + * which also is: + * ((a1 * b1) << (hshift * 2)) + (T1) + * ((a1 * b0 + a0 * b1) << hshift) + (T2) + * (a0 * b0) (T3) + * + * From this we can tell and (a1 * b1) has to be 0 or we'll overflow, that + * is, at least one of a1 or b1 has to be 0. Once this has been checked the + * addition: ((a1 * b0) << hshift) + ((a0 * b1) << hshift) + * isn't an addition as one of the terms will be 0. + * + * Since each factor in: (a0 * b0) + * only uses half the capicity of the underlaying type it can't overflow + * + * The addition of T2 and T3 can overflow so we use __INTOF_ADD() to + * perform that addition. If the addition succeeds without overflow the + * result is assigned the required sign and checked for overflow again. + */ + +#define __intof_mul_negate ((__intof_oa < 1) != (__intof_ob < 1)) +#define __intof_mul_hshift (sizeof(uintmax_t) * 8 / 2) +#define __intof_mul_hmask (UINTMAX_MAX >> __intof_mul_hshift) +#define __intof_mul_a0 ((uintmax_t)(__intof_a) >> __intof_mul_hshift) +#define __intof_mul_b0 ((uintmax_t)(__intof_b) >> __intof_mul_hshift) +#define __intof_mul_a1 ((uintmax_t)(__intof_a) & __intof_mul_hmask) +#define __intof_mul_b1 ((uintmax_t)(__intof_b) & __intof_mul_hmask) +#define __intof_mul_t (__intof_mul_a1 * __intof_mul_b0 + \ + __intof_mul_a0 * __intof_mul_b1) + +#define __INTOF_MUL(c, a, b) (__extension__({ \ + typeof(a) __intof_oa = (a); \ + typeof(a) __intof_a = __intof_oa < 1 ? -__intof_oa : __intof_oa; \ + typeof(b) __intof_ob = (b); \ + typeof(b) __intof_b = __intof_ob < 1 ? -__intof_ob : __intof_ob; \ + typeof(c) __intof_c; \ + \ + __intof_oa == 0 || __intof_ob == 0 || \ + __intof_oa == 1 || __intof_ob == 1 ? \ + __INTOF_ASSIGN((c), __intof_oa * __intof_ob) : \ + (__intof_mul_a0 && __intof_mul_b0) || \ + __intof_mul_t > __intof_mul_hmask ? 1 : \ + __INTOF_ADD((__intof_c), __intof_mul_t << __intof_mul_hshift, \ + __intof_mul_a1 * __intof_mul_b1) ? 1 : \ + __intof_mul_negate ? __INTOF_ASSIGN((c), -__intof_c) : \ + __INTOF_ASSIGN((c), __intof_c); \ +})) + +#define __compiler_add_overflow(a, b, res) __INTOF_ADD(*(res), (a), (b)) +#define __compiler_sub_overflow(a, b, res) __INTOF_SUB(*(res), (a), (b)) +#define __compiler_mul_overflow(a, b, res) __INTOF_MUL(*(res), (a), (b)) + +#endif /*!__HAVE_BUILTIN_OVERFLOW*/ + +#define __compiler_compare_and_swap(p, oval, nval) \ + __atomic_compare_exchange_n((p), (oval), (nval), true, \ + __ATOMIC_ACQUIRE, __ATOMIC_RELAXED) \ + +#define __compiler_atomic_load(p) __atomic_load_n((p), __ATOMIC_RELAXED) +#define __compiler_atomic_store(p, val) \ + __atomic_store_n((p), (val), __ATOMIC_RELAXED) + +#define barrier() asm volatile ("" : : : "memory") + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#if __has_attribute(__fallthrough__) +#define fallthrough __attribute__((__fallthrough__)) +#else +#define fallthrough do {} while (0) /* fallthrough */ +#endif + +#endif /*COMPILER_H*/ diff --git a/module/optee/smt/test/ext/optee_scmi.h b/module/optee/smt/test/ext/optee_scmi.h new file mode 100644 index 000000000..85feb006c --- /dev/null +++ b/module/optee/smt/test/ext/optee_scmi.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2023, Linaro Limited + */ +#ifndef OPTEE_SCMI_H +#define OPTEE_SCMI_H + +#include +#include + +/* + * Return virtual address mapped for target SMT IOMEM address range + * + * @pa: Target address range base physical address + * @sz: Target address range byte size + * @shmem_is_secure: True if memory is secure, false otherwise + * Return a virtual address or 0 is memory is not mapped + */ +uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure); + +#endif /* OPTEE_SCMI_H */ diff --git a/module/optee/smt/test/ext/tee_api_defines.h b/module/optee/smt/test/ext/tee_api_defines.h new file mode 100644 index 000000000..9fb93d3b6 --- /dev/null +++ b/module/optee/smt/test/ext/tee_api_defines.h @@ -0,0 +1,601 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* Based on GP TEE Internal Core API Specification Version 1.1 */ + +#ifndef TEE_API_DEFINES_H +#define TEE_API_DEFINES_H + +#define TEE_CORE_API_MAJOR_VERSION 1U +#define TEE_CORE_API_MINOR_VERSION 1U +#define TEE_CORE_API_MAINTENANCE_VERSION 0U +#define TEE_CORE_API_VERSION \ + ((TEE_CORE_API_MAJOR_VERSION << 24) | \ + (TEE_CORE_API_MINOR_VERSION << 16) | \ + (TEE_CORE_API_MAINTENANCE_VERSION << 8)) +#define TEE_CORE_API_1_1 + +/* + * The things that follows below to select compatibility version 1.1 doesn't + * do much useful at the moment since OP-TEE is already compatible with that + * version by default. However, that will change when a newer version of + * this API is provided. + * + * Below follows the GP defined way of letting a TA define that it wants an + * API compatible with version 1.1 or the latest. An alternative approach + * is to set __OPTEE_CORE_API_COMPAT_1_1, but that's an OP-TEE extension. + * + * The GP specs (>= 1.2) requires that only APIs defined in the indicated + * version SHALL be made available when using this mechanism. However, that + * is far beyond what ordinary standards requires as they permit + * extensions. With this, in OP-TEE, extensions and new API that doesn't + * interfere with the selected version of the standard will be permitted. + */ +#if defined(TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION) && \ + !defined(TEE_CORE_API_REQUIRED_MINOR_VERSION) +#error "Required TEE_CORE_API_REQUIRED_MINOR_VERSION undefined" +#endif +#if defined(TEE_CORE_API_REQUIRED_MINOR_VERSION) && \ + !defined(TEE_CORE_API_REQUIRED_MAJOR_VERSION) +#error "Required TEE_CORE_API_REQUIRED_MAJOR_VERSION undefined" +#endif + +#if defined(TEE_CORE_API_REQUIRED_MAJOR_VERSION) +#if TEE_CORE_API_REQUIRED_MAJOR_VERSION != 1 && \ + TEE_CORE_API_REQUIRED_MAJOR_VERSION != 0 +#error "Required major version not supported" +#endif +#ifdef TEE_CORE_API_REQUIRED_MINOR_VERSION +#if TEE_CORE_API_REQUIRED_MINOR_VERSION == 1 +#define __OPTEE_CORE_API_COMPAT_1_1 1 +#else +#error "Required minor version not supported" +#endif +#if defined(TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION) && \ + TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION != 0 +#error "Required maintenance version not supported" +#endif +#endif +#endif + +/* + * For backwards compatibility with v1.1 as provided by up to OP-TEE + * version 3.19.0, define __OPTEE_CORE_API_COMPAT_1_1 to 1. + * + * Some versions of the GP specs have introduced backwards incompatible + * changes. For example the v1.0: + * + * TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, + * const void *chunk, uint32_t chunkLen, + * void *hash, uint32_t *hashLen); + * + * Was changed in v1.1.1 to this: + * + * TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, + * const void *chunk, size_t chunkLen, + * void *hash, size_t *hashLen); + * + * Note the type change for "hashLen", a source of problem especially on + * platforms where size_t is a 64-bit unsigned integer. + * + * As a way of allowing older TAs to be compiled with a newer version of + * the API we can turn off or hide different incompatible changes. New + * features which are not interfering with older versions of the API are + * not disabled. So by enabling __OPTEE_CORE_API_COMPAT_1_1 will not result + * in pure 1.1 API, it will be a hybrid API that should work with most TAs + * not yet updated to the new API. + * + * Backwards compatibility is provided by duplicating all functions that + * has changed since v1.1. The original function is given a "__GP11_" + * prefix and preprocessor macros are used to let a legacy TA use the old + * function instead. The same principle applies to defined types. + */ +#ifndef __OPTEE_CORE_API_COMPAT_1_1 +#define __OPTEE_CORE_API_COMPAT_1_1 0 +#endif + +#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_CIPHERTEXT_INVALID 0xF0100006 +#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_SM4_ECB_NOPAD 0x10000014 +#define TEE_ALG_SM4_CBC_NOPAD 0x10000114 +#define TEE_ALG_SM4_CTR 0x10000214 +#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_SM2_DSA_SM3 0x70006045 +#define TEE_ALG_DH_DERIVE_SHARED_SECRET 0x80000032 +#define TEE_ALG_SM2_KEP 0x60000045 +#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_SHA3_224 0x50000008 +#define TEE_ALG_SHA3_256 0x50000009 +#define TEE_ALG_SHA3_384 0x5000000A +#define TEE_ALG_SHA3_512 0x5000000B +#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 +#define TEE_ALG_HMAC_SM3 0x30000007 +/* + * 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_ED25519 0x70006043 /* v1.3.1 spec */ +#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 +#define TEE_ALG_SM2_PKE 0x80000045 +#define TEE_ALG_SM3 0x50000007 +#define TEE_ALG_X25519 0x80000044 +#define TEE_ALG_ILLEGAL_VALUE 0xEFFFFFFF + +/* Object Types */ + +#define TEE_TYPE_AES 0xA0000010 +#define TEE_TYPE_DES 0xA0000011 +#define TEE_TYPE_DES3 0xA0000013 +#define TEE_TYPE_SM4 0xA0000014 +#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_HMAC_SM3 0xA0000007 /* Not in spec */ +#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_ED25519_PUBLIC_KEY 0xA0000043 /* v1.3.1 spec */ +#define TEE_TYPE_ED25519_KEYPAIR 0xA1000043 /* v1.3.1 spec */ +#define TEE_TYPE_SM2_DSA_PUBLIC_KEY 0xA0000045 +#define TEE_TYPE_SM2_DSA_KEYPAIR 0xA1000045 +#define TEE_TYPE_SM2_KEP_PUBLIC_KEY 0xA0000046 +#define TEE_TYPE_SM2_KEP_KEYPAIR 0xA1000046 +#define TEE_TYPE_SM2_PKE_PUBLIC_KEY 0xA0000047 +#define TEE_TYPE_SM2_PKE_KEYPAIR 0xA1000047 +#define TEE_TYPE_GENERIC_SECRET 0xA0000000 +#define TEE_TYPE_CORRUPTED_OBJECT 0xA00000BE +#define TEE_TYPE_DATA 0xA00000BF +#define TEE_TYPE_X25519_PUBLIC_KEY 0xA0000044 +#define TEE_TYPE_X25519_KEYPAIR 0xA1000044 + +/* 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_SM2_ID_INITIATOR 0xD0000446 +#define TEE_ATTR_SM2_ID_RESPONDER 0xD0000546 +#define TEE_ATTR_SM2_KEP_USER 0xF0000646 +#define TEE_ATTR_SM2_KEP_CONFIRMATION_IN 0xD0000746 +#define TEE_ATTR_SM2_KEP_CONFIRMATION_OUT 0xD0000846 + +/* + * Commit 5b385b3f835d ("core: crypto: add support for SM2 KEP") defined by + * mistake the wrong values for these two. OP-TEE recognizes these two as + * alternative IDs in parallel with the correct official values when + * supplied as parameters when deriving a key using the TEE_ALG_SM2_KEP + * algorithm. + */ +#define __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X 0xD0000946 +#define __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y 0xD0000A46 + +#define TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X 0xD0000146 +#define TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y 0xD0000246 +#define TEE_ATTR_EDDSA_CTX 0xD0000643 /* v1.3.1 spec */ +#define TEE_ATTR_ED25519_PUBLIC_VALUE 0xD0000743 /* v1.3.1 spec */ +#define TEE_ATTR_ED25519_PRIVATE_VALUE 0xC0000843 /* v1.3.1 spec */ +#define TEE_ATTR_X25519_PUBLIC_VALUE 0xD0000944 +#define TEE_ATTR_X25519_PRIVATE_VALUE 0xC0000A44 +#define TEE_ATTR_EDDSA_PREHASH 0xF0000004 /* v1.3.1 spec */ + +#define TEE_ATTR_FLAG_PUBLIC (1 << 28) +#define TEE_ATTR_FLAG_VALUE (1 << 29) +/* + * Deprecated, but kept for backwards compatibility + * + * Be careful with GPD TEE Internal API specification v1.0 where table 6-12 + * defines BIT [28] with the right meaning whereas sections 5.4.3 and 5.4.4 + * falsely describe a reversed bit flag value meaning. + */ +#define TEE_ATTR_BIT_PROTECTED TEE_ATTR_FLAG_PUBLIC +#define TEE_ATTR_BIT_VALUE TEE_ATTR_FLAG_VALUE + +/* List of Supported ECC Curves */ +#define TEE_CRYPTO_ELEMENT_NONE 0x00000000 +#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 +#define TEE_ECC_CURVE_25519 0x00000300 +#define TEE_ECC_CURVE_SM2 0x00000400 + +/* 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_OUPUT, + * 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/module/optee/smt/test/ext/tee_api_types.h b/module/optee/smt/test/ext/tee_api_types.h new file mode 100644 index 000000000..0b232172f --- /dev/null +++ b/module/optee/smt/test/ext/tee_api_types.h @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* Based on GP TEE Internal API Specification Version 0.11 */ +#ifndef TEE_API_TYPES_H +#define TEE_API_TYPES_H + +#include +#include +#include +#include +#include + +/* + * Common Definitions + */ + +typedef uint32_t TEE_Result; + +typedef struct { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint8_t clockSeqAndNode[8]; +} TEE_UUID; + +/* + * The TEE_Identity structure defines the full identity of a Client: + * - login is one of the TEE_LOGIN_XXX constants + * - uuid contains the client UUID or Nil if not applicable + */ +typedef struct { + uint32_t login; + TEE_UUID uuid; +} TEE_Identity; + +/* + * This union describes one parameter passed by the Trusted Core Framework + * to the entry points TA_OpenSessionEntryPoint or + * TA_InvokeCommandEntryPoint or by the TA to the functions + * TEE_OpenTASession or TEE_InvokeTACommand. + * + * Which of the field value or memref to select is determined by the + * parameter type specified in the argument paramTypes passed to the entry + * point. +*/ +typedef union { + struct { + void *buffer; + uint32_t size; + } memref; + struct { + uint32_t a; + uint32_t b; + } value; +} TEE_Param; + +/* + * The type of opaque handles on TA Session. These handles are returned by + * the function TEE_OpenTASession. + */ +typedef struct __TEE_TASessionHandle *TEE_TASessionHandle; + +/* + * The type of opaque handles on property sets or enumerators. These + * handles are either one of the pseudo handles TEE_PROPSET_XXX or are + * returned by the function TEE_AllocatePropertyEnumerator. +*/ +typedef struct __TEE_PropSetHandle *TEE_PropSetHandle; + +typedef struct __TEE_ObjectHandle *TEE_ObjectHandle; +typedef struct __TEE_ObjectEnumHandle *TEE_ObjectEnumHandle; +typedef struct __TEE_OperationHandle *TEE_OperationHandle; + +/* + * Storage Definitions + */ + +typedef uint32_t TEE_ObjectType; + +typedef struct { + uint32_t objectType; + __extension__ union { + uint32_t keySize; /* used in 1.1 spec */ + uint32_t objectSize; /* used in 1.1.1 spec */ + }; + __extension__ union { + uint32_t maxKeySize; /* used in 1.1 spec */ + uint32_t maxObjectSize; /* used in 1.1.1 spec */ + }; + uint32_t objectUsage; + uint32_t dataSize; + uint32_t dataPosition; + uint32_t handleFlags; +} TEE_ObjectInfo; + +typedef enum { + TEE_DATA_SEEK_SET = 0, + TEE_DATA_SEEK_CUR = 1, + TEE_DATA_SEEK_END = 2 +} TEE_Whence; + +typedef struct { + uint32_t attributeID; + union { + struct { + void *buffer; + uint32_t length; + } ref; + struct { + uint32_t a, b; + } value; + } content; +} TEE_Attribute; + +/* Cryptographic Operations API */ + +typedef enum { + TEE_MODE_ENCRYPT = 0, + TEE_MODE_DECRYPT = 1, + TEE_MODE_SIGN = 2, + TEE_MODE_VERIFY = 3, + TEE_MODE_MAC = 4, + TEE_MODE_DIGEST = 5, + TEE_MODE_DERIVE = 6 +} TEE_OperationMode; + +typedef struct { + uint32_t algorithm; + uint32_t operationClass; + uint32_t mode; + uint32_t digestLength; + uint32_t maxKeySize; + uint32_t keySize; + uint32_t requiredKeyUsage; + uint32_t handleState; +} TEE_OperationInfo; + +typedef struct { + uint32_t keySize; + uint32_t requiredKeyUsage; +} TEE_OperationInfoKey; + +typedef struct { + uint32_t algorithm; + uint32_t operationClass; + uint32_t mode; + uint32_t digestLength; + uint32_t maxKeySize; + uint32_t handleState; + uint32_t operationState; + uint32_t numberOfKeys; + TEE_OperationInfoKey keyInformation[]; +} TEE_OperationInfoMultiple; + +/* Time & Date API */ + +typedef struct { + uint32_t seconds; + uint32_t millis; +} TEE_Time; + +/* TEE Arithmetical APIs */ + +typedef uint32_t TEE_BigInt; + +typedef uint32_t TEE_BigIntFMM; + +typedef uint32_t TEE_BigIntFMMContext __aligned(__alignof__(void *)); + +/* Tee Secure Element APIs */ + +typedef struct __TEE_SEServiceHandle *TEE_SEServiceHandle; +typedef struct __TEE_SEReaderHandle *TEE_SEReaderHandle; +typedef struct __TEE_SESessionHandle *TEE_SESessionHandle; +typedef struct __TEE_SEChannelHandle *TEE_SEChannelHandle; + +typedef struct { + bool sePresent; + bool teeOnly; + bool selectResponseEnable; +} TEE_SEReaderProperties; + +typedef struct { + uint8_t *buffer; + size_t bufferLen; +} TEE_SEAID; + +/* Other definitions */ +typedef uint32_t TEE_ErrorOrigin; +typedef void *TEE_Session; + +#define TEE_MEM_INPUT 0x00000001 +#define TEE_MEM_OUTPUT 0x00000002 + +#define TEE_MEMREF_0_USED 0x00000001 +#define TEE_MEMREF_1_USED 0x00000002 +#define TEE_MEMREF_2_USED 0x00000004 +#define TEE_MEMREF_3_USED 0x00000008 + +#define TEE_SE_READER_NAME_MAX 20 + +#endif /* TEE_API_TYPES_H */ diff --git a/module/optee/smt/test/ext/types_ext.h b/module/optee/smt/test/ext/types_ext.h new file mode 100644 index 000000000..0bbade5c5 --- /dev/null +++ b/module/optee/smt/test/ext/types_ext.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __TYPES_EXT_H +#define __TYPES_EXT_H + +#include +#include +#include +#include +#include + +typedef uintptr_t uaddr_t; +#define PRIxUA PRIxPTR + +typedef uintptr_t vaddr_t; +#define PRIxVA PRIxPTR + +#if defined(__ILP32__) && defined(CFG_CORE_LARGE_PHYS_ADDR) +typedef uint64_t paddr_t; +typedef uint64_t paddr_size_t; +#define PRIxPA PRIx64 +#define PRIxPASZ PRIx64 +#define __SIZEOF_PADDR__ 8 +#else +typedef uintptr_t paddr_t; +typedef uintptr_t paddr_size_t; +#define PRIxPA PRIxPTR +#define PRIxPASZ PRIxPTR +#define __SIZEOF_PADDR__ __SIZEOF_POINTER__ +#endif + +#define PRIxVA_WIDTH ((int)(sizeof(vaddr_t) * 2)) +#define PRIxPA_WIDTH ((int)(sizeof(paddr_t) * 2)) + +#endif /* __TYPES_EXT_H */ diff --git a/module/optee/smt/test/fwk_module_idx.h b/module/optee/smt/test/fwk_module_idx.h new file mode 100644 index 000000000..c9631c5b8 --- /dev/null +++ b/module/optee/smt/test/fwk_module_idx.h @@ -0,0 +1,25 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEST_FWK_MODULE_IDX_H +#define TEST_FWK_MODULE_IDX_H + +#include + +enum fwk_module_idx { + FWK_MODULE_IDX_OPTEE_MBX, + FWK_MODULE_IDX_OPTEE_SMT, + FWK_MODULE_IDX_SCMI, + FWK_MODULE_IDX_COUNT, +}; + +#define FWK_MODULE_BIND_ROUND_MAX 2 + +static const fwk_id_t fwk_module_id_scmi = + FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI); + +#endif /* TEST_FWK_MODULE_IDX_H */ diff --git a/module/optee/smt/test/mocks/.clang-format b/module/optee/smt/test/mocks/.clang-format new file mode 100644 index 000000000..eeca2395f --- /dev/null +++ b/module/optee/smt/test/mocks/.clang-format @@ -0,0 +1,4 @@ +{ + "DisableFormat": true, + "SortIncludes": false, +} diff --git a/module/optee/smt/test/mocks/Mockmod_optee_smt_extra.c b/module/optee/smt/test/mocks/Mockmod_optee_smt_extra.c new file mode 100644 index 000000000..842ba7c97 --- /dev/null +++ b/module/optee/smt/test/mocks/Mockmod_optee_smt_extra.c @@ -0,0 +1,217 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#include +#include +#include +#include "cmock.h" +#include "Mockmod_optee_smt_extra.h" + +static const char* CMockString_pa = "pa"; +static const char* CMockString_shmem_is_secure = "shmem_is_secure"; +static const char* CMockString_smt_phys_to_virt = "smt_phys_to_virt"; +static const char* CMockString_sz = "sz"; + +typedef struct _CMOCK_smt_phys_to_virt_CALL_INSTANCE +{ + UNITY_LINE_TYPE LineNumber; + char ExpectAnyArgsBool; + uintptr_t ReturnVal; + uintptr_t Expected_pa; + size_t Expected_sz; + bool Expected_shmem_is_secure; + char IgnoreArg_pa; + char IgnoreArg_sz; + char IgnoreArg_shmem_is_secure; + +} CMOCK_smt_phys_to_virt_CALL_INSTANCE; + +static struct Mockmod_optee_smt_extraInstance +{ + char smt_phys_to_virt_IgnoreBool; + uintptr_t smt_phys_to_virt_FinalReturn; + char smt_phys_to_virt_CallbackBool; + CMOCK_smt_phys_to_virt_CALLBACK smt_phys_to_virt_CallbackFunctionPointer; + int smt_phys_to_virt_CallbackCalls; + CMOCK_MEM_INDEX_TYPE smt_phys_to_virt_CallInstance; +} Mock; + +extern jmp_buf AbortFrame; + +void Mockmod_optee_smt_extra_Verify(void) +{ + UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM; + CMOCK_MEM_INDEX_TYPE call_instance; + call_instance = Mock.smt_phys_to_virt_CallInstance; + if (Mock.smt_phys_to_virt_IgnoreBool) + call_instance = CMOCK_GUTS_NONE; + if (CMOCK_GUTS_NONE != call_instance) + { + UNITY_SET_DETAIL(CMockString_smt_phys_to_virt); + UNITY_TEST_FAIL(cmock_line, CMockStringCalledLess); + } + if (Mock.smt_phys_to_virt_CallbackFunctionPointer != NULL) + { + call_instance = CMOCK_GUTS_NONE; + (void)call_instance; + } +} + +void Mockmod_optee_smt_extra_Init(void) +{ + Mockmod_optee_smt_extra_Destroy(); +} + +void Mockmod_optee_smt_extra_Destroy(void) +{ + CMock_Guts_MemFreeAll(); + memset(&Mock, 0, sizeof(Mock)); +} + +uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure) +{ + UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM; + CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance; + UNITY_SET_DETAIL(CMockString_smt_phys_to_virt); + cmock_call_instance = (CMOCK_smt_phys_to_virt_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.smt_phys_to_virt_CallInstance); + Mock.smt_phys_to_virt_CallInstance = CMock_Guts_MemNext(Mock.smt_phys_to_virt_CallInstance); + if (Mock.smt_phys_to_virt_IgnoreBool) + { + UNITY_CLR_DETAILS(); + if (cmock_call_instance == NULL) + return Mock.smt_phys_to_virt_FinalReturn; + memcpy((void*)(&Mock.smt_phys_to_virt_FinalReturn), (void*)(&cmock_call_instance->ReturnVal), + sizeof(uintptr_t[sizeof(cmock_call_instance->ReturnVal) == sizeof(uintptr_t) ? 1 : -1])); /* add uintptr_t to :treat_as_array if this causes an error */ + return cmock_call_instance->ReturnVal; + } + if (!Mock.smt_phys_to_virt_CallbackBool && + Mock.smt_phys_to_virt_CallbackFunctionPointer != NULL) + { + uintptr_t cmock_cb_ret = Mock.smt_phys_to_virt_CallbackFunctionPointer(pa, sz, shmem_is_secure, Mock.smt_phys_to_virt_CallbackCalls++); + UNITY_CLR_DETAILS(); + return cmock_cb_ret; + } + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore); + cmock_line = cmock_call_instance->LineNumber; + if (!cmock_call_instance->ExpectAnyArgsBool) + { + if (!cmock_call_instance->IgnoreArg_pa) + { + UNITY_SET_DETAILS(CMockString_smt_phys_to_virt,CMockString_pa); + UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(&cmock_call_instance->Expected_pa), (void*)(&pa), sizeof(uintptr_t), cmock_line, CMockStringMismatch); + } + if (!cmock_call_instance->IgnoreArg_sz) + { + UNITY_SET_DETAILS(CMockString_smt_phys_to_virt,CMockString_sz); + UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(&cmock_call_instance->Expected_sz), (void*)(&sz), sizeof(size_t), cmock_line, CMockStringMismatch); + } + if (!cmock_call_instance->IgnoreArg_shmem_is_secure) + { + UNITY_SET_DETAILS(CMockString_smt_phys_to_virt,CMockString_shmem_is_secure); + UNITY_TEST_ASSERT_EQUAL_INT(cmock_call_instance->Expected_shmem_is_secure, shmem_is_secure, cmock_line, CMockStringMismatch); + } + } + if (Mock.smt_phys_to_virt_CallbackFunctionPointer != NULL) + { + cmock_call_instance->ReturnVal = Mock.smt_phys_to_virt_CallbackFunctionPointer(pa, sz, shmem_is_secure, Mock.smt_phys_to_virt_CallbackCalls++); + } + UNITY_CLR_DETAILS(); + return cmock_call_instance->ReturnVal; +} + +void CMockExpectParameters_smt_phys_to_virt(CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance, uintptr_t pa, size_t sz, bool shmem_is_secure); +void CMockExpectParameters_smt_phys_to_virt(CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance, uintptr_t pa, size_t sz, bool shmem_is_secure) +{ + memcpy((void*)(&cmock_call_instance->Expected_pa), (void*)(&pa), + sizeof(uintptr_t[sizeof(pa) == sizeof(uintptr_t) ? 1 : -1])); /* add uintptr_t to :treat_as_array if this causes an error */ + cmock_call_instance->IgnoreArg_pa = 0; + memcpy((void*)(&cmock_call_instance->Expected_sz), (void*)(&sz), + sizeof(size_t[sizeof(sz) == sizeof(size_t) ? 1 : -1])); /* add size_t to :treat_as_array if this causes an error */ + cmock_call_instance->IgnoreArg_sz = 0; + cmock_call_instance->Expected_shmem_is_secure = shmem_is_secure; + cmock_call_instance->IgnoreArg_shmem_is_secure = 0; +} + +void smt_phys_to_virt_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, uintptr_t cmock_to_return) +{ + CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_smt_phys_to_virt_CALL_INSTANCE)); + CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance = (CMOCK_smt_phys_to_virt_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory); + memset(cmock_call_instance, 0, sizeof(*cmock_call_instance)); + Mock.smt_phys_to_virt_CallInstance = CMock_Guts_MemChain(Mock.smt_phys_to_virt_CallInstance, cmock_guts_index); + Mock.smt_phys_to_virt_IgnoreBool = (char)0; + cmock_call_instance->LineNumber = cmock_line; + cmock_call_instance->ExpectAnyArgsBool = (char)0; + cmock_call_instance->ReturnVal = cmock_to_return; + Mock.smt_phys_to_virt_IgnoreBool = (char)1; +} + +void smt_phys_to_virt_CMockStopIgnore(void) +{ + if(Mock.smt_phys_to_virt_IgnoreBool) + Mock.smt_phys_to_virt_CallInstance = CMock_Guts_MemNext(Mock.smt_phys_to_virt_CallInstance); + Mock.smt_phys_to_virt_IgnoreBool = (char)0; +} + +void smt_phys_to_virt_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, uintptr_t cmock_to_return) +{ + CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_smt_phys_to_virt_CALL_INSTANCE)); + CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance = (CMOCK_smt_phys_to_virt_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory); + memset(cmock_call_instance, 0, sizeof(*cmock_call_instance)); + Mock.smt_phys_to_virt_CallInstance = CMock_Guts_MemChain(Mock.smt_phys_to_virt_CallInstance, cmock_guts_index); + Mock.smt_phys_to_virt_IgnoreBool = (char)0; + cmock_call_instance->LineNumber = cmock_line; + cmock_call_instance->ExpectAnyArgsBool = (char)0; + cmock_call_instance->ReturnVal = cmock_to_return; + cmock_call_instance->ExpectAnyArgsBool = (char)1; +} + +void smt_phys_to_virt_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, uintptr_t pa, size_t sz, bool shmem_is_secure, uintptr_t cmock_to_return) +{ + CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_smt_phys_to_virt_CALL_INSTANCE)); + CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance = (CMOCK_smt_phys_to_virt_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory); + memset(cmock_call_instance, 0, sizeof(*cmock_call_instance)); + Mock.smt_phys_to_virt_CallInstance = CMock_Guts_MemChain(Mock.smt_phys_to_virt_CallInstance, cmock_guts_index); + Mock.smt_phys_to_virt_IgnoreBool = (char)0; + cmock_call_instance->LineNumber = cmock_line; + cmock_call_instance->ExpectAnyArgsBool = (char)0; + CMockExpectParameters_smt_phys_to_virt(cmock_call_instance, pa, sz, shmem_is_secure); + memcpy((void*)(&cmock_call_instance->ReturnVal), (void*)(&cmock_to_return), + sizeof(uintptr_t[sizeof(cmock_to_return) == sizeof(uintptr_t) ? 1 : -1])); /* add uintptr_t to :treat_as_array if this causes an error */ +} + +void smt_phys_to_virt_AddCallback(CMOCK_smt_phys_to_virt_CALLBACK Callback) +{ + Mock.smt_phys_to_virt_IgnoreBool = (char)0; + Mock.smt_phys_to_virt_CallbackBool = (char)1; + Mock.smt_phys_to_virt_CallbackFunctionPointer = Callback; +} + +void smt_phys_to_virt_Stub(CMOCK_smt_phys_to_virt_CALLBACK Callback) +{ + Mock.smt_phys_to_virt_IgnoreBool = (char)0; + Mock.smt_phys_to_virt_CallbackBool = (char)0; + Mock.smt_phys_to_virt_CallbackFunctionPointer = Callback; +} + +void smt_phys_to_virt_CMockIgnoreArg_pa(UNITY_LINE_TYPE cmock_line) +{ + CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance = (CMOCK_smt_phys_to_virt_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.smt_phys_to_virt_CallInstance)); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp); + cmock_call_instance->IgnoreArg_pa = 1; +} + +void smt_phys_to_virt_CMockIgnoreArg_sz(UNITY_LINE_TYPE cmock_line) +{ + CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance = (CMOCK_smt_phys_to_virt_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.smt_phys_to_virt_CallInstance)); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp); + cmock_call_instance->IgnoreArg_sz = 1; +} + +void smt_phys_to_virt_CMockIgnoreArg_shmem_is_secure(UNITY_LINE_TYPE cmock_line) +{ + CMOCK_smt_phys_to_virt_CALL_INSTANCE* cmock_call_instance = (CMOCK_smt_phys_to_virt_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.smt_phys_to_virt_CallInstance)); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp); + cmock_call_instance->IgnoreArg_shmem_is_secure = 1; +} + diff --git a/module/optee/smt/test/mocks/Mockmod_optee_smt_extra.h b/module/optee/smt/test/mocks/Mockmod_optee_smt_extra.h new file mode 100644 index 000000000..ea429341a --- /dev/null +++ b/module/optee/smt/test/mocks/Mockmod_optee_smt_extra.h @@ -0,0 +1,52 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#ifndef _MOCKMOD_OPTEE_SMT_EXTRA_H +#define _MOCKMOD_OPTEE_SMT_EXTRA_H + +#include "unity.h" +#include "mod_optee_smt_extra.h" + +/* Ignore the following warnings, since we are copying code */ +#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0))) +#pragma GCC diagnostic push +#endif +#if !defined(__clang__) +#pragma GCC diagnostic ignored "-Wpragmas" +#endif +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC diagnostic ignored "-Wduplicate-decl-specifier" +#endif + +void Mockmod_optee_smt_extra_Init(void); +void Mockmod_optee_smt_extra_Destroy(void); +void Mockmod_optee_smt_extra_Verify(void); + + + + +#define smt_phys_to_virt_IgnoreAndReturn(cmock_retval) smt_phys_to_virt_CMockIgnoreAndReturn(__LINE__, cmock_retval) +void smt_phys_to_virt_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, uintptr_t cmock_to_return); +#define smt_phys_to_virt_StopIgnore() smt_phys_to_virt_CMockStopIgnore() +void smt_phys_to_virt_CMockStopIgnore(void); +#define smt_phys_to_virt_ExpectAnyArgsAndReturn(cmock_retval) smt_phys_to_virt_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval) +void smt_phys_to_virt_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, uintptr_t cmock_to_return); +#define smt_phys_to_virt_ExpectAndReturn(pa, sz, shmem_is_secure, cmock_retval) smt_phys_to_virt_CMockExpectAndReturn(__LINE__, pa, sz, shmem_is_secure, cmock_retval) +void smt_phys_to_virt_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, uintptr_t pa, size_t sz, bool shmem_is_secure, uintptr_t cmock_to_return); +typedef uintptr_t (* CMOCK_smt_phys_to_virt_CALLBACK)(uintptr_t pa, size_t sz, bool shmem_is_secure, int cmock_num_calls); +void smt_phys_to_virt_AddCallback(CMOCK_smt_phys_to_virt_CALLBACK Callback); +void smt_phys_to_virt_Stub(CMOCK_smt_phys_to_virt_CALLBACK Callback); +#define smt_phys_to_virt_StubWithCallback smt_phys_to_virt_Stub +#define smt_phys_to_virt_IgnoreArg_pa() smt_phys_to_virt_CMockIgnoreArg_pa(__LINE__) +void smt_phys_to_virt_CMockIgnoreArg_pa(UNITY_LINE_TYPE cmock_line); +#define smt_phys_to_virt_IgnoreArg_sz() smt_phys_to_virt_CMockIgnoreArg_sz(__LINE__) +void smt_phys_to_virt_CMockIgnoreArg_sz(UNITY_LINE_TYPE cmock_line); +#define smt_phys_to_virt_IgnoreArg_shmem_is_secure() smt_phys_to_virt_CMockIgnoreArg_shmem_is_secure(__LINE__) +void smt_phys_to_virt_CMockIgnoreArg_shmem_is_secure(UNITY_LINE_TYPE cmock_line); + +#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0))) +#pragma GCC diagnostic pop +#endif +#endif + +#endif diff --git a/module/optee/smt/test/mod_optee_smt_extra.h b/module/optee/smt/test/mod_optee_smt_extra.h new file mode 100644 index 000000000..9ee1b9010 --- /dev/null +++ b/module/optee/smt/test/mod_optee_smt_extra.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Unity test framework needs the mocked version of the functions which are + * called by the function under test, e.g. in this case + * mutex_init and mutex_unlock. + * Normally mocked version of the function can be generated using + * CMock tool(see unit_test/user_guide.md) + * by providing the header that includes declarations. However, in a few cases + * it would need other header files as well complicating the Mocks generation. + * This file demonstrates, how to achieve requires mocks generation without + * much dependency. + */ + +#include + +uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure); diff --git a/module/optee/smt/test/mod_optee_smt_unit_test.c b/module/optee/smt/test/mod_optee_smt_unit_test.c new file mode 100644 index 000000000..6f0584d36 --- /dev/null +++ b/module/optee/smt/test/mod_optee_smt_unit_test.c @@ -0,0 +1,889 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * mod_optee_smt_unit_test.c is comming from the template file + * This is the minimum file setup you need to get started with Unit Testing + */ + +#include "scp_unity.h" +#include "unity.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include UNIT_TEST_SRC +#include "config_optee_smt.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +struct smt_channel_ctx fake_optee_smt_ctx[FAKE_SCMI_SERVICE_IDX_COUNT]; + +char mailbox_virt_buffer[FAKE_MAILBOX_SIZE]; +char channel_in_buffer[FAKE_MAILBOX_SIZE]; +char channel_out_buffer[FAKE_MAILBOX_SIZE]; + +int fake_signal_message_status = FWK_SUCCESS; + +/*! + * \brief test module's init function. + * + * \details Test all possible cases for init. + */ +void test_optee_smt_init(void) +{ + int status; + fwk_id_t module_id; + + module_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_SMT); + + /* Element count can't be null */ + status = mailbox_init(module_id, 0, NULL); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Fail to allocate module cxt */ + fwk_mm_calloc_ExpectAndReturn( + FAKE_SCMI_SERVICE_IDX_COUNT, + sizeof(struct smt_channel_ctx), + NULL); + status = mailbox_init(module_id, FAKE_SCMI_SERVICE_IDX_COUNT, NULL); + TEST_ASSERT_EQUAL(FWK_E_NOMEM, status); + + /* Allocate module context */ + fwk_mm_calloc_ExpectAndReturn( + 1, + sizeof(struct smt_channel_ctx), + fake_optee_smt_ctx); + status = mailbox_init(module_id, FAKE_SCMI_SERVICE_IDX_COUNT, NULL); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test module's element_init function. + * + * \details Test all possible cases for element_init. + */ +void test_mailbox_channel_init(void) +{ + int status; + fwk_id_t channel_id; + unsigned int slot_count; + struct mod_optee_smt_channel_config *channel_config; + enum mod_optee_smt_channel_type saved_type; + uintptr_t saved_address; + size_t saved_size; + + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + slot_count = 0; + channel_config = + (struct mod_optee_smt_channel_config*)smt_element_table[FAKE_SCMI_SERVICE_IDX_OSPM_0] + .data; + + /* Save current type */ + saved_type = channel_config->type; + + /* Set invalid type */ + channel_config->type = MOD_OPTEE_SMT_CHANNEL_TYPE_COUNT; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = mailbox_channel_init(channel_id, slot_count, channel_config); + TEST_ASSERT_EQUAL(FWK_E_DATA, status); + + /* Restore valid type */ + channel_config->type = saved_type; + + /* Save current address */ + saved_address = channel_config->mailbox_address; + + /* Set invalid mailbox address */ + channel_config->mailbox_address = 0; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = mailbox_channel_init(channel_id, slot_count, channel_config); + TEST_ASSERT_EQUAL(FWK_E_DATA, status); + + /* Restore valid address */ + channel_config->mailbox_address = saved_address; + + /* Save current size */ + saved_size = channel_config->mailbox_size; + + /* Set invalid mailbox size */ + channel_config->mailbox_size = 0; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = mailbox_channel_init(channel_id, slot_count, channel_config); + TEST_ASSERT_EQUAL(FWK_E_DATA, status); + + /* Restore valid size */ + channel_config->mailbox_size = saved_size; + + /* Fail to get virt address */ + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + smt_phys_to_virt_ExpectAndReturn(channel_config->mailbox_address, + channel_config->mailbox_size, + channel_config->policies & MOD_SMT_POLICY_SECURE, + (uintptr_t)NULL); + status = mailbox_channel_init(channel_id, slot_count, channel_config); + TEST_ASSERT_EQUAL(FWK_E_DATA, status); + + /* Successfully init channel */ + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + smt_phys_to_virt_ExpectAndReturn(channel_config->mailbox_address, + channel_config->mailbox_size, + channel_config->policies & MOD_SMT_POLICY_SECURE, + (uintptr_t)mailbox_virt_buffer); + fwk_mm_alloc_ExpectAndReturn(1, channel_config->mailbox_size, channel_in_buffer); + fwk_mm_alloc_ExpectAndReturn(1, channel_config->mailbox_size, channel_out_buffer); + status = mailbox_channel_init(channel_id, slot_count, channel_config); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test module's bind fucntion for round 0. + * + * \details Test bind for round 0 and others except for round 1 when it needs + * additional information from bind_request of other modules. + */ +void test_mailbox_smt_bind_round0(void) +{ + int status; + unsigned int i; + fwk_id_t bind_id; + struct smt_channel_ctx *channel_ctx; + + /* + * Bind module always succeed because there is nothing to do ... + * Take the opportunity to test all possible rounds in one shot because + * it's a nop, + */ + bind_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_SMT); + for (i = 0; i <= FWK_MODULE_BIND_ROUND_MAX; i++) { + fwk_id_is_type_ExpectAndReturn(bind_id, FWK_ID_TYPE_MODULE, true); + status = mailbox_smt_bind(bind_id, i); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + } + + /* Fail to bind an element round 0 */ + bind_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(bind_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(bind_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + fwk_module_bind_ExpectAndReturn( + channel_ctx->config->driver_id, + channel_ctx->config->driver_api_id, + &channel_ctx->driver_api, + FWK_E_PARAM); + status = mailbox_smt_bind(bind_id, 0); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Succeed to bind an element round 0 */ + bind_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(bind_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(bind_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + fwk_module_bind_ExpectAndReturn( + channel_ctx->config->driver_id, + channel_ctx->config->driver_api_id, + &channel_ctx->driver_api, + FWK_SUCCESS); + status = mailbox_smt_bind(bind_id, 0); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test module's bind_request function. + * + * \details Test all possible cases for bind_request function + */ +void test_mailbox_smt_process_bind_request(void) +{ + int status; + fwk_id_t source_id; + fwk_id_t target_id; + fwk_id_t api_id; + void *test_driver_input_api; + struct smt_channel_ctx *channel_ctx; + + source_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SCMI, FAKE_SCMI_SERVICE_IDX_OSPM_0); + api_id = ((fwk_id_t) FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_SMT, MOD_OPTEE_SMT_API_IDX_COUNT)); + + /* Bind to something else than an element always fails */ + target_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_SMT); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, false); + status = mailbox_smt_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Bind to an out of range element */ + target_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_COUNT); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_SERVICE_IDX_COUNT); + status = mailbox_smt_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_ACCESS, status); + + /* Bind to an out of range interface */ + target_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_api_idx_ExpectAndReturn(api_id, MOD_OPTEE_SMT_API_IDX_COUNT); + status = mailbox_smt_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Bind to scmi interface */ + api_id = ((fwk_id_t) FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_SMT, MOD_OPTEE_SMT_API_IDX_SCMI_TRANSPORT)); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_api_idx_ExpectAndReturn(api_id, MOD_OPTEE_SMT_API_IDX_SCMI_TRANSPORT); + status = mailbox_smt_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(&smt_mod_scmi_to_transport_api, test_driver_input_api); + + /* Bind with wrong source id (has been set during bind round0) */ + api_id = ((fwk_id_t) FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_SMT, MOD_OPTEE_SMT_API_IDX_DRIVER_INPUT)); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_api_idx_ExpectAndReturn(api_id, MOD_OPTEE_SMT_API_IDX_DRIVER_INPUT); + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + fwk_id_get_module_idx_ExpectAndReturn(channel_ctx->driver_id, FWK_MODULE_IDX_OPTEE_MBX); + fwk_id_get_module_idx_ExpectAndReturn(source_id, FWK_MODULE_IDX_SCMI); + status = mailbox_smt_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_ACCESS, status); + + /* Bind to input driver interface */ + source_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_SERVICE_IDX_OSPM_0); + api_id = ((fwk_id_t) FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_SMT, MOD_OPTEE_SMT_API_IDX_DRIVER_INPUT)); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_api_idx_ExpectAndReturn(api_id, MOD_OPTEE_SMT_API_IDX_DRIVER_INPUT); + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + fwk_id_get_module_idx_ExpectAndReturn(channel_ctx->driver_id, FWK_MODULE_IDX_OPTEE_MBX); + fwk_id_get_module_idx_ExpectAndReturn(source_id, FWK_MODULE_IDX_OPTEE_MBX); + fwk_id_get_element_idx_ExpectAndReturn(channel_ctx->driver_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(source_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = mailbox_smt_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(&driver_input_api, test_driver_input_api); +} + +/*! + * \brief test module's bind function for element during round 1. + * + * \details Test bind of elements for round 1. + */ +void test_mailbox_smt_bind_round1(void) +{ + int status; + fwk_id_t element_id; + struct smt_channel_ctx *channel_ctx; + + /* Fail to bind an element round 1 */ + element_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(element_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + fwk_module_bind_ExpectAndReturn( + channel_ctx->scmi_service_id, + FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_TRANSPORT), + &channel_ctx->scmi_api, + FWK_E_PARAM); + status = mailbox_smt_bind(element_id, 1); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Succeed to bind an element at round 1 */ + element_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(element_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + fwk_module_bind_ExpectAndReturn( + channel_ctx->scmi_service_id, + FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_TRANSPORT), + &channel_ctx->scmi_api, + FWK_SUCCESS); + status = mailbox_smt_bind(element_id, 1); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test module's start function. + * + * \details Test all cases for start function. + */ +void test_mailbox_start(void) +{ + int status; + fwk_id_t module_id; + + /* Start always succeed */ + module_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_SMT); + status = mailbox_start(module_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test get_secure function. + * + * \details Test all cases for get_secure function. + */ +void test_smt_get_secure(void) +{ + int status; + fwk_id_t channel_id; + uint32_t saved_policies; + bool secure; + + struct mod_optee_smt_channel_config *device_config; + + /* Fail if the pointer is null */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_secure(channel_id, NULL); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + device_config = + (struct mod_optee_smt_channel_config *)smt_element_table[FAKE_SCMI_SERVICE_IDX_OSPM_0] + .data; + + /* Save policies */ + saved_policies = device_config->policies; + + /* Return secure state of the channel */ + device_config->policies = MOD_SMT_POLICY_SECURE; + secure = 0xAA; + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_secure(channel_id, &secure); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(true, secure); + + /* Restore policies */ + device_config->policies = saved_policies; + + /* Return non secure state of the channel */ + secure = 0xAA; + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_secure(channel_id, &secure); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(false, secure); +} + +/*! + * \brief test get_max_payload_size function. + * + * \details Test all cases for get_max_payload_size function. + */ +void test_smt_get_max_payload_size(void) +{ + int status; + fwk_id_t channel_id; + size_t payload_size; + struct smt_channel_ctx *channel_ctx; + + /* Init channel context */ + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + + /* Fail if the pointer is null */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_max_payload_size(channel_id, NULL); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Return payload size */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + payload_size = 0xAAAA; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_max_payload_size(channel_id, &payload_size); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(channel_ctx->max_payload_size, payload_size); +} + +/*! + * \brief test early access to get_message_header function. + * + * \details Test all cases for get_message_header function before + * a message has been received. + */ +void test_smt_get_message_header_early(void) +{ + int status; + fwk_id_t channel_id; + uint32_t header; + + /* Fail if the pointer is null */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_message_header(channel_id, NULL); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* No message available */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + header = 0x0000; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_message_header(channel_id, &header); + TEST_ASSERT_EQUAL(FWK_E_ACCESS, status); +} + +/*! + * \brief test get_message_header function. + * + * \details Test all other cases for get_message_header function. + */ +void test_smt_get_message_header(void) +{ + int status; + fwk_id_t channel_id; + uint32_t header; + + /* Return header */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + header = 0x0000; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_message_header(channel_id, &header); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(((struct mod_optee_smt_memory *)(mailbox_virt_buffer))->message_header, header); +} + +/*! + * \brief test early access to get_payload function. + * + * \details Test all cases for get_payload function before + * a message has been received. + */ +void test_smt_get_payload_early(void) +{ + int status; + fwk_id_t channel_id; + void *fake_payload; + + /* Fail if the pointer is null */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_payload(channel_id, NULL, NULL); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* No message available */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_payload(channel_id, (const void **)&fake_payload, NULL); + TEST_ASSERT_EQUAL(FWK_E_ACCESS, status); +} + +/*! + * \brief test get_payload function. + * + * \details Test all remaining cases for get_payload function. + */ +void test_smt_get_payload(void) +{ + int status; + fwk_id_t channel_id; + void *fake_payload; + size_t fake_size; + + /* Return payload pointer */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_payload(channel_id, (const void **)&fake_payload, NULL); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(((struct mod_optee_smt_memory *)(channel_in_buffer))->payload, fake_payload); + + /* Return payload pointer and size */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fake_size = 0x0000; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_get_payload(channel_id, (const void **)&fake_payload, &fake_size); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(((struct mod_optee_smt_memory *)(channel_in_buffer))->payload, fake_payload); + TEST_ASSERT_EQUAL(((struct mod_optee_smt_memory *)(channel_in_buffer))->length - sizeof(uint32_t), fake_size); + +} + +void fake_fwk_str_memcpy(void *dest, const void *src, size_t count, int iteration) +{ +} + +/*! + * \brief test early access to write_payload function. + * + * \details Test all remaining cases for write_payload function before + * a message has been received. + */ +void test_smt_write_payload_early(void) +{ + int status; + fwk_id_t channel_id; + char fake_payload[FAKE_MAILBOX_SIZE]; + struct smt_channel_ctx *channel_ctx; + + /* Init channel context */ + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + + /* Fail if the pointer is null */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_write_payload(channel_id, 0, NULL, 0); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Fail if the offset is out of range */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_write_payload(channel_id, channel_ctx->max_payload_size+1, fake_payload, 0); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Fail if the size is out of range */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_write_payload(channel_id, 0, (const void*)fake_payload, channel_ctx->max_payload_size+1); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Fail if the offset+size is out of range */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_write_payload(channel_id, channel_ctx->max_payload_size, (const void*)fake_payload, channel_ctx->max_payload_size); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* No message available */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_write_payload(channel_id, 0, (const void*)fake_payload, channel_ctx->max_payload_size); + TEST_ASSERT_EQUAL(FWK_E_ACCESS, status); +} + +/*! + * \brief test write_payload function. + * + * \details Test all remaining cases for write_payload function. + */ +void test_smt_write_payload(void) +{ + int status; + fwk_id_t channel_id; + char fake_payload[FAKE_MAILBOX_SIZE]; + struct smt_channel_ctx *channel_ctx; + + /* Init channel context */ + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + + /* write payload */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_str_memcpy_StubWithCallback(fake_fwk_str_memcpy); + status = smt_write_payload(channel_id, 0, (const void*)fake_payload, channel_ctx->max_payload_size); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test early access to signal_message. + * + * \details Test all cases for signaling a message to a static memory. + */ +void test_smt_signal_message_early(void) +{ + int status; + fwk_id_t channel_id; + + /* Mailbox not ready, discard message silently ... */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +static int fake_signal_message(fwk_id_t service_id) +{ + return fake_signal_message_status; +} + +struct mod_scmi_from_transport_api fake_scmi_api = { + .signal_error = NULL, /* Not used */ + .signal_message = fake_signal_message, +}; + +static int fake_raise_smt_interrupt(fwk_id_t channel_id) +{ + return FWK_SUCCESS; +} + +struct mod_optee_smt_driver_api fake_mbx_smt_api = { + .raise_interrupt = fake_raise_smt_interrupt, +}; + +void test_reset_virt_buffer(void) +{ + int i; + + for (i = 0; i < FAKE_MAILBOX_SIZE; i++) { + mailbox_virt_buffer[i] = 0xAA; + } +} + +void test_reset_in_buffer(void) +{ + int i; + + for (i = 0; i < FAKE_MAILBOX_SIZE; i++) { + channel_in_buffer[i] = 0; + } +} + +void test_reset_out_buffer(void) +{ + int i; + + for (i = 0; i < FAKE_MAILBOX_SIZE; i++) { + channel_out_buffer[i] = 0; + } +} + +/*! + * \brief test all cases of signal_message. + * + * \details Test all cases for signaling a message. + */ +void test_smt_signal_message(void) +{ + int status; + fwk_id_t channel_id; + struct smt_channel_ctx *channel_ctx; + + enum mod_optee_smt_channel_type saved_type; + struct mod_optee_smt_channel_config *device_config; + struct mod_optee_smt_memory *fake_memory; + + /* Init channel context and buffers */ + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + channel_ctx->scmi_api = &fake_scmi_api; + channel_ctx->driver_api = &fake_mbx_smt_api; + test_reset_virt_buffer(); + test_reset_in_buffer(); + test_reset_out_buffer(); + + device_config = + (struct mod_optee_smt_channel_config *)smt_element_table[FAKE_SCMI_SERVICE_IDX_OSPM_0] + .data; + + /* Save current type */ + saved_type = device_config->type; + + /* Set invalid channel type and silently return */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + device_config->type = MOD_OPTEE_SMT_CHANNEL_TYPE_COUNT; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + /* Set completer channel type */ + device_config->type = MOD_OPTEE_SMT_CHANNEL_TYPE_COMPLETER; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + /* Try to send a new message while one is pending */ + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_E_STATE, status); + + /* Restore valid channel type */ + device_config->type = saved_type; + /* Clear lock */ + channel_ctx->locked = false; + + /* Check message header correctness: length too small */ + test_reset_virt_buffer(); + test_reset_in_buffer(); + test_reset_out_buffer(); + channel_ctx->scmi_api = &fake_scmi_api; + fake_memory = (struct mod_optee_smt_memory *)mailbox_virt_buffer; + fake_memory->length = 0; + + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + /* smt_respond part */ + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_str_memcpy_StubWithCallback(fake_fwk_str_memcpy); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + /* Check message header correctness: length too large */ + test_reset_virt_buffer(); + test_reset_in_buffer(); + test_reset_out_buffer(); + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fake_memory->length = FAKE_MAILBOX_SIZE; + + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + /* smt_respond part */ + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_str_memcpy_StubWithCallback(fake_fwk_str_memcpy); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + /* Message is correct, signal upper layer which returns error */ + test_reset_virt_buffer(); + test_reset_in_buffer(); + test_reset_out_buffer(); + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fake_memory->length = FAKE_MAILBOX_SIZE - sizeof(struct mod_optee_smt_memory); + fake_signal_message_status = FWK_E_HANDLER; + + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_E_HANDLER, status); + + /* Clear lock */ + channel_ctx->locked = false; + + /* Message is correct, signal upper layer */ + test_reset_virt_buffer(); + test_reset_in_buffer(); + test_reset_out_buffer(); + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fake_memory->length = FAKE_MAILBOX_SIZE - sizeof(struct mod_optee_smt_memory); + fake_signal_message_status = FWK_SUCCESS; + + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test all cases of respond. + * + * \details Test all cases for responding to a message. + */ +void test_smt_respond(void) +{ + int status; + fwk_id_t channel_id; + struct smt_channel_ctx *channel_ctx; + size_t fake_size; + + /* Init channel context and buffers */ + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + channel_ctx->driver_api = &fake_mbx_smt_api; + test_reset_virt_buffer(); + test_reset_in_buffer(); + test_reset_out_buffer(); + + /* Successfully foward NULL payload */ + fake_size = 0; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_str_memcpy_Expect(((struct mod_optee_smt_memory *)(channel_ctx->mailbox_va))->payload, channel_ctx->out->payload, fake_size); + status = smt_respond(channel_id, NULL, fake_size); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +static int fake_raise_shm_interrupt(fwk_id_t channel_id) +{ + return FWK_SUCCESS; +} + +struct mod_optee_smt_driver_api fake_mbx_shm_api = { + .raise_interrupt = fake_raise_shm_interrupt, +}; + +/*! + * \brief test all cases of signal_message. + * + * \details Test all cases for signaling a message. + */ +void test_smt_transmit(void) +{ + int i, status; + char fake_payload[FAKE_MAILBOX_SIZE]; + size_t fake_size; + struct smt_channel_ctx *channel_ctx; + fwk_id_t channel_id; + + /* Init channel context */ + channel_ctx = &smt_ctx.channel_ctx_table[FAKE_SCMI_SERVICE_IDX_OSPM_0]; + channel_ctx->driver_api = &fake_mbx_shm_api; + + /* Null Payload */ + channel_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fake_size = channel_ctx->max_payload_size; + status = smt_transmit(channel_id, 0xAA, NULL, fake_size, true); + TEST_ASSERT_EQUAL(FWK_E_DATA, status); + + /* Init payload buffer */ + for (i = 0; i < FAKE_MAILBOX_SIZE; i++) { + fake_payload[i] = i; + } + + /* No message available, return silently */ + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_transmit(channel_id, 0xAA, fake_payload, fake_size, true); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + /* Signal a new message to scmi */ + fake_signal_message_status = FWK_SUCCESS; + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_signal_message(channel_id); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + /* Transmit async message */ + test_reset_virt_buffer(); + test_reset_in_buffer(); + test_reset_out_buffer(); + fwk_id_get_element_idx_ExpectAndReturn(channel_id, FAKE_SCMI_SERVICE_IDX_OSPM_0); + status = smt_transmit(channel_id, 0xAA, fake_payload, fake_size, true); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); +} + +int optee_smt_test_main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_optee_smt_init); + + RUN_TEST(test_smt_signal_message_early); + + RUN_TEST(test_mailbox_channel_init); + + RUN_TEST(test_mailbox_smt_bind_round0); + + RUN_TEST(test_mailbox_smt_process_bind_request); + + RUN_TEST(test_mailbox_smt_bind_round1); + + RUN_TEST(test_mailbox_start); + + RUN_TEST(test_smt_get_secure); + + RUN_TEST(test_smt_get_max_payload_size); + + RUN_TEST(test_smt_get_message_header_early); + + RUN_TEST(test_smt_get_payload_early); + + RUN_TEST(test_smt_write_payload_early); + + RUN_TEST(test_smt_signal_message); + + RUN_TEST(test_smt_get_message_header); + + RUN_TEST(test_smt_get_payload); + + RUN_TEST(test_smt_write_payload); + + RUN_TEST(test_smt_respond); + + RUN_TEST(test_smt_transmit); + + return UNITY_END(); +} + +#if !defined(TEST_ON_TARGET) +int main(void) +{ + return optee_smt_test_main(); +} +#endif diff --git a/unit_test/CMakeLists.txt b/unit_test/CMakeLists.txt index 3f4f7682e..dc520aedd 100644 --- a/unit_test/CMakeLists.txt +++ b/unit_test/CMakeLists.txt @@ -109,6 +109,7 @@ list(APPEND SCP_UNITY_SRC ${TEST_ROOT}/unity_mocks/scp_unity.c) list(APPEND UNIT_MODULE dvfs) list(APPEND UNIT_MODULE mhu3) list(APPEND UNIT_MODULE optee/mbx) +list(APPEND UNIT_MODULE optee/smt) list(APPEND UNIT_MODULE pl011) list(APPEND UNIT_MODULE scmi) list(APPEND UNIT_MODULE scmi_clock) -- GitLab