Format reverse engineering
Header
Each file begin with a header containing crucial information about the firmware.
offset |
length |
name |
description |
0x00 |
0x10 |
sig |
signature |
0x10 |
0x4 |
fw_size |
firmware size (in bytes) |
0x14 |
0x4 |
block_size |
block size (unsure) (in bytes) |
0x18 |
0x1 |
ver |
version encoding |
0x19 |
0x1 |
unk1 |
unknown |
0x1a |
0x10 |
sig2 |
second signature |
The block size is always 512. The first signature is the same for all versions of the firmware files.
signature |
11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 75 |
The second signature and unknown field depends on the version which is encoding as follows.
ver |
version |
unk1 |
sig2 |
0x0d |
1 |
0xd0 |
76 5c 50 94 69 b0 a7 03 10 f1 7e db 88 90 86 9d |
0x0e |
1 |
0xd0 |
92 22 7a 77 08 67 ae 06 16 06 b8 65 a6 42 f7 52 |
0xfd |
2 |
|
|
0x7e |
3 |
0xe1 |
3f ad f8 b0 2e af 67 49 b9 85 5f 63 4e 5e 8e 2e |
Common
Checksum
In several places the firmware files use a xor-based checksum. This section describes the algorithm used.
void compute_checksum(uint8_t *buf, int size, uint8_t t[20])
{
memset(t, 0, 20);
for(int i = 0; i < size; i++)
t[i % 20] ^= buf[i];
for(int i = 0; i < 20; i++)
t[i] = ~t[i];
}
int check_block(uint8_t *buf, uint8_t ref[20], unsigned size)
{
uint8_t t[20];
compute_checksum(buf, size, t);
return memcmp(ref, t, 20);
}
Version 3
The version 3 (encoded as 0x7e) differs significantly from previous versions.
Header Extra
The header contains a few extra fields described as follows.
offset |
length |
name |
description |
0x1ee |
0x1 |
blockA |
block address (in lower 4 bits) |
0x1fe |
0x1 |
blockB |
block address (in lower 4 bits) |
The first field indicates the block address (minus 2) of a 1024 bytes block. The sum of first and the second fields indicates the block address (minus 5) of a 512 bytes block.
Block A
The A block contains many information about what looks like a decompression algorithm. This block is 1024 bytes long and is located at block
blockA+2
(multiply this by 512 to get the offset). This block is XOR encoded using a key found in the block itself. The following procedure shows how to decode it. It uses a 1024 byte tables called
g_check_block_A_table
in the code below.
static int decode_block_A(uint8_t block[1020])
{
uint8_t *p = &g_check_block_A_table[32 * (block[998] & 0x1f)];
uint8_t key[32];
for(int i = 0; i < 20; i++)
{
block[1000 + i] ^= p[i];
key[i] = block[1000 + i];
}
for(int i = 20; i < 32; i++)
key[i] = key[i - 20];
for(int i = 0; i < 992; i++)
block[i] ^= key[i % 32] ^ g_check_block_A_table[i];
return check_block(block - 1, block + 1000, 1001);
}
Descrambled/unpacked content
The content of e100/e150/e200/e300 firmware is almost the same
filename |
description |
ADEC_63.BIN |
unscrambled version of 1st stage ADFU handler running from IRAM |
ADEC_N63.BIN |
scrambled version of ADEC_63.BIN |
ADFUS.BIN |
2nd stage ADFU handler running from DRAM |
ADFUZ.BIN |
1kB of zeros |
BREC96R1.BIN |
|
BRECF63.BIN |
|
BRECF96.BIN |
|
BRECFXXX.BIN |
The same as BRECF63.BIN |
FAT16.IMG |
Around 12MB fat image containing FONT16.BIN file |
FWIMAGE.FW |
Firmware archive |
FWSC96R1.BIN |
|
FWSCF63.BIN |
|
FWSCF96.BIN |
|
HWSC.BIN |
Sort of HW scanning procedure. Based on the outcome, different components are flashed. |
MBRC96R1.BIN |
|
MBRCF63.BIN |
|
MBRCF96.BIN |
|
MBRCFXXX.BIN |
The same as MBRCF63.BIN |
RCSL.BIN |
Contains procedure which returns 0xb4042020 unconditionally . The rest is zero |
U130.BIN |
sqlite3 database |
MBRCF*.BIN files have signature 'ActBrm' at offset 0x1f4 followed by 0xaa and 0x55. There is also 32bit checksum stored at 0x1fc.
/* buf points to the MBRCF*.BIN file content
* returned checksum can be compared to the one stored in file at offset 0x1fc
*/
uint32_t mbrcf_crc(char *buf)
{
int i;
uint32_t csum = 0;
/* treat file as little-endian 32bit words */
for (i=0; i<0x1fc; i+=4)
csum += (buf[i] | buf[i+1]<<8 | buf[i+2]<<16 | buf[i+3]<<24);
/* the checksum is extended with magic value */
return (csum + 0x1234);
}
FWIMAGE.FW contains:
filename |
description |
A_CODEC.DRV |
elf |
AD4AUDIO.LIB |
elf |
ADA.DRV |
elf, not stripped |
ADA_SIM.DRV |
elf, not stripped |
AD_AUDIO.LIB |
elf |
AE_WMA.LIB |
elf |
AOTG_UDC.DRV |
elf |
AOTG_UOC.DRV |
elf |
AVD4AMV.LIB |
elf |
AVD4AVI.LIB |
elf |
AVD4FLV.LIB |
elf |
AVD4WMV.LIB |
elf |
AVD_AMV.LIB |
elf |
AVD_AVI.LIB |
elf |
AVD_FLV.LIB |
elf |
AVD_WMV.LIB |
elf |
CARD.DRV |
elf, not stripped |
CARDIN.APP |
elf, not stripped |
CARDOUT.APP |
elf, not stripped |
CHARGE.DRV |
elf, not stripped |
CHDISK.APP |
elf, not stripped |
COM_UI.DRV |
elf, not stripped |
CONFIG.APP |
elf, not stripped |
DEC.DSP |
binary data |
DRM.DSP |
binary data |
EBOOK.APP |
elf, not stripped |
ENC.DSP |
binary data |
EXPLORER.CFG |
strings |
FFT.DRV |
elf |
FILENAVI.APP |
elf, not stripped |
FM.DRV |
elf, not stripped |
FM_DSP.DRV |
elf, not stripped |
FS.DRV |
elf |
FSG.DRV |
elf |
FUNCNAVI.APP |
elf, not stripped |
GUI.DRV |
elf |
HDSFRAME.HDS |
binary data |
ID_BMP.LIB |
elf |
ID_GIF.LIB |
elf |
ID_JPG.LIB |
elf |
ID_PNG.LIB |
elf |
IPP.LIB |
elf |
JUK_DRV.DRV |
elf |
KEY.DRV |
elf, not stripped |
KEYLOCK.APP |
elf, not stripped |
KSC.DRV |
elf |
KTF_DRV.DRV |
elf |
LCM.DRV |
elf, not stripped |
LOGO.APP |
elf, not stripped |
LOWPOW.APP |
elf, not stripped |
MANAGER.APP |
elf, not stripped |
MLANG_B5.DRV |
elf, not stripped |
MLANG.DRV |
elf, not stripped |
MLANG_GB.DRV |
elf, not stripped |
MLANGJIS.DRV |
elf, not stripped |
MLANG_KR.DRV |
elf, not stripped |
MLANG_L.DRV |
elf, not stripped |
MLAN_SIM.DRV |
elf, not stripped |
MMM_DCA.DRV |
elf |
MMM_DCT.DRV |
elf |
MMM_MTP.DRV |
elf |
MNAVI.DRV |
elf |
MSMTP.DRV |
elf |
MTPCFG.TXT |
text |
MTP.DSP |
binary data |
MTPLIST.DRV |
elf |
MTPTMP.BIN |
binary data |
MUSIC_EG.APP |
elf, not stripped |
MUSIC_UI.APP |
elf, not stripped |
NAND96R1.DRV |
MIPS binary |
NANDF63.DRV |
MIPS binary |
NANDF96.DRV |
MIPS binary |
PDCDEC.DSP |
This contains 'crypto' kernel to be run on DSP core. Raw binary can be extracted with attached python script |
PHOTO.APP |
elf, not stripped |
PLGENE.APP |
elf, not stripped |
RADIO_EG.APP |
elf, not stripped |
RADIO_ID.APP |
binary data |
RADIO_UI.APP |
elf, not stripped |
RECORD.APP |
elf, not stripped |
REGISTER.APP |
elf, not stripped |
RELEASE.APP |
elf, not stripped |
RES_DU.RES |
binary data |
RES_EN.RES |
binary data |
RES_FH.RES |
binary data |
RES_FR.RES |
binary data |
RES_GM.RES |
binary data |
RES_HZ.RES |
binary data |
RES_IT.RES |
binary data |
RES_JP.RES |
binary data |
RES_KR.RES |
binary data |
RES_PL.RES |
binary data |
RES_PT.RES |
binary data |
RES_RU.RES |
binary data |
RES_SP.RES |
binary data |
RES_SW.RES |
binary data |
RES_TK.RES |
binary data |
SETTING.APP |
elf, not stripped |
SHUTOFF.APP |
elf, not stripped. Contains small binary blob for DSP core. |
SHUTOFF.BIN |
binary data. Binary version of .text from SHUTOFF.APP padded to 8192 bytes |
SKT_DRV.DRV |
elf |
STANDBY.APP |
elf, not stripped |
START_M.RES |
binary data - mainly startup screen graphic |
SYSCFG.BIN |
binary data |
SYSCFG.EXE |
elf |
SYSCFG.SYS |
MIPS binary - this seems to be main uCOS binary (bin version of SYSCFG.EXE) |
TASKGUI.APP |
elf, not stripped |
TROM.BIN |
binary data |
UCHARGE.APP |
elf, not stripped |
UDISK.APP |
elf, not stripped |
UMTP.APP |
elf, not stripped |
UPGRADE.APP |
elf, not stripped |
UPGRADE.BIN |
|
UPGRADE.DRV |
elf |
USBUI.APP |
elf, not stripped |
V_CODEC.DRV |
elf |
VD4AMVB.LIB |
elf |
VD4FLV1.LIB |
elf |
VD4WMV.LIB |
elf |
VD4XVID.LIB |
elf |
VD_AMVB.LIB |
elf |
VD_FLV1.LIB |
elf |
VD_WMV.LIB |
elf |
VD_XVID.LIB |
elf |
VIDEO.APP |
elf, not stripped |
VRAM.DRV |
elf |
WELCOME.BIN |
Performs lowlevel lcd init; contains routines to display Welcome, Low battery and Hold screens |
Booting sequence
On power on the CPU begin execution at VA=0xbfc00000 (PA=0x1fc00000) where BROM is mapped. BROM loads MBRCF*.BIN stored at the beginning of nand flash into iram (VA=0xb4040000, PA=0x14040000), check signature and checksum and passes control to the just loaded code. MBRCF* initializes caches, clocks, DRAM, loads BREC* loader to the DRAM (VA=0x80000000, PA=0x00000000) and passes control to the BREC. BREC checks logical structure of flash, loads and passes control to uCOS kernel. If at any stage of load chain en error is encountered 'Hard DFU' handler stored at 0xbfc05400 (0x1ffc bytes) in BROM is copied to 0xb4046800 and CPU jumps to this handler.
MBRECF*
This file seems to contain 3 images:
offset |
length |
description |
0x0000 |
0x200 |
Loaded by BROM @ 0xb4040000. Uses nand driver loaded by BROM earlier @ 0xb4040200 |
0x200 |
0x3e00 |
Loaded @ 0xb4042a00, protected by magic 0xaa55 and 16bit checksum at the end. Inits DRAM, cache, checks low battery condition. Uses BROM nand driver. |
0x4000 |
0x4000 |
? |
Copyright © by the contributing authors.