Files
2026-09-30 22:48:06 +02:00

2.3 KiB

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

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.