extend "ok" temp range to 40C, since battery charger on bench can drive temp above
[fw/altos] / ao-tools / ao-makebin / ao-makebin.c
1 /*
2  * Copyright © 2016 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <getopt.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include "ao-hex.h"
24 #include "ao-elf.h"
25 #include "ao-dfu.h"
26
27 static const struct option options[] = {
28         { .name = "verbose", .has_arg = 0, .val = 'v' },
29         { .name = "output", .has_arg = 1, .val = 'o' },
30         { .name = "base", .has_arg = 1, .val = 'b' },
31         { .name = "align", .has_arg = 1, .val = 'a' },
32         { .name = "dfu", .has_arg = 0, .val = 'd' },
33         { 0, 0, 0, 0},
34 };
35
36 static void usage(char *program)
37 {
38         fprintf(stderr, "usage: %s [--verbose=<level>] [--output=<output.bin>] [--base=<base-address>] [--align=<align>] [--dfu] <input.elf> ...\n", program);
39         exit(1);
40 }
41
42 static int
43 ends_with(char *whole, char *suffix)
44 {
45         int whole_len = strlen(whole);
46         int suffix_len = strlen(suffix);
47
48         if (suffix_len > whole_len)
49                 return 0;
50         return strcmp(whole + whole_len - suffix_len, suffix) == 0;
51 }
52
53 static struct ao_dfu_info dfu_info = {
54         .bcdDevice = 0x0000,
55         .idProduct = 0xdf11,
56         .idVendor = 0x0483,
57 };
58
59 int
60 main (int argc, char **argv)
61 {
62         char                    *output = NULL;
63         struct ao_hex_image     *image = NULL;
64         struct ao_sym           *file_symbols;
65         int                     num_file_symbols;
66         FILE                    *file;
67         int                     c;
68         uint32_t                base = 0xffffffff;
69         uint32_t                align = 0;
70         uint32_t                length;
71         int                     verbose = 0;
72         int                     dfu = 0;
73
74         while ((c = getopt_long(argc, argv, "dvo:b:a:", options, NULL)) != -1) {
75                 switch (c) {
76                 case 'o':
77                         output = optarg;
78                         break;
79                 case 'v':
80                         verbose++;
81                         break;
82                 case 'b':
83                         base = strtoul(optarg, NULL, 0);
84                         break;
85                 case 'a':
86                         align = strtoul(optarg, NULL, 0);
87                         break;
88                 case 'd':
89                         dfu = 1;
90                         break;
91                 default:
92                         usage(argv[0]);
93                         break;
94                 }
95         }
96
97         while (argv[optind]) {
98                 char                    *input = argv[optind];
99                 struct ao_hex_image     *tmp;
100
101                 if (ends_with (input, ".ihx"))
102                         tmp = ao_hex_load(input, &file_symbols, &num_file_symbols);
103                 else
104                         tmp = ao_load_elf(input, &file_symbols, &num_file_symbols);
105
106                 if (!tmp)
107                         usage(argv[0]);
108
109                 if (verbose)
110                         fprintf(stderr, "%s: 0x%x %d\n", input, tmp->address, tmp->length);
111
112                 if (image) {
113                         image = ao_hex_image_cat(image, tmp);
114                         if (!image)
115                                 usage(argv[0]);
116                 } else
117                         image = tmp;
118                 optind++;
119         }
120
121         if (base != 0xffffffff && base > image->address) {
122                 fprintf(stderr, "requested base 0x%x is after image address 0x%x\n",
123                         base, image->address);
124                 usage(argv[0]);
125         }
126
127         if (verbose)
128                 fprintf(stderr, "%s: base 0x%x length %d\n", output ? output : "<stdout>", image->address, image->length);
129
130         if (!output)
131                 file = stdout;
132         else {
133                 file = fopen(output, "w");
134                 if (!file) {
135                         perror(output);
136                         exit(1);
137                 }
138         }
139
140         if (dfu) {
141                 if (!ao_dfu_write(file, &dfu_info, 1, image)) {
142                         fprintf(stderr, "%s: dfu_write failed: %s\n", output, strerror(errno));
143                         if (output)
144                                 unlink(output);
145                         exit(1);
146                 }
147         } else {
148                 while (base < image->address) {
149                         fputc(0xff, file);
150                         base++;
151                 }
152
153                 if (fwrite(image->data, 1, image->length, file) != image->length) {
154                         fprintf(stderr, "%s: failed to write bin file\n", output ? output : "<stdout>");
155                         if (output)
156                                 unlink(output);
157                         exit(1);
158                 }
159
160                 if (align) {
161                         length = image->length;
162
163                         while (length % align) {
164                                 fputc(0xff, file);
165                                 length++;
166                         }
167                 }
168                 fflush(file);
169         }
170
171         exit(0);
172 }