summaryrefslogtreecommitdiff
path: root/utils/hwstub/tools/hwstub_shell.cpp
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 02:02:53 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 02:25:15 +0200
commitc5357940ab0108b4102442d07825c44d5be0d22f (patch)
treeddfdd9744b1f0ac037fed1c802329cb4542f376b /utils/hwstub/tools/hwstub_shell.cpp
parent934e1e15af6f2b7bcfdd9dbe8a3a6393ffe5a4a1 (diff)
downloadrockbox-c5357940ab0108b4102442d07825c44d5be0d22f.tar.gz
rockbox-c5357940ab0108b4102442d07825c44d5be0d22f.zip
hwstub: major improvement in the stub and the tools
Fix the stub in many way to correctly detect the STMP family and act upon that. Drop some unused commands and bump version. Rewrite the tool to allows scripting in lua and load the register description from an XML file using the regtools. Introduce a new tool to load and run code using the hwstub (either binary format or Rockbox additive scramble format). Also switch to an optimise version of the memcpy/move/set functions to correctly handle alignement issue (like writing a full word/half-word when possible for registers which is crucial) Change-Id: Id1d5cfe0b1b47e8b43900d32c5cd6eafae6414f6
Diffstat (limited to 'utils/hwstub/tools/hwstub_shell.cpp')
-rw-r--r--utils/hwstub/tools/hwstub_shell.cpp873
1 files changed, 873 insertions, 0 deletions
diff --git a/utils/hwstub/tools/hwstub_shell.cpp b/utils/hwstub/tools/hwstub_shell.cpp
new file mode 100644
index 0000000000..58147319e0
--- /dev/null
+++ b/utils/hwstub/tools/hwstub_shell.cpp
@@ -0,0 +1,873 @@
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 "hwstub.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <stdbool.h>
27#include <readline/readline.h>
28#include <readline/history.h>
29#include <lua.hpp>
30#include "soc_desc.hpp"
31
32#if LUA_VERSION_NUM < 502
33#warning You need at least lua 5.2
34#endif
35
36/**
37 * Global variables
38 */
39bool g_quiet = false;
40struct hwstub_device_t g_hwdev;
41struct usb_resp_info_version_t g_hwdev_ver;
42struct usb_resp_info_layout_t g_hwdev_layout;
43struct usb_resp_info_features_t g_hwdev_features;
44struct usb_resp_info_stmp_t g_hwdev_stmp;
45lua_State *g_lua;
46
47/**
48 * hw specific
49 */
50
51void print_log(struct hwstub_device_t *hwdev)
52{
53 do
54 {
55 char buffer[128];
56 int length = hwstub_get_log(hwdev, buffer, sizeof(buffer) - 1);
57 if(length <= 0)
58 break;
59 buffer[length] = 0;
60 printf("%s", buffer);
61 }while(1);
62}
63
64/**
65 * Lua specific
66 */
67int my_lua_help(lua_State *state)
68{
69 bool has_sub = false;
70 // implement help() in C so that we do not rely on the init to implement it
71 // help can take optional arguments
72 int n = lua_gettop(state);
73
74 lua_getglobal(state, "hwstub");
75 if(!lua_istable(state, -1))
76 goto Lerr;
77 lua_getfield(state, -1, "help");
78 if(!lua_istable(state, -1))
79 goto Lerr;
80
81 for(int i = 1; i <= n; i++)
82 {
83 lua_pushvalue(state, i);
84 lua_gettable(state, -2);
85 if(lua_isnil(state, -1))
86 {
87 printf("I don't know subtopic '%s'!\n", lua_tostring(state, i));
88 return 0;
89 }
90 if(!lua_istable(state, -1))
91 {
92 printf("Subtopic '%s' is not a table!\n", lua_tostring(state, i));
93 return 0;
94 }
95 }
96
97 printf("================[ HELP ");
98 for(int i = 1; i <= n; i++)
99 printf("> %s ", lua_tostring(state, i));
100 printf("]================\n");
101
102 lua_pushnil(state);
103 while(lua_next(state, -2))
104 {
105 // key is at -2 and value at -1
106 if(lua_isstring(state, -1))
107 printf("%s\n", lua_tostring(state, -1));
108 else if(lua_istable(state, -1))
109 has_sub = true;
110 // pop value but keep key
111 lua_pop(state, 1);
112 }
113
114 if(has_sub)
115 {
116 printf("\n");
117 printf("You can get more information on the following subtopics:\n");
118 lua_pushnil(state);
119 while(lua_next(state, -2))
120 {
121 // key is at -2 and value at -1
122 if(lua_istable(state, -1))
123 printf("* %s\n", lua_tostring(state, -2));
124 // pop value but keep key
125 lua_pop(state, 1);
126 }
127 }
128 printf("================[ STOP ]================\n");
129
130 return 0;
131
132 Lerr:
133 printf("There is a problem with the Lua context. Help is expected to be in hwstub.help\n");
134 printf("You must have messed badly the environment.\n");
135 return 0;
136}
137
138typedef soc_word_t (*hw_readn_fn_t)(lua_State *state, soc_addr_t addr);
139typedef void (*hw_writen_fn_t)(lua_State *state, soc_addr_t addr, soc_word_t val);
140
141soc_word_t hw_read8(lua_State *state, soc_addr_t addr)
142{
143 uint8_t u;
144 if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
145 luaL_error(state, "fail to read8 @ %p", addr);
146 return u;
147}
148
149soc_word_t hw_read16(lua_State *state, soc_addr_t addr)
150{
151 uint16_t u;
152 if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
153 luaL_error(state, "fail to read16 @ %p", addr);
154 return u;
155}
156
157soc_word_t hw_read32(lua_State *state, soc_addr_t addr)
158{
159 uint32_t u;
160 if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
161 luaL_error(state, "fail to read32 @ %p", addr);
162 return u;
163}
164
165void hw_write8(lua_State *state, soc_addr_t addr, soc_word_t val)
166{
167 uint8_t u = val;
168 if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
169 luaL_error(state, "fail to write8 @ %p", addr);
170}
171
172void hw_write16(lua_State *state, soc_addr_t addr, soc_word_t val)
173{
174 uint16_t u = val;
175 if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
176 luaL_error(state, "fail to write16 @ %p", addr);
177}
178
179void hw_write32(lua_State *state, soc_addr_t addr, soc_word_t val)
180{
181 uint32_t u = val;
182 if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
183 luaL_error(state, "fail to write32 @ %p", addr);
184}
185
186int my_lua_readn(lua_State *state)
187{
188 hw_readn_fn_t fn = (hw_readn_fn_t)lua_touserdata(state, lua_upvalueindex(1));
189 int n = lua_gettop(state);
190 if(n != 1)
191 luaL_error(state, "readn takes a single argument");
192 lua_pushunsigned(state, fn(state, luaL_checkunsigned(state, 1)));
193 return 1;
194}
195
196int my_lua_writen(lua_State *state)
197{
198 hw_writen_fn_t fn = (hw_writen_fn_t)lua_touserdata(state, lua_upvalueindex(1));
199 int n = lua_gettop(state);
200 if(n != 2)
201 luaL_error(state, "writen takes two arguments");
202 fn(state, luaL_checkunsigned(state, 1), luaL_checkunsigned(state, 2));
203 return 0;
204}
205
206int my_lua_printlog(lua_State *state)
207{
208 print_log(&g_hwdev);
209 return 0;
210}
211
212bool my_lua_import_hwstub()
213{
214 int oldtop = lua_gettop(g_lua);
215
216 lua_newtable(g_lua); // hwstub
217
218 lua_newtable(g_lua); // options
219 lua_pushboolean(g_lua, g_quiet);
220 lua_setfield(g_lua, -2, "quiet");
221 lua_setfield(g_lua, -2, "options");
222
223 lua_newtable(g_lua); // dev
224 lua_newtable(g_lua); // version
225 lua_pushinteger(g_lua, g_hwdev_ver.major);
226 lua_setfield(g_lua, -2, "major");
227 lua_pushinteger(g_lua, g_hwdev_ver.minor);
228 lua_setfield(g_lua, -2, "minor");
229 lua_pushinteger(g_lua, g_hwdev_ver.revision);
230 lua_setfield(g_lua, -2, "revision");
231 lua_setfield(g_lua, -2, "version");
232
233 lua_newtable(g_lua); // layout
234 lua_newtable(g_lua); // ocram
235 lua_newtable(g_lua); // code
236 lua_pushinteger(g_lua, g_hwdev_layout.oc_code_start);
237 lua_setfield(g_lua, -2, "start");
238 lua_pushinteger(g_lua, g_hwdev_layout.oc_code_size);
239 lua_setfield(g_lua, -2, "size");
240 lua_setfield(g_lua, -2, "code");
241 lua_newtable(g_lua); // stack
242 lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_start);
243 lua_setfield(g_lua, -2, "start");
244 lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_size);
245 lua_setfield(g_lua, -2, "size");
246 lua_setfield(g_lua, -2, "stack");
247 lua_newtable(g_lua); // buffer
248 lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_start);
249 lua_setfield(g_lua, -2, "start");
250 lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_size);
251 lua_setfield(g_lua, -2, "size");
252 lua_setfield(g_lua, -2, "buffer");
253 lua_setfield(g_lua, -2, "ocram");
254 lua_setfield(g_lua, -2, "layout");
255
256 lua_newtable(g_lua); // stmp
257 lua_pushinteger(g_lua, g_hwdev_stmp.chipid);
258 lua_setfield(g_lua, -2, "chipid");
259 lua_pushinteger(g_lua, g_hwdev_stmp.rev);
260 lua_setfield(g_lua, -2, "rev");
261 lua_setfield(g_lua, -2, "stmp");
262
263 lua_newtable(g_lua); // features
264 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG));
265 lua_setfield(g_lua, -2, "log");
266 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_MEM));
267 lua_setfield(g_lua, -2, "mem");
268 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_CALL));
269 lua_setfield(g_lua, -2, "call");
270 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_JUMP));
271 lua_setfield(g_lua, -2, "jump");
272 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_AES_OTP));
273 lua_setfield(g_lua, -2, "aes_otp");
274 lua_setfield(g_lua, -2, "features");
275
276 lua_pushlightuserdata(g_lua, (void *)&hw_read8);
277 lua_pushcclosure(g_lua, my_lua_readn, 1);
278 lua_setfield(g_lua, -2, "read8");
279 lua_pushlightuserdata(g_lua, (void *)&hw_read16);
280 lua_pushcclosure(g_lua, my_lua_readn, 1);
281 lua_setfield(g_lua, -2, "read16");
282 lua_pushlightuserdata(g_lua, (void *)&hw_read32);
283 lua_pushcclosure(g_lua, my_lua_readn, 1);
284 lua_setfield(g_lua, -2, "read32");
285
286 lua_pushlightuserdata(g_lua, (void *)&hw_write8);
287 lua_pushcclosure(g_lua, my_lua_writen, 1);
288 lua_setfield(g_lua, -2, "write8");
289 lua_pushlightuserdata(g_lua, (void *)&hw_write16);
290 lua_pushcclosure(g_lua, my_lua_writen, 1);
291 lua_setfield(g_lua, -2, "write16");
292 lua_pushlightuserdata(g_lua, (void *)&hw_write32);
293 lua_pushcclosure(g_lua, my_lua_writen, 1);
294 lua_setfield(g_lua, -2, "write32");
295 lua_pushcclosure(g_lua, my_lua_printlog, 0);
296 lua_setfield(g_lua, -2, "print_log");
297
298 lua_setfield(g_lua, -2, "dev");
299
300 lua_newtable(g_lua); // host
301 lua_newtable(g_lua); // version
302 lua_pushinteger(g_lua, HWSTUB_VERSION_MAJOR);
303 lua_setfield(g_lua, -2, "major");
304 lua_pushinteger(g_lua, HWSTUB_VERSION_MINOR);
305 lua_setfield(g_lua, -2, "minor");
306 lua_pushinteger(g_lua, HWSTUB_VERSION_REV);
307 lua_setfield(g_lua, -2, "revision");
308 lua_setfield(g_lua, -2, "version");
309 lua_setfield(g_lua, -2, "host");
310
311 lua_newtable(g_lua); // soc
312 lua_setfield(g_lua, -2, "soc");
313
314 lua_newtable(g_lua); // help
315 lua_pushinteger(g_lua, 1);
316 lua_pushstring(g_lua, "This is the help for hwstub_tool. This tools uses Lua to interpret commands.");
317 lua_settable(g_lua, -3);
318 lua_pushinteger(g_lua, 2);
319 lua_pushstring(g_lua, "You can get help by running help(). Help is organised in topics and subtopics and so on.");
320 lua_settable(g_lua, -3);
321 lua_pushinteger(g_lua, 3);
322 lua_pushstring(g_lua, "If you want to access the help of topic x, subtopic y, subsubtopic z, type help(x,y,z).");
323 lua_settable(g_lua, -3);
324 lua_pushinteger(g_lua, 4);
325 lua_pushstring(g_lua, "Example: help(\"hwstub\").");
326 lua_settable(g_lua, -3);
327 lua_setfield(g_lua, -2, "help");
328
329 lua_setglobal(g_lua, "hwstub");
330
331 lua_pushcfunction(g_lua, my_lua_help);
332 lua_setglobal(g_lua, "help");
333
334 if(lua_gettop(g_lua) != oldtop)
335 {
336 printf("internal error: unbalanced my_lua_import_soc");
337 return false;
338 }
339 return true;
340}
341
342int my_lua_read_reg(lua_State *state)
343{
344 int n = lua_gettop(state);
345 if(n != 0)
346 luaL_error(state, "read() takes no argument");
347 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
348 lua_pushunsigned(state, hw_read32(state, addr));
349 return 1;
350}
351
352int my_lua_write_reg(lua_State *state)
353{
354 int n = lua_gettop(state);
355 if(n != 1)
356 luaL_error(state, "write() takes one argument");
357 soc_word_t val = luaL_checkunsigned(state, 1);
358 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
359 hw_write32(state, addr, val);
360 return 0;
361}
362
363int my_lua_read_field(lua_State *state)
364{
365 int n = lua_gettop(state);
366 if(n != 0)
367 luaL_error(state, "read() takes no argument");
368 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
369 soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2));
370 soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3));
371 lua_pushunsigned(state, (hw_read32(state, addr) >> shift) & mask);
372 return 1;
373}
374
375int my_lua_write_field(lua_State *state)
376{
377 int n = lua_gettop(state);
378 if(n != 0 && n!= 1)
379 luaL_error(state, "write() takes one or no argument");
380 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
381 soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2));
382 soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3));
383 bool is_sct = lua_toboolean(state, lua_upvalueindex(5));
384
385 soc_word_t value = mask;
386 if(n == 1)
387 {
388 if(!lua_isnumber(state, 1) && lua_isstring(state, 1))
389 {
390 lua_pushvalue(state, lua_upvalueindex(4));
391 lua_pushvalue(state, 1);
392 lua_gettable(state, -2);
393 if(lua_isnil(state, -1))
394 luaL_error(state, "field has no value %s", lua_tostring(state, 1));
395 value = luaL_checkunsigned(state, -1);
396 lua_pop(state, 2);
397 }
398 else
399 value = luaL_checkunsigned(state, 1);
400 value &= mask;
401 }
402
403 if(!is_sct)
404 value = value << shift | (hw_read32(state, addr) & ~(mask << shift));
405 else
406 value <<= shift;
407
408 hw_write32(state, addr, value);
409 return 0;
410}
411
412void my_lua_create_field(soc_addr_t addr, const soc_reg_field_t& field, bool sct)
413{
414 lua_newtable(g_lua);
415
416 lua_pushstring(g_lua, field.name.c_str());
417 lua_setfield(g_lua, -2, "name");
418
419 lua_pushunsigned(g_lua, addr);
420 lua_setfield(g_lua, -2, "addr");
421
422 lua_pushboolean(g_lua, sct);
423 lua_setfield(g_lua, -2, "sct");
424
425 lua_pushunsigned(g_lua, field.first_bit);
426 lua_setfield(g_lua, -2, "first_bit");
427
428 lua_pushunsigned(g_lua, field.last_bit);
429 lua_setfield(g_lua, -2, "last_bit");
430
431 lua_pushunsigned(g_lua, field.bitmask());
432 lua_setfield(g_lua, -2, "bitmask");
433
434 soc_word_t local_bitmask = field.bitmask() >> field.first_bit;
435 lua_pushunsigned(g_lua, local_bitmask);
436 lua_setfield(g_lua, -2, "local_bitmask");
437
438 lua_pushunsigned(g_lua, addr);
439 lua_pushunsigned(g_lua, field.first_bit);
440 lua_pushunsigned(g_lua, local_bitmask);
441 lua_pushcclosure(g_lua, my_lua_read_field, 3);
442 lua_setfield(g_lua, -2, "read");
443
444 lua_pushunsigned(g_lua, addr);
445 lua_pushunsigned(g_lua, field.first_bit);
446 lua_pushunsigned(g_lua, local_bitmask);
447 lua_pushvalue(g_lua, -4);
448 lua_pushboolean(g_lua, false);
449 lua_pushcclosure(g_lua, my_lua_write_field, 5);
450 lua_setfield(g_lua, -2, "write");
451
452 if(sct)
453 {
454 lua_pushunsigned(g_lua, addr + 4);
455 lua_pushunsigned(g_lua, field.first_bit);
456 lua_pushunsigned(g_lua, local_bitmask);
457 lua_pushvalue(g_lua, -4);
458 lua_pushboolean(g_lua, true);
459 lua_pushcclosure(g_lua, my_lua_write_field, 5);
460 lua_setfield(g_lua, -2, "set");
461
462 lua_pushunsigned(g_lua, addr + 8);
463 lua_pushunsigned(g_lua, field.first_bit);
464 lua_pushunsigned(g_lua, local_bitmask);
465 lua_pushvalue(g_lua, -4);
466 lua_pushboolean(g_lua, true);
467 lua_pushcclosure(g_lua, my_lua_write_field, 5);
468 lua_setfield(g_lua, -2, "clr");
469
470 lua_pushunsigned(g_lua, addr + 12);
471 lua_pushunsigned(g_lua, field.first_bit);
472 lua_pushunsigned(g_lua, local_bitmask);
473 lua_pushvalue(g_lua, -4);
474 lua_pushboolean(g_lua, true);
475 lua_pushcclosure(g_lua, my_lua_write_field, 5);
476 lua_setfield(g_lua, -2, "tog");
477 }
478
479 for(size_t i = 0; i < field.value.size(); i++)
480 {
481 lua_pushunsigned(g_lua, field.value[i].value);
482 lua_setfield(g_lua, -2, field.value[i].name.c_str());
483 }
484}
485
486void my_lua_create_reg(soc_addr_t addr, size_t index, const soc_reg_t& reg)
487{
488 lua_newtable(g_lua);
489
490 lua_pushstring(g_lua, reg.addr[index].name.c_str());
491 lua_setfield(g_lua, -2, "name");
492
493 lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
494 lua_setfield(g_lua, -2, "addr");
495
496 lua_pushboolean(g_lua, !!(reg.flags & REG_HAS_SCT));
497 lua_setfield(g_lua, -2, "sct");
498
499 lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
500 lua_pushcclosure(g_lua, my_lua_read_reg, 1);
501 lua_setfield(g_lua, -2, "read");
502
503 lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
504 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
505 lua_setfield(g_lua, -2, "write");
506
507 if(reg.flags & REG_HAS_SCT)
508 {
509 lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 4);
510 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
511 lua_setfield(g_lua, -2, "set");
512
513 lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 8);
514 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
515 lua_setfield(g_lua, -2, "clr");
516
517 lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 12);
518 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
519 lua_setfield(g_lua, -2, "tog");
520 }
521
522 for(size_t i = 0; i < reg.field.size(); i++)
523 {
524 my_lua_create_field(addr + reg.addr[index].addr, reg.field[i],
525 reg.flags & REG_HAS_SCT);
526 lua_setfield(g_lua, -2, reg.field[i].name.c_str());
527 }
528}
529
530void my_lua_create_dev(size_t index, const soc_dev_t& dev)
531{
532 lua_newtable(g_lua);
533
534 lua_pushstring(g_lua, dev.addr[index].name.c_str());
535 lua_setfield(g_lua, -2, "name");
536
537 lua_pushunsigned(g_lua, dev.addr[index].addr);
538 lua_setfield(g_lua, -2, "addr");
539
540 for(size_t i = 0; i < dev.reg.size(); i++)
541 {
542 bool table = dev.reg[i].addr.size() > 1;
543 if(table)
544 lua_newtable(g_lua);
545 else
546 lua_pushnil(g_lua);
547
548 for(size_t k = 0; k < dev.reg[i].addr.size(); k++)
549 {
550 my_lua_create_reg(dev.addr[index].addr, k, dev.reg[i]);
551 if(table)
552 {
553 lua_pushinteger(g_lua, k);
554 lua_pushvalue(g_lua, -2);
555 lua_settable(g_lua, -4);
556 }
557 lua_setfield(g_lua, -3, dev.reg[i].addr[k].name.c_str());
558 }
559
560 if(table)
561 lua_setfield(g_lua, -2, dev.reg[i].name.c_str());
562 else
563 lua_pop(g_lua, 1);
564 }
565}
566
567bool my_lua_import_soc(const soc_t& soc)
568{
569 int oldtop = lua_gettop(g_lua);
570
571 lua_getglobal(g_lua, "hwstub");
572 lua_getfield(g_lua, -1, "soc");
573
574 lua_newtable(g_lua);
575
576 lua_pushstring(g_lua, soc.name.c_str());
577 lua_setfield(g_lua, -2, "name");
578
579 lua_pushstring(g_lua, soc.desc.c_str());
580 lua_setfield(g_lua, -2, "desc");
581
582 for(size_t i = 0; i < soc.dev.size(); i++)
583 {
584 bool table = soc.dev[i].addr.size() > 1;
585 if(table)
586 lua_newtable(g_lua);
587 else
588 lua_pushnil(g_lua);
589
590 for(size_t k = 0; k < soc.dev[i].addr.size(); k++)
591 {
592 my_lua_create_dev(k, soc.dev[i]);
593 if(table)
594 {
595 lua_pushinteger(g_lua, k + 1);
596 lua_pushvalue(g_lua, -2);
597 lua_settable(g_lua, -4);
598 }
599 lua_setfield(g_lua, -3, soc.dev[i].addr[k].name.c_str());
600 }
601
602 if(table)
603 lua_setfield(g_lua, -2, soc.dev[i].name.c_str());
604 else
605 lua_pop(g_lua, 1);
606 }
607
608 lua_setfield(g_lua, -2, soc.name.c_str());
609
610 lua_pop(g_lua, 2);
611
612 if(lua_gettop(g_lua) != oldtop)
613 {
614 printf("internal error: unbalanced my_lua_import_soc\n");
615 return false;
616 }
617 return true;
618}
619
620bool my_lua_import_soc(const std::vector< soc_t >& socs)
621{
622 for(size_t i = 0; i < socs.size(); i++)
623 {
624 if(!g_quiet)
625 printf("importing %s...\n", socs[i].name.c_str());
626 if(!my_lua_import_soc(socs[i]))
627 return false;
628 }
629 return true;
630}
631
632/**
633 * glue
634 */
635
636void usage(void)
637{
638 printf("hwstub_tool, compiled with hwstub %d.%d.%d\n",
639 HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
640 printf("\n");
641 printf("usage: hwstub_tool [options] <soc desc files>\n");
642 printf("options:\n");
643 printf(" --help/-?\tDisplay this help\n");
644 printf(" --quiet/-q\tQuiet non-command messages\n");
645 printf(" -i <init>\tSet lua init file (default is init.lua)\n");
646 exit(1);
647}
648
649int main(int argc, char **argv)
650{
651 const char *lua_init = "init.lua";
652 // parse command line
653 while(1)
654 {
655 static struct option long_options[] =
656 {
657 {"help", no_argument, 0, '?'},
658 {"quiet", no_argument, 0, 'q'},
659 {0, 0, 0, 0}
660 };
661
662 int c = getopt_long(argc, argv, "?qi:", long_options, NULL);
663 if(c == -1)
664 break;
665 switch(c)
666 {
667 case -1:
668 break;
669 case 'q':
670 g_quiet = true;
671 break;
672 case '?':
673 usage();
674 break;
675 case 'i':
676 lua_init = optarg;
677 break;
678 default:
679 abort();
680 }
681 }
682
683 // load register descriptions
684 std::vector< soc_t > socs;
685 for(int i = optind; i < argc; i++)
686 if(!soc_desc_parse_xml(argv[i], socs))
687 {
688 printf("Cannot load description '%s'\n", argv[i]);
689 return 2;
690 }
691
692 // create usb context
693 libusb_context *ctx;
694 libusb_init(&ctx);
695 libusb_set_debug(ctx, 3);
696
697 // look for device
698 if(!g_quiet)
699 printf("Looking for device %#04x:%#04x...\n", HWSTUB_USB_VID, HWSTUB_USB_PID);
700
701 libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
702 HWSTUB_USB_VID, HWSTUB_USB_PID);
703 if(handle == NULL)
704 {
705 printf("No device found\n");
706 return 1;
707 }
708
709 // admin stuff
710 libusb_device *mydev = libusb_get_device(handle);
711 if(!g_quiet)
712 {
713 printf("device found at %d:%d\n",
714 libusb_get_bus_number(mydev),
715 libusb_get_device_address(mydev));
716 }
717 g_hwdev.handle = handle;
718 if(hwstub_probe(&g_hwdev))
719 {
720 printf("Cannot probe device!\n");
721 return 1;
722 }
723
724 // get hwstub information
725 int ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver));
726 if(ret != sizeof(g_hwdev_ver))
727 {
728 printf("Cannot get version!\n");
729 goto Lerr;
730 }
731 if(g_hwdev_ver.major != HWSTUB_VERSION_MAJOR || g_hwdev_ver.minor < HWSTUB_VERSION_MINOR)
732 {
733 printf("Warning: this tool is possibly incompatible with your device:\n");
734 printf("Device version: %d.%d.%d\n", g_hwdev_ver.major, g_hwdev_ver.minor, g_hwdev_ver.revision);
735 printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
736 }
737
738 // get memory layout information
739 ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout));
740 if(ret != sizeof(g_hwdev_layout))
741 {
742 printf("Cannot get layout: %d\n", ret);
743 goto Lerr;
744 }
745
746 // get features
747 ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_FEATURES, &g_hwdev_features, sizeof(g_hwdev_features));
748 if(ret != sizeof(g_hwdev_features))
749 {
750 printf("Cannot get features: %d\n", ret);
751 goto Lerr;
752 }
753
754 // get STMP specific information
755 ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp));
756 if(ret != sizeof(g_hwdev_stmp))
757 {
758 printf("Cannot get stmp: %d\n", ret);
759 goto Lerr;
760 }
761
762 // dump ROM
763 if(!g_quiet)
764 {
765 void *rom = malloc(64 * 1024);
766 ret = hwstub_rw_mem(&g_hwdev, 1, 0xc0000000, rom, 64 * 1024);
767 if(ret != 64 * 1024)
768 {
769 printf("Cannot read ROM: %d\n", ret);
770 goto Lerr;
771 }
772
773 printf("ROM successfully read!\n");
774 FILE *f = fopen("rom.bin", "wb");
775 fwrite(rom, 64 * 1024, 1, f);
776 fclose(f);
777 }
778
779 // test DCP
780#if 0
781 if(!g_quiet)
782 {
783 struct
784 {
785 uint8_t iv[16];
786 uint8_t data[16];
787 } __attribute__((packed)) dcp_test;
788
789 for(int i = 0; i < 16; i++)
790 dcp_test.iv[i] = rand();
791 for(int i = 0; i < 16; i++)
792 dcp_test.data[i] = rand();
793 printf("DCP\n");
794 printf(" IN\n");
795 printf(" IV:");
796 for(int i = 0; i < 16; i++)
797 printf(" %02x", dcp_test.iv[i]);
798 printf("\n");
799 printf(" IV:");
800 for(int i = 0; i < 16; i++)
801 printf(" %02x", dcp_test.data[i]);
802 printf("\n");
803
804 if(!hwstub_aes_otp(&g_hwdev, &dcp_test, sizeof(dcp_test), HWSTUB_AES_OTP_ENCRYPT))
805 {
806 printf(" OUT\n");
807 printf(" IV:");
808 for(int i = 0; i < 16; i++)
809 printf(" %02x", dcp_test.iv[i]);
810 printf("\n");
811 printf(" IV:");
812 for(int i = 0; i < 16; i++)
813 printf(" %02x", dcp_test.data[i]);
814 printf("\n");
815 }
816 else
817 printf("DCP error!\n");
818 }
819#endif
820
821 /** Init lua */
822
823 // create lua state
824 g_lua = luaL_newstate();
825 if(g_lua == NULL)
826 {
827 printf("Cannot create lua state\n");
828 return 1;
829 }
830 // import hwstub
831 if(!my_lua_import_hwstub())
832 printf("Cannot import hwstub description into Lua context\n");
833 // open all standard libraires
834 luaL_openlibs(g_lua);
835 // import socs
836 if(!my_lua_import_soc(socs))
837 printf("Cannot import SoC descriptions into Lua context\n");
838
839 if(luaL_dofile(g_lua, lua_init))
840 printf("error in init: %s\n", lua_tostring(g_lua, -1));
841 lua_pop(g_lua, lua_gettop(g_lua));
842
843 /** start interactive mode */
844 if(!g_quiet)
845 printf("Starting interactive lua session. Type 'help()' to get some help\n");
846
847 // use readline to provide some history and completion
848 rl_bind_key('\t', rl_complete);
849 while(1)
850 {
851 char *input = readline("> ");
852 if(!input)
853 break;
854 add_history(input);
855 // evaluate string
856 if(luaL_dostring(g_lua, input))
857 printf("error: %s\n", lua_tostring(g_lua, -1));
858 // pop everything to start from a clean stack
859 lua_pop(g_lua, lua_gettop(g_lua));
860 free(input);
861 }
862
863 Lerr:
864 // display log if handled
865 if(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)
866 {
867 if(!g_quiet)
868 printf("Device log:\n");
869 print_log(&g_hwdev);
870 }
871 hwstub_release(&g_hwdev);
872 return 1;
873}