[][OpenWrt Dev][Add crc32sum host utility]
[Description]
Add crc32sum host utility
[Release-log]
N/A
Change-Id: I8b616fafeeeda88f021aab9d6982073f29878b54
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5602768
diff --git a/openwrt_patches-21.02/122-add-crc32sum-utility.patch b/openwrt_patches-21.02/122-add-crc32sum-utility.patch
new file mode 100644
index 0000000..85a6462
--- /dev/null
+++ b/openwrt_patches-21.02/122-add-crc32sum-utility.patch
@@ -0,0 +1,10 @@
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -26,6 +26,7 @@ tools-y += e2fsprogs fakeroot findutils firmware-utils flex gengetopt
+ tools-y += libressl libtool lzma m4 make-ext4fs missing-macros mkimage
+ tools-y += mklibs mm-macros mtd-utils mtools padjffs2 patch-image
+ tools-y += patchelf pkgconf quilt squashfskit4 sstrip xxd zip zlib zstd
++tools-y += crc32sum
+ tools-$(BUILD_B43_TOOLS) += b43-tools
+ tools-$(BUILD_ISL) += isl
+ tools-$(BUILD_TOOLCHAIN) += expat gmp libelf mpc mpfr
diff --git a/prepare_sdk.sh b/prepare_sdk.sh
index ae48710..7a3dd67 100755
--- a/prepare_sdk.sh
+++ b/prepare_sdk.sh
@@ -33,6 +33,7 @@
#cp mtk target to OpenWRT
cp -fpR ${MTK_FEEDS_DIR}/target ./
cp -fpR ${MTK_FEEDS_DIR}/package ./
+cp -fpR ${MTK_FEEDS_DIR}/tools ./
#remove patch if choose to not "keep" patch
if [ -z ${2} ]; then
remove_patches
diff --git a/tools/crc32sum/Makefile b/tools/crc32sum/Makefile
new file mode 100644
index 0000000..bc13ecf
--- /dev/null
+++ b/tools/crc32sum/Makefile
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2021 MediaTek Inc. All rights reserved.
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=crc32sum
+PKG_VERSION:=1.0
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Prepare
+ mkdir -p $(HOST_BUILD_DIR)
+ $(CP) -a ./src/* $(HOST_BUILD_DIR)/
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/crc32sum $(STAGING_DIR_HOST)/bin/
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/crc32sum/src/Makefile b/tools/crc32sum/src/Makefile
new file mode 100644
index 0000000..f66cc39
--- /dev/null
+++ b/tools/crc32sum/src/Makefile
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2021 MediaTek Inc. All rights reserved.
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+all: crc32sum
+
+crc32sum: crc32sum.c
+ $(CC) $(CFLAGS) -O2 -ggdb -MD -o $@ $< $(LDFLAGS)
+
+clean:
+ rm -f crc32sum crc32sum.d
+
+.PHONY: clean
+
+-include crc32sum.d
\ No newline at end of file
diff --git a/tools/crc32sum/src/crc32sum.c b/tools/crc32sum/src/crc32sum.c
new file mode 100644
index 0000000..381c7a9
--- /dev/null
+++ b/tools/crc32sum/src/crc32sum.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#define SET_BINARY_MODE(_f) _setmode(_fileno(_f, O_BINARY)
+#else
+#define SET_BINARY_MODE(_f) ((void)0)
+#endif
+
+#define CRC32_LE_POLY_DEFAULT 0xedb88320
+#define CRC32_BE_POLY_DEFAULT 0x04c11db7
+#define CRC32_TABLE_ITEMS 256
+
+static uint32_t crc32_le_calc(uint32_t crc, const uint8_t *data, size_t length,
+ const uint32_t *crc_table)
+{
+ while (length--)
+ crc = crc_table[(uint8_t)(crc ^ *data++)] ^ (crc >> 8);
+
+ return crc;
+}
+
+static void crc32_le_init(uint32_t *crc_table, uint32_t poly)
+{
+ uint32_t i, j, v;
+
+ for (i = 0; i < CRC32_TABLE_ITEMS; i++) {
+ v = i;
+
+ for (j = 0; j < 8; j++)
+ v = (v >> 1) ^ ((v & 1) ? poly : 0);
+
+ crc_table[i] = v;
+ }
+}
+
+static uint32_t crc32_be_calc(uint32_t crc, const uint8_t *data, size_t length,
+ const uint32_t *crc_table)
+{
+ while (length--)
+ crc = crc_table[(uint8_t)((crc >> 24) ^ *data++)] ^ (crc << 8);
+
+ return crc;
+}
+
+static void crc32_be_init(uint32_t *crc_table, uint32_t poly)
+{
+ uint32_t i, j, v;
+
+ for (i = 0; i < CRC32_TABLE_ITEMS; i++) {
+ v = i << 24;
+
+ for (j = 0; j < 8; j++)
+ v = (v << 1) ^ ((v & (1 << 31)) ? poly : 0);
+
+ crc_table[i] = v;
+ }
+}
+
+struct crc_funcs {
+ uint32_t poly;
+
+ void (*init)(uint32_t *crc_table, uint32_t poly);
+ uint32_t (*calc)(uint32_t crc, const uint8_t *data, size_t length,
+ const uint32_t *crc_table);
+};
+
+static const struct crc_funcs crc32_le = {
+ .poly = CRC32_LE_POLY_DEFAULT,
+ .init = crc32_le_init,
+ .calc = crc32_le_calc,
+};
+
+static const struct crc_funcs crc32_be = {
+ .poly = CRC32_BE_POLY_DEFAULT,
+ .init = crc32_be_init,
+ .calc = crc32_be_calc,
+};
+
+static const struct crc_funcs *crc32_algo = &crc32_le;
+static uint32_t crc32_poly;
+static uint32_t crc32_val;
+static const char *input_file;
+static bool output_decimal;
+static bool no_comp;
+
+static void err(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "Error: ");
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+static void usage(FILE *con, const char *progname, int exitcode)
+{
+ const char *prog;
+ size_t len;
+
+ len = strlen(progname);
+ prog = progname + len - 1;
+
+ while (prog > progname) {
+ if (*prog == '\\' || *prog == '/') {
+ prog++;
+ break;
+ }
+
+ prog--;
+ }
+
+ fprintf(con, "CRC32 checksum tool\n");
+ fprintf(con, "\n");
+ fprintf(con, "Usage: %s [options] <input_file>\n", prog);
+ fprintf(con, "\n");
+ fprintf(con, "Options:\n");
+ fprintf(con, "\t-h display help message\n");
+ fprintf(con, "\t-i <val> crc value for incremental calculation\n");
+ fprintf(con, "\t (default is 0)\n");
+ fprintf(con, "\t-p <val> polynomial for calculation\n");
+ fprintf(con, "\t (default is 0x%08x for LE, 0x%08x for BE)\n",
+ crc32_le.poly, crc32_be.poly);
+ fprintf(con, "\t-b use big-endian mode\n");
+ fprintf(con, "\t-n do not use one's complement\n");
+ fprintf(con, "\t-d use decimal output\n");
+ fprintf(con, "\n");
+
+ exit(exitcode);
+}
+
+static int parse_args(int argc, char *argv[])
+{
+ int opt;
+
+ static const char *optstring = "i:p:bndh";
+
+ opterr = 0;
+
+ while ((opt = getopt(argc, argv, optstring)) >= 0) {
+ switch (opt) {
+ case 'i':
+ if (!isxdigit(optarg[0])) {
+ err("Invalid crc value - %s\n", optarg);
+ return -EINVAL;
+ }
+
+ crc32_val = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'p':
+ if (!isxdigit(optarg[0])) {
+ err("Invalid polynomial value - %s\n", optarg);
+ return -EINVAL;
+ }
+
+ crc32_poly = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'b':
+ crc32_algo = &crc32_be;
+ break;
+
+ case 'n':
+ no_comp = true;
+ break;
+
+ case 'd':
+ output_decimal = true;
+ break;
+
+ case 'h':
+ usage(stdout, argv[0], 0);
+ break;
+
+ default:
+ usage(stderr, argv[0], EXIT_FAILURE);
+ }
+ }
+
+ if (!crc32_poly)
+ crc32_poly = crc32_algo->poly;
+
+ if (optind >= argc)
+ input_file = "-";
+ else
+ input_file = argv[optind];
+
+ if (!input_file[0]) {
+ err("Input file must not be empty\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int crc32_calc(void)
+{
+ uint32_t crc_table[CRC32_TABLE_ITEMS];
+ bool using_stdin = false;
+ uint8_t buf[4096];
+ size_t size;
+ int ret, i;
+ FILE *f;
+
+ if (!strcmp(input_file, "-")) {
+ SET_BINARY_MODE(stdin);
+ using_stdin = true;
+ f = stdin;
+ } else {
+ f = fopen(input_file, "rb");
+ }
+
+ if (!f) {
+ err("Failed to open file '%s'\n", input_file);
+ return -EINVAL;
+ }
+
+ crc32_algo->init(crc_table, crc32_poly);
+
+ if (!no_comp)
+ crc32_val ^= 0xffffffff;
+
+ do {
+ size = fread(buf, 1, sizeof(buf), f);
+
+ if (size) {
+ crc32_val = crc32_algo->calc(crc32_val, buf, size,
+ crc_table);
+ }
+
+ if (size < sizeof(buf)) {
+ ret = ferror(f);
+
+ if (!ret && feof(f))
+ break;
+
+ err("Error while reading file: %d\n", ret);
+ break;
+ }
+ } while (true);
+
+ if (!using_stdin)
+ fclose(f);
+
+ if (ret)
+ return ret;
+
+ if (!no_comp)
+ crc32_val ^= 0xffffffff;
+
+ if (output_decimal)
+ printf("%u\n", crc32_val);
+ else
+ printf("%08x\n", crc32_val);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ if (parse_args(argc, argv))
+ return 1;
+
+ return crc32_calc();
+}