summaryrefslogtreecommitdiff
path: root/utils/imxtools/hwemul/tools/hwemul_tool.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/imxtools/hwemul/tools/hwemul_tool.c')
-rw-r--r--utils/imxtools/hwemul/tools/hwemul_tool.c558
1 files changed, 558 insertions, 0 deletions
diff --git a/utils/imxtools/hwemul/tools/hwemul_tool.c b/utils/imxtools/hwemul/tools/hwemul_tool.c
new file mode 100644
index 0000000000..c6056edf96
--- /dev/null
+++ b/utils/imxtools/hwemul/tools/hwemul_tool.c
@@ -0,0 +1,558 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "hwemul.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <stdbool.h>
27
28bool g_quiet = false;
29struct hwemul_device_t hwdev;
30struct hwemul_soc_t *cur_soc = NULL;
31
32void print_log(struct hwemul_device_t *hwdev)
33{
34 do
35 {
36 char buffer[128];
37 int length = hwemul_get_log(hwdev, buffer, sizeof(buffer) - 1);
38 if(length <= 0)
39 break;
40 buffer[length] = 0;
41 printf("%s", buffer);
42 }while(1);
43}
44
45int print_help()
46{
47 printf("Commands:\n");
48 printf(" help\t\tDisplay this help\n");
49 printf(" call <addr>\tCall address <addr>\n");
50 printf(" quit\t\tQuit this session\n");
51 printf(" read32 <addr>\tRead a 32-bit word at <addr>\n");
52 printf(" write32 <value> <addr>\tRead the 32-bit word <value> at <addr>\n");
53 printf(" read <regname>\tRead a register by name\n");
54 printf(" read <regname>.<field>\tRead a register field by name\n");
55 printf(" soc <socname>\tSelect the soc description to use\n");
56 printf(" write <value> <regname>\tWrite a register by name\n");
57 printf(" write <value <regname>.<field>\tWrite a register field by name\n");
58 printf(" NOTE: if the register is SCT variant, no read is performed.\n");
59 return 1;
60}
61
62int syntax_error(char *str)
63{
64 printf("Syntax error at '%s'. Type 'help' to get some help.\n", str);
65 return 1;
66}
67
68int parse_uint32(char *str, uint32_t *u)
69{
70 char *end;
71 *u = strtoul(str, &end, 0);
72 return *end == 0;
73}
74
75int do_call(uint32_t a)
76{
77 hwemul_call(&hwdev, a);
78 return 1;
79}
80
81int parse_call()
82{
83 char *arg = strtok(NULL, " ");
84 uint32_t addr;
85 if(arg && parse_uint32(arg, &addr))
86 return do_call(addr);
87 else
88 return syntax_error(arg);
89}
90
91int do_read32(uint32_t a)
92{
93 uint32_t val;
94 if(hwemul_rw_mem(&hwdev, 1, a, &val, sizeof(val)) == sizeof(val))
95 printf("%#x = %#x\n", a, val);
96 else
97 printf("read error at %#x\n", a);
98 return 1;
99}
100
101int parse_read32()
102{
103 char *arg = strtok(NULL, " ");
104 uint32_t addr;
105 if(arg && parse_uint32(arg, &addr))
106 return do_read32(addr);
107 else
108 return syntax_error(arg);
109}
110
111int do_write32(uint32_t val, uint32_t a)
112{
113 if(hwemul_rw_mem(&hwdev, 0, a, &val, sizeof(val)) == sizeof(val))
114 printf("data written\n");
115 else
116 printf("write error at %#x\n", a);
117 return 1;
118}
119
120int parse_write32()
121{
122 char *arg = strtok(NULL, " ");
123 uint32_t val;
124 if(!arg || !parse_uint32(arg, &val))
125 return syntax_error(arg);
126 uint32_t addr;
127 arg = strtok(NULL, " ");
128 if(arg && parse_uint32(arg, &addr))
129 return do_write32(val, addr);
130 else
131 return syntax_error(arg);
132}
133
134struct hwemul_soc_t *find_soc_by_name(const char *soc)
135{
136 struct hwemul_soc_list_t *list = hwemul_get_soc_list();
137 for(size_t i = 0; i < list->nr_socs; i++)
138 if(strcmp(soc, list->socs[i]->name) == 0)
139 return list->socs[i];
140 return NULL;
141}
142
143struct hwemul_soc_reg_t *find_reg_by_name(struct hwemul_soc_t *soc, const char *reg)
144{
145 for(size_t i = 0; i < soc->nr_regs; i++)
146 if(strcmp(reg, soc->regs_by_name[i]->name) == 0)
147 return soc->regs_by_name[i];
148 return NULL;
149}
150
151struct hwemul_soc_reg_field_t *find_field_by_name(struct hwemul_soc_reg_t *reg, const char *field)
152{
153 for(size_t i = 0; i < reg->nr_fields; i++)
154 if(strcmp(field, reg->fields_by_name[i]->name) == 0)
155 return reg->fields_by_name[i];
156 return NULL;
157}
158
159
160int do_read(char *regname)
161{
162 char *dot = strchr(regname, '.');
163 if(dot != NULL)
164 *dot++ = 0;
165 if(cur_soc == NULL)
166 {
167 printf("No soc selected!\n");
168 return 1;
169 }
170 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
171 if(reg == NULL)
172 {
173 printf("no reg '%s' found\n", regname);
174 return 1;
175 }
176 uint32_t val;
177 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &val, sizeof(val)) != sizeof(val))
178 {
179 printf("read error at %#x\n", reg->addr);
180 return 1;
181 }
182 if(dot)
183 {
184 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
185 if(field == NULL)
186 {
187 printf("no field '%s' found\n", dot);
188 return 1;
189 }
190 val >>= field->first_bit;
191 val &= (1 << (field->last_bit - field->first_bit + 1)) - 1;
192 printf("%s.%s = %#x\n", regname, dot, val);
193 }
194 else
195 printf("%s = %#x\n", regname, val);
196 return 1;
197}
198
199int parse_read()
200{
201 char *arg = strtok(NULL, " ");
202 if(arg)
203 return do_read(arg);
204 else
205 return syntax_error(arg);
206}
207
208int do_soc(char *soc)
209{
210 struct hwemul_soc_t *s = find_soc_by_name(soc);
211 if(s == NULL)
212 printf("no soc '%s' found\n", soc);
213 else
214 cur_soc = s;
215 return 1;
216}
217
218int parse_soc()
219{
220 char *arg = strtok(NULL, " ");
221 if(arg)
222 return do_soc(arg);
223 else
224 return syntax_error(arg);
225}
226
227int do_write(uint32_t val, char *regname)
228{
229 char *dot = strchr(regname, '.');
230 if(dot != NULL)
231 *dot++ = 0;
232 if(cur_soc == NULL)
233 {
234 printf("No soc selected!\n");
235 return 1;
236 }
237 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
238 int is_sct = 0;
239 uint32_t addr_off = 0;
240 if(reg == NULL)
241 {
242 size_t len = strlen(regname);
243 /* try SCT variant */
244 if(strcmp(regname + len - 4, "_SET") == 0)
245 addr_off = 4;
246 else if(strcmp(regname + len - 4, "_CLR") == 0)
247 addr_off = 8;
248 else if(strcmp(regname + len - 4, "_TOG") == 0)
249 addr_off = 12;
250 else
251 {
252 printf("no reg '%s' found\n", regname);
253 return 1;
254 }
255 is_sct = 1;
256 regname[len - 4] = 0;
257 reg = find_reg_by_name(cur_soc, regname);
258 if(reg == NULL)
259 {
260 printf("no reg '%s' found\n", regname);
261 return 1;
262 }
263 }
264 if(dot)
265 {
266 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
267 if(field == NULL)
268 {
269 printf("no field '%s' found\n", dot);
270 return 1;
271 }
272 uint32_t actual_val = 0;
273 if(!is_sct)
274 {
275 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &actual_val, sizeof(actual_val)) != sizeof(actual_val))
276 {
277 printf("read error at %#x\n", reg->addr);
278 return 1;
279 }
280 printf("read %#x at %#x\n", actual_val, reg->addr);
281 }
282 uint32_t mask = ((1 << (field->last_bit - field->first_bit + 1)) - 1) << field->first_bit;
283 printf("mask=%#x\n", mask);
284 val = (actual_val & ~mask) | ((val << field->first_bit) & mask);
285 }
286 printf("write %#x to %#x\n", val, reg->addr + addr_off);
287 if(hwemul_rw_mem(&hwdev, 0, reg->addr + addr_off, &val, sizeof(val)) != sizeof(val))
288 {
289 printf("write error at %#x\n", reg->addr);
290 return 1;
291 }
292 return 1;
293}
294
295int parse_write()
296{
297 char *arg = strtok(NULL, " ");
298 uint32_t val;
299 if(!arg || !parse_uint32(arg, &val))
300 return syntax_error(arg);
301 arg = strtok(NULL, " ");
302 if(arg)
303 return do_write(val, arg);
304 else
305 return syntax_error(arg);
306}
307
308int parse_command(char *cmd)
309{
310 if(strcmp(cmd, "help") == 0)
311 return print_help();
312 if(strcmp(cmd, "quit") == 0)
313 return 0;
314 if(strcmp(cmd, "call") == 0)
315 return parse_call();
316 if(strcmp(cmd, "read32") == 0)
317 return parse_read32();
318 if(strcmp(cmd, "write32") == 0)
319 return parse_write32();
320 if(strcmp(cmd, "read") == 0)
321 return parse_read();
322 if(strcmp(cmd, "soc") == 0)
323 return parse_soc();
324 if(strcmp(cmd, "write") == 0)
325 return parse_write();
326 return syntax_error(cmd);
327}
328
329int do_command()
330{
331 char *line = NULL;
332 int size = 0;
333 getline(&line, &size, stdin);
334 char *end = strchr(line, '\n');
335 if(end)
336 *end = 0;
337 char *pch = strtok(line, " ");
338 int ret;
339 if(pch)
340 ret = parse_command(pch);
341 else
342 ret = print_help();
343 free(line);
344 return ret;
345}
346
347void usage(void)
348{
349 printf("hwemul_tool, compiled with hwemul %d.%d.%d\n",
350 HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR, HWEMUL_VERSION_REV);
351 printf("available soc descriptions:");
352 for(unsigned i = 0; i < hwemul_get_soc_list()->nr_socs; i++)
353 printf(" %s", hwemul_get_soc_list()->socs[i]->name);
354 printf("\n");
355 printf("usage: hwemul_tool [options]\n");
356 printf("options:\n");
357 printf(" --help/-?\tDisplay this help\n");
358 printf(" --quiet/-q\tQuiet non-command messages\n");
359 exit(1);
360}
361
362int main(int argc, char **argv)
363{
364 while(1)
365 {
366 static struct option long_options[] =
367 {
368 {"help", no_argument, 0, '?'},
369 {"quiet", no_argument, 0, 'q'},
370 {0, 0, 0, 0}
371 };
372
373 int c = getopt_long(argc, argv, "?q", long_options, NULL);
374 if(c == -1)
375 break;
376 switch(c)
377 {
378 case -1:
379 break;
380 case 'q':
381 g_quiet = true;
382 break;
383 case '?':
384 usage();
385 break;
386 default:
387 abort();
388 }
389 }
390
391 if(argc - optind != 0)
392 {
393 usage();
394 return 1;
395 }
396
397 libusb_context *ctx;
398 libusb_init(&ctx);
399 libusb_set_debug(ctx, 3);
400
401 if(!g_quiet)
402 printf("Looking for device %#04x:%#04x...\n", HWEMUL_USB_VID, HWEMUL_USB_PID);
403
404 libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
405 HWEMUL_USB_VID, HWEMUL_USB_PID);
406 if(handle == NULL)
407 {
408 printf("No device found\n");
409 return 1;
410 }
411
412 libusb_device *mydev = libusb_get_device(handle);
413 if(!g_quiet)
414 {
415 printf("device found at %d:%d\n",
416 libusb_get_bus_number(mydev),
417 libusb_get_device_address(mydev));
418 }
419 hwdev.handle = handle;
420 if(hwemul_probe(&hwdev))
421 {
422 printf("Cannot probe device!\n");
423 return 1;
424 }
425
426 struct usb_resp_info_version_t ver;
427 int ret = hwemul_get_info(&hwdev, HWEMUL_INFO_VERSION, &ver, sizeof(ver));
428 if(ret != sizeof(ver))
429 {
430 printf("Cannot get version!\n");
431 goto Lerr;
432 }
433 if(!g_quiet)
434 printf("Device version: %d.%d.%d\n", ver.major, ver.minor, ver.revision);
435
436 struct usb_resp_info_layout_t layout;
437 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_LAYOUT, &layout, sizeof(layout));
438 if(ret != sizeof(layout))
439 {
440 printf("Cannot get layout: %d\n", ret);
441 goto Lerr;
442 }
443 if(!g_quiet)
444 {
445 printf("Device layout:\n");
446 printf(" Code: 0x%x (0x%x)\n", layout.oc_code_start, layout.oc_code_size);
447 printf(" Stack: 0x%x (0x%x)\n", layout.oc_stack_start, layout.oc_stack_size);
448 printf(" Buffer: 0x%x (0x%x)\n", layout.oc_buffer_start, layout.oc_buffer_size);
449 }
450
451 struct usb_resp_info_features_t features;
452 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_FEATURES, &features, sizeof(features));
453 if(ret != sizeof(features))
454 {
455 printf("Cannot get features: %d\n", ret);
456 goto Lerr;
457 }
458 if(!g_quiet)
459 {
460 printf("Device features:");
461 if(features.feature_mask & HWEMUL_FEATURE_LOG)
462 printf(" log");
463 if(features.feature_mask & HWEMUL_FEATURE_MEM)
464 printf(" mem");
465 if(features.feature_mask & HWEMUL_FEATURE_CALL)
466 printf(" call");
467 if(features.feature_mask & HWEMUL_FEATURE_JUMP)
468 printf(" jump");
469 if(features.feature_mask & HWEMUL_FEATURE_AES_OTP)
470 printf(" aes_otp");
471 printf("\n");
472 }
473
474 struct usb_resp_info_stmp_t stmp;
475 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_STMP, &stmp, sizeof(stmp));
476 if(ret != sizeof(stmp))
477 {
478 printf("Cannot get stmp: %d\n", ret);
479 goto Lerr;
480 }
481 if(!g_quiet)
482 {
483 printf("Device stmp:\n");
484 printf(" chip ID: %x (%s)\n", stmp.chipid,hwemul_get_product_string(&stmp));
485 printf(" revision: %d (%s)\n", stmp.rev, hwemul_get_rev_string(&stmp));
486 printf(" supported: %d\n", stmp.is_supported);
487 }
488
489 if(!g_quiet)
490 {
491 void *rom = malloc(64 * 1024);
492 ret = hwemul_rw_mem(&hwdev, 1, 0xc0000000, rom, 64 * 1024);
493 if(ret != 64 * 1024)
494 {
495 printf("Cannot read ROM: %d\n", ret);
496 goto Lerr;
497 }
498
499 printf("ROM successfully read!\n");
500 FILE *f = fopen("rom.bin", "wb");
501 fwrite(rom, 64 * 1024, 1, f);
502 fclose(f);
503 }
504
505 if(!g_quiet)
506 {
507 struct
508 {
509 uint8_t iv[16];
510 uint8_t data[16];
511 } __attribute__((packed)) dcp_test;
512
513 for(int i = 0; i < 16; i++)
514 dcp_test.iv[i] = rand();
515 for(int i = 0; i < 16; i++)
516 dcp_test.data[i] = rand();
517 printf("DCP\n");
518 printf(" IN\n");
519 printf(" IV:");
520 for(int i = 0; i < 16; i++)
521 printf(" %02x", dcp_test.iv[i]);
522 printf("\n");
523 printf(" IV:");
524 for(int i = 0; i < 16; i++)
525 printf(" %02x", dcp_test.data[i]);
526 printf("\n");
527
528 if(!hwemul_aes_otp(&hwdev, &dcp_test, sizeof(dcp_test), HWEMUL_AES_OTP_ENCRYPT))
529 {
530 printf(" OUT\n");
531 printf(" IV:");
532 for(int i = 0; i < 16; i++)
533 printf(" %02x", dcp_test.iv[i]);
534 printf("\n");
535 printf(" IV:");
536 for(int i = 0; i < 16; i++)
537 printf(" %02x", dcp_test.data[i]);
538 printf("\n");
539 }
540 else
541 printf("DCP error!\n");
542 }
543
544 if(!g_quiet)
545 printf("Starting interactive session. Type 'help' to get help.\n");
546 while(1)
547 if(!do_command())
548 break;
549 Lerr:
550 if(features.feature_mask & HWEMUL_FEATURE_LOG)
551 {
552 if(!g_quiet)
553 printf("Device log:\n");
554 print_log(&hwdev);
555 }
556 hwemul_release(&hwdev);
557 return 1;
558}