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