A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

hwpatcher: add generic RKW file patching script

This script is handy hacking tool to patch RKW file with
arbitrary binary and put jump into implanted code.
It also shows how to use hwstub crc routine.

Change-Id: I89b5086dc1ddaca3dbc03df26a85472d8a20d51e

+126
+126
utils/hwpatcher/rkwpatch.lua
··· 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])