1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Bertrik Sikken
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 * .sb file parser and chunk extractor
25 * Based on amsinfo, which is
26 * Copyright © 2008 Rafaël Carré <rafael.carre@gmail.com>
29 #define _ISOC99_SOURCE /* snprintf() */
45 /* all blocks are sized as a multiple of 0x1ff */
46 #define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
48 /* If you find a firmware that breaks the known format ^^ */
49 #define assert(a) do { if(!(a)) { fprintf(stderr,"Assertion \"%s\" failed in %s() line %d!\n\nPlease send us your firmware!\n",#a,__func__,__LINE__); exit(1); } } while(0)
51 #define crypto_cbc(...) \
52 do { int ret = crypto_cbc(__VA_ARGS__); \
53 if(ret != CRYPTO_ERROR_SUCCESS) \
54 bug("crypto_cbc error: %d\n", ret); \
61 static void elf_printf(void *user
, bool error
, const char *fmt
, ...)
63 if(!g_debug
&& !error
)
72 static void elf_write(void *user
, uint32_t addr
, const void *buf
, size_t count
)
75 fseek(f
, addr
, SEEK_SET
);
76 fwrite(buf
, count
, 1, f
);
79 static void extract_elf_section(struct elf_params_t
*elf
, int count
, uint32_t id
)
82 char *filename
= xmalloc(strlen(g_out_prefix
) + 32);
83 sb_fill_section_name(name
, id
);
84 sprintf(filename
, "%s%s.%d.elf", g_out_prefix
, name
, count
);
86 printf("Write boot section %s to %s\n", name
, filename
);
88 FILE *fd
= fopen(filename
, "wb");
93 elf_write_file(elf
, elf_write
, elf_printf
, fd
);
97 static void extract_sb_section(struct sb_section_t
*sec
)
102 char *filename
= xmalloc(strlen(g_out_prefix
) + 32);
103 sb_fill_section_name(sec_name
, sec
->identifier
);
104 sprintf(filename
, "%s%s.bin", g_out_prefix
, sec_name
);
105 FILE *fd
= fopen(filename
, "wb");
107 bugp("Cannot open %s for writing\n", filename
);
109 printf("Write data section %s to %s\n", sec_name
, filename
);
112 for(int j
= 0; j
< sec
->nr_insts
; j
++)
114 assert(sec
->insts
[j
].inst
== SB_INST_DATA
);
115 fwrite(sec
->insts
[j
].data
, sec
->insts
[j
].size
, 1, fd
);
121 struct elf_params_t elf
;
124 for(int i
= 0; i
< sec
->nr_insts
; i
++)
126 struct sb_inst_t
*inst
= &sec
->insts
[i
];
130 elf_add_load_section(&elf
, inst
->addr
, inst
->size
, inst
->data
);
133 elf_add_fill_section(&elf
, inst
->addr
, inst
->size
, inst
->pattern
);
137 elf_set_start_addr(&elf
, inst
->addr
);
138 extract_elf_section(&elf
, elf_count
++, sec
->identifier
);
143 /* ignore mode and nop */
148 if(!elf_is_empty(&elf
))
149 extract_elf_section(&elf
, elf_count
, sec
->identifier
);
153 static void extract_sb_file(struct sb_file_t
*file
)
155 for(int i
= 0; i
< file
->nr_sections
; i
++)
156 extract_sb_section(&file
->sections
[i
]);
159 static void usage(void)
161 printf("Usage: sbtoelf [options] sb-file\n");
162 printf("Options:\n");
163 printf(" -?/--help\tDisplay this message\n");
164 printf(" -o <prefix>\tEnable output and set prefix\n");
165 printf(" -d/--debug\tEnable debug output*\n");
166 printf(" -k <file>\tAdd key file\n");
167 printf(" -z\t\tAdd zero key\n");
168 printf(" -r\t\tUse raw command mode\n");
169 printf(" -a/--add-key <key>\tAdd single key (hex or usbotp)\n");
170 printf(" -n/--no-color\tDisable output colors\n");
171 printf(" -l/--loopback <file>\tProduce sb file out of extracted description*\n");
172 printf(" -f/--force\tForce reading even without a key*\n");
173 printf("Options marked with a * are for debug purpose only\n");
177 static void sb_printf(void *user
, bool error
, color_t c
, const char *fmt
, ...)
188 static struct crypto_key_t g_zero_key
=
190 .method
= CRYPTO_KEY
,
194 int main(int argc
, char **argv
)
196 bool raw_mode
= false;
197 const char *loopback
= NULL
;
201 static struct option long_options
[] =
203 {"help", no_argument
, 0, '?'},
204 {"debug", no_argument
, 0, 'd'},
205 {"add-key", required_argument
, 0, 'a'},
206 {"no-color", no_argument
, 0, 'n'},
207 {"loopback", required_argument
, 0, 'l'},
208 {"force", no_argument
, 0, 'f' },
212 int c
= getopt_long(argc
, argv
, "?do:k:zra:nl:f", long_options
, NULL
);
221 bug("Only one loopback file can be specified !\n");
234 g_out_prefix
= optarg
;
241 if(!add_keys_from_file(optarg
))
242 bug("Cannot add keys from %s\n", optarg
);
247 add_keys(&g_zero_key
, 1);
255 struct crypto_key_t key
;
257 if(!parse_key(&s
, &key
))
258 bug("Invalid key specified as argument\n");
260 bug("Trailing characters after key specified as argument\n");
269 if(argc
- optind
!= 1)
275 const char *sb_filename
= argv
[optind
];
278 struct sb_file_t
*file
= sb_read_file(sb_filename
, raw_mode
, NULL
, sb_printf
, &err
);
282 printf("SB read failed: %d\n", err
);
288 extract_sb_file(file
);
292 printf("[Debug output]\n");
293 sb_dump(file
, NULL
, sb_printf
);
297 /* sb_read_file will fill real key and IV but we don't want to override
298 * them when looping back otherwise the output will be inconsistent and
300 file
->override_real_key
= false;
301 file
->override_crypto_iv
= false;
302 sb_write_file(file
, loopback
);