diff options
Diffstat (limited to 'usr/src/lib/libfru/libfruraw/crcutils.c')
-rw-r--r-- | usr/src/lib/libfru/libfruraw/crcutils.c | 157 |
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); +} |