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>
35 static uint32_t crctable
[256];
37 /* Simple implementation of a function to reverse the bottom n bits in x */
38 static uint32_t bitreverse(uint32_t x
,int n
)
41 uint32_t mask
= 1<<(n
-1);
55 /* Generate a lookup table for a reverse CRC32 */
56 static void gentable(uint32_t poly
)
62 for (index
= 0; index
< 256; index
++)
64 r
= bitreverse(index
,8) << 24;
72 crctable
[index
] = bitreverse(r
,32);
76 /* Perform a reverse CRC32 */
77 static uint32_t calc_crc(unsigned char *message
, int size
)
82 for (i
=0; i
< size
; i
++){
83 if ((i
< 0x10) || (i
>= 0x18)) {
84 crc
= crctable
[((crc
^ (message
[i
])) & 0xff)] ^ (crc
>> 8);
91 /* Endian-safe functions to read/write a 32-bit little-endian integer */
93 static uint32_t get_uint32le(unsigned char* p
)
95 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
98 static void put_uint32le(unsigned char* p
, uint32_t x
)
101 p
[1] = (x
>> 8) & 0xff;
102 p
[2] = (x
>> 16) & 0xff;
103 p
[3] = (x
>> 24) & 0xff;
106 /* A simple checksum - seems to be used by the TCC76x firmwares */
107 void telechips_encode_sum(unsigned char* buf
, int length
)
112 /* Set checksum field to 0 */
113 put_uint32le(buf
+ 0x10, 0);
115 /* Perform a simple sum, treating the file as a series of 32-bit
116 little-endian integers */
118 for (i
=0; i
< length
; i
+=4) {
119 sum
+= get_uint32le(buf
+ i
);
121 /* Negate the sum - this means that the sum of the whole file
122 (including this value) will be equal to zero */
125 /* Set the checksum field */
126 put_uint32le(buf
+ 0x10, sum
);
130 /* Two reverse CRC32 checksums - seems to be used by the TCC77x firmwares */
131 void telechips_encode_crc(unsigned char* buf
, int length
)
135 /* Generate the CRC table */
136 gentable(0x8001801BL
);
138 /* Clear the existing CRC values */
139 put_uint32le(buf
+0x10, 0);
140 put_uint32le(buf
+0x18, 0);
142 /* Write the length */
143 put_uint32le(buf
+0x1c, length
);
145 /* Calculate the first CRC - over the entire file */
146 crc1
= calc_crc(buf
, length
);
148 /* What happens next depends on the filesize */
149 if (length
>= 128*1024)
151 put_uint32le(buf
+0x18, crc1
);
153 crc2
= calc_crc(buf
, 128*1024);
154 put_uint32le(buf
+0x10, crc2
);
156 put_uint32le(buf
+0x10, crc1
);