Sanitized research log, build/reproducibility docs, DTS, kernel configs, patches, initramfs sources, bootchain migration plans and test logs. B5 direct boot PASS; B6 modem lifecycle in progress. No dumps, NV/EFS, vendor firmware or device identifiers included.
47 lines
2.8 KiB
Python
47 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
# Parse primary+backup GPT from full image, verify every partition dump against it,
|
|
# write MANIFEST.md / manifest.tsv, extract GPT blobs.
|
|
import struct, hashlib, zlib, os, sys
|
|
W = os.path.expanduser("~/doc/modem/jz08-aurora")
|
|
full = f"{W}/dumps/full-emmc.bin"
|
|
f = open(full, "rb"); S = 512
|
|
size = os.path.getsize(full); nsec = size // S
|
|
def rd(lba, n=1): f.seek(lba*S); return f.read(n*S)
|
|
def hdr(lba):
|
|
h = rd(lba)
|
|
sig, rev, hs, crc, _, cur, bak, first, last, guid, elba, n, esz, ecrc = struct.unpack_from("<8sIII4sQQQQ16sQIII", h)
|
|
hh = bytearray(h[:hs]); hh[16:20] = b"\0"*4
|
|
ents = rd(elba, (n*esz+S-1)//S)[:n*esz]
|
|
return dict(sig=sig, cur=cur, bak=bak, first=first, last=last, elba=elba, n=n, esz=esz,
|
|
hcrc_ok=zlib.crc32(hh) == crc, ecrc_ok=zlib.crc32(ents) == ecrc, ents=ents)
|
|
p = hdr(1); b = hdr(p["bak"])
|
|
out = [f"full image: {size} bytes, {nsec} sectors, sha256 {hashlib.sha256(open(full,'rb').read()).hexdigest()}"]
|
|
for nm, h in (("primary", p), ("backup", b)):
|
|
out.append(f"{nm}: sig={h['sig']} cur={h['cur']} bak={h['bak']} first={h['first']} last={h['last']} entries@{h['elba']} n={h['n']} hdrCRC={'OK' if h['hcrc_ok'] else 'BAD'} entCRC={'OK' if h['ecrc_ok'] else 'BAD'}")
|
|
out.append(f"primary entries == backup entries: {p['ents'] == b['ents']}; backup hdr at last LBA: {p['bak'] == nsec-1}")
|
|
open(f"{W}/gpt/gpt-primary-34sectors.bin", "wb").write(rd(0, 34))
|
|
open(f"{W}/gpt/gpt-backup-33sectors.bin", "wb").write(rd(nsec-33, 33))
|
|
rows = []; ok = True
|
|
for i in range(p["n"]):
|
|
e = p["ents"][i*p["esz"]:(i+1)*p["esz"]]
|
|
if e[:16] == b"\0"*16: continue
|
|
first, last, attr = struct.unpack_from("<QQQ", e, 32)
|
|
name = e[56:128].decode("utf-16le").rstrip("\0")
|
|
cnt = last-first+1; bsz = cnt*S
|
|
fh = hashlib.sha256(rd(first, cnt)).hexdigest()
|
|
pf = f"{W}/partitions/{name}.bin"
|
|
if os.path.exists(pf):
|
|
psz = os.path.getsize(pf); ph = hashlib.sha256(open(pf, "rb").read()).hexdigest()
|
|
st = "MATCH" if (psz == bsz and ph == fh) else f"DIFF(size {psz} vs {bsz})"
|
|
else: st = "MISSING"
|
|
if st != "MATCH": ok = False
|
|
rows.append((i+1, name, first, cnt, bsz, f"{attr:#018x}", fh, st))
|
|
with open(f"{W}/manifest.tsv", "w") as m:
|
|
m.write("idx\tname\tstart_lba\tsectors\tbytes\tattrs\tsha256\trl_vs_rf\n")
|
|
for r in rows: m.write("\t".join(map(str, r)) + "\n")
|
|
with open(f"{W}/MANIFEST.md", "w") as m:
|
|
m.write("# Aurora eMMC manifest (from full-emmc.bin GPT)\n\n```\n" + "\n".join(out) + "\n```\n\n")
|
|
m.write("| # | name | start LBA | sectors | bytes | attrs | SHA256 | rl vs rf |\n|---|---|---|---|---|---|---|---|\n")
|
|
for r in rows: m.write("| " + " | ".join(map(str, r)) + " |\n")
|
|
m.write(f"\nALL PARTITIONS VERIFIED: {ok}\n")
|
|
print("\n".join(out)); print("ALL OK" if ok else "PROBLEMS"); [print(*r[:5], r[7]) for r in rows]
|