summaryrefslogtreecommitdiff
path: root/usr/src/lib/libfru/libfruraw/crcutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libfru/libfruraw/crcutils.c')
-rw-r--r--usr/src/lib/libfru/libfruraw/crcutils.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/usr/src/lib/libfru/libfruraw/crcutils.c b/usr/src/lib/libfru/libfruraw/crcutils.c
new file mode 100644
index 0000000000..a3815e700d
--- /dev/null
+++ b/usr/src/lib/libfru/libfruraw/crcutils.c
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <string.h>
+#include <limits.h>
+
+#include "crcmodel.h"
+
+#if defined(_LITTLE_ENDIAN)
+
+/* Little-endian architectures need byte-swapping. */
+
+#define sws(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
+#define swl(x) (sws(x >> 16) | (sws(x) << 16))
+
+#define swap_short(x) (x = sws(x))
+#define swap_long(x) (x = swl(x))
+
+#else /* if !_LITTLE_ENDIAN */
+
+/* Big-endian anchictectures don't need byte-swapping. */
+
+#define sws(x) (x)
+#define swl(x) (x)
+
+#define swap_short(x) (x = sws(x))
+#define swap_long(x) (x = swl(x))
+
+#endif /* _LITTLE_ENDIAN */
+
+unsigned char
+compute_crc8(unsigned char *bytes, int length)
+{
+ cm_t crc_mdl;
+ p_cm_t p_crc;
+ int i;
+ unsigned char aCRC;
+
+ p_crc = &crc_mdl;
+
+ p_crc->cm_width = 8;
+ p_crc->cm_poly = 0x107; /* = X^8 + x^2 + x + 1 */
+ p_crc->cm_init = 0;
+ p_crc->cm_refin = TRUE;
+ p_crc->cm_refot = TRUE;
+ p_crc->cm_xorot = 0;
+
+ cm_ini(p_crc);
+
+ for (i = 0; i < length; i++) {
+ cm_nxt(p_crc, bytes[i]);
+ }
+
+ aCRC = (unsigned char)cm_crc(p_crc);
+
+ return (aCRC);
+}
+
+uint32_t
+compute_crc32(unsigned char *bytes, int length)
+{
+ cm_t crc_mdl;
+ p_cm_t p_crc;
+ int i;
+ uint32_t aCRC;
+
+ p_crc = &crc_mdl;
+
+ p_crc->cm_width = 32;
+ p_crc->cm_poly = 0x04c11db7;
+ p_crc->cm_init = 0xffffffff;
+ p_crc->cm_refin = TRUE;
+ p_crc->cm_refot = TRUE;
+ p_crc->cm_xorot = 0xffffffff;
+
+ cm_ini(p_crc);
+
+ for (i = 0; i < length; i++) {
+ cm_nxt(p_crc, bytes[i]);
+ }
+
+ aCRC = (uint32_t)cm_crc(p_crc);
+
+ return (aCRC);
+}
+
+/*
+ * This is the max value an uint32_t value can hold...
+ * Define this for Windows compilers which don't have "limits.h" or equivalant
+ */
+#define UINT32_T_MAX 0xFFFFFFFF
+
+uint32_t
+compute_checksum32(unsigned char *bytes, int length)
+{
+ uint32_t regval = 0;
+ int i, j, k;
+ uint32_t next4bytes;
+ unsigned char tailbytes[4] = { 0x00, 0x00, 0x00, 0x00 };
+
+ /* Grab bytes in 4-byte chunks */
+ for (i = 0; i < length-4; i += 4) {
+ /* Grab chunk as an int */
+ (void) memcpy(&next4bytes, &(bytes[i]), 4);
+ swap_long(next4bytes);
+
+ if (next4bytes > UINT32_T_MAX - regval) {
+ next4bytes -= UINT32_T_MAX - regval;
+ regval = 0;
+ }
+
+ /* Add intval to regval */
+ regval += next4bytes;
+ }
+
+ /* Grab any remaining bytes at the end */
+ for (j = length-1, k = 3; j >= i; j--, k--) {
+ tailbytes[k] = bytes[j];
+ }
+
+/*
+ * Treat any remaining bytes put into tailbytes as if they were
+ * a left-zero-padded unsigned int (uint32_t == 4 bytes!)
+ */
+ (void) memcpy(&next4bytes, tailbytes, 4);
+ swap_long(next4bytes);
+ if (next4bytes > UINT32_T_MAX - regval) {
+ next4bytes -= UINT32_T_MAX - regval;
+ regval = 0;
+ }
+ regval += next4bytes;
+
+ return ((uint32_t)regval);
+}