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.
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);
}
Copyright © by the contributing authors.