Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sprdflash

Native flasher for SPRD/UNISOC .pac firmware — Air724UG, Air722UG and other RDA8910 / UIS8910 modules — that speaks the Spreadtrum BootROM/FDL download protocol directly over the serial port. No vendor download tool (CmdDloader.exe / ResearchDownload.exe) is required.

Sibling project to pacflash, which drives the vendor tool. sprdflash reimplements the wire protocol instead.

sprdflash info     firmware.pac    # parse + CRC-validate, classify FDL/flash/marker entries
sprdflash identify                 # connect to the BootROM and read its version (safe, read-only)
sprdflash flash    firmware.pac    # load FDL1/FDL2 and write every partition natively

How it works

The Spreadtrum BootROM speaks a framed protocol (BSL) over HDLC:

0x7e | escape( type[2] size[2] data[size] checksum[2] ) | 0x7e
  • BootROM mode uses a CRC16 checksum (poly 0x11021); once FDL1 runs the device switches to a ones-complement sum checksum.
  • Flash flow: autobaud (0x7e -> VER) -> CONNECT -> send FDL1 and EXEC -> re-handshake in sum-checksum mode -> send FDL2 and EXEC -> START_DATA/MIDST_DATA/END_DATA for each real partition -> NORMAL_RESET.

The FDL stages and partition load addresses are read straight from the .pac file table; logical erase/format markers are skipped.

Transport (important)

On the RDA8910/UIS8910 the BootROM enumerates as a CDC-ACM USB gadget (0525:A4A7, "SPRD U2S Diag"), but the BSL protocol does not ride the CDC serial framing. It uses the raw bulk endpoints of the data interface (OUT 0x02, IN 0x81), activated by a vendor control transfer (bmRequestType=0x21, bRequest=0, wValue=1). A plain COM-port open only sends the standard CDC line-state request, which the BootROM ignores — which is why a pyserial-only approach stays silent. sprdflash therefore talks to the device through libusb (--transport usb, the default). A --transport serial mode is provided for targets whose BootROM is exposed on a real UART.

Protocol references (clean-room; no vendor code used): the open-source spreadtrum_flash / spd_dump and iscle/sprdclient projects, plus the device's own USB descriptor.

Requirements

  • Python ≥ 3.10, pip install "sprdflash[usb]" (the [usb] extra pulls in pyusb + a bundled libusb).

  • A module in download mode. Two entry paths / USB identities are supported:

    • 1782:4D00 — the raw BootROM, reached by strapping the USB_BOOT pin high (to VDD_EXT / VDD_1V8, directly or via a pull-up) during reset. This is the most reliable native target (plain BSL autobaud).
    • 0525:A4A7 ("SPRD U2S Diag") — the soft-download interface exposed after AT*DOWNLOAD=1 on the AT port (see pacflash for the automated switch).

    Endpoints are auto-discovered from the descriptor, so either identity works.

  • A WinUSB/libusbK driver bound to the BootROM device. On Windows the device ships with the CDC/usbser (COM-port) driver, through which libusb cannot do I/O. Use Zadig once to replace the driver for USB 0525:A4A7 with WinUSB. This is a deliberate, reversible choice: while WinUSB is bound, the vendor tool and pacflash cannot use the device (they need the COM driver) — swap back to restore them.

Status: verified end-to-end on real hardware

sprdflash flashed the full 6 MB firmware to an Air724UG (RDA8910) in ~42 s with no vendor tool, and the module rebooted into the flashed firmware (ATI reported LuatOS-Air_V4035_..., IMEI intact, SIM READY).

The reverse engineering that made it work: the RDA8910 download agent reached via AT*DOWNLOAD (0525:a4a7) does not speak BSL in its first stage. It speaks a proprietary PDL (Packet Download Loader) protocol — ae-framed, over the vendor sprd_rdavcom COM port — to load and execute the first-stage loader (PDL1 / HOST_FDL). Only after FDL1 runs does the device switch to the BSL/HDLC protocol for FDL2 and the partitions. Both layers are implemented here (pdl.py, protocol.py) and stitched together in native.py. The PDL wire format was recovered by tracing the vendor ResearchDownload.exe with Frida.

You cannot brick the BootROM: a failed load just means re-entering download mode and retrying. If a device gets stuck mid-attempt, a USB device restart (pnputil /restart-device, elevated) or a power-cycle resets its agent.

Cross-SDK flashing (--format), also verified end-to-end

A same-SDK reflash writes the payload partitions only. Changing firmware type (e.g. LuatOS V4035 ⇄ CSDK V302340) additionally needs the PAC's logical 0xFE0000xx markers, which --format replays exactly as the vendor tool does — reverse-engineered byte-for-byte from a Frida trace and confirmed on hardware (the module boots the new SDK on the soft reset, IMEI and network intact):

  • FMT_FSSYSERASE_FLASH "SYSF" and FLASHERASE_FLASH 0 format the stale filesystem (FMT_FSEXT shares the address and is not a second erase).
  • NV is written from the PAC's nvitem template with a 12-byte START_DATA (addr | size | sum32) that END_DATA verifies. The template's leading CRC-16-ARC is recomputed first — the FDL2 validates it and rejects a stale one with OPERATION_FAILED. IMEI/RF-calibration live in a separate factorynv region the format never touches, so they survive the SDK change.
  • PREPACK (the prepack cpio) is written plain after NV.
  • After NORMAL_RESET the frame is flushed and the port held briefly before closing; closing immediately cancels the in-flight reset and the module returns to download mode instead of booting.
> sprdflash flash --format LuatOS-Air_V302340_CSDK_BT_TTS_elua.pac

Example

# module in download mode (AT*DOWNLOAD, or hold the boot key at power-on)

> sprdflash flash LuatOS-Air_V4035_RDA8910_TTS_NOVOLTE_FLOAT.pac
native-flashing ... via COM34 (PDL+BSL, no vendor tool)
  FDL1           100%
  FDL2           100%
  BOOTLOADER     100%
  AP             100%
  PS             100%
  LUA            100%
flash complete - module reboots into the new firmware

Older USB/BSL transport notes (superseded by the PDL/COM path above)

# one-time: Zadig -> USB 0525:A4A7 -> WinUSB -> Replace Driver

> sprdflash identify
connected via usb
BootROM version: SPRD3

> sprdflash flash C:\firmware\LuatOS-Air_V4035_RDA8910_TTS_NOVOLTE_FLOAT.pac
native-flashing ... via usb
  BOOTLOADER      100%
  AP              100%
  PS              100%
  ...
flash complete

Exit codes

code meaning
0 success
1 file not found
2 PAC validation failed
3 no device / download port
4 flash / protocol error
5 USB transport unavailable (install [usb], or bind WinUSB via Zadig)

License

MIT — see LICENSE. Protocol knowledge is from public open-source projects; no vendor binaries are included or required.

About

Native SPRD/UNISOC .pac firmware flasher (Air724UG/RDA8910) — speaks the BootROM/FDL protocol directly, no vendor download tool

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages