]> git.neil.brown.name Git - mdadm.git/blob - crc32c.c
Release mdadm-4.0
[mdadm.git] / crc32c.c
1 /*
2  * Oct 28, 2015 Song Liu simplified the code and port it to mdadm
3  *
4  * Aug 8, 2011 Bob Pearson with help from Joakim Tjernlund and George Spelvin
5  * cleaned up code to current version of sparse and added the slicing-by-8
6  * algorithm to the closely similar existing slicing-by-4 algorithm.
7  *
8  * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
9  * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
10  * Code was from the public domain, copyright abandoned.  Code was
11  * subsequently included in the kernel, thus was re-licensed under the
12  * GNU GPL v2.
13  *
14  * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
15  * Same crc32 function was used in 5 other places in the kernel.
16  * I made one version, and deleted the others.
17  * There are various incantations of crc32().  Some use a seed of 0 or ~0.
18  * Some xor at the end with ~0.  The generic crc32() function takes
19  * seed as an argument, and doesn't xor at the end.  Then individual
20  * users can do whatever they need.
21  *   drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
22  *   fs/jffs2 uses seed 0, doesn't xor with ~0.
23  *   fs/partitions/efi.c uses seed ~0, xor's with ~0.
24  *
25  * This source code is licensed under the GNU General Public License,
26  * Version 2.  See the file COPYING for more details.
27  */
28
29 #include <sys/types.h>
30 #include <asm/types.h>
31 #include <stdlib.h>
32
33 /*
34  * There are multiple 16-bit CRC polynomials in common use, but this is
35  * *the* standard CRC-32 polynomial, first popularized by Ethernet.
36  * 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+x^0
37  */
38 #define CRCPOLY_LE 0xedb88320
39 #define CRCPOLY_BE 0x04c11db7
40
41 /*
42  * This is the CRC32c polynomial, as outlined by Castagnoli.
43  * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+
44  * x^8+x^6+x^0
45  */
46 #define CRC32C_POLY_LE 0x82F63B78
47
48 /**
49  * crc32_le_generic() - Calculate bitwise little-endian Ethernet AUTODIN II
50  *                      CRC32/CRC32C
51  * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for other
52  *       uses, or the previous crc32/crc32c value if computing incrementally.
53  * @p: pointer to buffer over which CRC32/CRC32C is run
54  * @len: length of buffer @p
55  * @polynomial: CRC32/CRC32c LE polynomial
56  */
57 static inline __u32 crc32_le_generic(__u32 crc, unsigned char const *p,
58                                      size_t len, __u32 polynomial)
59 {
60         int i;
61         while (len--) {
62                 crc ^= *p++;
63                 for (i = 0; i < 8; i++)
64                         crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
65         }
66         return crc;
67 }
68
69 __u32 crc32_le(__u32 crc, unsigned char const *p, size_t len)
70 {
71         return crc32_le_generic(crc, p, len, CRCPOLY_LE);
72 }
73
74 __u32 crc32c_le(__u32 crc, unsigned char const *p, size_t len)
75 {
76         return crc32_le_generic(crc, p, len, CRC32C_POLY_LE);
77 }
78
79 /**
80  * crc32_be_generic() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
81  * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
82  *      other uses, or the previous crc32 value if computing incrementally.
83  * @p: pointer to buffer over which CRC32 is run
84  * @len: length of buffer @p
85  * @polynomial: CRC32 BE polynomial
86  */
87 static inline __u32 crc32_be_generic(__u32 crc, unsigned char const *p,
88                                      size_t len, __u32 polynomial)
89 {
90         int i;
91         while (len--) {
92                 crc ^= *p++ << 24;
93                 for (i = 0; i < 8; i++)
94                         crc =
95                             (crc << 1) ^ ((crc & 0x80000000) ? polynomial :
96                                           0);
97         }
98         return crc;
99 }
100
101 __u32 crc32_be(__u32 crc, unsigned char const *p, size_t len)
102 {
103         return crc32_be_generic(crc, p, len, CRCPOLY_BE);
104 }