uboot/test/dm/tee.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2018 Linaro Limited
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <log.h>
   9#include <malloc.h>
  10#include <dm/test.h>
  11#include <sandboxtee.h>
  12#include <tee.h>
  13#include <test/test.h>
  14#include <test/ut.h>
  15#include <tee/optee_ta_avb.h>
  16#include <tee/optee_ta_rpc_test.h>
  17
  18static int open_session(struct udevice *dev, u32 *session,
  19                        struct tee_optee_ta_uuid *uuid)
  20{
  21        struct tee_open_session_arg arg;
  22        int rc;
  23
  24        memset(&arg, 0, sizeof(arg));
  25        tee_optee_ta_uuid_to_octets(arg.uuid, uuid);
  26        rc = tee_open_session(dev, &arg, 0, NULL);
  27        if (rc)
  28                return rc;
  29        if (arg.ret)
  30                return -EIO;
  31        *session = arg.session;
  32
  33        return 0;
  34}
  35
  36static int invoke_func_avb(struct udevice *dev, u32 session)
  37{
  38        struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
  39        struct tee_invoke_arg arg;
  40
  41        memset(&arg, 0, sizeof(arg));
  42        arg.session = session;
  43        arg.func = TA_AVB_CMD_READ_LOCK_STATE;
  44
  45        if (tee_invoke_func(dev, &arg, 1, &param) || arg.ret)
  46                return -1;
  47
  48        return 0;
  49}
  50
  51static int invoke_func_rpc_test(struct udevice *dev, u32 session,
  52                                u64 op, u64 busnum, u64 chip_addr,
  53                                u64 xfer_flags, u8 *buf, size_t buf_size)
  54{
  55        struct tee_param param[2];
  56        struct tee_invoke_arg arg;
  57        struct tee_shm *shm_buf;
  58        int rc;
  59
  60        memset(&arg, 0, sizeof(arg));
  61        arg.session = session;
  62        arg.func = op;
  63
  64        rc = tee_shm_alloc(dev, buf_size,
  65                           TEE_SHM_ALLOC, &shm_buf);
  66        if (rc)
  67                return rc;
  68
  69        if (op == TA_RPC_TEST_CMD_I2C_WRITE)
  70                memcpy(shm_buf->addr, buf, buf_size);
  71
  72        memset(param, 0, sizeof(param));
  73        param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
  74        param[0].u.value.a = busnum;
  75        param[0].u.value.b = chip_addr;
  76        param[0].u.value.c = xfer_flags;
  77        param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
  78        param[1].u.memref.shm = shm_buf;
  79        param[1].u.memref.size = buf_size;
  80
  81        if (tee_invoke_func(dev, &arg, 2, param) || arg.ret) {
  82                rc = -1;
  83                goto out;
  84        }
  85
  86        if (op == TA_RPC_TEST_CMD_I2C_READ)
  87                memcpy(buf, shm_buf->addr, buf_size);
  88out:
  89        tee_shm_free(shm_buf);
  90        return rc;
  91}
  92
  93static int match(struct tee_version_data *vers, const void *data)
  94{
  95        return vers->gen_caps & TEE_GEN_CAP_GP;
  96}
  97
  98struct test_tee_vars {
  99        struct tee_shm *reg_shm;
 100        struct tee_shm *alloc_shm;
 101};
 102
 103static int test_tee(struct unit_test_state *uts, struct test_tee_vars *vars)
 104{
 105        struct tee_version_data vers;
 106        struct udevice *dev;
 107        struct sandbox_tee_state *state;
 108        struct tee_optee_ta_uuid avb_uuid = TA_AVB_UUID;
 109        u32 session = 0;
 110        int rc;
 111        u8 data[128];
 112
 113        dev = tee_find_device(NULL, match, NULL, &vers);
 114        ut_assert(dev);
 115        state = dev_get_priv(dev);
 116        ut_assert(!state->session);
 117
 118        rc = open_session(dev, &session, &avb_uuid);
 119        ut_assert(!rc);
 120        ut_assert(session == state->session);
 121
 122        rc = invoke_func_avb(dev, session);
 123        ut_assert(!rc);
 124
 125        rc = tee_close_session(dev, session);
 126        ut_assert(!rc);
 127        ut_assert(!state->session);
 128
 129        ut_assert(!state->num_shms);
 130        rc = tee_shm_register(dev, data, sizeof(data), 0, &vars->reg_shm);
 131        ut_assert(!rc);
 132        ut_assert(state->num_shms == 1);
 133
 134        rc = tee_shm_alloc(dev, 256, 0, &vars->alloc_shm);
 135        ut_assert(!rc);
 136        ut_assert(state->num_shms == 2);
 137
 138        ut_assert(tee_shm_is_registered(vars->reg_shm, dev));
 139        ut_assert(tee_shm_is_registered(vars->alloc_shm, dev));
 140
 141        tee_shm_free(vars->reg_shm);
 142        vars->reg_shm = NULL;
 143        tee_shm_free(vars->alloc_shm);
 144        vars->alloc_shm = NULL;
 145        ut_assert(!state->num_shms);
 146
 147        return rc;
 148}
 149
 150#define I2C_BUF_SIZE 64
 151
 152static int test_tee_rpc(struct unit_test_state *uts)
 153{
 154        struct tee_version_data vers;
 155        struct udevice *dev;
 156        struct sandbox_tee_state *state;
 157        struct tee_optee_ta_uuid rpc_test_uuid = TA_RPC_TEST_UUID;
 158        u32 session = 0;
 159        int rc;
 160
 161        char *test_str = "Test string";
 162        u8 data[I2C_BUF_SIZE] = {0};
 163        u8 data_from_eeprom[I2C_BUF_SIZE] = {0};
 164
 165        /* Use sandbox I2C EEPROM emulation; bus: 0, chip: 0x2c */
 166        u64 bus = 0;
 167        u64 chip = 0x2c;
 168        u64 xfer_flags = 0;
 169
 170        dev = tee_find_device(NULL, match, NULL, &vers);
 171        ut_assert(dev);
 172        state = dev_get_priv(dev);
 173        ut_assert(!state->session);
 174
 175        /* Test RPC call asking for I2C service */
 176        rc = open_session(dev, &session, &rpc_test_uuid);
 177        ut_assert(!rc);
 178        ut_assert(session == state->session);
 179
 180        /* Write buffer */
 181        strncpy((char *)data, test_str, strlen(test_str));
 182        rc = invoke_func_rpc_test(dev, session, TA_RPC_TEST_CMD_I2C_WRITE,
 183                                  bus, chip, xfer_flags, data, sizeof(data));
 184        ut_assert(!rc);
 185
 186        /* Read buffer */
 187        rc = invoke_func_rpc_test(dev, session, TA_RPC_TEST_CMD_I2C_READ,
 188                                  bus, chip, xfer_flags, data_from_eeprom,
 189                                  sizeof(data_from_eeprom));
 190        ut_assert(!rc);
 191
 192        /* Compare */
 193        ut_assert(!memcmp(data, data_from_eeprom, sizeof(data)));
 194
 195        rc = tee_close_session(dev, session);
 196        ut_assert(!rc);
 197        ut_assert(!state->session);
 198
 199        return rc;
 200}
 201
 202static int dm_test_tee(struct unit_test_state *uts)
 203{
 204        struct test_tee_vars vars = { NULL, NULL };
 205        int rc = test_tee(uts, &vars);
 206
 207        if (rc)
 208                goto out;
 209
 210        if (IS_ENABLED(CONFIG_OPTEE_TA_RPC_TEST))
 211                rc = test_tee_rpc(uts);
 212out:
 213        /* In case test_tee() asserts these may still remain allocated */
 214        tee_shm_free(vars.reg_shm);
 215        tee_shm_free(vars.alloc_shm);
 216
 217        return rc;
 218}
 219
 220DM_TEST(dm_test_tee, UT_TESTF_SCAN_FDT);
 221