#!/usr/bin/env python3
"""Decode the in-tree uuencoded radeon CIK UVD firmware blobs and dump
common_firmware_header fields (struct from sys/dev/drm/radeon/radeon_ucode.h)."""
import binascii, glob, struct, os

BASE = "sys/contrib/dev/drm/radeonfw"
if not os.path.isdir(BASE):
    BASE = "dfbsd-upstream/sys/contrib/dev/drm/radeonfw"

def uudecode(path):
    out = b""
    started = False
    for raw in open(path, "rb").read().split(b"\n"):
        l = raw.rstrip(b"\r")
        if not started:
            if l.startswith(b"begin "):
                started = True
            continue
        if l == b"end" or l == b"`" or l == b"":
            if l == b"end":
                break
            continue
        try:
            out += binascii.a2b_uu(l)
        except binascii.Error:
            # truncated final line variant
            try:
                out += binascii.a2b_uu(l + b" ")
            except binascii.Error:
                pass
    return out

for f in sorted(glob.glob(BASE + "/*uvd*.bin.uu")) + sorted(glob.glob(BASE + "/*uvd*.uu")):
    blob = uudecode(f)
    if not blob:
        print(f, "-> decode FAILED")
        continue
    sz, hdr, fmt, fver, uver = struct.unpack_from("<IIIII", blob, 0)
    vmaj, vmin, fam = (uver >> 24) & 0xFF, (uver >> 8) & 0xFF, uver & 0xFF
    print(f"{os.path.basename(f)}: datasize={len(blob)} (0x{len(blob):x})  "
          f"size_bytes={sz} header_size={hdr} (0x{hdr:x}) fmt={fmt:#x} "
          f"ucode_version={uver:#010x} -> v{vmaj}.{vmin} family={fam}  "
          f"datasize%4096={len(blob) % 4096}")
