Subversion Repositories QNX 8.QNX8 IFS tool

Rev

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

Rev 25 Rev 26
Line 28... Line 28...
28
#include <dirent.h>
28
#include <dirent.h>
29
#include <utime.h>
29
#include <utime.h>
30
#endif // _MSC_VER
30
#endif // _MSC_VER
31
 
31
 
32
// own includes
32
// own includes
-
 
33
#include "ucl/ucl.h"
-
 
34
#include "minilzo.h"
33
#include "buffer.h"
35
#include "buffer.h"
34
#include "sha512.h"
36
#include "sha512.h"
35
#include "elffile.h"
37
#include "elffile.h"
36
#include "ifsfile.h"
38
#include "ifsfile.h"
37
#include "utility.h"
39
#include "utility.h"
Line 130... Line 132...
130
static uint32_t image_maxsize = UINT32_MAX; // default image max size (no limit)
132
static uint32_t image_maxsize = UINT32_MAX; // default image max size (no limit)
131
static uint32_t image_totalsize = 0; // image total size, measured once all the blocks have been written to the output IFS file
133
static uint32_t image_totalsize = 0; // image total size, measured once all the blocks have been written to the output IFS file
132
static uint32_t image_align = 4; // default image alignment, as per QNX docs
134
static uint32_t image_align = 4; // default image alignment, as per QNX docs
133
static uint32_t image_kernel_ino = 0;
135
static uint32_t image_kernel_ino = 0;
134
static uint32_t image_bootscript_ino = 0;
136
static uint32_t image_bootscript_ino = 0;
-
 
137
static int startup_header_compression_flag = STARTUP_HDR_FLAGS1_COMPRESS_NONE;
135
#if defined(__x86_64__)
138
#if defined(__x86_64__)
136
static char image_processor[16] = "x86_64"; // default CPU type for which this image is built, either "x86_64" or "aarch64le" (will be used to find out the right include paths under $QNX_TARGET)
139
static char image_processor[16] = "x86_64"; // default CPU type for which this image is built, either "x86_64" or "aarch64le" (will be used to find out the right include paths under $QNX_TARGET)
137
static char image_processor_base[16] = "x86_64"; // default base CPU type for which this image is built, either "x86_64" or "aarch64le" (will be used to find out the right include paths under $QNX_TARGET)
140
static char image_processor_base[16] = "x86_64"; // default base CPU type for which this image is built, either "x86_64" or "aarch64le" (will be used to find out the right include paths under $QNX_TARGET)
138
#elif defined(__aarch64__)
141
#elif defined(__aarch64__)
139
static char image_processor[16] = "aarch64le"; // default CPU type for which this image is built, either "x86_64" or "aarch64le" (will be used to find out the right include paths under $QNX_TARGET)
142
static char image_processor[16] = "aarch64le"; // default CPU type for which this image is built, either "x86_64" or "aarch64le" (will be used to find out the right include paths under $QNX_TARGET)
Line 175... Line 178...
175
static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames
178
static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames
176
static void parse_line (FILE *buildfile_fp, char *line_buffer, fsentry_t **fsentries, size_t *fsentry_count, parms_t *default_parms); // parses a line in the build file and make the relevant changes to the fsentries array
179
static void parse_line (FILE *buildfile_fp, char *line_buffer, fsentry_t **fsentries, size_t *fsentry_count, parms_t *default_parms); // parses a line in the build file and make the relevant changes to the fsentries array
177
 
180
 
178
 
181
 
179
// imported function prototypes
182
// imported function prototypes
180
extern int dump_ifs_info (const char *ifs_pathname, bool want_everything); // [implemented in ifsdump.c] dumps detailed info about a particular IFS file on the standard output, returns 0 on success and >0 on error
183
extern int dump_ifs_info (const char *ifs_pathname, bool want_everything, bool hide_filename); // [implemented in ifsdump.c] dumps detailed info about a particular IFS file on the standard output, returns 0 on success and >0 on error
181
extern int dump_ifs_contents (const char *ifs_pathname, const char *outdir); // [implemented in ifsdump.c] dumps the IFS filesystem contents in outdir, returns 0 on success and >0 on error
184
extern int dump_ifs_contents (const char *ifs_pathname, const char *outdir); // [implemented in ifsdump.c] dumps the IFS filesystem contents in outdir, returns 0 on success and >0 on error
182
extern int dump_file_hex (const char *pathname); // [implemented in ifsdump.c] dumps the contents of pathname to stdout in mixed hexadecimal + ASCII (hex editor) format
185
extern int dump_file_hex (const char *pathname); // [implemented in ifsdump.c] dumps the contents of pathname to stdout in mixed hexadecimal + ASCII (hex editor) format
183
 
