A firmware unpacker & repacker for YI M1 firmware files. Parses the section headers of a firmware file, extracts the sections into separate files, and splits and decompresses the firmware code section. It can also change the region of firmware files between Chinese (CN) to International (INT) to install the international firmware on Chinese models and vice versa.
Requirements: Node.js & npm (recommended: v8.10.0 LTS)
Usage:
npm install
npm run unpack /path/to/firmware.bin
to unpack the firmware file into separate (decompressed) filesnpm run repack /path/to/firmware.bin
repacks unpacked data into a flashable firmware file (needs the .unpack
metadata file generated by the unpack
command) (flashing of generated file not tested yet!!!)npm run flipregion /path/to/firmware.bin
to change the region between CN and INTThe output will be a number of files (usually 4) named firmware.bin.{sectionNumber}[.{sectionId}]
.
ATTENTION: the firmware decompression/compression is not yet 100% correct, do not attempt to flash a repacked firmware file or it may damage the camera!
Firmware files consist of 4 sections.
Section Number | Section Id | Size | Description |
---|---|---|---|
0 | none | variable, ~7 MB | Most probably the actual firmware code. Contains two sections with 0x1000 byte length each, followed by 3 LZSS-compressed data sections). |
1 | ND1 | variable, ~4 MB | Offset 0x1600000. Memory image that contains resources like bitmaps, fonts, and texts in different languages |
2 | IPL | 128 kB, 0x20000 byte | Bootloader (Initial Program Loader) |
3 | PTBL | 4 kB, 0x1000 byte | Partition table, unknown format |
The section headers inside the firmware file are simple strings with a length of 256 byte (0x100). Examples from FW 2.9.1-int:
LENGTH=7366656 C59Y1 VER=M1INT DVR=Ver1.37 SUM=937214718 ND1 IPL PTBL
ND1 LENGTH=4197888 C59Y1 VER=M1INT DVR=Ver1.37 SUM=299791776 OFFSET=23068672
IPL LENGTH=131072 C59Y1 VER=M1INT DVR=Ver1.37 SUM=5714438
PTBL LENGTH=4096 C59Y1 VER=M1INT SUM=5181
The LENGTH
is the length in bytes of the following section body. SUM
is a simple checksum calculated by summing all bytes. OFFSET
seems to be an offset in the camera's memory space to which the section is written. The first header has the IDs of the following headers appended. All following headers start with their ID.
Tons of interesting strings regarding the system can be found by runnings the Unix strings
utility against the decompressed firmware. Some interesting strings regarding the hardware:
Section 0 / System
Section 2 / IPL
When the YI Camera app is paired with the camera, the camera sets a Wifi password which is a 8 digit number. This password can be read from the Android app through logcat
, and can then be used to connect a computer with the camera's wifi. The camera has a fixed IP 192.168.0.10
, and you can then send commands to the camera via GET requests, e.g. http://192.168.0.10/?data={"command":"GetCameraStatus"}
to get the camera status. The list of commands can be extracted from the decompressed firmware by extracting the strings with the strings
utility. The camera wifi is started up by the app through Bluetooth, so you have to connect the app first. Seems like it does not support multiple clients (they can connect but only the first gets an IP address), so you need to turn off the phone's wifi to successfully connect another device.
The Fujifilm X-A10 camera uses the same firmware format and can be unpacked with this tool as well. The compression scheme of the first section is also similar. In comparison to the M1 it contains an additional fifth section called "A9262" that contains additional code. Also interesting is that the model ID is very similar (M1: C59Y1, X-A10: C5932).
Other Fujifilm cameras, e.g. Finepix S800, seem to use a similar firmware format, but with shorter headers, so these cannot be unpacked with this tool.
What's the purpose of this tool?
To lay the roots for a firmware hack. To help with firmware analysis. To change firmware regions.
What can a potential firmware hack do?
How can I contribute?
Please open an issue, pull request, or drop me a mail at mg@protyposis.net
How dare you write this in JavaScript?
Times are changing, and messing with the string headers in C seemed too much of a hassle. JS with Node also runs on virtually every platform.