Blame view

lib/crc32.c 10.2 KB
affae2bff   wdenk   Initial revision
1
2
3
4
5
6
7
8
9
  /*
   * This file is derived from crc32.c from the zlib-1.1.3 distribution
   * by Jean-loup Gailly and Mark Adler.
   */
  
  /* crc32.c -- compute the CRC-32 of a data stream
   * Copyright (C) 1995-1998 Mark Adler
   * For conditions of distribution and use, see copyright notice in zlib.h
   */
74a18ee8a   Simon Glass   crc32: Correct en...
10
11
12
  #ifdef USE_HOSTCC
  #include <arpa/inet.h>
  #else
b3aff0cb9   Jon Loeliger   disk/ doc/ lib_*/...
13
  #include <common.h>
affae2bff   wdenk   Initial revision
14
  #endif
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
15
16
  #include <compiler.h>
  #include <u-boot/crc.h>
affae2bff   wdenk   Initial revision
17

f3b6d528e   Grant Erickson   Fix Compilation E...
18
  #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
1de6b28be   Bartlomiej Sieka   Use watchdog-awar...
19
  #include <watchdog.h>
f3b6d528e   Grant Erickson   Fix Compilation E...
20
  #endif
a31e091ad   Jean-Christophe PLAGNIOL-VILLARD   rename include/zl...
21
  #include "u-boot/zlib.h"
affae2bff   wdenk   Initial revision
22
23
24
  
  #define local static
  #define ZEXPORT	/* empty */
affae2bff   wdenk   Initial revision
25

3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
26
  #define tole(x) cpu_to_le32(x)
36c1877c5   Faiz Abbas   lib: Kconfig: Mov...
27
  #ifdef CONFIG_DYNAMIC_CRC_TABLE
affae2bff   wdenk   Initial revision
28
29
  
  local int crc_table_empty = 1;
89cdab788   Mike Frysinger   crc32: use uint32...
30
  local uint32_t crc_table[256];
affae2bff   wdenk   Initial revision
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  local void make_crc_table OF((void));
  
  /*
    Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
    x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
  
    Polynomials over GF(2) are represented in binary, one bit per coefficient,
    with the lowest powers in the most significant bit.  Then adding polynomials
    is just exclusive-or, and multiplying a polynomial by x is a right shift by
    one.  If we call the above polynomial p, and represent a byte as the
    polynomial q, also with the lowest power in the most significant bit (so the
    byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
    where a mod b means the remainder after dividing a by b.
  
    This calculation is done using the shift-register method of multiplying and
    taking the remainder.  The register is initialized to zero, and for each
    incoming bit, x^32 is added mod p to the register if the bit is a one (where
    x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
    x (which is shifting right by one and adding x^32 mod p if the bit shifted
    out is a one).  We start with the highest power (least significant bit) of
    q and repeat for all eight bits of q.
  
    The table is simply the CRC of all possible eight bit values.  This is all
    the information needed to generate CRC's on data a byte at a time for all
    combinations of CRC register values and incoming bytes.
  */
  local void make_crc_table()
  {
89cdab788   Mike Frysinger   crc32: use uint32...
59
    uint32_t c;
affae2bff   wdenk   Initial revision
60
    int n, k;
7ed401173   Wolfgang Denk   Coding Style clea...
61
    uLong poly;		/* polynomial exclusive-or pattern */
affae2bff   wdenk   Initial revision
62
63
64
65
66
67
68
69
70
71
72
73
74
    /* terms of polynomial defining this crc (except x^32): */
    static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
  
    /* make exclusive-or pattern from polynomial (0xedb88320L) */
    poly = 0L;
    for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
      poly |= 1L << (31 - p[n]);
  
    for (n = 0; n < 256; n++)
    {
      c = (uLong)n;
      for (k = 0; k < 8; k++)
        c = c & 1 ? poly ^ (c >> 1) : c >> 1;
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
75
      crc_table[n] = tole(c);
affae2bff   wdenk   Initial revision
76
77
78
79
80
81
82
    }
    crc_table_empty = 0;
  }
  #else
  /* ========================================================================
   * Table of CRC-32's of all single-byte values (made by make_crc_table)
   */
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
83

89cdab788   Mike Frysinger   crc32: use uint32...
84
  local const uint32_t crc_table[256] = {
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
  tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
  tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
  tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
  tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
  tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
  tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
  tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
  tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
  tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
  tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
  tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
  tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
  tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
  tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
  tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
  tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
  tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
  tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
  tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
  tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
  tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
  tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
  tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
  tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
  tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
  tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
  tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
  tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
  tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
  tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
  tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
  tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
  tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
  tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
  tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
  tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
  tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
  tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
  tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
  tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
  tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
  tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
  tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
  tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
  tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
  tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
  tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
  tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
  tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
  tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
  tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
  tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
  tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
  tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
  tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
  tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
  tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
  tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
  tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
  tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
  tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
  tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
  tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
affae2bff   wdenk   Initial revision
149
150
151
152
153
154
155
  };
  #endif
  
  #if 0
  /* =========================================================================
   * This function can be used by asm versions of crc32()
   */
