feat(tools): fw_info/fw_pack 镜像解析重打包(CRC32验证+字节级往返),112 测试全绿

This commit is contained in:
agent committed 2026-07-24 11:09:44 +00:00
1 parent 0e2a6a351f
commit 7079053dde
10 files changed
+987 -1

No files matched your search

View File
Whitespace-only changes.
+54
View File
@@ -0,0 +1,54 @@
"""DA14585 SUOTA 镜像解析/重打包(tools 交付物)。
格式(证据:app/ 样本 + CRC 反推验证):
[0:2] magic 'pQ' = 0x7051(LE)
[2:4] flags = 0x01AA
[4:8] body 长度(= 文件长 - 64)
[8:12] CRC32(body)(zlib 多项式,LE)
[12:64] 0xFF 填充
[64:] 镜像体,起始为 Cortex-M 向量表(SP, Reset, ...),加载基址 0x07FC0000
"""
from __future__ import annotations
import struct
import zlib
MAGIC_BYTES = b"pQ" # 文件头两字节 70 51
MAGIC = 0x7051
FLAGS_DEFAULT = 0x01AA
HEADER_SIZE = 64
LOAD_BASE = 0x07FC0000
def parse_image(data: bytes) -> dict:
if len(data) < HEADER_SIZE:
raise ValueError("文件小于 64 字节头")
if data[0:2] != MAGIC_BYTES:
raise ValueError(f"magic 错误: {data[0:2].hex()}(期望 {MAGIC_BYTES.hex()}='pQ')")
flags, body_size, crc = struct.unpack_from("<HII", data, 2)
body = data[HEADER_SIZE:HEADER_SIZE + body_size]
sp, reset = struct.unpack_from("<II", body, 0)
return {
"magic": MAGIC,
"flags": flags,
"body_size": body_size,
"crc_stored": crc,
"crc_valid": (zlib.crc32(body) & 0xFFFFFFFF) == crc,
"initial_sp": sp,
"reset_handler": reset,
"load_base": LOAD_BASE,
"file_size": len(data),
}
def unpack_body(data: bytes) -> bytes:
info = parse_image(data)
return data[HEADER_SIZE:HEADER_SIZE + info["body_size"]]
def pack_image(body: bytes, flags: int = FLAGS_DEFAULT) -> bytes:
header = MAGIC_BYTES + struct.pack("<HII", flags, len(body),
zlib.crc32(body) & 0xFFFFFFFF)
# 填充:黄金样本 0x20 处为 0x00(含义未知,保留以字节级一致),其余 0xFF
pad = bytearray(b"\xFF" * (HEADER_SIZE - len(header)))
pad[0x20 - len(header)] = 0x00
return header + bytes(pad) + body
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env python3
"""fw_info: 打印 DA14585 镜像头信息(JSON)。"""
import json, sys
from pathlib import Path
from fw import parse_image
if __name__ == "__main__":
data = Path(sys.argv[1]).read_bytes()
info = parse_image(data)
print(json.dumps({k: (hex(v) if isinstance(v, int) else v) for k, v in info.items()}, indent=2))
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env python3
"""fw_pack: 体→完整镜像(重算 CRC)。用法: fw_pack.py body.bin out.img [flags_hex]"""
import sys
from pathlib import Path
from fw import pack_image
if __name__ == "__main__":
body = Path(sys.argv[1]).read_bytes()
flags = int(sys.argv[3], 16) if len(sys.argv) > 3 else 0x01AA
Path(sys.argv[2]).write_bytes(pack_image(body, flags))
print(f"OK: {sys.argv[2]} ({len(body)}B body)")