diff options
Diffstat (limited to 'utils/imxtools/sbtools/sbtoelf.c')
-rw-r--r-- | utils/imxtools/sbtools/sbtoelf.c | 173 |
1 files changed, 147 insertions, 26 deletions
diff --git a/utils/imxtools/sbtools/sbtoelf.c b/utils/imxtools/sbtools/sbtoelf.c index 0170ea1836..0445c4a366 100644 --- a/utils/imxtools/sbtools/sbtoelf.c +++ b/utils/imxtools/sbtools/sbtoelf.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "crypto.h" | 40 | #include "crypto.h" |
41 | #include "elf.h" | 41 | #include "elf.h" |
42 | #include "sb.h" | 42 | #include "sb.h" |
43 | #include "sb1.h" | ||
43 | #include "misc.h" | 44 | #include "misc.h" |
44 | 45 | ||
45 | /* all blocks are sized as a multiple of 0x1ff */ | 46 | /* all blocks are sized as a multiple of 0x1ff */ |
@@ -156,6 +157,15 @@ static void extract_sb_file(struct sb_file_t *file) | |||
156 | extract_sb_section(&file->sections[i]); | 157 | extract_sb_section(&file->sections[i]); |
157 | } | 158 | } |
158 | 159 | ||
160 | static void extract_sb1_file(struct sb1_file_t *file) | ||
161 | { | ||
162 | FILE *f = fopen(g_out_prefix, "wb"); | ||
163 | if(f == NULL) | ||
164 | bugp("Cannot open %s for writing\n", g_out_prefix); | ||
165 | fwrite(file->data, file->data_size, 1, f); | ||
166 | fclose(f); | ||
167 | } | ||
168 | |||
159 | static void usage(void) | 169 | static void usage(void) |
160 | { | 170 | { |
161 | printf("Usage: sbtoelf [options] sb-file\n"); | 171 | printf("Usage: sbtoelf [options] sb-file\n"); |
@@ -170,6 +180,8 @@ static void usage(void) | |||
170 | printf(" -n/--no-color\tDisable output colors\n"); | 180 | printf(" -n/--no-color\tDisable output colors\n"); |
171 | printf(" -l/--loopback <file>\tProduce sb file out of extracted description*\n"); | 181 | printf(" -l/--loopback <file>\tProduce sb file out of extracted description*\n"); |
172 | printf(" -f/--force\tForce reading even without a key*\n"); | 182 | printf(" -f/--force\tForce reading even without a key*\n"); |
183 | printf(" -1/--v1\tForce to read file as a version 1 file\n"); | ||
184 | printf(" -2/--v2\tForce to read file as a version 2 file\n"); | ||
173 | printf("Options marked with a * are for debug purpose only\n"); | 185 | printf("Options marked with a * are for debug purpose only\n"); |
174 | exit(1); | 186 | exit(1); |
175 | } | 187 | } |
@@ -191,11 +203,72 @@ static struct crypto_key_t g_zero_key = | |||
191 | .u.key = {0} | 203 | .u.key = {0} |
192 | }; | 204 | }; |
193 | 205 | ||
206 | static struct crypto_key_t g_default_xor_key = | ||
207 | { | ||
208 | .method = CRYPTO_XOR_KEY, | ||
209 | .u.xor_key = | ||
210 | { | ||
211 | {.k = {0x67ECAEF6, 0xB31FB961, 0x118A9F4C, 0xA32A97DA, | ||
212 | 0x6CC39617, 0x5BC00314, 0x9D430685, 0x4D7DB502, | ||
213 | 0xA347685E, 0x3C87E86C, 0x8987AAA0, 0x24B78EF1, | ||
214 | 0x893B9605, 0x9BB8C2BE, 0x6D9544E2, 0x375B525C}}, | ||
215 | {.k = {0x3F424704, 0x53B5A331, 0x6AD345A5, 0x20DCEC51, | ||
216 | 0x743C8D3B, 0x444B3792, 0x0AF429569, 0xB7EE1111, | ||
217 | 0x583BF768, 0x9683BF9A, 0x0B032D799, 0xFE4E78ED, | ||
218 | 0xF20D08C2, 0xFA0BE4A2, 0x4D89C317, 0x887B2D6F}} | ||
219 | } | ||
220 | }; | ||
221 | |||
222 | enum sb_version_guess_t | ||
223 | { | ||
224 | SB_VERSION_1, | ||
225 | SB_VERSION_2, | ||
226 | SB_VERSION_UNK, | ||
227 | }; | ||
228 | |||
229 | enum sb_version_guess_t guess_sb_version(const char *filename) | ||
230 | { | ||
231 | FILE *f = fopen(filename, "rb"); | ||
232 | if(f == NULL) | ||
233 | bugp("Cannot open file for reading\n"); | ||
234 | // check signature | ||
235 | uint8_t sig[4]; | ||
236 | if(fseek(f, 20, SEEK_SET)) | ||
237 | return SB_VERSION_UNK; | ||
238 | if(fread(sig, 4, 1, f) != 1) | ||
239 | return SB_VERSION_UNK; | ||
240 | if(memcmp(sig, "STMP", 4) != 0) | ||
241 | return SB_VERSION_UNK; | ||
242 | // check header size (v1) | ||
243 | uint32_t hdr_size; | ||
244 | if(fseek(f, 8, SEEK_SET)) | ||
245 | return SB_VERSION_UNK; | ||
246 | if(fread(&hdr_size, 4, 1, f) != 1) | ||
247 | return SB_VERSION_UNK; | ||
248 | if(hdr_size == 0x34) | ||
249 | return SB_VERSION_1; | ||
250 | // check header size (v2) | ||
251 | if(fseek(f, 32, SEEK_SET)) | ||
252 | return SB_VERSION_UNK; | ||
253 | if(fread(&hdr_size, 4, 1, f) != 1) | ||
254 | return SB_VERSION_UNK; | ||
255 | if(hdr_size == 0xc) | ||
256 | return SB_VERSION_2; | ||
257 | return SB_VERSION_UNK; | ||
258 | } | ||
259 | |||
194 | int main(int argc, char **argv) | 260 | int main(int argc, char **argv) |
195 | { | 261 | { |
196 | bool raw_mode = false; | 262 | bool raw_mode = false; |
197 | const char *loopback = NULL; | 263 | const char *loopback = NULL; |
198 | 264 | bool force_sb1 = false; | |
265 | bool force_sb2 = false; | ||
266 | |||
267 | /* decrypt the xor key which is xor'ed */ | ||
268 | for(int i = 0; i < 2; i++) | ||
269 | for(int j = 0; j < 16; j++) | ||
270 | g_default_xor_key.u.xor_key[i].k[j] ^= 0xaa55aa55; | ||
271 | |||
199 | while(1) | 272 | while(1) |
200 | { | 273 | { |
201 | static struct option long_options[] = | 274 | static struct option long_options[] = |
@@ -205,11 +278,13 @@ int main(int argc, char **argv) | |||
205 | {"add-key", required_argument, 0, 'a'}, | 278 | {"add-key", required_argument, 0, 'a'}, |
206 | {"no-color", no_argument, 0, 'n'}, | 279 | {"no-color", no_argument, 0, 'n'}, |
207 | {"loopback", required_argument, 0, 'l'}, | 280 | {"loopback", required_argument, 0, 'l'}, |
208 | {"force", no_argument, 0, 'f' }, | 281 | {"force", no_argument, 0, 'f'}, |
282 | {"v1", no_argument, 0, '1'}, | ||
283 | {"v2", no_argument, 0, '2'}, | ||
209 | {0, 0, 0, 0} | 284 | {0, 0, 0, 0} |
210 | }; | 285 | }; |
211 | 286 | ||
212 | int c = getopt_long(argc, argv, "?do:k:zra:nl:f", long_options, NULL); | 287 | int c = getopt_long(argc, argv, "?do:k:zra:nl:f12x", long_options, NULL); |
213 | if(c == -1) | 288 | if(c == -1) |
214 | break; | 289 | break; |
215 | switch(c) | 290 | switch(c) |
@@ -243,10 +318,11 @@ int main(int argc, char **argv) | |||
243 | break; | 318 | break; |
244 | } | 319 | } |
245 | case 'z': | 320 | case 'z': |
246 | { | ||
247 | add_keys(&g_zero_key, 1); | 321 | add_keys(&g_zero_key, 1); |
248 | break; | 322 | break; |
249 | } | 323 | case 'x': |
324 | add_keys(&g_default_xor_key, 1); | ||
325 | break; | ||
250 | case 'r': | 326 | case 'r': |
251 | raw_mode = true; | 327 | raw_mode = true; |
252 | break; | 328 | break; |
@@ -261,11 +337,20 @@ int main(int argc, char **argv) | |||
261 | add_keys(&key, 1); | 337 | add_keys(&key, 1); |
262 | break; | 338 | break; |
263 | } | 339 | } |
340 | case '1': | ||
341 | force_sb1 = true; | ||
342 | break; | ||
343 | case '2': | ||
344 | force_sb2 = true; | ||
345 | break; | ||
264 | default: | 346 | default: |
265 | abort(); | 347 | abort(); |
266 | } | 348 | } |
267 | } | 349 | } |
268 | 350 | ||
351 | if(force_sb1 && force_sb2) | ||
352 | bug("You cannot force both version 1 and 2\n"); | ||
353 | |||
269 | if(argc - optind != 1) | 354 | if(argc - optind != 1) |
270 | { | 355 | { |
271 | usage(); | 356 | usage(); |
@@ -274,34 +359,70 @@ int main(int argc, char **argv) | |||
274 | 359 | ||
275 | const char *sb_filename = argv[optind]; | 360 | const char *sb_filename = argv[optind]; |
276 | 361 | ||
277 | enum sb_error_t err; | 362 | enum sb_version_guess_t ver = guess_sb_version(sb_filename); |
278 | struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err); | 363 | |
279 | if(file == NULL) | 364 | if(force_sb2 || ver == SB_VERSION_2) |
280 | { | 365 | { |
366 | enum sb_error_t err; | ||
367 | struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err); | ||
368 | if(file == NULL) | ||
369 | { | ||
370 | color(OFF); | ||
371 | printf("SB read failed: %d\n", err); | ||
372 | return 1; | ||
373 | } | ||
374 | |||
281 | color(OFF); | 375 | color(OFF); |
282 | printf("SB read failed: %d\n", err); | 376 | if(g_out_prefix) |
283 | return 1; | 377 | extract_sb_file(file); |
378 | if(g_debug) | ||
379 | { | ||
380 | color(GREY); | ||
381 | printf("[Debug output]\n"); | ||
382 | sb_dump(file, NULL, sb_printf); | ||
383 | } | ||
384 | if(loopback) | ||
385 | { | ||
386 | /* sb_read_file will fill real key and IV but we don't want to override | ||
387 | * them when looping back otherwise the output will be inconsistent and | ||
388 | * garbage */ | ||
389 | file->override_real_key = false; | ||
390 | file->override_crypto_iv = false; | ||
391 | sb_write_file(file, loopback); | ||
392 | } | ||
393 | sb_free(file); | ||
284 | } | 394 | } |
285 | 395 | else if(force_sb1 || ver == SB_VERSION_1) | |
286 | color(OFF); | ||
287 | if(g_out_prefix) | ||
288 | extract_sb_file(file); | ||
289 | if(g_debug) | ||
290 | { | 396 | { |
291 | color(GREY); | 397 | enum sb1_error_t err; |
292 | printf("[Debug output]\n"); | 398 | struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err); |
293 | sb_dump(file, NULL, sb_printf); | 399 | if(file == NULL) |
400 | { | ||
401 | color(OFF); | ||
402 | printf("SB read failed: %d\n", err); | ||
403 | return 1; | ||
404 | } | ||
405 | |||
406 | color(OFF); | ||
407 | if(g_out_prefix) | ||
408 | extract_sb1_file(file); | ||
409 | if(g_debug) | ||
410 | { | ||
411 | color(GREY); | ||
412 | printf("[Debug output]\n"); | ||
413 | sb1_dump(file, NULL, sb_printf); | ||
414 | } | ||
415 | if(loopback) | ||
416 | sb1_write_file(file, loopback); | ||
417 | |||
418 | sb1_free(file); | ||
294 | } | 419 | } |
295 | if(loopback) | 420 | else |
296 | { | 421 | { |
297 | /* sb_read_file will fill real key and IV but we don't want to override | 422 | color(OFF); |
298 | * them when looping back otherwise the output will be inconsistent and | 423 | printf("Cannot guess file type, are you sure it's a valid image ?\n"); |
299 | * garbage */ | 424 | return 1; |
300 | file->override_real_key = false; | ||
301 | file->override_crypto_iv = false; | ||
302 | sb_write_file(file, loopback); | ||
303 | } | 425 | } |
304 | sb_free(file); | ||
305 | clear_keys(); | 426 | clear_keys(); |
306 | 427 | ||
307 | return 0; | 428 | return 0; |