]>
Commit | Line | Data |
---|---|---|
bcc6c574 RG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright 2020 NXP | |
4 | */ | |
5 | ||
6 | #include <command.h> | |
d678a59d | 7 | #include <common.h> |
bcc6c574 RG |
8 | #include <env.h> |
9 | #include <errno.h> | |
10 | #include <image.h> | |
11 | #include <malloc.h> | |
12 | #include <mmc.h> | |
13 | #include <tee.h> | |
14 | #include <tee/optee_ta_avb.h> | |
15 | ||
16 | static struct udevice *tee; | |
17 | static u32 session; | |
18 | ||
19 | static int avb_ta_open_session(void) | |
20 | { | |
21 | const struct tee_optee_ta_uuid uuid = TA_AVB_UUID; | |
22 | struct tee_open_session_arg arg; | |
23 | int rc; | |
24 | ||
25 | tee = tee_find_device(tee, NULL, NULL, NULL); | |
26 | if (!tee) | |
27 | return -ENODEV; | |
28 | ||
29 | memset(&arg, 0, sizeof(arg)); | |
30 | tee_optee_ta_uuid_to_octets(arg.uuid, &uuid); | |
31 | rc = tee_open_session(tee, &arg, 0, NULL); | |
32 | if (!rc) | |
33 | session = arg.session; | |
34 | ||
35 | return 0; | |
36 | } | |
37 | ||
38 | static int invoke_func(u32 func, ulong num_param, struct tee_param *param) | |
39 | { | |
40 | struct tee_invoke_arg arg; | |
41 | ||
42 | if (!tee) | |
43 | if (avb_ta_open_session()) | |
44 | return -ENODEV; | |
45 | ||
46 | memset(&arg, 0, sizeof(arg)); | |
47 | arg.func = func; | |
48 | arg.session = session; | |
49 | ||
50 | if (tee_invoke_func(tee, &arg, num_param, param)) | |
51 | return -EFAULT; | |
52 | switch (arg.ret) { | |
53 | case TEE_SUCCESS: | |
54 | return 0; | |
55 | case TEE_ERROR_OUT_OF_MEMORY: | |
56 | case TEE_ERROR_STORAGE_NO_SPACE: | |
57 | return -ENOSPC; | |
58 | case TEE_ERROR_ITEM_NOT_FOUND: | |
59 | return -EIO; | |
60 | case TEE_ERROR_TARGET_DEAD: | |
61 | /* | |
62 | * The TA has paniced, close the session to reload the TA | |
63 | * for the next request. | |
64 | */ | |
65 | tee_close_session(tee, session); | |
66 | tee = NULL; | |
67 | return -EIO; | |
68 | default: | |
69 | return -EIO; | |
70 | } | |
71 | } | |
72 | ||
73 | static int read_persistent_value(const char *name, | |
74 | size_t buffer_size, | |
75 | u8 *out_buffer, | |
76 | size_t *out_num_bytes_read) | |
77 | { | |
78 | int rc = 0; | |
79 | struct tee_shm *shm_name; | |
80 | struct tee_shm *shm_buf; | |
81 | struct tee_param param[2]; | |
82 | size_t name_size = strlen(name) + 1; | |
83 | ||
84 | if (!tee) | |
85 | if (avb_ta_open_session()) | |
86 | return -ENODEV; | |
87 | ||
88 | rc = tee_shm_alloc(tee, name_size, | |
89 | TEE_SHM_ALLOC, &shm_name); | |
fbdaafbb IO |
90 | if (rc) { |
91 | rc = -ENOMEM; | |
92 | goto close_session; | |
93 | } | |
bcc6c574 RG |
94 | |
95 | rc = tee_shm_alloc(tee, buffer_size, | |
96 | TEE_SHM_ALLOC, &shm_buf); | |
97 | if (rc) { | |
98 | rc = -ENOMEM; | |
99 | goto free_name; | |
100 | } | |
101 | ||
102 | memcpy(shm_name->addr, name, name_size); | |
103 | ||
104 | memset(param, 0, sizeof(param)); | |
105 | param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; | |
106 | param[0].u.memref.shm = shm_name; | |
107 | param[0].u.memref.size = name_size; | |
108 | param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; | |
109 | param[1].u.memref.shm = shm_buf; | |
110 | param[1].u.memref.size = buffer_size; | |
111 | ||
112 | rc = invoke_func(TA_AVB_CMD_READ_PERSIST_VALUE, | |
113 | 2, param); | |
114 | if (rc) | |
115 | goto out; | |
116 | ||
117 | if (param[1].u.memref.size > buffer_size) { | |
118 | rc = -EINVAL; | |
119 | goto out; | |
120 | } | |
121 | ||
122 | *out_num_bytes_read = param[1].u.memref.size; | |
123 | ||
124 | memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read); | |
125 | ||
126 | out: | |
127 | tee_shm_free(shm_buf); | |
128 | free_name: | |
129 | tee_shm_free(shm_name); | |
fbdaafbb IO |
130 | close_session: |
131 | tee_close_session(tee, session); | |
132 | tee = NULL; | |
bcc6c574 RG |
133 | |
134 | return rc; | |
135 | } | |
136 | ||
137 | static int write_persistent_value(const char *name, | |
138 | size_t value_size, | |
139 | const u8 *value) | |
140 | { | |
141 | int rc = 0; | |
142 | struct tee_shm *shm_name; | |
143 | struct tee_shm *shm_buf; | |
144 | struct tee_param param[2]; | |
145 | size_t name_size = strlen(name) + 1; | |
146 | ||
fbdaafbb IO |
147 | if (!value_size) |
148 | return -EINVAL; | |
149 | ||
bcc6c574 RG |
150 | if (!tee) { |
151 | if (avb_ta_open_session()) | |
152 | return -ENODEV; | |
153 | } | |
bcc6c574 RG |
154 | |
155 | rc = tee_shm_alloc(tee, name_size, | |
156 | TEE_SHM_ALLOC, &shm_name); | |
fbdaafbb IO |
157 | if (rc) { |
158 | rc = -ENOMEM; | |
159 | goto close_session; | |
160 | } | |
bcc6c574 RG |
161 | |
162 | rc = tee_shm_alloc(tee, value_size, | |
163 | TEE_SHM_ALLOC, &shm_buf); | |
164 | if (rc) { | |
165 | rc = -ENOMEM; | |
166 | goto free_name; | |
167 | } | |
168 | ||
169 | memcpy(shm_name->addr, name, name_size); | |
170 | memcpy(shm_buf->addr, value, value_size); | |
171 | ||
172 | memset(param, 0, sizeof(param)); | |
173 | param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; | |
174 | param[0].u.memref.shm = shm_name; | |
175 | param[0].u.memref.size = name_size; | |
176 | param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; | |
177 | param[1].u.memref.shm = shm_buf; | |
178 | param[1].u.memref.size = value_size; | |
179 | ||
180 | rc = invoke_func(TA_AVB_CMD_WRITE_PERSIST_VALUE, | |
181 | 2, param); | |
182 | if (rc) | |
183 | goto out; | |
184 | ||
185 | out: | |
186 | tee_shm_free(shm_buf); | |
187 | free_name: | |
188 | tee_shm_free(shm_name); | |
fbdaafbb IO |
189 | close_session: |
190 | tee_close_session(tee, session); | |
191 | tee = NULL; | |
bcc6c574 RG |
192 | |
193 | return rc; | |
194 | } | |
195 | ||
196 | int do_optee_rpmb_read(struct cmd_tbl *cmdtp, int flag, int argc, | |
197 | char * const argv[]) | |
198 | { | |
199 | const char *name; | |
200 | size_t bytes; | |
201 | size_t bytes_read; | |
202 | void *buffer; | |
203 | char *endp; | |
204 | ||
205 | if (argc != 3) | |
206 | return CMD_RET_USAGE; | |
207 | ||
208 | name = argv[1]; | |
0b1284eb | 209 | bytes = dectoul(argv[2], &endp); |
bcc6c574 RG |
210 | if (*endp && *endp != '\n') |
211 | return CMD_RET_USAGE; | |
212 | ||
213 | buffer = malloc(bytes); | |
214 | if (!buffer) | |
215 | return CMD_RET_FAILURE; | |
216 | ||
217 | if (read_persistent_value(name, bytes, buffer, &bytes_read) == 0) { | |
218 | printf("Read %zu bytes, value = %s\n", bytes_read, | |
219 | (char *)buffer); | |
220 | free(buffer); | |
221 | return CMD_RET_SUCCESS; | |
222 | } | |
223 | ||
224 | printf("Failed to read persistent value\n"); | |
225 | ||
226 | free(buffer); | |
227 | ||
228 | return CMD_RET_FAILURE; | |
229 | } | |
230 | ||
231 | int do_optee_rpmb_write(struct cmd_tbl *cmdtp, int flag, int argc, | |
232 | char * const argv[]) | |
233 | { | |
234 | const char *name; | |
235 | const char *value; | |
236 | ||
237 | if (argc != 3) | |
238 | return CMD_RET_USAGE; | |
239 | ||
240 | name = argv[1]; | |
241 | value = argv[2]; | |
242 | ||
243 | if (write_persistent_value(name, strlen(value) + 1, | |
244 | (const uint8_t *)value) == 0) { | |
245 | printf("Wrote %zu bytes\n", strlen(value) + 1); | |
246 | return CMD_RET_SUCCESS; | |
247 | } | |
248 | ||
249 | printf("Failed to write persistent value\n"); | |
250 | ||
251 | return CMD_RET_FAILURE; | |
252 | } | |
253 | ||
254 | static struct cmd_tbl cmd_optee_rpmb[] = { | |
255 | U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_optee_rpmb_read, "", ""), | |
256 | U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_optee_rpmb_write, "", ""), | |
257 | }; | |
258 | ||
259 | static int do_optee_rpmb(struct cmd_tbl *cmdtp, int flag, int argc, | |
260 | char * const argv[]) | |
261 | { | |
262 | struct cmd_tbl *cp; | |
263 | ||
264 | cp = find_cmd_tbl(argv[1], cmd_optee_rpmb, ARRAY_SIZE(cmd_optee_rpmb)); | |
265 | ||
266 | argc--; | |
267 | argv++; | |
268 | ||
269 | if (!cp || argc > cp->maxargs) | |
270 | return CMD_RET_USAGE; | |
271 | ||
272 | if (flag == CMD_FLAG_REPEAT) | |
273 | return CMD_RET_FAILURE; | |
274 | ||
275 | return cp->cmd(cmdtp, flag, argc, argv); | |
276 | } | |
277 | ||
278 | U_BOOT_CMD ( | |
279 | optee_rpmb, 29, 0, do_optee_rpmb, | |
280 | "Provides commands for testing secure storage on RPMB on OPTEE", | |
281 | "read_pvalue <name> <bytes> - read a persistent value <name>\n" | |
282 | "optee_rpmb write_pvalue <name> <value> - write a persistent value <name>\n" | |
283 | ); |