rockbox/utils/hwstub/tools/hwstub_shell.cpp
Amaury Pouly c5357940ab 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
2013-06-13 02:25:15 +02:00

873 lines
26 KiB
C++

/***************************************************************************
* __________ __ ___.
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <stdbool.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <lua.hpp>
#include "soc_desc.hpp"
#if LUA_VERSION_NUM < 502
#warning You need at least lua 5.2
#endif
/**
* Global variables
*/
bool g_quiet = 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_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;
}
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); // 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_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_AES_OTP));
lua_setfield(g_lua, -2, "aes_otp");
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_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");
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] <soc desc files>\n");
printf("options:\n");
printf(" --help/-?\tDisplay this help\n");
printf(" --quiet/-q\tQuiet non-command messages\n");
printf(" -i <init>\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 STMP specific information
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);
}
// test DCP
#if 0
if(!g_quiet)
{
struct
{
uint8_t iv[16];
uint8_t data[16];
} __attribute__((packed)) dcp_test;
for(int i = 0; i < 16; i++)
dcp_test.iv[i] = rand();
for(int i = 0; i < 16; i++)
dcp_test.data[i] = rand();
printf("DCP\n");
printf(" IN\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.iv[i]);
printf("\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.data[i]);
printf("\n");
if(!hwstub_aes_otp(&g_hwdev, &dcp_test, sizeof(dcp_test), HWSTUB_AES_OTP_ENCRYPT))
{
printf(" OUT\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.iv[i]);
printf("\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.data[i]);
printf("\n");
}
else
printf("DCP error!\n");
}
#endif
/** 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(1)
{
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;
}