Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Rev 5 | Rev 7 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line 337... Line 337...
337
 
337
 
338
typedef struct __attribute__((packed)) image_header_s
338
typedef struct __attribute__((packed)) image_header_s
339
{
339
{
340
   uint8_t signature[7]; // image filesystem signature, i.e. "imagefs"
340
   uint8_t signature[7]; // image filesystem signature, i.e. "imagefs"
341
   uint8_t flags; // endian neutral flags, 0x1c
341
   uint8_t flags; // endian neutral flags, 0x1c
342
   uint32_t image_size; // size from header to end of trailer (here 0xca6fe0 or 13 266 912)
342
   uint32_t image_size; // size from start of header to end of trailer (here 0xca6fe0 or 13 266 912)
343
   uint32_t hdr_dir_size; // size from header to last dirent (here 0x12b8 or 4792)
343
   uint32_t hdr_dir_size; // size from start of header to last dirent (here 0x12b8 or 4792)
344
   uint32_t dir_offset; // offset from header to first dirent (here 0x5c or 92)
344
   uint32_t dir_offset; // offset from start of header to start of first dirent (here 0x5c or 92)
345
   uint32_t boot_ino[4]; // inode of files for bootstrap pgms (here 0xa0000002, 0, 0, 0)
345
   uint32_t boot_ino[4]; // inode of files for bootstrap pgms (here 0xa0000002, 0, 0, 0)
346
   uint32_t script_ino; // inode of file for script (here 3)
346
   uint32_t script_ino; // inode of file for script (here 3)
347
   uint32_t chain_paddr; // offset to next filesystem signature (0)
347
   uint32_t chain_paddr; // offset to next filesystem signature (0)
348
   uint32_t spare[10]; // zerofill
348
   uint32_t spare[10]; // zerofill
349
   uint32_t mountflags; // default _MOUNT_* from sys/iomsg.h (0)
349
   uint32_t mountflags; // default _MOUNT_* from sys/iomsg.h (0)
Line 407... Line 407...
407
static void sha512_private_transform (SHA512_CTX *context, const uint64_t *data); // used internally in SHA512_Update() and SHA512_Final()
407
static void sha512_private_transform (SHA512_CTX *context, const uint64_t *data); // used internally in SHA512_Update() and SHA512_Final()
408
static void SHA512_Init (SHA512_CTX *context);
408
static void SHA512_Init (SHA512_CTX *context);
409
static void SHA512_Update (SHA512_CTX *context, void *data, size_t len);
409
static void SHA512_Update (SHA512_CTX *context, void *data, size_t len);
410
static void SHA512_Final (uint8_t digest[SHA512_DIGEST_LENGTH], SHA512_CTX *context);
410
static void SHA512_Final (uint8_t digest[SHA512_DIGEST_LENGTH], SHA512_CTX *context);
411
static uint8_t *SHA512 (void *data, size_t data_len, uint8_t *digest); // computes a SHA-512 in one pass (shortcut for SHA512_Init(), SHA512_Update() N times and SHA512_Final())
411
static uint8_t *SHA512 (void *data, size_t data_len, uint8_t *digest); // computes a SHA-512 in one pass (shortcut for SHA512_Init(), SHA512_Update() N times and SHA512_Final())
412
static int32_t update_checksum32 (const int32_t start_value, const void *data, const size_t len); // update the sum of an array of 32-bit signed integers
-
 
413
static int32_t update_image_checksum (const int32_t start_value, const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image checksum to store in the image trailer
412
static int32_t update_checksum (const int32_t start_value, const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer
414
static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t)
413
static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t)
415
static void hex_fprintf (FILE *fp, const uint8_t *data, size_t data_size, int howmany_columns, const char *fmt, ...); // hexdump-style formatted output to a file stream (which may be stdout/stderr)
414
static void hex_fprintf (FILE *fp, const uint8_t *data, size_t data_size, int howmany_columns, const char *fmt, ...); // hexdump-style formatted output to a file stream (which may be stdout/stderr)
416
static char *binary (const uint8_t x, char char_for_zero, char char_for_one); // returns the binary representation of byte 'x' as a string
415
static char *binary (const uint8_t x, char char_for_zero, char char_for_one); // returns the binary representation of byte 'x' as a string
417
static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8]); // returns the ORed description of byte 'x' according to the description strings for each bit
416
static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8]); // returns the ORed description of byte 'x' according to the description strings for each bit
418
static int fwrite_filecontents (const char *pathname, FILE *fp); // dumps the contents of pathname into fp
417
static int fwrite_filecontents (const char *pathname, FILE *fp); // dumps the contents of pathname into fp
Line 667... Line 666...
667
      sprintf (&digest_as_string[2 * byte_index], "%02x", digest_or_NULL[byte_index]);
