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