diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/mks5lboot/main.c | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/mks5lboot/main.c')
-rw-r--r-- | utils/mks5lboot/main.c | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/utils/mks5lboot/main.c b/utils/mks5lboot/main.c new file mode 100644 index 0000000000..31e16eca82 --- /dev/null +++ b/utils/mks5lboot/main.c | |||
@@ -0,0 +1,296 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id:$ | ||
9 | * | ||
10 | * Copyright (C) 2015 by Cástor Muñoz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include <unistd.h> | ||
26 | #include <fcntl.h> | ||
27 | #include <sys/types.h> | ||
28 | #include <sys/stat.h> | ||
29 | |||
30 | #include "mks5lboot.h" | ||
31 | |||
32 | /* Win32 compatibility */ | ||
33 | #ifndef O_BINARY | ||
34 | #define O_BINARY 0 | ||
35 | #endif | ||
36 | |||
37 | #ifdef WIN32 | ||
38 | #include <windows.h> | ||
39 | #define sleep_ms(ms) Sleep(ms) | ||
40 | #else | ||
41 | #include <time.h> | ||
42 | static void sleep_ms(unsigned int ms) | ||
43 | { | ||
44 | struct timespec req; | ||
45 | req.tv_sec = ms / 1000; | ||
46 | req.tv_nsec = (ms % 1000) * 1000000; | ||
47 | nanosleep(&req, NULL); | ||
48 | } | ||
49 | #endif | ||
50 | |||
51 | #define DEFAULT_LOOP_PERIOD 1 /* seconds */ | ||
52 | |||
53 | #define _ERR(format, ...) \ | ||
54 | do { \ | ||
55 | snprintf(errstr, errstrsize, "[ERR] "format, __VA_ARGS__); \ | ||
56 | goto error; \ | ||
57 | } while(0) | ||
58 | |||
59 | static int write_file(char *outfile, unsigned char* buf, | ||
60 | int bufsize, char* errstr, int errstrsize) | ||
61 | { | ||
62 | int fd = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); | ||
63 | if (fd < 0) | ||
64 | _ERR("Could not open %s for writing", outfile); | ||
65 | |||
66 | if (write(fd, buf, bufsize) != bufsize) | ||
67 | _ERR("Could not write file %s", outfile); | ||
68 | |||
69 | return 1; | ||
70 | |||
71 | error: | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static unsigned char *read_file(char *infile, int *bufsize, | ||
76 | char* errstr, int errstrsize) | ||
77 | { | ||
78 | unsigned char *buf; | ||
79 | int fd; | ||
80 | struct stat s; | ||
81 | |||
82 | fd = open(infile, O_RDONLY|O_BINARY); | ||
83 | if (fd < 0) | ||
84 | _ERR("Could not open %s for reading", infile); | ||
85 | |||
86 | if (fstat(fd, &s) < 0) | ||
87 | _ERR("Checking size of input file %s", infile); | ||
88 | |||
89 | *bufsize = s.st_size; | ||
90 | |||
91 | buf = malloc(*bufsize); | ||
92 | if (buf == NULL) | ||
93 | _ERR("Could not allocate memory for %s", infile); | ||
94 | |||
95 | if (read(fd, buf, *bufsize) != *bufsize) | ||
96 | _ERR("Could not read file %s", infile); | ||
97 | |||
98 | return buf; | ||
99 | |||
100 | error: | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
104 | static void usage(void) | ||
105 | { | ||
106 | fprintf(stderr, | ||
107 | "Usage:\n" | ||
108 | " mks5lboot --bl-inst <bootloader.ipod> [-p <pid>] [--single]\n" | ||
109 | " --bl-uninst <platform> [-p <pid>]\n" | ||
110 | " --dfuscan [--loop [<sec>]] [-p <pid>]\n" | ||
111 | " --dfusend <infile.dfu> [-p <pid>]\n" | ||
112 | " --dfureset [--loop [<sec>]] [-p <pid>]\n" | ||
113 | " --mkdfu-inst <bootloader.ipod> <outfile.dfu> [--single]\n" | ||
114 | " --mkdfu-uninst <platform> <outfile.dfu>\n" | ||
115 | " --mkdfu-raw <filename.bin> <outfile.dfu>\n" | ||
116 | "\n" | ||
117 | "Commands:\n" | ||
118 | " --bl-inst Install file <bootloader.ipod> into an iPod device\n" | ||
119 | " (same as --mkdfu-inst and --dfusend).\n" | ||
120 | " --bl-uninst Remove a bootloader from an iPod device (same as\n" | ||
121 | " --mkdfu-uninst and --dfusend).\n" | ||
122 | "\n" | ||
123 | " --dfuscan scan for DFU USB devices and outputs the status.\n" | ||
124 | " --dfusend send DFU image <infile.dfu> to the device.\n" | ||
125 | " --dfureset reset DFU USB device bus.\n" | ||
126 | "\n" | ||
127 | " --mkdfu-inst Build a DFU image containing an installer for\n" | ||
128 | " <bootloader.ipod>, save it as <outfile.dfu>.\n" | ||
129 | " --mkdfu-uninst Build a DFU image containing an uninstaler for\n" | ||
130 | " <platform> devices, save it as <outfile.dfu>.\n" | ||
131 | " --mkdfu-raw Build a DFU image containing raw executable\n" | ||
132 | " code, save it ass <outfile.dfu>. <infile.bin>\n" | ||
133 | " is the code you want to run, it is loaded at\n" | ||
134 | " address 0x%08x and executed.\n" | ||
135 | "\n" | ||
136 | " <bootloader.ipod> is the rockbox bootloader that you want to\n" | ||
137 | " install (previously scrambled with tools/scramble utility).\n" | ||
138 | "\n" | ||
139 | " <platform> is the name of the platform (type of device) for\n" | ||
140 | " which the DFU uninstaller will be built. Currently supported\n" | ||
141 | " platform names are:\n" | ||
142 | " ipod6g: iPod Classic 6G\n" | ||
143 | "\n" | ||
144 | "Options:\n" | ||
145 | " -p, --pid <pid> Use a specific <pid> (Product Id) USB device,\n" | ||
146 | " if this option is ommited then it uses the\n" | ||
147 | " first USB DFU device found.\n" | ||
148 | " -l, --loop <sec> Run the command every <sec> seconds, default\n" | ||
149 | " period (<sec> ommited) is %d seconds.\n" | ||
150 | " -S, --single Be careful using this option. The bootloader\n" | ||
151 | " is installed for single boot, the original\n" | ||
152 | " Apple NOR boot is destroyed (if it exists),\n" | ||
153 | " and only Rockbox can be used.\n" | ||
154 | , DFU_LOADADDR + BIN_OFFSET | ||
155 | , DEFAULT_LOOP_PERIOD); | ||
156 | |||
157 | exit(1); | ||
158 | } | ||
159 | |||
160 | int main(int argc, char* argv[]) | ||
161 | { | ||
162 | char *dfuoutfile = NULL; | ||
163 | char *dfuinfile = NULL; | ||
164 | char *dfu_arg = NULL; | ||
165 | int dfu_type = DFU_NONE; | ||
166 | int n_cmds = 0; | ||
167 | int scan = 0; | ||
168 | int pid = 0; | ||
169 | int reset = 0; | ||
170 | int loop = 0; | ||
171 | int single = 0; | ||
172 | char errstr[200]; | ||
173 | unsigned char *dfubuf; | ||
174 | int dfusize; | ||
175 | |||
176 | fprintf(stderr, | ||
177 | #if defined(WIN32) && defined(USE_LIBUSBAPI) | ||
178 | "mks5lboot Version " VERSION " (libusb)\n" | ||
179 | #else | ||
180 | "mks5lboot Version " VERSION "\n" | ||
181 | #endif | ||
182 | "This is free software; see the source for copying conditions. There is NO\n" | ||
183 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" | ||
184 | "\n"); | ||
185 | fflush(stderr); | ||
186 | |||
187 | while (--argc) | ||
188 | { | ||
189 | argv++; | ||
190 | if (!memcmp(*argv, "--bl", 4)) { | ||
191 | if (!strcmp(*argv+4, "-inst")) dfu_type = DFU_INST; | ||
192 | else if (!strcmp(*argv+4, "-uninst")) dfu_type = DFU_UNINST; | ||
193 | else usage(); | ||
194 | if (!--argc) usage(); | ||
195 | dfu_arg = *++argv; | ||
196 | n_cmds++; | ||
197 | } | ||
198 | else if (!memcmp(*argv, "--mkdfu", 7)) { | ||
199 | if (!strcmp(*argv+7, "-inst")) dfu_type = DFU_INST; | ||
200 | else if (!strcmp(*argv+7, "-uninst")) dfu_type = DFU_UNINST; | ||
201 | else if (!strcmp(*argv+7, "-raw")) dfu_type = DFU_RAW; | ||
202 | else usage(); | ||
203 | if (!--argc) usage(); | ||
204 | dfu_arg = *++argv; | ||
205 | if (!--argc) usage(); | ||
206 | dfuoutfile = *++argv; | ||
207 | n_cmds++; | ||
208 | } | ||
209 | else if (!strcmp(*argv, "--dfusend")) { | ||
210 | if (!--argc) usage(); | ||
211 | dfuinfile = *++argv; | ||
212 | n_cmds++; | ||
213 | } | ||
214 | else if (!strcmp(*argv, "--dfuscan")) { | ||
215 | scan = 1; | ||
216 | n_cmds++; | ||
217 | } | ||
218 | else if (!strcmp(*argv, "--dfureset")) { | ||
219 | scan = 1; | ||
220 | reset = 1; | ||
221 | n_cmds++; | ||
222 | } | ||
223 | else if (!strcmp(*argv, "--pid") || !strcmp(*argv, "-p")) { | ||
224 | if (!--argc) usage(); | ||
225 | if (sscanf(*++argv, "%x", &pid) != 1) usage(); | ||
226 | } | ||
227 | else if (!strcmp(*argv, "--loop") || !strcmp (*argv, "-l")) { | ||
228 | if (!(argc-1) || *(argv+1)[0] == '-') { | ||
229 | loop = DEFAULT_LOOP_PERIOD; | ||
230 | } | ||
231 | else { | ||
232 | if ((sscanf(*++argv, "%d", &loop) != 1) || !loop) usage(); | ||
233 | argc--; | ||
234 | } | ||
235 | } | ||
236 | else if (!strcmp(*argv, "--single") || !strcmp(*argv, "-S")) { | ||
237 | single = 1; | ||
238 | } | ||
239 | else if (!strcmp(*argv, "--debug")) { | ||
240 | ipoddfu_debug(1); | ||
241 | } | ||
242 | else | ||
243 | usage(); | ||
244 | } | ||
245 | |||
246 | if (n_cmds != 1) | ||
247 | usage(); | ||
248 | |||
249 | if ((dfu_type == DFU_INST) && single) | ||
250 | dfu_type = DFU_INST_SINGLE; | ||
251 | |||
252 | if (scan) { | ||
253 | int cnt = 0; | ||
254 | while (1) { | ||
255 | int state, res; | ||
256 | if (loop) printf("[%d] ", cnt); | ||
257 | else printf("[INFO] "); | ||
258 | printf("DFU %s:\n", reset ? "reset":"scan"); | ||
259 | res = ipoddfu_scan(pid, &state, reset, errstr, sizeof(errstr)); | ||
260 | if (res == 0) | ||
261 | printf("%s\n", errstr); | ||
262 | else | ||
263 | printf("[INFO] DFU device state: %d\n", state); | ||
264 | if (!loop) | ||
265 | exit(!res); | ||
266 | fflush(stdout); | ||
267 | sleep_ms(loop*1000); | ||
268 | cnt += loop; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | if (dfuinfile) | ||
273 | dfubuf = read_file(dfuinfile, &dfusize, errstr, sizeof(errstr)); | ||
274 | else | ||
275 | dfubuf = mkdfu(dfu_type, dfu_arg, &dfusize, errstr, sizeof(errstr)); | ||
276 | |||
277 | if (!dfubuf) | ||
278 | goto error; | ||
279 | |||
280 | if (dfuoutfile) { | ||
281 | if (write_file(dfuoutfile, dfubuf, dfusize, errstr, sizeof(errstr))) { | ||
282 | printf("[INFO] Created file %s (%d bytes)\n", dfuoutfile, dfusize); | ||
283 | exit(0); | ||
284 | } | ||
285 | } | ||
286 | else { | ||
287 | if (ipoddfu_send(pid, dfubuf, dfusize, errstr, sizeof(errstr))) { | ||
288 | printf("[INFO] DFU image sent successfully (%d bytes)\n", dfusize); | ||
289 | exit(0); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | error: | ||
294 | printf("%s\n", errstr); | ||
295 | exit(1); | ||
296 | } | ||