diff options
-rw-r--r-- | utils/hwpatcher/rkwpatch.lua | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/utils/hwpatcher/rkwpatch.lua b/utils/hwpatcher/rkwpatch.lua new file mode 100644 index 0000000000..85237b69a4 --- /dev/null +++ b/utils/hwpatcher/rkwpatch.lua | |||
@@ -0,0 +1,126 @@ | |||
1 | --[[ | ||
2 | RKW patching tool | ||
3 | required argument (in order): | ||
4 | - path to rkw | ||
5 | - path to stub | ||
6 | - physical address where to put bin blob | ||
7 | - physical address where to put jump | ||
8 | - path to output patched firmware | ||
9 | ]]-- | ||
10 | require("lib") | ||
11 | require("arm") | ||
12 | |||
13 | function printf(...) | ||
14 | io.write(string.format(...)) | ||
15 | end | ||
16 | |||
17 | if #arg < 5 then | ||
18 | printf("Arguments: source.rkw blob.bin blob_address jump_address output.rkw\n") | ||
19 | printf("source.rkw\tRKW file to be patched\n") | ||
20 | printf("blob.bin\tArbitrary binary to be implanted (e.g hwstub.bin)\n") | ||
21 | printf("blob_address\tPhysical address where to implant blob (e.g 0x6008300c)\n") | ||
22 | printf("jump_address\tPhysical address where to put jump to implanted binary (e.g 0x60097f2c)\n") | ||
23 | printf("output.rkw\tResulting RKW file\n") | ||
24 | os.exit(1) | ||
25 | end | ||
26 | |||
27 | -- return rkw file offset based on physical runtime mem addr | ||
28 | -- sdram base address is 0x60000000 and rkw header is 0x2c long | ||
29 | function addr2rkw(addr) | ||
30 | return (addr + 0x2c - 0x60000000) | ||
31 | end | ||
32 | |||
33 | -- read input file | ||
34 | local fw = hwp.load_file(arg[1]) | ||
35 | |||
36 | -- read and check RKW magic number | ||
37 | local rkw_magic = hwp.read32(fw, hwp.make_addr(0)) | ||
38 | |||
39 | if rkw_magic ~= 0x4c44524b then | ||
40 | printf("error: wrong RKW magic number\n") | ||
41 | os.exit(1) | ||
42 | end | ||
43 | |||
44 | -- check RKW header size | ||
45 | local rkw_header_size = hwp.read32(fw, hwp.make_addr(0x04)) | ||
46 | |||
47 | if rkw_header_size ~= 0x2c then | ||
48 | printf("error: RKW header size 0x%0x should be 0x2c!\n", rkw_header_size) | ||
49 | os.exit(1) | ||
50 | end | ||
51 | |||
52 | -- check RKW header CRC | ||
53 | local header_crc = hwp.crc(RKW, fw, hwp.make_addr(0), 0x28) | ||
54 | |||
55 | if hwp.read32(fw, hwp.make_addr(0x28)) ~= header_crc then | ||
56 | printf("error: RKW header CRC mismatch\n") | ||
57 | os.exit(1) | ||
58 | end | ||
59 | |||
60 | local firmware_blob = hwp.make_addr(rkw_header_size) | ||
61 | local blob_size = hwp.read32(fw, hwp.make_addr(0x10)) - hwp.read32(fw, hwp.make_addr(0x8)) | ||
62 | local rkw_crc = 0 | ||
63 | |||
64 | -- check if blob has CRC attached | ||
65 | if blob_size < hwp.section_info(fw, "").size then | ||
66 | rkw_crc = hwp.crc(RKW, fw, firmware_blob, blob_size) | ||
67 | |||
68 | if hwp.read32(fw, hwp.make_addr(blob_size+rkw_header_size)) ~= rkw_crc then | ||
69 | printf("error: RKW CRC mismatch\n") | ||
70 | os.exit(1) | ||
71 | end | ||
72 | else | ||
73 | printf("error: blob reported size: 0x%0x >= actual blob size: 0x%0x\n", blob_size, hwp.section_info(fw, "").size) | ||
74 | os.exit(1) | ||
75 | end | ||
76 | |||
77 | printf("RKW sanity checks passed\n") | ||
78 | printf("RKW magic:\t0x%0x\n", rkw_magic) | ||
79 | printf("Header size:\t0x%0x\n", rkw_header_size) | ||
80 | printf("Image Base:\t0x%0x\n", hwp.read32(fw, hwp.make_addr(0x8))) | ||
81 | printf("Load Base:\t0x%0x\n", hwp.read32(fw, hwp.make_addr(0xc))) | ||
82 | printf("Load Limit:\t0x%0x\n", hwp.read32(fw, hwp.make_addr(0x10))) | ||
83 | printf("ZI Base:\t0x%0x\n", hwp.read32(fw, hwp.make_addr(0x14))) | ||
84 | printf("Entry point:\t0x%0x\n", hwp.read32(fw, hwp.make_addr(0x20))) | ||
85 | printf("Load flags:\t0x%0x\n", hwp.read32(fw, hwp.make_addr(0x24))) | ||
86 | printf("Header crc:\t0x%0x\n", header_crc) | ||
87 | printf("Blob crc:\t0x%0x\n", rkw_crc) | ||
88 | |||
89 | -- branch instruction | ||
90 | local jump_instr_addr = hwp.make_addr(addr2rkw(arg[4])) | ||
91 | if (jump_instr_addr == nil) then | ||
92 | printf("error: invalid jump instruction address\n") | ||
93 | os.exit(1) | ||
94 | end | ||
95 | |||
96 | local stub_addr = hwp.make_addr(addr2rkw(arg[3])) -- some decoder stuff | ||
97 | if (stub_addr == nil) then | ||
98 | printf("error: invalid blob implant address\n") | ||
99 | os.exit(1) | ||
100 | end | ||
101 | |||
102 | -- put stub at the right place | ||
103 | local stub = hwp.load_bin_file(arg[2]) | ||
104 | if (stub == nil) then | ||
105 | printf("error: can't load blob file: %s\n", arg[2]) | ||
106 | os.exit(1) | ||
107 | end | ||
108 | |||
109 | local stub_info = hwp.section_info(stub, "") | ||
110 | local stub_data = hwp.read(stub, hwp.make_addr(stub_info.addr, ""), stub_info.size) | ||
111 | hwp.write(fw, stub_addr, stub_data) | ||
112 | printf("Implanting blob at: 0x%0x\n", arg[3]) | ||
113 | |||
114 | -- patch jump | ||
115 | local branch_to_stub = arm.make_branch(arm.to_arm(stub_addr), false) | ||
116 | arm.write_branch(fw, jump_instr_addr, branch_to_stub, hwp.inc_addr(stub_addr, stub_info.size)) | ||
117 | printf("Patching jump instruction at: 0x%0x\n", arg[4]) | ||
118 | |||
119 | -- patch rkw crc | ||
120 | rkw_crc = hwp.crc(RKW, fw, firmware_blob, blob_size) | ||
121 | printf("Patching RKW with new CRC: 0x%0x\n", rkw_crc) | ||
122 | hwp.write32(fw, hwp.make_addr(blob_size+rkw_header_size), rkw_crc) | ||
123 | |||
124 | -- save | ||
125 | hwp.save_file(fw, arg[5]) | ||
126 | printf("Saving output to: '%s'\n", arg[5]) | ||