diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2012-12-16 21:22:15 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2012-12-16 21:28:41 +0100 |
commit | 1e2e79d66809ad0f1ff598bf9dbed8e322a1f8ea (patch) | |
tree | faa0444ad49c3c092ba0ee1efab4dfbe6c813d11 /utils/imxtools/sbtools | |
parent | 212cfdf771dc0059804cf817caaf2e43ef2b3f50 (diff) | |
download | rockbox-1e2e79d66809ad0f1ff598bf9dbed8e322a1f8ea.tar.gz rockbox-1e2e79d66809ad0f1ff598bf9dbed8e322a1f8ea.zip |
imxtools/sbtools: introduce elftosb1 for stmp36xx
The tool still lacks some feature of the proprietary one but
can create files with all the basic features.
Change-Id: Ib0c91210940ca829291ce70945f88dc510a49974
Diffstat (limited to 'utils/imxtools/sbtools')
-rw-r--r-- | utils/imxtools/sbtools/Makefile | 5 | ||||
-rw-r--r-- | utils/imxtools/sbtools/elftosb1.c | 543 |
2 files changed, 547 insertions, 1 deletions
diff --git a/utils/imxtools/sbtools/Makefile b/utils/imxtools/sbtools/Makefile index bc7180d866..16ae0878b0 100644 --- a/utils/imxtools/sbtools/Makefile +++ b/utils/imxtools/sbtools/Makefile | |||
@@ -3,7 +3,7 @@ CC=gcc | |||
3 | LD=gcc | 3 | LD=gcc |
4 | CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES) | 4 | CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES) |
5 | LDFLAGS=`pkg-config --libs libusb-1.0` | 5 | LDFLAGS=`pkg-config --libs libusb-1.0` |
6 | BINS=elftosb sbtoelf sbloader rsrctool | 6 | BINS=elftosb sbtoelf sbloader rsrctool elftosb1 |
7 | 7 | ||
8 | all: $(BINS) | 8 | all: $(BINS) |
9 | 9 | ||
@@ -16,6 +16,9 @@ sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o xorcrypt.o elf.o misc.o sb.o s | |||
16 | elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o | 16 | elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o |
17 | $(LD) -o $@ $^ $(LDFLAGS) | 17 | $(LD) -o $@ $^ $(LDFLAGS) |
18 | 18 | ||
19 | elftosb1: elftosb1.o xorcrypt.o elf.o misc.o sb1.o | ||
20 | $(LD) -o $@ $^ $(LDFLAGS) | ||
21 | |||
19 | sbloader: sbloader.o | 22 | sbloader: sbloader.o |
20 | $(LD) -o $@ $^ $(LDFLAGS) | 23 | $(LD) -o $@ $^ $(LDFLAGS) |
21 | 24 | ||
diff --git a/utils/imxtools/sbtools/elftosb1.c b/utils/imxtools/sbtools/elftosb1.c new file mode 100644 index 0000000000..a654b6b34a --- /dev/null +++ b/utils/imxtools/sbtools/elftosb1.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 Amaury Pouly | ||
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 | #define _ISOC99_SOURCE | ||
23 | #define _POSIX_C_SOURCE 200809L /* for strdup */ | ||
24 | #include <stdio.h> | ||
25 | #include <errno.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <string.h> | ||
28 | #include <ctype.h> | ||
29 | #include <time.h> | ||
30 | #include <stdarg.h> | ||
31 | #include <strings.h> | ||
32 | |||
33 | #include "crypto.h" | ||
34 | #include "elf.h" | ||
35 | #include "sb1.h" | ||
36 | #include "misc.h" | ||
37 | |||
38 | #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) | ||
39 | |||
40 | /** | ||
41 | * Globals | ||
42 | */ | ||
43 | |||
44 | char *g_output_file; | ||
45 | bool g_critical; | ||
46 | bool g_final; | ||
47 | bool g_strict = true; | ||
48 | uint32_t g_jump_arg; | ||
49 | |||
50 | /** | ||
51 | * Helpers | ||
52 | */ | ||
53 | |||
54 | typedef char* (*get_next_arg_t)(void *user); | ||
55 | |||
56 | struct cmd_line_next_arg_user_t | ||
57 | { | ||
58 | int argc; | ||
59 | char **argv; | ||
60 | }; | ||
61 | |||
62 | static char *cmd_line_next_arg(void *user) | ||
63 | { | ||
64 | struct cmd_line_next_arg_user_t *uu = user; | ||
65 | if(uu->argc == 0) | ||
66 | return NULL; | ||
67 | uu->argc--; | ||
68 | uu->argv++; | ||
69 | return *(uu->argv - 1); | ||
70 | } | ||
71 | |||
72 | static bool elf_read(void *user, uint32_t addr, void *buf, size_t count) | ||
73 | { | ||
74 | if(fseek((FILE *)user, addr, SEEK_SET) == -1) | ||
75 | return false; | ||
76 | return fread(buf, 1, count, (FILE *)user) == count; | ||
77 | } | ||
78 | |||
79 | static void elf_printf(void *user, bool error, const char *fmt, ...) | ||
80 | { | ||
81 | if(!g_debug && !error) | ||
82 | return; | ||
83 | (void) user; | ||
84 | va_list args; | ||
85 | va_start(args, fmt); | ||
86 | vprintf(fmt, args); | ||
87 | va_end(args); | ||
88 | } | ||
89 | |||
90 | static int sb1_add_inst(struct sb1_file_t *sb, struct sb1_inst_t *insts, int nr_insts) | ||
91 | { | ||
92 | sb->insts = augment_array(sb->insts, sizeof(struct sb1_inst_t), sb->nr_insts, | ||
93 | insts, nr_insts); | ||
94 | sb->nr_insts += nr_insts; | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int sb1_add_load(struct sb1_file_t *sb, void *data, int size, uint32_t addr) | ||
99 | { | ||
100 | while(size > 0) | ||
101 | { | ||
102 | int len = MIN(size, SB1_CMD_MAX_LOAD_SIZE); | ||
103 | struct sb1_inst_t inst; | ||
104 | memset(&inst, 0, sizeof(inst)); | ||
105 | inst.cmd = SB1_INST_LOAD; | ||
106 | inst.size = len; | ||
107 | inst.addr = addr; | ||
108 | inst.critical = g_critical; | ||
109 | inst.data = xmalloc(len); | ||
110 | memcpy(inst.data, data, len); | ||
111 | if(g_debug) | ||
112 | printf("Add instruction: load %#x bytes at %#x\n", len, addr); | ||
113 | int ret = sb1_add_inst(sb, &inst, 1); | ||
114 | if(ret < 0) | ||
115 | return ret; | ||
116 | data += len; | ||
117 | size -= len; | ||
118 | addr += len; | ||
119 | } | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int sb1_add_switch(struct sb1_file_t *sb, uint32_t driver) | ||
124 | { | ||
125 | struct sb1_inst_t inst; | ||
126 | memset(&inst, 0, sizeof(inst)); | ||
127 | inst.cmd = SB1_INST_MODE; | ||
128 | inst.critical = g_critical; | ||
129 | inst.mode = driver; | ||
130 | if(g_debug) | ||
131 | printf("Add instruction: switch driver to %#x\n", driver); | ||
132 | g_final = true; | ||
133 | return sb1_add_inst(sb, &inst, 1); | ||
134 | } | ||
135 | |||
136 | static int sb1_add_sdram(struct sb1_file_t *sb, uint32_t cs, uint32_t size) | ||
137 | { | ||
138 | struct sb1_inst_t inst; | ||
139 | memset(&inst, 0, sizeof(inst)); | ||
140 | inst.cmd = SB1_INST_SDRAM; | ||
141 | inst.critical = g_critical; | ||
142 | inst.sdram.chip_select = cs; | ||
143 | inst.sdram.size_index = sb1_sdram_index_by_size(size); | ||
144 | if(sb1_sdram_index_by_size(size) < 0) | ||
145 | bug("Unknown SDRAM size: %d MB\n", size); | ||
146 | if(g_debug) | ||
147 | printf("Add instruction: init SDRAM (chip select=%d, size=%d MB)\n", cs, size); | ||
148 | return sb1_add_inst(sb, &inst, 1); | ||
149 | } | ||
150 | |||
151 | static int sb1_add_call(struct sb1_file_t *sb, uint32_t addr, uint32_t arg) | ||
152 | { | ||
153 | struct sb1_inst_t inst; | ||
154 | memset(&inst, 0, sizeof(inst)); | ||
155 | inst.cmd = SB1_INST_CALL; | ||
156 | inst.critical = g_critical; | ||
157 | inst.addr = addr; | ||
158 | inst.argument = arg; | ||
159 | if(g_debug) | ||
160 | printf("Add instruction: call %#x with argument %#x\n", addr, arg); | ||
161 | return sb1_add_inst(sb, &inst, 1); | ||
162 | } | ||
163 | |||
164 | static int sb1_add_jump(struct sb1_file_t *sb, uint32_t addr, uint32_t arg) | ||
165 | { | ||
166 | struct sb1_inst_t inst; | ||
167 | memset(&inst, 0, sizeof(inst)); | ||
168 | inst.cmd = SB1_INST_JUMP; | ||
169 | inst.critical = g_critical; | ||
170 | inst.addr = addr; | ||
171 | inst.argument = arg; | ||
172 | if(g_debug) | ||
173 | printf("Add instruction: jump %#x with argument %#x\n", addr, arg); | ||
174 | g_final = true; | ||
175 | return sb1_add_inst(sb, &inst, 1); | ||
176 | } | ||
177 | |||
178 | static int sb1_add_fill(struct sb1_file_t *sb, uint32_t pattern, uint32_t size, uint32_t addr) | ||
179 | { | ||
180 | while(size > 0) | ||
181 | { | ||
182 | int len = MIN(size, SB1_CMD_MAX_FILL_SIZE); | ||
183 | struct sb1_inst_t inst; | ||
184 | memset(&inst, 0, sizeof(inst)); | ||
185 | inst.cmd = SB1_INST_FILL; | ||
186 | inst.critical = g_critical; | ||
187 | inst.size = len; | ||
188 | inst.addr = addr; | ||
189 | inst.pattern = pattern; | ||
190 | inst.datatype = SB1_DATATYPE_UINT32; | ||
191 | if(g_debug) | ||
192 | printf("Add instruction: fill %#x bytes with pattern %#x at address %#x\n", | ||
193 | size, pattern, addr); | ||
194 | int ret = sb1_add_inst(sb, &inst, 1); | ||
195 | if(ret < 0) | ||
196 | return ret; | ||
197 | size -= len; | ||
198 | addr += len; | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * SB file modification | ||
206 | */ | ||
207 | |||
208 | static void generate_default_sb_version(struct sb1_version_t *ver) | ||
209 | { | ||
210 | ver->major = ver->minor = ver->revision = 0x9999; | ||
211 | } | ||
212 | |||
213 | static struct sb1_file_t *create_sb1_file(void) | ||
214 | { | ||
215 | struct sb1_file_t *sb = xmalloc(sizeof(struct sb1_file_t)); | ||
216 | memset(sb, 0, sizeof(struct sb1_file_t)); | ||
217 | |||
218 | /* default versions and key, apply_args() will overwrite if specified */ | ||
219 | generate_default_sb_version(&sb->product_ver); | ||
220 | generate_default_sb_version(&sb->component_ver); | ||
221 | sb1_get_default_key(&sb->key); | ||
222 | |||
223 | return sb; | ||
224 | } | ||
225 | |||
226 | static void *load_file(const char *filename, int *size) | ||
227 | { | ||
228 | FILE *fd = fopen(filename, "rb"); | ||
229 | if(fd == NULL) | ||
230 | bug("cannot open '%s' for reading\n", filename); | ||
231 | if(g_debug) | ||
232 | printf("Loading binary file '%s'...\n", filename); | ||
233 | fseek(fd, 0, SEEK_END); | ||
234 | *size = ftell(fd); | ||
235 | fseek(fd, 0, SEEK_SET); | ||
236 | void *data = xmalloc(*size); | ||
237 | fread(data, 1, *size, fd); | ||
238 | fclose(fd); | ||
239 | return data; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * Command line parsing | ||
244 | */ | ||
245 | |||
246 | #define MAX_NR_ARGS 2 | ||
247 | |||
248 | #define ARG_STR 0 | ||
249 | #define ARG_UINT 1 | ||
250 | |||
251 | #define CMD_FN(name) \ | ||
252 | int name(struct sb1_file_t *sb, union cmd_arg_t args[MAX_NR_ARGS]) | ||
253 | |||
254 | union cmd_arg_t | ||
255 | { | ||
256 | char *str; | ||
257 | unsigned long uint; | ||
258 | }; | ||
259 | |||
260 | typedef int (*process_arg_t)(struct sb1_file_t *sb, union cmd_arg_t args[MAX_NR_ARGS]); | ||
261 | |||
262 | struct cmd_entry_t | ||
263 | { | ||
264 | const char *name; | ||
265 | int nr_args; | ||
266 | int arg_type[MAX_NR_ARGS]; | ||
267 | process_arg_t fn; | ||
268 | }; | ||
269 | |||
270 | /* Callbacks */ | ||
271 | |||
272 | static void usage(void); | ||
273 | |||
274 | CMD_FN(cmd_help) | ||
275 | { | ||
276 | (void) args; | ||
277 | (void) sb; | ||
278 | usage(); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | CMD_FN(cmd_debug) | ||
283 | { | ||
284 | (void) args; | ||
285 | (void) sb; | ||
286 | g_debug = true; | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | CMD_FN(cmd_drive_tag) | ||
291 | { | ||
292 | sb->drive_tag = args[0].uint; | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | CMD_FN(cmd_load_binary) | ||
297 | { | ||
298 | int size; | ||
299 | void *data = load_file(args[0].str, &size); | ||
300 | int ret = sb1_add_load(sb, data, size, args[1].uint); | ||
301 | free(data); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | CMD_FN(cmd_output) | ||
306 | { | ||
307 | (void) sb; | ||
308 | g_output_file = strdup(args[0].str); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | CMD_FN(cmd_switch) | ||
313 | { | ||
314 | return sb1_add_switch(sb, args[0].uint); | ||
315 | } | ||
316 | |||
317 | CMD_FN(cmd_sdram) | ||
318 | { | ||
319 | return sb1_add_sdram(sb, args[0].uint, args[1].uint); | ||
320 | } | ||
321 | |||
322 | CMD_FN(cmd_critical) | ||
323 | { | ||
324 | (void) sb; | ||
325 | (void) args; | ||
326 | g_critical = true; | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | CMD_FN(cmd_clear_critical) | ||
331 | { | ||
332 | (void) sb; | ||
333 | (void) args; | ||
334 | g_critical = false; | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | CMD_FN(cmd_strict) | ||
339 | { | ||
340 | (void) sb; | ||
341 | (void) args; | ||
342 | g_strict = true; | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | CMD_FN(cmd_clear_strict) | ||
347 | { | ||
348 | (void) sb; | ||
349 | (void) args; | ||
350 | g_strict = false; | ||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | CMD_FN(cmd_call) | ||
355 | { | ||
356 | /* FIXME: the proprietary sbtoelf always sets argument to 0 ?! */ | ||
357 | return sb1_add_call(sb, args[0].uint, g_jump_arg); | ||
358 | } | ||
359 | |||
360 | CMD_FN(cmd_jumparg) | ||
361 | { | ||
362 | (void) sb; | ||
363 | g_jump_arg = args[0].uint; | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int load_elf(struct sb1_file_t *sb, const char *filename, int act) | ||
368 | { | ||
369 | struct elf_params_t elf; | ||
370 | FILE *fd = fopen(filename, "rb"); | ||
371 | if(fd == NULL) | ||
372 | bug("cannot open '%s'\n", filename); | ||
373 | if(g_debug) | ||
374 | printf("Loading elf file '%s'...\n", filename); | ||
375 | elf_init(&elf); | ||
376 | bool loaded = elf_read_file(&elf, elf_read, elf_printf, fd); | ||
377 | fclose(fd); | ||
378 | if(!loaded) | ||
379 | bug("error loading elf file '%s'\n", filename); | ||
380 | //elf_translate_addresses(&elf); | ||
381 | elf_sort_by_address(&elf); | ||
382 | |||
383 | struct elf_section_t *esec = elf.first_section; | ||
384 | while(esec) | ||
385 | { | ||
386 | if(esec->type == EST_LOAD) | ||
387 | sb1_add_load(sb, esec->section, esec->size, esec->addr); | ||
388 | else if(esec->type == EST_FILL) | ||
389 | sb1_add_fill(sb, esec->pattern, esec->size, esec->addr); | ||
390 | esec = esec->next; | ||
391 | } | ||
392 | |||
393 | int ret = 0; | ||
394 | if(act == SB1_INST_JUMP || act == SB1_INST_CALL) | ||
395 | { | ||
396 | if(!elf.has_start_addr) | ||
397 | bug("Cannot jump/call: '%s' has no start address!\n", filename); | ||
398 | if(act == SB1_INST_JUMP) | ||
399 | ret = sb1_add_jump(sb, elf.start_addr, g_jump_arg); | ||
400 | else | ||
401 | ret = sb1_add_call(sb, elf.start_addr, g_jump_arg); | ||
402 | } | ||
403 | |||
404 | elf_release(&elf); | ||
405 | |||
406 | return ret; | ||
407 | } | ||
408 | |||
409 | CMD_FN(cmd_load) | ||
410 | { | ||
411 | return load_elf(sb, args[0].str, SB1_INST_LOAD); | ||
412 | } | ||
413 | |||
414 | CMD_FN(cmd_loadjump) | ||
415 | { | ||
416 | return load_elf(sb, args[0].str, SB1_INST_JUMP); | ||
417 | } | ||
418 | |||
419 | CMD_FN(cmd_loadjumpreturn) | ||
420 | { | ||
421 | return load_elf(sb, args[0].str, SB1_INST_CALL); | ||
422 | } | ||
423 | |||
424 | #define CMD(name,fn,nr_args,...) {name,nr_args,{__VA_ARGS__},fn}, | ||
425 | struct cmd_entry_t g_cmds[] = | ||
426 | { | ||
427 | CMD("-d", cmd_debug, 0) | ||
428 | CMD("-debugon", cmd_debug, 0) | ||
429 | CMD("-h", cmd_help, 0) | ||
430 | CMD("-?", cmd_help, 0) | ||
431 | CMD("-load-binary", cmd_load_binary, 2, ARG_STR, ARG_UINT) | ||
432 | CMD("-drive-tag", cmd_drive_tag, 1, ARG_UINT) | ||
433 | CMD("-o", cmd_output, 1, ARG_STR) | ||
434 | CMD("-w", cmd_switch, 1, ARG_UINT) | ||
435 | CMD("-switchdriver", cmd_switch, 1, ARG_UINT) | ||
436 | CMD("-sdram", cmd_sdram, 2, ARG_UINT, ARG_UINT) | ||
437 | CMD("-c", cmd_critical, 0) | ||
438 | CMD("-critical", cmd_critical, 0) | ||
439 | CMD("-C", cmd_clear_critical, 0) | ||
440 | CMD("-noncritical", cmd_clear_critical, 0) | ||
441 | CMD("-n", cmd_strict, 0) | ||
442 | CMD("-strict", cmd_strict, 0) | ||
443 | CMD("-N", cmd_clear_strict, 0) | ||
444 | CMD("-nonstrict", cmd_clear_strict, 0) | ||
445 | CMD("-call", cmd_call, 1, ARG_UINT) | ||
446 | CMD("-jumparg", cmd_jumparg, 1, ARG_UINT) | ||
447 | CMD("-f", cmd_load, 1, ARG_STR) | ||
448 | CMD("-load", cmd_load, 1, ARG_STR) | ||
449 | CMD("-r", cmd_loadjumpreturn, 1, ARG_STR) | ||
450 | CMD("-loadjumpreturn", cmd_loadjumpreturn, 1, ARG_STR) | ||
451 | CMD("-j", cmd_loadjump, 1, ARG_STR) | ||
452 | CMD("-loadjump", cmd_loadjump, 1, ARG_STR) | ||
453 | }; | ||
454 | #undef CMD | ||
455 | |||
456 | #define NR_CMDS (int)(sizeof(g_cmds) / sizeof(g_cmds[0])) | ||
457 | |||
458 | static int apply_args(struct sb1_file_t *sb, get_next_arg_t next, void *user) | ||
459 | { | ||
460 | while(true) | ||
461 | { | ||
462 | /* next command ? */ | ||
463 | char *cmd = next(user); | ||
464 | if(cmd == NULL) | ||
465 | break; | ||
466 | /* switch */ | ||
467 | int i = 0; | ||
468 | while(i < NR_CMDS && strcmp(cmd, g_cmds[i].name) != 0) | ||
469 | i++; | ||
470 | if(i == NR_CMDS) | ||
471 | bug("Unknown option '%s'\n", cmd); | ||
472 | union cmd_arg_t args[MAX_NR_ARGS]; | ||
473 | for(int j = 0; j < g_cmds[i].nr_args; j++) | ||
474 | { | ||
475 | args[j].str = next(user); | ||
476 | if(args[j].str == NULL) | ||
477 | bug("Option '%s' requires %d arguments, only %d given\n", cmd, g_cmds[i].nr_args, j); | ||
478 | if(g_cmds[i].arg_type[j] == ARG_UINT) | ||
479 | { | ||
480 | char *end; | ||
481 | args[j].uint = strtoul(args[j].str, &end, 0); | ||
482 | if(*end) | ||
483 | bug("Option '%s' expects an integer as argument %d\n", cmd, j + 1); | ||
484 | } | ||
485 | } | ||
486 | int ret = g_cmds[i].fn(sb, args); | ||
487 | if(ret < 0) | ||
488 | return ret; | ||
489 | } | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | static void usage(void) | ||
494 | { | ||
495 | printf("Usage: elftosb1 [options]\n"); | ||
496 | printf("Options:\n"); | ||
497 | printf(" -h/-?/-help\t\t\tDisplay this message\n"); | ||
498 | printf(" -o <file>\t\t\tSet output file\n"); | ||
499 | printf(" -d/-debugon\t\t\tEnable debug output\n"); | ||
500 | printf(" -k <file>\t\t\tSet key file\n"); | ||
501 | printf(" -load-binary <file> <addr>\tLoad a binary file at a specified address\n"); | ||
502 | printf(" -drive-tag <tag>\t\tSpecify drive tag\n"); | ||
503 | printf(" -w/-switchdriver <driver>\tSwitch driver\n"); | ||
504 | printf(" -sdram <chip select> <size>\tInit SDRAM\n"); | ||
505 | printf(" -f/-load <file>\t\tLoad a ELF file\n"); | ||
506 | |||
507 | exit(1); | ||
508 | } | ||
509 | |||
510 | int main(int argc, char **argv) | ||
511 | { | ||
512 | if(argc <= 1) | ||
513 | usage(); | ||
514 | |||
515 | struct sb1_file_t *sb = create_sb1_file(); | ||
516 | |||
517 | struct cmd_line_next_arg_user_t u; | ||
518 | u.argc = argc - 1; | ||
519 | u.argv = argv + 1; | ||
520 | int ret = apply_args(sb, &cmd_line_next_arg, &u); | ||
521 | if(ret < 0) | ||
522 | { | ||
523 | sb1_free(sb); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | if(!g_output_file) | ||
528 | bug("You must specify an output file\n"); | ||
529 | if(!g_final) | ||
530 | { | ||
531 | if(g_strict) | ||
532 | bug("There is no final command in this command stream!\n"); | ||
533 | else | ||
534 | printf("Warning: there is no final command in this command stream!\n"); | ||
535 | } | ||
536 | |||
537 | enum sb1_error_t err = sb1_write_file(sb, g_output_file); | ||
538 | if(err != SB1_SUCCESS) | ||
539 | printf("Error: %d\n", err); | ||
540 | |||
541 | return ret; | ||
542 | } | ||
543 | |||