Downloads
release
dev builds
extras
themes
Documentation
manual
wiki
device status
Support
forums
mailing lists
IRC
Development
bugs
patches
dev guide
Search
Donate
Search
| Go
Wiki
>
Main
>
ATJ213xFirmware
%TOC% ---+ 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. <verbatim class="c"> 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); } </verbatim> ---+ 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. <verbatim class="c"> 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); } </verbatim>
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r3
<
r2
<
r1
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
r3 - 14 Sep 2012 - 10:58:54 -
AmauryPouly
Copyright © by the contributing authors.