diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-06-24 18:04:17 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-06-24 18:07:56 +0200 |
commit | c9a028cc183d638c16ca9a8858b783b1830be16f (patch) | |
tree | 1bd29843ec0b8d3eb80a6209d1c4e32144175dfe /utils/hwpatcher/lib.lua | |
parent | 761f59c9e3be0ffd77d2dc1b8095a3b877badeda (diff) | |
download | rockbox-c9a028cc183d638c16ca9a8858b783b1830be16f.tar.gz rockbox-c9a028cc183d638c16ca9a8858b783b1830be16f.zip |
Introduce hwpatcher, a tool to patch binaries
This tool is a scriptable (lua) tool to patch binaries, it supports:
- raw binary
- ELF
- SB(v1/v2)
It also contains some basic routines to parse and generate useful arm/thumb code
like jump or register load/store. This is very useful to take a firmware and
patch an interrupt vector or some code to jump to an extra payload added to
the binary. Examples are provided for several STMP based target which the payload
is expected to be hwstub, and also for the Sansa View. A typical patcher usually
requires three elements:
- the lua patcher itself
- the payload (hwstub for example)
- (optional) a small stub either to jump properly to the payload or determine
under which circumstance to do the jump (hold a key for example)
Change-Id: I6d36020a3bc9e636615ac8221b7591ade5f251e3
Diffstat (limited to 'utils/hwpatcher/lib.lua')
-rw-r--r-- | utils/hwpatcher/lib.lua | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/utils/hwpatcher/lib.lua b/utils/hwpatcher/lib.lua new file mode 100644 index 0000000000..7a3e4a4115 --- /dev/null +++ b/utils/hwpatcher/lib.lua | |||
@@ -0,0 +1,107 @@ | |||
1 | --[[ | ||
2 | hwpatcher library | ||
3 | |||
4 | The C code provides the following functions. | ||
5 | |||
6 | At global level: | ||
7 | - quit() Quit the interactive mode | ||
8 | - exit() Same as quit() | ||
9 | |||
10 | In the hwp table: | ||
11 | - load_file(filename) Load a firmware and guess type | ||
12 | - load_elf_file(filename) Load a firmware as ELF | ||
13 | - load_sb_file(filename) Load a firmware as SB | ||
14 | - load_sb1_file(filename) Load a firmware as SB1 | ||
15 | - load_bin_file(filename) Load a firmware as binary | ||
16 | - save_file(obj, filename) Save a firmware to a file | ||
17 | - read(obj, addr, len) Read data from a firmware | ||
18 | - write(obj, addr, data) Write data to a firmware | ||
19 | - section_info(obj, sec) Return information about a section in a table (or nil) | ||
20 | - md5sum(filename) Compute the MD5 sum of a file | ||
21 | |||
22 | Data read/written from/to a firmware must must be an array of bytes. | ||
23 | The address must be a table of the following fields: | ||
24 | - address: contain the address | ||
25 | - section: optional section name | ||
26 | Data section information is a table with the following fields: | ||
27 | - address: first address if the section | ||
28 | - size: size of the section | ||
29 | We provide the following functions to help dealing with addresses: | ||
30 | - make_addr | ||
31 | |||
32 | ]]-- | ||
33 | |||
34 | function hwp.deepcopy(o, seen) | ||
35 | seen = seen or {} | ||
36 | if o == nil then return nil end | ||
37 | if seen[o] then return seen[o] end | ||
38 | |||
39 | local no | ||
40 | if type(o) == 'table' then | ||
41 | no = {} | ||
42 | seen[o] = no | ||
43 | |||
44 | for k, v in next, o, nil do | ||
45 | no[hwp.deepcopy(k, seen)] = hwp.deepcopy(v, seen) | ||
46 | end | ||
47 | setmetatable(no, hwp.deepcopy(getmetatable(o), seen)) | ||
48 | else -- number, string, boolean, etc | ||
49 | no = o | ||
50 | end | ||
51 | return no | ||
52 | end | ||
53 | |||
54 | function hwp.make_addr(addr, section) | ||
55 | local t = {addr = addr, section = section} | ||
56 | local addr_to_string = function(self) | ||
57 | if self.section == nil then | ||
58 | return string.format("%#x", self.addr) | ||
59 | else | ||
60 | return string.format("%#x@%s", self.addr, self.section) | ||
61 | end | ||
62 | end | ||
63 | setmetatable(t, {__tostring = addr_to_string}) | ||
64 | return t | ||
65 | end | ||
66 | |||
67 | function hwp.inc_addr(addr, amount) | ||
68 | return hwp.make_addr(addr.addr + amount, addr.section) | ||
69 | end | ||
70 | |||
71 | -- pack an array of bytes in a integer (little-endian) | ||
72 | function hwp.pack(arr) | ||
73 | local v = 0 | ||
74 | for i = #arr, 1, -1 do | ||
75 | v = bit32.bor(bit32.lshift(v, 8),bit32.band(arr[i], 0xff)) | ||
76 | end | ||
77 | return v | ||
78 | end | ||
79 | |||
80 | -- do the converse | ||
81 | function hwp.unpack(v, n) | ||
82 | local t = {} | ||
83 | for i = 1, n do | ||
84 | t[i] = bit32.band(v, 0xff) | ||
85 | v = bit32.rshift(v, 8) | ||
86 | end | ||
87 | return t | ||
88 | end | ||
89 | |||
90 | -- read a 32-bit value | ||
91 | function hwp.read32(obj, addr) | ||
92 | return hwp.pack(hwp.read(obj, addr, 4)) | ||
93 | end | ||
94 | |||
95 | -- write a 32-bit value | ||
96 | function hwp.write32(obj, addr, v) | ||
97 | return hwp.write(obj, addr, hwp.unpack(v, 4)) | ||
98 | end | ||
99 | |||
100 | -- convert a MD5 hash to a string | ||
101 | function hwp.md5str(md5) | ||
102 | local s = "" | ||
103 | for i = 1, #md5 do | ||
104 | s = s .. string.format("%02x", md5[i]) | ||
105 | end | ||
106 | return s | ||
107 | end | ||