1 //
2 // srecord - manipulate eprom load files
3 // Copyright (C) 2000-2002, 2006-2010, 2012, 2014 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or (at
8 // your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18 //
19 //
20 // Implemented from scratch from
21 // "A painless guide to CRC error detection algorithms"
22 // http://www.repairfaq.org/filipg/LINK/F_crc_v3.html
23 //
24 // See also http://www.joegeluso.com/software/articles/ccitt.htm (gone)
25 // http://srecord.sourceforge.net/crc16-ccitt.html (duplicate)
26 // etc/crc16-ccitt.html (in the source tarball).
27 //
28 // See test/01/t0150a.sh for test vectors.
29 //
30
31 #include <cstring>
32 #include <string>
33
34 #include <srecord/bitrev.h>
35 #include <srecord/crc16.h>
36 #include <srecord/quit.h>
37 #include <srecord/sizeof.h>
38
39
40 //
41 // The Chapter numbers come from Williams, N. (1993) "A painless guide
42 // to CRC error detection algorithms"
43 // http://www.repairfaq.org/filipg/LINK/F_crc_v3.html
44 //
45 #define IMPL_CH9 9
46 #define IMPL_CH10 10
47 #define IMPL_CH11 11 // doesn't work yet (i.e. not same results as 9 and 10)
48 // but it "almost" works, according to test/01/t0150a.sh
49
50 // So, for now we will be conservative, and use Chapter 10
51 #define IMPL IMPL_CH10
52
53
54 //
55 // Use a seed of 0xFFFF when augmenting manually (i.e. augmenting by 16
56 // zero bits by processing two zero bytes at the end of the data), but a
57 // seed of 0x1D0F when the augmenting is done by shifting where the XOR
58 // appears in the updcrc function.
59 //
60 // The 0x1D0F value is calculated by using the manual augmentation
61 // updcrc function:
62 // updcrc(0, updcrc(0, 0xFFFF))
63 //
64 static unsigned short const ccitt_seed = 0xFFFF;
65 static unsigned short const broken_seed = 0x84CF;
66 static unsigned short const xmodem_seed = 0;
67
68
69 void
calculate_table(void)70 srecord::crc16::calculate_table(void)
71 {
72 if (polynomial == 0)
73 polynomial = polynomial_ccitt;
74 if (bitdir == bit_direction_most_to_least)
75 {
76 for (unsigned b = 0; b < 256; ++b)
77 {
78 unsigned short v = b << 8;
79 for (unsigned j = 0; j < 8; ++j)
80 v = (v & 0x8000) ? ((v << 1) ^ polynomial) : (v << 1);
81 table[b] = v;
82 }
83 }
84 else
85 {
86 polynomial = bitrev16(polynomial);
87 for (unsigned b = 0; b < 256; ++b)
88 {
89 unsigned short v = b;
90 for (unsigned j = 0; j < 8; ++j)
91 v = (v & 1) ? ((v >> 1) ^ polynomial) : (v >> 1);
92 table[b] = v;
93 }
94 }
95 }
96
97
98 static int
state_from_seed_mode(srecord::crc16::seed_mode_t seed_mode)99 state_from_seed_mode(srecord::crc16::seed_mode_t seed_mode)
100 {
101 switch (seed_mode)
102 {
103 case srecord::crc16::seed_mode_ccitt:
104 return ccitt_seed;
105
106 case srecord::crc16::seed_mode_xmodem:
107 return xmodem_seed;
108
109 case srecord::crc16::seed_mode_broken:
110 return broken_seed;
111 }
112 return ccitt_seed;
113 }
114
115
crc16(seed_mode_t seed_mode,bool a_augment,unsigned short a_polynomial,bit_direction_t a_bitdir)116 srecord::crc16::crc16(
117 seed_mode_t seed_mode,
118 bool a_augment,
119 unsigned short a_polynomial,
120 bit_direction_t a_bitdir
121 ) :
122 state(state_from_seed_mode(seed_mode)),
123 augment(a_augment),
124 polynomial(a_polynomial),
125 bitdir(a_bitdir)
126 {
127 #if (IMPL == IMPL_CH11)
128 #if 1
129 // the "pre-augment" crc seed
130 state = 0x1D0F;
131 #else
132 // The above nukes the seed value the user may have provided,
133 // making this look more likely:
134 state = updcrc(0, updcrc(0, state));
135 #endif
136 #endif
137 calculate_table();
138 }
139
140
crc16(const crc16 & rhs)141 srecord::crc16::crc16(const crc16 &rhs) :
142 state(rhs.state),
143 augment(rhs.augment),
144 polynomial(rhs.polynomial),
145 bitdir(rhs.bitdir)
146 {
147 for (size_t j = 0; j < 256; ++j)
148 table[j] = rhs.table[j];
149 }
150
151
152 srecord::crc16 &
operator =(const crc16 & rhs)153 srecord::crc16::operator=(const crc16 &rhs)
154 {
155 if (this != &rhs)
156 {
157 state = rhs.state;
158 augment = rhs.augment;
159 polynomial = rhs.polynomial;
160 bitdir = rhs.bitdir;
161 for (size_t j = 0; j < 256; ++j)
162 table[j] = rhs.table[j];
163 }
164 return *this;
165 }
166
167
~crc16()168 srecord::crc16::~crc16()
169 {
170 }
171
172
173 #if (IMPL == IMPL_CH9)
174
175 //
176 // This is the simplest possible implementation. It can be used to
177 // validate the two following table-driven implementations.
178 //
179 // See "A painless guide to CRC error detection algorithms",
180 // Chapter 9, http://www.repairfaq.org/filipg/LINK/F_crc_v33.html#CRCV_001
181 // 'A Straightforward CRC Implementation', for an explanation.
182 //
183
184 inline unsigned short
updcrc(unsigned char c,unsigned short state) const185 srecord::crc16::updcrc(unsigned char c, unsigned short state)
186 const
187 {
188 if (bitdir == bit_direction_most_to_least)
189 {
190 for (unsigned i = 0; i < 8; ++i)
191 {
192 bool xor_flag = !!(state & 0x8000);
193 state <<= 1;
194 if (c & 0x80)
195 state |= 1;
196 if (xor_flag)
197 state ^= polynomial;
198 c <<= 1;
199 }
200 }
201 else
202 {
203 // note: calculate_table() already reversed the bits in the polynomial
204 for (unsigned i = 0; i < 8; ++i)
205 {
206 bool xor_flag = !!(state & 1);
207 state >>= 1;
208 if (c & 1)
209 state |= 0x8000;
210 if (xor_flag)
211 state ^= polynomial;
212 c >>= 1;
213 }
214 }
215 return state;
216 }
217
218 #endif // IMPL_CH9
219 #if (IMPL == IMPL_CH10)
220
221 //
222 // This version of updcrc doesn't augment automagically, you must
223 // do it explicitly in the get() method. It is a more intuitave
224 // implementation than the "augmentation included" implementation below.
225 //
226 // See "A painless guide to CRC error detection algorithms",
227 // Chapter 10, http://www.repairfaq.org/filipg/LINK/F_crc_v33.html#CRCV_002
228 // 'A Table-Driven Implementation', for an explanation.
229 //
230
231 inline unsigned short
updcrc(unsigned char c,unsigned short state) const232 srecord::crc16::updcrc(unsigned char c, unsigned short state)
233 const
234 {
235 if (bitdir == bit_direction_least_to_most)
236 {
237 return (((state >> 8) & 0xFF) | (c << 8)) ^ table[state & 0xFF];
238 }
239 else
240 {
241 return ((state << 8) | c) ^ table[state >> 8];
242 }
243 }
244
245 #endif // IMPL_CH10
246 #if (IMPL == IMPL_CH11)
247
248 //
249 // This version of updcrc means that the 16-zero-bit augmentation has
250 // already happened. There is no need to explicitly do it in the get()
251 // method. This is deep voodoo even for folks who actually understand
252 // XOR arithmetic.
253 //
254 // See "A painless guide to CRC error detection algorithms",
255 // Chapter 11, http://www.repairfaq.org/filipg/LINK/F_crc_v33.html#CRCV_003
256 // 'A Slightly Mangled Table-Driven Implementation', for an explanation.
257 //
258
259 inline unsigned short
updcrc(unsigned char c,unsigned short state) const260 srecord::crc16::updcrc(unsigned char c, unsigned short state)
261 const
262 {
263 if (bitdir == bit_direction_least_to_most)
264 return (state >> 8) ^ table[(state ^ c) & 0xFF];
265 else
266 return (state << 8) ^ table[((state >> 8) ^ c) & 0xFF];
267 }
268
269 #endif // IMPL_CH11
270
271
272 void
next(unsigned char ch)273 srecord::crc16::next(unsigned char ch)
274 {
275 state = updcrc(ch, state);
276 }
277
278
279 void
nextbuf(const void * data,size_t nbytes)280 srecord::crc16::nextbuf(const void *data, size_t nbytes)
281 {
282 unsigned char *dp = (unsigned char *)data;
283 while (nbytes > 0)
284 {
285 state = updcrc(*dp++, state);
286 --nbytes;
287 }
288 }
289
290
291 unsigned short
get(void) const292 srecord::crc16::get(void)
293 const
294 {
295 #if (IMPL < IMPL_CH11)
296 // The whole idea is that Ch.11 technique is "pre-auugmented"
297 if (augment)
298 {
299 return updcrc(0, updcrc(0, state));
300 }
301 #endif
302 return state;
303 }
304
305
306 #include <cstdio>
307
308
309 void
print_table(void) const310 srecord::crc16::print_table(void)
311 const
312 {
313 printf("/*\n");
314 printf
315 (
316 " * Bit order: %s\n",
317 (
318 bitdir == bit_direction_most_to_least
319 ?
320 "most to least"
321 :
322 "least to most"
323 )
324 );
325 printf(" * Polynomial: 0x");
326 if (bitdir == bit_direction_most_to_least)
327 printf("%04X", polynomial);
328 else
329 printf("%04X", bitrev16(polynomial));
330 printf("\n */\n");
331 printf("const unsigned short table[256] =\n{\n");
332 for (size_t j = 0; j < 256; ++j)
333 {
334 if ((j & 7) == 0)
335 printf(" /* %02X */", int(j));
336 printf(" 0x%04X,", table[j]);
337 if ((j & 7) == 7)
338 printf("\n");
339 }
340 printf("};\n");
341 }
342
343
344 int
polynomial_by_name(const char * name)345 srecord::crc16::polynomial_by_name(const char *name)
346 {
347 struct table_t
348 {
349 const char *name;
350 int value;
351 };
352
353 static const table_t table[] =
354 {
355 { "ansi", polynomial_ansi },
356 { "bisync", polynomial_ansi },
357 { "bluetooth", polynomial_ccitt },
358 { "ccitt", polynomial_ccitt },
359 { "dnp", polynomial_dnp },
360 { "hdlc", polynomial_ccitt },
361 { "ibm", polynomial_ansi },
362 { "iec-870", polynomial_dnp },
363 { "m-bus", polynomial_dnp },
364 { "modbus", polynomial_ansi },
365 { "scsi-dif", polynomial_t10_dif },
366 { "sd", polynomial_ccitt },
367 { "t10-dif", polynomial_t10_dif },
368 { "usb", polynomial_ansi },
369 { "v.41", polynomial_ccitt },
370 { "x.25", polynomial_ccitt },
371 { "x3.28", polynomial_ansi },
372 { "xmodem", polynomial_ccitt },
373 };
374
375 std::string names;
376 for (const table_t *tp = table; tp < ENDOF(table); ++tp)
377 {
378 if (0 == strcasecmp(name, tp->name))
379 return tp->value;
380 if (!names.empty())
381 names += ", ";
382 names += tp->name;
383 }
384
385 quit_default.fatal_error
386 (
387 "CRC-16 polynomial name \"%s\" unknown (known names are %s)",
388 name,
389 names.c_str()
390 );
391 return polynomial_ccitt;
392 }
393
394
395 // vim: set ts=8 sw=4 et :
396