666
      sprintf (&digest_as_string[2 * byte_index], "%02x", digest_or_NULL[byte_index]);
668
   return (digest_as_string);
667
   return (digest_as_string);
669
}
668
}
670
 
669
 
671
 
670
 
672
static int32_t update_checksum32_NOT (const int32_t start_value, const void *data, const size_t len)
671
static int32_t update_checksum (const int32_t start_value, const void *data, const size_t data_len, const bool is_foreign_endianness)
673
{
672
{
674
   // compute the sum of an array of 32-bit signed integers
-
 
675
 
-
 
676
   const int32_t *values_array = data;
-
 
677
   int32_t sum = start_value;
-
 
678
 
-
 
679
   for (size_t value_index = 0; value_index < len / sizeof (int32_t); value_index++)
-
 
680
      sum += values_array[value_index];
-
 
681
 
-
 
682
   return (sum);
-
 
683
}
-
 
684
 
-
 
685
 
-
 
686
static int32_t update_checksum32 (const int32_t start_value, const void *data, const size_t data_len)
-
 
687
{
-
 
688
   uint8_t hold_cksum_4[4] = { 0, 0, 0, 0 };
-
 
689
 
-
 
690
   int32_t image_cksum = start_value;
-
 
691
 
-
 
692
   int hold_index; // ST2C_4@4
-
 
693
   uint64_t i; // [sp+30h] [bp-10h]@3
-
 
694
   char *current_char_ptr; // [sp+38h] [bp-8h]@3
-
 
695
   char *data_start; // [sp+50h] [bp+10h]@1
-
 
696
   uint64_t _data_len; // [sp+58h] [bp+18h]@1
-
 
697
 
-
 
698
   data_start = data;
-
 
699
   _data_len = data_len;
-
 
700
   current_char_ptr = data_start;
-
 
701
   for (i = 0; i < data_len; ++i)
-
 
702
   {
-
 
703
      hold_index = i & 3;
-
 
704
      hold_cksum_4[hold_index] = *current_char_ptr;
-
 
705
      if (hold_index == 3)
-
 
706
      {
-
 
707
         if (false) // endianness
-
 
708
            image_cksum += (hold_cksum_4[3] << 0)
-
 
709
            + (hold_cksum_4[2] << 8)
-
 
710
            + (hold_cksum_4[1] << 16)
-
 
711
            + (hold_cksum_4[0] << 24);
-
 
712
         else
-
 
713
            image_cksum += (hold_cksum_4[0] << 0)
-
 
714
            + (hold_cksum_4[1] << 8)
-
 
715
            + (hold_cksum_4[2] << 16)
-
 
716
            + (hold_cksum_4[3] << 24);
-
 
717
      }
-
 
718
      current_char_ptr++;
-
 
719
   }
-
 
720
   return (-image_cksum);
-
 
721
}
-
 
722
 
-
 
723
 
-
 
724
static int32_t update_image_checksum (const int32_t start_value, const void *data, const size_t data_len, const bool is_foreign_endianness)
-
 
725
{
-
 
726
   // computes the checksum of an IFS image section, i.e. from the start of the image header to the end of the image trailer minus the last 4 bytes where the checksum is stored
673
   // computes the checksum of an IFS image or startup section, i.e. from the start of the header to the end of the trailer minus the last 4 bytes where the checksum is stored
727
 
674
 
728
   uint8_t accumulator[4] = { 0, 0, 0, 0 };
675
   uint8_t accumulator[4] = { 0, 0, 0, 0 };
729
   int32_t image_cksum = start_value;
676
   int32_t image_cksum = start_value;
730
   char *current_char_ptr = data;
677
   const char *current_char_ptr = data;
731
   size_t i;
678
   size_t i;
732
 
679
 
733
   for (i = 0; i < data_len; i++)
680
   for (i = 0; i < data_len; i++)
734
   {
681
   {
735
      accumulator[i % 4] = *current_char_ptr;
682
      accumulator[i % 4] = *current_char_ptr;
Line 1443... Line 1390...
1443
               if (entry_parms.precompiled_data == NULL)
1390
               if (entry_parms.precompiled_data == NULL)
1444
               {
1391
               {
1445
                  fprintf (stderr, "fatal error: out of memory\n");
1392
                  fprintf (stderr, "fatal error: out of memory\n");
1446
                  exit (1);
1393
                  exit (1);
1447
               }
1394
               }
1448
               fp = fopen ("procnto-smp-instr.bin", "rb");
1395
               fp = fopen (kernelfile_pathname, "rb");
1449
               fread (entry_parms.precompiled_data, 1, stat_buf.st_size, fp);
1396
               fread (entry_parms.precompiled_data, 1, stat_buf.st_size, fp);
1450
               fclose (fp);
1397
               fclose (fp);
1451
               entry_parms.precompiled_datalen = stat_buf.st_size;
1398
               entry_parms.precompiled_datalen = stat_buf.st_size;
1452
            }
1399
            }
1453
            else if (strcmp (token, "+script") == 0) {
1400
            else if (strcmp (token, "+script") == 0) {
Line 1597... Line 1544...
1597
      if (blob_datasize > 0)
1544
      if (blob_datasize > 0)
1598
         free (blob_data); // if blob data was allocated, free it
1545
         free (blob_data); // if blob data was allocated, free it
1599
   }
1546
   }
1600
 
1547
 
1601
   // sort the filesystem entries by pathname
1548
   // sort the filesystem entries by pathname
1602
   qsort (fsentries, fsentry_count, sizeof (fsentry_t), fsentry_compare_pathnames_cb);
1549
   qsort (&fsentries[1], fsentry_count - 1, sizeof (fsentry_t), fsentry_compare_pathnames_cb);
1603
 
1550
 
1604
   // calculate filesystem entries size
1551
   // calculate filesystem entries size
1605
   imgdir_size = sizeof (image_header);
1552
   imgdir_size = sizeof (image_header);
1606
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
1553
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
1607
   {
1554
   {
Line 1674... Line 1621...
1674
   image_header.script_ino    = image_bootscript_ino; // inode of file for script (here 3)
1621
   image_header.script_ino    = image_bootscript_ino; // inode of file for script (here 3)
1675
   image_header.mountpoint[0] = '/'; // default mountpoint for image ("/" + "\0\0\0")
1622
   image_header.mountpoint[0] = '/'; // default mountpoint for image ("/" + "\0\0\0")
1676
   fwrite (&image_header, sizeof (image_header), 1, fp); // write image header
1623
   fwrite (&image_header, sizeof (image_header), 1, fp); // write image header
1677
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1624
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1678
 
1625
 
1679
   // write empty image directory
1626
   // write image directory (with the wrong file offsets)
1680
   imgdir_offset = ftell (fp);
1627
   imgdir_offset = ftell (fp);
1681
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
1628
   for (fsentry_index = 0; fsentry_index < fsentry_count; fsentry_index++)
1682
      fwrite_fsentry (&fsentries[fsentry_index], fp);
1629
      fwrite_fsentry (&fsentries[fsentry_index], fp); // NOTE: padding is handled in this function
1683
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1630
   PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
1684
 
1631
 
1685
   // is it a bootable image with a kernel file ?
1632
   // is it a bootable image with a kernel file ?
1686
   if ((startupfile_pathname != NULL) && (kernelfile_pathname != NULL))
1633
   if ((startupfile_pathname != NULL) && (kernelfile_pathname != NULL))
1687
   {
1634
   {
Line 1759... Line 1706...
1759
         exit (1);
1706
         exit (1);
1760
      }
1707
      }
1761
      fseek (fp, startupheader_offset, SEEK_SET);
1708
      fseek (fp, startupheader_offset, SEEK_SET);
1762
      fread (blob_data, 1, blob_datasize, fp);
1709
      fread (blob_data, 1, blob_datasize, fp);
1763
      SHA512 (blob_data, blob_datasize, startup_trailer.sha512); // compute SHA512 checksum
1710
      SHA512 (blob_data, blob_datasize, startup_trailer.sha512); // compute SHA512 checksum
-
 
1711
      if (   ( (startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
-
 
1712
          || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
-
 
1713
         is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
-
 
1714
      else
-
 
1715
         is_foreign_endianness = false; // else this header is for the same endianness as us
1764
      startup_trailer.cksum = 0; // compute old checksum
1716
      startup_trailer.cksum = 0; // compute old checksum
1765
      startup_trailer.cksum = update_checksum32 (startup_trailer.cksum, (const uint32_t *) blob_data, blob_datasize);
1717
      startup_trailer.cksum = update_checksum (startup_trailer.cksum, (const uint32_t *) blob_data, blob_datasize, is_foreign_endianness);
1766
      startup_trailer.cksum = update_checksum32 (startup_trailer.cksum, (const uint32_t *) startup_trailer.sha512, sizeof (startup_trailer.sha512));
1718
      startup_trailer.cksum = update_checksum (startup_trailer.cksum, (const uint32_t *) startup_trailer.sha512, sizeof (startup_trailer.sha512), is_foreign_endianness);
1767
      free (blob_data);
1719
      free (blob_data);
1768
 
1720
 
1769
      // rewrite startup trailer with final values
1721
      // rewrite startup trailer with final values
1770
      fseek (fp, startuptrailer_offset, SEEK_SET);
1722
      fseek (fp, startuptrailer_offset, SEEK_SET);
1771
      fwrite (&startup_trailer, sizeof (startup_trailer), 1, fp); // write startup trailer
1723
      fwrite (&startup_trailer, sizeof (startup_trailer), 1, fp); // write startup trailer
Line 1796... Line 1748...
1796
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
1748
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
1797
      is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
1749
      is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
1798
   else
1750
   else
1799
      is_foreign_endianness = false; // else this header is for the same endianness as us
1751
      is_foreign_endianness = false; // else this header is for the same endianness as us
1800
   image_trailer.cksum = 0; // compute old checksum
1752
   image_trailer.cksum = 0; // compute old checksum
1801
   image_trailer.cksum = update_image_checksum (image_trailer.cksum, (const uint32_t *) blob_data, blob_datasize, is_foreign_endianness);
1753
   image_trailer.cksum = update_checksum (image_trailer.cksum, (const uint32_t *) blob_data, blob_datasize, is_foreign_endianness);
1802
   image_trailer.cksum = update_image_checksum (image_trailer.cksum, (const uint32_t *) image_trailer.sha512, sizeof (image_trailer.sha512), is_foreign_endianness);
1754
   image_trailer.cksum = update_checksum (image_trailer.cksum, (const uint32_t *) image_trailer.sha512, sizeof (image_trailer.sha512), is_foreign_endianness);
1803
   free (blob_data);
1755
   free (blob_data);
1804
 
1756
 
1805
   // rewrite image trailer with final checksum values
1757
   // rewrite image trailer with final checksum values
1806
   fseek (fp, imgtrailer_offset, SEEK_SET);
1758
   fseek (fp, imgtrailer_offset, SEEK_SET);
1807
   fwrite (&image_trailer, sizeof (image_trailer), 1, fp); // write image trailer
1759
   fwrite (&image_trailer, sizeof (image_trailer), 1, fp); // write image trailer
Line 1955... Line 1907...
1955
 
1907
 
1956
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
1908
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
1957
         printf ("\n");
1909
         printf ("\n");
1958
         printf ("Startup blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
1910
         printf ("Startup blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
1959
         printf ("   size 0x%zx (%zd) bytes\n", startupfile_blobsize, startupfile_blobsize);
1911
         printf ("   size 0x%zx (%zd) bytes\n", startupfile_blobsize, startupfile_blobsize);
1960
         printf ("   checksum %d\n", update_checksum32 (0, &filedata[current_offset], startupfile_blobsize));
1912
         printf ("   checksum %d\n", update_checksum (0, &filedata[current_offset], startupfile_blobsize, is_foreign_endianness));
1961
 
1913
 
1962
         current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer
1914
         current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer
1963
         printf ("\n");
1915
         printf ("\n");
1964
         printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1));
1916
         printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1));
1965
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
1917
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
1966
         {
1918
         {
1967
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
1919
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
1968
               sprintf (&recorded_sha512[2 * byte_index], "%02x", startup_trailer_v2->sha512[byte_index]);
1920
               sprintf (&recorded_sha512[2 * byte_index], "%02x", startup_trailer_v2->sha512[byte_index]);
1969
            strcpy (computed_sha512, SHA512 (startup_header, (size_t) ((uint8_t *) startup_trailer_v2 - (uint8_t *) startup_header), NULL));
1921
            strcpy (computed_sha512, SHA512 (startup_header, (size_t) ((uint8_t *) startup_trailer_v2 - (uint8_t *) startup_header), NULL));
1970
            recorded_checksum = startup_trailer_v2->cksum;
1922
            recorded_checksum = startup_trailer_v2->cksum;
1971
            computed_checksum = update_checksum32 (0, startup_header, sizeof (startup_header) + startupfile_blobsize + SHA512_DIGEST_LENGTH);
1923
            computed_checksum = update_checksum (0, startup_header, sizeof (startup_header_t) + startupfile_blobsize + SHA512_DIGEST_LENGTH, is_foreign_endianness);
1972
            printf ("    sha512 = %s - %s\n", recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
1924
            printf ("    sha512 = %s - %s\n", recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
1973
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
1925
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
1974
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
1926
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
1975
               printf ("Computed SHA-512: %s\n", computed_sha512);
1927
               printf ("Computed SHA-512: %s\n", computed_sha512);
1976
            if (computed_checksum != recorded_checksum)
1928
            if (computed_checksum != recorded_checksum)
1977
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
1929
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
1978
         }
1930
         }
1979
         else // old v1 trailer
1931
         else // old v1 trailer
1980
         {
1932
         {
1981
            recorded_checksum = startup_trailer_v1->cksum;
1933
            recorded_checksum = startup_trailer_v1->cksum;
1982
            computed_checksum = update_checksum32 (0, startup_header, sizeof (startup_header) + startupfile_blobsize);
1934
            computed_checksum = update_checksum (0, startup_header, sizeof (startup_header) + startupfile_blobsize, is_foreign_endianness);
1983
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
1935
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
1984
            if (computed_checksum != recorded_checksum)
1936
            if (computed_checksum != recorded_checksum)
1985
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
1937
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
1986
         }
1938
         }
1987
 
1939
 
Line 1995... Line 1947...
1995
         image_header = (image_header_t *) &filedata[imageheader_offset];
1947
         image_header = (image_header_t *) &filedata[imageheader_offset];
1996
 
1948
 
1997
         // layout:
1949
         // layout:
1998
         // [IMAGE HEADER]
1950
         // [IMAGE HEADER]
1999
         // [image directory entries]
1951
         // [image directory entries]
2000
         // [file blobs up to KERNEL]
1952
         // [smallest file blobs up to KERNEL]
2001
         // [padding]
1953
         // [padding]
2002
         // [KERNEL]
1954
         // [KERNEL]
2003
         // [file blobs]
1955
         // [rest of file blobs]
2004
         // [IMAGE FOOTER]
1956
         // [IMAGE FOOTER]
2005
 
1957
 
2006
         printf ("\n");
1958
         printf ("\n");
2007
         printf ("Image header at offset %zx (%zd):\n", current_offset, current_offset);
1959
         printf ("Image header at offset %zx (%zd):\n", current_offset, current_offset);
2008
         printf ("   signature    = %02x %02x %02x %02x %02x %02x %02x (\"%.7s\") - good\n", image_header->signature[0], image_header->signature[1], image_header->signature[2], image_header->signature[3], image_header->signature[4], image_header->signature[5], image_header->signature[6], image_header->signature);
1960
         printf ("   signature    = %02x %02x %02x %02x %02x %02x %02x (\"%.7s\") - good\n", image_header->signature[0], image_header->signature[1], image_header->signature[2], image_header->signature[3], image_header->signature[4], image_header->signature[5], image_header->signature[6], image_header->signature);
Line 2045... Line 1997...
2045
 
1997
 
2046
         current_offset += sizeof (image_header_t); // jump over the image header and reach the first directory entry
1998
         current_offset += sizeof (image_header_t); // jump over the image header and reach the first directory entry
2047
 
1999
 
2048
         // there may be padding before the first directory entry
2000
         // there may be padding before the first directory entry
2049
         if (image_header->dir_offset - sizeof (image_header_t) > 0)
2001
         if (image_header->dir_offset - sizeof (image_header_t) > 0)
2050
            hex_printf (&filedata[current_offset], image_header->dir_offset - sizeof (image_header_t), "\n%d padding bytes at offset 0x%zd (%zd):\n", image_header->dir_offset - sizeof (image_header_t), current_offset, current_offset);
2002
            hex_printf (&filedata[current_offset], image_header->dir_offset - sizeof (image_header_t), "\n" "%zd padding bytes at offset 0x%zd (%zd):\n", image_header->dir_offset - sizeof (image_header_t), current_offset, current_offset);
2051
         current_offset += image_header->dir_offset - sizeof (image_header_t); // padding was processed, jump over it
2003
         current_offset += image_header->dir_offset - sizeof (image_header_t); // padding was processed, jump over it
2052
 
2004
 
2053
         // dump all directory entries until the last one included
2005
         // dump all directory entries until the last one included
2054
         fsentries = NULL;
2006
         fsentries = NULL;
2055
         fsentry_count = 0;
2007
         fsentry_count = 0;
2056
         while (&filedata[current_offset] < (uint8_t *) image_header + image_header->hdr_dir_size)
2008
         while (current_offset < imageheader_offset + image_header->hdr_dir_size)
2057
         {
2009
         {
2058
            current_fsentry = (fsentry_t *) &filedata[current_offset];
2010
            current_fsentry = (fsentry_t *) &filedata[current_offset];
2059
 
2011
 
2060
            if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header))
2012
            if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header))
2061
               break; // end padding reached
2013
               break; // end padding reached
Line 2104... Line 2056...
2104
            }
2056
            }
2105
 
2057
 
2106
            current_offset += current_fsentry->header.size;
2058
            current_offset += current_fsentry->header.size;
2107
         }
2059
         }
2108
         if (imageheader_offset + image_header->hdr_dir_size < current_offset + sizeof (current_fsentry->header))
2060
         if (imageheader_offset + image_header->hdr_dir_size < current_offset + sizeof (current_fsentry->header))
2109
            hex_printf (&filedata[current_offset], imageheader_offset + image_header->hdr_dir_size - current_offset, "\n" "%d padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + image_header->hdr_dir_size - current_offset, current_offset, current_offset);
2061
            hex_printf (&filedata[current_offset], imageheader_offset + image_header->hdr_dir_size - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + image_header->hdr_dir_size - current_offset, current_offset, current_offset);
2110
         current_offset += imageheader_offset + image_header->hdr_dir_size - current_offset; // padding was processed, jump over it
2062
         current_offset += imageheader_offset + image_header->hdr_dir_size - current_offset; // padding was processed, jump over it
2111
 
2063
 
2112
         // at this point we are past the directory entries; what is stored now, up to and until the image trailer, is the files' data
2064
         // at this point we are past the directory entries; what is stored now, up to and until the image trailer, is the files' data
2113
         if (fsentry_count > 0)
2065
         if (fsentry_count > 0)
2114
         {
2066
         {
Line 2130... Line 2082...
2130
               fsentry_index = nearest_index;
2082
               fsentry_index = nearest_index;
2131
               current_fsentry = fsentries[fsentry_index]; // quick access to closest fsentry
2083
               current_fsentry = fsentries[fsentry_index]; // quick access to closest fsentry
2132
 
2084
 
2133
               // there may be padding before the file data
2085
               // there may be padding before the file data
2134
               if (imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset > 0)
2086
               if (imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset > 0)
2135
                  hex_printf (&filedata[current_offset], imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, "\n" "%d padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, current_offset, current_offset);
2087
                  hex_printf (&filedata[current_offset], imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, current_offset, current_offset);
2136
               current_offset += imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset; // padding was processed, jump over it
2088
               current_offset += imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset; // padding was processed, jump over it
2137
 
2089
 
2138
               printf ("\n");
2090
               printf ("\n");
2139
               printf ("File data blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2091
               printf ("File data blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2140
               printf ("   corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count);
2092
               printf ("   corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count);
2141
               printf ("   corresponding inode 0x%08x (%d) - %s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "is" : "nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2093
               printf ("   corresponding inode 0x%08x (%d) -%s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "" : " nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2142
               printf ("   corresponding path: \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2094
               printf ("   corresponding path: \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2143
               printf ("   size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size);
2095
               printf ("   size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size);
2144
               printf ("   first 4 bytes: %02x%02x%02x%02x [%c%c%c%c] (%s)\n", (uint8_t) filedata[current_offset + 0], (uint8_t) filedata[current_offset + 1], (uint8_t) filedata[current_offset + 2], (uint8_t) filedata[current_offset + 3], (isprint (filedata[current_offset + 0]) ? filedata[current_offset + 0] : '.'), (isprint (filedata[current_offset + 1]) ? filedata[current_offset + 1] : '.'), (isprint (filedata[current_offset + 2]) ? filedata[current_offset + 2] : '.'), (isprint (filedata[current_offset + 3]) ? filedata[current_offset + 3] : '.'), (memcmp (&filedata[current_offset], "\x7f" "ELF", 4) == 0 ? "ELF binary" : (memcmp (&filedata[current_offset], "#!", 2) == 0 ? "shell script" : "???")));
2096
               printf ("   first 4 bytes: %02x%02x%02x%02x \"%c%c%c%c\" (%s)\n", (uint8_t) filedata[current_offset + 0], (uint8_t) filedata[current_offset + 1], (uint8_t) filedata[current_offset + 2], (uint8_t) filedata[current_offset + 3], (isprint (filedata[current_offset + 0]) ? filedata[current_offset + 0] : '.'), (isprint (filedata[current_offset + 1]) ? filedata[current_offset + 1] : '.'), (isprint (filedata[current_offset + 2]) ? filedata[current_offset + 2] : '.'), (isprint (filedata[current_offset + 3]) ? filedata[current_offset + 3] : '.'), (memcmp (&filedata[current_offset], "\x7f" "ELF", 4) == 0 ? "ELF binary" : (memcmp (&filedata[current_offset], "#!", 2) == 0 ? "shell script" : "data file")));
2145
               printf ("   checksum %d\n", update_image_checksum (0, &filedata[current_offset], current_fsentry->u.file.size, is_foreign_endianness));
2097
               printf ("   checksum %d\n", update_checksum (0, &filedata[current_offset], current_fsentry->u.file.size, is_foreign_endianness));
2146
 
2098
 
2147
               current_offset += current_fsentry->u.file.size; // now jump over this file's data
2099
               current_offset += current_fsentry->u.file.size; // now jump over this file's data
2148
            }
2100
            }
2149
         }
2101
         }
2150
 
2102
 
2151
         // ad this point we're past the last file data, there may be padding before the image trailer
2103
         // ad this point we're past the last file data, there may be padding before the image trailer
2152
         if (imagetrailer_offset - current_offset > 0)
2104
         if (imagetrailer_offset - current_offset > 0)
2153
            hex_printf (&filedata[current_offset], imagetrailer_offset - current_offset, "\n" "%d padding bytes at offset %zx (%zd):\n", imagetrailer_offset - current_offset, current_offset, current_offset);
2105
            hex_printf (&filedata[current_offset], imagetrailer_offset - current_offset, "\n" "%zd padding bytes at offset %zx (%zd):\n", imagetrailer_offset - current_offset, current_offset, current_offset);
2154
         current_offset += imagetrailer_offset - current_offset; // padding was processed, jump over it
2106
         current_offset += imagetrailer_offset - current_offset; // padding was processed, jump over it
2155
 
2107
 
2156
         printf ("\n");
2108
         printf ("\n");
2157
         printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1));
2109
         printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1));
2158
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
2110
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
2159
         {
2111
         {
2160
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
2112
            for (byte_index = 0; byte_index < SHA512_DIGEST_LENGTH; byte_index++)
2161
               sprintf (&recorded_sha512[2 * byte_index], "%02x", image_trailer_v2->sha512[byte_index]);
2113
               sprintf (&recorded_sha512[2 * byte_index], "%02x", image_trailer_v2->sha512[byte_index]);
2162
            strcpy (computed_sha512, SHA512 (image_header, (size_t) ((uint8_t *) image_trailer_v2 - (uint8_t *) image_header), NULL));
2114
            strcpy (computed_sha512, SHA512 (image_header, (size_t) ((uint8_t *) image_trailer_v2 - (uint8_t *) image_header), NULL));
2163
            recorded_checksum = image_trailer_v2->cksum;
2115
            recorded_checksum = image_trailer_v2->cksum;
2164
            computed_checksum = update_image_checksum (0, image_header, /*sizeof (image_header) +*/ image_header->image_size - sizeof (image_trailer_v2_t) + SHA512_DIGEST_LENGTH, is_foreign_endianness);
2116
            computed_checksum = update_checksum (0, image_header, image_header->image_size - sizeof (image_trailer_v2_t) + SHA512_DIGEST_LENGTH, is_foreign_endianness);
2165
            printf ("    sha512 = %s - %s\n", recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
2117
            printf ("    sha512 = %s - %s\n", recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD"));
2166
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2118
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2167
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
2119
            if (strcasecmp (computed_sha512, recorded_sha512) != 0)
2168
               printf ("Computed SHA-512: %s\n", computed_sha512);
2120
               printf ("Computed SHA-512: %s\n", computed_sha512);
2169
            if (computed_checksum != recorded_checksum)
2121
            if (computed_checksum != recorded_checksum)
2170
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2122
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2171
         }
2123
         }
2172
         else // old v1 trailer
2124
         else // old v1 trailer
2173
         {
2125
         {
2174
            recorded_checksum = image_trailer_v1->cksum;
2126
            recorded_checksum = image_trailer_v1->cksum;
2175
            computed_checksum = update_image_checksum (0, image_header, /*sizeof (image_header) +*/ image_header->image_size - sizeof (image_trailer_v1_t), is_foreign_endianness);
2127
            computed_checksum = update_checksum (0, image_header, image_header->image_size - sizeof (image_trailer_v1_t), is_foreign_endianness);
2176
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2128
            printf ("    cksum = 0x%08x (%d) - %s\n", recorded_checksum, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD"));
2177
            if (computed_checksum != recorded_checksum)
2129
            if (computed_checksum != recorded_checksum)
2178
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2130
               printf ("Computed cksum: 0x%08x (%d)\n", computed_checksum, computed_checksum);
2179
         }
2131
         }
2180
 
2132
 
Line 2193... Line 2145...
2193
            break; // if not found, stop scanning
2145
            break; // if not found, stop scanning
2194
 
2146
 
2195
         bootfile_blobsize = byte_index - current_offset;
2147
         bootfile_blobsize = byte_index - current_offset;
2196
         printf ("Boot blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2148
         printf ("Boot blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2197
         printf ("   size 0x%zx (%zd) bytes\n", bootfile_blobsize, bootfile_blobsize);
2149
         printf ("   size 0x%zx (%zd) bytes\n", bootfile_blobsize, bootfile_blobsize);
2198
         printf ("   checksum 0x%08x\n", update_checksum32 (0, &filedata[current_offset], bootfile_blobsize));
2150
         printf ("   checksum 0x%08x\n", update_checksum (0, &filedata[current_offset], bootfile_blobsize, false)); // NOTE: endianness is not known yet -- assume same
2199
 
2151
 
2200
         current_offset = byte_index; // now reach the next segment
2152
         current_offset = byte_index; // now reach the next segment
2201
      }
2153
      }
2202
   }
2154
   }
2203
 
2155
 
2204
   // at this point there's nothing left we're able to parse
2156
   // at this point there's nothing left we're able to parse
2205
   if (current_offset < filesize)
2157
   if (current_offset < filesize)
2206
   {
2158
   {
2207
      printf ("End of identifiable data reached.\n");
2159
      printf ("End of identifiable data reached.\n");
-
 
2160
      if (filesize - current_offset < 16384)
2208
      hex_printf (&filedata[current_offset], filesize - current_offset, "\n" "%d extra bytes at offset %zx (%zd):\n", filesize - current_offset, current_offset, current_offset);
2161
         hex_printf (&filedata[current_offset], filesize - current_offset, "\n" "%zd extra bytes at offset %zx (%zd):\n", filesize - current_offset, current_offset, current_offset);
-
 
2162
      else
-
 
2163
         printf ("\n" "%zd extra bytes at offset %zx (%zd) - size > 16k, not printed\n", filesize - current_offset, current_offset, current_offset);
2209
   }
2164
   }
2210
 
2165
 
2211
   printf ("End of file reached at offset 0x%zx (%zd)\n", filesize, filesize);
2166
   printf ("End of file reached at offset 0x%zx (%zd)\n", filesize, filesize);
2212
   printf ("IFS dissecation complete.\n");
2167
   printf ("IFS dissecation complete.\n");
2213
   return (0);
2168
   return (0);