Rev 26 | Rev 30 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 26 | Rev 27 | ||
|---|---|---|---|
| Line 663... | Line 663... | ||
| 663 | size_t imageheader_offset = 0; |
663 | size_t imageheader_offset = 0; |
| 664 | size_t imagetrailer_offset = 0; |
664 | size_t imagetrailer_offset = 0; |
| 665 | fsentry_t **fsentries = NULL; // mallocated |
665 | fsentry_t **fsentries = NULL; // mallocated |
| 666 | size_t fsentry_count = 0; |
666 | size_t fsentry_count = 0; |
| 667 | fsentry_t *current_fsentry = NULL; |
667 | fsentry_t *current_fsentry = NULL; |
| - | 668 | buffer_t decompression_dst; |
|
| 668 | size_t startupfile_blobsize = 0; |
669 | size_t startupfile_blobsize = 0; |
| - | 670 | size_t compressed_blocksize; |
|
| 669 | struct utimbuf file_times = { 0, 0 }; |
671 | struct utimbuf file_times = { 0, 0 }; |
| 670 | void *reallocated_ptr; |
672 | void *reallocated_ptr; |
| - | 673 | uint8_t *decompressor_out; |
|
| - | 674 | uint8_t *decompressor_in; |
|
| - | 675 | size_t decompressor_outlen; |
|
| 671 | size_t bootfile_blobsize = 0; |
676 | size_t bootfile_blobsize = 0; |
| 672 | size_t current_offset; |
677 | size_t current_offset; |
| 673 | size_t fsentry_index; |
678 | size_t fsentry_index; |
| 674 | size_t nearest_distance; |
679 | size_t nearest_distance; |
| 675 | size_t nearest_index; |
680 | size_t nearest_index; |
| 676 | size_t byte_index; |
681 | size_t byte_index; |
| 677 | buffer_t file; |
682 | buffer_t file; |
| 678 | FILE *fp; |
683 | FILE *fp; |
| - | 684 | int cf; |
|
| 679 | 685 | ||
| 680 | // open and read IFS file |
686 | // open and read IFS file |
| 681 | if (!Buffer_ReadFromFile (&file, ifs_pathname)) |
687 | if (!Buffer_ReadFromFile (&file, ifs_pathname)) |
| 682 | DIE_WITH_EXITCODE (1, "can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno)); |
688 | DIE_WITH_EXITCODE (1, "can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno)); |
| 683 | 689 | ||
| Line 688... | Line 694... | ||
| 688 | // parse file from start to end |
694 | // parse file from start to end |
| 689 | current_offset = 0; |
695 | current_offset = 0; |
| 690 | for (;;) |
696 | for (;;) |
| 691 | { |
697 | { |
| 692 | // does a startup header start here ? |
698 | // does a startup header start here ? |
| - | 699 | if ((current_offset + sizeof (startup_header_t) < file.size) |
|
| - | 700 | && (startup_header == NULL) |
|
| 693 |
|
701 | && (memcmp (&file.bytes[current_offset], "\xeb\x7e\xff\x00", 4) == 0)) |
| 694 | { |
702 | { |
| 695 | startupheader_offset = current_offset; |
703 | startupheader_offset = current_offset; |
| 696 | startup_header = (startup_header_t *) &file.bytes[startupheader_offset]; |
704 | startup_header = (startup_header_t *) &file.bytes[startupheader_offset]; |
| 697 | 705 | ||
| 698 | // layout: |
706 | // layout: |
| Line 704... | Line 712... | ||
| 704 | if (current_offset + startup_header->startup_size > file.size) |
712 | if (current_offset + startup_header->startup_size > file.size) |
| 705 | { |
713 | { |
| 706 | LOG_WARNING ("this IFS file is corrupted (startup trailer extends past end of file)"); |
714 | LOG_WARNING ("this IFS file is corrupted (startup trailer extends past end of file)"); |
| 707 | goto endofdata; |
715 | goto endofdata; |
| 708 | } |
716 | } |
| - | 717 | ||
| - | 718 | // take note of the image compression flags |
|
| - | 719 | cf = startup_header->flags1 & STARTUP_HDR_FLAGS1_COMPRESS_MASK; |
|
| 709 | 720 | ||
| 710 | // locate the right startup trailer at the right offset |
721 | // locate the right startup trailer at the right offset |
| 711 | if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) |
722 | if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) |
| 712 | startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t); |
723 | startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t); |
| 713 | else // old V1 trailer |
724 | else // old V1 trailer |
| Line 725... | Line 736... | ||
| 725 | current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer |
736 | current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer |
| 726 | current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // jump over the startup trailer and reach the next segment |
737 | current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // jump over the startup trailer and reach the next segment |
| 727 | } |
738 | } |
| 728 | 739 | ||
| 729 | // else does an image header start here ? |
740 | // else does an image header start here ? |
| - | 741 | else if ((current_offset + sizeof (image_header_t) < file.size) |
|
| - | 742 | && (image_header == NULL) |
|
| 730 |
|
743 | && (((cf == STARTUP_HDR_FLAGS1_COMPRESS_NONE) && (memcmp (&file.bytes[current_offset], "imagefs", 7) == 0)) |
| - | 744 | || (cf != STARTUP_HDR_FLAGS1_COMPRESS_NONE) && (startup_header->imagefs_size > 0))) |
|
| 731 | { |
745 | { |
| 732 | imageheader_offset = current_offset; |
746 | imageheader_offset = current_offset; |
| 733 | image_header = (image_header_t *) &file.bytes[imageheader_offset]; |
747 | image_header = (image_header_t *) &file.bytes[imageheader_offset]; |
| - | 748 | ||
| - | 749 | // should we decompress it ? |
|
| - | 750 | if (cf != STARTUP_HDR_FLAGS1_COMPRESS_NONE) |
|
| - | 751 | { |
|
| - | 752 | // it appears mkifs compresses data in blocks, prefixed by 2-byte block size in BIG ENDIAN |
|
| - | 753 | Buffer_InitWithSize (&decompression_dst, startup_header->imagefs_size * 11 / 10); // mallocate and add 10% for safety |
|
| - | 754 | decompression_dst.size = 0; |
|
| - | 755 | ||
| - | 756 | if (cf == STARTUP_HDR_FLAGS1_COMPRESS_UCL) |
|
| - | 757 | ASSERT (ucl_init () == UCL_E_OK, "UCL library initialization failed -- please recompile this tool with less aggressive optimizations"); |
|
| - | 758 | else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_LZO) |
|
| - | 759 | ASSERT (lzo_init () == LZO_E_OK, "LZO library initialization failed -- please recompile this tool with less aggressive optimizations"); |
|
| - | 760 | else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_ZLIB) |
|
| - | 761 | { |
|
| - | 762 | LOG_WARNING ("unimplemented compression scheme: zlib (FIXME)"); |
|
| - | 763 | goto endofdata; |
|
| - | 764 | } |
|
| - | 765 | else |
|
| - | 766 | { |
|
| - | 767 | LOG_WARNING ("unsupported compression flags: 0x%2x", cf); |
|
| - | 768 | goto endofdata; |
|
| - | 769 | } |
|
| - | 770 | ||
| - | 771 | // run the compressed payload (the imagefs) through the right decompression algorithm |
|
| - | 772 | for (;;) |
|
| - | 773 | { |
|
| - | 774 | compressed_blocksize = (file.bytes[current_offset + 0] << 8) | (file.bytes[current_offset + 1] << 0); // read block size word (in big engian) |
|
| - | 775 | current_offset += 2; // skip it |
|
| - | 776 | if (compressed_blocksize == 0) |
|
| - | 777 | break; // a nil block size means end of stream is reached |
|
| - | 778 | LOG_DEBUG ("about to decompress block of %zd bytes", compressed_blocksize); |
|
| - | 779 | decompressor_in = &file.bytes[current_offset]; |
|
| - | 780 | decompressor_out = &decompression_dst.bytes[decompression_dst.size]; |
|
| - | 781 | decompressor_outlen = 0; |
|
| - | 782 | ||
| - | 783 | if (cf == STARTUP_HDR_FLAGS1_COMPRESS_UCL) |
|
| - | 784 | { |
|
| - | 785 | // UCL compression. NOTE: the decompressor function used in startup-x86 is "ucl_nrv2b_decompress_8 / ucl_nrv2b_decompress_le16 / ucl_nrv2b_decompress_le32" |
|
| - | 786 | static ucl_uint ucl_outlen; // have a different variable because of pointer size mismatch |
|
| - | 787 | if (ucl_nrv2b_decompress_8 (decompressor_in, (ucl_uint) compressed_blocksize, decompressor_out, &ucl_outlen, NULL) != UCL_E_OK) |
|
| - | 788 | { |
|
| - | 789 | LOG_WARNING ("this IFS file is corrupted (UCL decompression failed)"); |
|
| - | 790 | goto endofdata; |
|
| - | 791 | } |
|
| - | 792 | decompressor_outlen = ucl_outlen; |
|
| - | 793 | } |
|
| - | 794 | else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_LZO) |
|
| - | 795 | { |
|
| - | 796 | // LZO decompression. NOTE: mkifs uses the full LZO package, whereas I use minilzo. |
|
| - | 797 | static lzo_uint lzo_outlen; // have a different variable because of pointer size mismatch |
|
| - | 798 | if (lzo1x_decompress (decompressor_in, (lzo_uint) compressed_blocksize, decompressor_out, &lzo_outlen, NULL) != LZO_E_OK) |
|
| - | 799 | { |
|
| - | 800 | LOG_WARNING ("this IFS file is corrupted (UCL decompression failed)"); |
|
| - | 801 | goto endofdata; |
|
| - | 802 | } |
|
| - | 803 | decompressor_outlen = lzo_outlen; |
|
| - | 804 | } |
|
| - | 805 | else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_ZLIB) |
|
| - | 806 | ; // TODO |
|
| - | 807 | ||
| - | 808 | current_offset += compressed_blocksize; |
|
| - | 809 | decompression_dst.size += decompressor_outlen; |
|
| - | 810 | } |
|
| - | 811 | ||
| - | 812 | LOG_INFO ("decompressed %zd bytes into %zd bytes\n", file.size - imageheader_offset, decompression_dst.size); |
|
| - | 813 | ||
| - | 814 | // now place the decompressed buffer in the payload at the imagefs offset |
|
| - | 815 | ASSERT_WITH_ERRNO (Buffer_WriteBufferAt (&file, imageheader_offset, &decompression_dst)); |
|
| - | 816 | current_offset = imageheader_offset; // jump back to where we put the uncompressed data |
|
| - | 817 | file.size = imageheader_offset + decompression_dst.size; // update IFS data size |
|
| - | 818 | ||
| - | 819 | startup_header = (startup_header_t *) &file.bytes[startupheader_offset]; // fix the pointers that might have changed |
|
| - | 820 | image_header = (image_header_t *) &file.bytes[imageheader_offset]; // fix the pointers that might have changed |
|
| - | 821 | } |
|
| 734 | 822 | ||
| 735 | // layout: |
823 | // layout: |
| 736 | // [IMAGE HEADER] |
824 | // [IMAGE HEADER] |
| 737 | // [image directory entries] |
825 | // [image directory entries] |
| 738 | // [smallest file blobs up to KERNEL] |
826 | // [smallest file blobs up to KERNEL] |