xref: /rk3399_rockchip-uboot/lib/crc32.c (revision d20a40de9db07de1f1f06a79a4da1cdda5379b75)
178acc472SPeter Tyser /*
278acc472SPeter Tyser  * This file is derived from crc32.c from the zlib-1.1.3 distribution
378acc472SPeter Tyser  * by Jean-loup Gailly and Mark Adler.
478acc472SPeter Tyser  */
578acc472SPeter Tyser 
678acc472SPeter Tyser /* crc32.c -- compute the CRC-32 of a data stream
778acc472SPeter Tyser  * Copyright (C) 1995-1998 Mark Adler
878acc472SPeter Tyser  * For conditions of distribution and use, see copyright notice in zlib.h
978acc472SPeter Tyser  */
1078acc472SPeter Tyser 
1178acc472SPeter Tyser #ifndef USE_HOSTCC
1278acc472SPeter Tyser #include <common.h>
1378acc472SPeter Tyser #endif
1478acc472SPeter Tyser #include <compiler.h>
1578acc472SPeter Tyser #include <u-boot/crc.h>
1678acc472SPeter Tyser 
1778acc472SPeter Tyser #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
1878acc472SPeter Tyser #include <watchdog.h>
1978acc472SPeter Tyser #endif
2078acc472SPeter Tyser #include "u-boot/zlib.h"
2178acc472SPeter Tyser 
2278acc472SPeter Tyser #define local static
2378acc472SPeter Tyser #define ZEXPORT	/* empty */
2478acc472SPeter Tyser 
2578acc472SPeter Tyser #define tole(x) cpu_to_le32(x)
2678acc472SPeter Tyser 
2778acc472SPeter Tyser #ifdef DYNAMIC_CRC_TABLE
2878acc472SPeter Tyser 
2978acc472SPeter Tyser local int crc_table_empty = 1;
3078acc472SPeter Tyser local uint32_t crc_table[256];
3178acc472SPeter Tyser local void make_crc_table OF((void));
3278acc472SPeter Tyser 
3378acc472SPeter Tyser /*
3478acc472SPeter Tyser   Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
3578acc472SPeter Tyser   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.
3678acc472SPeter Tyser 
3778acc472SPeter Tyser   Polynomials over GF(2) are represented in binary, one bit per coefficient,
3878acc472SPeter Tyser   with the lowest powers in the most significant bit.  Then adding polynomials
3978acc472SPeter Tyser   is just exclusive-or, and multiplying a polynomial by x is a right shift by
4078acc472SPeter Tyser   one.  If we call the above polynomial p, and represent a byte as the
4178acc472SPeter Tyser   polynomial q, also with the lowest power in the most significant bit (so the
4278acc472SPeter Tyser   byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
4378acc472SPeter Tyser   where a mod b means the remainder after dividing a by b.
4478acc472SPeter Tyser 
4578acc472SPeter Tyser   This calculation is done using the shift-register method of multiplying and
4678acc472SPeter Tyser   taking the remainder.  The register is initialized to zero, and for each
4778acc472SPeter Tyser   incoming bit, x^32 is added mod p to the register if the bit is a one (where
4878acc472SPeter Tyser   x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
4978acc472SPeter Tyser   x (which is shifting right by one and adding x^32 mod p if the bit shifted
5078acc472SPeter Tyser   out is a one).  We start with the highest power (least significant bit) of
5178acc472SPeter Tyser   q and repeat for all eight bits of q.
5278acc472SPeter Tyser 
5378acc472SPeter Tyser   The table is simply the CRC of all possible eight bit values.  This is all
5478acc472SPeter Tyser   the information needed to generate CRC's on data a byte at a time for all
5578acc472SPeter Tyser   combinations of CRC register values and incoming bytes.
5678acc472SPeter Tyser */
5778acc472SPeter Tyser local void make_crc_table()
5878acc472SPeter Tyser {
5978acc472SPeter Tyser   uint32_t c;
6078acc472SPeter Tyser   int n, k;
6178acc472SPeter Tyser   uLong poly;		/* polynomial exclusive-or pattern */
6278acc472SPeter Tyser   /* terms of polynomial defining this crc (except x^32): */
6378acc472SPeter Tyser   static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
6478acc472SPeter Tyser 
6578acc472SPeter Tyser   /* make exclusive-or pattern from polynomial (0xedb88320L) */
6678acc472SPeter Tyser   poly = 0L;
6778acc472SPeter Tyser   for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
6878acc472SPeter Tyser     poly |= 1L << (31 - p[n]);
6978acc472SPeter Tyser 
7078acc472SPeter Tyser   for (n = 0; n < 256; n++)
7178acc472SPeter Tyser   {
7278acc472SPeter Tyser     c = (uLong)n;
7378acc472SPeter Tyser     for (k = 0; k < 8; k++)
7478acc472SPeter Tyser       c = c & 1 ? poly ^ (c >> 1) : c >> 1;
7578acc472SPeter Tyser     crc_table[n] = tole(c);
7678acc472SPeter Tyser   }
7778acc472SPeter Tyser   crc_table_empty = 0;
7878acc472SPeter Tyser }
7978acc472SPeter Tyser #else
8078acc472SPeter Tyser /* ========================================================================
8178acc472SPeter Tyser  * Table of CRC-32's of all single-byte values (made by make_crc_table)
8278acc472SPeter Tyser  */
8378acc472SPeter Tyser 
8478acc472SPeter Tyser local const uint32_t crc_table[256] = {
8578acc472SPeter Tyser tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
8678acc472SPeter Tyser tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
8778acc472SPeter Tyser tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
8878acc472SPeter Tyser tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
8978acc472SPeter Tyser tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
9078acc472SPeter Tyser tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
9178acc472SPeter Tyser tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
9278acc472SPeter Tyser tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
9378acc472SPeter Tyser tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
9478acc472SPeter Tyser tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
9578acc472SPeter Tyser tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
9678acc472SPeter Tyser tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
9778acc472SPeter Tyser tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
9878acc472SPeter Tyser tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
9978acc472SPeter Tyser tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
10078acc472SPeter Tyser tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
10178acc472SPeter Tyser tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
10278acc472SPeter Tyser tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
10378acc472SPeter Tyser tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
10478acc472SPeter Tyser tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
10578acc472SPeter Tyser tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
10678acc472SPeter Tyser tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
10778acc472SPeter Tyser tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
10878acc472SPeter Tyser tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
10978acc472SPeter Tyser tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
11078acc472SPeter Tyser tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
11178acc472SPeter Tyser tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
11278acc472SPeter Tyser tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
11378acc472SPeter Tyser tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
11478acc472SPeter Tyser tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
11578acc472SPeter Tyser tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
11678acc472SPeter Tyser tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
11778acc472SPeter Tyser tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
11878acc472SPeter Tyser tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
11978acc472SPeter Tyser tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
12078acc472SPeter Tyser tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
12178acc472SPeter Tyser tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
12278acc472SPeter Tyser tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
12378acc472SPeter Tyser tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
12478acc472SPeter Tyser tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
12578acc472SPeter Tyser tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
12678acc472SPeter Tyser tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
12778acc472SPeter Tyser tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
12878acc472SPeter Tyser tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
12978acc472SPeter Tyser tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
13078acc472SPeter Tyser tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
13178acc472SPeter Tyser tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
13278acc472SPeter Tyser tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
13378acc472SPeter Tyser tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
13478acc472SPeter Tyser tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
13578acc472SPeter Tyser tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
13678acc472SPeter Tyser tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
13778acc472SPeter Tyser tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
13878acc472SPeter Tyser tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
13978acc472SPeter Tyser tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
14078acc472SPeter Tyser tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
14178acc472SPeter Tyser tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
14278acc472SPeter Tyser tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
14378acc472SPeter Tyser tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
14478acc472SPeter Tyser tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
14578acc472SPeter Tyser tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
14678acc472SPeter Tyser tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
14778acc472SPeter Tyser tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
14878acc472SPeter Tyser tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
14978acc472SPeter Tyser };
15078acc472SPeter Tyser #endif
15178acc472SPeter Tyser 
15278acc472SPeter Tyser #if 0
15378acc472SPeter Tyser /* =========================================================================
15478acc472SPeter Tyser  * This function can be used by asm versions of crc32()
15578acc472SPeter Tyser  */
15678acc472SPeter Tyser const uint32_t * ZEXPORT get_crc_table()
15778acc472SPeter Tyser {
15878acc472SPeter Tyser #ifdef DYNAMIC_CRC_TABLE
15978acc472SPeter Tyser   if (crc_table_empty) make_crc_table();
16078acc472SPeter Tyser #endif
16178acc472SPeter Tyser   return (const uint32_t *)crc_table;
16278acc472SPeter Tyser }
16378acc472SPeter Tyser #endif
16478acc472SPeter Tyser 
16578acc472SPeter Tyser /* ========================================================================= */
16678acc472SPeter Tyser # if __BYTE_ORDER == __LITTLE_ENDIAN
16778acc472SPeter Tyser #  define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
16878acc472SPeter Tyser # else
16978acc472SPeter Tyser #  define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
17078acc472SPeter Tyser # endif
17178acc472SPeter Tyser 
17278acc472SPeter Tyser /* ========================================================================= */
17378acc472SPeter Tyser 
17478acc472SPeter Tyser /* No ones complement version. JFFS2 (and other things ?)
17578acc472SPeter Tyser  * don't use ones compliment in their CRC calculations.
17678acc472SPeter Tyser  */
17778acc472SPeter Tyser uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len)
17878acc472SPeter Tyser {
17978acc472SPeter Tyser     const uint32_t *tab = crc_table;
18078acc472SPeter Tyser     const uint32_t *b =(const uint32_t *)buf;
18178acc472SPeter Tyser     size_t rem_len;
18278acc472SPeter Tyser #ifdef DYNAMIC_CRC_TABLE
18378acc472SPeter Tyser     if (crc_table_empty)
18478acc472SPeter Tyser       make_crc_table();
18578acc472SPeter Tyser #endif
18678acc472SPeter Tyser     crc = cpu_to_le32(crc);
18778acc472SPeter Tyser     /* Align it */
18878acc472SPeter Tyser     if (((long)b) & 3 && len) {
18978acc472SPeter Tyser 	 uint8_t *p = (uint8_t *)b;
19078acc472SPeter Tyser 	 do {
19178acc472SPeter Tyser 	      DO_CRC(*p++);
19278acc472SPeter Tyser 	 } while ((--len) && ((long)p)&3);
19378acc472SPeter Tyser 	 b = (uint32_t *)p;
19478acc472SPeter Tyser     }
19578acc472SPeter Tyser 
19678acc472SPeter Tyser     rem_len = len & 3;
19778acc472SPeter Tyser     len = len >> 2;
19878acc472SPeter Tyser     for (--b; len; --len) {
19978acc472SPeter Tyser 	 /* load data 32 bits wide, xor data 32 bits wide. */
20078acc472SPeter Tyser 	 crc ^= *++b; /* use pre increment for speed */
20178acc472SPeter Tyser 	 DO_CRC(0);
20278acc472SPeter Tyser 	 DO_CRC(0);
20378acc472SPeter Tyser 	 DO_CRC(0);
20478acc472SPeter Tyser 	 DO_CRC(0);
20578acc472SPeter Tyser     }
20678acc472SPeter Tyser     len = rem_len;
20778acc472SPeter Tyser     /* And the last few bytes */
20878acc472SPeter Tyser     if (len) {
20978acc472SPeter Tyser 	 uint8_t *p = (uint8_t *)(b + 1) - 1;
21078acc472SPeter Tyser 	 do {
21178acc472SPeter Tyser 	      DO_CRC(*++p); /* use pre increment for speed */
21278acc472SPeter Tyser 	 } while (--len);
21378acc472SPeter Tyser     }
21478acc472SPeter Tyser 
21578acc472SPeter Tyser     return le32_to_cpu(crc);
21678acc472SPeter Tyser }
21778acc472SPeter Tyser #undef DO_CRC
21878acc472SPeter Tyser 
21978acc472SPeter Tyser uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *p, uInt len)
22078acc472SPeter Tyser {
22178acc472SPeter Tyser      return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
22278acc472SPeter Tyser }
22378acc472SPeter Tyser 
22478acc472SPeter Tyser /*
22578acc472SPeter Tyser  * Calculate the crc32 checksum triggering the watchdog every 'chunk_sz' bytes
22678acc472SPeter Tyser  * of input.
22778acc472SPeter Tyser  */
22878acc472SPeter Tyser uint32_t ZEXPORT crc32_wd (uint32_t crc,
22978acc472SPeter Tyser 			   const unsigned char *buf,
23078acc472SPeter Tyser 			   uInt len, uInt chunk_sz)
23178acc472SPeter Tyser {
23278acc472SPeter Tyser #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
23378acc472SPeter Tyser 	const unsigned char *end, *curr;
23478acc472SPeter Tyser 	int chunk;
23578acc472SPeter Tyser 
23678acc472SPeter Tyser 	curr = buf;
23778acc472SPeter Tyser 	end = buf + len;
23878acc472SPeter Tyser 	while (curr < end) {
23978acc472SPeter Tyser 		chunk = end - curr;
24078acc472SPeter Tyser 		if (chunk > chunk_sz)
24178acc472SPeter Tyser 			chunk = chunk_sz;
24278acc472SPeter Tyser 		crc = crc32 (crc, curr, chunk);
24378acc472SPeter Tyser 		curr += chunk;
24478acc472SPeter Tyser 		WATCHDOG_RESET ();
24578acc472SPeter Tyser 	}
24678acc472SPeter Tyser #else
24778acc472SPeter Tyser 	crc = crc32 (crc, buf, len);
24878acc472SPeter Tyser #endif
24978acc472SPeter Tyser 
25078acc472SPeter Tyser 	return crc;
25178acc472SPeter Tyser }
252*d20a40deSSimon Glass 
253*d20a40deSSimon Glass void crc32_wd_buf(const unsigned char *input, unsigned int ilen,
254*d20a40deSSimon Glass 		unsigned char *output, unsigned int chunk_sz)
255*d20a40deSSimon Glass {
256*d20a40deSSimon Glass 	uint32_t crc;
257*d20a40deSSimon Glass 
258*d20a40deSSimon Glass 	crc = crc32_wd(0, input, ilen, chunk_sz);
259*d20a40deSSimon Glass 	memcpy(output, &crc, sizeof(crc));
260*d20a40deSSimon Glass }
261