/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2012 by Amaury Pouly * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "hwstub.h" #include #include #include #include #include #include #include #include #include "soc_desc.hpp" #if LUA_VERSION_NUM < 502 #warning You need at least lua 5.2 #endif /** * Global variables */ bool g_quiet = false; bool g_exit = false; struct hwstub_device_t g_hwdev; struct usb_resp_info_version_t g_hwdev_ver; struct usb_resp_info_layout_t g_hwdev_layout; struct usb_resp_info_features_t g_hwdev_features; struct usb_resp_info_target_t g_hwdev_target; struct usb_resp_info_stmp_t g_hwdev_stmp; lua_State *g_lua; /** * hw specific */ void print_log(struct hwstub_device_t *hwdev) { do { char buffer[128]; int length = hwstub_get_log(hwdev, buffer, sizeof(buffer) - 1); if(length <= 0) break; buffer[length] = 0; printf("%s", buffer); }while(1); } /** * Lua specific */ int my_lua_help(lua_State *state) { bool has_sub = false; // implement help() in C so that we do not rely on the init to implement it // help can take optional arguments int n = lua_gettop(state); lua_getglobal(state, "hwstub"); if(!lua_istable(state, -1)) goto Lerr; lua_getfield(state, -1, "help"); if(!lua_istable(state, -1)) goto Lerr; for(int i = 1; i <= n; i++) { lua_pushvalue(state, i); lua_gettable(state, -2); if(lua_isnil(state, -1)) { printf("I don't know subtopic '%s'!\n", lua_tostring(state, i)); return 0; } if(!lua_istable(state, -1)) { printf("Subtopic '%s' is not a table!\n", lua_tostring(state, i)); return 0; } } printf("================[ HELP "); for(int i = 1; i <= n; i++) printf("> %s ", lua_tostring(state, i)); printf("]================\n"); lua_pushnil(state); while(lua_next(state, -2)) { // key is at -2 and value at -1 if(lua_isstring(state, -1)) printf("%s\n", lua_tostring(state, -1)); else if(lua_istable(state, -1)) has_sub = true; // pop value but keep key lua_pop(state, 1); } if(has_sub) { printf("\n"); printf("You can get more information on the following subtopics:\n"); lua_pushnil(state); while(lua_next(state, -2)) { // key is at -2 and value at -1 if(lua_istable(state, -1)) printf("* %s\n", lua_tostring(state, -2)); // pop value but keep key lua_pop(state, 1); } } printf("================[ STOP ]================\n"); return 0; Lerr: printf("There is a problem with the Lua context. Help is expected to be in hwstub.help\n"); printf("You must have messed badly the environment.\n"); return 0; } typedef soc_word_t (*hw_readn_fn_t)(lua_State *state, soc_addr_t addr); typedef void (*hw_writen_fn_t)(lua_State *state, soc_addr_t addr, soc_word_t val); soc_word_t hw_read8(lua_State *state, soc_addr_t addr) { uint8_t u; if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to read8 @ %p", addr); return u; } soc_word_t hw_read16(lua_State *state, soc_addr_t addr) { uint16_t u; if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to read16 @ %p", addr); return u; } soc_word_t hw_read32(lua_State *state, soc_addr_t addr) { uint32_t u; if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to read32 @ %p", addr); return u; } void hw_write8(lua_State *state, soc_addr_t addr, soc_word_t val) { uint8_t u = val; if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to write8 @ %p", addr); } void hw_write16(lua_State *state, soc_addr_t addr, soc_word_t val) { uint16_t u = val; if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to write16 @ %p", addr); } void hw_write32(lua_State *state, soc_addr_t addr, soc_word_t val) { uint32_t u = val; if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to write32 @ %p", addr); } int my_lua_readn(lua_State *state) { hw_readn_fn_t fn = (hw_readn_fn_t)lua_touserdata(state, lua_upvalueindex(1)); int n = lua_gettop(state); if(n != 1) luaL_error(state, "readn takes a single argument"); lua_pushunsigned(state, fn(state, luaL_checkunsigned(state, 1))); return 1; } int my_lua_writen(lua_State *state) { hw_writen_fn_t fn = (hw_writen_fn_t)lua_touserdata(state, lua_upvalueindex(1)); int n = lua_gettop(state); if(n != 2) luaL_error(state, "writen takes two arguments"); fn(state, luaL_checkunsigned(state, 1), luaL_checkunsigned(state, 2)); return 0; } int my_lua_printlog(lua_State *state) { print_log(&g_hwdev); return 0; } int my_lua_atexit(lua_State *state) { int n = lua_gettop(state); if(n != 1) luaL_error(state, "atexit takes one argument"); const char *arg = luaL_checkstring(state, 1); int ret = -1; if(strcmp(arg, "nop") == 0) ret = hwstub_atexit(&g_hwdev, HWSTUB_ATEXIT_NOP); else if(strcmp(arg, "reboot") == 0) ret = hwstub_atexit(&g_hwdev, HWSTUB_ATEXIT_REBOOT); else if(strcmp(arg, "off") == 0) ret = hwstub_atexit(&g_hwdev, HWSTUB_ATEXIT_OFF); else luaL_error(state, "unknown atexit method '%s'", arg); if(ret < 0) luaL_error(state, "fail to set atexit method"); return 0; } int my_lua_exit(lua_State *state) { if(hwstub_exit(&g_hwdev) < 0) luaL_error(state, "fail to exit hwstub"); return 0; } int my_lua_quit(lua_State *state) { g_exit = true; return 0; } bool my_lua_import_hwstub() { int oldtop = lua_gettop(g_lua); lua_newtable(g_lua); // hwstub lua_newtable(g_lua); // options lua_pushboolean(g_lua, g_quiet); lua_setfield(g_lua, -2, "quiet"); lua_setfield(g_lua, -2, "options"); lua_newtable(g_lua); // dev lua_newtable(g_lua); // version lua_pushinteger(g_lua, g_hwdev_ver.major); lua_setfield(g_lua, -2, "major"); lua_pushinteger(g_lua, g_hwdev_ver.minor); lua_setfield(g_lua, -2, "minor"); lua_pushinteger(g_lua, g_hwdev_ver.revision); lua_setfield(g_lua, -2, "revision"); lua_setfield(g_lua, -2, "version"); lua_newtable(g_lua); // layout lua_newtable(g_lua); // ocram lua_newtable(g_lua); // code lua_pushinteger(g_lua, g_hwdev_layout.oc_code_start); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.oc_code_size); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "code"); lua_newtable(g_lua); // stack lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_start); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_size); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "stack"); lua_newtable(g_lua); // buffer lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_start); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_size); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "buffer"); lua_setfield(g_lua, -2, "ocram"); lua_setfield(g_lua, -2, "layout"); lua_newtable(g_lua); // target lua_pushstring(g_lua, g_hwdev_target.name); lua_setfield(g_lua, -2, "name"); lua_pushinteger(g_lua, g_hwdev_target.id); lua_setfield(g_lua, -2, "id"); lua_setfield(g_lua, -2, "target"); if(g_hwdev_target.id == HWSTUB_TARGET_STMP) { lua_newtable(g_lua); // stmp lua_pushinteger(g_lua, g_hwdev_stmp.chipid); lua_setfield(g_lua, -2, "chipid"); lua_pushinteger(g_lua, g_hwdev_stmp.rev); lua_setfield(g_lua, -2, "rev"); lua_setfield(g_lua, -2, "stmp"); } lua_newtable(g_lua); // features lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)); lua_setfield(g_lua, -2, "log"); lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_MEM)); lua_setfield(g_lua, -2, "mem"); lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_CALL)); lua_setfield(g_lua, -2, "call"); lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_JUMP)); lua_setfield(g_lua, -2, "jump"); lua_setfield(g_lua, -2, "features"); lua_pushlightuserdata(g_lua, (void *)&hw_read8); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read8"); lua_pushlightuserdata(g_lua, (void *)&hw_read16); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read16"); lua_pushlightuserdata(g_lua, (void *)&hw_read32); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read32"); lua_pushlightuserdata(g_lua, (void *)&hw_write8); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write8"); lua_pushlightuserdata(g_lua, (void *)&hw_write16); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write16"); lua_pushlightuserdata(g_lua, (void *)&hw_write32); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write32"); lua_pushcclosure(g_lua, my_lua_printlog, 0); lua_setfield(g_lua, -2, "print_log"); lua_pushcclosure(g_lua, my_lua_atexit, 0); lua_setfield(g_lua, -2, "atexit"); lua_pushcclosure(g_lua, my_lua_exit, 0); lua_setfield(g_lua, -2, "exit"); lua_setfield(g_lua, -2, "dev"); lua_newtable(g_lua); // host lua_newtable(g_lua); // version lua_pushinteger(g_lua, HWSTUB_VERSION_MAJOR); lua_setfield(g_lua, -2, "major"); lua_pushinteger(g_lua, HWSTUB_VERSION_MINOR); lua_setfield(g_lua, -2, "minor"); lua_pushinteger(g_lua, HWSTUB_VERSION_REV); lua_setfield(g_lua, -2, "revision"); lua_setfield(g_lua, -2, "version"); lua_setfield(g_lua, -2, "host"); lua_newtable(g_lua); // soc lua_setfield(g_lua, -2, "soc"); lua_newtable(g_lua); // help lua_pushinteger(g_lua, 1); lua_pushstring(g_lua, "This is the help for hwstub_tool. This tools uses Lua to interpret commands."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 2); lua_pushstring(g_lua, "You can get help by running help(). Help is organised in topics and subtopics and so on."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 3); lua_pushstring(g_lua, "If you want to access the help of topic x, subtopic y, subsubtopic z, type help(x,y,z)."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 4); lua_pushstring(g_lua, "Example: help(\"hwstub\")."); lua_settable(g_lua, -3); lua_setfield(g_lua, -2, "help"); lua_setglobal(g_lua, "hwstub"); lua_pushcfunction(g_lua, my_lua_help); lua_setglobal(g_lua, "help"); lua_pushcfunction(g_lua, my_lua_quit); lua_setglobal(g_lua, "exit"); lua_pushcfunction(g_lua, my_lua_quit); lua_setglobal(g_lua, "quit"); if(lua_gettop(g_lua) != oldtop) { printf("internal error: unbalanced my_lua_import_soc"); return false; } return true; } int my_lua_read_reg(lua_State *state) { int n = lua_gettop(state); if(n != 0) luaL_error(state, "read() takes no argument"); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); lua_pushunsigned(state, hw_read32(state, addr)); return 1; } int my_lua_write_reg(lua_State *state) { int n = lua_gettop(state); if(n != 1) luaL_error(state, "write() takes one argument"); soc_word_t val = luaL_checkunsigned(state, 1); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); hw_write32(state, addr, val); return 0; } int my_lua_read_field(lua_State *state) { int n = lua_gettop(state); if(n != 0) luaL_error(state, "read() takes no argument"); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2)); soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3)); lua_pushunsigned(state, (hw_read32(state, addr) >> shift) & mask); return 1; } int my_lua_write_field(lua_State *state) { int n = lua_gettop(state); if(n != 0 && n!= 1) luaL_error(state, "write() takes one or no argument"); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2)); soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3)); bool is_sct = lua_toboolean(state, lua_upvalueindex(5)); soc_word_t value = mask; if(n == 1) { if(!lua_isnumber(state, 1) && lua_isstring(state, 1)) { lua_pushvalue(state, lua_upvalueindex(4)); lua_pushvalue(state, 1); lua_gettable(state, -2); if(lua_isnil(state, -1)) luaL_error(state, "field has no value %s", lua_tostring(state, 1)); value = luaL_checkunsigned(state, -1); lua_pop(state, 2); } else value = luaL_checkunsigned(state, 1); value &= mask; } if(!is_sct) value = value << shift | (hw_read32(state, addr) & ~(mask << shift)); else value <<= shift; hw_write32(state, addr, value); return 0; } void my_lua_create_field(soc_addr_t addr, const soc_reg_field_t& field, bool sct) { lua_newtable(g_lua); lua_pushstring(g_lua, field.name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushunsigned(g_lua, addr); lua_setfield(g_lua, -2, "addr"); lua_pushboolean(g_lua, sct); lua_setfield(g_lua, -2, "sct"); lua_pushunsigned(g_lua, field.first_bit); lua_setfield(g_lua, -2, "first_bit"); lua_pushunsigned(g_lua, field.last_bit); lua_setfield(g_lua, -2, "last_bit"); lua_pushunsigned(g_lua, field.bitmask()); lua_setfield(g_lua, -2, "bitmask"); soc_word_t local_bitmask = field.bitmask() >> field.first_bit; lua_pushunsigned(g_lua, local_bitmask); lua_setfield(g_lua, -2, "local_bitmask"); lua_pushunsigned(g_lua, addr); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushcclosure(g_lua, my_lua_read_field, 3); lua_setfield(g_lua, -2, "read"); lua_pushunsigned(g_lua, addr); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, false); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "write"); if(sct) { lua_pushunsigned(g_lua, addr + 4); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, true); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "set"); lua_pushunsigned(g_lua, addr + 8); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, true); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "clr"); lua_pushunsigned(g_lua, addr + 12); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, true); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "tog"); } for(size_t i = 0; i < field.value.size(); i++) { lua_pushunsigned(g_lua, field.value[i].value); lua_setfield(g_lua, -2, field.value[i].name.c_str()); } } void my_lua_create_reg(soc_addr_t addr, size_t index, const soc_reg_t& reg) { lua_newtable(g_lua); lua_pushstring(g_lua, reg.addr[index].name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_setfield(g_lua, -2, "addr"); lua_pushboolean(g_lua, !!(reg.flags & REG_HAS_SCT)); lua_setfield(g_lua, -2, "sct"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_pushcclosure(g_lua, my_lua_read_reg, 1); lua_setfield(g_lua, -2, "read"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "write"); if(reg.flags & REG_HAS_SCT) { lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 4); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "set"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 8); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "clr"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 12); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "tog"); } for(size_t i = 0; i < reg.field.size(); i++) { my_lua_create_field(addr + reg.addr[index].addr, reg.field[i], reg.flags & REG_HAS_SCT); lua_setfield(g_lua, -2, reg.field[i].name.c_str()); } } void my_lua_create_dev(size_t index, const soc_dev_t& dev) { lua_newtable(g_lua); lua_pushstring(g_lua, dev.addr[index].name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushunsigned(g_lua, dev.addr[index].addr); lua_setfield(g_lua, -2, "addr"); for(size_t i = 0; i < dev.reg.size(); i++) { bool table = dev.reg[i].addr.size() > 1; if(table) lua_newtable(g_lua); else lua_pushnil(g_lua); for(size_t k = 0; k < dev.reg[i].addr.size(); k++) { my_lua_create_reg(dev.addr[index].addr, k, dev.reg[i]); if(table) { lua_pushinteger(g_lua, k); lua_pushvalue(g_lua, -2); lua_settable(g_lua, -4); } lua_setfield(g_lua, -3, dev.reg[i].addr[k].name.c_str()); } if(table) lua_setfield(g_lua, -2, dev.reg[i].name.c_str()); else lua_pop(g_lua, 1); } } bool my_lua_import_soc(const soc_t& soc) { int oldtop = lua_gettop(g_lua); lua_getglobal(g_lua, "hwstub"); lua_getfield(g_lua, -1, "soc"); lua_newtable(g_lua); lua_pushstring(g_lua, soc.name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushstring(g_lua, soc.desc.c_str()); lua_setfield(g_lua, -2, "desc"); for(size_t i = 0; i < soc.dev.size(); i++) { bool table = soc.dev[i].addr.size() > 1; if(table) lua_newtable(g_lua); else lua_pushnil(g_lua); for(size_t k = 0; k < soc.dev[i].addr.size(); k++) { my_lua_create_dev(k, soc.dev[i]); if(table) { lua_pushinteger(g_lua, k + 1); lua_pushvalue(g_lua, -2); lua_settable(g_lua, -4); } lua_setfield(g_lua, -3, soc.dev[i].addr[k].name.c_str()); } if(table) lua_setfield(g_lua, -2, soc.dev[i].name.c_str()); else lua_pop(g_lua, 1); } lua_setfield(g_lua, -2, soc.name.c_str()); lua_pop(g_lua, 2); if(lua_gettop(g_lua) != oldtop) { printf("internal error: unbalanced my_lua_import_soc\n"); return false; } return true; } bool my_lua_import_soc(const std::vector< soc_t >& socs) { for(size_t i = 0; i < socs.size(); i++) { if(!g_quiet) printf("importing %s...\n", socs[i].name.c_str()); if(!my_lua_import_soc(socs[i])) return false; } return true; } /** * glue */ void usage(void) { printf("hwstub_tool, compiled with hwstub %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV); printf("\n"); printf("usage: hwstub_tool [options] \n"); printf("options:\n"); printf(" --help/-?\tDisplay this help\n"); printf(" --quiet/-q\tQuiet non-command messages\n"); printf(" -i \tSet lua init file (default is init.lua)\n"); exit(1); } int main(int argc, char **argv) { const char *lua_init = "init.lua"; // parse command line while(1) { static struct option long_options[] = { {"help", no_argument, 0, '?'}, {"quiet", no_argument, 0, 'q'}, {0, 0, 0, 0} }; int c = getopt_long(argc, argv, "?qi:", long_options, NULL); if(c == -1) break; switch(c) { case -1: break; case 'q': g_quiet = true; break; case '?': usage(); break; case 'i': lua_init = optarg; break; default: abort(); } } // load register descriptions std::vector< soc_t > socs; for(int i = optind; i < argc; i++) if(!soc_desc_parse_xml(argv[i], socs)) { printf("Cannot load description '%s'\n", argv[i]); return 2; } // create usb context libusb_context *ctx; libusb_init(&ctx); libusb_set_debug(ctx, 3); // look for device if(!g_quiet) printf("Looking for device %#04x:%#04x...\n", HWSTUB_USB_VID, HWSTUB_USB_PID); libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx, HWSTUB_USB_VID, HWSTUB_USB_PID); if(handle == NULL) { printf("No device found\n"); return 1; } // admin stuff libusb_device *mydev = libusb_get_device(handle); if(!g_quiet) { printf("device found at %d:%d\n", libusb_get_bus_number(mydev), libusb_get_device_address(mydev)); } g_hwdev.handle = handle; if(hwstub_probe(&g_hwdev)) { printf("Cannot probe device!\n"); return 1; } // get hwstub information int ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver)); if(ret != sizeof(g_hwdev_ver)) { printf("Cannot get version!\n"); goto Lerr; } if(g_hwdev_ver.major != HWSTUB_VERSION_MAJOR || g_hwdev_ver.minor < HWSTUB_VERSION_MINOR) { printf("Warning: this tool is possibly incompatible with your device:\n"); printf("Device version: %d.%d.%d\n", g_hwdev_ver.major, g_hwdev_ver.minor, g_hwdev_ver.revision); printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV); } // get memory layout information ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout)); if(ret != sizeof(g_hwdev_layout)) { printf("Cannot get layout: %d\n", ret); goto Lerr; } // get features ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_FEATURES, &g_hwdev_features, sizeof(g_hwdev_features)); if(ret != sizeof(g_hwdev_features)) { printf("Cannot get features: %d\n", ret); goto Lerr; } // get target ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_TARGET, &g_hwdev_target, sizeof(g_hwdev_target)); if(ret != sizeof(g_hwdev_target)) { printf("Cannot get target: %d\n", ret); goto Lerr; } // get STMP specific information if(g_hwdev_target.id == HWSTUB_TARGET_STMP) { ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp)); if(ret != sizeof(g_hwdev_stmp)) { printf("Cannot get stmp: %d\n", ret); goto Lerr; } } // dump ROM if(!g_quiet) { void *rom = malloc(64 * 1024); ret = hwstub_rw_mem(&g_hwdev, 1, 0xc0000000, rom, 64 * 1024); if(ret != 64 * 1024) { printf("Cannot read ROM: %d\n", ret); goto Lerr; } printf("ROM successfully read!\n"); FILE *f = fopen("rom.bin", "wb"); fwrite(rom, 64 * 1024, 1, f); fclose(f); } /** Init lua */ // create lua state g_lua = luaL_newstate(); if(g_lua == NULL) { printf("Cannot create lua state\n"); return 1; } // import hwstub if(!my_lua_import_hwstub()) printf("Cannot import hwstub description into Lua context\n"); // open all standard libraires luaL_openlibs(g_lua); // import socs if(!my_lua_import_soc(socs)) printf("Cannot import SoC descriptions into Lua context\n"); if(luaL_dofile(g_lua, lua_init)) printf("error in init: %s\n", lua_tostring(g_lua, -1)); lua_pop(g_lua, lua_gettop(g_lua)); /** start interactive mode */ if(!g_quiet) printf("Starting interactive lua session. Type 'help()' to get some help\n"); // use readline to provide some history and completion rl_bind_key('\t', rl_complete); while(!g_exit) { char *input = readline("> "); if(!input) break; add_history(input); // evaluate string if(luaL_dostring(g_lua, input)) printf("error: %s\n", lua_tostring(g_lua, -1)); // pop everything to start from a clean stack lua_pop(g_lua, lua_gettop(g_lua)); free(input); } Lerr: // display log if handled if(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG) { if(!g_quiet) printf("Device log:\n"); print_log(&g_hwdev); } hwstub_release(&g_hwdev); return 1; }