1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Telechips firmware checksum support for scramble
12 * Copyright (C) 2007 Dave Chapman
14 * Thanks to Hein-Pieter van Braam for his work in identifying the
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ****************************************************************************/
29 #include <sys/types.h>
36 static uint32_t crctable
[256];
38 /* Simple implementation of a function to reverse the bottom n bits in x */
39 static uint32_t bitreverse(uint32_t x
,int n
)
42 uint32_t mask
= 1<<(n
-1);
56 /* Generate a lookup table for a reverse CRC32 */
57 static void gentable(uint32_t poly
)
63 for (idx
= 0; idx
< 256; idx
++)
65 r
= bitreverse(idx
,8) << 24;
73 crctable
[idx
] = bitreverse(r
,32);
77 /* Perform a reverse CRC32 */
78 static uint32_t calc_crc(unsigned char *message
, int size
)
83 for (i
=0; i
< size
; i
++){
84 if ((i
< 0x10) || (i
>= 0x18)) {
85 crc
= crctable
[((crc
^ (message
[i
])) & 0xff)] ^ (crc
>> 8);
92 /* Endian-safe functions to read/write a 32-bit little-endian integer */
94 static uint32_t get_uint32le(unsigned char* p
)
96 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
99 static void put_uint32le(unsigned char* p
, uint32_t x
)
102 p
[1] = (x
>> 8) & 0xff;
103 p
[2] = (x
>> 16) & 0xff;
104 p
[3] = (x
>> 24) & 0xff;
107 /* A simple checksum - seems to be used by the TCC76x firmwares */
108 void telechips_encode_sum(unsigned char* buf
, int length
)
113 /* Set checksum field to 0 */
114 put_uint32le(buf
+ 0x10, 0);
116 /* Perform a simple sum, treating the file as a series of 32-bit
117 little-endian integers */
119 for (i
=0; i
< length
; i
+=4) {
120 sum
+= get_uint32le(buf
+ i
);
122 /* Negate the sum - this means that the sum of the whole file
123 (including this value) will be equal to zero */
126 /* Set the checksum field */
127 put_uint32le(buf
+ 0x10, sum
);
131 /* Two reverse CRC32 checksums - seems to be used by the TCC77x firmwares */
132 void telechips_encode_crc(unsigned char* buf
, int length
)
136 /* Generate the CRC table */
137 gentable(0x8001801BL
);
139 /* Clear the existing CRC values */
140 put_uint32le(buf
+0x10, 0);
141 put_uint32le(buf
+0x18, 0);
143 /* Write the length */
144 put_uint32le(buf
+0x1c, length
);
146 /* Calculate the first CRC - over the entire file */
147 crc1
= calc_crc(buf
, length
);
149 /* What happens next depends on the filesize */
150 if (length
>= 128*1024)
152 put_uint32le(buf
+0x18, crc1
);
154 crc2
= calc_crc(buf
, 128*1024);
155 put_uint32le(buf
+0x10, crc2
);
157 put_uint32le(buf
+0x10, crc1
);
161 int telechips_test_crc(unsigned char* buf
, int length
)
163 uint32_t crc1
, crc2
, test_crc1
, test_crc2
;
164 unsigned char *test_buf
;
166 crc1
= get_uint32le(buf
+ 0x10);
167 crc2
= get_uint32le(buf
+ 0x18);
169 test_buf
= malloc(length
);
173 memcpy(test_buf
, buf
, length
);
174 telechips_encode_crc(test_buf
, length
);
176 test_crc1
= get_uint32le(test_buf
+ 0x10);
177 test_crc2
= get_uint32le(test_buf
+ 0x18);
181 return (crc1
== test_crc1
&& crc2
== test_crc2
) ? 0 : 2;