#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-or-later """Validate and display the bounded structure of an Apple Image3 file.""" import argparse import json from pathlib import Path import struct import sys IMG3_HEADER = struct.Struct("<4s4I") TAG_HEADER = struct.Struct("<4s2I") class Img3Error(ValueError): pass def fourcc(raw): return raw[::-1].decode("ascii", errors="replace") def scalar(tag, payload): if tag == "TYPE" and len(payload) >= 4: return fourcc(payload[:4]) if tag == "VERS" and len(payload) > 4: return payload[4:].split(b"\0", 1)[0].decode("ascii", errors="replace") if tag in {"CHIP", "BORD", "SEPO", "PROD", "SDOM"} and len(payload) == 4: return f"0x{struct.unpack('= 8: key_modifier, key_bits = struct.unpack_from(" len(data): raise Img3Error( f"full_size {full_size} is outside the {len(data)}-byte input" ) if data_size > full_size - IMG3_HEADER.size: raise Img3Error("data_size extends past full_size") if shsh_offset > data_size: raise Img3Error("shsh_offset extends past data_size") tags = [] offset = IMG3_HEADER.size end = IMG3_HEADER.size + data_size while offset < end: if end - offset < TAG_HEADER.size: raise Img3Error(f"truncated tag header at 0x{offset:x}") raw_tag, total_size, payload_size = TAG_HEADER.unpack_from(data, offset) tag = fourcc(raw_tag) if total_size < TAG_HEADER.size: raise Img3Error(f"{tag} at 0x{offset:x} has an invalid total size") if payload_size > total_size - TAG_HEADER.size: raise Img3Error( f"{tag} at 0x{offset:x} has an invalid payload size" ) if total_size > end - offset: raise Img3Error(f"{tag} at 0x{offset:x} extends past data_size") payload_start = offset + TAG_HEADER.size payload = data[payload_start:payload_start + payload_size] tags.append({ "tag": tag, "offset": offset, "payload_offset": payload_start, "total_size": total_size, "payload_size": payload_size, "padding_size": total_size - TAG_HEADER.size - payload_size, "value": scalar(tag, payload), }) offset += total_size if offset != end: raise Img3Error("tag sizes do not exactly cover data_size") return { "magic": "Img3", "file_size": len(data), "full_size": full_size, "data_size": data_size, "shsh_offset": shsh_offset, "image_type": fourcc(struct.pack("