A single CLI plus curated chip data for BC-250 hardware research. 43 subcommands, 64 python modules, ~110 atlas data files, 457 tests.
Five tracks share one tool:
- Per-firmware analysis - scan / map / target / disasm a firmware blob (PSP_TOS, ABL0..N, PMFW, UMC_FW, ...) into a versioned research-map.
- Chip-wide atlas - queryable hardware schematic for the whole part (IP blocks, mailboxes, msgids, feature mask, driver gates, live silicon state); emits JSON + Markdown + interactive HTML with 10 Mermaid diagrams. Drives kernel-patch generation and wiki publishing.
- SPI boot-trace analysis - analyses pico2-spi-tap captures against a BIOS image, classifies blobs by read pattern, surfaces re-read windows, simulates firmware-substitution logic before flashing.
- PSP triage - LIVE/DEAD classification for ring-cmd handlers, SVC dispatch tables, TBB jump tables, USR-controlled write destinations, caller chains, SVC-name recovery.
- BIOS / envelope tooling - PSP firmware-directory parser,
$PS1signed-envelope decode + repack, ABL stage characterization, APCB v3 parser + checksum-preserving editor, UEFI FV/FFS parser.
bin/recon doctor # health check (run this first)
bin/recon tools # categorized index of every probe (NEW)
bin/recon tools --ns bios # one namespace
bin/recon tools --grep apcb # substring filter
bin/recon profiles # list known firmware targets
bin/recon atlas # chip-wide hardware schematic (default: bc250)
bin/recon atlas --probe # … and pull live state from the chip via SSHrecon tools is the canonical tool index — same data the MCP server exposes, grouped by namespace. Use it to discover what's available without reading source.
Per-firmware analysis:
bin/recon scan --profile psp_tos # full audit + bridges + MMIO snapshot
bin/recon map --profile psp_tos # parse outputs → research-map.{json,md}
bin/recon target # ranked next-step findings
bin/recon disasm 0x031f8 # Thumb-2 disassembly with annotations
bin/recon disasm-fn --input <fw> --addr 0x11920SPI MITM trace analysis:
bin/recon spi-trace --trace boot1.csv --bios $BIOS # baseline classify
bin/recon spi-trace --trace boot1.csv --bios $BIOS --rereads # TOCTOU window surfacer
bin/recon spi-trace --trace boot1.csv --bios $BIOS --simulate-mitm # dry-run Mode B logicCanonical inventory generated from the ProbeSpec registry. Refresh with recon docs sync; CI guards against drift via recon docs check. For interactive filtering, use recon tools (--ns, --grep, --cli, --tier, --summary, --explain-tiers, --json).
Auto-generated by recon docs sync from the ProbeSpec registry. 57 probes across 11 namespaces. Do not edit by hand — run recon docs sync to refresh.
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | atlas |
recon atlas |
Chip-wide hardware schematic; emits JSON+Markdown+HTML. |
| T0 | atlas_diff |
recon diff |
Diff two research-maps. |
| T0 | atlas_query |
recon query |
Point lookup over a run's research-map. |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | bios_abl_decoder |
recon abl-decoder |
ABL stage characterization. |
| T0 | bios_apcb_audit |
recon apcb |
Audit APCB against AMD baseline; detect stripped groups (CCXG/GNBG silicon-segmentation signal) + count post-Robin5 CBS Token-Pair records. |
| T0 | bios_apcb_diff |
recon apcb |
Diff two APCBs with per-group annotation. Useful for Robin1/3/5 version-skew, BIOS-vs-chip_now identity, population fingerprinting. |
| T0 | bios_apcb_info |
recon apcb |
Parse APCB header + list groups + verify checksum. |
| T0 | bios_extract |
recon extract |
Pull PSP firmware-directory entries from a BIOS image (list or extract by type). |
| T0 | bios_extract_fw |
recon extract-bios-fw |
PSP firmware-directory parser ($PS1, BHD) → extract blobs. |
| T0 | bios_ps1_envelope |
recon ps1-envelope |
Decode signed $PS1 envelope. |
| T0 | bios_ps1_repack |
recon ps1-repack |
Repack $PS1 envelope (in-memory bytes only — no flash write). |
| T0 | bios_uefi |
recon uefi |
UEFI Firmware Volume + FFS parser + SMM-surface scanner. Inventories PEIMs/DXE drivers in AGESA.fv for AGESA pre-boot analysis. |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | board_debug_survey |
(MCP only) | Static UART/JTAG survey from atlas yaml — does NOT probe. |
| T1 | board_hwmon_snapshot |
(MCP only) | Always-safe hwmon snapshot — preferred over chip_gpu_metrics during workload. |
| T1 | board_i2c_adapters |
(MCP only) | Visible i2c adapters incl. amdgpu-exposed. |
| T2 | board_i2c_walk |
(MCP only) | i2cdetect -y -r address probe (read-only quick). |
| T0 | board_pcie_inspect |
(MCP only) | PCIe topology / config (read-only) / AER counters. |
| T2 | board_pmbus |
(MCP only) | PMBus identify + telemetry register reads. |
| T0 | board_sensors_inventory |
(MCP only) | lm_sensors registered hwmon devices. |
| T1 | board_smi_cmd_port |
(MCP only) | Real SW-SMI command port from FADT SMI_CMD (BC-250 = 0xB0, NOT 0xB2). |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T2 | chip_nvar_read |
(MCP only) | Resolve & read an AMI NVAR (UEFI) variable's current value from flash via SMM. |
| T7 | chip_nvar_set |
(MCP only) | Set a byte in an AMI NVAR variable via SMM (NVAR-append) — writes the store; gated. |
| T2 | chip_smiflash_read |
(MCP only) | Read SPI flash at a chip offset via SMM (no external programmer). |
| T7 | chip_smiflash_write |
(MCP only) | Write SPI flash via SMM — BRICK-CLASS; classifier-refused without override. |
| T2 | chip_smn_read |
(MCP only) | Single SMN read at vetted addr (tier varies by addr). |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | docs_check |
recon docs |
CI guard: exit non-zero if README's AUTO-GENERATED tool-index block is stale relative to the registry. |
| T0 | docs_sync |
recon docs |
Rewrite README.md AUTO-GENERATED tool-index block from the ProbeSpec registry. Run after adding/removing probes. |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | doctor |
recon doctor |
Health check (deps + target reachable + atlas schema valid). |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | fw_annotate |
recon annotate |
Annotate disasm with pool literals and branch targets. |
| T0 | fw_disasm |
recon disasm |
Annotated Thumb-2/ARM32 disasm at addr. |
| T0 | fw_disasm_fn |
recon disasm-fn |
Single-function disasm; stops at epilogue. |
| T0 | fw_dump |
recon dump |
Full-firmware disasm corpus. |
| T0 | fw_dump_strings |
recon dump-strings |
Printable-ASCII extraction. |
| T0 | fw_find_abs_writer |
recon find-abs-writer |
Absolute-address writer detector. |
| T0 | fw_find_bl |
recon find-bl |
BL/BLX call sites to a target address. |
| T0 | fw_find_callers |
recon find-callers |
BL/BLX caller chain up from a target (detects boot-init-only handlers). |
| T0 | fw_find_imm |
recon find-imm |
Every insn carrying a given immediate. |
| T0 | fw_find_stride_writer |
recon find-stride-writer |
Strided writer detector. |
| T0 | fw_find_svc |
recon find-svc |
SVC sites (omit ID to enumerate all). |
| T0 | fw_find_writer |
recon find-writer |
Funcs writing target value to kernel addr - PSP handler call-chain analysis. |
| T0 | fw_map |
recon map |
Fold scan outputs into research-map.{json,md}. |
| T0 | fw_psp_ring_handlers |
recon ring-cmd-triage |
Ring-cmd handler LIVE/DEAD classification. |
| T0 | fw_psp_svc_dispatch |
recon dump-svc-table |
Static PSP SVC dispatch table extract. |
| T0 | fw_psp_tbb_table |
recon dump-tbb-table |
PSP TBB (Trusted Boot Block) jump-table extract. |
| T0 | fw_scan |
recon scan |
Full scanner audit + bridges + MMIO snapshot. Creates runs//. |
| T0 | fw_scope_dispatcher |
recon scope-dispatcher |
USR scope dispatcher analysis. |
| T0 | fw_scope_handler |
recon scope-handler |
USR scope handler classification. |
| T0 | fw_strings |
recon strings |
Printable-string sweep over a run/profile. |
| T0 | fw_ta_scan |
recon ta-scan |
Caller-dest write-path scanner: find PSP SVC handlers that write to a USR-r0/1/2/3-derived kernel address. Supports PSP handler research. Subcommands: run, analyze. |
| T0 | fw_target |
recon target |
Rank next-step findings (P1/P2/P3). |
| T0 | fw_trace_svc_names |
recon trace-svc-names |
Auto-identify PSP/AGESA SVC numbers from Svc_* log strings via ADR back-walk. Emits name -> SVC# mapping. |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | memory_reorg |
(MCP only) | Fold researcher's claude-memory into ariel-memory under BC-250 tree. |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | profiles_list |
recon profiles |
Known firmware profiles. |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | safety_classify_probe |
recon classify-probe |
The planning oracle. Returns tier/refused/safer_alternatives for a candidate probe. |
| T0 | safety_list_probes |
recon list-probes |
Filterable view of all registered probes — backed by recon.registry.filter_by. |
| T0 | safety_liveness_check |
recon liveness |
ssh + hwmon responsive sentinel against a target host. |
| Tier | MCP probe | CLI subcommand | Description |
|---|---|---|---|
| T0 | spi_trace |
recon spi-trace |
Baseline classifier / TOCTOU surfacer / Mode B dry-run for pico2 SPI traces. |
The auto-generated table above is the source of truth for which probes exist. The cheat sheet below adds CLI flag-level usage notes; refer to recon <cmd> --help for the authoritative flag set.
| Subcommand | Purpose |
|---|---|
scan |
Run full scanner audit + bridges + MMIO snapshot. Creates runs/<profile>/<ts>/. Flags: --profile, --fw, --svcs, --no-mmio, --audit-arg (repeatable). |
map |
Fold scan outputs into research-map.json + research-map.md. |
target |
Rank next-step findings (P1 boot-only MMIO publishers, P2 high-fanin convergence, P3 unannotated crypto hits). --write-back patches findings into the map. |
query |
Point lookup: query func 0x031f8, query mmio MP0_C2PMSG_64, query site 0x11920, query find aes. JSON or text. |
diff |
Diff two research-maps (a b, run dirs or research-map.json files). |
disasm |
Annotated Thumb-2/ARM32 disasm at an address (--len, --arm). Resolves pool literals + branch targets, marks SVCs + writes. |
disasm-fn |
Single-function disasm (--input, --addr, `--mode thumb |
dump |
Full-firmware disassembly corpus (--gaps includes scanner-gap regions, --raw adds linear-sweep). |
dump-strings |
Printable-ASCII extraction (--min-len, --max-len, --dotted, --json). |
strings |
Printable-strings sweep over a run/profile (--min, --grep). |
find-bl |
BL/BLX call sites to a target address. |
find-imm |
Every insn carrying a given immediate. |
find-svc |
SVC sites (omit ID to enumerate all). |
find-callers |
Trace BL/BLX caller chain up from a target (--depth, default 6). Detects boot-init-only handlers (zero-caller chain ends). |
find-writer |
Functions writing a target value to a kernel address (--any-value, --usr-dst for USR-arg-derived destinations). PSP handler call-chain analysis. |
find-abs-writer |
Writes to a specific absolute address. Searches pool literals, movw+movt, indirect writes via base+offset (--addr, --offset, --mode thumb,arm). |
find-stride-writer |
Writes at offset N of a stride-indexed table base (--base, --stride, --offset, --value). |
annotate |
Persistent annotation sidecar (annotations/<profile>.json). Subcommands: func, const, svc, slot, show, path. |
profiles |
Inspect firmware-target registry. Subcommands: list, show NAME. |
doctor |
Health checks (profiles, scanner, run state, firmware availability, kernel match). --deep adds default-firmware + extra probes. --check-tools audits module → CLI → MCP coverage. --json for CI. |
tools |
Categorized index of every registered probe (CLI + MCP). Filters: --ns, --grep, --cli, --tier, --summary, --explain-tiers, --json. |
docs |
README auto-generation from the ProbeSpec registry. Subcommands: sync (rewrite the AUTO-GENERATED block), check (CI guard against drift), print (emit block to stdout). |
| Subcommand | Purpose |
|---|---|
atlas |
Build chip-wide hardware schematic. See recon atlas for the full flag surface. |
| Subcommand | Purpose |
|---|---|
spi-trace |
Classify SPI flash trace blobs vs BIOS layout, surface TOCTOU re-reads, simulate Mode B firmware, emit C / CDC target tables, diff against baseline. See recon spi-trace. |
| Subcommand | Purpose |
|---|---|
ta-scan |
Caller-dest write-path scanner; finds SVC handlers that write to USR-controlled kernel addrs. Subcommands: run (sweep), analyze (classify hits in existing scan dir). Wired to the PSPEMU harness via PSPEMU_HOME + PSP_HARNESS_DIR. |
ring-cmd-triage |
LIVE/DEAD triage of PSP ring-buffer cmd handlers (--tbb-addr, default 0x1057e for BC-250; --count, default 37; --scan bytes per worker). |
scope-dispatcher |
Bulk LIVE/DEAD triage across every entry of a dispatch table (--tbb-addr or --svc-table, --count, --no-follow-stubs). |
scope-handler |
Single-function deep scope (SVCs, BL targets, writes, pool loads, ADR string refs, gate calls, LIVE/DEAD verdict). |
trace-svc-names |
Auto-identify SVC numbers from Svc_* log strings via ADR back-walk; emits name → SVC# mapping. |
dump-svc-table |
Decode PC-relative SVC dispatch jump table (--table, --count, --base-svc). |
dump-tbb-table |
Decode Thumb-2 TBB/TBH dispatch table or --auto find all (--tbh for halfword). |
| Subcommand | Purpose |
|---|---|
extract-bios-fw |
Parse AMD PSP firmware directories from a BIOS image; list and optionally extract each entry (--extract DIR). |
ps1-envelope |
Decode AMD $PS1 signed-firmware envelopes; extract body (--body PATH); optionally --try-decompress. |
ps1-repack |
Rebuild a $PS1 envelope around a modified body. Preserves the 0x100-byte header + 0x100-byte trailer. Accepts --attacker-body (raw replacement body) or --decompressed-body (auto-zlib-compress at levels 9-1). |
abl-decoder |
One-shot ABL{0..N} stage characterization: extract from BIOS, $PS1-decode, decompress, dump strings, classify role. --validate-attacker runs a pre-flash sanity check comparing a modified image against the original. |
apcb |
APCB v3 parser + checksum-preserving editor + group audit + cross-revision diff. Subcommands: info, verify, groups, extract, set-memclk, find-u16, audit, diff. Used to detect Sony's CCXG/GNBG strip on BC-250 / 4800S. |
extract |
Pull PSP firmware-directory entries from a BIOS image; list (default) or extract by type regex (--type, optional --decrypt --uncompress). |
uefi |
UEFI Firmware Volume / FFS parser + SMM-surface scanner. Subcommands: info, list, extract, scan-smm-handlers, scan-swsmi-handlers, find-protocol, scan-spi-wp. Inventories PEIMs/DXE drivers in AGESA.fv for AGESA pre-boot analysis. |
Reads curated chip data from data/atlas/<chip>/*.json plus prior
per-firmware research-maps and emits a unified artifact.
recon atlas # JSON + MD with 10 Mermaid diagrams
recon atlas --html # standalone interactive HTML (sidebar nav)
recon atlas --probe # add live silicon snapshot (SSH+ioctl)
recon atlas --watch SECONDS # continuous --probe with diff alerts
recon atlas --snapshot # versioned snapshot to snapshots/<chip>/<ts>.json
recon atlas --history # snapshot timeline + per-field change frequency
recon atlas --history-detailed # … plus full per-snapshot diffs
recon atlas --publish-wiki # upload atlas.md to GitLab wiki
recon atlas --wiki-project-id 5 --wiki-slug BC250-Hardware-Atlas
recon atlas --list-liberation # prioritized MMIO/feature to-do list (P1..P4)
recon atlas --diff RUN_A RUN_B # diff two atlas runs
recon atlas --compare bc250 vangogh renoir # cross-chip msgid mining
recon atlas --query-smn 0xC180 # resolve SMN address → named register
recon atlas --validate # JSON-Schema validation against data/atlas/schema.json
recon atlas --psp-ta-scan # PSP MP9 TA registry analyzer
recon atlas --gen-patch SERIES_ID # generate kernel patch from atlas dataOutput per run (in runs/<ts>-atlas-<chip>/):
atlas.json— machine-readable hardware tree (schema v1).atlas.md— Markdown with 10 Mermaid diagrams + per-IP tables + msgid catalog + feature-mask decode + patch-series tracker + live state.atlas.html— standalone HTML with sidebar nav (when--htmlgiven).
- Chip topology (IP blocks clustered by GPU/Memory/MCU/NB-IO)
- Mailbox graph (host driver → SMN window → queues → owner IP)
- Firmware → IP block map
- Driver gates by IP block (pie)
- Driver gates by type (ring-emit-skip, tlb-path-skip, ...)
- Clock + power tree (rails + domains + SMU actuator hub, DS state colour-coded)
- SMN address space (IP-base timeline)
- Msgid distribution per queue (pie)
- SMU feature mask state (pie: enabled / disabled / unknown)
- Feature bits by category (pie: DeepSleep / Throttle / Power / CPU / DPM / …)
A _mermaid_patch_series_status() diagram tracks readiness across the
patch-series registry too.
--gen-patch <id> reads data/atlas/<chip>/patch-series.json and
emits a real unified-diff .patch. Series registry on BC-250:
| ID | Name | Status | Risk |
|---|---|---|---|
| 1 | message_map expansion (16 MSG_MAP entries from mailbox-msgids.json) |
verified, built end-to-end, chip post-patch returns expected SMU responses | low |
| 2 | deep-sleep + GFXOFF wiring | pending | medium |
| 3 | real DPM table | pending | medium |
| 4 | BACO + S3 + GFXOFF callbacks | pending | high |
| 5 | CPU DPM via SetSoftMin/MaxCclk | pending | low |
| 6 | researcher's Q3 surface | pending | medium |
| 7 | IP block enumeration completeness | pending | low |
| 8 | VCN re-enable | investigation | medium |
| 9 | promote MMIO liberation to amdgpu init | blocked (WREG32_SOC15 ordering vs RLC/GC/KIQ) | high |
| B1..B6 | BAPM/CACW track (sysfs, profiles, baseline, userspace daemon, telemetry learning, upstream wiring) | various | various |
--probe SSHes to $RECON_BC250_HOST (default project-ariel.local)
as $RECON_BC250_USER and reads: PMFW heartbeat
(0x3B1054C ~1 kHz tick), PSP debug magic (0xC180), feature mask
(0xC71C), MP1 event counter + status, Q0 last cmd/arg, PMFW version,
CLK DS state per instance. Output matches the live-state.json schema.
Inputs a pico2-spi-tap CSV (timestamp_us,opcode,addr,length,sha256_first16)
plus a BIOS image. Cross-references each read against the
PSP-directory blob layout from extract-bios-fw and classifies
per-blob:
SINGLE_READ- read once, no re-read window.VERIFY_THEN_USE- 2+ reads with consistent hash, re-read window present.VERIFY_THEN_USE_INCONSISTENT- 2+ reads with different hashes (substitution active or trace corrupted).CHUNKED_FULL_LOAD- 95%+ coverage via fragments; chunked-load pattern (BC-250 PSP_BL style).PARTIAL- incomplete blob load captured.NEVER_READ- blob present in BIOS but absent from trace.
recon spi-trace --trace boot1.csv --bios $BIOS # baseline classify
recon spi-trace --trace boot1.csv --bios $BIOS --rereads # widest-gap TOCTOU first
recon spi-trace --trace boot1.csv --bios $BIOS --rereads --rereads-min-gap-ms 1.0
recon spi-trace --trace boot1.csv --bios $BIOS --rereads --rereads-region 0x800000:0xac0000
recon spi-trace --trace boot1.csv --bios $BIOS --bus-stats # PROCEED / PROCEED_RISKY / ABORT
recon spi-trace --trace boot1.csv --bios $BIOS --simulate-mitm --mitm-mask 0x1 --simulate-target ABL0
recon spi-trace --trace boot1.csv --bios $BIOS --analyze-chunks # per-blob irregular-chunk surfacing
recon spi-trace --trace new.csv --bios $BIOS --diff-baseline baseline.csv
recon spi-trace --bios $BIOS --synthetic 32 --synthetic-pattern verify_then_use # offline self-test
recon spi-trace --trace boot1.csv --bios $BIOS --target-table c # C source for mitm_state.c
recon spi-trace --trace boot1.csv --bios $BIOS --target-table cdc # USB CDC paste-into-picocom commands--simulate-mitm dry-runs the Mode B firmware logic against the trace
so you can validate --mitm-mask (default 0x1 = use-then-verify
pattern; 0x2 = verify-then-use; 0xffffffff = always substitute)
and --simulate-target blob filter before flashing pico2.
--diff-baseline is the post-modification verification step: capture
a baseline before Mode B goes live, capture again after, diff.
Per-blob output: UNCHANGED / READS_COUNT_CHANGED / HASHES_CHANGED
/ TIMING_CHANGED / NEW_BLOB / MISSING_BLOB. HASHES_CHANGED on
your target = strong signal Mode B served different bytes.
--synthetic generates a trace without hardware (verify_then_use,
single_read, or mixed patterns) for offline self-test and CI.
Reference traces ship at recon/data/spi-traces/2026-05-25/:
boot7-cold.csv, boot8-warm.csv, boot9-cold.csv,
boot11-cold-dryrun.csv (~1144 lines total, real BC-250 boots).
Importable without going through the CLI:
recon.apcb- APCB v3 parser + checksum-preserving editor (matches corebootapcb_v3_edit.pysemantics). Functions:parse_header(),verify_checksum(),recompute_checksum_byte(),find_groups(),parse_groups(),find_u16_le(),set_memclk(),extract_bhd_body_from_bios(). Used to build modified APCB images for Mode B firmware substitution (e.g. MCLK overrides).recon.uefi— FV / FFS / section parser.parse_fv_header(),parse_ffs_files(),parse_ffs_sections(),find_ui_name(),guid_str(). Used by AGESA + BIOS firmware analysis.recon.paths— Hub layout resolver.find_recon_root(),reset_cache(); exportsRECON_ROOT,RUNS_DIR,EXTRACTS_DIR,PROFILES_DIR.recon.profiles— Profile loader.list_profiles(),load_profile(name).
data/atlas/ ships chip-specific JSON sources. JSON-Schema v1 at
data/atlas/schema.json (kind: chip-atlas).
data/atlas/bc250/— primary target, 103 JSON files. Core:chip.json,ip-blocks.json,mailboxes.json,mailbox-msgids.json(144 msgids across Q0..Q4),feature-mask.json(64-bit decode),pmfw-tables.json,cacw-surface.json,clock-power-tree.json,smn-registers.json(48 named addresses),patch-series.json(12-series recovery roadmap),driver-gates.json,live-state.json. Per-investigation closed-finding snapshots cover BAPM, MGCG, AVFS, fuse audit, PSP TA registry, build-pipeline forensics, ACPI methods, DCN/DCE display engine audit, KFD compute pipes, microcode introspection, SVI2 voltage surface, DIDT subsystem inventory, GMC/MMHUB/GFXHUB audit, IP-discovery live comparison, MP1 + MP9 SMN region sweeps, CPU MSR snapshot, cross-chip msgid comparison, tier-1 IFR empirical failure, ring-emit-skips audit, gfx-off surface, VCN firmware gap, transfer table SMU↔DRAM probe.data/atlas/vangogh/— Steam Deck APU sibling. 4 files (chip.json,mailbox-msgids.jsonwith 77 Q0 msgids,ip-blocks.jsonwith 17 IPs,feature-mask.jsonwith 60 bits).data/atlas/renoir/— Ryzen 4000U/H APU sibling. 2 files (chip.json,mailbox-msgids.jsonwith 56 Q0 msgids).data/atlas/sienna_cichlid/— RDNA2 discrete-GPU sibling reference.chip.jsonskeleton only.
recon/data/spi-traces/2026-05-25/— 4 pico2-spi-tap reference traces from real BC-250 boots (cold + warm + dryrun).tests/fixtures/—sample_mode_a_trace.csv+ fixture README; drivestest_toctou_pipeline.py.snapshots/bc250/— timestamped atlas--snapshotoutputs for drift detection.profiles/— firmware-target profile JSONs (bc250-r14.json,psp_tos.json).runs/— versioned per-run output dirs (gitignored).extracts/—extract-bios-fw --extract DIRoutput staging (gitignored, operator-populated).annotations/— persistent sidecar (<profile>.json) populated byrecon annotate.
recon/
bin/recon # CLI launcher (delegates to recon.cli:main)
recon/ # 64 python modules (including subpackages)
cli.py # subcommand dispatch
atlas.py # chip-wide schematic builder
spi_trace.py # SPI boot-trace analyser
scan.py / map.py / target.py # per-firmware workflow
doctor.py / profiles.py / paths.py
disasm.py / disasm_fn.py / dump.py
dump_strings.py / dump_svc_table.py / dump_tbb_table.py
annotate.py / strings.py / query.py / diff.py
find_bl.py / find_imm.py / find_svc.py
find_callers.py / find_writer.py / find_abs_writer.py / find_stride_writer.py
extract.py / extract_bios_fw.py
abl_decoder.py
ps1_envelope.py / ps1_repack.py
ring_cmd_triage.py
scope_dispatcher.py / scope_handler.py
trace_svc_names.py
ta_scan.py
apcb.py # APCB v3 parser + checksum-preserving editor
uefi.py # FV / FFS / section parser
data/spi-traces/<date>/ # captured pico2-spi-tap reference traces
data/
atlas/<chip>/*.json # curated chip data (bc250, vangogh, renoir, sienna_cichlid)
atlas/schema.json # atlas.json JSON-Schema v1
tools/share/ # operator-runnable scripts (5 scripts)
docs/spec.md # original wiki spec (archived)
profiles/ # per-firmware profile JSONs
runs/ # versioned run dirs (gitignored)
snapshots/ # per-chip --snapshot output (gitignored)
tests/ # 27 test files, 457 tests
Makefile / pyproject.toml / .pre-commit-config.yaml / .gitlab-ci.yml
Each firmware target lives in profiles/<name>.json. Currently
registered: bc250-r14 (PSP_TOS R14 with full board context),
psp_tos (generic). Adding a target = drop a JSON file + register a
Profile entry in recon/profiles.py referencing
_EXTRACTS_P3 / "..." paths.
recon profiles # list
recon profiles show bc250-r14 # pretty-print JSON
recon scan --profile bc250-r14 # use it457 tests across 27 files. Headline (top 15 by count):
| File | Tests | Coverage |
|---|---|---|
test_atlas.py |
67 | end-to-end atlas build, diff, compare, patch-series codegen, JSON-Schema validation, snapshot history, HTML / wiki emit |
test_imports.py |
45 | collection-time import smoke pass — every cli.DISPATCH target imports cleanly (auto-grows with new subcommands) |
test_toctou_pipeline.py |
31 | end-to-end BIOS → extract → $PS1 decode → decompress → spi-trace analysis |
test_safety.py |
28 | safety classifier rules + budget + liveness |
test_doctor.py |
25 | health-check scenarios (incl. --check-tools coverage audit) |
test_query.py |
22 | research-map lookups (func, mmio, site, find, annotation fusion) |
test_disasm.py |
19 | Thumb / ARM disasm |
test_target.py |
18 | finding ranking |
test_map.py |
18 | scan-output folding |
test_uefi.py |
17 | UEFI FV/FFS parser + SMM handler scan |
test_apcb.py |
15 | APCB v3 parser + editor, BHD extraction, MCLK override, group audit + cross-revision diff |
test_registry.py |
15 | ProbeSpec registry + tier filtering |
mcp/test_server.py |
15 | MCP server JSON-RPC round-trip + tool registration |
test_dump.py |
14 | full-firmware dumps |
test_annotate.py |
14 | sidecar CRUD |
Remaining 12 files cover scan, paths, cli, strings, profiles, find_svc, find_imm, diff, probes/{chip_smn,board}, mcp/dispatch_argparse, and docs drift-guard.
make test # all 457 tests
pytest tests/test_atlas.py -v
pytest tests/test_toctou_pipeline.py -v
pytest tests/test_apcb.py -vAtlas outputs are deterministic (bit-identical across runs modulo
the generated timestamp + live-probe values). Determinism guards
plus content-correctness tests verify the curated data (feature decode
against bitmask, known SMN addresses, MSG_MAP cross-resolution).
atlas-live-probe.sh— probe chip-state claims (feature mask Q0 0x3D, SetCoreEnableMask handler, MP1/PMFW telemetry, gfx state) against atlas baseline; validates DLV-A14, DLV-A52,live-state.json.bc250-checkpoint.sh— comprehensive single-shot BC-250 state capture (Q0 msgid probes, MP1 + PSP SMN telemetry,amdgpu_pm_info, CPU MSRs, hwmon, ip_discovery). Pre/post-liberation diff source.verify-setcoreenable-q0.sh— independently verify SetCoreEnableMask (0x2C) is a HANDLER on BC-250 Q0; safe (arg=0 no-op); reproduces DLV-A52.smn-telemetry-probe.py— SMN-register polling via the AMD MP1 PCI config backdoor (0xB8/0xBC); read-only; reads PMFW heartbeat, MP1 event counter, Q0/Q3 mailbox snapshots.build-and-test-bc250-patch-series.sh— fetch a patch from GitLab MR, rebuild amdgpu out-of-tree, module-swap with auto-rollback, live checkpoint before + after.
RECON_ROOT— override hub directory (default: walk-up to findMakefile + recon/__init__.py).RECON_BC250_HOST— target host foratlas --probe / --watch / --snapshot(defaultproject-ariel.local).RECON_BC250_USER— SSH user for probe commands.GITLAB_URL/GITLAB_TOKEN— foratlas --publish-wiki(read from~/.config/recon/secrets.envif unset).PSP_INPUTS_DIR— extracted PSP firmware blobs foratlas --psp-ta-scanbyte-grep and forta-scan.PSPEMU_HOME— PSPEMU build root (used bydoctor+ta-scan).PSP_HARNESS_DIR— PSP svc-fuzz harness directory (used byta-scan).BC250_BIOS_DIR— BIOS image directory forextract-bios-fw/spi-trace --bios.PICO_SDK_PATH— pico SDK 2.x for building the pico2 firmware (sources on theshare-bc250-patch-build-scriptbranch).
# 1. Extract every interesting entry from a stock BIOS
bin/recon extract-bios-fw \
--bios $BC250_BIOS_DIR/Robin1.00/Robin1.00 \
--extract /tmp/bc250-extracts
# 2. Register a Profile in recon/profiles.py pointing at <name>_body.bin
# 3. Scan / map / target / disasm
bin/recon scan --profile <name>
bin/recon map --profile <name>
bin/recon target --profile <name>
# 4. Atlas integrates per-firmware research-maps
bin/recon atlas --chip bc250# 0. Capture a boot trace with pico2-spi-tap. Wire pico2 GP2..GP5
# to BC-250 BIOS flash CS#/CLK/MOSI/MISO. Cold-boot BC-250 while
# `cat /dev/ttyACM0 > boot1.csv` runs on the host.
# 1. Confirm coverage + classify blobs
recon spi-trace --trace boot1.csv --bios $BIOS --bus-stats
# 2. Find re-read windows
recon spi-trace --trace boot1.csv --bios $BIOS --rereads --rereads-min-gap-ms 1.0
# 3. Build a modified firmware image (APCB-mod example) via recon.apcb library
python3 -c 'from recon.apcb import parse_groups, set_memclk; ...'
# 4. Wrap it back into a $PS1 envelope
recon ps1-repack --original ABL0.bin --decompressed-body modified_body.bin --out ABL0_modified.bin
# 5. Dry-run Mode B firmware logic against the trace
recon spi-trace --trace boot1.csv --bios $BIOS --simulate-mitm \
--mitm-mask 0x1 --simulate-target ABL0
# 6. Emit C target table for the pico2 firmware
recon spi-trace --trace boot1.csv --bios $BIOS --target-table c
# 7. Post-modification verification
recon spi-trace --trace post.csv --bios $BIOS --diff-baseline pre.csv# 1. Find SVC handlers that write to USR-controlled kernel addrs
recon ta-scan run --profile bc250-r14
# 2. Triage candidates
recon ta-scan analyze --scan-dir runs/<ts>-ta-scan/
# 3. Drill into a specific handler
recon scope-handler --input <fw> --addr 0x114b8
# 4. Confirm with a focused write-locator
recon find-writer 0x<kernel_addr> 0x<target_value> --usr-dst# 1. Enumerate the SVC dispatch table
recon dump-svc-table --table 0x45e4 --count 128 --base-svc 0x51
# 2. Auto-find every TBB/TBH table in the firmware
recon dump-tbb-table --auto
# 3. Bulk LIVE/DEAD classify a specific dispatcher
recon scope-dispatcher --input <fw> --tbb-addr 0x1057e --count 37
# 4. Recover SVC names from log strings
recon trace-svc-names --input <fw>- 2026-05-05 — Original
reconcodebase lost in forge crash (lived at<workdir>/<path>, never in git). Wiki spec survived;extract.pyrecovered via decompyle++ (docs/decompiled-extract.py`). - 2026-05-06..2026-05-19 — Phase 1.3: per-firmware workflow rebuilt from spec, module-by-module.
- 2026-05-21 — Phase 2:
recon atlaschip-wide hardware schematic shipped over 14 MRs. 10 Mermaid renderers, live-state probing, snapshot / history / diff, JSON-Schema validation, atlas-driven kernel patch generation, wiki publishing, cross-chip msgid mining. Series 1 (message_map expansion) generated + applied + built end-to-end against BC-250. - 2026-05-22..2026-05-23 — BC-250 kernel-callers + BAPM + sdpm patch series landed (MRs !11..!27): 23 msgids wired, 25 debugfs entries, 40-CU MMIO restored (+65.6% FP32). MGCG / BAPM compute deadlock characterised + parked. ~30 new closed-finding atlas JSONs.
- 2026-05-24 - Phase 3 kickoff: in-band PSP handler analysis fully
exhausted (10-iter loop closed every
field_0/caller_idpath). PSP triage tooling shipped (ta-scan,ring-cmd-triage,scope-dispatcher,scope-handler,trace-svc-names,disasm-fn,find-{callers,writer,abs-writer,stride-writer},dump-{strings,svc-table,tbb-table}). Pivot to hardware-side SPI boot-trace track. - 2026-05-25 - Re-read window for BHD verify-then-use confirmed
empirically (12.1s gap between verify-read and use-read of
$BHD@0xab1000; sniffer SHA + FIFO fix enabled the finding).spi-trace,extract-bios-fw,abl-decoder,ps1-envelope/ps1-repack,apcb(parser + editor), anduefi(FV / FFS parser) shipped. 31-testtest_toctou_pipeline.pycovers the spi-trace pipeline end-to-end. Reference boot traces archived atrecon/data/spi-traces/2026-05-25/.
- Spec:
docs/spec.md - AMD PSP documentation: AMD PPR for Family 17h processors
- SPI boot-trace methodology: based on pAMDora research (39C3)