xref: /linux/lib/crc/crc32-main.c (revision a578dd095dfe8b56c167201d9aea43e47d27f807)
10bcfca56SEric Biggers // SPDX-License-Identifier: GPL-2.0-only
20bcfca56SEric Biggers /*
30bcfca56SEric Biggers  * Aug 8, 2011 Bob Pearson with help from Joakim Tjernlund and George Spelvin
40bcfca56SEric Biggers  * cleaned up code to current version of sparse and added the slicing-by-8
50bcfca56SEric Biggers  * algorithm to the closely similar existing slicing-by-4 algorithm.
60bcfca56SEric Biggers  *
70bcfca56SEric Biggers  * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
80bcfca56SEric Biggers  * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
90bcfca56SEric Biggers  * Code was from the public domain, copyright abandoned.  Code was
100bcfca56SEric Biggers  * subsequently included in the kernel, thus was re-licensed under the
110bcfca56SEric Biggers  * GNU GPL v2.
120bcfca56SEric Biggers  *
130bcfca56SEric Biggers  * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
140bcfca56SEric Biggers  * Same crc32 function was used in 5 other places in the kernel.
150bcfca56SEric Biggers  * I made one version, and deleted the others.
160bcfca56SEric Biggers  * There are various incantations of crc32().  Some use a seed of 0 or ~0.
170bcfca56SEric Biggers  * Some xor at the end with ~0.  The generic crc32() function takes
180bcfca56SEric Biggers  * seed as an argument, and doesn't xor at the end.  Then individual
190bcfca56SEric Biggers  * users can do whatever they need.
200bcfca56SEric Biggers  *   drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
210bcfca56SEric Biggers  *   fs/jffs2 uses seed 0, doesn't xor with ~0.
220bcfca56SEric Biggers  *   fs/partitions/efi.c uses seed ~0, xor's with ~0.
230bcfca56SEric Biggers  */
240bcfca56SEric Biggers 
250bcfca56SEric Biggers /* see: Documentation/staging/crc32.rst for a description of algorithms */
260bcfca56SEric Biggers 
270bcfca56SEric Biggers #include <linux/crc32.h>
28*1a822ea5SEric Biggers #include <linux/export.h>
290bcfca56SEric Biggers #include <linux/module.h>
300bcfca56SEric Biggers #include <linux/types.h>
310bcfca56SEric Biggers 
320bcfca56SEric Biggers #include "crc32table.h"
330bcfca56SEric Biggers 
340bcfca56SEric Biggers static inline u32 __maybe_unused
crc32_le_base(u32 crc,const u8 * p,size_t len)350bcfca56SEric Biggers crc32_le_base(u32 crc, const u8 *p, size_t len)
360bcfca56SEric Biggers {
370bcfca56SEric Biggers 	while (len--)
380bcfca56SEric Biggers 		crc = (crc >> 8) ^ crc32table_le[(crc & 255) ^ *p++];
390bcfca56SEric Biggers 	return crc;
400bcfca56SEric Biggers }
410bcfca56SEric Biggers 
420bcfca56SEric Biggers static inline u32 __maybe_unused
crc32_be_base(u32 crc,const u8 * p,size_t len)430bcfca56SEric Biggers crc32_be_base(u32 crc, const u8 *p, size_t len)
440bcfca56SEric Biggers {
450bcfca56SEric Biggers 	while (len--)
460bcfca56SEric Biggers 		crc = (crc << 8) ^ crc32table_be[(crc >> 24) ^ *p++];
470bcfca56SEric Biggers 	return crc;
480bcfca56SEric Biggers }
490bcfca56SEric Biggers 
500bcfca56SEric Biggers static inline u32 __maybe_unused
crc32c_base(u32 crc,const u8 * p,size_t len)510bcfca56SEric Biggers crc32c_base(u32 crc, const u8 *p, size_t len)
520bcfca56SEric Biggers {
530bcfca56SEric Biggers 	while (len--)
540bcfca56SEric Biggers 		crc = (crc >> 8) ^ crc32ctable_le[(crc & 255) ^ *p++];
550bcfca56SEric Biggers 	return crc;
560bcfca56SEric Biggers }
570bcfca56SEric Biggers 
580bcfca56SEric Biggers #ifdef CONFIG_CRC32_ARCH
590bcfca56SEric Biggers #include "crc32.h" /* $(SRCARCH)/crc32.h */
600bcfca56SEric Biggers 
crc32_optimizations(void)610bcfca56SEric Biggers u32 crc32_optimizations(void)
620bcfca56SEric Biggers {
630bcfca56SEric Biggers 	return crc32_optimizations_arch();
640bcfca56SEric Biggers }
650bcfca56SEric Biggers EXPORT_SYMBOL(crc32_optimizations);
660bcfca56SEric Biggers #else
670bcfca56SEric Biggers #define crc32_le_arch crc32_le_base
680bcfca56SEric Biggers #define crc32_be_arch crc32_be_base
690bcfca56SEric Biggers #define crc32c_arch crc32c_base
700bcfca56SEric Biggers #endif
710bcfca56SEric Biggers 
crc32_le(u32 crc,const void * p,size_t len)720bcfca56SEric Biggers u32 crc32_le(u32 crc, const void *p, size_t len)
730bcfca56SEric Biggers {
740bcfca56SEric Biggers 	return crc32_le_arch(crc, p, len);
750bcfca56SEric Biggers }
760bcfca56SEric Biggers EXPORT_SYMBOL(crc32_le);
770bcfca56SEric Biggers 
crc32_be(u32 crc,const void * p,size_t len)780bcfca56SEric Biggers u32 crc32_be(u32 crc, const void *p, size_t len)
790bcfca56SEric Biggers {
800bcfca56SEric Biggers 	return crc32_be_arch(crc, p, len);
810bcfca56SEric Biggers }
820bcfca56SEric Biggers EXPORT_SYMBOL(crc32_be);
830bcfca56SEric Biggers 
crc32c(u32 crc,const void * p,size_t len)840bcfca56SEric Biggers u32 crc32c(u32 crc, const void *p, size_t len)
850bcfca56SEric Biggers {
860bcfca56SEric Biggers 	return crc32c_arch(crc, p, len);
870bcfca56SEric Biggers }
880bcfca56SEric Biggers EXPORT_SYMBOL(crc32c);
890bcfca56SEric Biggers 
900bcfca56SEric Biggers #ifdef crc32_mod_init_arch
crc32_mod_init(void)910bcfca56SEric Biggers static int __init crc32_mod_init(void)
920bcfca56SEric Biggers {
930bcfca56SEric Biggers 	crc32_mod_init_arch();
940bcfca56SEric Biggers 	return 0;
950bcfca56SEric Biggers }
960bcfca56SEric Biggers subsys_initcall(crc32_mod_init);
970bcfca56SEric Biggers 
crc32_mod_exit(void)980bcfca56SEric Biggers static void __exit crc32_mod_exit(void)
990bcfca56SEric Biggers {
1000bcfca56SEric Biggers }
1010bcfca56SEric Biggers module_exit(crc32_mod_exit);
1020bcfca56SEric Biggers #endif
1030bcfca56SEric Biggers 
1040bcfca56SEric Biggers MODULE_DESCRIPTION("CRC32 library functions");
1050bcfca56SEric Biggers MODULE_LICENSE("GPL");
106