1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2012 by Amaury Pouly
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
27 #include <readline/readline.h>
28 #include <readline/history.h>
31 struct hwemul_device_t hwdev
;
32 struct hwemul_soc_t
*cur_soc
= NULL
;
34 void print_log(struct hwemul_device_t
*hwdev
)
39 int length
= hwemul_get_log(hwdev
, buffer
, sizeof(buffer
) - 1);
49 printf("Commands:\n");
50 printf(" help\t\tDisplay this help\n");
51 printf(" call <addr>\tCall address <addr>\n");
52 printf(" quit\t\tQuit this session\n");
53 printf(" read32 <addr>\tRead a 32-bit word at <addr>\n");
54 printf(" write32 <value> <addr>\tRead the 32-bit word <value> at <addr>\n");
55 printf(" read <regname>\tRead a register by name\n");
56 printf(" read <regname>.<field>\tRead a register field by name\n");
57 printf(" soc <socname>\tSelect the soc description to use\n");
58 printf(" write <value> <regname>\tWrite a register by name\n");
59 printf(" write <value <regname>.<field>\tWrite a register field by name\n");
60 printf(" NOTE: if the register is SCT variant, no read is performed.\n");
64 int syntax_error(char *str
)
66 printf("Syntax error at '%s'. Type 'help' to get some help.\n", str
);
70 int parse_uint32(char *str
, uint32_t *u
)
73 *u
= strtoul(str
, &end
, 0);
77 int do_call(uint32_t a
)
79 hwemul_call(&hwdev
, a
);
85 char *arg
= strtok(NULL
, " ");
87 if(arg
&& parse_uint32(arg
, &addr
))
90 return syntax_error(arg
);
93 int do_read32(uint32_t a
)
96 if(hwemul_rw_mem(&hwdev
, 1, a
, &val
, sizeof(val
)) == sizeof(val
))
97 printf("%#x = %#x\n", a
, val
);
99 printf("read error at %#x\n", a
);
105 char *arg
= strtok(NULL
, " ");
107 if(arg
&& parse_uint32(arg
, &addr
))
108 return do_read32(addr
);
110 return syntax_error(arg
);
113 int do_write32(uint32_t val
, uint32_t a
)
115 if(hwemul_rw_mem(&hwdev
, 0, a
, &val
, sizeof(val
)) == sizeof(val
))
116 printf("data written\n");
118 printf("write error at %#x\n", a
);
124 char *arg
= strtok(NULL
, " ");
126 if(!arg
|| !parse_uint32(arg
, &val
))
127 return syntax_error(arg
);
129 arg
= strtok(NULL
, " ");
130 if(arg
&& parse_uint32(arg
, &addr
))
131 return do_write32(val
, addr
);
133 return syntax_error(arg
);
136 struct hwemul_soc_t
*find_soc_by_name(const char *soc
)
138 struct hwemul_soc_list_t
*list
= hwemul_get_soc_list();
139 for(size_t i
= 0; i
< list
->nr_socs
; i
++)
140 if(strcmp(soc
, list
->socs
[i
]->name
) == 0)
141 return list
->socs
[i
];
145 struct hwemul_soc_reg_t
*find_reg_by_name(struct hwemul_soc_t
*soc
, const char *reg
)
147 for(size_t i
= 0; i
< soc
->nr_regs
; i
++)
148 if(strcmp(reg
, soc
->regs_by_name
[i
]->name
) == 0)
149 return soc
->regs_by_name
[i
];
153 struct hwemul_soc_reg_field_t
*find_field_by_name(struct hwemul_soc_reg_t
*reg
, const char *field
)
155 for(size_t i
= 0; i
< reg
->nr_fields
; i
++)
156 if(strcmp(field
, reg
->fields_by_name
[i
]->name
) == 0)
157 return reg
->fields_by_name
[i
];
162 int do_read(char *regname
)
164 char *dot
= strchr(regname
, '.');
169 printf("No soc selected!\n");
172 struct hwemul_soc_reg_t
*reg
= find_reg_by_name(cur_soc
, regname
);
175 printf("no reg '%s' found\n", regname
);
179 if(hwemul_rw_mem(&hwdev
, 1, reg
->addr
, &val
, sizeof(val
)) != sizeof(val
))
181 printf("read error at %#x\n", reg
->addr
);
186 struct hwemul_soc_reg_field_t
*field
= find_field_by_name(reg
, dot
);
189 printf("no field '%s' found\n", dot
);
192 val
>>= field
->first_bit
;
193 val
&= (1 << (field
->last_bit
- field
->first_bit
+ 1)) - 1;
194 printf("%s.%s = %#x\n", regname
, dot
, val
);
197 printf("%s = %#x\n", regname
, val
);
203 char *arg
= strtok(NULL
, " ");
207 return syntax_error(arg
);
210 int do_soc(char *soc
)
212 struct hwemul_soc_t
*s
= find_soc_by_name(soc
);
214 printf("no soc '%s' found\n", soc
);
222 char *arg
= strtok(NULL
, " ");
226 return syntax_error(arg
);
229 int do_write(uint32_t val
, char *regname
)
231 char *dot
= strchr(regname
, '.');
236 printf("No soc selected!\n");
239 struct hwemul_soc_reg_t
*reg
= find_reg_by_name(cur_soc
, regname
);
241 uint32_t addr_off
= 0;
244 size_t len
= strlen(regname
);
245 /* try SCT variant */
246 if(strcmp(regname
+ len
- 4, "_SET") == 0)
248 else if(strcmp(regname
+ len
- 4, "_CLR") == 0)
250 else if(strcmp(regname
+ len
- 4, "_TOG") == 0)
254 printf("no reg '%s' found\n", regname
);
258 regname
[len
- 4] = 0;
259 reg
= find_reg_by_name(cur_soc
, regname
);
262 printf("no reg '%s' found\n", regname
);
268 struct hwemul_soc_reg_field_t
*field
= find_field_by_name(reg
, dot
);
271 printf("no field '%s' found\n", dot
);
274 uint32_t actual_val
= 0;
277 if(hwemul_rw_mem(&hwdev
, 1, reg
->addr
, &actual_val
, sizeof(actual_val
)) != sizeof(actual_val
))
279 printf("read error at %#x\n", reg
->addr
);
282 printf("read %#x at %#x\n", actual_val
, reg
->addr
);
284 uint32_t mask
= ((1 << (field
->last_bit
- field
->first_bit
+ 1)) - 1) << field
->first_bit
;
285 printf("mask=%#x\n", mask
);
286 val
= (actual_val
& ~mask
) | ((val
<< field
->first_bit
) & mask
);
288 printf("write %#x to %#x\n", val
, reg
->addr
+ addr_off
);
289 if(hwemul_rw_mem(&hwdev
, 0, reg
->addr
+ addr_off
, &val
, sizeof(val
)) != sizeof(val
))
291 printf("write error at %#x\n", reg
->addr
);
299 char *arg
= strtok(NULL
, " ");
301 if(!arg
|| !parse_uint32(arg
, &val
))
302 return syntax_error(arg
);
303 arg
= strtok(NULL
, " ");
305 return do_write(val
, arg
);
307 return syntax_error(arg
);
310 int parse_command(char *cmd
)
312 if(strcmp(cmd
, "help") == 0)
314 if(strcmp(cmd
, "quit") == 0)
316 if(strcmp(cmd
, "call") == 0)
318 if(strcmp(cmd
, "read32") == 0)
319 return parse_read32();
320 if(strcmp(cmd
, "write32") == 0)
321 return parse_write32();
322 if(strcmp(cmd
, "read") == 0)
324 if(strcmp(cmd
, "soc") == 0)
326 if(strcmp(cmd
, "write") == 0)
327 return parse_write();
328 return syntax_error(cmd
);
331 void interactive_mode(void)
333 rl_bind_key('\t', rl_complete
);
336 char *input
= readline("> ");
340 int ret
= parse_command(input
);
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
);
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");
362 int main(int argc
, char **argv
)
366 static struct option long_options
[] =
368 {"help", no_argument
, 0, '?'},
369 {"quiet", no_argument
, 0, 'q'},
373 int c
= getopt_long(argc
, argv
, "?q", long_options
, NULL
);
391 if(argc
- optind
!= 0)
399 libusb_set_debug(ctx
, 3);
402 printf("Looking for device %#04x:%#04x...\n", HWEMUL_USB_VID
, HWEMUL_USB_PID
);
404 libusb_device_handle
*handle
= libusb_open_device_with_vid_pid(ctx
,
405 HWEMUL_USB_VID
, HWEMUL_USB_PID
);
408 printf("No device found\n");
412 libusb_device
*mydev
= libusb_get_device(handle
);
415 printf("device found at %d:%d\n",
416 libusb_get_bus_number(mydev
),
417 libusb_get_device_address(mydev
));
419 hwdev
.handle
= handle
;
420 if(hwemul_probe(&hwdev
))
422 printf("Cannot probe device!\n");
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
))
430 printf("Cannot get version!\n");
434 printf("Device version: %d.%d.%d\n", ver
.major
, ver
.minor
, ver
.revision
);
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
))
440 printf("Cannot get layout: %d\n", ret
);
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
);
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
))
455 printf("Cannot get features: %d\n", ret
);
460 printf("Device features:");
461 if(features
.feature_mask
& HWEMUL_FEATURE_LOG
)
463 if(features
.feature_mask
& HWEMUL_FEATURE_MEM
)
465 if(features
.feature_mask
& HWEMUL_FEATURE_CALL
)
467 if(features
.feature_mask
& HWEMUL_FEATURE_JUMP
)
469 if(features
.feature_mask
& HWEMUL_FEATURE_AES_OTP
)
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
))
478 printf("Cannot get stmp: %d\n", ret
);
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
);
491 void *rom
= malloc(64 * 1024);
492 ret
= hwemul_rw_mem(&hwdev
, 1, 0xc0000000, rom
, 64 * 1024);
495 printf("Cannot read ROM: %d\n", ret
);
499 printf("ROM successfully read!\n");
500 FILE *f
= fopen("rom.bin", "wb");
501 fwrite(rom
, 64 * 1024, 1, f
);
511 } __attribute__((packed
)) dcp_test
;
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();
520 for(int i
= 0; i
< 16; i
++)
521 printf(" %02x", dcp_test
.iv
[i
]);
524 for(int i
= 0; i
< 16; i
++)
525 printf(" %02x", dcp_test
.data
[i
]);
528 if(!hwemul_aes_otp(&hwdev
, &dcp_test
, sizeof(dcp_test
), HWEMUL_AES_OTP_ENCRYPT
))
532 for(int i
= 0; i
< 16; i
++)
533 printf(" %02x", dcp_test
.iv
[i
]);
536 for(int i
= 0; i
< 16; i
++)
537 printf(" %02x", dcp_test
.data
[i
]);
541 printf("DCP error!\n");
545 printf("Starting interactive session. Type 'help' to get help.\n");
550 if(features
.feature_mask
& HWEMUL_FEATURE_LOG
)
553 printf("Device log:\n");
556 hwemul_release(&hwdev
);