Rebased from upstream / out of band repository.
[librecmc/librecmc.git] / tools / firmware-utils / src / xorimage.c
index b5ab83fa7a65159810d75126008b12482bf1cbad..56e2c3797df4eb1aa3ddafbd36cab6ea918b724c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * xorimage.c - partially based on OpenWrt's addpattern.c
+ * xorimage.c - partially based on libreCMC's addpattern.c
  *
  * 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
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 #include <stdint.h>
-#include <time.h>
 #include <unistd.h>
 #include <sys/stat.h>
 
 static char default_pattern[] = "12345678";
+static int is_hex_pattern;
 
 
 int xor_data(uint8_t *data, size_t len, const uint8_t *pattern, int p_len, int p_off)
@@ -44,7 +45,7 @@ void usage(void) __attribute__ (( __noreturn__ ));
 
 void usage(void)
 {
-       fprintf(stderr, "Usage: xorimage [-i infile] [-o outfile] [-p <pattern>]\n");
+       fprintf(stderr, "Usage: xorimage [-i infile] [-o outfile] [-p <pattern>] [-x]\n");
        exit(EXIT_FAILURE);
 }
 
@@ -57,12 +58,14 @@ int main(int argc, char **argv)
        char *ifn = NULL;
        char *ofn = NULL;
        const char *pattern = default_pattern;
+       char hex_pattern[128];
+       unsigned int hex_buf;
        int c;
        int v0, v1, v2;
        size_t n;
        int p_len, p_off = 0;
 
-       while ((c = getopt(argc, argv, "i:o:p:h")) != -1) {
+       while ((c = getopt(argc, argv, "i:o:p:xh")) != -1) {
                switch (c) {
                        case 'i':
                                ifn = optarg;
@@ -73,6 +76,9 @@ int main(int argc, char **argv)
                        case 'p':
                                pattern = optarg;
                                break;
+                       case 'x':
+                               is_hex_pattern = true;
+                               break;
                        case 'h':
                        default:
                                usage();
@@ -101,6 +107,27 @@ int main(int argc, char **argv)
                usage();
        }
 
+       if (is_hex_pattern) {
+               int i;
+
+               if ((p_len / 2) > sizeof(hex_pattern)) {
+                       fprintf(stderr, "provided hex pattern is too long\n");
+                       usage();
+               }
+
+               if (p_len % 2 != 0) {
+                       fprintf(stderr, "the number of characters (hex) is incorrect\n");
+                       usage();
+               }
+
+               for (i = 0; i < (p_len / 2); i++) {
+                       if (sscanf(pattern + (i * 2), "%2x", &hex_buf) < 0) {
+                               fprintf(stderr, "invalid hex digit around %d\n", i * 2);
+                               usage();
+                       }
+                       hex_pattern[i] = (char)hex_buf;
+               }
+       }
 
        while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
                if (n < sizeof(buf)) {
@@ -111,7 +138,12 @@ int main(int argc, char **argv)
                        }
                }
 
-               p_off = xor_data(buf, n, pattern, p_len, p_off);
+               if (is_hex_pattern) {
+                       p_off = xor_data(buf, n, hex_pattern, (p_len / 2),
+                                        p_off);
+               } else {
+                       p_off = xor_data(buf, n, pattern, p_len, p_off);
+               }
 
                if (!fwrite(buf, n, 1, out)) {
                FWRITE_ERROR: