mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 17:42:41 +00:00
678 lines
17 KiB
Diff
678 lines
17 KiB
Diff
From eea2581a6ab99f62ce12137cc69e317d8de67215 Mon Sep 17 00:00:00 2001
|
|
From: Your Name <you@example.com>
|
|
Date: Wed, 7 Aug 2024 15:52:58 +0800
|
|
Subject: [PATCH] add sonicfi rap630w 211g
|
|
|
|
Signed-off-by: Your Name <you@example.com>
|
|
---
|
|
include/image-commands.mk | 27 ++
|
|
package/base-files/files/lib/upgrade/stage2 | 2 +-
|
|
scripts/mkits_sonicfi_rap630w_211g.sh | 237 ++++++++++++++++
|
|
tools/Makefile | 1 +
|
|
tools/crc32sum/Makefile | 23 ++
|
|
tools/crc32sum/src/Makefile | 18 ++
|
|
tools/crc32sum/src/crc32sum.c | 282 ++++++++++++++++++++
|
|
7 files changed, 589 insertions(+), 1 deletion(-)
|
|
create mode 100755 scripts/mkits_sonicfi_rap630w_211g.sh
|
|
create mode 100644 tools/crc32sum/Makefile
|
|
create mode 100644 tools/crc32sum/src/Makefile
|
|
create mode 100644 tools/crc32sum/src/crc32sum.c
|
|
|
|
diff --git a/include/image-commands.mk b/include/image-commands.mk
|
|
index dc6ee6e7c1..0013eeb540 100644
|
|
--- a/include/image-commands.mk
|
|
+++ b/include/image-commands.mk
|
|
@@ -291,6 +291,32 @@ define Build/initrd_compression
|
|
$(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_ZSTD),.zstd)
|
|
endef
|
|
|
|
+ifeq ($(CONFIG_TARGET_mediatek_mt7981_DEVICE_sonicfi_rap630w_211g),y)
|
|
+define Build/fit
|
|
+ $(TOPDIR)/scripts/mkits_sonicfi_rap630w_211g.sh \
|
|
+ -D $(DEVICE_NAME) -o $@.its -k $@ \
|
|
+ -C $(word 1,$(1)) \
|
|
+ $(if $(word 2,$(1)),\
|
|
+ $(if $(findstring 11,$(if $(DEVICE_DTS_OVERLAY),1)$(if $(findstring $(KERNEL_BUILD_DIR)/image-,$(word 2,$(1))),,1)), \
|
|
+ -d $(KERNEL_BUILD_DIR)/image-$$(basename $(word 2,$(1))), \
|
|
+ -d $(word 2,$(1)))) \
|
|
+ $(if $(findstring with-rootfs,$(word 3,$(1))),-r $(IMAGE_ROOTFS)) \
|
|
+ $(if $(findstring with-initrd,$(word 3,$(1))), \
|
|
+ $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS_SEPARATE), \
|
|
+ -i $(KERNEL_BUILD_DIR)/initrd.cpio$(strip $(call Build/initrd_compression)))) \
|
|
+ -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \
|
|
+ $(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \
|
|
+ $(if $(DEVICE_DTS_DELIMITER),-l $(DEVICE_DTS_DELIMITER)) \
|
|
+ $(if $(DEVICE_DTS_LOADADDR),-s $(DEVICE_DTS_LOADADDR)) \
|
|
+ $(if $(DEVICE_DTS_OVERLAY),$(foreach dtso,$(DEVICE_DTS_OVERLAY), -O $(dtso):$(KERNEL_BUILD_DIR)/image-$(dtso).dtbo)) \
|
|
+ -c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config-1") \
|
|
+ -A $(LINUX_KARCH) -v $(LINUX_VERSION) \
|
|
+ $(if $(CONFIG_TARGET_ROOTFS_SQUASHFS),-r $(ROOTFS/squashfs/$(DEVICE_NAME)))
|
|
+ PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage $(if $(findstring external,$(word 3,$(1))),\
|
|
+ -E -B 0x1000 $(if $(findstring static,$(word 3,$(1))),-p 0x1000)) -f $@.its $@.new
|
|
+ @mv $@.new $@
|
|
+endef
|
|
+else
|
|
define Build/fit
|
|
$(TOPDIR)/scripts/mkits.sh \
|
|
-D $(DEVICE_NAME) -o $@.its -k $@ \
|
|
@@ -314,6 +340,7 @@ define Build/fit
|
|
-E -B 0x1000 $(if $(findstring static,$(word 3,$(1))),-p 0x1000)) -f $@.its $@.new
|
|
@mv $@.new $@
|
|
endef
|
|
+endif
|
|
|
|
define Build/libdeflate-gzip
|
|
$(STAGING_DIR_HOST)/bin/libdeflate-gzip -f -12 -c $@ $(1) > $@.new
|
|
diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2
|
|
index 5ce0b3549c..2f1cb45b6e 100755
|
|
--- a/package/base-files/files/lib/upgrade/stage2
|
|
+++ b/package/base-files/files/lib/upgrade/stage2
|
|
@@ -11,7 +11,7 @@ export VERBOSE=1
|
|
export CONFFILES=/tmp/sysupgrade.conffiles
|
|
|
|
RAMFS_COPY_BIN= # extra programs for temporary ramfs root
|
|
-RAMFS_COPY_DATA= # extra data files
|
|
+RAMFS_COPY_DATA="/lib/upgrade/sonicfi/*.sh" # extra data files
|
|
|
|
include /lib/upgrade
|
|
|
|
diff --git a/scripts/mkits_sonicfi_rap630w_211g.sh b/scripts/mkits_sonicfi_rap630w_211g.sh
|
|
new file mode 100755
|
|
index 0000000000..35f2d00767
|
|
--- /dev/null
|
|
+++ b/scripts/mkits_sonicfi_rap630w_211g.sh
|
|
@@ -0,0 +1,237 @@
|
|
+#!/bin/sh
|
|
+#
|
|
+# Licensed under the terms of the GNU GPL License version 2 or later.
|
|
+#
|
|
+# Author: Peter Tyser <ptyser@xes-inc.com>
|
|
+#
|
|
+# U-Boot firmware supports the booting of images in the Flattened Image
|
|
+# Tree (FIT) format. The FIT format uses a device tree structure to
|
|
+# describe a kernel image, device tree blob, ramdisk, etc. This script
|
|
+# creates an Image Tree Source (.its file) which can be passed to the
|
|
+# 'mkimage' utility to generate an Image Tree Blob (.itb file). The .itb
|
|
+# file can then be booted by U-Boot (or other bootloaders which support
|
|
+# FIT images). See doc/uImage.FIT/howto.txt in U-Boot source code for
|
|
+# additional information on FIT images.
|
|
+#
|
|
+
|
|
+usage() {
|
|
+ printf "Usage: %s -A arch -C comp -a addr -e entry" "$(basename "$0")"
|
|
+ printf " -v version -k kernel [-D name -n address -d dtb] -o its_file"
|
|
+
|
|
+ printf "\n\t-A ==> set architecture to 'arch'"
|
|
+ printf "\n\t-C ==> set compression type 'comp'"
|
|
+ printf "\n\t-c ==> set config name 'config'"
|
|
+ printf "\n\t-a ==> set load address to 'addr' (hex)"
|
|
+ printf "\n\t-e ==> set entry point to 'entry' (hex)"
|
|
+ printf "\n\t-f ==> set device tree compatible string"
|
|
+ printf "\n\t-i ==> include initrd Blob 'initrd'"
|
|
+ printf "\n\t-v ==> set kernel version to 'version'"
|
|
+ printf "\n\t-k ==> include kernel image 'kernel'"
|
|
+ printf "\n\t-D ==> human friendly Device Tree Blob 'name'"
|
|
+ printf "\n\t-n ==> fdt unit-address 'address'"
|
|
+ printf "\n\t-d ==> include Device Tree Blob 'dtb'"
|
|
+ printf "\n\t-r ==> include RootFS blob 'rootfs'"
|
|
+ printf "\n\t-H ==> specify hash algo instead of SHA1"
|
|
+ printf "\n\t-l ==> legacy mode character (@ etc otherwise -)"
|
|
+ printf "\n\t-o ==> create output file 'its_file'"
|
|
+ printf "\n\t-O ==> create config with dt overlay 'name:dtb'"
|
|
+ printf "\n\t-s ==> set FDT load address to 'addr' (hex)"
|
|
+ printf "\n\t\t(can be specified more than once)\n"
|
|
+ exit 1
|
|
+}
|
|
+
|
|
+REFERENCE_CHAR='-'
|
|
+FDTNUM=1
|
|
+ROOTFSNUM=1
|
|
+INITRDNUM=1
|
|
+HASH=sha1
|
|
+LOADABLES=
|
|
+DTOVERLAY=
|
|
+DTADDR=
|
|
+
|
|
+while getopts ":A:a:c:C:D:d:e:f:i:k:l:n:o:O:v:r:s:H:" OPTION
|
|
+do
|
|
+ case $OPTION in
|
|
+ A ) ARCH=$OPTARG;;
|
|
+ a ) LOAD_ADDR=$OPTARG;;
|
|
+ c ) CONFIG=$OPTARG;;
|
|
+ C ) COMPRESS=$OPTARG;;
|
|
+ D ) DEVICE=$OPTARG;;
|
|
+ d ) DTB=$OPTARG;;
|
|
+ e ) ENTRY_ADDR=$OPTARG;;
|
|
+ f ) COMPATIBLE=$OPTARG;;
|
|
+ i ) INITRD=$OPTARG;;
|
|
+ k ) KERNEL=$OPTARG;;
|
|
+ l ) REFERENCE_CHAR=$OPTARG;;
|
|
+ n ) FDTNUM=$OPTARG;;
|
|
+ o ) OUTPUT=$OPTARG;;
|
|
+ O ) DTOVERLAY="$DTOVERLAY ${OPTARG}";;
|
|
+ r ) ROOTFS=$OPTARG;;
|
|
+ s ) FDTADDR=$OPTARG;;
|
|
+ H ) HASH=$OPTARG;;
|
|
+ v ) VERSION=$OPTARG;;
|
|
+ * ) echo "Invalid option passed to '$0' (options:$*)"
|
|
+ usage;;
|
|
+ esac
|
|
+done
|
|
+
|
|
+# Make sure user entered all required parameters
|
|
+if [ -z "${ARCH}" ] || [ -z "${COMPRESS}" ] || [ -z "${LOAD_ADDR}" ] || \
|
|
+ [ -z "${ENTRY_ADDR}" ] || [ -z "${VERSION}" ] || [ -z "${KERNEL}" ] || \
|
|
+ [ -z "${OUTPUT}" ] || [ -z "${CONFIG}" ]; then
|
|
+ usage
|
|
+fi
|
|
+
|
|
+ARCH_UPPER=$(echo "$ARCH" | tr '[:lower:]' '[:upper:]')
|
|
+
|
|
+if [ -n "${COMPATIBLE}" ]; then
|
|
+ COMPATIBLE_PROP="compatible = \"${COMPATIBLE}\";"
|
|
+fi
|
|
+
|
|
+[ "$FDTADDR" ] && {
|
|
+ DTADDR="$FDTADDR"
|
|
+}
|
|
+
|
|
+# Conditionally create fdt information
|
|
+if [ -n "${DTB}" ]; then
|
|
+ FDT_NODE="
|
|
+ fdt${REFERENCE_CHAR}$FDTNUM {
|
|
+ description = \"${ARCH_UPPER} OpenWrt ${DEVICE} device tree blob\";
|
|
+ ${COMPATIBLE_PROP}
|
|
+ data = /incbin/(\"${DTB}\");
|
|
+ type = \"flat_dt\";
|
|
+ ${DTADDR:+load = <${DTADDR}>;}
|
|
+ arch = \"${ARCH}\";
|
|
+ compression = \"none\";
|
|
+ hash${REFERENCE_CHAR}1 {
|
|
+ algo = \"crc32\";
|
|
+ };
|
|
+ hash${REFERENCE_CHAR}2 {
|
|
+ algo = \"${HASH}\";
|
|
+ };
|
|
+ };
|
|
+"
|
|
+ FDT_PROP="fdt = \"fdt${REFERENCE_CHAR}$FDTNUM\";"
|
|
+fi
|
|
+
|
|
+if [ -n "${INITRD}" ]; then
|
|
+ INITRD_NODE="
|
|
+ initrd${REFERENCE_CHAR}$INITRDNUM {
|
|
+ description = \"${ARCH_UPPER} OpenWrt ${DEVICE} initrd\";
|
|
+ ${COMPATIBLE_PROP}
|
|
+ data = /incbin/(\"${INITRD}\");
|
|
+ type = \"ramdisk\";
|
|
+ arch = \"${ARCH}\";
|
|
+ os = \"linux\";
|
|
+ hash${REFERENCE_CHAR}1 {
|
|
+ algo = \"crc32\";
|
|
+ };
|
|
+ hash${REFERENCE_CHAR}2 {
|
|
+ algo = \"${HASH}\";
|
|
+ };
|
|
+ };
|
|
+"
|
|
+ INITRD_PROP="ramdisk=\"initrd${REFERENCE_CHAR}${INITRDNUM}\";"
|
|
+fi
|
|
+
|
|
+
|
|
+if [ -n "${ROOTFS}" ]; then
|
|
+ ROOTFS_SIZE=$(stat -c %s ${ROOTFS})
|
|
+ ROOTFS_SHA1=$(sha1sum ${ROOTFS} | awk '{print "<0x"substr($0,1,8) " 0x"substr($0,9,8) " 0x"substr($0,17,8) " 0x"substr($0,25,8) " 0x"substr($0,33,8) ">"}')
|
|
+ ROOTFS_CRC32=$(crc32sum ${ROOTFS})
|
|
+ ROOTFS_NODE="
|
|
+ rootfs {
|
|
+ size = <${ROOTFS_SIZE}>;
|
|
+ hash-1 {
|
|
+ value = <0x${ROOTFS_CRC32}>;
|
|
+ algo = \"crc32\";
|
|
+ };
|
|
+ hash-2 {
|
|
+ value = ${ROOTFS_SHA1};
|
|
+ algo = \"sha1\";
|
|
+ };
|
|
+ };
|
|
+"
|
|
+fi
|
|
+
|
|
+# add DT overlay blobs
|
|
+FDTOVERLAY_NODE=""
|
|
+OVCONFIGS=""
|
|
+[ "$DTOVERLAY" ] && for overlay in $DTOVERLAY ; do
|
|
+ overlay_blob=${overlay##*:}
|
|
+ ovname=${overlay%%:*}
|
|
+ ovnode="fdt-$ovname"
|
|
+ ovsize=$(wc -c "$overlay_blob" | awk '{print $1}')
|
|
+ echo "$ovname ($overlay_blob) : $ovsize" >&2
|
|
+ FDTOVERLAY_NODE="$FDTOVERLAY_NODE
|
|
+
|
|
+ $ovnode {
|
|
+ description = \"${ARCH_UPPER} OpenWrt ${DEVICE} device tree overlay $ovname\";
|
|
+ ${COMPATIBLE_PROP}
|
|
+ data = /incbin/(\"${overlay_blob}\");
|
|
+ type = \"flat_dt\";
|
|
+ arch = \"${ARCH}\";
|
|
+ compression = \"none\";
|
|
+ hash${REFERENCE_CHAR}1 {
|
|
+ algo = \"crc32\";
|
|
+ };
|
|
+ hash${REFERENCE_CHAR}2 {
|
|
+ algo = \"${HASH}\";
|
|
+ };
|
|
+ };
|
|
+"
|
|
+ OVCONFIGS="$OVCONFIGS
|
|
+
|
|
+ $ovname {
|
|
+ description = \"OpenWrt ${DEVICE} overlay $ovname\";
|
|
+ fdt = \"$ovnode\";
|
|
+ ${COMPATIBLE_PROP}
|
|
+ };
|
|
+ "
|
|
+done
|
|
+
|
|
+# Create a default, fully populated DTS file
|
|
+DATA="/dts-v1/;
|
|
+
|
|
+/ {
|
|
+ description = \"${ARCH_UPPER} OpenWrt FIT (Flattened Image Tree)\";
|
|
+ #address-cells = <1>;
|
|
+
|
|
+ images {
|
|
+ kernel${REFERENCE_CHAR}1 {
|
|
+ description = \"${ARCH_UPPER} OpenWrt Linux-${VERSION}\";
|
|
+ data = /incbin/(\"${KERNEL}\");
|
|
+ type = \"kernel\";
|
|
+ arch = \"${ARCH}\";
|
|
+ os = \"linux\";
|
|
+ compression = \"${COMPRESS}\";
|
|
+ load = <${LOAD_ADDR}>;
|
|
+ entry = <${ENTRY_ADDR}>;
|
|
+ hash${REFERENCE_CHAR}1 {
|
|
+ algo = \"crc32\";
|
|
+ };
|
|
+ hash${REFERENCE_CHAR}2 {
|
|
+ algo = \"$HASH\";
|
|
+ };
|
|
+ };
|
|
+${INITRD_NODE}
|
|
+${FDT_NODE}
|
|
+${FDTOVERLAY_NODE}
|
|
+ };
|
|
+${ROOTFS_NODE}
|
|
+ configurations {
|
|
+ default = \"${CONFIG}\";
|
|
+ ${CONFIG} {
|
|
+ description = \"OpenWrt ${DEVICE}\";
|
|
+ kernel = \"kernel${REFERENCE_CHAR}1\";
|
|
+ ${FDT_PROP}
|
|
+ ${LOADABLES:+loadables = ${LOADABLES};}
|
|
+ ${COMPATIBLE_PROP}
|
|
+ ${INITRD_PROP}
|
|
+ };
|
|
+ ${OVCONFIGS}
|
|
+ };
|
|
+};"
|
|
+
|
|
+# Write .its file to disk
|
|
+echo "$DATA" > "${OUTPUT}"
|
|
diff --git a/tools/Makefile b/tools/Makefile
|
|
index 40c3ec1ab0..6c7abaaf9c 100644
|
|
--- a/tools/Makefile
|
|
+++ b/tools/Makefile
|
|
@@ -68,6 +68,7 @@ tools-y += sstrip
|
|
tools-y += zip
|
|
tools-y += zlib
|
|
tools-y += zstd
|
|
+tools-y += crc32sum
|
|
tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS),y) += liblzo
|
|
tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_B43_TOOLS),y) += b43-tools
|
|
tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_BZIP2_TOOLS),y) += bzip2
|
|
diff --git a/tools/crc32sum/Makefile b/tools/crc32sum/Makefile
|
|
new file mode 100644
|
|
index 0000000000..bc13ecf92b
|
|
--- /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 0000000000..7428ba2f54
|
|
--- /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
|
|
diff --git a/tools/crc32sum/src/crc32sum.c b/tools/crc32sum/src/crc32sum.c
|
|
new file mode 100644
|
|
index 0000000000..381c7a95a7
|
|
--- /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();
|
|
+}
|
|
--
|
|
2.43.2
|
|
|