Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ihex: Add support for long records to ihex2fw.c

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>

authored by

David Woodhouse and committed by
David Woodhouse
59890f74 8bd6b222

+47 -19
+7
firmware/Makefile
··· 35 35 quiet_cmd_ihex2fw = IHEX2FW $@ 36 36 cmd_ihex2fw = $(objtree)/$(obj)/ihex2fw $< $@ 37 37 38 + quiet_cmd_h16tofw = H16TOFW $@ 39 + cmd_h16tofw = $(objtree)/$(obj)/ihex2fw -w $< $@ 40 + 38 41 quiet_cmd_fwbin = MK_FW $@ 39 42 cmd_fwbin = FWNAME="$(patsubst firmware/%.gen.S,%,$@)"; \ 40 43 FWSTR="$(subst /,_,$(subst .,_,$(subst -,_,$(patsubst \ ··· 101 98 # more compact binary representation of ihex records (<linux/ihex.h>) 102 99 $(obj)/%.fw: $(obj)/%.HEX $(obj)/ihex2fw | $(objtree)/$(obj)/$$(dir %) 103 100 $(call cmd,ihex2fw) 101 + 102 + # .H16 is our own modified form of Intel HEX, with 16-bit length for records. 103 + $(obj)/%.fw: $(obj)/%.H16 $(obj)/ihex2fw | $(objtree)/$(obj)/$$(dir %) 104 + $(call cmd,h16tofw) 104 105 105 106 $(firmware-dirs): 106 107 $(call cmd,mkdir)
+40 -19
firmware/ihex2fw.c
··· 20 20 #include <string.h> 21 21 #include <unistd.h> 22 22 #include <stdlib.h> 23 + #define _GNU_SOURCE 24 + #include <getopt.h> 25 + 23 26 24 27 struct ihex_binrec { 25 28 struct ihex_binrec *next; /* not part of the real data structure */ ··· 54 51 static int output_records(int outfd); 55 52 56 53 static int sort_records = 0; 54 + static int wide_records = 0; 55 + 56 + int usage(void) 57 + { 58 + fprintf(stderr, "ihex2fw: Convert ihex files into binary " 59 + "representation for use by Linux kernel\n"); 60 + fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n"); 61 + fprintf(stderr, " -w: wide records (16-bit length)\n"); 62 + fprintf(stderr, " -s: sort records by address\n"); 63 + return 1; 64 + } 57 65 58 66 int main(int argc, char **argv) 59 67 { 60 68 int infd, outfd; 61 69 struct stat st; 62 70 uint8_t *data; 71 + int opt; 63 72 64 - if (argc == 4 && !strcmp(argv[1], "-s")) { 65 - sort_records = 1; 66 - argc--; 67 - argv++; 73 + while ((opt = getopt(argc, argv, "ws")) != -1) { 74 + switch (opt) { 75 + case 'w': 76 + wide_records = 1; 77 + break; 78 + case 's': 79 + sort_records = 1; 80 + break; 81 + default: 82 + return usage(); 83 + } 68 84 } 69 - if (argc != 3) { 70 - usage: 71 - fprintf(stderr, "ihex2fw: Convert ihex files into binary " 72 - "representation for use by Linux kernel\n"); 73 - fprintf(stderr, "usage: ihex2fw [-s] <src.HEX> <dst.fw>\n"); 74 - fprintf(stderr, " -s: sort records by address\n"); 75 - return 1; 76 - } 77 - if (!strcmp(argv[1], "-")) 85 + 86 + if (optind + 2 != argc) 87 + return usage(); 88 + 89 + if (!strcmp(argv[optind], "-")) 78 90 infd = 0; 79 91 else 80 - infd = open(argv[1], O_RDONLY); 92 + infd = open(argv[optind], O_RDONLY); 81 93 if (infd == -1) { 82 94 fprintf(stderr, "Failed to open source file: %s", 83 95 strerror(errno)); 84 - goto usage; 96 + return usage(); 85 97 } 86 98 if (fstat(infd, &st)) { 87 99 perror("stat"); ··· 108 90 return 1; 109 91 } 110 92 111 - if (!strcmp(argv[2], "-")) 93 + if (!strcmp(argv[optind+1], "-")) 112 94 outfd = 1; 113 95 else 114 - outfd = open(argv[2], O_TRUNC|O_CREAT|O_WRONLY, 0644); 96 + outfd = open(argv[optind+1], O_TRUNC|O_CREAT|O_WRONLY, 0644); 115 97 if (outfd == -1) { 116 98 fprintf(stderr, "Failed to open destination file: %s", 117 99 strerror(errno)); 118 - goto usage; 100 + return usage(); 119 101 } 120 102 if (process_ihex(data, st.st_size)) 121 103 return 1; ··· 148 130 } 149 131 150 132 len = hex(data + i, &crc); i += 2; 151 - 133 + if (wide_records) { 134 + len <<= 8; 135 + len += hex(data + i, &crc); i += 2; 136 + } 152 137 record = malloc((sizeof (*record) + len + 3) & ~3); 153 138 if (!record) { 154 139 fprintf(stderr, "out of memory for records\n");