89cdab788   Mike Frysinger   crc32: use uint32...
156
  const uint32_t * ZEXPORT get_crc_table()
affae2bff   wdenk   Initial revision
157
  {
36c1877c5   Faiz Abbas   lib: Kconfig: Mov...
158
  #ifdef CONFIG_DYNAMIC_CRC_TABLE
affae2bff   wdenk   Initial revision
159
160
    if (crc_table_empty) make_crc_table();
  #endif
89cdab788   Mike Frysinger   crc32: use uint32...
161
    return (const uint32_t *)crc_table;
affae2bff   wdenk   Initial revision
162
163
164
165
  }
  #endif
  
  /* ========================================================================= */
322ff395c   Jeff Angielski   env: fix endian o...
166
  # if __BYTE_ORDER == __LITTLE_ENDIAN
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
167
168
169
170
  #  define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
  # else
  #  define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
  # endif
affae2bff   wdenk   Initial revision
171
172
  
  /* ========================================================================= */
affae2bff   wdenk   Initial revision
173
174
175
176
  
  /* No ones complement version. JFFS2 (and other things ?)
   * don't use ones compliment in their CRC calculations.
   */
89cdab788   Mike Frysinger   crc32: use uint32...
177
  uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len)
affae2bff   wdenk   Initial revision
178
  {
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
179
180
181
      const uint32_t *tab = crc_table;
      const uint32_t *b =(const uint32_t *)buf;
      size_t rem_len;
36c1877c5   Faiz Abbas   lib: Kconfig: Mov...
182
  #ifdef CONFIG_DYNAMIC_CRC_TABLE
affae2bff   wdenk   Initial revision
183
184
185
      if (crc_table_empty)
        make_crc_table();
  #endif
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
      crc = cpu_to_le32(crc);
      /* Align it */
      if (((long)b) & 3 && len) {
  	 uint8_t *p = (uint8_t *)b;
  	 do {
  	      DO_CRC(*p++);
  	 } while ((--len) && ((long)p)&3);
  	 b = (uint32_t *)p;
      }
  
      rem_len = len & 3;
      len = len >> 2;
      for (--b; len; --len) {
  	 /* load data 32 bits wide, xor data 32 bits wide. */
  	 crc ^= *++b; /* use pre increment for speed */
  	 DO_CRC(0);
  	 DO_CRC(0);
  	 DO_CRC(0);
  	 DO_CRC(0);
      }
      len = rem_len;
      /* And the last few bytes */
      if (len) {
  	 uint8_t *p = (uint8_t *)(b + 1) - 1;
  	 do {
  	      DO_CRC(*++p); /* use pre increment for speed */
  	 } while (--len);
affae2bff   wdenk   Initial revision
213
      }
affae2bff   wdenk   Initial revision
214

3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
215
      return le32_to_cpu(crc);
affae2bff   wdenk   Initial revision
216
  }
3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
217
  #undef DO_CRC
affae2bff   wdenk   Initial revision
218

3ee8c1207   Joakim Tjernlund   crc32: Impl. linu...
219
220
221
222
  uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *p, uInt len)
  {
       return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
  }
215b01bba   Bartlomiej Sieka   Add support for c...
223
224
225
226
227
  
  /*
   * Calculate the crc32 checksum triggering the watchdog every 'chunk_sz' bytes
   * of input.
   */
03ccdbcd5   Wolfgang Denk   lib_generic/crc32...
228
229
230
  uint32_t ZEXPORT crc32_wd (uint32_t crc,
  			   const unsigned char *buf,
  			   uInt len, uInt chunk_sz)
215b01bba   Bartlomiej Sieka   Add support for c...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  {
  #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  	const unsigned char *end, *curr;
  	int chunk;
  
  	curr = buf;
  	end = buf + len;
  	while (curr < end) {
  		chunk = end - curr;
  		if (chunk > chunk_sz)
  			chunk = chunk_sz;
  		crc = crc32 (crc, curr, chunk);
  		curr += chunk;
  		WATCHDOG_RESET ();
  	}
  #else
7ed401173   Wolfgang Denk   Coding Style clea...
247
  	crc = crc32 (crc, buf, len);
215b01bba   Bartlomiej Sieka   Add support for c...
248
249
250
251
  #endif
  
  	return crc;
  }
d20a40de9   Simon Glass   Roll crc32 into h...
252
253
254
255
256
257
258
  
  void crc32_wd_buf(const unsigned char *input, unsigned int ilen,
  		unsigned char *output, unsigned int chunk_sz)
  {
  	uint32_t crc;
  
  	crc = crc32_wd(0, input, ilen, chunk_sz);
74a18ee8a   Simon Glass   crc32: Correct en...
259
  	crc = htonl(crc);
d20a40de9   Simon Glass   Roll crc32 into h...
260
261
  	memcpy(output, &crc, sizeof(crc));
  }