54 lines
2.4 KiB
Python
54 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Parse and verify DA14585 firmware image header (Dialog SUOTA/multi-image format).
|
|
|
|
Image header layout (64 bytes):
|
|
+0x00 u8[2] magic 0x70 0x51 ('pQ' LE word 0x5170) = IMAGE_VALID
|
|
+0x02 u8[2] signature version/application id (here 0xAA 0x01)
|
|
+0x04 u32 code_size size of code region (= file_size - 64)
|
|
+0x08 u32 crc32 CRC over code region
|
|
+0x0C 52B reserved 0xFF
|
|
"""
|
|
import struct, sys, zlib, binascii
|
|
|
|
IMG = "/mnt/documents/Works/Eink/qianbian/app/firmware-PP_da14585_4.2_CH.img"
|
|
|
|
def crc32_mpeg(data, init=0xFFFFFFFF, xorout=0, poly=0x04C11DB7):
|
|
crc = init
|
|
for b in data:
|
|
crc ^= b << 24
|
|
for _ in range(8):
|
|
crc = ((crc << 1) ^ poly) & 0xFFFFFFFF if (crc & 0x80000000) else (crc << 1) & 0xFFFFFFFF
|
|
return crc ^ xorout
|
|
|
|
def main():
|
|
data = open(IMG, "rb").read()
|
|
print(f"file size: {len(data)} (0x{len(data):x})")
|
|
magic = data[0:2]
|
|
sig = data[2:4]
|
|
code_size, crc_hdr = struct.unpack_from("<II", data, 4)
|
|
reserved = data[12:64]
|
|
print(f"magic : {magic.hex()} ({magic!r})")
|
|
print(f"signature : {sig.hex()}")
|
|
print(f"code_size : {code_size} (0x{code_size:x}) file-64 = {len(data)-64}")
|
|
print(f"header CRC : 0x{crc_hdr:08x}")
|
|
print(f"reserved : all 0xff = {all(b==0xff for b in reserved)}")
|
|
print(f"size match : {code_size == len(data)-64}")
|
|
|
|
code = data[64:64+code_size]
|
|
# try CRC variants
|
|
c_zlib = zlib.crc32(code) & 0xFFFFFFFF # CRC-32 (reflected, init/xor FF)
|
|
c_bzip2 = crc32_mpeg(code, 0xFFFFFFFF, 0xFFFFFFFF) # CRC-32/BZIP2
|
|
c_mpeg = crc32_mpeg(code, 0xFFFFFFFF, 0) # CRC-32/MPEG-2
|
|
c_posix = crc32_mpeg(code, 0, 0xFFFFFFFF) # CRC-32/POSIX (cksum-ish)
|
|
c_jam = zlib.crc32(code, 0xFFFFFFFF) ^ 0 ^ 0xFFFFFFFF # jamcrc style check
|
|
print(f"CRC32 zlib : 0x{c_zlib:08x} match={c_zlib==crc_hdr}")
|
|
print(f"CRC32 bzip2 : 0x{c_bzip2:08x} match={c_bzip2==crc_hdr}")
|
|
print(f"CRC32 mpeg2 : 0x{c_mpeg:08x} match={c_mpeg==crc_hdr}")
|
|
print(f"CRC32 posix : 0x{c_posix:08x} match={c_posix==crc_hdr}")
|
|
# also try crc over code with initial vector table included (whole thing)
|
|
c_zlib_all = zlib.crc32(data[0:64+code_size]) & 0xFFFFFFFF
|
|
print(f"CRC32 zlib(all incl hdr): 0x{c_zlib_all:08x}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|