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