186
 
184
 
187
 
185
int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness)
188
int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness)
Line 1775... Line 1778...
1775
               }
1778
               }
1776
               utc_time.tm_mon--; // convert month from [1-12] to [0-11]
1779
               utc_time.tm_mon--; // convert month from [1-12] to [0-11]
1777
               entry_parms.mtime = (uint32_t) mktime (&utc_time);
1780
               entry_parms.mtime = (uint32_t) mktime (&utc_time);
1778
            }
1781
            }
1779
         }
1782
         }
-
 
1783
         else if (strncmp (token, "compress=", 9) == 0) { REACH_TOKEN_VALUE (); startup_header_compression_flag = (strcmp (value, "1") == 0 ? STARTUP_HDR_FLAGS1_COMPRESS_ZLIB : (strcmp (value, "2") == 0 ? STARTUP_HDR_FLAGS1_COMPRESS_LZO : STARTUP_HDR_FLAGS1_COMPRESS_UCL)); }
-
 
1784
         else if (strcmp (token, "+compress")   == 0) startup_header_compression_flag = STARTUP_HDR_FLAGS1_COMPRESS_UCL;
-
 
1785
         else if (strcmp (token, "-compress")   == 0) startup_header_compression_flag = STARTUP_HDR_FLAGS1_COMPRESS_NONE;
1780
         else if (strcmp (token, "+script")     == 0) entry_parms.is_compiled_bootscript         = true;
1786
         else if (strcmp (token, "+script")     == 0) entry_parms.is_compiled_bootscript         = true;
1781
         else if (strcmp (token, "-script")     == 0) entry_parms.is_compiled_bootscript         = false;
1787
         else if (strcmp (token, "-script")     == 0) entry_parms.is_compiled_bootscript         = false;
1782
         else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks         = true;
1788
         else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks         = true;
1783
         else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks         = false;
1789
         else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks         = false;
1784
         else if (strcmp (token, "+autolink")   == 0) entry_parms.should_autosymlink_dylib       = true;
1790
         else if (strcmp (token, "+autolink")   == 0) entry_parms.should_autosymlink_dylib       = true;
Line 2015... Line 2021...
2015
   char path_in_ifs[MAXPATHLEN] = "";
2021
   char path_in_ifs[MAXPATHLEN] = "";
2016
   const char *ifs_pathname = NULL;
2022
   const char *ifs_pathname = NULL;
2017
   const char *rootdir_pathname = NULL;
2023
   const char *rootdir_pathname = NULL;
2018
   const fsentry_t *fsentry;
2024
   const fsentry_t *fsentry;
2019
   void *reallocated_ptr;
2025
   void *reallocated_ptr;
-
 
2026
   buffer_t compressed_imagefs;
-
 
2027
   uint8_t *compressor_out;
-
 
2028
   uint8_t *compressor_in;
-
 
2029
   size_t compressor_outlen;
-
 
2030
   size_t compressor_inlen;
2020
   size_t reallocated_size;
2031
   size_t reallocated_size;
2021
   size_t available_space;
2032
   size_t available_space;
2022
   size_t fsentry_index;
2033
   size_t fsentry_index;
2023
   size_t largest_index;
2034
   size_t largest_index;
2024
   size_t largest_size;
2035
   size_t largest_size;
2025
   size_t imgdir_size;
2036
   size_t imgdir_size;
2026
   size_t curr_offset;
2037
   size_t curr_offset;
-
 
2038
   size_t remaining_len;
2027
   ifs_t ifs = { 0 };
2039
   ifs_t ifs = { 0 };
2028
   int32_t checksum;
2040
   int32_t checksum;
2029
   char *first_pathname = NULL;
2041
   char *first_pathname = NULL;
2030
   char *second_pathname = NULL;
2042
   char *second_pathname = NULL;
2031
   char *third_pathname = NULL;
2043
   char *third_pathname = NULL;
Line 2038... Line 2050...
2038
   bool want_everything = false;
2050
   bool want_everything = false;
2039
   bool want_help = false;
2051
   bool want_help = false;
2040
   bool want_dump = false;
2052
   bool want_dump = false;
2041
   bool want_strip = false;
2053
   bool want_strip = false;
2042
   bool want_hexdump = false;
2054
   bool want_hexdump = false;
-
 
2055
   bool hide_filename = false;
2043
   bool is_foreign_endianness;
2056
   bool is_foreign_endianness;
