Zsun Card Reader Firmware Update Format

2016/02/19 Note: This method has been tested multiple times on our devices and worked without problem, however at least three unexpected bricks have been reported! (sounding like failed rootfs flash)

TL;DR

  1. Insert FAT32-formatted microSD card (128MB is more than enough)
  2. Connect to WiFi
  3. Create .update directory on Zsun SMB/Windows Share (on Windows call it .update., don't ask why - it'll work) and copy SD100-openwrt.tar.gz (https://hackerspace.pl/~informatic/SD100-openwrt.tar.gz) there
  4. Wait for long LED flash, then multiple fast flashes - now OpenWRT is booting for the first time.
  5. … PROFIT!

Automatic flasher and builder: https://code.hackerspace.pl/informatic/zsun-fw-tools

Technical description

Many interesting features are available on http://10.168.168.1:8080/ which is served by /var/webs/webs binary, for instance http://10.168.168.1:8080/goform/Setcardworkmode (connects card reader to AR9331 SoC) or http://10.168.168.1:8080/goform/upFirmWare.

/goform/upFirmWare reads update tarball from .update/ directory on microSD card. (/etc/disk/.update) Sadly that directory is removed on mount by /sbin/lbd_mount, thus it has to be uploaded using SMB/Windows Network Shares. /goform/upFirmWare handler is at .text:0x00405E04 address in /var/webs/webs binary. It does multiple checks and then executes /etc/ath/update.sh which handles all the actual update. After that device is rebooted.

Furthermore S update action executes ./mtd_write after entering /etc/disk/.update thus we have to bundle that with update package too. After flashing rootfs /sbin/reboot will fail. This is why we have minimal statically linked reboot executable. (minreboot)

What we are basically doing is hijacking ./mtd_write execution and doing our own calls to ./mtd_write.actual (yes, actual mtd_write binary), and then just running /tmp/minreboot (copied there at the beginning of update script, since /tmp stays in ramfs)

Expected update file format is:

SD100-whatevername.tar.gz    # SD100 has to match /etc/producttype
├── md5                      # md5sum of following tarball
└── intermediate-v1.1.tar.gz # v1.1 has to be greater than value in /etc/ver (1.0 in stock)
    ├── config
    ├── updated_file
    └── another_updated_file

config file format read by update.sh is as follows:

$filename:$work:$path

Where:
  $work == U - mkdir -p $path ; cp -f $filename $path
  $work == D - rm -rf $path/$filename
  $work == S - /mtd_write $filename $path
  
Lines starting with # are ignored.

Example:
  testfile:U:/etc          # Copies testfile to /etc
  openwrt.bin:S:/dev/mtd3  # Flashes partition

upFirmWare response status codes:

Status Description
-2 Update file not found or /etc/producttype mismatch
-3 MD5 mismatch
1 Invalid version (/etc/ver, try to add 1)
2 Update successful (also returned if update.sh failed!)