Subversion Repositories QNX 8.QNX8 IFS tool

Rev

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

Rev 16 Rev 26
Line 21... Line 21...
21
#include <unistd.h>
21
#include <unistd.h>
22
#include <utime.h>
22
#include <utime.h>
23
#endif // _MSC_VER
23
#endif // _MSC_VER
24
 
24
 
25
// own includes
25
// own includes
-
 
26
#include "ucl/ucl.h"
-
 
27
#include "minilzo.h"
26
#include "buffer.h"
28
#include "buffer.h"
27
#include "sha512.h"
29
#include "sha512.h"
28
#include "ifsfile.h"
30
#include "ifsfile.h"
29
#include "elffile.h"
31
#include "elffile.h"
30
#include "utility.h"
32
#include "utility.h"
Line 33... Line 35...
33
// imported global variables
35
// imported global variables
34
extern int verbose_level; // from ifstool.c
36
extern int verbose_level; // from ifstool.c
35
 
37
 
36
 
38
 
37
// exported function prototypes
39
// exported function prototypes
38
int dump_ifs_info (const char *ifs_pathname, bool want_everything); // dumps detailed info about a particular IFS file on the standard output, returns 0 on success and >0 on error
40
int dump_ifs_info (const char *ifs_pathname, bool want_everything, bool hide_filename); // dumps detailed info about a particular IFS file on the standard output, returns 0 on success and >0 on error
39
int dump_ifs_contents (const char *ifs_pathname, const char *outdir); // dumps the IFS filesystem contents in outdir, returns 0 on success and >0 on error
41
int dump_ifs_contents (const char *ifs_pathname, const char *outdir); // dumps the IFS filesystem contents in outdir, returns 0 on success and >0 on error
40
int dump_file_hex (const char *pathname); // hexdump the content of pathname, returns 0 on success and != 0 on error
42
int dump_file_hex (const char *pathname); // hexdump the content of pathname, returns 0 on success and != 0 on error
41
 
43
 
42
 
44
 
43
// prototypes of local functions
45
// prototypes of local functions
Line 149... Line 151...
149
      }
151
      }
150
   return (outstr);
152
   return (outstr);
151
}
153
}
152
 
154
 
153
 
155
 