-
 
2057
   int compressor_ret;
2044
   FILE *buildfile_fp;
2058
   FILE *buildfile_fp;
2045
 
2059
 
2046
   // initialize stuff
2060
   // initialize stuff
2047
   saved_ELF_sections = (char **) malloc (4 * sizeof (char *));
2061
   saved_ELF_sections = (char **) malloc (4 * sizeof (char *));
2048
   ASSERT_WITH_ERRNO (saved_ELF_sections);
2062
   ASSERT_WITH_ERRNO (saved_ELF_sections);
Line 2091... Line 2105...
2091
         want_hexdump = true;
2105
         want_hexdump = true;
2092
      else if (strcmp (argv[arg_index], "--strip") == 0)
2106
      else if (strcmp (argv[arg_index], "--strip") == 0)
2093
         want_strip = true;
2107
         want_strip = true;
2094
      else if (strcmp (argv[arg_index], "--everything") == 0)
2108
      else if (strcmp (argv[arg_index], "--everything") == 0)
2095
         want_everything = true;
2109
         want_everything = true;
-
 
2110
      else if (strcmp (argv[arg_index], "--hide-filename") == 0)
-
 
2111
         hide_filename = true;
2096
      else if (strncmp (argv[arg_index], "-v", 2) == 0) // -v[....]
2112
      else if (strncmp (argv[arg_index], "-v", 2) == 0) // -v[....]
2097
         verbose_level += (int) strlen (argv[arg_index] + 1); // increase verbosity by the number of characters in this flag
2113
         verbose_level += (int) strlen (argv[arg_index] + 1); // increase verbosity by the number of characters in this flag
2098
      else if ((strcmp (argv[arg_index], "-l") == 0) && (arg_index + 1 < argc))
2114
      else if ((strcmp (argv[arg_index], "-l") == 0) && (arg_index + 1 < argc))
2099
         arg_index++; // these args will be parsed once the build file is open
2115
         arg_index++; // these args will be parsed once the build file is open
2100
      else if ((strcmp (argv[arg_index], "-r") == 0) && (arg_index + 1 < argc))
2116
      else if ((strcmp (argv[arg_index], "-r") == 0) && (arg_index + 1 < argc))
Line 2133... Line 2149...
2133
      fprintf (out, "ifstool - QNX in-kernel filesystem creation utility by Pierre-Marie Baty <pm@pmbaty.com>\n");
2149
      fprintf (out, "ifstool - QNX in-kernel filesystem creation utility by Pierre-Marie Baty <pm@pmbaty.com>\n");
2134
      fprintf (out, "          version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
2150
      fprintf (out, "          version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
2135
      if (!want_help)
2151
      if (!want_help)
2136
         fprintf (out, "error: missing parameters\n");
2152
         fprintf (out, "error: missing parameters\n");
2137
      fprintf (out, "usage:\n");
2153
      fprintf (out, "usage:\n");
2138
      fprintf (out, "    ifstool --info [--everything] <ifs file>\n");
2154
      fprintf (out, "    ifstool --info [--everything] [--hide-filename] <ifs file>\n");
2139
      fprintf (out, "    ifstool --dump [--outdir <path>] <ifs file>\n");
2155
      fprintf (out, "    ifstool --dump [--outdir <path>] <ifs file>\n");
2140
      fprintf (out, "    ifstool --strip [--outfile <pathname>] <ELF file>\n");
2156
      fprintf (out, "    ifstool --strip [--outfile <pathname>] <ELF file>\n");
2141
      fprintf (out, "    ifstool [-?|--help]\n");
2157
      fprintf (out, "    ifstool [-?|--help]\n");
2142
      // mkifs [-?] [-l inputline] [-n[n]] [-o directory] [-p patchfile] [-r rootdir] [-s section] [-v] [buildfile] [directory] [outputfile]
2158
      // mkifs [-?] [-l inputline] [-n[n]] [-o directory] [-p patchfile] [-r rootdir] [-s section] [-v] [buildfile] [directory] [outputfile]
2143
      fprintf (out, "    ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kerneloffs <fileoffs>] [-a suffix] [-l inputline] [-n[n]] [-r rootdir] [-s section] [-v[...]] [buildfile] [directory] [outputfile]\n");
2159
      fprintf (out, "    ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kerneloffs <fileoffs>] [-a suffix] [-l inputline] [-n[n]] [-r rootdir] [-s section] [-v[...]] [buildfile] [directory] [outputfile]\n");
Line 2212... Line 2228...
2212
      exit (want_help ? 0 : 1);
2228
      exit (want_help ? 0 : 1);
2213
   }
2229
   }
