diff mbox series

firmware-utils: support checksum for AVM fritzbox wasp SOCs

Message ID 20220113102003.2369-1-kestrel1974@t-online.de
State Superseded
Delegated to: Rafał Miłecki
Headers show
Series firmware-utils: support checksum for AVM fritzbox wasp SOCs | expand

Commit Message

kestrel1974@t-online.de Jan. 13, 2022, 10:20 a.m. UTC
From: Daniel Kestrel <kestrel1974@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@t-online.de>
---
 CMakeLists.txt          |   1 +
 src/avm-wasp-checksum.c | 141 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 142 insertions(+)
 create mode 100644 src/avm-wasp-checksum.c

Comments

Hauke Mehrtens Jan. 16, 2022, 5:52 p.m. UTC | #1
Hi,

This code looks good in general just some small comments.

Hauke

On 1/13/22 11:20, kestrel1974@t-online.de wrote:
> From: Daniel Kestrel <kestrel1974@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@t-online.de>
> ---
>   CMakeLists.txt          |   1 +
>   src/avm-wasp-checksum.c | 141 ++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 142 insertions(+)
>   create mode 100644 src/avm-wasp-checksum.c
> 
.....
> +
> +	while (!feof(in_fp)) {
> +		switch (model) {
> +		case MODEL_3390:
> +			read = fread(buf, sizeof(uint32_t), CHUNK_SIZE, in_fp);

fread() and fwrite() are returning a size_t and not a ssize_t.
You should probably also check for errors with ferror().

You can probably also change it like this:

		read = fread(buf, sizeof(uint32_t), CHUNK_SIZE, in_fp);
		// Error handling
		switch (model) {
		case MODEL_3390:
			for (int i = 0; i < read; i++)
				crc = crc ^ buf[i];
			break;
		case MODEL_X490:
			crc32(buf, read * sizeof(uint32_t), &crc);
			break;
		}
		fwrite(buf, sizeof(uint32_t), read, out_fp);
		// Error handling


> +			for (int i = 0; i < read; i++)
> +				crc = crc ^ buf[i];
> +			fwrite(buf, sizeof(uint32_t), read, out_fp);
> +			break;
> +		case MODEL_X490:
> +			read = fread(buf, 1, sizeof(uint32_t) * CHUNK_SIZE, in_fp);
> +			crc32(buf, read, &crc);
> +			fwrite(buf, 1, read, out_fp);
> +			break;
> +		}
> +	}
> +	if (model == MODEL_X490)
> +		crc = __bswap_32(crc);
> +	fwrite(&crc, sizeof(uint32_t), 1, out_fp);
> +	fclose(in_fp);
> +	fclose(out_fp);
> +	printf("Done.\n");
> +	return EXIT_SUCCESS;
> +}
diff mbox series

Patch

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..cbf6a19
--- /dev/null
+++ b/src/avm-wasp-checksum.c
@@ -0,0 +1,141 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Andreas Boehler <dev@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];
+	ssize_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);
+			for (int i = 0; i < read; i++)
+				crc = crc ^ buf[i];
+			fwrite(buf, sizeof(uint32_t), read, out_fp);
+			break;
+		case MODEL_X490:
+			read = fread(buf, 1, sizeof(uint32_t) * CHUNK_SIZE, in_fp);
+			crc32(buf, read, &crc);
+			fwrite(buf, 1, read, out_fp);
+			break;
+		}
+	}
+	if (model == MODEL_X490)
+		crc = __bswap_32(crc);
+	fwrite(&crc, sizeof(uint32_t), 1, out_fp);
+	fclose(in_fp);
+	fclose(out_fp);
+	printf("Done.\n");
+	return EXIT_SUCCESS;
+}