mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-29 09:32:34 +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
 | |
| 
 | 