2214
 
2230
 
2215
   // else do we want info about a particular IFS ? if so, dissecate it
2231
   // else do we want info about a particular IFS ? if so, dissecate it
2216
   else if (want_info)
2232
   else if (want_info)
2217
      exit (dump_ifs_info (first_pathname, want_everything));
2233
      exit (dump_ifs_info (first_pathname, want_everything, hide_filename));
2218
 
2234
 
2219
   // else do we want to dump its contents ? if so, do so
2235
   // else do we want to dump its contents ? if so, do so
2220
   else if (want_dump)
2236
   else if (want_dump)
2221
      exit (dump_ifs_contents (first_pathname, (second_pathname != NULL ? second_pathname : ".")));
2237
      exit (dump_ifs_contents (first_pathname, (second_pathname != NULL ? second_pathname : ".")));
2222
 
2238
 
Line 2307... Line 2323...
2307
 
2323
 
2308
      ifs.offsets.startupheader = ifs.data.size; // save startup header offset for future use
2324
      ifs.offsets.startupheader = ifs.data.size; // save startup header offset for future use
2309
      memset (&startup_header, 0, sizeof (startup_header)); // prepare startup header
2325
      memset (&startup_header, 0, sizeof (startup_header)); // prepare startup header
2310
      memcpy (startup_header.signature, "\xeb\x7e\xff\x00", 4); // startup header signature, i.e. 0xff7eeb
2326
      memcpy (startup_header.signature, "\xeb\x7e\xff\x00", 4); // startup header signature, i.e. 0xff7eeb
2311
      startup_header.version       = 1;
2327
      startup_header.version       = 1;
2312
      startup_header.flags1        = STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2; // flags, 0x21 (STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2)
2328
      startup_header.flags1        = STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2 | startup_header_compression_flag; // flags, 0x21 (STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2)
2313
      startup_header.header_size   = sizeof (startup_header); // 256
2329
      startup_header.header_size   = sizeof (startup_header); // 256
2314
      if (strcmp (image_processor, "x86_64") == 0)
2330
      if (strcmp (image_processor, "x86_64") == 0)
2315
         startup_header.machine = ELF_MACHINE_X86_64; // EM_X86_64
2331
         startup_header.machine = ELF_MACHINE_X86_64; // EM_X86_64
2316
      else if (strcmp (image_processor, "aarch64le") == 0)
2332
      else if (strcmp (image_processor, "aarch64le") == 0)
2317
         startup_header.machine = ELF_MACHINE_AARCH64; // EM_AARCH64
2333
         startup_header.machine = ELF_MACHINE_AARCH64; // EM_AARCH64
Line 2320... Line 2336...
2320
      startup_header.startup_vaddr = image_base + (uint32_t) startupfile_ep_from_imagebase; // [I ] Virtual Address to transfer to after IPL is done, here 0x01403008 (appears in "Entry" column for "startup.*")
2336
      startup_header.startup_vaddr = image_base + (uint32_t) startupfile_ep_from_imagebase; // [I ] Virtual Address to transfer to after IPL is done, here 0x01403008 (appears in "Entry" column for "startup.*")
2321
      startup_header.image_paddr   = image_base + (uint32_t) bootfile_size;                 // F[IS] Physical address of image, here 0x01400f30 (appears in "Offset" column for "startup-header" which is the first entry/start of file)
2337
      startup_header.image_paddr   = image_base + (uint32_t) bootfile_size;                 // F[IS] Physical address of image, here 0x01400f30 (appears in "Offset" column for "startup-header" which is the first entry/start of file)
2322
      startup_header.ram_paddr     = startup_header.image_paddr;                            // [IS] Physical address of RAM to copy image to (startup_size bytes copied), here 0x01400f30 (same as above)
2338
      startup_header.ram_paddr     = startup_header.image_paddr;                            // [IS] Physical address of RAM to copy image to (startup_size bytes copied), here 0x01400f30 (same as above)
2323
      startup_header.ram_size      = WILL_BE_FILLED_LATER;                                  // [ S] Amount of RAM used by the startup program and executables contained in the file system, here 0x00cd6128 i.e. 13 459 752 dec. which is 13 Mb. i.e. IFS file size minus 0x9eee (40686)
2339
      startup_header.ram_size      = WILL_BE_FILLED_LATER;                                  // [ S] Amount of RAM used by the startup program and executables contained in the file system, here 0x00cd6128 i.e. 13 459 752 dec. which is 13 Mb. i.e. IFS file size minus 0x9eee (40686)
