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 |
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 |
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 |
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 ( |
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 |
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 = |
1717 | startup_trailer.cksum = update_checksum (startup_trailer.cksum, (const uint32_t *) blob_data, blob_datasize, is_foreign_endianness); |
1766 | startup_trailer.cksum = |
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 = |
1753 | image_trailer.cksum = update_checksum (image_trailer.cksum, (const uint32_t *) blob_data, blob_datasize, is_foreign_endianness); |
1802 | image_trailer.cksum = |
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", |
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 = |
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 = |
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 |
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 ( |
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" " |
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" " |
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) - |
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 *) ¤t_fsentry->u.file.path); // convert from pointer to char array |
2094 | printf (" corresponding path: \"%s\"\n", (char *) ¤t_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 |
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", |
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" " |
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 = |
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 = |
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", |
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" " |
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); |