diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-08-31 20:41:33 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2017-01-02 21:43:51 +0100 |
commit | 23ecdebf97d0decfbfd5938abda1779072c44c66 (patch) | |
tree | 9603c9807d78a6145160f955946c67cff91397f1 | |
parent | ff946f1f69c325a948e3e73ac21c3880a0ea94d2 (diff) | |
download | rockbox-23ecdebf97d0decfbfd5938abda1779072c44c66.tar.gz rockbox-23ecdebf97d0decfbfd5938abda1779072c44c66.zip |
mkimxboot: implement firmware unpatching
Change-Id: Idfd68c06f89cdef8e95865e3ff177a6daa072c1a
-rw-r--r-- | rbutil/mkimxboot/mkimxboot.c | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/rbutil/mkimxboot/mkimxboot.c b/rbutil/mkimxboot/mkimxboot.c index 1d1ec54e10..5c63141624 100644 --- a/rbutil/mkimxboot/mkimxboot.c +++ b/rbutil/mkimxboot/mkimxboot.c | |||
@@ -491,11 +491,100 @@ static enum imx_error_t patch_firmware(struct imx_option_t opt, | |||
491 | } | 491 | } |
492 | } | 492 | } |
493 | 493 | ||
494 | static enum imx_error_t unpatch_std_zero_host_play(int jump_before, | ||
495 | struct imx_option_t opt, struct sb_file_t *sb_file) | ||
496 | { | ||
497 | /* find rockbox section */ | ||
498 | int rb_sec = -1; | ||
499 | for(int i = 0; i < sb_file->nr_sections; i++) | ||
500 | if(sb_file->sections[i].identifier == MAGIC_ROCK) | ||
501 | rb_sec = i; | ||
502 | if(rb_sec == -1) | ||
503 | { | ||
504 | printf("[ERR][INTERNAL] Cannot find rockbox section\n"); | ||
505 | return IMX_ERROR; | ||
506 | } | ||
507 | /** 1) remove rockbox section */ | ||
508 | /* free rockbox section */ | ||
509 | sb_free_section(sb_file->sections[rb_sec]); | ||
510 | /* create a new array of sections */ | ||
511 | sb_file->nr_sections--; | ||
512 | struct sb_section_t *new_sec = xmalloc(sb_file->nr_sections * sizeof(struct sb_section_t)); | ||
513 | /* copy all sections exception rockbox */ | ||
514 | memcpy(new_sec, sb_file->sections, rb_sec * sizeof(struct sb_section_t)); | ||
515 | memcpy(new_sec + rb_sec, sb_file->sections + rb_sec + 1, | ||
516 | (sb_file->nr_sections - rb_sec) * sizeof(struct sb_section_t)); | ||
517 | /* free old array and replace it */ | ||
518 | free(sb_file->sections); | ||
519 | sb_file->sections = new_sec; | ||
520 | |||
521 | /** 2) remove patch instructions in boot section */ | ||
522 | struct sb_section_t *sec = &sb_file->sections[0]; | ||
523 | int jump_idx = 0; | ||
524 | while(jump_idx < sec->nr_insts && jump_before > 0) | ||
525 | if(sec->insts[jump_idx++].inst == SB_INST_CALL) | ||
526 | jump_before--; | ||
527 | if(jump_idx == sec->nr_insts) | ||
528 | { | ||
529 | printf("[ERR] Cannot locate call in section ____\n"); | ||
530 | return IMX_DONT_KNOW_HOW_TO_PATCH; | ||
531 | } | ||
532 | /* free two instructions */ | ||
533 | sb_free_instruction(sec->insts[jump_idx]); | ||
534 | sb_free_instruction(sec->insts[jump_idx + 1]); | ||
535 | /* create a new array of instructions */ | ||
536 | sec->nr_insts -= 2; | ||
537 | struct sb_inst_t *new_inst = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t)); | ||
538 | /* copy all instructions except the two patch to remove */ | ||
539 | memcpy(new_inst, sec->insts, jump_idx * sizeof(struct sb_inst_t)); | ||
540 | memcpy(new_inst + jump_idx, sec->insts + jump_idx + 2, | ||
541 | (sec->nr_insts - jump_idx) * sizeof(struct sb_inst_t)); | ||
542 | /* free old array and replace it */ | ||
543 | free(sec->insts); | ||
544 | sec->insts = new_inst; | ||
545 | |||
546 | return IMX_SUCCESS; | ||
547 | } | ||
548 | |||
494 | static enum imx_error_t unpatch_firmware(struct imx_option_t opt, | 549 | static enum imx_error_t unpatch_firmware(struct imx_option_t opt, |
495 | struct sb_file_t *sb_file) | 550 | struct sb_file_t *sb_file) |
496 | { | 551 | { |
497 | printf("[ERR] Unimplemented\n"); | 552 | /* keep consistent with patch_firmware */ |
498 | return IMX_ERROR; | 553 | switch(opt.model) |
554 | { | ||
555 | case MODEL_FUZEPLUS: | ||
556 | /* The Fuze+ uses the standard ____, host, play sections, patch after third | ||
557 | * call in ____ section */ | ||
558 | return unpatch_std_zero_host_play(3, opt, sb_file); | ||
559 | case MODEL_ZENXFI3: | ||
560 | /* The ZEN X-Fi3 uses the standard ____, hSst, pSay sections, patch after third | ||
561 | * call in ____ section. Although sections names use the S variant, they are standard. */ | ||
562 | return unpatch_std_zero_host_play(3, opt, sb_file); | ||
563 | case MODEL_NWZE360: | ||
564 | case MODEL_NWZE370: | ||
565 | /* The NWZ-E360/E370 uses the standard ____, host, play sections, patch after first | ||
566 | * call in ____ section. */ | ||
567 | return unpatch_std_zero_host_play(1, opt, sb_file); | ||
568 | case MODEL_ZENXFI2: | ||
569 | /* The ZEN X-Fi2 has two types of firmware: recovery and normal. | ||
570 | * Normal uses the standard ___, host, play sections and recovery only ____ */ | ||
571 | switch(opt.fw_variant) | ||
572 | { | ||
573 | case VARIANT_ZENXFI2_RECOVERY: | ||
574 | case VARIANT_ZENXFI2_NAND: | ||
575 | case VARIANT_ZENXFI2_SD: | ||
576 | return unpatch_std_zero_host_play(1, opt, sb_file); | ||
577 | default: | ||
578 | return IMX_DONT_KNOW_HOW_TO_PATCH; | ||
579 | } | ||
580 | break; | ||
581 | case MODEL_ZENXFISTYLE: | ||
582 | /* The ZEN X-Fi Style uses the standard ____, host, play sections, patch after first | ||
583 | * call in ____ section. */ | ||
584 | return unpatch_std_zero_host_play(1, opt, sb_file); | ||
585 | default: | ||
586 | return IMX_DONT_KNOW_HOW_TO_PATCH; | ||
587 | } | ||
499 | } | 588 | } |
500 | 589 | ||
501 | static uint32_t get_uint32be(unsigned char *p) | 590 | static uint32_t get_uint32be(unsigned char *p) |
@@ -558,7 +647,7 @@ static enum imx_error_t find_model_by_md5sum(uint8_t file_md5sum[16], int *md5_i | |||
558 | } | 647 | } |
559 | if(i == NR_IMX_SUMS) | 648 | if(i == NR_IMX_SUMS) |
560 | { | 649 | { |
561 | printf("[ERR] MD5 sum doesn't match any known file\n"); | 650 | printf("[WARN] MD5 sum doesn't match any known file\n"); |
562 | return IMX_NO_MATCH; | 651 | return IMX_NO_MATCH; |
563 | } | 652 | } |
564 | *md5_idx = i; | 653 | *md5_idx = i; |
@@ -886,6 +975,9 @@ static enum imx_error_t make_boot(struct sb_file_t *sb_file, const char *bootfil | |||
886 | if(ret != IMX_SUCCESS) | 975 | if(ret != IMX_SUCCESS) |
887 | return ret; | 976 | return ret; |
888 | } | 977 | } |
978 | /* if asked to produce OF, don't do anything more */ | ||
979 | if(opt.output == IMX_ORIG_FW) | ||
980 | return IMX_SUCCESS; | ||
889 | /* load rockbox file */ | 981 | /* load rockbox file */ |
890 | struct rb_fw_t boot_fw; | 982 | struct rb_fw_t boot_fw; |
891 | enum imx_error_t ret = rb_fw_load(&boot_fw, bootfile, opt.model); | 983 | enum imx_error_t ret = rb_fw_load(&boot_fw, bootfile, opt.model); |