summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-15 22:13:08 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-15 22:27:34 +0200
commit58e27b9fa1e9ea058eb5161f140e0909c4821c92 (patch)
treed4f105c3fc42f78805ab8e86ad3455c4ae313136
parent6483e23f07f52bd3f90373896b585c0afa38036a (diff)
downloadrockbox-58e27b9fa1e9ea058eb5161f140e0909c4821c92.tar.gz
rockbox-58e27b9fa1e9ea058eb5161f140e0909c4821c92.zip
mkimxboot: refactor code, no functional change
The mkimxboot was becoming messy with juge functions and redundant code. Factor reading/writing/loading code into smaller functions. Introduce the concept of rockbox firmware to simplify support of other formats than scramble. Change-Id: I3a61295ca5abca1a0eee8c9e8709c6b8dfa256a6
-rw-r--r--rbutil/mkimxboot/mkimxboot.c471
-rw-r--r--rbutil/mkimxboot/mkimxboot.h3
2 files changed, 252 insertions, 222 deletions
diff --git a/rbutil/mkimxboot/mkimxboot.c b/rbutil/mkimxboot/mkimxboot.c
index d420afce5d..da1e49876d 100644
--- a/rbutil/mkimxboot/mkimxboot.c
+++ b/rbutil/mkimxboot/mkimxboot.c
@@ -28,6 +28,14 @@
28#include "dualboot.h" 28#include "dualboot.h"
29#include "md5.h" 29#include "md5.h"
30 30
31/* abstract structure to represent a Rockbox firmware. It can be a scrambled file
32 * or an ELF file or whatever. */
33struct rb_fw_t
34{
35 void *boot;
36 size_t boot_sz;
37};
38
31struct imx_fw_variant_desc_t 39struct imx_fw_variant_desc_t
32{ 40{
33 /* Offset within file */ 41 /* Offset within file */
@@ -160,7 +168,7 @@ static const struct imx_model_desc_t imx_models[] =
160#define MAGIC_NORMAL 0xcafebabe 168#define MAGIC_NORMAL 0xcafebabe
161 169
162static enum imx_error_t patch_std_zero_host_play(int jump_before, int model, 170static enum imx_error_t patch_std_zero_host_play(int jump_before, int model,
163 enum imx_output_type_t type, struct sb_file_t *sb_file, void *boot, size_t boot_sz) 171 enum imx_output_type_t type, struct sb_file_t *sb_file, struct rb_fw_t boot_fw)
164{ 172{
165 /* We assume the file has three boot sections: ____, host, play and one 173 /* We assume the file has three boot sections: ____, host, play and one
166 * resource section rsrc. 174 * resource section rsrc.
@@ -229,8 +237,8 @@ static enum imx_error_t patch_std_zero_host_play(int jump_before, int model,
229 rock_sec.insts = xmalloc(2 * sizeof(struct sb_inst_t)); 237 rock_sec.insts = xmalloc(2 * sizeof(struct sb_inst_t));
230 memset(rock_sec.insts, 0, 2 * sizeof(struct sb_inst_t)); 238 memset(rock_sec.insts, 0, 2 * sizeof(struct sb_inst_t));
231 rock_sec.insts[0].inst = SB_INST_LOAD; 239 rock_sec.insts[0].inst = SB_INST_LOAD;
232 rock_sec.insts[0].size = boot_sz; 240 rock_sec.insts[0].size = boot_fw.boot_sz;
233 rock_sec.insts[0].data = memdup(boot, boot_sz); 241 rock_sec.insts[0].data = memdup(boot_fw.boot, boot_fw.boot_sz);
234 rock_sec.insts[0].addr = imx_models[model].bootloader_addr; 242 rock_sec.insts[0].addr = imx_models[model].bootloader_addr;
235 rock_sec.insts[1].inst = SB_INST_JUMP; 243 rock_sec.insts[1].inst = SB_INST_JUMP;
236 rock_sec.insts[1].addr = imx_models[model].bootloader_addr; 244 rock_sec.insts[1].addr = imx_models[model].bootloader_addr;
@@ -253,13 +261,13 @@ static enum imx_error_t patch_std_zero_host_play(int jump_before, int model,
253 sb_free_instruction(sec->insts[i]); 261 sb_free_instruction(sec->insts[i]);
254 memset(new_insts + jump_idx, 0, 2 * sizeof(struct sb_inst_t)); 262 memset(new_insts + jump_idx, 0, 2 * sizeof(struct sb_inst_t));
255 new_insts[jump_idx + 0].inst = SB_INST_LOAD; 263 new_insts[jump_idx + 0].inst = SB_INST_LOAD;
256 new_insts[jump_idx + 0].size = boot_sz; 264 new_insts[jump_idx + 0].size = boot_fw.boot_sz;
257 new_insts[jump_idx + 0].data = memdup(boot, boot_sz); 265 new_insts[jump_idx + 0].data = memdup(boot_fw.boot, boot_fw.boot_sz);
258 new_insts[jump_idx + 0].addr = imx_models[model].bootloader_addr; 266 new_insts[jump_idx + 0].addr = imx_models[model].bootloader_addr;
259 new_insts[jump_idx + 1].inst = SB_INST_JUMP; 267 new_insts[jump_idx + 1].inst = SB_INST_JUMP;
260 new_insts[jump_idx + 1].addr = imx_models[model].bootloader_addr; 268 new_insts[jump_idx + 1].addr = imx_models[model].bootloader_addr;
261 new_insts[jump_idx + 1].argument = recovery ? MAGIC_RECOVERY : MAGIC_NORMAL; 269 new_insts[jump_idx + 1].argument = recovery ? MAGIC_RECOVERY : MAGIC_NORMAL;
262 270
263 free(sec->insts); 271 free(sec->insts);
264 sec->insts = new_insts; 272 sec->insts = new_insts;
265 sec->nr_insts = jump_idx + 2; 273 sec->nr_insts = jump_idx + 2;
@@ -327,7 +335,7 @@ static enum imx_error_t parse_version(const char *s, struct sb_version_t *ver)
327 335
328static enum imx_error_t patch_firmware(enum imx_model_t model, 336static enum imx_error_t patch_firmware(enum imx_model_t model,
329 enum imx_firmware_variant_t variant, enum imx_output_type_t type, 337 enum imx_firmware_variant_t variant, enum imx_output_type_t type,
330 struct sb_file_t *sb_file, void *boot, size_t boot_sz, 338 struct sb_file_t *sb_file, struct rb_fw_t boot_fw,
331 const char *force_version) 339 const char *force_version)
332{ 340{
333 if(force_version) 341 if(force_version)
@@ -342,11 +350,11 @@ static enum imx_error_t patch_firmware(enum imx_model_t model,
342 case MODEL_FUZEPLUS: 350 case MODEL_FUZEPLUS:
343 /* The Fuze+ uses the standard ____, host, play sections, patch after third 351 /* The Fuze+ uses the standard ____, host, play sections, patch after third
344 * call in ____ section */ 352 * call in ____ section */
345 return patch_std_zero_host_play(3, model, type, sb_file, boot, boot_sz); 353 return patch_std_zero_host_play(3, model, type, sb_file, boot_fw);
346 case MODEL_ZENXFI3: 354 case MODEL_ZENXFI3:
347 /* The ZEN X-Fi3 uses the standard ____, hSst, pSay sections, patch after third 355 /* The ZEN X-Fi3 uses the standard ____, hSst, pSay sections, patch after third
348 * call in ____ section. Although sections names use the S variant, they are standard. */ 356 * call in ____ section. Although sections names use the S variant, they are standard. */
349 return patch_std_zero_host_play(3, model, type, sb_file, boot, boot_sz); 357 return patch_std_zero_host_play(3, model, type, sb_file, boot_fw);
350 case MODEL_ZENXFI2: 358 case MODEL_ZENXFI2:
351 /* The ZEN X-Fi2 has two types of firmware: recovery and normal. 359 /* The ZEN X-Fi2 has two types of firmware: recovery and normal.
352 * Normal uses the standard ___, host, play sections and recovery only ____ */ 360 * Normal uses the standard ___, host, play sections and recovery only ____ */
@@ -355,7 +363,7 @@ static enum imx_error_t patch_firmware(enum imx_model_t model,
355 case VARIANT_ZENXFI2_RECOVERY: 363 case VARIANT_ZENXFI2_RECOVERY:
356 case VARIANT_ZENXFI2_NAND: 364 case VARIANT_ZENXFI2_NAND:
357 case VARIANT_ZENXFI2_SD: 365 case VARIANT_ZENXFI2_SD:
358 return patch_std_zero_host_play(1, model, type, sb_file, boot, boot_sz); 366 return patch_std_zero_host_play(1, model, type, sb_file, boot_fw);
359 default: 367 default:
360 return IMX_DONT_KNOW_HOW_TO_PATCH; 368 return IMX_DONT_KNOW_HOW_TO_PATCH;
361 } 369 }
@@ -413,165 +421,240 @@ void dump_imx_dev_info(const char *prefix)
413 } 421 }
414} 422}
415 423
416enum imx_error_t mkimxboot(const char *infile, const char *bootfile, 424/* find an entry into imx_sums which matches the MD5 sum of a file */
417 const char *outfile, struct imx_option_t opt) 425static enum imx_error_t find_model_by_md5sum(uint8_t file_md5sum[16], int *md5_idx)
418{ 426{
419 /* Dump tables */ 427 int i = 0;
420 if(opt.fw_variant > VARIANT_COUNT) { 428 while(i < NR_IMX_SUMS)
421 return IMX_ERROR;
422 }
423 dump_imx_dev_info("[INFO] ");
424 /* compute MD5 sum of the file */
425 uint8_t file_md5sum[16];
426 do
427 { 429 {
428 FILE *f = fopen(infile, "rb"); 430 uint8_t md5[20];
429 if(f == NULL) 431 if(strlen(imx_sums[i].md5sum) != 32)
430 { 432 {
431 printf("[ERR] Cannot open input file\n"); 433 printf("[INFO] Invalid MD5 sum in imx_sums\n");
432 return IMX_OPEN_ERROR; 434 return IMX_ERROR;
433 } 435 }
434 fseek(f, 0, SEEK_END); 436 for(int j = 0; j < 16; j++)
435 size_t sz = ftell(f);
436 fseek(f, 0, SEEK_SET);
437 void *buf = xmalloc(sz);
438 if(fread(buf, sz, 1, f) != 1)
439 { 437 {
440 fclose(f); 438 byte a, b;
441 free(buf); 439 if(convxdigit(imx_sums[i].md5sum[2 * j], &a) || convxdigit(imx_sums[i].md5sum[2 * j + 1], &b))
442 printf("[ERR] Cannot read file\n"); 440 {
443 return IMX_READ_ERROR; 441 printf("[ERR][INTERNAL] Bad checksum format: %s\n", imx_sums[i].md5sum);
442 return IMX_ERROR;
443 }
444 md5[j] = (a << 4) | b;
444 } 445 }
446 if(memcmp(file_md5sum, md5, 16) == 0)
447 break;
448 i++;
449 }
450 if(i == NR_IMX_SUMS)
451 {
452 printf("[ERR] MD5 sum doesn't match any known file\n");
453 return IMX_NO_MATCH;
454 }
455 *md5_idx = i;
456 return IMX_SUCCESS;
457}
458
459/* read a file to a buffer */
460static enum imx_error_t read_file(const char *file, void **buffer, size_t *size)
461{
462 FILE *f = fopen(file, "rb");
463 if(f == NULL)
464 {
465 printf("[ERR] Cannot open file '%s' for reading: %m\n", file);
466 return IMX_OPEN_ERROR;
467 }
468 fseek(f, 0, SEEK_END);
469 *size = ftell(f);
470 fseek(f, 0, SEEK_SET);
471 *buffer = xmalloc(*size);
472 if(fread(*buffer, *size, 1, f) != 1)
473 {
474 free(*buffer);
475 fclose(f);
476 printf("[ERR] Cannot read file '%s': %m\n", file);
477 return IMX_READ_ERROR;
478 }
479 fclose(f);
480 return IMX_SUCCESS;
481}
482
483/* write a file from a buffer */
484static enum imx_error_t write_file(const char *file, void *buffer, size_t size)
485{
486 FILE *f = fopen(file, "wb");
487 if(f == NULL)
488 {
489 printf("[ERR] Cannot open file '%s' for writing: %m\n", file);
490 return IMX_OPEN_ERROR;
491 }
492 if(fwrite(buffer, size, 1, f) != 1)
493 {
494 fclose(f);
495 printf("[ERR] Cannot write file '%s': %m\n", file);
496 return IMX_WRITE_ERROR;
497 }
498 fclose(f);
499 return IMX_SUCCESS;
500}
501
502/* compute MD5 sum of a buffer */
503static enum imx_error_t compute_md5sum_buf(void *buf, size_t sz, uint8_t file_md5sum[16])
504{
505 md5_context ctx;
506 md5_starts(&ctx);
507 md5_update(&ctx, buf, sz);
508 md5_finish(&ctx, file_md5sum);
509 return IMX_SUCCESS;
510}
511
512/* compute MD5 of a file */
513static enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16])
514{
515 FILE *f = fopen(file, "rb");
516 if(f == NULL)
517 {
518 printf("[ERR] Cannot open input file\n");
519 return IMX_OPEN_ERROR;
520 }
521 fseek(f, 0, SEEK_END);
522 size_t sz = ftell(f);
523 fseek(f, 0, SEEK_SET);
524 void *buf = xmalloc(sz);
525 if(fread(buf, sz, 1, f) != 1)
526 {
445 fclose(f); 527 fclose(f);
446 md5_context ctx;
447 md5_starts(&ctx);
448 md5_update(&ctx, buf, sz);
449 md5_finish(&ctx, file_md5sum);
450 free(buf); 528 free(buf);
451 }while(0); 529 printf("[ERR] Cannot read file\n");
530 return IMX_READ_ERROR;
531 }
532 fclose(f);
533 compute_md5sum_buf(buf, sz, file_md5sum);
534 free(buf);
535 return IMX_SUCCESS;
536}
537
538static enum imx_error_t load_sb_file(const char *file, int md5_idx,
539 struct imx_option_t opt, struct sb_file_t **sb_file)
540{
541 if(imx_sums[md5_idx].fw_variants[opt.fw_variant].size == 0)
542 {
543 printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[opt.fw_variant]);
544 return IMX_VARIANT_MISMATCH;
545 }
546 enum imx_model_t model = imx_sums[md5_idx].model;
547 enum sb_error_t err;
548 g_debug = opt.debug;
549 clear_keys();
550 add_keys(imx_models[model].keys, imx_models[model].nr_keys);
551 *sb_file = sb_read_file_ex(file, imx_sums[md5_idx].fw_variants[opt.fw_variant].offset,
552 imx_sums[md5_idx].fw_variants[opt.fw_variant].size, false, NULL, &imx_printf, &err);
553 if(*sb_file == NULL)
554 {
555 clear_keys();
556 return IMX_FIRST_SB_ERROR + err;
557 }
558 return IMX_SUCCESS;
559}
560
561/* Load a rockbox firwmare from a buffer. Data is copied. */
562static enum imx_error_t rb_fw_load_buf(struct rb_fw_t *fw, uint8_t *buf, size_t sz,
563 enum imx_model_t model)
564{
565 if(sz < 8)
566 {
567 printf("[ERR] Bootloader file is too small to be valid\n");
568 return IMX_BOOT_INVALID;
569 }
570 /* check model name */
571 uint8_t *name = buf + 4;
572 if(memcmp(name, imx_models[model].rb_model_name, 4) != 0)
573 {
574 printf("[ERR] Bootloader model doesn't match found model for input file\n");
575 return IMX_BOOT_MISMATCH;
576 }
577 /* check checksum */
578 uint32_t sum = imx_models[model].rb_model_num;
579 for(int i = 8; i < sz; i++)
580 sum += buf[i];
581 if(sum != get_uint32be(buf))
582 {
583 printf("[ERR] Bootloader checksum mismatch\n");
584 return IMX_BOOT_CHECKSUM_ERROR;
585 }
586 fw->boot = memdup(buf + 8, sz - 8);
587 fw->boot_sz = sz - 8;
588 return IMX_SUCCESS;
589}
590
591/* load a rockbox firmware from a file. */
592static enum imx_error_t rb_fw_load(struct rb_fw_t *fw, const char *file,
593 enum imx_model_t model)
594{
595 void *buf;
596 size_t sz;
597 int ret = read_file(file, &buf, &sz);
598 if(ret == IMX_SUCCESS)
599 {
600 ret = rb_fw_load_buf(fw, buf, sz, model);
601 free(buf);
602 }
603 return ret;
604}
605
606/* free rockbox firmware */
607static void rb_fw_free(struct rb_fw_t *fw)
608{
609 free(fw->boot);
610 fw->boot = NULL;
611 fw->boot_sz = 0;
612}
613
614enum imx_error_t mkimxboot(const char *infile, const char *bootfile,
615 const char *outfile, struct imx_option_t opt)
616{
617 /* sanity check */
618 if(opt.fw_variant > VARIANT_COUNT)
619 return IMX_ERROR;
620 /* Dump tables */
621 dump_imx_dev_info("[INFO] ");
622 /* compute MD5 sum of the file */
623 uint8_t file_md5sum[16];
624 enum imx_error_t ret = compute_md5sum(infile, file_md5sum);
625 if(ret != IMX_SUCCESS)
626 return ret;
452 printf("[INFO] MD5 sum of the file: "); 627 printf("[INFO] MD5 sum of the file: ");
453 print_hex(file_md5sum, 16, true); 628 print_hex(file_md5sum, 16, true);
454 /* find model */ 629 /* find model */
455 enum imx_model_t model;
456 int md5_idx; 630 int md5_idx;
457 do 631 ret = find_model_by_md5sum(file_md5sum, &md5_idx);
458 { 632 if(ret != IMX_SUCCESS)
459 int i = 0; 633 return ret;
460 while(i < NR_IMX_SUMS) 634 enum imx_model_t model = imx_sums[md5_idx].model;
461 {
462 uint8_t md5[20];
463 if(strlen(imx_sums[i].md5sum) != 32)
464 {
465 printf("[INFO] Invalid MD5 sum in imx_sums\n");
466 return IMX_ERROR;
467 }
468 for(int j = 0; j < 16; j++)
469 {
470 byte a, b;
471 if(convxdigit(imx_sums[i].md5sum[2 * j], &a) || convxdigit(imx_sums[i].md5sum[2 * j + 1], &b))
472 {
473 printf("[ERR][INTERNAL] Bad checksum format: %s\n", imx_sums[i].md5sum);
474 return IMX_ERROR;
475 }
476 md5[j] = (a << 4) | b;
477 }
478 if(memcmp(file_md5sum, md5, 16) == 0)
479 break;
480 i++;
481 }
482 if(i == NR_IMX_SUMS)
483 {
484 printf("[ERR] MD5 sum doesn't match any known file\n");
485 return IMX_NO_MATCH;
486 }
487 model = imx_sums[i].model;
488 md5_idx = i;
489 }while(0);
490 printf("[INFO] File is for model %d (%s, version %s)\n", model, 635 printf("[INFO] File is for model %d (%s, version %s)\n", model,
491 imx_models[model].model_name, imx_sums[md5_idx].version); 636 imx_models[model].model_name, imx_sums[md5_idx].version);
492 /* load rockbox file */ 637 /* load rockbox file */
493 uint8_t *boot; 638 struct rb_fw_t boot_fw;
494 size_t boot_size; 639 ret = rb_fw_load(&boot_fw, bootfile, model);
495 do 640 if(ret != IMX_SUCCESS)
496 { 641 return ret;
497 FILE *f = fopen(bootfile, "rb");
498 if(f == NULL)
499 {
500 printf("[ERR] Cannot open boot file\n");
501 return IMX_OPEN_ERROR;
502 }
503 fseek(f, 0, SEEK_END);
504 boot_size = ftell(f);
505 fseek(f, 0, SEEK_SET);
506 boot = xmalloc(boot_size);
507 if(fread(boot, boot_size, 1, f) != 1)
508 {
509 free(boot);
510 fclose(f);
511 printf("[ERR] Cannot read boot file\n");
512 return IMX_READ_ERROR;
513 }
514 fclose(f);
515 }while(0);
516 /* Check boot file */
517 do
518 {
519 if(boot_size < 8)
520 {
521 printf("[ERR] Bootloader file is too small to be valid\n");
522 free(boot);
523 return IMX_BOOT_INVALID;
524 }
525 /* check model name */
526 uint8_t *name = boot + 4;
527 if(memcmp(name, imx_models[model].rb_model_name, 4) != 0)
528 {
529 printf("[ERR] Bootloader model doesn't match found model for input file\n");
530 free(boot);
531 return IMX_BOOT_MISMATCH;
532 }
533 /* check checksum */
534 uint32_t sum = imx_models[model].rb_model_num;
535 for(int i = 8; i < boot_size; i++)
536 sum += boot[i];
537 if(sum != get_uint32be(boot))
538 {
539 printf("[ERR] Bootloader checksum mismatch\n");
540 free(boot);
541 return IMX_BOOT_CHECKSUM_ERROR;
542 }
543 }while(0);
544 /* load OF file */ 642 /* load OF file */
545 struct sb_file_t *sb_file; 643 struct sb_file_t *sb_file;
546 do 644 ret = load_sb_file(infile, md5_idx, opt, &sb_file);
645 if(ret != IMX_SUCCESS)
547 { 646 {
548 if(imx_sums[md5_idx].fw_variants[opt.fw_variant].size == 0) 647 rb_fw_free(&boot_fw);
549 { 648 return ret;
550 printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[opt.fw_variant]); 649 }
551 free(boot);
552 return IMX_VARIANT_MISMATCH;
553 }
554 enum sb_error_t err;
555 g_debug = opt.debug;
556 clear_keys();
557 add_keys(imx_models[model].keys, imx_models[model].nr_keys);
558 sb_file = sb_read_file_ex(infile, imx_sums[md5_idx].fw_variants[opt.fw_variant].offset,
559 imx_sums[md5_idx].fw_variants[opt.fw_variant].size, false, NULL, &imx_printf, &err);
560 if(sb_file == NULL)
561 {
562 clear_keys();
563 free(boot);
564 return IMX_FIRST_SB_ERROR + err;
565 }
566 }while(0);
567 /* produce file */ 650 /* produce file */
568 enum imx_error_t ret = patch_firmware(model, opt.fw_variant, opt.output, 651 ret = patch_firmware(model, opt.fw_variant, opt.output,
569 sb_file, boot + 8, boot_size - 8, opt.force_version); 652 sb_file, boot_fw, opt.force_version);
570 if(ret == IMX_SUCCESS) 653 if(ret == IMX_SUCCESS)
571 ret = sb_write_file(sb_file, outfile); 654 ret = sb_write_file(sb_file, outfile);
572 655
573 clear_keys(); 656 clear_keys();
574 free(boot); 657 rb_fw_free(&boot_fw);
575 sb_free(sb_file); 658 sb_free(sb_file);
576 return ret; 659 return ret;
577} 660}
@@ -579,78 +662,38 @@ enum imx_error_t mkimxboot(const char *infile, const char *bootfile,
579enum imx_error_t extract_firmware(const char *infile, 662enum imx_error_t extract_firmware(const char *infile,
580 enum imx_firmware_variant_t fw_variant, const char *outfile) 663 enum imx_firmware_variant_t fw_variant, const char *outfile)
581{ 664{
582 /* Dump tables */ 665 /* sanity check */
583 if(fw_variant > VARIANT_COUNT) { 666 if(fw_variant > VARIANT_COUNT)
584 return IMX_ERROR; 667 return IMX_ERROR;
585 } 668 /* dump tables */
586 dump_imx_dev_info("[INFO] "); 669 dump_imx_dev_info("[INFO] ");
587 /* compute MD5 sum of the file */ 670 /* compute MD5 sum of the file */
671 void *buf;
672 size_t sz;
588 uint8_t file_md5sum[16]; 673 uint8_t file_md5sum[16];
589 FILE *f = fopen(infile, "rb"); 674 int ret = read_file(infile, &buf, &sz);
590 if(f == NULL) 675 if(ret != IMX_SUCCESS)
591 { 676 return ret;
592 printf("[ERR] Cannot open input file\n"); 677 ret = compute_md5sum_buf(buf, sz, file_md5sum);
593 return IMX_OPEN_ERROR; 678 if(ret != IMX_SUCCESS)
594 }
595 fseek(f, 0, SEEK_END);
596 size_t sz = ftell(f);
597 fseek(f, 0, SEEK_SET);
598 void *buf = xmalloc(sz);
599 if(fread(buf, sz, 1, f) != 1)
600 { 679 {
601 fclose(f);
602 free(buf); 680 free(buf);
603 printf("[ERR] Cannot read file\n"); 681 return ret;
604 return IMX_READ_ERROR;
605 } 682 }
606 md5_context ctx;
607 md5_starts(&ctx);
608 md5_update(&ctx, buf, sz);
609 md5_finish(&ctx, file_md5sum);
610 fclose(f);
611
612 printf("[INFO] MD5 sum of the file: "); 683 printf("[INFO] MD5 sum of the file: ");
613 print_hex(file_md5sum, 16, true); 684 print_hex(file_md5sum, 16, true);
614 /* find model */ 685 /* find model */
615 enum imx_model_t model;
616 int md5_idx; 686 int md5_idx;
617 do 687 ret = find_model_by_md5sum(file_md5sum, &md5_idx);
688 if(ret != IMX_SUCCESS)
618 { 689 {
619 int i = 0; 690 free(buf);
620 while(i < NR_IMX_SUMS) 691 return ret;
621 { 692 }
622 uint8_t md5[20]; 693 enum imx_model_t model = imx_sums[md5_idx].model;
623 if(strlen(imx_sums[i].md5sum) != 32)
624 {
625 printf("[INFO] Invalid MD5 sum in imx_sums\n");
626 return IMX_ERROR;
627 }
628 for(int j = 0; j < 16; j++)
629 {
630 byte a, b;
631 if(convxdigit(imx_sums[i].md5sum[2 * j], &a) || convxdigit(imx_sums[i].md5sum[2 * j + 1], &b))
632 {
633 printf("[ERR][INTERNAL] Bad checksum format: %s\n", imx_sums[i].md5sum);
634 free(buf);
635 return IMX_ERROR;
636 }
637 md5[j] = (a << 4) | b;
638 }
639 if(memcmp(file_md5sum, md5, 16) == 0)
640 break;
641 i++;
642 }
643 if(i == NR_IMX_SUMS)
644 {
645 printf("[ERR] MD5 sum doesn't match any known file\n");
646 return IMX_NO_MATCH;
647 }
648 model = imx_sums[i].model;
649 md5_idx = i;
650 }while(0);
651 printf("[INFO] File is for model %d (%s, version %s)\n", model, 694 printf("[INFO] File is for model %d (%s, version %s)\n", model,
652 imx_models[model].model_name, imx_sums[md5_idx].version); 695 imx_models[model].model_name, imx_sums[md5_idx].version);
653 696 /* extract firmware */
654 if(imx_sums[md5_idx].fw_variants[fw_variant].size == 0) 697 if(imx_sums[md5_idx].fw_variants[fw_variant].size == 0)
655 { 698 {
656 printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[fw_variant]); 699 printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[fw_variant]);
@@ -658,23 +701,9 @@ enum imx_error_t extract_firmware(const char *infile,
658 return IMX_VARIANT_MISMATCH; 701 return IMX_VARIANT_MISMATCH;
659 } 702 }
660 703
661 f = fopen(outfile, "wb"); 704 ret = write_file(outfile,
662 if(f == NULL) 705 buf + imx_sums[md5_idx].fw_variants[fw_variant].offset,
663 { 706 imx_sums[md5_idx].fw_variants[fw_variant].size);
664 printf("[ERR] Cannot open input file\n");
665 free(buf);
666 return IMX_OPEN_ERROR;
667 }
668 enum imx_error_t ret = IMX_SUCCESS;
669
670 if(fwrite(buf + imx_sums[md5_idx].fw_variants[fw_variant].offset,
671 imx_sums[md5_idx].fw_variants[fw_variant].size, 1, f) != 1)
672 {
673 printf("[ERR] Cannot write file\n");
674 ret = IMX_ERROR;
675 }
676 fclose(f);
677 free(buf); 707 free(buf);
678
679 return ret; 708 return ret;
680} 709}
diff --git a/rbutil/mkimxboot/mkimxboot.h b/rbutil/mkimxboot/mkimxboot.h
index 748742f523..de564dc5d4 100644
--- a/rbutil/mkimxboot/mkimxboot.h
+++ b/rbutil/mkimxboot/mkimxboot.h
@@ -41,7 +41,8 @@ enum imx_error_t
41 IMX_BOOT_CHECKSUM_ERROR = -7, 41 IMX_BOOT_CHECKSUM_ERROR = -7,
42 IMX_DONT_KNOW_HOW_TO_PATCH = -8, 42 IMX_DONT_KNOW_HOW_TO_PATCH = -8,
43 IMX_VARIANT_MISMATCH = -9, 43 IMX_VARIANT_MISMATCH = -9,
44 IMX_FIRST_SB_ERROR = -10, 44 IMX_WRITE_ERROR = -10,
45 IMX_FIRST_SB_ERROR = -11,
45}; 46};
46 47
47enum imx_output_type_t 48enum imx_output_type_t