diff --git a/package/utils/fritz-tools/src/fritz_cal_extract.c b/package/utils/fritz-tools/src/fritz_cal_extract.c index 9899cd53c33..c4547bc7e05 100644 --- a/package/utils/fritz-tools/src/fritz_cal_extract.c +++ b/package/utils/fritz-tools/src/fritz_cal_extract.c @@ -8,6 +8,9 @@ * that is Not copyrighted -- provided to the public domain * Version 1.4 11 December 2005 Mark Adler * + * Modifications to also handle calibration data in reversed byte order + * (c) 2024 by . + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -28,31 +31,54 @@ #include #include #include +#include #include #include #include #include "zlib.h" #define CHUNK 1024 +#define DEFAULT_BUFFERSIZE (129 * 1024) -static inline size_t special_min(size_t a, size_t b) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +/* Reverse byte order in data buffer. + * 'top' is position of last valid data byte = (datasize - 1) + */ +static void buffer_reverse(unsigned char *data, unsigned int top) { - return a == 0 ? b : (a < b ? a : b); + register unsigned char swapbyte; + const unsigned int center = top / 2; + + for (unsigned int bottom = 0; bottom < center; ++bottom, --top) { + swapbyte = data[bottom]; + data[bottom] = data[top]; + data[top] = swapbyte; + } } -/* Decompress from file source to file dest until stream ends or EOF. - inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be - allocated for processing, Z_DATA_ERROR if the deflate data is - invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and - the version of the library linked do not match, or Z_ERRNO if there - is an error reading or writing the files. */ -static int inf(FILE *source, FILE *dest, size_t limit, size_t skip) +/* Decompress from file source to data buffer until stream ends + * or *limit bytes have been written to buffer. + * + * On call, 'limit' must reference a variable containing the intended + * number of bytes to retrieve (must be <= allocated buffer size). + * + * Return values (success): + * Z_END_STREAM if complete data was retrieved (*limit == size of complete data), + * or Z_OK if data was retrieved up to limit (*limit == original value). + * + * Return values (failure): + * Z_MEM_ERROR if memory could not be allocated for processing, + * Z_DATA_ERROR if the deflate data is invalid or incomplete, + * Z_VERSION_ERROR if the version of zlib.h and the version of the + * library linked do not match, or + * Z_ERRNO if there is an error reading or writing the files. + */ +static int inflate_to_buffer(FILE *source, unsigned char *buf, size_t *limit) { int ret; - size_t have; z_stream strm; unsigned char in[CHUNK]; - unsigned char out[CHUNK]; /* allocate inflate state */ strm.zalloc = Z_NULL; @@ -64,6 +90,10 @@ static int inf(FILE *source, FILE *dest, size_t limit, size_t skip) if (ret != Z_OK) return ret; + /* set data buffer as stream output */ + strm.avail_out = *limit; + strm.next_out = buf; + /* decompress until deflate stream ends or end of file */ do { strm.avail_in = fread(in, 1, CHUNK, source); @@ -75,35 +105,28 @@ static int inf(FILE *source, FILE *dest, size_t limit, size_t skip) break; strm.next_in = in; - /* run inflate() on input until output buffer not full */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { + /* run inflate(), fill data buffer with all available output */ + ret = inflate(&strm, Z_FINISH); + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + + switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; /* and fall through */ case Z_DATA_ERROR: case Z_MEM_ERROR: (void)inflateEnd(&strm); return ret; - } - have = special_min(limit, CHUNK - strm.avail_out) - skip; - if (fwrite(&out[skip], have, 1, dest) != 1 || ferror(dest)) { - (void)inflateEnd(&strm); - return Z_ERRNO; - } - skip = 0; - limit -= have; - } while (strm.avail_out == 0 && limit > 0); + } + /* done when inflate() says it's done or limit reached */ + } while (ret != Z_STREAM_END && strm.avail_out > 0); - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END && limit > 0); + /* set limit to end of retrieved data */ + assert(strm.total_out <= *limit); + *limit = strm.total_out; /* clean up and return */ (void)inflateEnd(&strm); - return (limit == 0 ? Z_OK : (ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR)); + return (ret == Z_STREAM_END ? Z_STREAM_END : (strm.avail_out == 0 ? Z_OK : Z_DATA_ERROR)); } /* report a zlib or i/o error */ @@ -140,7 +163,8 @@ static unsigned int get_num(char *str) static void usage(void) { - fprintf(stderr, "Usage: fritz_cal_extract [-s seek offset] [-i skip] [-o output file] [-l limit] [infile] -e entry_id\n" + fprintf(stderr, "Usage: fritz_cal_extract -e entry_id [-s seek offset] [-l limit]\n" + "\t[-r reverse extracted data] [-i skip n bytes] [-o output file] [infile]\n" "Finds and extracts zlib compressed calibration data in the EVA loader\n"); exit(EXIT_FAILURE); } @@ -154,15 +178,18 @@ struct cal_entry { int main(int argc, char **argv) { struct cal_entry cal = { .len = 0 }; + unsigned char *buf = NULL; FILE *in = stdin; FILE *out = stdout; + size_t datasize = DEFAULT_BUFFERSIZE; size_t limit = 0, skip = 0; int initial_offset = 0; int entry = -1; + bool reversed = false, limit_was_set = true; int ret; int opt; - while ((opt = getopt(argc, argv, "s:e:o:l:i:")) != -1) { + while ((opt = getopt(argc, argv, "s:e:o:l:i:r")) != -1) { switch (opt) { case 's': initial_offset = (int)get_num(optarg); @@ -199,6 +226,9 @@ int main(int argc, char **argv) goto out_bad; } break; + case 'r': + reversed = true; + break; default: /* '?' */ usage(); } @@ -243,11 +273,50 @@ int main(int argc, char **argv) goto out_bad; } - ret = inf(in, out, limit, skip); - if (ret == Z_OK) - goto out; + /* Set boundaries. Only keep default datasize if we need complete data + * for reversal and didn't set a higher limit. */ + if (!limit) { + limit_was_set = false; + limit = datasize - skip; + } + datasize = (reversed && datasize >= limit + skip) ? datasize : (limit + skip); - zerr(ret); + /* Create data buffer. */ + buf = malloc(datasize); + assert(buf != NULL); + + ret = inflate_to_buffer(in, buf, &datasize); + + if ((reversed || !limit_was_set) && ret != Z_STREAM_END) { /* didn't read to stream end */ + fprintf(stderr, "Failed: Data exceeds buffer size of %u. Refusing to reverse" + " or store incomplete data." + " Use a higher limit [-l] to increase buffer size.\n", + (unsigned int) datasize); + goto out_bad; + } + + ret = (ret == Z_STREAM_END) ? Z_OK : ret; /* normalize return value */ + if (ret != Z_OK) { + zerr(ret); + goto out_bad; + } + + if (reversed) + buffer_reverse(buf, datasize - 1); + + if (datasize <= skip) { + fprintf(stderr, "Failed to skip %u bytes, total data size is %u!\n", + (unsigned int)skip, (unsigned int)datasize); + goto out_bad; + } + + limit = MIN(limit, datasize - skip); + if (fwrite(&buf[skip], limit, 1, out) != 1 || ferror(out)) { + fprintf(stderr, "Failed to write data buffer to output file"); + goto out_bad; + } + + goto out; out_bad: ret = EXIT_FAILURE; @@ -257,5 +326,6 @@ out: fclose(in); if (out) fclose(out); + free(buf); return ret; } diff --git a/target/linux/lantiq/xrx200/base-files/etc/hotplug.d/firmware/12-ath9k-eeprom b/target/linux/lantiq/xrx200/base-files/etc/hotplug.d/firmware/12-ath9k-eeprom index eefc39b30b4..2e5bf10bf92 100644 --- a/target/linux/lantiq/xrx200/base-files/etc/hotplug.d/firmware/12-ath9k-eeprom +++ b/target/linux/lantiq/xrx200/base-files/etc/hotplug.d/firmware/12-ath9k-eeprom @@ -22,11 +22,14 @@ case "$FIRMWARE" in avm,fritz7360sl) caldata_extract "urlader" 0x985 0x1000 ;; - avm,fritz7412|\ - avm,fritz7430) + avm,fritz7412) /usr/bin/fritz_cal_extract -i 1 -s 0x1e000 -e 0x207 -l 5120 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader") || \ /usr/bin/fritz_cal_extract -i 1 -s 0x1e800 -e 0x207 -l 5120 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader") ;; + avm,fritz7430) + /usr/bin/fritz_cal_extract -r -i 4 -s 0x1e000 -e 0x207 -l 5120 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader") || \ + /usr/bin/fritz_cal_extract -r -i 4 -s 0x1e800 -e 0x207 -l 5120 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader") + ;; bt,homehub-v5a) caldata_extract_ubi "caldata" 0x1000 0x1000 ath9k_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary_ubi caldata 0x110c) 2) 0x10c