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