From: Daniel Kestrel Date: Mon, 17 Jan 2022 08:36:29 +0000 (+0100) Subject: firmware-utils: support checksum for AVM fritzbox wasp SOCs X-Git-Url: http://git.openwrt.org/openwrt/docs.git?a=commitdiff_plain;h=497726b45263ba6f652724213d14084e89e4f970;p=project%2Ffirmware-utils.git firmware-utils: support checksum for AVM fritzbox wasp SOCs 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 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 4de70d1..e6592bc 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 + * + * 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 +#include +#include +#include +#include /* for getopt() */ +#include + +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; +}