[PATCH v2] firmware-utils: support checksum for AVM fritzbox wasp SOCs

kestrel1974 at t-online.de kestrel1974 at t-online.de
Mon Jan 17 00:36:29 PST 2022


From: Daniel Kestrel <kestrel1974 at t-online.de>

This patch adds creating the checksum to be able to create an
image and boot the secondary ath79 based wireless assist (WASP)
SoC with a second instance of OpenWrt for some AVM Fritzbox
devices (3390, 3490, 5490, 7490).
The utility is called avm-wasp-checksum and was originally
created by Andreas Boehler.

Signed-off-by: Daniel Kestrel <kestrel1974 at t-online.de>
---
 CMakeLists.txt          |   1 +
 src/avm-wasp-checksum.c | 171 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 172 insertions(+)
 create mode 100644 src/avm-wasp-checksum.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f406520..5f886ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,6 +29,7 @@ ENDMACRO(FW_UTIL)
 FW_UTIL(add_header "" "" "")
 FW_UTIL(addpattern "" "" "")
 FW_UTIL(asustrx "" "" "")
+FW_UTIL(avm-wasp-checksum "" --std=gnu99 "")
 FW_UTIL(bcm4908asus "" "" "")
 FW_UTIL(bcm4908kernel "" "" "")
 FW_UTIL(buffalo-enc src/buffalo-lib.c "" "")
diff --git a/src/avm-wasp-checksum.c b/src/avm-wasp-checksum.c
new file mode 100644
index 0000000..8c112f3
--- /dev/null
+++ b/src/avm-wasp-checksum.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Andreas Boehler <dev at aboehler.at>
+ *
+ * This tool was based on:
+ *      firmware-crc.pl by Atheros Communications
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>     /* for getopt() */
+#include <byteswap.h>
+
+char *infile;
+char *outfile;
+char *progname;
+enum {
+	MODEL_3390,
+	MODEL_X490
+} model;
+
+#define CHUNK_SIZE 256
+
+uint32_t crc32_for_byte(uint32_t r)
+{
+	for (int j = 0; j < 8; ++j)
+		r = (r & 1 ? 0 : (uint32_t)0xEDB88320L) ^ r >> 1;
+	return r ^ (uint32_t)0xFF000000L;
+}
+
+void crc32(const void *data, size_t n_bytes, uint32_t *crc)
+{
+	static uint32_t table[0x100];
+
+	if (!*table)
+		for (size_t i = 0; i < 0x100; ++i)
+			table[i] = crc32_for_byte(i);
+	for (size_t i = 0; i < n_bytes; ++i)
+		*crc = table[(uint8_t)*crc ^ ((uint8_t *)data)[i]] ^ *crc >> 8;
+}
+
+static void usage(int status)
+{
+	fprintf(stderr, "Usage: %s [OPTIONS...]\n", progname);
+	fprintf(stderr,
+		"\n"
+		"Options:\n"
+		"  -i              input file name\n"
+		"  -o              output file name\n"
+		"  -m              model (3390, x490 for 3490/5490/7490)\n"
+		"  -h              show this screen\n"
+	);
+
+	exit(status);
+}
+
+int main(int argc, char *argv[])
+{
+	uint32_t crc = 0;
+	FILE *in_fp;
+	FILE *out_fp;
+	uint32_t buf[CHUNK_SIZE];
+	size_t read;
+
+	progname = argv[0];
+
+	while (1) {
+		int c;
+
+		c = getopt(argc, argv, "i:o:m:h");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'i':
+			infile = optarg;
+			break;
+		case 'o':
+			outfile = optarg;
+			break;
+		case 'm':
+			if (strcmp(optarg, "3390") == 0)
+				model = MODEL_3390;
+			else if (strcmp(optarg, "x490") == 0)
+				model = MODEL_X490;
+			else
+				usage(EXIT_FAILURE);
+			break;
+		case 'h':
+			usage(EXIT_SUCCESS);
+		default:
+			usage(EXIT_FAILURE);
+			break;
+		}
+	}
+
+	if (!infile || !outfile)
+		usage(EXIT_FAILURE);
+
+	in_fp = fopen(infile, "r");
+	if (!in_fp) {
+		fprintf(stderr, "Error opening input file: %s\n", infile);
+		return EXIT_FAILURE;
+	}
+	out_fp = fopen(outfile, "w");
+	if (!out_fp) {
+		fprintf(stderr, "Error opening output file: %s\n", outfile);
+		fclose(in_fp);
+		return EXIT_FAILURE;
+	}
+
+	while (!feof(in_fp)) {
+		switch (model) {
+		case MODEL_3390:
+			read = fread(buf, sizeof(uint32_t), CHUNK_SIZE, in_fp);
+			if (ferror(in_fp)) {
+				fprintf(stderr, "Error reading input file: %s\n", infile);
+				fclose(in_fp);
+				fclose(out_fp);
+				return EXIT_FAILURE;
+			}
+			for (int i = 0; i < read; i++)
+				crc = crc ^ buf[i];
+			fwrite(buf, sizeof(uint32_t), read, out_fp);
+			if (ferror(out_fp)) {
+				fprintf(stderr, "Error writing output file: %s\n", outfile);
+				fclose(in_fp);
+				fclose(out_fp);
+				return EXIT_FAILURE;
+			}
+			break;
+		case MODEL_X490:
+			read = fread(buf, 1, sizeof(uint32_t) * CHUNK_SIZE, in_fp);
+			if (ferror(in_fp)) {
+				fprintf(stderr, "Error reading input file: %s\n", infile);
+				fclose(in_fp);
+				fclose(out_fp);
+				return EXIT_FAILURE;
+			}
+			crc32(buf, read, &crc);
+			fwrite(buf, 1, read, out_fp);
+			if (ferror(out_fp)) {
+				fprintf(stderr, "Error writing output file: %s\n", outfile);
+				fclose(in_fp);
+				fclose(out_fp);
+				return EXIT_FAILURE;
+			}
+			break;
+		}
+	}
+	if (model == MODEL_X490)
+		crc = __bswap_32(crc);
+	fwrite(&crc, sizeof(uint32_t), 1, out_fp);
+	if (ferror(out_fp)) {
+		fprintf(stderr, "Error writing checksum to output file: %s\n", outfile);
+		fclose(in_fp);
+		fclose(out_fp);
+		return EXIT_FAILURE;
+	}
+	fclose(in_fp);
+	fclose(out_fp);
+	printf("Done.\n");
+	return EXIT_SUCCESS;
+}
-- 
2.17.1




More information about the openwrt-devel mailing list