2324
      startup_header.startup_size  = WILL_BE_FILLED_LATER;                                  // [I ] Size of startup (never compressed), here 0x02f148 or 192 840 bytes
2340
      startup_header.startup_size  = WILL_BE_FILLED_LATER;                                  // [I ] Size of startup (never compressed), here 0x02f148 or 192 840 bytes
2325
      startup_header.stored_size   = WILL_BE_FILLED_LATER;                                  // [I ] Size of entire image, here 0x00cd6128 (same as ram_size)
2341
      startup_header.stored_size   = WILL_BE_FILLED_LATER;                                  // [I ] Size of entire image file (startup + *optionally compressed* imagefs) without optional boot prefix, here 0x00cd6128
2326
      startup_header.imagefs_size  = WILL_BE_FILLED_LATER;                                  // [ S] Size of uncompressed imagefs, here 0x00ca6fe0 or 13 266 912 bytes
2342
      startup_header.imagefs_size  = WILL_BE_FILLED_LATER;                                  // [ S] Size of uncompressed imagefs, here 0x00ca6fe0 or 13 266 912 bytes
2327
      startup_header.preboot_size  = (uint16_t) bootfile_size;                              // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file))
2343
      startup_header.preboot_size  = (uint16_t) bootfile_size;                              // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file))
2328
      ASSERT_WITH_ERRNO (Buffer_Append (&ifs.data, &startup_header, sizeof (startup_header))); // write startup header
2344
      ASSERT_WITH_ERRNO (Buffer_Append (&ifs.data, &startup_header, sizeof (startup_header))); // write startup header
2329
      ASSERT_WITH_ERRNO (Buffer_PadWithZeroesTo (&ifs.data, ROUND_TO_UPPER_MULTIPLE (ifs.data.size, image_align))); // pad as necessary
2345
      ASSERT_WITH_ERRNO (Buffer_PadWithZeroesTo (&ifs.data, ROUND_TO_UPPER_MULTIPLE (ifs.data.size, image_align))); // pad as necessary
2330
 
2346
 
Line 2376... Line 2392...
2376
   imgdir_size = ifs.data.size - ifs.offsets.imagedir; // measure image dir size and save it for future use
2392
   imgdir_size = ifs.data.size - ifs.offsets.imagedir; // measure image dir size and save it for future use
2377
 
2393
 
2378
   // is it a bootable image with a startup file ?
2394
   // is it a bootable image with a startup file ?
2379
   if (startupfile_pathname != NULL)
2395
   if (startupfile_pathname != NULL)
2380
   {
2396
   {
2381
      // start by writing the startup script data blob, if we have one
-
 
2382
      for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
-
 
2383
         if (fsentries[fsentry_index].header.ino == image_bootscript_ino)
-
 
2384
            break; // locate the startup script directory entry
-
 
2385
      if (fsentry_index < fsentry_count) // found it ?
-
 
2386
      {
-
 
2387
         if (ifs.data.size + fsentries[fsentry_index].u.file.size >= kernelfile_offset)
-
 
2388
            DIE_WITH_EXITCODE (1, "the compiled startup script is too big (%zd bytes, max is %zd) to fit at current offset %zd. Use --kerneloffs <addr> to relocate (warning: untested)", (size_t) fsentries[fsentry_index].u.file.size, kernelfile_offset - ifs.data.size, ifs.data.size);
-
 
2389
         fsentries[fsentry_index].u.file.offset = (uint32_t) (ifs.data.size - ifs.offsets.imageheader); // save file data blob offset in file structure
-
 
2390
         Buffer_AppendIFSFileData (&ifs.data, &fsentries[fsentry_index]); // write file data
-
 
2391
         fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
-
 
2392
      }
-
 
2393
 
-
 
2394
      // now write the filesystem entries that may fit before the kernel
2397
      // write the filesystem entries that may fit before the kernel
2395
      for (;;)
2398
      for (;;)
2396
      {
2399
      {
2397
         available_space = kernelfile_offset - ifs.data.size; // measure the available space until the kernel
2400
         available_space = kernelfile_offset - ifs.data.size; // measure the available space until the kernel
2398
 
2401
 
2399
         // look for the biggest one that can fit
2402
         // look for the biggest one that can fit
Line 2488... Line 2491...
2488
      Buffer_WriteIFSDirectoryEntryAt (&ifs.data, curr_offset, &fsentries[fsentry_index]); // rewrite each dirent
2491
      Buffer_WriteIFSDirectoryEntryAt (&ifs.data, curr_offset, &fsentries[fsentry_index]); // rewrite each dirent
2489
      curr_offset += fsentries[fsentry_index].header.size; // advance to the next one
2492
      curr_offset += fsentries[fsentry_index].header.size; // advance to the next one
2490
   }
2493
   }
2491
 
2494
 
2492
   // ALL CHECKSUMS AT THE VERY END
2495
   // ALL CHECKSUMS AT THE VERY END
-
 
2496
 
-
 
2497
   // compute SHA-512 checksum and V1 checksum of image block
-
 
2498
   if (   ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
-
 
2499
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__   )))
-
 
