54 lines
2.3 KiB
Markdown
54 lines
2.3 KiB
Markdown
# Firmware update (SD path)
|
|
|
|
How a stock or modded `.bin` gets onto the device and exactly what is verified.
|
|
No hardware access needed — SD card + OLED only.
|
|
|
|
## Trigger
|
|
|
|
File named `Lofi-12 XT.bin` at SD root (from the official update ZIP:
|
|
https://sonicware.jp/pages/downloads), then hold **PAD while powering on**.
|
|
Updater (`SYSTEM UPDATE`) lives in SPI AIS flash, **not** in the `.bin`, so a
|
|
bad SYSTEM image can always be reverted with a stock SD.
|
|
|
|
## Stages (OLED text)
|
|
|
|
1. `Checking... 0%` — parse + validate the file (checks below). Failures:
|
|
`The firmware file not exist.`, `This card is invalid format.`,
|
|
`ERROR : This file is invalid.` / `Check the firmware file.`
|
|
2. `Are you sure?` — `[CLR] : No / [OK] : Yes`.
|
|
3. Per section (`>> BOOT / SYSTEM / PRESET / MCU / MCU Boot`, prompts `BOOT:`…):
|
|
`Erasing...`, `Writing...`, `Verifying...` with `%` progress.
|
|
4. `100%, done.` / `Update completed.` (`100%, NG.` / `Update failed.` on error)
|
|
→ `Please restart.`
|
|
|
|
## Checks performed on the `.bin`
|
|
|
|
1. Magic: `cmtd` @`0x00`, `mmtd` @`0x30`, `sect` chain from `0x54`.
|
|
2. `cmtd+0x04` filesize equals actual file size.
|
|
3. `sect` chain tiles EOF exactly (`next = off + 12 + len`); load addresses must
|
|
land in DDR (`0xC2xxxxxx`); entry point must sit inside the code sect.
|
|
4. **Checksum** `cmtd+0x08` — recomputed and compared (`CMPEQ`, reject =
|
|
`ERROR : This file is invalid.`). Rule (proven 3/3, see below):
|
|
CRC32-IEEE, init 0, over the whole file with bytes `[8:12]` replaced by
|
|
`0xC27C6282`. `mmtd+0x08` flags are covered as-is (no special handling).
|
|
|
|
## Forging a valid image
|
|
|
|
```bash
|
|
python3 tools/lofi_patch_string.py stock.bin mod.bin OldString NewStringX
|
|
python3 tools/prove_checksum.py mod.bin # expect MATCH
|
|
```
|
|
|
|
`lofi_pack.py`/`lofi_patch_string.py` stamp the checksum automatically
|
|
(`lofi_image.compute_checksum`); `--checksum keep` preserves the old value.
|
|
`analysis/solve_ckseed.py` re-derives the seed constant from any stock image
|
|
(GF(2) solve, expect `C27C6282`).
|
|
|
|
## Notes
|
|
|
|
- Public ZIPs ship only the SYSTEM section; BOOT/PRESET/MCU use separate files.
|
|
- Only same-length string/asset/constant edits keep every address stable
|
|
(Level-0). Longer content needs slack-space pointer patching (`lofi_xref.py`).
|
|
- The AT32 USB MCU updates through `updateMCUSection` — protocol unreversed;
|
|
leave MCU sections alone.
|