rockbox/utils/hwpatcher/generic_stmp.lua
Amaury Pouly c9a028cc18 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
2014-06-24 18:07:56 +02:00

108 lines
3.4 KiB
Lua

--[[
Generic STMP hacking
required argument (in order):
- path to firmware
- path to output firmware
- path to blob
- path to stub
]]--
require("lib")
require("arm")
if #arg < 4 then
error("usage: <fw file> <out file> <blob> <stub>")
end
-- compute MD5
print("Computing MD5 sum of the firmware...")
local md5 = hwp.md5sum(arg[1])
print("=> " .. hwp.md5str(md5))
local md5_db =
{
["d0047f8a87d456a0032297b3c802a1ff"] =
{
model = "Sony NWZ-E3600 1.0.0",
irq_addr_pool = 0x40A314E4,
irq_addr_pool_sec = "play.1",
-- proxy_addr = 0x4005C1E0,
-- proxy_addr_sec = "play.1"
proxy_addr = 0x4007C258,
proxy_addr_sec = "play.1",
-- stub_addr = 0x1971C8,
-- stub_addr_virt = 0x2971C8,
-- stub_addr_sec = "pvmi",
},
["f42742d4d90d88e2fb6ff468c1389f5f"] =
{
model = "Creative ZEN X-Fi Style 1.03.04",
irq_addr_pool = 0x402D3A64,
irq_addr_pool_sec = "play.1",
proxy_addr = 0x402E076C,
proxy_addr_sec = "play.1"
},
["c180f57e2b2d62620f87a1d853f349ff"] =
{
model = "Creative ZEN X-Fi3 1.00.25e",
irq_addr_pool = 0x405916f0,
proxy_addr = 0x40384674,
}
}
local db_entry = md5_db[hwp.md5str(md5)]
if db_entry == nil then
error("Cannot find device in the DB")
os.exit(1)
end
print("Model: " .. db_entry.model)
local fw = hwp.load_file(arg[1])
local irq_addr_pool = hwp.make_addr(db_entry.irq_addr_pool, db_entry.irq_addr_pool_sec)
local proxy_addr = arm.to_arm(hwp.make_addr(db_entry.proxy_addr, db_entry.proxy_addr_sec))
-- read old IRQ address pool
local old_irq_addr = hwp.make_addr(hwp.read32(fw, irq_addr_pool))
print(string.format("Old IRQ address: %s", old_irq_addr))
-- put stub at the beginning of the proxy
local stub = hwp.load_bin_file(arg[4])
local stub_info = hwp.section_info(stub, "")
local stub_data = hwp.read(stub, hwp.make_addr(stub_info.addr, ""), stub_info.size)
local stub_addr = nil
local stub_addr_virt = nil
if db_entry.stub_addr ~= nil then
stub_addr = arm.to_arm(hwp.make_addr(db_entry.stub_addr, db_entry.stub_addr_sec))
if db_entry.stub_addr_virt ~= nil then
stub_addr_virt = arm.to_arm(hwp.make_addr(db_entry.stub_addr_virt, db_entry.stub_addr_sec))
else
stub_addr_virt = stub_addr
end
hwp.write(fw, stub_addr, stub_data)
else
stub_addr = proxy_addr
stub_addr_virt = stub_addr
hwp.write(fw, stub_addr, stub_data)
proxy_addr = hwp.inc_addr(proxy_addr, stub_info.size)
end
-- modify irq
hwp.write32(fw, irq_addr_pool, proxy_addr.addr)
print(string.format("New IRQ address: %s", proxy_addr))
-- in proxy, save registers
arm.write_save_regs(fw, proxy_addr)
proxy_addr = hwp.inc_addr(proxy_addr, 4)
-- load blob
local blob = hwp.load_bin_file(arg[3])
local blob_info = hwp.section_info(blob, "")
-- patch blob with stub address
hwp.write32(blob, hwp.make_addr(blob_info.addr + 4, ""), stub_addr_virt.addr)
-- write it !
local blob_data = hwp.read(blob, hwp.make_addr(blob_info.addr, ""), blob_info.size)
hwp.write(fw, proxy_addr, blob_data)
proxy_addr = hwp.inc_addr(proxy_addr, blob_info.size)
-- restore registers
arm.write_restore_regs(fw, proxy_addr)
proxy_addr = hwp.inc_addr(proxy_addr, 4)
-- branch to old code
local branch_to_old = arm.make_branch(old_irq_addr, false)
arm.write_branch(fw, proxy_addr, branch_to_old, hwp.inc_addr(proxy_addr, 4))
-- save
hwp.save_file(fw, arg[2])