2500
      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
-
 
2501
   else
-
 
2502
      is_foreign_endianness = false; // else this header is for the same endianness as us
-
 
2503
 
-
 
2504
   if (image_header.flags & IMAGE_FLAGS_TRAILER_V2) // is it a V2 trailer ?
-
 
2505
   {
-
 
2506
      SHA512 (&ifs.data.bytes[ifs.offsets.imageheader], ifs.offsets.imagetrailer - ifs.offsets.imageheader, &ifs.data.bytes[ifs.offsets.imagetrailer]); // compute SHA512 checksum and write it in place
-
 
2507
      checksum = update_checksum (&ifs.data.bytes[ifs.offsets.imageheader], ifs.offsets.imagetrailer + SHA512_DIGEST_LENGTH - ifs.offsets.imageheader, is_foreign_endianness); // compute old checksum
-
 
2508
      memcpy (&ifs.data.bytes[ifs.offsets.imagetrailer + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
-
 
2509
   }
-
 
2510
   else // old V1 trailer
-
 
2511
   {
-
 
2512
      checksum = update_checksum (&ifs.data.bytes[ifs.offsets.imageheader], ifs.offsets.imagetrailer - ifs.offsets.imageheader, is_foreign_endianness); // compute old checksum
-
 
2513
      memcpy (&ifs.data.bytes[ifs.offsets.imagetrailer], &checksum, 4); // and write it in place
-
 
2514
   }
-
 
2515
 
-
 
2516
   // should we compress the image block ?
-
 
2517
   if (startup_header_compression_flag != STARTUP_HDR_FLAGS1_COMPRESS_NONE)
-
 
2518
   {
-
 
2519
      // it appears mkifs compresses data in blocks, prefixed by 2-byte block size in BIG ENDIAN
-
 
2520
      Buffer_InitWithSize (&compressed_imagefs, image_header.image_size * 11 / 10); // mallocate and add 10% for safety
-
 
2521
      compressed_imagefs.size = 0;
-
 
2522
      compressor_in = &ifs.data.bytes[ifs.offsets.imageheader]; // point at the start of the data to compress
-
 
2523
      compressor_out = &compressed_imagefs.bytes[2]; // point after the compressed block size word
-
 
2524
      remaining_len = ifs.data.size - ifs.offsets.imageheader; // see how many bytes there are to compress
-
 
2525
 
-
 
2526
      if (startup_header_compression_flag == STARTUP_HDR_FLAGS1_COMPRESS_UCL)
-
 
2527
         ASSERT (ucl_init () == UCL_E_OK, "UCL library initialization failed -- please recompile this tool with less aggressive optimizations");
-
 
2528
      else if (startup_header_compression_flag == STARTUP_HDR_FLAGS1_COMPRESS_LZO)
-
 
2529
         ASSERT (ucl_init () == UCL_E_OK, "LZO library initialization failed -- please recompile this tool with less aggressive optimizations");
-
 
2530
      else if (startup_header_compression_flag == STARTUP_HDR_FLAGS1_COMPRESS_ZLIB)
-
 
2531
         DIE_WITH_EXITCODE (1, "unimplemented compression scheme: zlib (FIXME)");
-
 
2532
      else
-
 
2533
         DIE_WITH_EXITCODE (1, "unsupported compression flags: 0x%2x", startup_header_compression_flag);
-
 
2534
   
-
 
2535
      // run the compressible payload (the imagefs) through the right compression algorithm
-
 
2536
      while (remaining_len > 0)
-
 
2537
      {
-
 
2538
         compressor_inlen = (ucl_uint) remaining_len; // size the compressor input appropriately
-
 
2539
         if (compressor_inlen > 65536)
-
 
2540
            compressor_inlen = 65536; // cap it to a VERY conservative value
-
 
2541
         if (startup_header_compression_flag == STARTUP_HDR_FLAGS1_COMPRESS_UCL)
-
 
2542
         {
-
 
2543
            // UCL compression. NOTE: the decompressor function used in startup-x86 is "ucl_nrv2b_decompress_8". Also compression level is hardcoded at 9 in mkifs, but can range from 1 to 10
-
 
2544
            static ucl_uint ucl_outlen; // have a different variable because of pointer size mismatch
-
 
2545
            while (((compressor_ret = ucl_nrv2b_99_compress (compressor_in, (ucl_uint) compressor_inlen, compressor_out, &ucl_outlen, NULL, 9, NULL, NULL)) == UCL_E_OK) && (ucl_outlen > 0xFFFF))
-
 
2546
               compressor_inlen -= 4096; // as long as we can't produce compressed blocks whose size can fit in 2 bytes, try again with 4kb input less
-
 
2547
            ASSERT (compressor_ret == UCL_E_OK, "UCL compression error: ucl_nrv2b_99_compress() returned %d", compressor_ret); // make sure it's not a compression error
-
 
2548
            compressor_outlen = ucl_outlen; // cast back to size_t
-
 
2549
         }
-
 
2550
         else if (startup_header_compression_flag == STARTUP_HDR_FLAGS1_COMPRESS_LZO)
-
 
2551
         {
-
 
2552
            // LZO compression. NOTE: the compressor function used in mkifs is "lzo1x_999_compress" which is from the full LZO package... I use use minilzo, but I have to admit the compression ratio of the full LZO is *much* better.
-
 
2553
            static lzo_align_t lzo_workmem[(LZO1X_1_MEM_COMPRESS + (sizeof (lzo_align_t) - 1)) / sizeof(lzo_align_t)]; // heap-allocated aligned buffer
-
 
2554
            static lzo_uint lzo_outlen; // have a different variable because of pointer size mismatch
-
 
2555
            while (((compressor_ret = lzo1x_1_compress (compressor_in, compressor_inlen, compressor_out, &lzo_outlen, lzo_workmem)) == UCL_E_OK) && (lzo_outlen > 0xFFFF))
-
 
2556
               compressor_inlen -= 4096; // as long as we can't produce compressed blocks whose size can fit in 2 bytes, try again with 4kb input less
-
 
2557
            ASSERT (compressor_ret == LZO_E_OK, "LZO compression error: lzo1x_1_compress() returned %d", compressor_ret); // make sure it's not a compression error
-
 
2558
            compressor_outlen = lzo_outlen; // cast back to size_t
-
 
2559
         }
-
 
2560
         else if (startup_header_compression_flag == STARTUP_HDR_FLAGS1_COMPRESS_ZLIB)
-
 
2561
         {
-
 
2562
            // Zlib (TODO)
-
 
2563
         }
-
 
2564
 
-
 
2565
         // the compression produced a block smaller than 65536 bytes
-
 
2566
         LOG_DEBUG ("compressed block size %zd", compressor_outlen);
-
 
2567
         compressed_imagefs.bytes[compressed_imagefs.size + 0] = (uint8_t) (compressor_outlen >> 8); // write compressed block size word (in big endian)
-
 
2568
         compressed_imagefs.bytes[compressed_imagefs.size + 1] = (uint8_t) (compressor_outlen >> 0);
-
 
2569
         compressed_imagefs.size += 2 + (size_t) compressor_outlen; // advance in compression buffer by the compressed block size word plus the compressed block size
-
 
2570
 
-
 
2571
         remaining_len -= compressor_inlen; // see how many bytes remain to compress
-
 
2572
 
-
 
2573
         compressor_in += compressor_inlen; // advance in input stream
-
 
2574
         compressor_out += 2 + compressor_outlen; // advance in output stream
-
 
2575
      }
-
 
2576
 
-
 
2577
      compressed_imagefs.bytes[compressed_imagefs.size + 0] = 0; // write the end of stream marker (empty block with nil size)
-
 
2578
      compressed_imagefs.bytes[compressed_imagefs.size + 1] = 0;
-
 
2579
      compressed_imagefs.size += 2;
-
 
2580
      LOG_INFO ("compressed %zd bytes into %zd bytes\n", ifs.data.size - ifs.offsets.imageheader, compressed_imagefs.size);
-
 
2581
 
-
 
2582
      /////////////////////////////////////////////////////////////
-
 
2583
      // WARNING: ALL IFS OFFSETS BECOME INVALID PAST THIS POINT //
-
 
2584
      /////////////////////////////////////////////////////////////
-
 
2585
 
-
 
2586
      // now place the compressed buffer in the payload at the imagefs offset
-
 
2587
      ASSERT_WITH_ERRNO (Buffer_WriteBufferAt (&ifs.data, ifs.offsets.imageheader, &compressed_imagefs));
-
 
2588
      ifs.data.size = ifs.offsets.imageheader + compressed_imagefs.size; // update IFS data size
-
 
2589
      Buffer_Forget (&compressed_imagefs);
-
 
2590
 
-
 
2591
      // fix the stored size in the startup header
-
 
2592
      startup_header.stored_size = (uint32_t) (ifs.data.size - ifs.offsets.startupheader);
-
 
2593
      ASSERT_WITH_ERRNO (Buffer_WriteAt (&ifs.data, ifs.offsets.startupheader, &startup_header, sizeof (startup_header))); // write the final startup header at its right offset
-
 
2594
   }
2493
 
2595
 
2494
   // do we have a startup file ? if so, this is a bootable image
2596
   // do we have a startup file ? if so, this is a bootable image
2495
   if (startupfile_pathname != NULL)
2597
   if (startupfile_pathname != NULL)
2496
   {
2598
   {
2497
      // compute SHA-512 checksum and V1 checksum of startup block
2599
      // compute SHA-512 checksum and V1 checksum of startup block
2498
      if (   ( (startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2600
      if (   ( (startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2499
          || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2601
          || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__   )))
2500
         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
2602
         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
2501
      else
2603
      else
2502
         is_foreign_endianness = false; // else this header is for the same endianness as us
2604
         is_foreign_endianness = false; // else this header is for the same endianness as us
2503
 
2605
 
2504
      if (startup_header.flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) // is it a V2 trailer ?
2606
      if (startup_header.flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) // is it a V2 trailer ?
Line 2510... Line 2612...
2510
      else // old V1 trailer
2612
      else // old V1 trailer
2511
      {
2613
      {
2512
         checksum = update_checksum (&ifs.data.bytes[ifs.offsets.startupheader], ifs.offsets.startuptrailer - ifs.offsets.startupheader, is_foreign_endianness); // compute old checksum
2614
         checksum = update_checksum (&ifs.data.bytes[ifs.offsets.startupheader], ifs.offsets.startuptrailer - ifs.offsets.startupheader, is_foreign_endianness); // compute old checksum
2513
         memcpy (&ifs.data.bytes[ifs.offsets.startuptrailer], &checksum, 4); // and write it in place
2615
         memcpy (&ifs.data.bytes[ifs.offsets.startuptrailer], &checksum, 4); // and write it in place
2514
      }
2616
      }
2515
   }
-
 
2516
 
-
 
2517
   // compute SHA-512 checksum and V1 checksum of image block
-
 
2518
   if (   ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
-
 
2519
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
-
 
2520
      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
-
 
2521
   else
-
 
2522
      is_foreign_endianness = false; // else this header is for the same endianness as us
-
 
2523
 
-
 
2524
   if (image_header.flags & IMAGE_FLAGS_TRAILER_V2) // is it a V2 trailer ?
-
 
2525
   {
-
 
2526
      SHA512 (&ifs.data.bytes[ifs.offsets.imageheader], ifs.offsets.imagetrailer - ifs.offsets.imageheader, &ifs.data.bytes[ifs.offsets.imagetrailer]); // compute SHA512 checksum and write it in place
-
 
2527
      checksum = update_checksum (&ifs.data.bytes[ifs.offsets.imageheader], ifs.offsets.imagetrailer + SHA512_DIGEST_LENGTH - ifs.offsets.imageheader, is_foreign_endianness); // compute old checksum
-
 
2528
      memcpy (&ifs.data.bytes[ifs.offsets.imagetrailer + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
-
 
2529
   }
-
 
2530
   else // old V1 trailer
-
 
2531
   {
-
 
2532
      checksum = update_checksum (&ifs.data.bytes[ifs.offsets.imageheader], ifs.offsets.imagetrailer - ifs.offsets.imageheader, is_foreign_endianness); // compute old checksum
-
 
2533
      memcpy (&ifs.data.bytes[ifs.offsets.imagetrailer], &checksum, 4); // and write it in place
-
 
2534
   }
2617
   }
2535
 
2618
 
2536
   // now rewrite IFS with the correct checksums
2619
   // now rewrite IFS with the correct checksums
2537
   ASSERT_WITH_ERRNO (Buffer_WriteToFile (&ifs.data, (ifs_pathname != NULL ? ifs_pathname : "<stdout>")));
2620
   ASSERT_WITH_ERRNO (Buffer_WriteToFile (&ifs.data, (ifs_pathname != NULL ? ifs_pathname : "<stdout>")));
2538
 
2621