Metadata-Version: 2.4
Name: ingenic-flash-tool
Version: 0.5.5
Summary: Lightweight CLI tool for flashing Ingenic SoCs via USB boot mode
License-Expression: MIT
Project-URL: Repository, https://github.com/will-tm/ingenic-flash-tool
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyusb>=1.2.0
Dynamic: license-file

# ingenic-flash-tool

Lightweight Python CLI tool for flashing Ingenic T-series SoCs (T20/T21/T23/T30/T31/T40/T41) via USB boot mode. Supports SPI NOR flash and eMMC.

## Installation

```bash
pip install ingenic-flash-tool
```

Requires `libusb` on your system:
- **Linux**: `sudo apt install libusb-1.0-0` or `sudo pacman -S libusb`
- **macOS**: `brew install libusb`

### udev rules (Linux)

To use without `sudo`, add a udev rule:

```bash
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="a108", MODE="0666"' | sudo tee /etc/udev/rules.d/99-ingenic.rules
sudo udevadm control --reload-rules && sudo udevadm trigger
```

## Usage

### Detect device

```
$ ingenic-flash-tool detect
Device found!
  USB PID:  0xc309 (T-series)
  CPU info: b'T 3 1 V ' (hex: 5420332031205620)
```

### Flash SPI NOR

```
$ ingenic-flash-tool -v flash prj008 firmware.bin
INFO: Boot ROM CPU info: 5420332031205620
INFO: Loading ginfo (324 bytes) to 0x80001000
INFO: Loading SPL (32384 bytes) to 0x80001800
INFO: SPL running: 5420332031205620
INFO: Loading stage2 (417656 bytes) to 0x80100000
INFO: Stage2 running: b'PRJ\x00\x00\x00\x00\x00'
INFO: Flash JEDEC ID: 0xef7018
INFO: Initializing flash...
INFO: Writing 232652 bytes (227K) at offset 0x0
  [########################################] 100% (232652/232652)
Flash complete!
```

### Flash eMMC

```
$ ingenic-flash-tool -v flash prj008_mmc0 firmware.bin
INFO: Stage2 running: b'PRJ\x00\x00\x00\x00\x00'
INFO: Initializing flash...
INFO: Writing 232652 bytes (227K) at offset 0x0
  [########################################] 100% (232652/232652)
Flash complete!
```

### Options

- `-v` / `-vv` — increase verbosity
- `--offset 0x40000` — write at a specific flash offset
- `--erase-all` — full chip erase before writing (SPI NOR only, default: sector erase)
- `--no-reboot` — don't reboot the device after flashing

### Boot device

Boot into stage2 burner without flashing (useful for debugging):

```
$ ingenic-flash-tool boot prj008
Device booted into stage2: b'PRJ\x00\x00\x00\x00\x00' (50524a0000000000)
```

### Show chip info

```
$ ingenic-flash-tool info
Supported chips:
  prj008      PID=0xc309  ginfo=0x80001000 [bundled]
  prj008_mmc0 PID=0xc309  ginfo=0x80001000 [bundled]
  t20         PID=0xc309  ginfo=0x80001000 [bundled]
  ...
```

## Supported Hardware

| Board/Target   | Flash Type | Status |
|----------------|------------|--------|
| prj008         | SPI NOR    | Full support (T31/T33 camera board) |
| prj008_mmc0    | eMMC/SD    | Full support (MSC0 slot) |
| T20–T41        | —          | Boot only (need board-specific ginfo + config) |
| 40+ chips      | —          | Bundled SPL/U-Boot for all Ingenic SoCs |

Full flash support requires board-specific firmware files (`ginfo.bin`, `spl.bin`, `uboot.bin`, and config blobs). PRJ008 files are bundled for both SPI NOR and eMMC.

## How It Works

The tool implements the Ingenic USB boot protocol, reverse-engineered from USB packet captures:

1. **Boot ROM** — The SoC enters USB boot mode. The tool sends a DDR configuration block (ginfo) and first-stage bootloader (SPL) via vendor USB requests.

2. **SPL** — The SPL initializes DDR memory, then stays resident and re-implements USB. It does **not** return to the boot ROM. The tool sends the stage2 burner firmware (U-Boot) via the SPL's USB interface.

3. **Stage2 Burner** — A specialized U-Boot build that handles flash operations. The tool sends board configuration, then writes firmware in 64KB chunks with CRC verification. Supports SPI NOR (with JEDEC auto-detection), SPI NAND, and eMMC/SD.

### Protocol details

```
Boot ROM requests: GET_CPU_INFO(0x00), SET_DATA_ADDR(0x01), SET_DATA_LEN(0x02),
                   PROGRAM_START1(0x04)
SPL requests:      FLUSH_CACHES(0x03), PROGRAM_START2(0x05)
Stage2 requests:   GET_ACK(0x10), INIT(0x11), WRITE(0x12), UPDATE_CFG(0x14),
                   REBOOT(0x16), GET_FLASH_INFO(0x26)
```

Key discovery: `FLUSH_CACHES` and `PROGRAM_START2` are only supported by the resident SPL, **not** the boot ROM (contrary to the JZ4760 documentation). The boot ROM only supports requests `0x00`–`0x02` and `0x04`.

## Development

```bash
git clone https://github.com/will-tm/ingenic-flash-tool.git
cd ingenic-flash-tool
python -m venv .venv
source .venv/bin/activate
pip install -e .
```

## License

MIT
