summaryrefslogtreecommitdiff
path: root/rbutil/mks5lboot/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/mks5lboot/main.c')
-rw-r--r--rbutil/mks5lboot/main.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/rbutil/mks5lboot/main.c b/rbutil/mks5lboot/main.c
new file mode 100644
index 0000000000..98c85b9bb7
--- /dev/null
+++ b/rbutil/mks5lboot/main.c
@@ -0,0 +1,287 @@
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 <time.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30
31#include "mks5lboot.h"
32
33/* Win32 compatibility */
34#ifndef O_BINARY
35#define O_BINARY 0
36#endif
37
38#define DEFAULT_LOOP_PERIOD 1 /* seconds */
39
40#define ERROR(format, ...) \
41 do { \
42 snprintf(errstr, errstrsize, "[ERR] "format, __VA_ARGS__); \
43 goto error; \
44 } while(0)
45
46static int write_file(char *outfile, unsigned char* buf,
47 int bufsize, char* errstr, int errstrsize)
48{
49 int fd = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
50 if (fd < 0)
51 ERROR("Could not open %s for writing", outfile);
52
53 if (write(fd, buf, bufsize) != bufsize)
54 ERROR("Could not write file %s", outfile);
55
56 return 1;
57
58error:
59 return 0;
60}
61
62static unsigned char *read_file(char *infile, int *bufsize,
63 char* errstr, int errstrsize)
64{
65 unsigned char *buf;
66 int fd;
67 struct stat s;
68
69 fd = open(infile, O_RDONLY|O_BINARY);
70 if (fd < 0)
71 ERROR("Could not open %s for reading", infile);
72
73 if (fstat(fd, &s) < 0)
74 ERROR("Checking size of input file %s", infile);
75
76 *bufsize = s.st_size;
77
78 buf = malloc(*bufsize);
79 if (buf == NULL)
80 ERROR("Could not allocate memory for %s", infile);
81
82 if (read(fd, buf, *bufsize) != *bufsize)
83 ERROR("Could not read file %s", infile);
84
85 return buf;
86
87error:
88 return NULL;
89}
90
91static void sleep_ms(unsigned int ms)
92{
93 struct timespec req;
94 req.tv_sec = ms / 1000;
95 req.tv_nsec = (ms % 1000) * 1000000;
96 nanosleep(&req, NULL);
97}
98
99static void usage(void)
100{
101 fprintf(stderr,
102 "Usage:\n"
103 " mks5lboot --bl-inst <bootloader.ipod> [-p <pid>] [--single]\n"
104 " --bl-uninst <platform> [-p <pid>]\n"
105 " --dfuscan [--loop [<sec>]] [-p <pid>]\n"
106 " --dfusend <infile.dfu> [-p <pid>]\n"
107 " --dfureset [--loop [<sec>]] [-p <pid>]\n"
108 " --mkdfu-inst <bootloader.ipod> <outfile.dfu> [--single]\n"
109 " --mkdfu-uninst <platform> <outfile.dfu>\n"
110 " --mkdfu-raw <filename.bin> <outfile.dfu>\n"
111 "\n"
112 "Commands:\n"
113 " --bl-inst Install file <bootloader.ipod> into an iPod device\n"
114 " (same as --mkdfu-inst and --dfusend).\n"
115 " --bl-uninst Remove a bootloader from an iPod device (same as\n"
116 " --mkdfu-uninst and --dfusend).\n"
117 "\n"
118 " --dfuscan scan for DFU USB devices and outputs the status.\n"
119 " --dfusend send DFU image <infile.dfu> to the device.\n"
120 " --dfureset reset DFU USB device bus.\n"
121 "\n"
122 " --mkdfu-inst Build a DFU image containing an installer for\n"
123 " <bootloader.ipod>, save it as <outfile.dfu>.\n"
124 " --mkdfu-uninst Build a DFU image containing an uninstaler for\n"
125 " <platform> devices, save it as <outfile.dfu>.\n"
126 " --mkdfu-raw Build a DFU image containing raw executable\n"
127 " code, save it ass <outfile.dfu>. <infile.bin>\n"
128 " is the code you want to run, it is loaded at\n"
129 " address 0x%08x and executed.\n"
130 "\n"
131 " <bootloader.ipod> is the rockbox bootloader that you want to\n"
132 " install (previously scrambled with tools/scramble utility).\n"
133 "\n"
134 " <platform> is the name of the platform (type of device) for\n"
135 " which the DFU uninstaller will be built. Currently supported\n"
136 " platform names are:\n"
137 " ipod6g: iPod Classic 6G\n"
138 "\n"
139 "Options:\n"
140 " -p, --pid <pid> Use a specific <pid> (Product Id) USB device,\n"
141 " if this option is ommited then it uses the\n"
142 " first USB DFU device found.\n"
143 " -l, --loop <sec> Run the command every <sec> seconds, default\n"
144 " period (<sec> ommited) is %d seconds.\n"
145 " -S, --single Be careful using this option. The bootloader\n"
146 " is installed for single boot, the original\n"
147 " Apple NOR boot is destroyed (if it exists),\n"
148 " and only Rockbox can be used.\n"
149 , DFU_LOADADDR + BIN_OFFSET
150 , DEFAULT_LOOP_PERIOD);
151
152 exit(1);
153}
154
155int main(int argc, char* argv[])
156{
157 char *dfuoutfile = NULL;
158 char *dfuinfile = NULL;
159 char *dfu_arg = NULL;
160 int dfu_type = DFU_NONE;
161 int n_cmds = 0;
162 int scan = 0;
163 int pid = 0;
164 int reset = 0;
165 int loop = 0;
166 int single = 0;
167 char errstr[200];
168 unsigned char *dfubuf;
169 int dfusize;
170
171 fprintf(stderr,
172 "mks5lboot Version " VERSION "\n"
173 "This is free software; see the source for copying conditions. There is NO\n"
174 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
175 "\n");
176 fflush(stderr);
177
178 while (--argc)
179 {
180 argv++;
181 if (!memcmp(*argv, "--bl", 4)) {
182 if (!strcmp(*argv+4, "-inst")) dfu_type = DFU_INST;
183 else if (!strcmp(*argv+4, "-uninst")) dfu_type = DFU_UNINST;
184 else usage();
185 if (!--argc) usage();
186 dfu_arg = *++argv;
187 n_cmds++;
188 }
189 else if (!memcmp(*argv, "--mkdfu", 7)) {
190 if (!strcmp(*argv+7, "-inst")) dfu_type = DFU_INST;
191 else if (!strcmp(*argv+7, "-uninst")) dfu_type = DFU_UNINST;
192 else if (!strcmp(*argv+7, "-raw")) dfu_type = DFU_RAW;
193 else usage();
194 if (!--argc) usage();
195 dfu_arg = *++argv;
196 if (!--argc) usage();
197 dfuoutfile = *++argv;
198 n_cmds++;
199 }
200 else if (!strcmp(*argv, "--dfusend")) {
201 if (!--argc) usage();
202 dfuinfile = *++argv;
203 n_cmds++;
204 }
205 else if (!strcmp(*argv, "--dfuscan")) {
206 scan = 1;
207 n_cmds++;
208 }
209 else if (!strcmp(*argv, "--dfureset")) {
210 scan = 1;
211 reset = 1;
212 n_cmds++;
213 }
214 else if (!strcmp(*argv, "--pid") || !strcmp(*argv, "-p")) {
215 if (!--argc) usage();
216 if (sscanf(*++argv, "%x", &pid) != 1) usage();
217 }
218 else if (!strcmp(*argv, "--loop") || !strcmp (*argv, "-l")) {
219 if (!(argc-1) || *(argv+1)[0] == '-') {
220 loop = DEFAULT_LOOP_PERIOD;
221 }
222 else {
223 if ((sscanf(*++argv, "%d", &loop) != 1) || !loop) usage();
224 argc--;
225 }
226 }
227 else if (!strcmp(*argv, "--single") || !strcmp(*argv, "-S")) {
228 single = 1;
229 }
230 else if (!strcmp(*argv, "--debug")) {
231 ipoddfu_debug(1);
232 }
233 else
234 usage();
235 }
236
237 if (n_cmds != 1)
238 usage();
239
240 if ((dfu_type == DFU_INST) && single)
241 dfu_type = DFU_INST_SINGLE;
242
243 if (scan) {
244 int cnt = 0;
245 while (1) {
246 int state, res;
247 if (loop) printf("[%d] ", cnt);
248 else printf("[INFO] ");
249 printf("DFU %s:\n", reset ? "reset":"scan");
250 res = ipoddfu_scan(pid, &state, reset, errstr, sizeof(errstr));
251 if (res == 0)
252 printf("%s\n", errstr);
253 else
254 printf("[INFO] DFU device state: %d\n", state);
255 if (!loop)
256 exit(!res);
257 fflush(stdout);
258 sleep_ms(loop*1000);
259 cnt += loop;
260 }
261 }
262
263 if (dfuinfile)
264 dfubuf = read_file(dfuinfile, &dfusize, errstr, sizeof(errstr));
265 else
266 dfubuf = mkdfu(dfu_type, dfu_arg, &dfusize, errstr, sizeof(errstr));
267
268 if (!dfubuf)
269 goto error;
270
271 if (dfuoutfile) {
272 if (write_file(dfuoutfile, dfubuf, dfusize, errstr, sizeof(errstr))) {
273 printf("[INFO] Created file %s (%d bytes)\n", dfuoutfile, dfusize);
274 exit(0);
275 }
276 }
277 else {
278 if (ipoddfu_send(pid, dfubuf, dfusize, errstr, sizeof(errstr))) {
279 printf("[INFO] DFU image sent successfully (%d bytes)\n", dfusize);
280 exit(0);
281 }
282 }
283
284error:
285 printf("%s\n", errstr);
286 exit(1);
287}