154
int dump_ifs_info (const char *ifs_pathname, bool want_everything)
156
int dump_ifs_info (const char *ifs_pathname, bool want_everything, bool hide_filename)
155
{
157
{
156
   #define hex_printf(buf,size,...) do { \
158
   #define hex_printf(buf,size,...) do { \
157
      if (want_everything || ((size) <= 16 * 1024)) /* only print when it's not too big (up to 16 kb) */\
159
      if (want_everything || ((size) <= 16 * 1024)) /* only print when it's not too big (up to 16 kb) */\
158
         hex_fprintf (stdout, (buf), (size), 16, __VA_ARGS__); /* use 16 columns in hex output to stdout */ \
160
         hex_fprintf (stdout, (buf), (size), 16, __VA_ARGS__); /* use 16 columns in hex output to stdout */ \
159
      else { \
161
      else { \
Line 195... Line 197...
195
   image_trailer_v2_t *image_trailer_v2 = NULL;
197
   image_trailer_v2_t *image_trailer_v2 = NULL;
196
   size_t imagetrailer_offset = 0;
198
   size_t imagetrailer_offset = 0;
197
   fsentry_t **fsentries = NULL; // mallocated
199
   fsentry_t **fsentries = NULL; // mallocated
198
   size_t fsentry_count = 0;
200
   size_t fsentry_count = 0;
199
   fsentry_t *current_fsentry = NULL;
201
   fsentry_t *current_fsentry = NULL;
-
 
202
   buffer_t decompression_dst;
200
   char recorded_sha512[2 * SHA512_DIGEST_LENGTH + 1] = "";
203
   char recorded_sha512[2 * SHA512_DIGEST_LENGTH + 1] = "";
201
   char computed_sha512[2 * SHA512_DIGEST_LENGTH + 1] = "";
204
   char computed_sha512[2 * SHA512_DIGEST_LENGTH + 1] = "";
202
   size_t startupfile_blobsize = 0;
205
   size_t startupfile_blobsize = 0;
-
 
206
   size_t compressed_blocksize;
203
   void *reallocated_ptr;
207
   void *reallocated_ptr;
204
   bool is_foreign_endianness;
208
   bool is_foreign_endianness;
-
 
209
   uint8_t *decompressor_out;
-
 
210
   uint8_t *decompressor_in;
-
 
211
   size_t decompressor_outlen;
205
   size_t bootfile_blobsize = 0;
212
   size_t bootfile_blobsize = 0;
206
   size_t current_offset;
213
   size_t current_offset;
207
   size_t fsentry_index;
214
   size_t fsentry_index;
208
   size_t nearest_distance;
215
   size_t nearest_distance;
209
   size_t nearest_index;
216
   size_t nearest_index;
210
   size_t byte_index;
217
   size_t byte_index;
211
   uint32_t recorded_checksum;
218
   uint32_t recorded_checksum;
212
   uint32_t computed_checksum;
219
   uint32_t computed_checksum;
213
   buffer_t file;
220
   buffer_t file;
214
   time_t mtime;
221
   time_t mtime;
-
 
222
   int cf;
215
 
223
 
216
   // open and read IFS file
224
   // open and read IFS file
217
   if (!Buffer_ReadFromFile (&file, ifs_pathname))
225
   if (!Buffer_ReadFromFile (&file, ifs_pathname))
218
      DIE_WITH_EXITCODE (1, "can't open \"%s\" for reading: %s", ifs_pathname, strerror (errno));
226
      DIE_WITH_EXITCODE (1, "can't open \"%s\" for reading: %s", ifs_pathname, strerror (errno));
219
 
227
 
220
   printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
228
   printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
-
 
229
   if (hide_filename)
-
 
230
      printf ("IFS file - size 0x%zx (%zd) bytes\n", file.size, file.size);
-
 
231
   else
221
   printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, file.size, file.size);
232
      printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, file.size, file.size);
222
 
233
 
223
   // parse file from start to end
234
   // parse file from start to end
224
   current_offset = 0;
235
   current_offset = 0;
-
 
236
   cf = STARTUP_HDR_FLAGS1_COMPRESS_NONE;
225
   for (;;)
237
   for (;;)
226
   {
238
   {
227
      // does a startup header start here ?
239
      // does a startup header start here ?
-
 
240
      if ((current_offset + sizeof (startup_header_t) < file.size)
-
 
241
          && (startup_header == NULL)
228
      if ((current_offset + sizeof (startup_header_t) < file.size) && (memcmp (&file.bytes[current_offset], "\xeb\x7e\xff\x00", 4) == 0))
242
          && (memcmp (&file.bytes[current_offset], "\xeb\x7e\xff\x00", 4) == 0))
229
      {
243
      {
230
         startupheader_offset = current_offset;
244
         startupheader_offset = current_offset;
231
         startup_header = (startup_header_t *) &file.bytes[startupheader_offset];
245
         startup_header = (startup_header_t *) &file.bytes[startupheader_offset];
232
 
246
 
233
         // layout:
247
         // layout:
Line 237... Line 251...
237
 
251
 
238
         printf ("\n");
252
         printf ("\n");
239
         printf ("Startup header at offset 0x%zx (%zd):\n", current_offset, current_offset);
253
         printf ("Startup header at offset 0x%zx (%zd):\n", current_offset, current_offset);
240
         printf ("   signature     = %02x %02x %02x %02x - good\n", startup_header->signature[0], startup_header->signature[1], startup_header->signature[2], startup_header->signature[3]);
254
         printf ("   signature     = %02x %02x %02x %02x - good\n", startup_header->signature[0], startup_header->signature[1], startup_header->signature[2], startup_header->signature[3]);
241
         printf ("   version       = 0x%04x (%d) - %s\n", startup_header->version, startup_header->version, (startup_header->version == 1 ? "looks good" : "???"));
255
         printf ("   version       = 0x%04x (%d) - %s\n", startup_header->version, startup_header->version, (startup_header->version == 1 ? "looks good" : "???"));
-
 
256
         cf = startup_header->flags1 & STARTUP_HDR_FLAGS1_COMPRESS_MASK;
242
         printf ("   flags1        = 0x%02x (%s)\n", startup_header->flags1, describe_uint8 (startup_header->flags1, startupheader_flags1_strings));
257
         printf ("   flags1        = 0x%02x (%s) - %s\n", startup_header->flags1, describe_uint8 (startup_header->flags1, startupheader_flags1_strings), (cf == STARTUP_HDR_FLAGS1_COMPRESS_NONE ? "uncompressed image" : (cf == STARTUP_HDR_FLAGS1_COMPRESS_ZLIB ? "Zlib-compressed image (non-bootable)" : (cf == STARTUP_HDR_FLAGS1_COMPRESS_LZO ? "LZO-compressed image" : (cf == STARTUP_HDR_FLAGS1_COMPRESS_UCL ? "UCL-compressed image" : "compressed image (unknown algorithm)")))));
243
         printf ("   flags2        = 0x%02x (%s) - %s\n", startup_header->flags2, BINARY (startup_header->flags2), (startup_header->flags2 == 0 ? "looks good" : "???"));
258
         printf ("   flags2        = 0x%02x (%s) - %s\n", startup_header->flags2, BINARY (startup_header->flags2), (startup_header->flags2 == 0 ? "looks good" : "???"));
244
         printf ("   header_size   = 0x%04x (%d) - %s\n", startup_header->header_size, startup_header->header_size, (startup_header->header_size == sizeof (startup_header_t) ? "looks good" : "BAD"));
259
         printf ("   header_size   = 0x%04x (%d) - %s\n", startup_header->header_size, startup_header->header_size, (startup_header->header_size == sizeof (startup_header_t) ? "looks good" : "BAD"));
245
         printf ("   machine       = 0x%04x (%d) - %s\n", startup_header->machine, startup_header->machine, (startup_header->machine == ELF_MACHINE_X86_64 ? "x86_64" : (startup_header->machine == ELF_MACHINE_AARCH64 ? "aarch64" : "unknown")));
260
         printf ("   machine       = 0x%04x (%d) - %s\n", startup_header->machine, startup_header->machine, (startup_header->machine == ELF_MACHINE_X86_64 ? "x86_64" : (startup_header->machine == ELF_MACHINE_AARCH64 ? "aarch64" : "unknown")));
246
         printf ("   startup_vaddr = 0x%08x (%d) - virtual address to transfer to after IPL is done\n", startup_header->startup_vaddr, startup_header->startup_vaddr);
261
         printf ("   startup_vaddr = 0x%08x (%d) - virtual address to transfer to after IPL is done\n", startup_header->startup_vaddr, startup_header->startup_vaddr);
247
         printf ("   paddr_bias    = 0x%08x (%d) - value to add to physical addresses to get an indirectable pointer value\n", startup_header->paddr_bias, startup_header->paddr_bias);
262
         printf ("   paddr_bias    = 0x%08x (%d) - value to add to physical addresses to get an indirectable pointer value\n", startup_header->paddr_bias, startup_header->paddr_bias);
248
         printf ("   image_paddr   = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_paddr);
263
         printf ("   image_paddr   = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_paddr);
249
         printf ("   ram_paddr     = 0x%08x (%d) - physical address of RAM to copy image to (startup_size bytes copied)\n", startup_header->ram_paddr, startup_header->ram_paddr);
264
         printf ("   ram_paddr     = 0x%08x (%d) - physical address of RAM to copy image to (startup_size bytes copied)\n", startup_header->ram_paddr, startup_header->ram_paddr);
250
         printf ("   ram_size      = 0x%08x (%d) - amount of RAM used by the startup program and executables in the fs\n", startup_header->ram_size, startup_header->ram_size);
265
         printf ("   ram_size      = 0x%08x (%d) - amount of RAM used by the startup program and executables in the fs\n", startup_header->ram_size, startup_header->ram_size);
251
         printf ("   startup_size  = 0x%08x (%d) - size of startup (never compressed) - %s\n", startup_header->startup_size, startup_header->startup_size, (current_offset + sizeof (image_header_t) + startup_header->startup_size + (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)) < file.size ? "looks good" : "BAD (IFS file too short)"));
266
         printf ("   startup_size  = 0x%08x (%d) - size of startup (never compressed) - %s\n", startup_header->startup_size, startup_header->startup_size, (current_offset + sizeof (image_header_t) + startup_header->startup_size + (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)) < file.size ? "looks good" : "BAD (IFS file too short)"));
252
         printf ("   stored_size   = 0x%08x (%d) - size of entire image - %s\n", startup_header->stored_size, startup_header->stored_size, (startup_header->stored_size == startup_header->ram_size ? "looks good" : "???"));
267
         printf ("   stored_size   = 0x%08x (%d) - stored size of image - %s\n", startup_header->stored_size, startup_header->stored_size, (startup_header->stored_size <= startup_header->ram_size ? "looks good" : "???"));
253
         printf ("   imagefs_paddr = 0x%08x (%d) - set by IPL when startup runs - %s\n", startup_header->imagefs_paddr, startup_header->imagefs_paddr, (startup_header->imagefs_paddr == 0 ? "looks good" : "??? should be zero"));
268
         printf ("   imagefs_paddr = 0x%08x (%d) - set by IPL when startup runs - %s\n", startup_header->imagefs_paddr, startup_header->imagefs_paddr, (startup_header->imagefs_paddr == 0 ? "looks good" : "??? should be zero"));
254
         printf ("   imagefs_size  = 0x%08x (%d) - size of uncompressed imagefs\n", startup_header->imagefs_size, startup_header->imagefs_size);
269
         printf ("   imagefs_size  = 0x%08x (%d) - size of uncompressed imagefs\n", startup_header->imagefs_size, startup_header->imagefs_size);
255
         printf ("   preboot_size  = 0x%04x (%d) - size of loaded before header - %s\n", startup_header->preboot_size, startup_header->preboot_size, (startup_header->preboot_size == current_offset ? "looks good" : "???"));
270
         printf ("   preboot_size  = 0x%04x (%d) - size of loaded before header - %s\n", startup_header->preboot_size, startup_header->preboot_size, (startup_header->preboot_size == current_offset ? "looks good" : "???"));
256
         printf ("   zero0         = 0x%04x (%d) - zeros - %s\n", startup_header->zero0, startup_header->zero0, (startup_header->zero0 == 0 ? "looks good" : "??? should be zero"));
271
         printf ("   zero0         = 0x%04x (%d) - zeros - %s\n", startup_header->zero0, startup_header->zero0, (startup_header->zero0 == 0 ? "looks good" : "??? should be zero"));
257
         printf ("   zero[0]       = 0x%08x (%d) - zeros - %s\n", startup_header->zero[0], startup_header->zero[0], (startup_header->zero[0] == 0 ? "looks good" : "??? should be zero"));
272
         printf ("   zero[0]       = 0x%08x (%d) - zeros - %s\n", startup_header->zero[0], startup_header->zero[0], (startup_header->zero[0] == 0 ? "looks good" : "??? should be zero"));
Line 320... Line 335...
320
 
335
 
321
         current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment
336
         current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment
322
      }
337
      }
323
 
338
 
324
      // else does an image header start here ?
339
      // else does an image header start here ?
-
 
340
      else if ((current_offset + sizeof (image_header_t) < file.size)
-
 
341
               && (image_header == NULL)
325
      else if ((current_offset + sizeof (image_header_t) < file.size) && (memcmp (&file.bytes[current_offset], "imagefs", 7) == 0))
342
               && (   ((cf == STARTUP_HDR_FLAGS1_COMPRESS_NONE) && (memcmp (&file.bytes[current_offset], "imagefs", 7) == 0))
-
 
343
                   || (cf != STARTUP_HDR_FLAGS1_COMPRESS_NONE) && (startup_header->imagefs_size > 0)))
326
      {
344
      {
327
         imageheader_offset = current_offset;
345
         imageheader_offset = current_offset;
328
         image_header = (image_header_t *) &file.bytes[imageheader_offset];
346
         image_header = (image_header_t *) &file.bytes[imageheader_offset];
-
 
347
 
-
 
348
         // should we decompress it ?
-
 
349
         if (cf != STARTUP_HDR_FLAGS1_COMPRESS_NONE)
-
 
350
         {
-
 
351
            // it appears mkifs compresses data in blocks, prefixed by 2-byte block size in BIG ENDIAN
-
 
352
            Buffer_InitWithSize (&decompression_dst, startup_header->imagefs_size * 11 / 10); // mallocate and add 10% for safety
-
 
353
            decompression_dst.size = 0;
-
 
354
 
-
 
355
            if (cf == STARTUP_HDR_FLAGS1_COMPRESS_UCL)
-
 
356
               ASSERT (ucl_init () == UCL_E_OK, "UCL library initialization failed -- please recompile this tool with less aggressive optimizations");
-
 
357
            else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_LZO)
-
 
358
               ASSERT (lzo_init () == LZO_E_OK, "LZO library initialization failed -- please recompile this tool with less aggressive optimizations");
-
 
359
            else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_ZLIB)
-
 
360
            {
-
 
361
               LOG_WARNING ("unimplemented compression scheme: zlib (FIXME)");
-
 
362
               goto endofdata;
-
 
363
            }
-
 
364
            else
-
 
365
            {
-
 
366
               LOG_WARNING ("unsupported compression flags: 0x%2x", cf);
-
 
367
               goto endofdata;
-
 
368
            }
-
 
369
 
-
 
370
            // run the compressed payload (the imagefs) through the right decompression algorithm
-
 
371
            for (;;)
-
 
372
            {
-
 
373
               compressed_blocksize = (file.bytes[current_offset + 0] << 8) | (file.bytes[current_offset + 1] << 0); // read block size word (in big engian)
-
 
374
               current_offset += 2; // skip it
-
 
375
               if (compressed_blocksize == 0)
-
 
376
                  break; // a nil block size means end of stream is reached
-
 
377
               LOG_DEBUG ("about to decompress block of %zd bytes", compressed_blocksize);
-
 
378
               decompressor_in = &file.bytes[current_offset];
-
 
379
               decompressor_out = &decompression_dst.bytes[decompression_dst.size];
-
 
380
               decompressor_outlen = 0;
-
 
381
 
-
 
382
               if (cf == STARTUP_HDR_FLAGS1_COMPRESS_UCL)
-
 
383
               {
-
 
384
                  // UCL compression. NOTE: the decompressor function used in startup-x86 is "ucl_nrv2b_decompress_8 / ucl_nrv2b_decompress_le16 / ucl_nrv2b_decompress_le32"
-
 
385
                  static ucl_uint ucl_outlen; // have a different variable because of pointer size mismatch
-
 
386
                  if (ucl_nrv2b_decompress_8 (decompressor_in, (ucl_uint) compressed_blocksize, decompressor_out, &ucl_outlen, NULL) != UCL_E_OK)
-
 
387
                  {
-
 
388
                     LOG_WARNING ("this IFS file is corrupted (UCL decompression failed)");
-
 
389
                     goto endofdata;
-
 
390
                  }
-
 
391
                  decompressor_outlen = ucl_outlen;
-
 
392
               }
-
 
393
               else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_LZO)
-
 
394
               {
-
 
395
                  // LZO decompression. NOTE: mkifs uses the full LZO package, whereas I use minilzo.
-
 
396
                  static lzo_uint lzo_outlen; // have a different variable because of pointer size mismatch
-
 
397
                  if (lzo1x_decompress (decompressor_in, (lzo_uint) compressed_blocksize, decompressor_out, &lzo_outlen, NULL) != LZO_E_OK)
-
 
398
                  {
-
 
399
                     LOG_WARNING ("this IFS file is corrupted (UCL decompression failed)");
-
 
400
                     goto endofdata;
-
 
401
                  }
-
 
402
                  decompressor_outlen = lzo_outlen;
-
 
403
               }
-
 
404
               else if (cf == STARTUP_HDR_FLAGS1_COMPRESS_ZLIB)
-
 
405
                  ; // TODO
-
 
406
 
-
 
407
               current_offset += compressed_blocksize;
-
 
408
               decompression_dst.size += decompressor_outlen;
-
 
409
            }
-
 
410
 
-
 
411
            LOG_INFO ("decompressed %zd bytes into %zd bytes\n", file.size - imageheader_offset, decompression_dst.size);
-
 
412
 
-
 
413
            // now place the decompressed buffer in the payload at the imagefs offset
-
 
414
            ASSERT_WITH_ERRNO (Buffer_WriteBufferAt (&file, imageheader_offset, &decompression_dst));
-
 
415
            current_offset = imageheader_offset; // jump back to where we put the uncompressed data
-
 
416
            file.size = imageheader_offset + decompression_dst.size; // update IFS data size
-
 
417
 
-
 
418
            startup_header = (startup_header_t *) &file.bytes[startupheader_offset]; // fix the pointers that might have changed
-
 
419
            if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
-
 
420
               startup_trailer_v2 = (startup_trailer_v2_t *) &file.bytes[startuptrailer_offset];
-
 
421
            else // old V1 trailer
-
 
422
               startup_trailer_v1 = (startup_trailer_v1_t *) &file.bytes[startuptrailer_offset];
-
 
423
            image_header = (image_header_t *) &file.bytes[imageheader_offset]; // fix the pointers that might have changed
-
 
424
         }
329
 
425
 
330
         // layout:
426
         // layout:
331
         // [IMAGE HEADER]
427
         // [IMAGE HEADER]
332
         // [image directory entries]
428
         // [image directory entries]
333
         // [smallest file blobs up to KERNEL]
429
         // [smallest file blobs up to KERNEL]