Roll CRC16-CCITT into the hash infrastructure
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>
Sun, 25 Nov 2018 18:22:19 +0000 (19:22 +0100)
committerTom Rini <trini@konsulko.com>
Sun, 9 Dec 2018 01:18:44 +0000 (20:18 -0500)
The CRC16-CCITT checksum function is useful for space-constrained
applications (such as obtaining a checksum across a 2KBit or 4KBit
EEPROM) in boot applications. It has not been accessible from boot
scripts until now (due to not having a dedicated command and not being
supported by the hash infrstructure) limiting its applicability
outside of custom commands.

This adds the CRC16-CCITT (poly 0x1021, init 0x0) algorithm to the
list of available hashes and adds a new crc16_ccitt_wd_buf() to make
this possible.

Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
[trini: Fix building crc16.o for SPL/TPL]
Signed-off-by: Tom Rini <trini@konsulko.com>
common/hash.c
include/u-boot/crc.h
lib/Makefile
lib/crc16.c
tools/Makefile

index ef146513a076f4b8d9da4adcf231361404350450..413a5bfcdae5e49061ff3a4710865f11660000c1 100644 (file)
@@ -85,6 +85,33 @@ static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void
 }
 #endif
 
+static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp)
+{
+       uint16_t *ctx = malloc(sizeof(uint16_t));
+       *ctx = 0;
+       *ctxp = ctx;
+       return 0;
+}
+
+static int hash_update_crc16_ccitt(struct hash_algo *algo, void *ctx,
+                                  const void *buf, unsigned int size,
+                                  int is_last)
+{
+       *((uint16_t *)ctx) = crc16_ccitt(*((uint16_t *)ctx), buf, size);
+       return 0;
+}
+
+static int hash_finish_crc16_ccitt(struct hash_algo *algo, void *ctx,
+                                  void *dest_buf, int size)
+{
+       if (size < algo->digest_size)
+               return -1;
+
+       *((uint16_t *)dest_buf) = *((uint16_t *)ctx);
+       free(ctx);
+       return 0;
+}
+
 static int hash_init_crc32(struct hash_algo *algo, void **ctxp)
 {
        uint32_t *ctx = malloc(sizeof(uint32_t));
@@ -159,6 +186,15 @@ static struct hash_algo hash_algo[] = {
 #endif
        },
 #endif
+       {
+               .name           = "crc16-ccitt",
+               .digest_size    = 2,
+               .chunk_size     = CHUNKSZ,
+               .hash_func_ws   = crc16_ccitt_wd_buf,
+               .hash_init      = hash_init_crc16_ccitt,
+               .hash_update    = hash_update_crc16_ccitt,
+               .hash_finish    = hash_finish_crc16_ccitt,
+       },
        {
                .name           = "crc32",
                .digest_size    = 4,
index 111b22c4b646a54eae0df68246ad1df10e83e66c..788ef29a17b273c3d7de0ddc6359baf80c9c07d1 100644 (file)
@@ -13,6 +13,17 @@ unsigned int crc8(unsigned int crc_start, const unsigned char *vptr, int len);
 
 /* lib/crc16.c - 16 bit CRC with polynomial x^16+x^12+x^5+1 (CRC-CCITT) */
 uint16_t crc16_ccitt(uint16_t crc_start, const unsigned char *s, int len);
+/**
+ * crc16_ccitt_wd_buf - Perform CRC16-CCIT on an input buffer and return the
+ *                      16-bit result (network byte-order) in an output buffer
+ *
+ * @in:        input buffer
+ * @len: input buffer length
+ * @out: output buffer (at least 2 bytes)
+ * @chunk_sz: ignored
+ */
+void crc16_ccitt_wd_buf(const uint8_t *in, uint len,
+                       uint8_t *out, uint chunk_sz);
 
 /* lib/crc32.c */
 uint32_t crc32 (uint32_t, const unsigned char *, uint);
index 8321355a44f7c73ce430b8c74156123295d7e347..a6dd928a9265f1a823965edb54095d968730b97a 100644 (file)
@@ -76,6 +76,7 @@ endif
 
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
+obj-$(CONFIG_$(SPL_TPL_)HASH_SUPPORT) += crc16.o
 obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
 endif
 obj-$(CONFIG_ADDR_MAP) += addr_map.o
index 25bdfd8e72f450bcd613acaa8025776dd4a3fe0d..f46ba727c9a869afae3af9bfd0abff1d3b26db42 100644 (file)
  *==========================================================================
  */
 
+#ifdef USE_HOSTCC
+#include <arpa/inet.h>
+#else
+#include <common.h>
+#endif
 #include <u-boot/crc.h>
 
 /* Table of CRC constants - implements x^16+x^12+x^5+1 */
@@ -60,14 +65,20 @@ static const uint16_t crc16_tab[] = {
        0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
 };
 
-uint16_t crc16_ccitt(uint16_t crc_start, unsigned char *buf, int len)
+uint16_t crc16_ccitt(uint16_t cksum, const unsigned char *buf, int len)
 {
-       int i;
-       uint16_t cksum;
-
-       cksum = crc_start;
-       for (i = 0;  i < len;  i++)
+       for (int i = 0;  i < len;  i++)
                cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xff] ^ (cksum << 8);
 
        return cksum;
 }
+
+void crc16_ccitt_wd_buf(const uint8_t *in, uint len,
+                       uint8_t *out, uint chunk_sz)
+{
+       uint16_t crc;
+
+       crc = crc16_ccitt(0, in, len);
+       crc = htons(crc);
+       memcpy(out, &crc, sizeof(crc));
+}
index c93d17a42fdf93a7705d156e3bcb461c3aac2592..c26b631560ea01487623720b73cd4aa4d9d67d78 100644 (file)
@@ -106,6 +106,7 @@ dumpimage-mkimage-objs := aisimage.o \
                        stm32image.o \
                        $(ROCKCHIP_OBS) \
                        socfpgaimage.o \
+                       lib/crc16.o \
                        lib/sha1.o \
                        lib/sha256.o \
                        common/hash.o \