lib/crc8: Add crc start value
authorStefan Roese <sr@denx.de>
Fri, 8 Apr 2016 13:56:29 +0000 (15:56 +0200)
committerTom Rini <trini@konsulko.com>
Tue, 12 Apr 2016 00:48:26 +0000 (20:48 -0400)
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 <sr@denx.de>
Cc: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/tpm/tpm_tis_sandbox.c
include/linux/crc8.h
lib/crc8.c

index 9ea98075b3071b8c594d75fe6b344114f2bad520..4aade565e27a78a5b0da9ba962c4cab386b1c8cc 100644 (file)
@@ -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));
index b5fd2ac9d6e5899c20552cdee1561df7a244012f..f7c300a9b1ed0591d72b2de469a46d7e6bc52a76 100644 (file)
  * 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
index 8b68a29e40be79d95c85ce88c9c6bd65b643a1be..51d540fbcb4acc0a71a83a9055a9e295638c136f 100644 (file)
@@ -6,20 +6,27 @@
 
 #include "linux/crc8.h"
 
-unsigned int crc8(const unsigned char *vptr, int len)
+#define POLY   (0x1070U << 3)
+
+static unsigned char _crc8(unsigned short data)
 {
-       const unsigned char *data = vptr;
-       unsigned int crc = 0;
-       int i, j;
-
-       for (j = len; j; j--, data++) {
-               crc ^= (*data << 8);
-               for (i = 8; i; i--) {
-                       if (crc & 0x8000)
-                               crc ^= (0x1070 << 3);
-                       crc <<= 1;
-               }
+       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;
 }