xref: /illumos-gate/usr/src/lib/libfru/libfruraw/crcutils.c (revision 48edc7cf07b5dccc3ad84bf2dafe4150bd666d60)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <string.h>
28 #include <limits.h>
29 
30 #include "crcmodel.h"
31 
32 #if defined(_LITTLE_ENDIAN)
33 
34 /* Little-endian architectures need byte-swapping. */
35 
36 #define	sws(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
37 #define	swl(x) (sws(x >> 16) | (sws(x) << 16))
38 
39 #define	swap_short(x) (x = sws(x))
40 #define	swap_long(x) (x = swl(x))
41 
42 #else   /* if !_LITTLE_ENDIAN */
43 
44 /* Big-endian anchictectures don't need byte-swapping. */
45 
46 #define	sws(x) (x)
47 #define	swl(x) (x)
48 
49 #define	swap_short(x) (x = sws(x))
50 #define	swap_long(x) (x = swl(x))
51 
52 #endif  /* _LITTLE_ENDIAN */
53 
54 unsigned char
55 compute_crc8(unsigned char *bytes, int length)
56 {
57 	cm_t crc_mdl;
58 	p_cm_t p_crc;
59 	int i;
60 	unsigned char aCRC;
61 
62 	p_crc = &crc_mdl;
63 
64 	p_crc->cm_width = 8;
65 	p_crc->cm_poly = 0x107; /* = X^8 + x^2 + x + 1 */
66 	p_crc->cm_init = 0;
67 	p_crc->cm_refin = TRUE;
68 	p_crc->cm_refot = TRUE;
69 	p_crc->cm_xorot = 0;
70 
71 	cm_ini(p_crc);
72 
73 	for (i = 0; i < length; i++) {
74 		cm_nxt(p_crc, bytes[i]);
75 	}
76 
77 	aCRC = (unsigned char)cm_crc(p_crc);
78 
79 	return (aCRC);
80 }
81 
82 uint32_t
83 compute_crc32(unsigned char *bytes, int length)
84 {
85 	cm_t crc_mdl;
86 	p_cm_t p_crc;
87 	int i;
88 	uint32_t aCRC;
89 
90 	p_crc = &crc_mdl;
91 
92 	p_crc->cm_width = 32;
93 	p_crc->cm_poly = 0x04c11db7;
94 	p_crc->cm_init = 0xffffffff;
95 	p_crc->cm_refin = TRUE;
96 	p_crc->cm_refot = TRUE;
97 	p_crc->cm_xorot = 0xffffffff;
98 
99 	cm_ini(p_crc);
100 
101 	for (i = 0; i < length; i++) {
102 		cm_nxt(p_crc, bytes[i]);
103 	}
104 
105 	aCRC = (uint32_t)cm_crc(p_crc);
106 
107 	return (aCRC);
108 }
109 
110 /*
111  * This is the max value an uint32_t value can hold...
112  * Define this for Windows compilers which don't have "limits.h" or equivalant
113  */
114 #define	UINT32_T_MAX 0xFFFFFFFF
115 
116 uint32_t
117 compute_checksum32(unsigned char *bytes, int length)
118 {
119 	uint32_t regval = 0;
120 	int i, j, k;
121 	uint32_t next4bytes;
122 	unsigned char tailbytes[4] = { 0x00, 0x00, 0x00, 0x00 };
123 
124 	/* Grab bytes in 4-byte chunks */
125 	for (i = 0; i < length-4; i += 4) {
126 		/* Grab chunk as an int */
127 		(void) memcpy(&next4bytes, &(bytes[i]), 4);
128 		swap_long(next4bytes);
129 
130 		if (next4bytes > UINT32_T_MAX - regval) {
131 			next4bytes -= UINT32_T_MAX - regval;
132 			regval = 0;
133 		}
134 
135 		/* Add intval to regval */
136 		regval += next4bytes;
137 	}
138 
139 	/* Grab any remaining bytes at the end */
140 	for (j = length-1, k = 3; j >= i; j--, k--) {
141 		tailbytes[k] = bytes[j];
142 	}
143 
144 /*
145  * Treat any remaining bytes put into tailbytes as if they were
146  * a left-zero-padded unsigned int (uint32_t == 4 bytes!)
147  */
148 	(void) memcpy(&next4bytes, tailbytes, 4);
149 	swap_long(next4bytes);
150 	if (next4bytes > UINT32_T_MAX - regval) {
151 		next4bytes -= UINT32_T_MAX - regval;
152 		regval = 0;
153 	}
154 	regval += next4bytes;
155 
156 	return ((uint32_t)regval);
157 }
158