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      \
 $(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)
 
 
 #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 */
 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");
                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;
        }
 
        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");