From 456ecd08ec026e67a17a77baa3778c9f1b8e474d Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 8 Apr 2016 15:56:29 +0200 Subject: [PATCH] lib/crc8: Add crc start value To make the usage of this function more flexible, lets add the CRC start value as parameter to this function. This way it can be used by other functions requiring different start values than 0 as well. For non-zero CRC start values to work, I've reworked the function a bit. The new implementation is copied from the Linux version in drivers/i2c/i2c-core.c / i2c_smbus_pec(). Which supports non-zero CRC stating values. I've double-checked that the results for zero starting values are identical to the results from the original version of this function. Signed-off-by: Stefan Roese Cc: Simon Glass Reviewed-by: Simon Glass --- drivers/tpm/tpm_tis_sandbox.c | 2 +- include/linux/crc8.h | 3 ++- lib/crc8.c | 33 ++++++++++++++++++++------------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c index 9ea98075b3..4aade565e2 100644 --- a/drivers/tpm/tpm_tis_sandbox.c +++ b/drivers/tpm/tpm_tis_sandbox.c @@ -217,7 +217,7 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, rsk.struct_version = 2; rsk.uid = ROLLBACK_SPACE_KERNEL_UID; rsk.kernel_versions = 0; - rsk.crc8 = crc8((unsigned char *)&rsk, + rsk.crc8 = crc8(0, (unsigned char *)&rsk, offsetof(struct rollback_space_kernel, crc8)); memcpy(data, &rsk, sizeof(rsk)); diff --git a/include/linux/crc8.h b/include/linux/crc8.h index b5fd2ac9d6..f7c300a9b1 100644 --- a/include/linux/crc8.h +++ b/include/linux/crc8.h @@ -14,10 +14,11 @@ * This uses an x^8 + x^2 + x + 1 polynomial. A table-based algorithm would * be faster, but for only a few bytes it isn't worth the code size * + * @crc_start: CRC8 start value * @vptr: Buffer to checksum * @len: Length of buffer in bytes * @return CRC8 checksum */ -unsigned int crc8(const unsigned char *vptr, int len); +unsigned int crc8(unsigned int crc_start, const unsigned char *vptr, int len); #endif diff --git a/lib/crc8.c b/lib/crc8.c index 8b68a29e40..51d540fbcb 100644 --- a/lib/crc8.c +++ b/lib/crc8.c @@ -6,20 +6,27 @@ #include "linux/crc8.h" -unsigned int crc8(const unsigned char *vptr, int len) -{ - const unsigned char *data = vptr; - unsigned int crc = 0; - int i, j; +#define POLY (0x1070U << 3) - for (j = len; j; j--, data++) { - crc ^= (*data << 8); - for (i = 8; i; i--) { - if (crc & 0x8000) - crc ^= (0x1070 << 3); - crc <<= 1; - } +static unsigned char _crc8(unsigned short data) +{ + int i; + + for (i = 0; i < 8; i++) { + if (data & 0x8000) + data = data ^ POLY; + data = data << 1; } - return (crc >> 8) & 0xff; + return (unsigned char)(data >> 8); +} + +unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len) +{ + int i; + + for (i = 0; i < len; i++) + crc = _crc8((crc ^ vptr[i]) << 8); + + return crc; }