diff options
Diffstat (limited to 'tools/telechips.c')
-rw-r--r-- | tools/telechips.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/tools/telechips.c b/tools/telechips.c new file mode 100644 index 0000000000..5b6f3c23b3 --- /dev/null +++ b/tools/telechips.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Telechips firmware checksum support for scramble | ||
11 | * | ||
12 | * Copyright (C) 2007 Dave Chapman | ||
13 | * | ||
14 | * Thanks to Hein-Pieter van Braam for his work in identifying the | ||
15 | * CRC algorithm used. | ||
16 | * | ||
17 | * All files in this archive are subject to the GNU General Public License. | ||
18 | * See the file COPYING in the source tree root for full license agreement. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | |||
25 | #include <stdio.h> | ||
26 | #include <unistd.h> | ||
27 | #include <sys/types.h> | ||
28 | #include <sys/stat.h> | ||
29 | #include <fcntl.h> | ||
30 | #include <stdint.h> | ||
31 | #include <stdlib.h> | ||
32 | |||
33 | static uint32_t crctable[256]; | ||
34 | |||
35 | /* Simple implementation of a function to reverse the bottom n bits in x */ | ||
36 | static uint32_t bitreverse(uint32_t x,int n) | ||
37 | { | ||
38 | int i; | ||
39 | uint32_t mask = 1<<(n-1); | ||
40 | uint32_t res = 0; | ||
41 | |||
42 | for (i=0; i<n; i++) | ||
43 | { | ||
44 | if (x & 1) | ||
45 | res |= mask; | ||
46 | |||
47 | x >>= 1; | ||
48 | mask >>= 1; | ||
49 | } | ||
50 | return res; | ||
51 | } | ||
52 | |||
53 | /* Generate a lookup table for a reverse CRC32 */ | ||
54 | static void gentable(uint32_t poly) | ||
55 | { | ||
56 | int i; | ||
57 | uint32_t r; | ||
58 | uint32_t index; | ||
59 | |||
60 | for (index = 0; index < 256; index++) | ||
61 | { | ||
62 | r = bitreverse(index,8) << 24; | ||
63 | for (i=0; i<8; i++) | ||
64 | { | ||
65 | if (r & (1 << 31)) | ||
66 | r = (r << 1) ^ poly; | ||
67 | else | ||
68 | r<<=1; | ||
69 | } | ||
70 | crctable[index] = bitreverse(r,32); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /* Perform a reverse CRC32 */ | ||
75 | static uint32_t calc_crc(unsigned char *message, int size) | ||
76 | { | ||
77 | uint32_t crc = 0; | ||
78 | int i; | ||
79 | |||
80 | for (i=0; i < size; i++){ | ||
81 | if ((i < 0x10) || (i >= 0x18)) { | ||
82 | crc = crctable[((crc ^ (message[i])) & 0xff)] ^ (crc >> 8); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | return crc; | ||
87 | } | ||
88 | |||
89 | /* Endian-safe functions to read/write a 32-bit little-endian integer */ | ||
90 | |||
91 | static uint32_t get_uint32le(unsigned char* p) | ||
92 | { | ||
93 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | ||
94 | } | ||
95 | |||
96 | static void put_uint32le(unsigned char* p, uint32_t x) | ||
97 | { | ||
98 | p[0] = x & 0xff; | ||
99 | p[1] = (x >> 8) & 0xff; | ||
100 | p[2] = (x >> 16) & 0xff; | ||
101 | p[3] = (x >> 24) & 0xff; | ||
102 | } | ||
103 | |||
104 | /* A simple checksum - seems to be used by the TCC76x firmwares */ | ||
105 | void telechips_encode_sum(unsigned char* buf, int length) | ||
106 | { | ||
107 | uint32_t sum; | ||
108 | int i; | ||
109 | |||
110 | /* Set checksum field to 0 */ | ||
111 | put_uint32le(buf + 0x10, 0); | ||
112 | |||
113 | /* Perform a simple sum, treating the file as a series of 32-bit | ||
114 | little-endian integers */ | ||
115 | sum = 0; | ||
116 | for (i=0; i < length; i+=4) { | ||
117 | sum += get_uint32le(buf + i); | ||
118 | } | ||
119 | /* Negate the sum - this means that the sum of the whole file | ||
120 | (including this value) will be equal to zero */ | ||
121 | sum = -sum; | ||
122 | |||
123 | /* Set the checksum field */ | ||
124 | put_uint32le(buf + 0x10, sum); | ||
125 | } | ||
126 | |||
127 | |||
128 | /* Two reverse CRC32 checksums - seems to be used by the TCC77x firmwares */ | ||
129 | void telechips_encode_crc(unsigned char* buf, int length) | ||
130 | { | ||
131 | uint32_t crc1,crc2; | ||
132 | |||
133 | /* Generate the CRC table */ | ||
134 | gentable(0x8001801BL); | ||
135 | |||
136 | /* Clear the existing CRC values */ | ||
137 | put_uint32le(buf+0x10, 0); | ||
138 | put_uint32le(buf+0x18, 0); | ||
139 | |||
140 | /* Write the length */ | ||
141 | put_uint32le(buf+0x1c, length); | ||
142 | |||
143 | /* Calculate the first CRC - over the entire file */ | ||
144 | crc1 = calc_crc(buf, length); | ||
145 | |||
146 | /* What happens next depends on the filesize */ | ||
147 | if (length >= 128*1024) | ||
148 | { | ||
149 | put_uint32le(buf+0x18, crc1); | ||
150 | |||
151 | crc2 = calc_crc(buf, 128*1024); | ||
152 | put_uint32le(buf+0x10, crc2); | ||
153 | } else { | ||
154 | put_uint32le(buf+0x10, crc1); | ||
155 | } | ||
156 | } | ||