agentleFS
DavidClawsonDavidClawson/ripcord/.claude/skills/firmware-bringup/SKILL.md

firmware-bringup

Skill2 starsChanged 6 months agoMITView on GitHub

Bring up a firmware target in ripcord from opaque binary to an execution-verified hardware-boundary (MMIO) transcript. Use when the user wants to emulate a firmware target, capture how the MCU drives a peripheral or opaque device (FPGA/ASIC), reverse-engineer a hardware protocol, triage why a firmware image won't boot in Renode, or reproduce/extend the FNIRSI scope bring-up. Chains identify → pipeline → boot-triage → decompose → function-level emulation → reconcile.

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 1

    1. TaiMaBenJi/taima-skills★ 1100% same

    Edited · 0

    None found.

    Wrote their own version · 0

    None found.

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository2 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Don't fake a cold boot for a two-stage image: If boot triage shows the app isn't independently cold-bootable (Phase B decision), pivot to …

    line 26
  2. Distinctive:

    Prefer empiricism over theory: When unsure why execution stalls, run it and read the trace.

    line 30
  3. Very specific:

    run scripts/renode/emulate_function.py --target T --entry <lo> --stop <after-key-op> --reg <base-regs> --mem <globals> --run.

    line 51
  4. Very specific:

    A spin balloons the trace to multiple GB: Always cap --duration / --timeout, watch for the "trace still growing" warning, and rm …

    line 88

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Firmware bring-up (ripcord)

Drive a firmware target from opaque binary to an execution-verified hardware-boundary transcript in the mmio_events warehouse. The full, authoritative recipe — with the decision points — lives in notes/firmware-bringup-runbook.md. Read that file first, then execute the phases below. The worked example (FNIRSI 2C53T) is in notes/renode-at32-bringup.md; the static protocol it verifies against is notes/scope_acquisition_spec.md.

This skill is the ripcord thesis in miniature: convert a static hypothesis about how the MCU drives its hardware into an observed transcript. For an opaque peripheral, that transcript is the reverse-engineered interface.

Operating rules

  • Confidence discipline. Tag every claim by provenance. A value the firmware wrote is observed; a reply the stub invented is unverified until a hardware trace confirms it. Never present an inferred FPGA/peripheral reply as fact. (See notes/confidence-scheme.md.)
  • Don't fake a cold boot for a two-stage image. If boot triage shows the app isn't independently cold-bootable (Phase B decision), pivot to function-level emulation — do not invent bootloader context to force the reset path.
  • Prefer empiricism over theory. When unsure why execution stalls, run it and read the trace; each stall names the next thing to model. Don't over-reason a disassembly when a 2-second emulation answers it.
  • Work the existing tools; don't re-implement what's listed. Add a target via config.yaml only — no new pipeline stages without the user's ask.

Phases (see the runbook for the decision points)

  1. Ingest. scripts/identify.py <binary>; add to config.yaml (base_addr + raw_binary: true for raw images); run snakemake --cores 4 --resources ghidra=1.
  2. Boot triage. Boot from the reset vector with a platform .repl (reuse scripts/renode/at32f403a.repl for STM32F1-class chips). Classify: progresses / configASSERT-hang / status-poll spin / two-stage. Use the runbook's red-flag checklist to detect not-cold-bootable images.
  3. Function-level emulation (if not cold-bootable):
    • find the driver via peripheral_xrefs;
    • split monster functions with scripts/analysis/decompose.py;
    • recover command bytes + the entry register context with scripts/analysis/disasm.py (--filter skeleton / --filter calls);
    • extend the peripheral stub (the scripts/renode/fpga_protocol.py pattern);
    • run scripts/renode/emulate_function.py --target T --entry <lo> --stop <after-key-op> --reg <base-regs> --mem <globals> --run.
  4. Reconcile. Diff the captured transcript against the static spec; upgrade confirmed facts static-inferred → execution-verified; iterate the poll/assert-satisfaction loop until the boundary runs to completion. Record each promoted fact as a contract via scripts/contracts/ledger.py (see the execution-verify skill) — the ledger, not prose, is the durable result.

Function-level emulation techniques (hard-won)

These generalize to any two-stage / RTOS firmware where you enter a function without the full boot context:

  • Enter past a blocking RTOS primitive. A task that opens with xQueueReceive(…, portMAX_DELAY) spins forever in emulation (the queue is empty). Enter at the post-receive PC instead and stage the received value in memory: --reg sp=… --reg <base regs> --mem <stack slot>=<cmd byte>. Read the prologue with disasm.py to recover the exact register context (peripheral base, state base, stack-arg slot) the skipped prologue would have set.
  • NOP-patch a boot/scheduler-dependent helper via --mem. A bl to a FreeRTOS yield/delay (writes 0x10000000 PENDSVSET to ICSR 0xE000ED04) or a timer-list walk needs scheduler state the entry skips, and it spins. Flash is a writable MappedMemory, so rewrite the call site to two Thumb NOPs: --mem 0x<callsite>=0xBF00BF00. Do not try to skip it with a PC←LR hook — Renode does not cleanly redirect PC from a block-begin hook (it desyncs or halts). The flash patch is deterministic.
  • Share one peripheral model across stubs. Renode runs every Python.PythonPeripheral in one IronPython engine and imports a module once, so a module-level singleton (fpga_protocol.get_model()) lets e.g. a GPIO stub drive set_cs() and the SPI stub read the same FpgaModel — model the real handshake instead of a hardcoded shortcut.
  • Prove a data path with a distinguishable pattern. Set RIPCORD_FPGA_SAMPLE_PATTERN=1 so idle reads return an incrementing counter; a buffer that fills 02 03 04… proves each clocked-in byte reached the MCU buffer. Gate the pattern on a handshake line (CS) to also prove a GPIO stub drives the model — a counter-filled buffer can then only mean CS was asserted.
  • A spin balloons the trace to multiple GB. Always cap --duration / --timeout, watch for the "trace still growing" warning, and rm build/*_fn_*_trace.log after each run. A 240 s spin once wrote a 4.8 GB trace.

Output

Report: where boot triage landed (and why), the isolated driver function/phase, the captured MMIO/command sequence, what it confirmed vs corrected in the static spec, and the next stall to satisfy. Log a dated run entry in the relevant notes/*-bringup.md so the loop's progress is durable.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.