]>
Commit | Line | Data |
---|---|---|
a6ab4245 JW |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2018 Linaro Limited | |
4 | */ | |
5 | ||
d678a59d | 6 | #include <common.h> |
a6ab4245 | 7 | #include <dm.h> |
f7ae49fc | 8 | #include <log.h> |
336d4615 | 9 | #include <malloc.h> |
a6ab4245 JW |
10 | #include <dm/test.h> |
11 | #include <sandboxtee.h> | |
12 | #include <tee.h> | |
0e1fad43 | 13 | #include <test/test.h> |
a6ab4245 JW |
14 | #include <test/ut.h> |
15 | #include <tee/optee_ta_avb.h> | |
9d1215be | 16 | #include <tee/optee_ta_rpc_test.h> |
a6ab4245 | 17 | |
9d1215be IO |
18 | static int open_session(struct udevice *dev, u32 *session, |
19 | struct tee_optee_ta_uuid *uuid) | |
a6ab4245 JW |
20 | { |
21 | struct tee_open_session_arg arg; | |
a6ab4245 JW |
22 | int rc; |
23 | ||
24 | memset(&arg, 0, sizeof(arg)); | |
9d1215be | 25 | tee_optee_ta_uuid_to_octets(arg.uuid, uuid); |
a6ab4245 JW |
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 | ||
9d1215be | 36 | static int invoke_func_avb(struct udevice *dev, u32 session) |
a6ab4245 JW |
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, ¶m) || arg.ret) | |
46 | return -1; | |
47 | ||
48 | return 0; | |
49 | } | |
50 | ||
9d1215be IO |
51 | static 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); | |
88 | out: | |
89 | tee_shm_free(shm_buf); | |
90 | return rc; | |
91 | } | |
92 | ||
a6ab4245 JW |
93 | static int match(struct tee_version_data *vers, const void *data) |
94 | { | |
95 | return vers->gen_caps & TEE_GEN_CAP_GP; | |
96 | } | |
97 | ||
c091dc7d JW |
98 | struct test_tee_vars { |
99 | struct tee_shm *reg_shm; | |
100 | struct tee_shm *alloc_shm; | |
101 | }; | |
102 | ||
103 | static int test_tee(struct unit_test_state *uts, struct test_tee_vars *vars) | |
a6ab4245 JW |
104 | { |
105 | struct tee_version_data vers; | |
106 | struct udevice *dev; | |
107 | struct sandbox_tee_state *state; | |
9d1215be | 108 | struct tee_optee_ta_uuid avb_uuid = TA_AVB_UUID; |
a6ab4245 JW |
109 | u32 session = 0; |
110 | int rc; | |
111 | u8 data[128]; | |
a6ab4245 JW |
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 | ||
9d1215be | 118 | rc = open_session(dev, &session, &avb_uuid); |
a6ab4245 JW |
119 | ut_assert(!rc); |
120 | ut_assert(session == state->session); | |
121 | ||
9d1215be | 122 | rc = invoke_func_avb(dev, session); |
a6ab4245 JW |
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); | |
c091dc7d | 130 | rc = tee_shm_register(dev, data, sizeof(data), 0, &vars->reg_shm); |
a6ab4245 JW |
131 | ut_assert(!rc); |
132 | ut_assert(state->num_shms == 1); | |
133 | ||
c091dc7d | 134 | rc = tee_shm_alloc(dev, 256, 0, &vars->alloc_shm); |
a6ab4245 JW |
135 | ut_assert(!rc); |
136 | ut_assert(state->num_shms == 2); | |
137 | ||
c091dc7d JW |
138 | ut_assert(tee_shm_is_registered(vars->reg_shm, dev)); |
139 | ut_assert(tee_shm_is_registered(vars->alloc_shm, dev)); | |
a6ab4245 | 140 | |
c091dc7d JW |
141 | tee_shm_free(vars->reg_shm); |
142 | vars->reg_shm = NULL; | |
143 | tee_shm_free(vars->alloc_shm); | |
144 | vars->alloc_shm = NULL; | |
a6ab4245 JW |
145 | ut_assert(!state->num_shms); |
146 | ||
9d1215be IO |
147 | return rc; |
148 | } | |
149 | ||
150 | #define I2C_BUF_SIZE 64 | |
151 | ||
152 | static 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; | |
a6ab4245 JW |
200 | } |
201 | ||
c091dc7d JW |
202 | static 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 | ||
9d1215be IO |
207 | if (rc) |
208 | goto out; | |
209 | ||
210 | if (IS_ENABLED(CONFIG_OPTEE_TA_RPC_TEST)) | |
211 | rc = test_tee_rpc(uts); | |
212 | out: | |
c091dc7d JW |
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 | ||
e180c2b1 | 220 | DM_TEST(dm_test_tee, UT_TESTF_SCAN_FDT); |