Releases: ajsb85/sprdflash-rs
Release list
SPRD Flash Tool v0.8.0
Standalone extraction — whole-flash backup and layout reconstruction, no matching PAC or on-device partition table required.
Highlights
💾 Whole-flash backup — dump --full
sprdflash dump --full --enter-download --pac any-rda8910.pac --out ./dump
Reads the entire flash into flash.bin, auto-discovering its size by
binary-searching READ_FLASH — this FDL2 has no geometry command, so an in-range
read replies READ_FLASH and an out-of-range one replies INVALID_CMD, and the
boundary is the flash size. Needs only any RDA8910 PAC for the FDL stages.
Hardware-verified on an Air724UG: size auto-found as 8 MiB, every partition
matching its offset in the image.
🧩 Reconstruct a layout from a dump — layout
sprdflash layout --flash ./dump/flash.bin --out layout.xml
Recovers a proposed <BMAConfig> from a full dump alone — no device, no
matching PAC. It classifies on-flash content: U-Boot uImage code regions (magic
0x27051956, exact size, header + payload CRC-32 verified), LuatOS luadb,
and the wear-levelled NOR filesystem back half (longest single-generation run =
the live FS). Hardware-verified: 5/5 flash-resident partition bases + reserved
sizes reproduced byte-exact vs the real PAC.
Region names are generic content-type defaults (uimage_0, luadb_0,
filesystem_0, nv_0) — the flash stores no partition role names, and roles are
firmware-specific. What a dump can't give (documented): role names, the FDL
loaders (they live in SRAM, not NOR), and the PAC's erase/control directives.
🔎 Capability probe — parts
Probes an FDL2's capabilities and flash extent. On the RDA8910, every
introspection command (READ_PARTITION, chip/flash info) replies INVALID_CMD,
which is why the layout has to be recovered from content rather than queried.
Verifying downloads
echo 'ajsb85@firechip.dev ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXmKlNp62mfIFNHT4Duv6vcTwfqb/M6OUs34upSpN/L' > allowed_signers
ssh-keygen -Y verify -f allowed_signers -I ajsb85@firechip.dev -n file \
-s sprdflash-v0.8.0-x86_64-unknown-linux-gnu.sig \
< sprdflash-v0.8.0-x86_64-unknown-linux-gnu
gh attestation verify sprdflash-v0.8.0-x86_64-unknown-linux-gnu --repo ajsb85/sprdflash-rsChanges
- feat(cli):
dump --full— standalone whole-flash backup with size discovery - feat(cli):
layout— reconstruct a proposed<BMAConfig>from a dump - feat(cli):
parts— probe FDL2 capabilities / flash extent - feat(core):
crc32(IEEE) + thereconstructmodule
Full Changelog: v0.7.0...v0.8.0
SPRD Flash Tool v0.7.0
Golden-device cloning and flexible extraction, built on the proven read-back path.
Highlights
🧬 Clone a reference unit into a flashable golden PAC — clone
sprdflash clone --enter-download --pac reference.pac --out golden.pac
Reads a device's partitions off the flash (read-only) and splices them into a
copy of the reference PAC — same FDL stages, layout, markers, and XML — then
refreshes the header + payload CRC-16-ARC and validates the result before
writing. The output is a flashable .pac capturing a configured reference
unit's firmware, which you can flash to other units — no vendor tool.
Hardware-verified on an Air724UG (RDA8910): cloning a device that holds the
reference firmware produces a golden PAC byte-identical (SHA-256) to the
reference — a lossless round-trip.
🎯 Arbitrary-region dump — dump --region
sprdflash dump --enter-download --pac any-rda8910.pac \
--region 0x60000000:42112 --region 0x60010000:2468352 --out ./dump
Read any flash range(s) as ADDR:SIZE (hex or decimal, repeatable) instead of
the PAC's partition layout — the PAC is then used only for the FDL stages.
🔁 Any RDA8910 PAC works for the FDL stages
The FDL1/FDL2 download agents are interchangeable across firmware versions for
the same chip. Hardware-verified: dumping an Air-firmware device using a LuatOS-
HMI PAC's FDLs yields byte-identical bytes to a dump with the matching PAC. So
you don't need a device's exact firmware to extract or clone it — any PAC for the
chip supplies the FDLs.
Note: fully PAC-free extraction (no PAC at all) is intentionally not shipped
— it would require redistributing Unisoc's proprietary FDL blobs (a licensing
problem) and reverse-engineering on-device partition-table discovery. Bring any
RDA8910 PAC for the FDLs instead.
Verifying downloads
echo 'ajsb85@firechip.dev ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXmKlNp62mfIFNHT4Duv6vcTwfqb/M6OUs34upSpN/L' > allowed_signers
ssh-keygen -Y verify -f allowed_signers -I ajsb85@firechip.dev -n file \
-s sprdflash-v0.7.0-x86_64-unknown-linux-gnu.sig \
< sprdflash-v0.7.0-x86_64-unknown-linux-gnu
gh attestation verify sprdflash-v0.7.0-x86_64-unknown-linux-gnu --repo ajsb85/sprdflash-rsChanges
- feat(cli):
clone— capture a device into a flashable golden PAC - feat(cli):
dump --region ADDR:SIZEfor arbitrary flash ranges
Full Changelog: v0.6.0...v0.7.0
SPRD Flash Tool v0.6.0
Read-back extraction, and diagnostics hardened by real-device recovery testing.
Highlights
📤 Extract partitions off a device — dump
sprdflash dump --enter-download --pac firmware.pac --out ./dump
Reads every partition straight off the flash with READ_FLASH and writes one
<file_id>.bin per partition — read-only, no writes to the device. The PAC
supplies this device's FDL1/FDL2 stages and the partition layout (addresses +
sizes); the bytes come off the device.
Hardware-verified on an Air724UG (RDA8910): all four partitions (5.72 MiB) dump
byte-identical (SHA-256) to the flashed PAC — proving READ_FLASH reads
persistent flash, not just data written in the same session. A real
backup/clone/forensics primitive.
♻️ flash auto-recovers a module stuck in FDL2
If a previous flash aborted after loading FDL2 (e.g. a genuine read-back verify
failure), the module is left in FDL2 and a fresh flash's PDL handshake would
fail. flash now detects that, sends a NORMAL_RESET, waits for the module to
re-enumerate and its firmware to settle, and retries once — no manual reset
needed. Also available standalone as sprdflash reset.
🔎 Honest timeouts
Read timeouts reported deadline - now, which is always ~0 once the deadline has
passed, so every timeout read "after 0ns". They now report the real time waited
(e.g. after 5.00s).
Verifying downloads
Every binary ships with a detached SSH signature (.sig, Ed25519, namespace
file, key SHA256:1wCKrSPq3V4q7DkiomqRJKzr6Vc1bY+eKU1qRvEvGKk) and keyless
Sigstore build provenance:
echo 'ajsb85@firechip.dev ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXmKlNp62mfIFNHT4Duv6vcTwfqb/M6OUs34upSpN/L' > allowed_signers
ssh-keygen -Y verify -f allowed_signers -I ajsb85@firechip.dev -n file \
-s sprdflash-v0.6.0-x86_64-unknown-linux-gnu.sig \
< sprdflash-v0.6.0-x86_64-unknown-linux-gnu
gh attestation verify sprdflash-v0.6.0-x86_64-unknown-linux-gnu --repo ajsb85/sprdflash-rsChanges
- feat(cli):
dump— extract partitions off the device (read-only) - fix(cli): auto-recover a flash from FDL2 (reset + retry)
- fix(transport): report the real read-timeout duration, not
0ns - refactor(flash): shared FDL bring-up for
runanddump
Full Changelog: v0.5.0...v0.6.0
SPRD Flash Tool v0.5.0
Full Changelog: v0.4.0...v0.5.0
SPRD Flash Tool v0.4.0
High-assurance flashing and unattended line operation.
This release adds a byte-for-byte read-back check for units that need it, a
continuous "run all shift" line mode, and a hardware-free test path that
exercises the entire flash protocol in CI with no device attached.
Highlights
🔎 Post-write read-back verify — --verify-readback
After each partition is written, its bytes are read straight back off the device
with the BSL READ_FLASH command and compared to the source image. Any
difference fails the flash immediately with read-back verify failed for <partition>, so a marginal cable, a flaky USB hub, or a bad flash block is
caught on the line instead of in the field.
It roughly doubles flash time, so it is off by default — reserve it for
high-assurance builds or fixture bring-up.
sprdflash flash firmware.pac --format --verify-readback
♾️ Continuous line mode — --loop
Runs the line unattended: each station keeps flashing units, waiting for the
operator to swap in the next module between cycles, until you press Ctrl-C.
The stop is graceful — in-flight units finish and their records are written
before exit. Pair it with --metrics-addr so a Prometheus/Grafana board watches
yield and throughput live for the whole shift.
sprdflash line firmware.pac \
--station fixture-1:COM12 --station fixture-2:COM22 \
--format --loop --metrics-addr 0.0.0.0:9184 \
--records /var/log/flash/units.jsonl
Memory stays bounded no matter how long it runs: records stream to the JSONL
sink and fold into the metrics counters, with only a recent tail kept in memory
for the summary. A short floor between cycles keeps a misconfigured or empty line
from busy-spinning.
🧪 Hardware-free end-to-end tests
The serial byte stream now sits behind a Transport trait, and a new
MockTransport speaks just enough of the PDL and BSL protocols to drive a
complete PDL → BSL → partitions → format → reset flash with no device
attached. CI now covers the happy path, adaptive-retry recovery after a
dropped ack, and both the passing and corruption-detected read-back paths.
Verifying downloads
Every binary ships with a detached SSH signature (.sig) made with the
maintainer's Ed25519 key (SHA256:1wCKrSPq3V4q7DkiomqRJKzr6Vc1bY+eKU1qRvEvGKk,
signature namespace file):
# one-time: trust the signing key
echo 'ajsb85@firechip.dev ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXmKlNp62mfIFNHT4Duv6vcTwfqb/M6OUs34upSpN/L' > allowed_signers
ssh-keygen -Y verify -f allowed_signers -I ajsb85@firechip.dev -n file \
-s sprdflash-v0.4.0-x86_64-unknown-linux-gnu.sig \
< sprdflash-v0.4.0-x86_64-unknown-linux-gnu
# -> Good "file" signature for ajsb85@firechip.devEach binary also carries keyless Sigstore build provenance
from GitHub Actions, verifiable with gh attestation verify <file> --repo ajsb85/sprdflash-rs.
Changes
- feat(flash): optional post-write read-back verification (
--verify-readback) - feat(line): continuous unattended mode with graceful stop (
--loop) - test(flash): protocol mock and end-to-end flash tests
- refactor(transport): abstract the byte stream behind a
Transporttrait
Assets
| Platform | Binary |
|---|---|
| Windows x86-64 | sprdflash-v0.4.0-x86_64-pc-windows-msvc.exe |
| Linux x86-64 | sprdflash-v0.4.0-x86_64-unknown-linux-gnu |
| macOS Apple Silicon | sprdflash-v0.4.0-aarch64-apple-darwin |
| macOS Intel | sprdflash-v0.4.0-x86_64-apple-darwin |
Full Changelog: v0.3.0...v0.4.0
SPRD Flash Tool v0.3.0
Full Changelog: v0.2.0...v0.3.0
SPRD Flash Tool v0.2.0
Full Changelog: v0.1.0...v0.2.0
SPRD Flash Tool v0.1.0
Pure-Rust, cross-platform (Windows 11 + Linux/WSL) native flasher for
SPRD/UNISOC .pac firmware — RDA8910 / UIS8910 (Air724UG and friends) — built
for the manufacturing line and verified end-to-end on real hardware.
Highlights
- No vendor tool. Speaks the full download protocol directly: PDL (loads
FDL1) → BSL/FDL2 → partitions → optional cross-SDK--format→ reset. - Hardware-verified on a real Air724UG (RDA8910): a same-SDK reflash and
a cross-SDK change (LuatOS V4035 ⇄ CSDK V302340) that boots directly on the
soft reset with IMEI and NV intact. - Manufacturing line orchestrator: one thread per fixture, flashing and
boot-verifying in parallel, each unit boot-verified (ATI/IMEI) and written as
one JSON-lines record for the MES/ERP, with yield + throughput metrics and
automatic recovery of a wedged agent. - Sans-I/O core (
#![forbid(unsafe_code)]), Rust 2024 edition, MSRV
1.85,clippy -D warningsclean, CI on Windows + Linux.
What's in the box
| Crate | Role |
|---|---|
sprdflash-core |
Pure protocol: PAC parse, PDL + BSL framing, checksums, cross-SDK plan |
sprdflash-transport |
serialport byte stream, USB discovery, beacon-window connect, recovery |
sprdflash-flash |
Device driver: PDL → BSL → partitions → format → reset |
sprdflash-line |
Parallel stations, boot-verify, JSON-lines records, metrics |
sprdflash-cli |
The sprdflash binary: info, list-ports, flash, line |
Measured speed
6 MB in ~33 s (chunk = 2048), 22% faster than the reference Python (~42 s).
The device is flash-write-bound (~186 KiB/s), so line throughput comes from
per-fixture parallelism (~110 units/hour each) → thousands/day across a bank
of stations.
Usage
# one device, auto mode-switch, boots into the new firmware
sprdflash flash --enter-download firmware.pac
# cross-SDK change (formats FS, refreshes NV, keeps IMEI)
sprdflash flash --enter-download --format firmware.pac
# manufacturing line: parallel stations + MES records
sprdflash line firmware.pac --station f1:COM12 --station f2:COM22 \
--format --records units.jsonl
ERP / MES integration
Every flashed unit emits one JSON line (schema, PostgreSQL DDL with KPI views,
and a report catalog under docs/). See
docs/erp-mes-data-model.md.
Verification
-
The
v0.1.0tag is SSH-signed (git tag -v v0.1.0). -
The Windows binary is shipped with a detached SSH signature
(sprdflash-v0.1.0-x86_64-windows.exe.sig). Verify with:ssh-keygen -Y verify -f allowed_signers -I ajsb85@firechip.dev \ -n file -s sprdflash-v0.1.0-x86_64-windows.exe.sig \ < sprdflash-v0.1.0-x86_64-windows.exe
Signed-off-by: Alexander Salas Bastidas <ajsb85@firechip.dev>