mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 10:07:38 -04:00
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
This commit is contained in:
parent
761f59c9e3
commit
c9a028cc18
17 changed files with 2228 additions and 0 deletions
27
utils/hwpatcher/Makefile
Normal file
27
utils/hwpatcher/Makefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
CC=gcc
|
||||
CXX=g++
|
||||
LD=g++
|
||||
SBTOOLS_DIR=../imxtools/sbtools
|
||||
CFLAGS=-Wall -O3 -std=c99 -g -I$(SBTOOLS_DIR) `pkg-config --cflags lua5.2`
|
||||
LDFLAGS=`pkg-config --libs lua5.2` -L$(REGTOOLS_LIB_DIR) `xml2-config --libs` -lreadline
|
||||
EXEC=hwpatcher
|
||||
SBTOOLS_SRC=elf.c crypto.c sb.c sb1.c aes128.c crc.c misc.c sha1.c xorcrypt.c
|
||||
SBTOOLS_OBJ=$(SBTOOLS_SRC:.c=.o)
|
||||
SRC=$(wildcard *.c)
|
||||
OBJ=$(SRC:.c=.o)
|
||||
|
||||
all: $(EXEC)
|
||||
|
||||
%.o: $(SBTOOLS_DIR)/%.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
%.o: $%.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
hwpatcher: hwpatcher.o md5.o $(SBTOOLS_OBJ)
|
||||
$(LD) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(SBTOOLS_OBJ) $(OBJ) $(EXEC)
|
||||
|
||||
|
25
utils/hwpatcher/Makefile.patch
Normal file
25
utils/hwpatcher/Makefile.patch
Normal file
|
@ -0,0 +1,25 @@
|
|||
PREFIX?=arm-elf-eabi-
|
||||
AS=$(PREFIX)gcc
|
||||
ASFLAGS=-nostdlib -ffreestanding -mcpu=arm926ej-s
|
||||
OC=$(PREFIX)objcopy
|
||||
TARGETS=fuzeplus zenxfi2 zenxfi3 zen nwz zenxfistyle
|
||||
OPT_fuzeplus=-DSANSA_FUZEPLUS
|
||||
OPT_zenxfi2=-DCREATIVE_ZENXFI2
|
||||
OPT_zenxfi3=-DCREATIVE_ZENXFI3
|
||||
OPT_zen=-DCREATIVE_ZEN
|
||||
OPT_nwz=-DSONY_NWZ
|
||||
OPT_zenxfistyle=-DCREATIVE_ZENXFISTYLE
|
||||
|
||||
BOOTBINS=$(patsubst %, patch_%.bin, $(TARGETS))
|
||||
BOOTELF=$(patsubst %, patch_%.elf, $(TARGETS))
|
||||
|
||||
all: $(BOOTBINS)
|
||||
|
||||
patch_%.bin: patch_%.elf
|
||||
$(OC) -O binary $^ $@
|
||||
|
||||
patch_%.elf: patch.S
|
||||
$(AS) $(ASFLAGS) $(OPT_$(@:patch_%.elf=%)) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf $(BOOTBINS) $(BOOTELF)
|
205
utils/hwpatcher/arm.lua
Normal file
205
utils/hwpatcher/arm.lua
Normal file
|
@ -0,0 +1,205 @@
|
|||
--[[
|
||||
hwpatcher arm decoding/encoding library
|
||||
|
||||
]]--
|
||||
arm = {}
|
||||
|
||||
-- determines whether an address is in Thumb code or not
|
||||
function arm.is_thumb(addr)
|
||||
return bit32.extract(addr.addr, 0) == 1
|
||||
end
|
||||
|
||||
-- translate address to real address (ie without Thumb bit)
|
||||
-- produces an error if address is not properly aligned in ARM mode
|
||||
function arm.xlate_addr(addr)
|
||||
local res = hwp.deepcopy(addr)
|
||||
if arm.is_thumb(addr) then
|
||||
res.addr = bit32.replace(addr.addr, 0, 0)
|
||||
elseif bit32.extract(addr.addr, 0, 2) ~= 0 then
|
||||
error("ARM address is not word-aligned")
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- switch between arm and thumb
|
||||
function arm.to_thumb(addr)
|
||||
local res = hwp.deepcopy(addr)
|
||||
res.addr = bit32.bor(addr.addr, 1)
|
||||
return res
|
||||
end
|
||||
|
||||
function arm.to_arm(addr)
|
||||
return arm.xlate_addr(addr)
|
||||
end
|
||||
|
||||
-- sign extend a value to 32-bits
|
||||
-- only the lower 'bits' bits are considered, everything else is trashed
|
||||
-- watch out arithmetic vs logical shift !
|
||||
function arm.sign32(v)
|
||||
if bit32.extract(v, 31) == 1 then
|
||||
return -1 - bit32.bnot(v)
|
||||
else
|
||||
return v
|
||||
end
|
||||
end
|
||||
function arm.sign_extend(val, bits)
|
||||
return arm.sign32(bit32.arshift(bit32.lshift(val, 32 - bits), 32 - bits))
|
||||
end
|
||||
|
||||
-- check that a signed value fits in some field
|
||||
function arm.check_sign_truncation(val, bits)
|
||||
return val == arm.sign_extend(val, bits)
|
||||
end
|
||||
|
||||
-- create a branch description
|
||||
function arm.make_branch(addr, link)
|
||||
local t = {type = "branch", addr = addr, link = link}
|
||||
local branch_to_string = function(self)
|
||||
return string.format("branch(%s,%s)", self.addr, self.link)
|
||||
end
|
||||
setmetatable(t, {__tostring = branch_to_string})
|
||||
return t
|
||||
end
|
||||
|
||||
-- parse a jump and returns its description
|
||||
function arm.parse_branch(fw, addr)
|
||||
local opcode = hwp.read32(fw, arm.xlate_addr(addr))
|
||||
if arm.is_thumb(addr) then
|
||||
if bit32.band(opcode, 0xf800) ~= 0xf000 then
|
||||
error("first instruction is not a bl(x) prefix")
|
||||
end
|
||||
local to_thumb = false
|
||||
if bit32.band(opcode, 0xf8000000) == 0xf8000000 then
|
||||
to_thumb = true
|
||||
elseif bit32.band(opcode, 0xf8000000) ~= 0xe8000000 then
|
||||
error("second instruction is not a bl(x) suffix")
|
||||
end
|
||||
local dest = hwp.make_addr(bit32.lshift(arm.sign_extend(opcode, 11), 12) +
|
||||
arm.xlate_addr(addr).addr + 4 +
|
||||
bit32.rshift(bit32.band(opcode, 0x7ff0000), 16) * 2, addr.section)
|
||||
if to_thumb then
|
||||
dest = arm.to_thumb(dest)
|
||||
else
|
||||
dest.addr = bit32.replace(dest.addr, 0, 0, 2)
|
||||
end
|
||||
return arm.make_branch(dest, true)
|
||||
else
|
||||
if bit32.band(opcode, 0xfe000000) == 0xfa000000 then -- BLX
|
||||
local dest = hwp.make_addr(arm.sign_extend(opcode, 24) * 4 + 8 +
|
||||
bit32.extract(opcode, 24) * 2 + arm.xlate_addr(addr).addr, addr.section)
|
||||
return arm.make_branch(arm.to_thumb(dest), true)
|
||||
elseif bit32.band(opcode, 0xfe000000) == 0xea000000 then -- B(L)
|
||||
local dest = hwp.make_addr(arm.sign_extend(opcode, 24) * 4 + 8 +
|
||||
arm.xlate_addr(addr).addr, addr.section)
|
||||
return arm.make_branch(arm.to_arm(dest), bit32.extract(opcode, 24))
|
||||
else
|
||||
error("instruction is not a valid branch")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- generate the encoding of a branch
|
||||
-- if the branch cannot be encoded using an immediate branch, it is generated
|
||||
-- with an indirect form like a ldr, using a pool
|
||||
function arm.write_branch(fw, addr, dest, pool)
|
||||
local offset = arm.xlate_addr(dest.addr).addr - arm.xlate_addr(addr).addr
|
||||
local exchange = arm.is_thumb(addr) ~= arm.is_thumb(dest.addr)
|
||||
local opcode = 0
|
||||
if arm.is_thumb(addr) then
|
||||
if not dest.link then
|
||||
return arm.write_load_pc(fw, addr, dest, pool)
|
||||
end
|
||||
offset = offset - 4 -- in Thumb, PC+4 relative
|
||||
-- NOTE: BLX is undefined if the resulting offset has bit 0 set, follow
|
||||
-- the procedure from the manual to ensure correct operation
|
||||
if bit32.extract(offset, 1) ~= 0 then
|
||||
offset = offset + 2
|
||||
end
|
||||
offset = offset / 2
|
||||
if not arm.check_sign_truncation(offset, 22) then
|
||||
error("destination is too far for immediate branch from thumb")
|
||||
end
|
||||
opcode = 0xf000 + -- BL/BLX prefix
|
||||
bit32.band(bit32.rshift(offset, 11), 0x7ff) + -- offset (high part)
|
||||
bit32.lshift(exchange and 0xe800 or 0xf800,16) + -- BLX suffix
|
||||
bit32.lshift(bit32.band(offset, 0x7ff), 16) -- offset (low part)
|
||||
else
|
||||
offset = offset - 8 -- in ARM, PC+8 relative
|
||||
if exchange and not dest.link then
|
||||
return arm.write_load_pc(fw, addr, dest, pool)
|
||||
end
|
||||
offset = offset / 4
|
||||
if not arm.check_sign_truncation(offset, 24) then
|
||||
if pool == nil then
|
||||
error("destination is too far for immediate branch from arm (no pool available)")
|
||||
else
|
||||
return arm.write_load_pc(fw, addr, dest, pool)
|
||||
end
|
||||
end
|
||||
opcode = bit32.lshift(exchange and 0xf or 0xe, 28) + -- BLX / AL cond
|
||||
bit32.lshift(0xa, 24) + -- branch
|
||||
bit32.lshift(exchange and bit32.extract(offset, 1) or dest.link and 1 or 0, 24) + -- link / bit1
|
||||
bit32.band(offset, 0xffffff)
|
||||
end
|
||||
return hwp.write32(fw, arm.xlate_addr(addr), opcode)
|
||||
end
|
||||
|
||||
function arm.write_load_pc(fw, addr, dest, pool)
|
||||
-- write pool
|
||||
hwp.write32(fw, pool, dest.addr.addr)
|
||||
-- write "ldr pc, [pool]"
|
||||
local opcode
|
||||
if arm.is_thumb(addr) then
|
||||
error("unsupported pc load in thumb mode")
|
||||
else
|
||||
local offset = pool.addr - arm.xlate_addr(addr).addr - 8 -- ARM is PC+8 relative
|
||||
local add = offset >= 0 and 1 or 0
|
||||
offset = math.abs(offset)
|
||||
opcode = bit32.lshift(0xe, 28) + -- AL cond
|
||||
bit32.lshift(1, 26) + -- ldr/str
|
||||
bit32.lshift(1, 24) + -- P
|
||||
bit32.lshift(add, 23) + -- U
|
||||
bit32.lshift(1, 20) + -- ldr
|
||||
bit32.lshift(15, 16) + -- Rn=PC
|
||||
bit32.lshift(15, 12) + -- Rd=PC
|
||||
bit32.band(offset, 0xfff)
|
||||
end
|
||||
return hwp.write32(fw, arm.xlate_addr(addr), opcode)
|
||||
end
|
||||
|
||||
-- generate the encoding of a "bx lr"
|
||||
function arm.write_return(fw, addr)
|
||||
if arm.is_thumb(addr) then
|
||||
error("unsupported return from thumb code")
|
||||
end
|
||||
local opcode = bit32.lshift(0xe, 28) + -- AL cond
|
||||
bit32.lshift(0x12, 20) + -- BX
|
||||
bit32.lshift(1, 4) + -- BX
|
||||
bit32.lshift(0xfff, 8) + -- SBO
|
||||
14 -- LR
|
||||
hwp.write32(fw, arm.xlate_addr(addr), opcode)
|
||||
end
|
||||
|
||||
function arm.write_xxx_regs(fw, addr, load)
|
||||
if arm.is_thumb(addr) then
|
||||
error("unsupported save/restore regs from thumb code")
|
||||
end
|
||||
-- STMFD sp!,{r0-r12, lr}
|
||||
local opcode = bit32.lshift(0xe, 28) + -- AL cond
|
||||
bit32.lshift(0x4, 25) + -- STM/LDM
|
||||
bit32.lshift(load and 0 or 1,24) + -- P
|
||||
bit32.lshift(load and 1 or 0, 23) + -- U
|
||||
bit32.lshift(1, 21) +-- W
|
||||
bit32.lshift(load and 1 or 0, 20) + -- L
|
||||
bit32.lshift(13, 16) + -- base = SP
|
||||
0x5fff -- R0-R12,LR
|
||||
return hwp.write32(fw, addr, opcode)
|
||||
end
|
||||
|
||||
function arm.write_save_regs(fw, addr)
|
||||
return arm.write_xxx_regs(fw, addr, false)
|
||||
end
|
||||
|
||||
function arm.write_restore_regs(fw, addr)
|
||||
return arm.write_xxx_regs(fw, addr, true)
|
||||
end
|
49
utils/hwpatcher/creative.lua
Normal file
49
utils/hwpatcher/creative.lua
Normal file
|
@ -0,0 +1,49 @@
|
|||
--[[
|
||||
Creative ZEN hacking
|
||||
required argument (in order):
|
||||
- path to firmware
|
||||
- path to output firmware
|
||||
- path to blob
|
||||
- path to stub
|
||||
]]--
|
||||
|
||||
if #arg < 4 then
|
||||
error("not enough argument to fuzep patcher")
|
||||
end
|
||||
|
||||
local fw = hwp.load_file(arg[1])
|
||||
local irq_addr_pool = hwp.make_addr(0x38)
|
||||
local proxy_addr = arm.to_arm(hwp.make_addr(0x402519A0))
|
||||
-- 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)
|
||||
hwp.write(fw, proxy_addr, stub_data)
|
||||
local stub_addr = proxy_addr
|
||||
proxy_addr = hwp.inc_addr(proxy_addr, stub_info.size)
|
||||
-- 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.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])
|
49
utils/hwpatcher/fuzep.lua
Normal file
49
utils/hwpatcher/fuzep.lua
Normal file
|
@ -0,0 +1,49 @@
|
|||
--[[
|
||||
Fuze+ 2.36.8 hacking
|
||||
required argument (in order):
|
||||
- path to firmware
|
||||
- path to output firmware
|
||||
- path to blob
|
||||
- path to stub
|
||||
]]--
|
||||
|
||||
if #arg < 4 then
|
||||
error("not enough argument to fuzep patcher")
|
||||
end
|
||||
|
||||
local fw = hwp.load_file(arg[1])
|
||||
local irq_addr_pool = hwp.make_addr(0x41172d44)
|
||||
local proxy_addr = arm.to_arm(hwp.make_addr(0x40f35874))
|
||||
-- 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)
|
||||
hwp.write(fw, proxy_addr, stub_data)
|
||||
local stub_addr = proxy_addr
|
||||
proxy_addr = hwp.inc_addr(proxy_addr, stub_info.size)
|
||||
-- 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.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])
|
38
utils/hwpatcher/fuzep_rb.lua
Normal file
38
utils/hwpatcher/fuzep_rb.lua
Normal file
|
@ -0,0 +1,38 @@
|
|||
--[[
|
||||
Fuze+ RB hacking
|
||||
required argument (in order):
|
||||
- path to firmware
|
||||
- path to output firmware
|
||||
- path to blob
|
||||
]]--
|
||||
|
||||
if #arg < 3 then
|
||||
error("not enough argument to fuzep patcher")
|
||||
end
|
||||
|
||||
local fw = hwp.load_file(arg[1])
|
||||
local irq_addr_pool = hwp.make_addr(0x38)
|
||||
local proxy_addr = arm.to_arm(hwp.make_addr(0x60115ba4))
|
||||
-- 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))
|
||||
-- modify it
|
||||
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)
|
||||
-- do some work
|
||||
local blob = hwp.load_bin_file(arg[3])
|
||||
local blob_info = hwp.section_info(blob, "")
|
||||
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)
|
||||
-- save
|
||||
hwp.save_file(fw, arg[2])
|
108
utils/hwpatcher/generic_stmp.lua
Normal file
108
utils/hwpatcher/generic_stmp.lua
Normal file
|
@ -0,0 +1,108 @@
|
|||
--[[
|
||||
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])
|
||||
|
1123
utils/hwpatcher/hwpatcher.c
Normal file
1123
utils/hwpatcher/hwpatcher.c
Normal file
File diff suppressed because it is too large
Load diff
107
utils/hwpatcher/lib.lua
Normal file
107
utils/hwpatcher/lib.lua
Normal file
|
@ -0,0 +1,107 @@
|
|||
--[[
|
||||
hwpatcher library
|
||||
|
||||
The C code provides the following functions.
|
||||
|
||||
At global level:
|
||||
- quit() Quit the interactive mode
|
||||
- exit() Same as quit()
|
||||
|
||||
In the hwp table:
|
||||
- load_file(filename) Load a firmware and guess type
|
||||
- load_elf_file(filename) Load a firmware as ELF
|
||||
- load_sb_file(filename) Load a firmware as SB
|
||||
- load_sb1_file(filename) Load a firmware as SB1
|
||||
- load_bin_file(filename) Load a firmware as binary
|
||||
- save_file(obj, filename) Save a firmware to a file
|
||||
- read(obj, addr, len) Read data from a firmware
|
||||
- write(obj, addr, data) Write data to a firmware
|
||||
- section_info(obj, sec) Return information about a section in a table (or nil)
|
||||
- md5sum(filename) Compute the MD5 sum of a file
|
||||
|
||||
Data read/written from/to a firmware must must be an array of bytes.
|
||||
The address must be a table of the following fields:
|
||||
- address: contain the address
|
||||
- section: optional section name
|
||||
Data section information is a table with the following fields:
|
||||
- address: first address if the section
|
||||
- size: size of the section
|
||||
We provide the following functions to help dealing with addresses:
|
||||
- make_addr
|
||||
|
||||
]]--
|
||||
|
||||
function hwp.deepcopy(o, seen)
|
||||
seen = seen or {}
|
||||
if o == nil then return nil end
|
||||
if seen[o] then return seen[o] end
|
||||
|
||||
local no
|
||||
if type(o) == 'table' then
|
||||
no = {}
|
||||
seen[o] = no
|
||||
|
||||
for k, v in next, o, nil do
|
||||
no[hwp.deepcopy(k, seen)] = hwp.deepcopy(v, seen)
|
||||
end
|
||||
setmetatable(no, hwp.deepcopy(getmetatable(o), seen))
|
||||
else -- number, string, boolean, etc
|
||||
no = o
|
||||
end
|
||||
return no
|
||||
end
|
||||
|
||||
function hwp.make_addr(addr, section)
|
||||
local t = {addr = addr, section = section}
|
||||
local addr_to_string = function(self)
|
||||
if self.section == nil then
|
||||
return string.format("%#x", self.addr)
|
||||
else
|
||||
return string.format("%#x@%s", self.addr, self.section)
|
||||
end
|
||||
end
|
||||
setmetatable(t, {__tostring = addr_to_string})
|
||||
return t
|
||||
end
|
||||
|
||||
function hwp.inc_addr(addr, amount)
|
||||
return hwp.make_addr(addr.addr + amount, addr.section)
|
||||
end
|
||||
|
||||
-- pack an array of bytes in a integer (little-endian)
|
||||
function hwp.pack(arr)
|
||||
local v = 0
|
||||
for i = #arr, 1, -1 do
|
||||
v = bit32.bor(bit32.lshift(v, 8),bit32.band(arr[i], 0xff))
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- do the converse
|
||||
function hwp.unpack(v, n)
|
||||
local t = {}
|
||||
for i = 1, n do
|
||||
t[i] = bit32.band(v, 0xff)
|
||||
v = bit32.rshift(v, 8)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
-- read a 32-bit value
|
||||
function hwp.read32(obj, addr)
|
||||
return hwp.pack(hwp.read(obj, addr, 4))
|
||||
end
|
||||
|
||||
-- write a 32-bit value
|
||||
function hwp.write32(obj, addr, v)
|
||||
return hwp.write(obj, addr, hwp.unpack(v, 4))
|
||||
end
|
||||
|
||||
-- convert a MD5 hash to a string
|
||||
function hwp.md5str(md5)
|
||||
local s = ""
|
||||
for i = 1, #md5 do
|
||||
s = s .. string.format("%02x", md5[i])
|
||||
end
|
||||
return s
|
||||
end
|
246
utils/hwpatcher/md5.c
Normal file
246
utils/hwpatcher/md5.c
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* RFC 1321 compliant MD5 implementation
|
||||
*
|
||||
* Copyright (C) 2001-2003 Christophe Devine
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#define GET_UINT32(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (uint32) (b)[(i) ] ) \
|
||||
| ( (uint32) (b)[(i) + 1] << 8 ) \
|
||||
| ( (uint32) (b)[(i) + 2] << 16 ) \
|
||||
| ( (uint32) (b)[(i) + 3] << 24 ); \
|
||||
}
|
||||
|
||||
#define PUT_UINT32(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (uint8) ( (n) ); \
|
||||
(b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
|
||||
(b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
|
||||
(b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
|
||||
}
|
||||
|
||||
void md5_starts( md5_context *ctx )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void md5_process( md5_context *ctx, uint8 data[64] )
|
||||
{
|
||||
uint32 X[16], A, B, C, D;
|
||||
|
||||
GET_UINT32( X[0], data, 0 );
|
||||
GET_UINT32( X[1], data, 4 );
|
||||
GET_UINT32( X[2], data, 8 );
|
||||
GET_UINT32( X[3], data, 12 );
|
||||
GET_UINT32( X[4], data, 16 );
|
||||
GET_UINT32( X[5], data, 20 );
|
||||
GET_UINT32( X[6], data, 24 );
|
||||
GET_UINT32( X[7], data, 28 );
|
||||
GET_UINT32( X[8], data, 32 );
|
||||
GET_UINT32( X[9], data, 36 );
|
||||
GET_UINT32( X[10], data, 40 );
|
||||
GET_UINT32( X[11], data, 44 );
|
||||
GET_UINT32( X[12], data, 48 );
|
||||
GET_UINT32( X[13], data, 52 );
|
||||
GET_UINT32( X[14], data, 56 );
|
||||
GET_UINT32( X[15], data, 60 );
|
||||
|
||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define P(a,b,c,d,k,s,t) \
|
||||
{ \
|
||||
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
|
||||
P( A, B, C, D, 0, 7, 0xD76AA478 );
|
||||
P( D, A, B, C, 1, 12, 0xE8C7B756 );
|
||||
P( C, D, A, B, 2, 17, 0x242070DB );
|
||||
P( B, C, D, A, 3, 22, 0xC1BDCEEE );
|
||||
P( A, B, C, D, 4, 7, 0xF57C0FAF );
|
||||
P( D, A, B, C, 5, 12, 0x4787C62A );
|
||||
P( C, D, A, B, 6, 17, 0xA8304613 );
|
||||
P( B, C, D, A, 7, 22, 0xFD469501 );
|
||||
P( A, B, C, D, 8, 7, 0x698098D8 );
|
||||
P( D, A, B, C, 9, 12, 0x8B44F7AF );
|
||||
P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
|
||||
P( B, C, D, A, 11, 22, 0x895CD7BE );
|
||||
P( A, B, C, D, 12, 7, 0x6B901122 );
|
||||
P( D, A, B, C, 13, 12, 0xFD987193 );
|
||||
P( C, D, A, B, 14, 17, 0xA679438E );
|
||||
P( B, C, D, A, 15, 22, 0x49B40821 );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (y ^ (z & (x ^ y)))
|
||||
|
||||
P( A, B, C, D, 1, 5, 0xF61E2562 );
|
||||
P( D, A, B, C, 6, 9, 0xC040B340 );
|
||||
P( C, D, A, B, 11, 14, 0x265E5A51 );
|
||||
P( B, C, D, A, 0, 20, 0xE9B6C7AA );
|
||||
P( A, B, C, D, 5, 5, 0xD62F105D );
|
||||
P( D, A, B, C, 10, 9, 0x02441453 );
|
||||
P( C, D, A, B, 15, 14, 0xD8A1E681 );
|
||||
P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
|
||||
P( A, B, C, D, 9, 5, 0x21E1CDE6 );
|
||||
P( D, A, B, C, 14, 9, 0xC33707D6 );
|
||||
P( C, D, A, B, 3, 14, 0xF4D50D87 );
|
||||
P( B, C, D, A, 8, 20, 0x455A14ED );
|
||||
P( A, B, C, D, 13, 5, 0xA9E3E905 );
|
||||
P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
|
||||
P( C, D, A, B, 7, 14, 0x676F02D9 );
|
||||
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
|
||||
P( A, B, C, D, 5, 4, 0xFFFA3942 );
|
||||
P( D, A, B, C, 8, 11, 0x8771F681 );
|
||||
P( C, D, A, B, 11, 16, 0x6D9D6122 );
|
||||
P( B, C, D, A, 14, 23, 0xFDE5380C );
|
||||
P( A, B, C, D, 1, 4, 0xA4BEEA44 );
|
||||
P( D, A, B, C, 4, 11, 0x4BDECFA9 );
|
||||
P( C, D, A, B, 7, 16, 0xF6BB4B60 );
|
||||
P( B, C, D, A, 10, 23, 0xBEBFBC70 );
|
||||
P( A, B, C, D, 13, 4, 0x289B7EC6 );
|
||||
P( D, A, B, C, 0, 11, 0xEAA127FA );
|
||||
P( C, D, A, B, 3, 16, 0xD4EF3085 );
|
||||
P( B, C, D, A, 6, 23, 0x04881D05 );
|
||||
P( A, B, C, D, 9, 4, 0xD9D4D039 );
|
||||
P( D, A, B, C, 12, 11, 0xE6DB99E5 );
|
||||
P( C, D, A, B, 15, 16, 0x1FA27CF8 );
|
||||
P( B, C, D, A, 2, 23, 0xC4AC5665 );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (y ^ (x | ~z))
|
||||
|
||||
P( A, B, C, D, 0, 6, 0xF4292244 );
|
||||
P( D, A, B, C, 7, 10, 0x432AFF97 );
|
||||
P( C, D, A, B, 14, 15, 0xAB9423A7 );
|
||||
P( B, C, D, A, 5, 21, 0xFC93A039 );
|
||||
P( A, B, C, D, 12, 6, 0x655B59C3 );
|
||||
P( D, A, B, C, 3, 10, 0x8F0CCC92 );
|
||||
P( C, D, A, B, 10, 15, 0xFFEFF47D );
|
||||
P( B, C, D, A, 1, 21, 0x85845DD1 );
|
||||
P( A, B, C, D, 8, 6, 0x6FA87E4F );
|
||||
P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
|
||||
P( C, D, A, B, 6, 15, 0xA3014314 );
|
||||
P( B, C, D, A, 13, 21, 0x4E0811A1 );
|
||||
P( A, B, C, D, 4, 6, 0xF7537E82 );
|
||||
P( D, A, B, C, 11, 10, 0xBD3AF235 );
|
||||
P( C, D, A, B, 2, 15, 0x2AD7D2BB );
|
||||
P( B, C, D, A, 9, 21, 0xEB86D391 );
|
||||
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
}
|
||||
|
||||
void md5_update( md5_context *ctx, uint8 *input, uint32 length )
|
||||
{
|
||||
uint32 left, fill;
|
||||
|
||||
if( ! length ) return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += length;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < length )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && length >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, fill );
|
||||
md5_process( ctx, ctx->buffer );
|
||||
length -= fill;
|
||||
input += fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( length >= 64 )
|
||||
{
|
||||
md5_process( ctx, input );
|
||||
length -= 64;
|
||||
input += 64;
|
||||
}
|
||||
|
||||
if( length )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, length );
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 md5_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
void md5_finish( md5_context *ctx, uint8 digest[16] )
|
||||
{
|
||||
uint32 last, padn;
|
||||
uint32 high, low;
|
||||
uint8 msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32( low, msglen, 0 );
|
||||
PUT_UINT32( high, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
md5_update( ctx, md5_padding, padn );
|
||||
md5_update( ctx, msglen, 8 );
|
||||
|
||||
PUT_UINT32( ctx->state[0], digest, 0 );
|
||||
PUT_UINT32( ctx->state[1], digest, 4 );
|
||||
PUT_UINT32( ctx->state[2], digest, 8 );
|
||||
PUT_UINT32( ctx->state[3], digest, 12 );
|
||||
}
|
||||
|
25
utils/hwpatcher/md5.h
Normal file
25
utils/hwpatcher/md5.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef _MD5_H
|
||||
#define _MD5_H
|
||||
|
||||
#ifndef uint8
|
||||
#define uint8 unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef uint32
|
||||
#define uint32 unsigned long int
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 total[2];
|
||||
uint32 state[4];
|
||||
uint8 buffer[64];
|
||||
}
|
||||
md5_context;
|
||||
|
||||
void md5_starts( md5_context *ctx );
|
||||
void md5_update( md5_context *ctx, uint8 *input, uint32 length );
|
||||
void md5_finish( md5_context *ctx, uint8 digest[16] );
|
||||
|
||||
#endif /* md5.h */
|
||||
|
87
utils/hwpatcher/patch.S
Normal file
87
utils/hwpatcher/patch.S
Normal file
|
@ -0,0 +1,87 @@
|
|||
.text
|
||||
.global _start
|
||||
_start:
|
||||
b exec
|
||||
branch_addr:
|
||||
.word kill
|
||||
hw_power_sts:
|
||||
#if defined(CREATIVE_ZEN)
|
||||
.word 0x800440b0 /* STMP3700 */
|
||||
#else
|
||||
.word 0x800440c0 /* IMX233 */
|
||||
#endif
|
||||
hw_pinctrl_din0:
|
||||
.word 0x80018600
|
||||
hw_pinctrl_din1:
|
||||
.word 0x80018610
|
||||
hw_pinctrl_din2:
|
||||
.word 0x80018620
|
||||
kill:
|
||||
ldr pc, branch_addr
|
||||
exec:
|
||||
#if defined(SANSA_FUZEPLUS)
|
||||
/* check PSWITCH=1 (power button pressed) */
|
||||
ldr r0, hw_power_sts
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #20
|
||||
and r0, #3
|
||||
cmp r0, #1
|
||||
bne ret
|
||||
/* check B1P30=0 (volume down pressed) */
|
||||
ldr r0, hw_pinctrl_din1
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #30
|
||||
ands r0, #1
|
||||
beq kill
|
||||
#elif defined(CREATIVE_ZENXFI3)
|
||||
/* check PSWITCH=1 (power button pressed) */
|
||||
ldr r0, hw_power_sts
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #20
|
||||
and r0, #3
|
||||
cmp r0, #1
|
||||
bne ret
|
||||
/* check B2P07=0 (volume down pressed) */
|
||||
ldr r0, hw_pinctrl_din2
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #7
|
||||
ands r0, #1
|
||||
beq kill
|
||||
#elif defined(CREATIVE_ZENXFI2)
|
||||
/* check B0P11=0 (power button pressed) and B0P14 (select button pressed) */
|
||||
ldr r0, hw_pinctrl_din0
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #11
|
||||
tst r0, #1
|
||||
bne ret
|
||||
mov r0, r0, lsr #3
|
||||
tst r0, #1
|
||||
beq kill
|
||||
#elif defined(CREATIVE_ZEN)
|
||||
/* check PSWITCH=1 (power button pressed) */
|
||||
ldr r0, hw_power_sts
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #18
|
||||
and r0, #3
|
||||
cmp r0, #0
|
||||
bne kill
|
||||
#elif defined(SONY_NWZ)
|
||||
/* check PSWITCH=3 (power button pressed) */
|
||||
ldr r0, hw_power_sts
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #20
|
||||
and r0, #3
|
||||
cmp r0, #3
|
||||
beq kill
|
||||
#elif defined(CREATIVE_ZENXFISTYLE)
|
||||
/* check PSWITCH=1 (power button pressed) */
|
||||
ldr r0, hw_power_sts
|
||||
ldr r0, [r0]
|
||||
mov r0, r0, lsr #20
|
||||
and r0, #3
|
||||
cmp r0, #1
|
||||
beq kill
|
||||
#else
|
||||
#error implement me
|
||||
#endif
|
||||
ret:
|
1
utils/hwpatcher/patch_viewbl.lua
Normal file
1
utils/hwpatcher/patch_viewbl.lua
Normal file
|
@ -0,0 +1 @@
|
|||
|
38
utils/hwpatcher/view.lua
Normal file
38
utils/hwpatcher/view.lua
Normal file
|
@ -0,0 +1,38 @@
|
|||
--[[
|
||||
Sansa View bootloader hacking
|
||||
required argument (in order):
|
||||
- path to bootloader
|
||||
- path to output bootloader
|
||||
- path to stub
|
||||
]]--
|
||||
require("lib")
|
||||
require("arm")
|
||||
|
||||
if #arg < 3 then
|
||||
error("not enough argument to fuzep patcher")
|
||||
end
|
||||
|
||||
local md5 = hwp.md5sum(arg[1])
|
||||
if hwp.md5str(md5) ~= "4bc1760327c37b9ffd00315c8aa7f376" then
|
||||
error("MD5 sum of the file doesn't match")
|
||||
end
|
||||
|
||||
local fw = hwp.load_file(arg[1])
|
||||
local jump_instr_addr = arm.to_thumb(hwp.make_addr(0x753C))
|
||||
local stub_addr = hwp.make_addr(0x137B0)
|
||||
-- read old jump address
|
||||
--local old_jump = arm.parse_branch(fw, jump_instr_addr)
|
||||
--print(string.format("Old jump address: %s", old_jump))
|
||||
-- put stub at the right place
|
||||
local stub = hwp.load_bin_file(arg[3])
|
||||
local stub_info = hwp.section_info(stub, "")
|
||||
local stub_data = hwp.read(stub, hwp.make_addr(stub_info.addr, ""), stub_info.size)
|
||||
hwp.write(fw, stub_addr, stub_data)
|
||||
-- patch jump
|
||||
local branch_to_stub = arm.make_branch(arm.to_arm(stub_addr), true)
|
||||
arm.write_branch(fw, jump_instr_addr, branch_to_stub, hwp.inc_addr(stub_addr, stub_info.size))
|
||||
-- read jump address
|
||||
local new_jump = arm.parse_branch(fw, jump_instr_addr)
|
||||
print(string.format("New jump address: %s", new_jump))
|
||||
-- save
|
||||
hwp.save_file(fw, arg[2])
|
1
utils/hwpatcher/zen.lua
Normal file
1
utils/hwpatcher/zen.lua
Normal file
|
@ -0,0 +1 @@
|
|||
|
50
utils/hwpatcher/zxfi2.lua
Normal file
50
utils/hwpatcher/zxfi2.lua
Normal file
|
@ -0,0 +1,50 @@
|
|||
--[[
|
||||
Zen X-Fi2 1.23.01e NAND hacking
|
||||
required argument (in order):
|
||||
- path to firmware
|
||||
- path to output firmware
|
||||
- path to blob
|
||||
- path to stub
|
||||
]]--
|
||||
|
||||
if #arg < 4 then
|
||||
error("not enough argument to fuzep patcher")
|
||||
end
|
||||
|
||||
local fw = hwp.load_file(arg[1])
|
||||
local irq_addr_pool = hwp.make_addr(0x4035e154, "play")
|
||||
local proxy_addr = arm.to_arm(hwp.make_addr(0x402f06f8, "play"))
|
||||
-- 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)
|
||||
hwp.write(fw, proxy_addr, stub_data)
|
||||
local stub_addr = proxy_addr
|
||||
proxy_addr = hwp.inc_addr(proxy_addr, stub_info.size)
|
||||
-- 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.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])
|
||||
|
49
utils/hwpatcher/zxfi3.lua
Normal file
49
utils/hwpatcher/zxfi3.lua
Normal file
|
@ -0,0 +1,49 @@
|
|||
--[[
|
||||
Zen X-Fi3 1.00.25e hacking
|
||||
required argument (in order):
|
||||
- path to firmware
|
||||
- path to output firmware
|
||||
- path to blob
|
||||
- path to stub
|
||||
]]--
|
||||
|
||||
if #arg < 4 then
|
||||
error("not enough argument to fuzep patcher")
|
||||
end
|
||||
|
||||
local fw = hwp.load_file(arg[1])
|
||||
local irq_addr_pool = hwp.make_addr(0x405916f0)
|
||||
local proxy_addr = arm.to_arm(hwp.make_addr(0x40384674))
|
||||
-- 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)
|
||||
hwp.write(fw, proxy_addr, stub_data)
|
||||
local stub_addr = proxy_addr
|
||||
proxy_addr = hwp.inc_addr(proxy_addr, stub_info.size)
|
||||
-- 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.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])
|
Loading…
Add table
Add a link
Reference in a new issue