ihex: Add support for long records to ihex2fw.c
David Woodhouse [Thu, 26 Jun 2008 12:55:30 +0000 (13:55 +0100)]
Some drivers could do with using records like Intel HEX, but with each
record being larger than 256 bytes. This has been possible in the binary
representation (struct ihex_binrec) in the kernel since the beginning --
at least of the the current version of history. But we haven't been able
to represent that in the .HEX files which get converted to .fw files.

This adds a '-w' option to ihex2fw to make it interpret the first _two_
bytes of each line as the record length, instead of only one byte. And
adds makefile rules for %.H16->%.fw which use that.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

firmware/Makefile
firmware/ihex2fw.c

index 9e780a3..40881a9 100644 (file)
@@ -35,6 +35,9 @@ quiet_cmd_ihex  = IHEX    $@
 quiet_cmd_ihex2fw  = IHEX2FW $@
       cmd_ihex2fw  = $(objtree)/$(obj)/ihex2fw $< $@
 
+quiet_cmd_h16tofw  = H16TOFW $@
+      cmd_h16tofw  = $(objtree)/$(obj)/ihex2fw -w $< $@
+
 quiet_cmd_fwbin = MK_FW   $@
       cmd_fwbin = FWNAME="$(patsubst firmware/%.gen.S,%,$@)";               \
                  FWSTR="$(subst /,_,$(subst .,_,$(subst -,_,$(patsubst      \
@@ -99,6 +102,10 @@ $(obj)/%: $(obj)/%.ihex | $(objtree)/$(obj)/$$(dir %)
 $(obj)/%.fw: $(obj)/%.HEX $(obj)/ihex2fw | $(objtree)/$(obj)/$$(dir %)
        $(call cmd,ihex2fw)
 
+# .H16 is our own modified form of Intel HEX, with 16-bit length for records.
+$(obj)/%.fw: $(obj)/%.H16 $(obj)/ihex2fw | $(objtree)/$(obj)/$$(dir %)
+       $(call cmd,h16tofw)
+
 $(firmware-dirs):
        $(call cmd,mkdir)
 
index 9e77cd2..660b191 100644 (file)
@@ -20,6 +20,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+
 
 struct ihex_binrec {
        struct ihex_binrec *next; /* not part of the real data structure */
@@ -51,34 +54,49 @@ static void file_record(struct ihex_binrec *record);
 static int output_records(int outfd);
 
 static int sort_records = 0;
+static int wide_records = 0;
+
+int usage(void)
+{
+       fprintf(stderr, "ihex2fw: Convert ihex files into binary "
+               "representation for use by Linux kernel\n");
+       fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n");
+       fprintf(stderr, "       -w: wide records (16-bit length)\n");
+       fprintf(stderr, "       -s: sort records by address\n");
+       return 1;
+}
 
 int main(int argc, char **argv)
 {
        int infd, outfd;
        struct stat st;
        uint8_t *data;
+       int opt;
 
-       if (argc == 4 && !strcmp(argv[1], "-s")) {
-               sort_records = 1;
-               argc--;
-               argv++;
-       }
-       if (argc != 3) {
-       usage:
-               fprintf(stderr, "ihex2fw: Convert ihex files into binary "
-                               "representation for use by Linux kernel\n");
-               fprintf(stderr, "usage: ihex2fw [-s] <src.HEX> <dst.fw>\n");
-               fprintf(stderr, "       -s: sort records by address\n");
-               return 1;
+       while ((opt = getopt(argc, argv, "ws")) != -1) {
+               switch (opt) {
+               case 'w':
+                       wide_records = 1;
+                       break;
+               case 's':
+                       sort_records = 1;
+                       break;
+               default:
+                       return usage();
+               }
        }
-       if (!strcmp(argv[1], "-"))
+
+       if (optind + 2 != argc)
+               return usage();
+
+       if (!strcmp(argv[optind], "-"))
            infd = 0;
        else
-               infd = open(argv[1], O_RDONLY);
+               infd = open(argv[optind], O_RDONLY);
        if (infd == -1) {
                fprintf(stderr, "Failed to open source file: %s",
                        strerror(errno));
-               goto usage;
+               return usage();
        }
        if (fstat(infd, &st)) {
                perror("stat");
@@ -90,14 +108,14 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       if (!strcmp(argv[2], "-"))
+       if (!strcmp(argv[optind+1], "-"))
            outfd = 1;
        else
-               outfd = open(argv[2], O_TRUNC|O_CREAT|O_WRONLY, 0644);
+               outfd = open(argv[optind+1], O_TRUNC|O_CREAT|O_WRONLY, 0644);
        if (outfd == -1) {
                fprintf(stderr, "Failed to open destination file: %s",
                        strerror(errno));
-               goto usage;
+               return usage();
        }
        if (process_ihex(data, st.st_size))
                return 1;
@@ -130,7 +148,10 @@ next_record:
        }
 
        len = hex(data + i, &crc); i += 2;
-
+       if (wide_records) {
+               len <<= 8;
+               len += hex(data + i, &crc); i += 2;
+       }
        record = malloc((sizeof (*record) + len + 3) & ~3);
        if (!record) {
                fprintf(stderr, "out of memory for records\n");