90 lines
5.6 KiB
Markdown
90 lines
5.6 KiB
Markdown
# UniFlash: an opensource Unisoc/Spreadtrum feature phone flash reader/writer
|
|
|
|
## About
|
|
|
|
Cross-platform MediaTek feature phone dumping had been achieved long ago with [MTreader](https://gitlab.com/suborg/mtreader). Now it's time to do the same for Unisoc (ex-Spreadtrum) phones. And not only that, but also to be able to flash them and extract their compressed firmware contents!
|
|
|
|
Unfortunately, the architecture of Unisoc chipset boot ROM doesn't allow us to get away without any loader blobs. So, some FDL binaries are also shipped in this repo.
|
|
|
|
UniFlash started out as UniDump (see [this blog post](https://chronovir.us/2021/12/18/Opus-Spreadtrum/)) but had been quickly upgraded to do both tasks.
|
|
|
|
The `uniflash.py` file is the main script to use. The `unicmd.py` file is the library created for easier command interface encapsulation.
|
|
|
|
For further dumped firmware repacking, I recommend [bzpwork](https://github.com/ilyazx/bzpwork) by ilyazx.
|
|
|
|
**Note: the flasher part is still under testing/study, use at your own risk!**
|
|
|
|
## Dependencies
|
|
|
|
Python 3.8+ and PyUSB.
|
|
|
|
## Usage as a flasher/dumper
|
|
|
|
Run `python uniflash.py -h` to see all parameters. But there are several typical scenarios that UniFlash officially supports.
|
|
|
|
**Note**: you need to hold a bootkey pressed when connecting the device for it to be detected correctly. This key can vary across devices. Typically it's Call, Soft Left, Soft Right, Center, 9 or #, but it can be anything else.
|
|
|
|
Some chipset versions (esp. the ones before SC6531E) require the following procedure to connect in order to initiate successful data transfer:
|
|
|
|
1. Pull out the battery and the cable.
|
|
2. Insert the cable.
|
|
3. Hold the bootkey and then insert the battery.
|
|
|
|
UniFlash ships with several typical targets that you can specify with `-t` (`--target`) parameter and not have to configure anything else:
|
|
|
|
- `sc6531efm_generic` (default) - for SC6531E/F/M with no signed FDLs;
|
|
- `sc6530_generic` - for SC6530 and SC6531B/C/DA with no signed FDLs;
|
|
- `sc7703a_generic` - for SC7703A with no signed FDLs.
|
|
|
|
If you want to, the targets are fully overridable with individual parameters, see program help for all details.
|
|
|
|
### SC6531E
|
|
|
|
This is the default target for UniFlash, FDLs for it are shipped in the repo and you don't need to configure anything else (even `-t` parameter) unless your model requires signed FDLs.
|
|
|
|
For SC6531E, firmware is usually 4MB long, so you just need to run `python uniflash.py dump your-output-file.bin` to dump the firmware image and `python uniflash.py flash your-input-file.bin` to flash it.
|
|
|
|
### SC6531F/M
|
|
|
|
For SC6531F or SC6531M, the target is still `sc6531efm_generic` unless your model uses signed FDLs. However, **specifying the wrong dump length and attempts to write flash from the same dump can make the device unbootable!**
|
|
|
|
Here, firmware can be larger, so you need to pass in the length. As with any integer parameter here, you can pass it in hexadecimal format as well.
|
|
|
|
E.g. for CAT B26 (bootkey is `#`) the dumping command is: `python uniflash.py -l 0x800000 dump b26.bin`
|
|
|
|
### SC6531C
|
|
|
|
SC6531C is a single-FDL variant. Both readback and flashing are now supported here. Here, if your model doesn't require signed FDLs, you need to specify `sc6530_generic` target and typically 8MB length, for instance, for Alcatel OT-2051D the boot key is Call key and the command to dump is: `python uniflash.py -t sc6530_generic -l 0x800000 dump ot2051d.bin`
|
|
|
|
### SC6531D and lower
|
|
|
|
For now, SC6531DA and other variants of SC6531 chipset older than SC6531C are not supported or at least tested. You may verify the support by using the same `sc6530_generic` target as for SC6531C.
|
|
|
|
### Add your own targets
|
|
|
|
If you work with non-standard devices but don't find specifying individual FDL parameters every time convenient, you can always create your own target and refer to it via the `-t` parameter. It's pretty straightforward: you just need to collect FDL loader files for your device, rename them accordingly and place them into `fdls/` directory in the root of UniFlash project.
|
|
|
|
For two-FDL targets (more common scenario), the naming scheme is like this: `[targetname]_[load_addr_1]_fdl1.bin` and `[targetname]_[load_addr_2]_fdl2.bin`.
|
|
|
|
For single-FDL targets, the FDL file name must be `[targetname]_[load_addr]_single.bin`.
|
|
|
|
For example, if you have found signed FDL loaders for Nokia 105 2019 somewhere and want to add this phone as a target, you know that they are loaded into `0x40004000` and `0x14000000` respectively, so you can rename them, for instance, to `sc6531efm_nokia105_0x40004000_fdl1.bin` and `sc6531efm_nokia105_0x14000000_fdl2.bin`, place them into `fdls/` and then just use `-t sc6531efm_nokia105` in your commands. This signed target, by the way, has already been added as an example.
|
|
|
|
## Usage as a stone image unpacker
|
|
|
|
The main syntax is as follows: `python uniflash.py stone-unpack [stone-file.bin] [-d target_dir]`
|
|
|
|
The firmware is going to be unpacked into the following files in the target directory (specified with `-d` parameter, defaults to the same directory as the source stone image file):
|
|
|
|
- `ps.bin` - protocol station image, always uncompressed, the first in the binary;
|
|
- `kern.bin` (optional) - single-block LZMA-SPD compressed kernel partition;
|
|
- `user.bin` - multi-block LZMA-SPD compressed user firmware partition;
|
|
- `rsrc.bin` - multi-block LZMA-SPD compressed user resources partition;
|
|
- `blk_xxxxxxxx` (optional) - any of the additional LZMA-SPD or standard LZMA compressed sections found in the image.
|
|
|
|
LZMA-SPD, also known as LZMA-B3, is a proprietary modification of LZMA algorithm with simplified literal encoder/decoder.
|
|
|
|
## Credits
|
|
|
|
Created by Luxferre in 2021. All files except the FDL blobs are public domain.
|