#!/usr/bin/env python3
import hashlib
import json
import pathlib
import re
import struct
import subprocess
import sys

elf, binary, map_file = map(pathlib.Path, sys.argv[1:4])
map_text = map_file.read_text(errors="replace")
dis = subprocess.check_output(["arm-none-eabi-objdump", "-d", str(elf)], text=True)
sections = subprocess.check_output(["arm-none-eabi-objdump", "-h", str(elf)], text=True)
data = binary.read_bytes()
sp, reset = struct.unpack_from("<II", data)
required = ["drill_smo_init", "drill_smo_step", "drill_smo_sincos", "mfoc_step", "run_synthetic", "main", "drill_safe_boot"]
missing = [symbol for symbol in required if not re.search(r"\b" + re.escape(symbol) + r"\b", map_text)]
if missing:
    raise SystemExit("missing linked symbols: " + ",".join(missing))
if sp != 0x20005800:
    raise SystemExit(f"bad initial SP: {sp:#x}")
if not (reset & 1) or not (0x08000000 <= (reset & ~1) < 0x08020000):
    raise SystemExit("invalid reset vector")
if ".isr_vector" not in sections or ".text" not in sections:
    raise SystemExit("missing vector/text section")
for symbol in required:
    if symbol not in dis:
        raise SystemExit("missing disassembly symbol " + symbol)
size = subprocess.check_output(["arm-none-eabi-size", str(elf)], text=True).splitlines()[-1].split()
result = {
    "status": "LINKED_TARGET_DIAGNOSTIC_STATIC_CHECK_PASS",
    "target": "STM32G431CBT6 Cortex-M4F",
    "flash_bytes": len(data),
    "flash_capacity_bytes": 131072,
    "ram_bytes": int(size[1]) + int(size[2]),
    "ram_capacity_bytes": 22528,
    "initial_sp": hex(sp),
    "reset_vector": hex(reset),
    "linked_symbols": required,
    "synthetic_forward_reverse_tests_in_image": True,
    "foc_current_controller_linked_and_called": True,
    "TIM1_ADC_SPI_initialized": False,
    "DRV_RUN_REQ_or_MOE_enabled": False,
    "physical_runtime_test": False,
    "sha256_bin": hashlib.sha256(data).hexdigest(),
    "sha256_elf": hashlib.sha256(elf.read_bytes()).hexdigest(),
}
print(json.dumps(result, ensure_ascii=False, indent=2))
