Subversion Repositories QNX 8.QNX8 IFS tool

Rev

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
      if ((current_offset + sizeof (startup_header_t) < file.size) && (memcmp (&file.bytes[current_offset], "\xeb\x7e\xff\x00", 4) == 0))
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
714
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t);
725
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t);
715
 
726
 
716
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
727
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
717
 
728
 
718
         // write startup blob
729
         // write startup blob
719
         sprintf_s (outfile_pathname, sizeof (outfile_pathname), "%s/startup.bin", outdir);
730
         sprintf_s (outfile_pathname, sizeof (outfile_pathname), "%s/startup.bin", outdir);
720
         fopen_s (&fp, outfile_pathname, "wb");
731
         fopen_s (&fp, outfile_pathname, "wb");
721
         ASSERT (fp, "failed to open '%s': %s", outfile_pathname, strerror (errno));
732
         ASSERT (fp, "failed to open '%s': %s", outfile_pathname, strerror (errno));
722
         fwrite (&file.bytes[current_offset], 1, startupfile_blobsize, fp);
733
         fwrite (&file.bytes[current_offset], 1, startupfile_blobsize, fp);
723
         fclose (fp);
734
         fclose (fp);
724
 
735
 
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
      else if ((current_offset + sizeof (image_header_t) < file.size) && (memcmp (&file.bytes[current_offset], "imagefs", 7) == 0))
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]