# SPI flash dumping (CH341a) Required once: backs up the bootloader/app (`IC300`) and factory data (`IC301`) before any modding, and produced the dumps every finding here rests on. Dumps stay local — never commit or publish them (vendor IP; `.gitignore` blocks `*.bin`). Involved enough to deserve its own page; checklist version in `RE-PROCESS.md` §1. ## 0. What you need - Black CH341a Mini Programmer (v1612-class flow below; others similar), SOIC-8 clip, multimeter, a Linux host with `flashrom`. - Target: core module, `IC300` (boot+app) + `IC301` (data), both `MX25L12833F`. ## 1. Identify the chips Factory stickers cover the markings — peel carefully, photograph first. Confirm SOIC-8 pin 1 (dot/dimple, lower-left on both packages below) and probe `VCC`/`GND` powered on (`VCC` = 3.3 V on this board). The exact part name matters for `flashrom -c`. ![IC300 + IC301, stickers removed — both MX25L12833F](photos/ic300-ic301-closeup.jpg) ## 2. Fix the programmer voltage (do not skip) The black board's 3.3/5 V jumper only switches ZIF `VCC`. The CH341A chip itself stays on 5 V USB, so `CS/MOSI/CLK` idle at ~5 V even in the 3.3 V position — out of spec for 2.7–3.6 V flash (degrades/kills). Verify: plug in empty, meter `GND → CS/MOSI/CLK`. If ~5 V, either do the 3.3 V mod (feed CH341 `VCC` pin 28 from the `AMS1117` 3.3 V output) or use a level-shifter adapter board. Re-meter: all signals ~3.3 V before touching the device. ## 3. Select SPI mode Two personalities: `1a86:5523` + `ttyUSB0` = UART mode (useless here), `1a86:5512` = SPI mode (`flashrom` needs this). Move the P/SPI jumper, replug, confirm with `dmesg` (`New USB device found, idVendor=1a86, idProduct=5512`). ## 4. Permissions and containers - `Couldn't open device … errno=13` = permissions. Test with `sudo`; make it permanent with a udev rule for `1a86:5512` (`MODE="0666"`) + `udevadm control --reload-rules && udevadm trigger`. - `sudo` inside distrobox/toolbox is **not** host root for USB. Run on the host: `distrobox-host-exec sudo flashrom …` (or `flatpak-spawn --host …`); podman / docker need `--privileged -v /dev/bus/usb:/dev/bus/usb`. ## 5. Dump (read-only) 1. Device fully unpowered. Hold the SoC in reset if clipping in-circuit (avoids bus contention with the C6748 driving SPI); `WP`/`HOLD` pulled high. 2. Seat the SOIC-8 clip on pin 1 → pin 1. A slipped clip shorts rails — reseat, don't force. 3. Per chip, read **twice** to scratch files, then keep the verified copy as the canonical dump: `flashrom -p ch341a_spi -c -r ic300_a.bin` (then `_b`). 4. `sha256sum ic300_*.bin; cmp ic300_a.bin ic300_b.bin` — must be identical; expect exactly 16,777,216 B per MX25L12833F. Third read on any mismatch. Then save one verified copy as `ic300.bin` (`ic301.bin` for the other chip). Canonical names everywhere: `ic300.bin` / `ic301.bin`. 5. Never `-w`/`-E` (write/erase) during backup. Writing is only for recovery with a verified dump in hand. ## 6. Sanity-check the dumps - IC300 starts `54 49 50 41` (`TIPA` = AIS `0x41504954`), entropy ~6.9. - IC301 starts `AILS`, pattern names in clear, `RIFF/WAVE`s from `0x8007E0`. - `onlySD == 0` string-set test vs the running firmware version (see `RE-PROCESS.md` §2) confirms which release is flashed. ## Troubleshooting | Symptom | Cause → fix | |---|---| | `1a86:5523`, `ttyUSB0` | UART mode → move mode jumper, replug | | `Couldn't open … errno=13` (even with sudo in container) | USB not passed through → run on host (§4) | | `FF…`/`00…` reads, JEDEC ID unknown | Clip seating / wrong `-c` name / chip still powered by board → reseat, hold reset, re-probe `VCC` | | Signals meter ~5 V | Unmodded black CH341a → §2 before retrying |