The tools/ directory ships a collection of host-side Python scripts that pair with the Flashy firmware:
drivers for routine bench work, capture parsers for reverse-engineering, kernel-extraction utilities,
and crypto helpers. Most are command-line and assume Python 3.9+ with pyserial and
pycryptodome installed. A point-and-click desktop wrapper around the most-used
workflows is on the roadmap — until then, drop into a terminal.
--help output or module docstring than the one-line summary here.
You don’t need VS Code. Pick the path that matches how much setup you want to do:
| Path | When to use it | What you install |
|---|---|---|
| 1. Prebuilt installer (zero Python needed) |
You just want VIN scan / read / write / capture — the most-used workflows. The installer ships standalone .exe bundles for those plus .bat launchers you double-click. |
Flashy-Tool-Setup-1.5.x.exe from the latest release. Or unzip Flashy-Tool.zip into a folder and double-click any .bat. |
| 2. Windows Terminal (any tool, terminal-only) |
You want to run any .py in tools/ — including the ones not in the bundled set (e.g. obd2/clear_dtc.py, set_rtc_local.py, e92a_*). Cleanest no-IDE answer. |
Python 3.9+ from python.org (check “Add to PATH” on install), then pip install pyserial pycryptodome. Get Windows Terminal from the Microsoft Store, then right-click the repo folder → “Open in Terminal”. Git Bash works too if you prefer a Unix-style shell. |
| 3. Thonny or PyCharm (GUI alternative to VS Code) |
You want a click-to-run editor with a built-in terminal, but don’t want VS Code’s complexity. Open the repo, click a .py, hit Run. |
Thonny for beginners (single download, simple UI). PyCharm Community for a full pro IDE — closest like-for-like swap with VS Code, free for open-source / personal use. |
If you’re on Linux or macOS, paths 2 and 3 work the same — the repo’s scripts are pure Python with no Windows-specific bits except the default COM-port detection (you can override with --port /dev/ttyACM0 or similar).
The repo includes a .vscode/extensions.json hint that VS Code reads on first open. Accept the “Install recommended extensions” prompt to get:
.py, syntax highlighting, IntelliSense.The repo also ships a .vscode/tasks.json (gitignored, locally maintained) with one-click tasks for build firmware, upload firmware, serial monitor, build Windows release, and every bench tool. Open via Ctrl+Shift+P → Tasks: Run Task.
Vendor-neutral host scripts that wrap the firmware's universal OBD-II services. These work across manufacturers (GM, Ford, Toyota, BMW, etc.) because Mode $04 / Mode 9 are SAE J1979 mandates and UDS $14 / $10 03 are ISO 14229. See tools/obd2/README.md for the NRC reference table.
| Script | What it does |
|---|---|
| obd2/clear_dtc.py | Universal Clear DTC. Pass 1 broadcasts OBD-II Mode $04 to functional 0x7DF and collects each ECU's response from 0x7E8…0x7EF. Pass 2 falls back to physical UDS $10 03 + $14 FF FF FF per responder when Mode $04 NRCs. |
| obd2/scan_full.py | Mode 9 dump for every module on the bus — VIN, ECU Name, CAL IDs, CVNs, GM $1A B4 cal info. Default output is the firmware text; --json emits parsed structured data per module. |
Host-side serial drivers for routine work with a flashed Feather M4 CAN: capture, VIN, SD upload, diagnostics.
| Script | What it does |
|---|---|
| capture_bus.py | Captures CAN frames straight off the Feather to a SavvyCAN-format CSV — the input format the kernel-extraction tools expect. |
| capture_read.py | Drives a full ECU flash read through the Feather and saves the result to a binary file on the host. |
| capture_write.py | Writes firmware to an ECU through the Feather with block-by-block verification. |
| flashy_diag.py | Scripted serial driver: send a sequence of Feather commands and capture each response with wallclock timestamps. Handy for bench recovery probes and protocol experiments. |
| sd_upload.py | Uploads a file from the host to the Feather’s SD card over serial at ~5 KB/s. Used to stage write payloads without pulling the card. |
| set_rtc_local.py | Sets Flashy’s PCF8523 RTC from the PC’s current local time (or UTC with --utc). Auto-detects the Feather by USB VID. Exits the boot menu first so SETCLOCK isn’t intercepted. |
| vin_scan.py | Scans the CAN bus for all modules, prints each VIN, and offers an interactive update for any module. |
| vin_update.py | Updates the VIN on a GM ECU via the Feather in programming mode (auth + $2E F190 / $3B 90). |
| vinwrite_debug.py | Runs VINWRITE through escalating session/auth stages so the log shows exactly which gate the ECU requires; stops at the first stage that succeeds. |
Pull kernel binaries and protocol structure out of CAN-bus captures.
| Script | What it does |
|---|---|
| extract_kernel.py | Pulls the T87 write kernel out of a SavvyCAN CSV by reassembling the ISO-TP $36 TransferData frames after $34 RequestDownload. |
| extract_kernel_from_csv.py | General-purpose kernel extractor for any ISO-TP multi-frame upload captured to SavvyCAN CSV. Prints embedded copyright/version strings if it finds them. |
| extract_usbjtag_kernel.py | Variant of the kernel extractor tuned for E38 captures. |
| parse_write_protocol.py | Reads a SavvyCAN write capture and breaks it into protocol phases: diagnostics, security, kernel upload, erase, write, finalize. |
| socketcan_sniff.py | Connects to a remote socketcand daemon and writes frames to a SavvyCAN-compatible CSV. Useful when the bus is on a different machine. |
Drivers and patchers targeted at the T87A 8L90 TCM (SPC564A80).
| Script | What it does |
|---|---|
| t87_calwrite.py | Writes the T87 TCM calibration region only, with readback verification. Smaller blast radius than a full write. |
| t87_fullwrite.py | Full T87 TCM flash write (OS + calibration) through the Feather, with verify. |
| t87a_patch.py | Applies the 5-patch unlock recipe to a T87A image and recalculates Boot Block CRC16 + Wordsum checksums. See the T87A Unlock Recipe for the patch map. |
| test_calread.py | Bench validation: partial reads of T87 NVM/adaptation and calibration regions to confirm CALREAD is healthy. |
| test_read.py | Full-read driver with double-read + checksum compare across two consecutive reads (no power cycle in between). |
| test_t87_fullread_quick.py | Quick FULLREAD smoke test — fires the command and watches for kernel-upload completion. |
| test_t87_write_kernel.py | Safe kernel-upload test: uploads kernel and checks it responds; does NOT erase or write flash. |
| test_write.py | Single-sector erase + write + verify on E38; useful as a minimal-risk write smoke test. |
Bench helpers for the E92 ECM family. E92A refers to the late-model (2017+) variant that uses GM 5-byte algo 146.
| Script | What it does |
|---|---|
| e92a_fullread_drive.py | Drives E92FULLREAD on a late-model E92 by orchestrating the firmware’s built-in algo-146 unlock + kernel upload from the host side. |
| e92a_seedkey_test.py | Captures a fresh E92A seed and computes candidate keys for the highest-priority GM 5-byte algorithm indices — a research aid, not a normal-flow tool. |
| e92a_try_algo.py | Fetches a fresh seed, computes the key for a given algo index, and submits it — one MEC counter attempt per run. |
| e92a_try_key.py | Sends a single $27 02 key on a primed E92A and reports the ECU response. Useful for validating an externally-computed key. |
| e92a_unlock_attempt.py | End-to-end E92A authentication using the firmware’s built-in algo 146. |
GM seed-to-key derivation: the algorithms behind $27 SecurityAccess.
| Script | What it does |
|---|---|
| seed_key_algo.py | Reference implementation of the GM 2-byte seed-to-key algorithm space (1280 algo indices). |
| gm5byte/keylib.py | Core utilities for the GM 5-byte (AES-128) seed-to-key derivation pipeline used by T87A algo 135 and E92A algo 146. |
| gm5byte/keygen.py | CLI wrapper around keylib for one-shot seed-to-key computation. |
| gm5byte/gui.py | PyQt5 GUI front-end for the 5-byte derivation, for users who prefer a window over a terminal. |
Used by the maintainers to produce releases. Most users won’t need these directly.
| Script | What it does |
|---|---|
| bin2header.py | Converts a raw binary file to a C header with a byte-array constant plus size and load-address macros. |
| build_exe.py | Builds the Windows release: PyInstaller bundles for each user-facing tool, batch shortcuts, portable zip, and (with --installer) the Inno Setup Flashy-Tool-Setup-*.exe. |
| build_kernel_registry.py | PlatformIO pre-build hook: scans Cernels/ for kernel.bin + meta.json entries and emits the auto-generated headers the firmware uses to expose the runtime kernel registry (KLIST / KUSE). |
| detect_port.py | Auto-detects the Feather M4 CAN’s serial port by USB vendor/product ID; used by the .bat launchers in the Windows release. |
| pyinstaller_hook.py | Runtime hook for PyInstaller bundles: fixes data-file paths and pauses the console on exit so users can read errors. |