summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-12-16 21:22:15 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2012-12-16 21:28:41 +0100
commit1e2e79d66809ad0f1ff598bf9dbed8e322a1f8ea (patch)
treefaa0444ad49c3c092ba0ee1efab4dfbe6c813d11
parent212cfdf771dc0059804cf817caaf2e43ef2b3f50 (diff)
downloadrockbox-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
-rw-r--r--utils/imxtools/sbtools/Makefile5
-rw-r--r--utils/imxtools/sbtools/elftosb1.c543
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
3LD=gcc 3LD=gcc
4CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES) 4CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES)
5LDFLAGS=`pkg-config --libs libusb-1.0` 5LDFLAGS=`pkg-config --libs libusb-1.0`
6BINS=elftosb sbtoelf sbloader rsrctool 6BINS=elftosb sbtoelf sbloader rsrctool elftosb1
7 7
8all: $(BINS) 8all: $(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
16elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o 16elftosb: 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
19elftosb1: elftosb1.o xorcrypt.o elf.o misc.o sb1.o
20 $(LD) -o $@ $^ $(LDFLAGS)
21
19sbloader: sbloader.o 22sbloader: 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
44char *g_output_file;
45bool g_critical;
46bool g_final;
47bool g_strict = true;
48uint32_t g_jump_arg;
49
50/**
51 * Helpers
52 */
53
54typedef char* (*get_next_arg_t)(void *user);
55
56struct cmd_line_next_arg_user_t
57{
58 int argc;
59 char **argv;
60};
61
62static 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
72static 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
79static 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
90static 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
98static 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
123static 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
136static 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
151static 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
164static 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
178static 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
208static void generate_default_sb_version(struct sb1_version_t *ver)
209{
210 ver->major = ver->minor = ver->revision = 0x9999;
211}
212
213static 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
226static 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
254union cmd_arg_t
255{
256 char *str;
257 unsigned long uint;
258};
259
260typedef int (*process_arg_t)(struct sb1_file_t *sb, union cmd_arg_t args[MAX_NR_ARGS]);
261
262struct 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
272static void usage(void);
273
274CMD_FN(cmd_help)
275{
276 (void) args;
277 (void) sb;
278 usage();
279 return 0;
280}
281
282CMD_FN(cmd_debug)
283{
284 (void) args;
285 (void) sb;
286 g_debug = true;
287 return 0;
288}
289
290CMD_FN(cmd_drive_tag)
291{
292 sb->drive_tag = args[0].uint;
293 return 0;
294}
295
296CMD_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
305CMD_FN(cmd_output)
306{
307 (void) sb;
308 g_output_file = strdup(args[0].str);
309 return 0;
310}
311
312CMD_FN(cmd_switch)
313{
314 return sb1_add_switch(sb, args[0].uint);
315}
316
317CMD_FN(cmd_sdram)
318{
319 return sb1_add_sdram(sb, args[0].uint, args[1].uint);
320}
321
322CMD_FN(cmd_critical)
323{
324 (void) sb;
325 (void) args;
326 g_critical = true;
327 return 0;
328}
329
330CMD_FN(cmd_clear_critical)
331{
332 (void) sb;
333 (void) args;
334 g_critical = false;
335 return 0;
336}
337
338CMD_FN(cmd_strict)
339{
340 (void) sb;
341 (void) args;
342 g_strict = true;
343 return 0;
344}
345
346CMD_FN(cmd_clear_strict)
347{
348 (void) sb;
349 (void) args;
350 g_strict = false;
351 return 0;
352}
353
354CMD_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
360CMD_FN(cmd_jumparg)
361{
362 (void) sb;
363 g_jump_arg = args[0].uint;
364 return 0;
365}
366
367static 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
409CMD_FN(cmd_load)
410{
411 return load_elf(sb, args[0].str, SB1_INST_LOAD);
412}
413
414CMD_FN(cmd_loadjump)
415{
416 return load_elf(sb, args[0].str, SB1_INST_JUMP);
417}
418
419CMD_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},
425struct 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
458static 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
493static 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
510int 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