#!/usr/bin/env python3 """Host inspection of the SD image's MBR and extracted boot payload only.""" import argparse, hashlib, json, struct, subprocess, tempfile from datetime import datetime, timezone from pathlib import Path p = argparse.ArgumentParser(description=__doc__) p.add_argument('--image', type=Path, required=True) p.add_argument('--bundle', type=Path, required=True) p.add_argument('--debugfs', type=Path, required=True) p.add_argument('--scratch', type=Path, required=True) a = p.parse_args() def sha(path): h = hashlib.sha256() with path.open('rb') as f: while block := f.read(1024 * 1024): h.update(block) return h.hexdigest() image = a.image.resolve(strict=True) bundle = a.bundle.resolve(strict=True) with image.open('rb') as f: mbr = f.read(512) assert mbr[510:512] == b'\x55\xaa' parts = [] for i in range(4): e = mbr[446 + i * 16:462 + i * 16] if e[4]: start, count = struct.unpack_from(' --bundle --debugfs --scratch ', 'image': str(image), 'image_bytes': image.stat().st_size, 'image_sha256': sha(image), 'bundle': str(bundle), 'identity': json.loads((bundle / 'identity.json').read_text()), 'partitions': parts, 'boot_payload': observed, 'kernel_tree_initrd_and_bootargs_match_trial_bundle': True, 'all_selectors_name_combined_tree': True, 'result': 'PASS', 'limits': ['Host boot-payload inspection only; not a flashed-image, untouched autoboot or physical glass/input result.', 'The root partition layout is checked; its filesystem contents are not independently extracted by this recipe.'], }, indent=2))