This commit is contained in:
Dejvino
2026-09-30 22:48:06 +02:00
commit 8913cb4314
37 changed files with 3190 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
# Lofi-12 XT — Findings Library
Living knowledge base for this device. Process/tips live in `RE-PROCESS.md`.
Per-version firmware notes: `Lofi-12XT_v*/…/reversed.md`; version diff: `rev-diff.md`;
mod feasibility: `tweakability-report.md`; tool docs: `tools/README.md`.
Deep dives: `docs/hardware.md`, `docs/bootloader.md`, `docs/firmware-update.md`,
`docs/firmware/v1.5.205.md`.
## 1. Hardware
- Device: Sonicware Lofi-12 XT (shares platform with SmplTrek/Cydrums).
- Main SoC (core module): **TI TMS320C6748** — ARM9 + C674x DSP. Marking on unit:
`TMS320 C6748EZW T / 13CP99W / GI 375 / 527 ZWT`.
- DRAM (core module): **EtronTech EM68C16CWQG-25H** — 1 Gbit DDR2, base `0xC0000000`.
- SPI flash (core module, 2×): **Macronix MX25L12833F** (`MXIC MX 25L12833F M2I-10G`),
16 MByte each, SOIC-8, silkscreen `IC300` / `IC301`. Shipping units hide the
marking under small stickers (`C047`/`C949`-style labels) — peel + photo to confirm.
- USB/aux MCU (main board): **ARTERY AT32F421K8T** (own firmware, out of scope).
- Storage: full-size SD slot (firmware update + samples/projects).
- PCBs seen: `405-VTOR-3852` (I/O), `405-VTOR-3849B` (main), `405-VTOR-3853` (jack),
core module with `CN201A/CN200A/CN203A/CN203B` board-to-board connectors.
- Silkscreen pin tables on main board expose `UART1_RX1/TX1`, `SPI1_SCK/MOSI`,
`SD_*`, `USB_DP/DN`, key/LED matrix — worth mapping before any invasive work.
## 2. Memory map (DDR2)
| Region | Content |
|---|---|
| `0xC0000000…` | DDR2 base (128 MB) |
| `0xC2xxxxxx` | SD `.bin` application image (DSP). v1.5 code `C2B80C00`, strings `C2D84DE0`, assets `C2DA7600` |
| `0xC7074630–C70B0598` | SPI AIS bootloader image (DSP), entry `C70A28A0` |
| `0xC706F280` | Runtime constant seen in updater (also == checksum seed, §5) |
| `0xC27C6282` | Scratch DDR used by updater (§5; value doubles as checksum seed) |
## 3. SPI flash layout (`ic300.bin` / `ic301.bin`, 16 MiB each)
Dumps: `ic300.bin` (`c2b86808…`), `ic301.bin` (`81f7b1f5…`). Always keep these
as recovery backups; re-verify with a second read (`sha256sum` + `cmp`).
**IC300 (boot + app):** TI AIS image, magic `0x41504954` (`TIPA`) at file `0x0`.
PLL/DDR config (`0x5853590D` ×2), then 10× Section Load (`0x58535901`):
| File off | DDR | Size |
|---|---|---|
| `0x000050` | `C7074630` | `0x1D0` |
| `0x00022C` | `C7074800` | `0x33B00` (main code) |
| `0x033D38` | `C70A8300` | `0x28CC` (rodata) |
| … | `C70AABD0`/`C70AABE0`/`C70AABF0` | `0xC`/`0xC`/`0xD44` |
| … | `C70AF000`/`C70AF4E8`/`C70AF5EC`/`C70AF660` | `0x200`/`0x104`/`0x70`/`0xF38` |
`JumpClose (0x58535906)` at file `0x38660` → entry `C70A28A0` (DSP reset prelude
`ZERO b0; mvc b0,ier; mvc b0,csr`). After it: `FF` gap to `~0x100000`, data to
`~0x1EFFFF`, `FF` gap `0x1F–0x4Fxxxx`, data `0x500000–0xFC7C17`. No AIS CRC opcodes.
**IC301 (data):** `AILS` header + drum-pattern names (`KICK/HIHAT/BALLAD/BLUES/…`),
24× `RIFF/WAVE` starting `0x8007E0`, nearly full to `0xFFFD7B`. Factory-sample flash.
**Update path (from updater strings + code):** `SystemUpdater::{start,
updateBootSection, updateMainSection, updatePresetSection, updateMCUSection,
updateMCUBootSection}(CatMetaData::ROMSection)` + `SystemVerify::verifyPresetSection`.
Public ZIPs ship only the SYSTEM section (the SD `.bin`); BOOT/PRESET/MCU use
separate (unreleased) files. Updater lives in AIS flash, so a bad SYSTEM image
cannot kill recovery — hold PAD while powering on → `SYSTEM UPDATE` still works.
## 4. SD `.bin` container (`cmtd/mmtd/sect → EOF`)
| Off | Field |
|---|---|
| `0x00` | `cmtd` magic |
| `0x04` | u32 LE filesize (must match actual) |
| `0x08` | u32 checksum — **solved, §5** |
| `0x0C` | reserved 0 |
| `0x10–0x2F` | `12, 1, 3, fw_maj, fw_min, fw_patch, 48, remaining` |
| `0x30` | `mmtd` magic; `+0x04` remaining; `+0x08` flags (per-build, part of hash) |
| `0x40` | fw triple; `0x4C` entry point; `0x50` sect count |
| `0x54…` | `sect` ×N: `73 65 63 74` + u32 load_addr + u32 len + payload; must tile EOF |
Known builds: v1.1.156 (1,595,605 B, entry `C26C4820`, 7 sects), v1.2.179
(1,606,197 B, entry `C26CA4C0`, 6 sects), v1.5.205 (1,707,049 B, entry
`C2CD1AA0`, 7 sects). Code is C674x LE, entropy ~6.89, unencrypted. Parser/packer:
`tools/lofi_image.py` (`parse_image` asserts filesize + chain fit).
## 5. Checksum (SOLVED)
**Rule:** `cmtd+0x08` = CRC32-IEEE (init 0) over the entire file with bytes
`[8:12]` replaced by `0xC27C6282`.
- `tools/lofi_image.py`: `CKSEED = 0xC27C6282`, `compute_checksum()`; `build_image()`
auto-computes by default (`--checksum keep` in `lofi_pack.py` preserves).
- Proof: GF(2) linear solve per image for the 32 unknown bits at `[8:12]` gives
`K = 0xC27C6282` on **all three** images independently (2⁻⁶⁴ fluke); forward
recompute reproduces `F58AF539 / DFF0D8C2 / B17C0857`; `unpack→pack` rebuilds
stock v1.5.205 byte-identical; a `Threshold→ThresholX` mod forges to a
self-consistent `462F735B`.
- Code anchors (bootloader DSP): CRC routine `C70A0A60`
(`NOT A6→state`, poly `EDB88320` via `MVK/MVKH`, byte loop, final `NOT` in delay
slot ≡ zlib chaining `F(buf,len,init)`); 4K-chunk caller `C708E4E4`
(`MVK 0x1000`, `CMPGT`, `CALLP C70A0A60`); check fn `C709E7C0`
(16-byte header CRC init 0 → chained 0x40000 chunks → `CMPEQ A13,A12` compare);
orchestrator `C708678C CALLP C709E7C0`, reject path builds
`ERROR : This file is invalid.` (`C70A8E82`).
- Forging: build image normally, then set `[8:12] = compute_checksum(image)`.
## 6. OLED / updater UI strings (orientation)
`Checking... 0%`, `Check the firmware file.`, `ERROR : This file is invalid.`,
`Erasing.../Writing.../Verifying... 0%`, `100%, done./OK./NG.`,
`Update completed./Update failed.`, `Please restart.`, `Are you sure?`,
`[CLR] : No / [OK] : Yes`, `>> BOOT/MCU/MCU Boot/PRESET/SYSTEM`,
`BOOT:/MCU:/MCU Boot:/PRESET:/SYSTEM:`, `$ systemupdate`, `[Lofi-12 XT] ~`,
`SYSTEM INFO/VERSION/BOOT/SYSTEM/MCU`, crash dumper (`Legacy NMI Exception`,
`A0–A31/B0–B31`, `NTSR/ITSR/…`). v1.5-only markers: `AppAudioExport*`,
`MIsolator/MRackComp/SlipRoll/HoldDelay`, `MIDINoteMap`, `REVERSE`,
`removeResourceFork` (all present in IC300 → board runs v1.5).
## 7. Open questions
- `mmtd+0x08` flags semantics (timestamp? covered by checksum as-is, no need to crack).
- Exact flash section table for BOOT/PRESET/MCU offsets (only SYSTEM reverse-engineered).
- AT32F421 firmware extraction/update protocol.
- UART/JTAG test-point mapping (silkscreen names exist, continuity not traced).