blob: 6963893326c0d6df648b00e0200393361c97d6bd [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <mapmem.h>
8#include <tee.h>
9
10#define RMA_OS_DEBUG_ENABLE (0)
11
12#define CMD_RMA_OS_INIT_DATA (0)
13#define CMD_RMA_OS_GET_CMD_LIST (1)
14#define CMD_RMA_OS_RUN_CMD (2)
15#define CMD_RMA_OS_GET_INFO (3)
16
17#define TA_RMA_TEE_OS_UUID \
18 { 0x99a216e5, 0x6718, 0x4dfd, \
19 { 0xbb, 0xb1, 0x37, 0xcd, 0x0d, 0x00, 0x10, 0xc6 } }
20
21#define RMA_CMD_MAX_NUM (64)
22#define RMA_CMD_MAX_LENGTH (128)
23#define RMA_AUTH_HDR_MAGIC (0x414D52) // "RMA"
24#define RMA_AUTH_DATA_MAX_SIZE (32 + 256 + 16 * RMA_CMD_MAX_NUM)
25
26struct rma_info_output {
27 char name[RMA_CMD_MAX_LENGTH];
28 char info[RMA_CMD_MAX_LENGTH];
29};
30
31static struct rma_info_output rma_info[RMA_CMD_MAX_NUM + 1];
32
33static void dump_rma_info(struct rma_info_output *result, uint32_t len,
34 char *title, char *comment)
35{
36 uint32_t i;
37
38 for (i = 0; i < 10; i++)
39 printf("---------");
40
41 printf("\n");
42
43 printf("%-55s | %s\n", title, comment);
44
45 for (i = 0; i < 10; i++)
46 printf("---------");
47 printf("\n");
48
49 for (i = 0; i < len; i++)
50 printf("%-55s | %s\n", result[i].name, result[i].info);
51
52 for (i = 0; i < 10; i++)
53 printf("---------");
54
55 printf("\n");
56}
57
58static int do_rma_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
59{
60 int ret = CMD_RET_SUCCESS;
61 uint8_t *buf;
62 uint32_t map_addr = 0;
63 uint32_t magic;
64 uint32_t number;
65 uint32_t real_size;
66 char rma_data[RMA_AUTH_DATA_MAX_SIZE];
67 struct tee_param params;
68 struct udevice *dev;
69 struct tee_open_session_arg open_arg;
70 struct tee_invoke_arg invoke_arg;
71 const struct tee_optee_ta_uuid uuid = TA_RMA_TEE_OS_UUID;
72
73 if (argc != 2) {
74 printf("Usage: rma init ADDR, ADDR is memory address\n");
75 return CMD_RET_USAGE;
76 }
77
78 /* Get RMA data memory address */
79 map_addr = simple_strtoul(argv[1], NULL, 16);
80 if (map_addr <= 0 || map_addr >= 0xffffffff) {
81 printf("RMA data memory address: %#x invalid!\n", map_addr);
82 return CMD_RET_USAGE;
83 }
84
85 /* Map RMA data memory */
86 buf = map_sysmem(map_addr, RMA_AUTH_DATA_MAX_SIZE);
87
88 /* Check RMA data magic */
89 magic = *(uint32_t *)buf;
90 if (magic != RMA_AUTH_HDR_MAGIC) {
91 printf("RMA data magic: %#x invalid, it must be %#x\n",
92 magic, RMA_AUTH_HDR_MAGIC);
93 unmap_sysmem(buf);
94 return -CMD_RET_FAILURE;
95 }
96
97 /* Check RMA data size */
98 number = *(uint32_t *)(buf + 16);
99 real_size = RMA_AUTH_DATA_MAX_SIZE - (16 * (RMA_CMD_MAX_NUM - number));
100 if (real_size > RMA_AUTH_DATA_MAX_SIZE) {
101 printf("RMA data size %#x larger than %#x\n",
102 real_size, RMA_AUTH_DATA_MAX_SIZE);
103 unmap_sysmem(buf);
104 return -CMD_RET_FAILURE;
105 }
106
107 /* Get RMA data */
108 memset(rma_data, 0, sizeof(rma_data));
109 memcpy(rma_data, buf, real_size);
110
111 /* Unmap RMA data memory */
112 unmap_sysmem(buf);
113
114#if RMA_OS_DEBUG_ENABLE
115 /* Debug print RMA data */
116 int index;
117
118 printf("[Debug] RMA Data:\n");
119 for (index = 0; index < real_size; index++) {
120 if ((index % 16) == 0)
121 printf("\n");
122 printf("%02x ", rma_data[index]);
123 }
124 printf("\nPrint data finished!\n");
125#endif
126
127 /* Find TEE device */
128 dev = tee_find_device(NULL, NULL, NULL, NULL);
129 if (!dev) {
130 printf("tee_find_device failed");
131 return -CMD_RET_FAILURE;
132 }
133
134 /* Open TEE session */
135 memset(&open_arg, 0, sizeof(open_arg));
136 tee_optee_ta_uuid_to_octets(open_arg.uuid, &uuid);
137 ret = tee_open_session(dev, &open_arg, 0, NULL);
138 if (ret) {
139 printf("tee_open_session failed, ret: %#x\n", ret);
140 return CMD_RET_FAILURE;
141 }
142 if (open_arg.ret) {
143 printf("tee_open_session failed, ret: %#x, origin: %#x\n",
144 open_arg.ret, open_arg.ret_origin);
145 return CMD_RET_FAILURE;
146 }
147
148 /* Alloc share memory for RMA data */
149 memset(&params, 0, sizeof(params));
150 params.attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
151 params.u.memref.size = real_size;
152 ret = tee_shm_alloc(dev, real_size, 0, &params.u.memref.shm);
153 if (ret) {
154 printf("tee_shm_alloc failed, ret: %#x\n", ret);
155 tee_close_session(dev, open_arg.session);
156 return CMD_RET_FAILURE;
157 }
158 memcpy(params.u.memref.shm->addr, rma_data, real_size);
159
160 /* Invoke TEE command */
161 memset(&invoke_arg, 0, sizeof(invoke_arg));
162 invoke_arg.session = open_arg.session;
163 invoke_arg.func = CMD_RMA_OS_INIT_DATA;
164 ret = tee_invoke_func(dev, &invoke_arg, 1, &params);
165 if (ret) {
166 printf("tee_invoke_func failed, ret = %#x\n", ret);
167 ret = CMD_RET_FAILURE;
168 goto exit;
169 }
170 if (invoke_arg.ret) {
171 printf("RMA OS init failed, ret: %#x, origin: %#x\n",
172 invoke_arg.ret, invoke_arg.ret_origin);
173 ret = CMD_RET_FAILURE;
174 goto exit;
175 }
176 printf("RMA OS init and verify authentication data successfully!\n");
177
178exit:
179 tee_shm_free(params.u.memref.shm);
180 tee_close_session(dev, open_arg.session);
181
182 return ret;
183}
184
185static int do_rma_list(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
186{
187 int ret = CMD_RET_SUCCESS;
188 uint32_t info_size;
189 struct tee_param params;
190 struct udevice *dev;
191 struct tee_open_session_arg open_arg;
192 struct tee_invoke_arg invoke_arg;
193 const struct tee_optee_ta_uuid uuid = TA_RMA_TEE_OS_UUID;
194
195 /* Find TEE device */
196 dev = tee_find_device(NULL, NULL, NULL, NULL);
197 if (!dev) {
198 printf("call tee_find_device failed");
199 return -CMD_RET_FAILURE;
200 }
201
202 /* Open TEE session */
203 memset(&open_arg, 0, sizeof(open_arg));
204 tee_optee_ta_uuid_to_octets(open_arg.uuid, &uuid);
205 ret = tee_open_session(dev, &open_arg, 0, NULL);
206 if (ret) {
207 printf("call tee_open_session failed, ret: %#x\n", ret);
208 return CMD_RET_FAILURE;
209 }
210 if (open_arg.ret) {
211 printf("call tee_open_session failed, ret: %#x, origin: %#x\n",
212 open_arg.ret, open_arg.ret_origin);
213 return CMD_RET_FAILURE;
214 }
215
216 /* Alloc share memory for RMA command list */
217 memset((void *)rma_info, 0, sizeof(rma_info));
218 info_size = sizeof(rma_info);
219 memset(&params, 0, sizeof(params));
220 params.attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
221 params.u.memref.size = info_size;
222 ret = tee_shm_alloc(dev, info_size, 0, &params.u.memref.shm);
223 if (ret) {
224 printf("tee_shm_alloc failed, ret: %#x\n", ret);
225 tee_close_session(dev, open_arg.session);
226 return CMD_RET_FAILURE;
227 }
228
229 /* Invoke TEE command */
230 memset(&invoke_arg, 0, sizeof(invoke_arg));
231 invoke_arg.session = open_arg.session;
232 invoke_arg.func = CMD_RMA_OS_GET_CMD_LIST;
233 ret = tee_invoke_func(dev, &invoke_arg, 1, &params);
234 if (ret) {
235 printf("tee_invoke_func failed, ret = %#x\n", ret);
236 ret = CMD_RET_FAILURE;
237 goto exit;
238 }
239 if (invoke_arg.ret) {
240 printf("Get RMA Command List failed, ret: %#x, origin: %#x\n",
241 invoke_arg.ret, invoke_arg.ret_origin);
242 ret = CMD_RET_FAILURE;
243 goto exit;
244 }
245
246 /* Dump RMA command list */
247 info_size = (params.u.memref.size / sizeof(struct rma_info_output));
248 memcpy(rma_info, params.u.memref.shm->addr, params.u.memref.size);
249 dump_rma_info(rma_info, info_size, "Command", "Status");
250
251exit:
252 tee_shm_free(params.u.memref.shm);
253 tee_close_session(dev, open_arg.session);
254
255 return ret;
256}
257
258static int do_rma_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
259{
260 int ret = CMD_RET_SUCCESS;
261 int cmd = 0;
262 struct tee_param params[4];
263 struct udevice *dev;
264 struct tee_open_session_arg open_arg;
265 struct tee_invoke_arg invoke_arg;
266 const struct tee_optee_ta_uuid uuid = TA_RMA_TEE_OS_UUID;
267
268 if (argc != 2) {
269 printf("Usage: rma cmd ID, ID is command index\n");
270 return CMD_RET_USAGE;
271 }
272
273 /* Check RMA command range */
274 cmd = simple_strtoul(argv[1], NULL, 10);
275 if (cmd <= 0 || cmd > RMA_CMD_MAX_NUM) {
276 printf("Command ID: %d invalid! Range: 1~%d\n", cmd, RMA_CMD_MAX_NUM);
277 return CMD_RET_USAGE;
278 }
279
280 /* Find TEE device */
281 dev = tee_find_device(NULL, NULL, NULL, NULL);
282 if (!dev) {
283 printf("tee_find_device failed");
284 return -CMD_RET_FAILURE;
285 }
286
287 /* Open TEE session */
288 memset(&open_arg, 0, sizeof(open_arg));
289 tee_optee_ta_uuid_to_octets(open_arg.uuid, &uuid);
290 ret = tee_open_session(dev, &open_arg, 0, NULL);
291 if (ret) {
292 printf("tee_open_session failed, ret: %#x\n", ret);
293 ret = CMD_RET_FAILURE;
294 return ret;
295 }
296 if (open_arg.ret) {
297 printf("tee_open_session failed, ret: %#x, origin: %#x\n",
298 open_arg.ret, open_arg.ret_origin);
299 ret = CMD_RET_FAILURE;
300 return ret;
301 }
302
303 /* Set TEE invoke params */
304 memset(params, 0, sizeof(params));
305 params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INOUT;
306 params[0].u.value.a = cmd;
307 params[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INOUT;
308 params[2].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
309 params[3].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
310
311 /* Invoke TEE command */
312 memset(&invoke_arg, 0, sizeof(invoke_arg));
313 invoke_arg.session = open_arg.session;
314 invoke_arg.func = CMD_RMA_OS_RUN_CMD;
315 ret = tee_invoke_func(dev, &invoke_arg, 4, params);
316 if (ret) {
317 printf("tee_invoke_func failed, ret = %#x\n", ret);
318 ret = CMD_RET_FAILURE;
319 goto exit;
320 }
321 if (invoke_arg.ret) {
322 printf("Run RMA Command %d failed, ret: %#x, origin: %#x\n",
323 cmd, invoke_arg.ret, invoke_arg.ret_origin);
324 ret = CMD_RET_FAILURE;
325 goto exit;
326 }
327 printf("Run RMA Command %d successfully!\n", cmd);
328
329exit:
330 tee_close_session(dev, open_arg.session);
331
332 return ret;
333}
334
335static int do_rma_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
336{
337 int ret = CMD_RET_SUCCESS;
338 uint32_t info_size;
339 struct tee_param params;
340 struct udevice *dev;
341 struct tee_open_session_arg open_arg;
342 struct tee_invoke_arg invoke_arg;
343 const struct tee_optee_ta_uuid uuid = TA_RMA_TEE_OS_UUID;
344
345 /* Find TEE device */
346 dev = tee_find_device(NULL, NULL, NULL, NULL);
347 if (!dev) {
348 printf("call tee_find_device failed");
349 return -CMD_RET_FAILURE;
350 }
351
352 /* Open TEE session */
353 memset(&open_arg, 0, sizeof(open_arg));
354 tee_optee_ta_uuid_to_octets(open_arg.uuid, &uuid);
355 ret = tee_open_session(dev, &open_arg, 0, NULL);
356 if (ret) {
357 printf("call tee_open_session failed, ret: %#x\n", ret);
358 return CMD_RET_FAILURE;
359 }
360 if (open_arg.ret) {
361 printf("call tee_open_session failed, ret: %#x, origin: %#x\n",
362 open_arg.ret, open_arg.ret_origin);
363 return CMD_RET_FAILURE;
364 }
365
366 /* Alloc share memory for RMA OS info */
367 memset((void *)rma_info, 0, sizeof(rma_info));
368 info_size = sizeof(rma_info);
369 memset(&params, 0, sizeof(params));
370 params.attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
371 params.u.memref.size = info_size;
372 ret = tee_shm_alloc(dev, info_size, 0, &params.u.memref.shm);
373 if (ret) {
374 printf("tee_shm_alloc failed, ret: %#x\n", ret);
375 tee_close_session(dev, open_arg.session);
376 return CMD_RET_FAILURE;
377 }
378
379 /* Invoke TEE command */
380 memset(&invoke_arg, 0, sizeof(invoke_arg));
381 invoke_arg.session = open_arg.session;
382 invoke_arg.func = CMD_RMA_OS_GET_INFO;
383 ret = tee_invoke_func(dev, &invoke_arg, 1, &params);
384 if (ret) {
385 printf("tee_invoke_func failed, ret = %#x\n", ret);
386 ret = CMD_RET_FAILURE;
387 goto exit;
388 }
389 if (invoke_arg.ret) {
390 printf("Get RMA OS information failed, ret: %#x, origin: %#x\n",
391 invoke_arg.ret, invoke_arg.ret_origin);
392 ret = CMD_RET_FAILURE;
393 goto exit;
394 }
395
396 /* Dump RMA OS information */
397 info_size = (params.u.memref.size / sizeof(struct rma_info_output));
398 memcpy(rma_info, params.u.memref.shm->addr, params.u.memref.size);
399 dump_rma_info(rma_info, info_size, "Information", "Status");
400
401exit:
402 tee_shm_free(params.u.memref.shm);
403 tee_close_session(dev, open_arg.session);
404
405 return ret;
406}
407
408static cmd_tbl_t cmd_rma_sub[] = {
409 U_BOOT_CMD_MKENT(init, 2, 0, do_rma_init, "", ""),
410 U_BOOT_CMD_MKENT(list, 1, 0, do_rma_list, "", ""),
411 U_BOOT_CMD_MKENT(cmd, 2, 0, do_rma_cmd, "", ""),
412 U_BOOT_CMD_MKENT(info, 1, 0, do_rma_info, "", ""),
413};
414
415static int do_rma(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
416{
417 cmd_tbl_t *c;
418
419 if (argc < 2)
420 return cmd_usage(cmdtp);
421
422 argc--;
423 argv++;
424
425 /* Check uboot sub command */
426 c = find_cmd_tbl(argv[0], &cmd_rma_sub[0], ARRAY_SIZE(cmd_rma_sub));
427
428 if (c)
429 return c->cmd(cmdtp, flag, argc, argv);
430 else
431 return cmd_usage(cmdtp);
432}
433
434static char rma_help_text[] =
435 "\n"
436 "[rma info] -Show RMA OS information\n"
437 "[rma init] -Init RMA OS and verify authentication data\n"
438 " e.g: rma init ADDR; ADDR is memory address, e.g: 0x1080000\n"
439 "[rma list] -Show RMA OS command permission list\n"
440 "[rma cmd] -Run a RMA OS command\n"
441 " e.g: rma cmd ID; ID is command index, e.g: 1,2,3...\n";
442
443U_BOOT_CMD(rma, CONFIG_SYS_MAXARGS, 0, do_rma,
444 "RMA OS Function", rma_help_text);
445