diff options
author | INAGAKI Hiroshi <musashino.open@gmail.com> | 2019-03-16 13:19:24 +0900 |
---|---|---|
committer | Christian Lamparter <chunkeey@gmail.com> | 2019-04-06 19:14:06 +0200 |
commit | fac27643f057d681ec276828dc4d1ba7159b5680 (patch) | |
tree | 209df79361a403d5e7b3e48516d168317cf76680 /tools/firmware-utils | |
parent | d80a1c6e2cca46d52870bd6674f3a4466bd7013d (diff) | |
download | upstream-fac27643f057d681ec276828dc4d1ba7159b5680.tar.gz upstream-fac27643f057d681ec276828dc4d1ba7159b5680.tar.bz2 upstream-fac27643f057d681ec276828dc4d1ba7159b5680.zip |
firmware-utils: add nec-enc
nec-enc provides firmware encoding/decoding with model specific key
for NEC devices.
known devices:
- Aterm WF1200CR
- Aterm WG1200CR
- Aterm WG2600HS
usage:
nec-enc -i infile -o outfile -k key
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
[checkpatch fixes, marked usage as noreturn, added static function,
moved buf* from stack to the global data segment]
Diffstat (limited to 'tools/firmware-utils')
-rw-r--r-- | tools/firmware-utils/Makefile | 1 | ||||
-rw-r--r-- | tools/firmware-utils/src/nec-enc.c | 129 |
2 files changed, 130 insertions, 0 deletions
diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index 864a3df15d..7745b7bab2 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -85,6 +85,7 @@ define Host/Compile $(call cc,mkdlinkfw mkdlinkfw-lib, -lz -Wall --std=c99) $(call cc,dns313-header, -Wall) $(call cc,mksercommfw, -Wall) + $(call cc,nec-enc, -Wall) endef define Host/Install diff --git a/tools/firmware-utils/src/nec-enc.c b/tools/firmware-utils/src/nec-enc.c new file mode 100644 index 0000000000..3c4e38721e --- /dev/null +++ b/tools/firmware-utils/src/nec-enc.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * nec-enc.c - encode/decode nec firmware with key + * + * based on xorimage.c in OpenWrt + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <unistd.h> + +#define KEY_LEN 16 +#define PATTERN_LEN 251 + +static int +xor_pattern(uint8_t *data, size_t len, const char *key, int k_len, int k_off) +{ + int offset = k_off; + + while (len--) { + *data ^= key[offset]; + data++; + offset = (offset + 1) % k_len; + } + + return offset; +} + +static void xor_data(uint8_t *data, size_t len, const uint8_t *pattern) +{ + for (int i = 0; i < len; i++) { + *data ^= pattern[i]; + data++; + } +} + +static void __attribute__((noreturn)) usage(void) +{ + fprintf(stderr, "Usage: nec-enc -i infile -o outfile -k <key>\n"); + exit(EXIT_FAILURE); +} + +static unsigned char buf_pattern[4096], buf[4096]; + +int main(int argc, char **argv) +{ + int k_off = 0, ptn = 0, c, ret = EXIT_SUCCESS; + char *ifn = NULL, *ofn = NULL, *key = NULL; + size_t n, k_len; + FILE *out, *in; + + while ((c = getopt(argc, argv, "i:o:k:h")) != -1) { + switch (c) { + case 'i': + ifn = optarg; + break; + case 'o': + ofn = optarg; + break; + case 'k': + key = optarg; + break; + case 'h': + default: + usage(); + } + } + + if (optind != argc || optind == 1) { + fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]); + usage(); + } + + in = fopen(ifn, "r"); + if (!in) { + perror("can not open input file"); + usage(); + } + + out = fopen(ofn, "w"); + if (!out) { + perror("can not open output file"); + usage(); + } + + if (!key) { + fprintf(stderr, "key is not specified\n"); + usage(); + } + + k_len = strnlen(key, KEY_LEN + 1); + if (k_len == 0 || k_len > KEY_LEN) { + fprintf(stderr, "key length is not in range (0,%d)\n", KEY_LEN); + usage(); + } + + while ((n = fread(buf, 1, sizeof(buf), in)) > 0) { + for (int i = 0; i < n; i++) { + buf_pattern[i] = ptn + 1; + ptn++; + + if (ptn > 250) + ptn = 0; + } + + k_off = xor_pattern(buf_pattern, n, key, k_len, k_off); + xor_data(buf, n, buf_pattern); + + if (fwrite(buf, 1, n, out) != n) { + perror("failed to write"); + ret = EXIT_FAILURE; + goto out; + } + } + + if (ferror(in)) { + perror("failed to read"); + ret = EXIT_FAILURE; + goto out; + } + +out: + fclose(in); + fclose(out); + return ret; +} |