Rev 20 | Rev 22 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 20 | Rev 21 | ||
---|---|---|---|
Line 4... | Line 4... | ||
4 | // TODO: startup file stripping |
4 | // TODO: startup file stripping |
5 | // TODO: kernel file stripping |
- | |
6 | // TODO: boot script compiler |
5 | // TODO: boot script compiler |
7 | 6 | ||
8 | // standard C includes |
7 | // standard C includes |
9 | #include <stdint.h> |
8 | #include <stdint.h> |
10 | #include <stdbool.h> |
9 | #include <stdbool.h> |
Line 94... | Line 93... | ||
94 | bool should_allow_nonexistent_files; // [+|-optional] whether to continue processing on unexistent files |
93 | bool should_allow_nonexistent_files; // [+|-optional] whether to continue processing on unexistent files |
95 | bool is_bootstrap_file; // entry has the [virtual] attribute |
94 | bool is_bootstrap_file; // entry has the [virtual] attribute |
96 | bool is_compiled_bootscript; // entry has [+script] attribute |
95 | bool is_compiled_bootscript; // entry has [+script] attribute |
97 | int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx) |
96 | int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx) |
98 | char *search; // [search=path[:path]] binary search path (the default one will be constructed at startup) |
97 | char *search; // [search=path[:path]] binary search path (the default one will be constructed at startup) |
99 | - | ||
100 | 98 | ||
101 | buffer_t data; // the resolved file's own data bytes |
99 | buffer_t data; // the resolved file's own data bytes |
102 | } parms_t; |
100 | } parms_t; |
103 | 101 | ||
104 | 102 | ||
Line 136... | Line 134... | ||
136 | // bootable IFS support |
134 | // bootable IFS support |
137 | static char *bootfile_pathname = NULL; // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS |
135 | static char *bootfile_pathname = NULL; // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS |
138 | static size_t bootfile_size = 0; // HACK: size of the bootcode binary blob file to put at the start of a bootable IFS |
136 | static size_t bootfile_size = 0; // HACK: size of the bootcode binary blob file to put at the start of a bootable IFS |
139 | static char *startupfile_pathname = NULL; // HACK: pathname to precompiled startup file blob to put in the startup header of a bootable IFS |
137 | static char *startupfile_pathname = NULL; // HACK: pathname to precompiled startup file blob to put in the startup header of a bootable IFS |
140 | static size_t startupfile_ep_from_imagebase = 0; // HACK: startup code entrypoint offset from image base for a bootable IFS |
138 | static size_t startupfile_ep_from_imagebase = 0; // HACK: startup code entrypoint offset from image base for a bootable IFS |
141 | static size_t kernelfile_offset = 0x32000; // kernel file offset in the IFS (is it ever supposed to change) |
139 | static size_t kernelfile_offset = 0x32000; // kernel file offset in the IFS (is it ever supposed to change?) |
142 | 140 | ||
143 | 141 | ||
144 | // exported function prototypes |
142 | // exported function prototypes |
145 | int32_t update_checksum (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 |
143 | int32_t update_checksum (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 |
146 | 144 | ||
Line 754... | Line 752... | ||
754 | char **args; |
752 | char **args; |
755 | size_t count; |
753 | size_t count; |
756 | } stringarray_t; |
754 | } stringarray_t; |
757 | 755 | ||
758 | static thread_local char *candidate_pathname = NULL; |
756 | static thread_local char *candidate_pathname = NULL; |
- | 757 | static thread_local parms_t default_parms = { 0 }; |
|
759 | static int inode_count = 0; // will be preincremented each time this function is called |
758 | static int inode_count = 0; // will be preincremented each time this function is called |
760 | 759 | ||
761 | stringarray_t global_argv = { NULL, 0 }; |
760 | stringarray_t global_argv = { NULL, 0 }; |
762 | stringarray_t global_envp = { NULL, 0 }; |
761 | stringarray_t global_envp = { NULL, 0 }; |
763 | stringarray_t line_argv = { NULL, 0 }; |
762 | stringarray_t line_argv = { NULL, 0 }; |
Line 799... | Line 798... | ||
799 | ASSERT_WITH_ERRNO (candidate_pathname); |
798 | ASSERT_WITH_ERRNO (candidate_pathname); |
800 | } |
799 | } |
801 | 800 | ||
802 | if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ? |
801 | if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ? |
803 | { |
802 | { |
- | 803 | if (buildhost_pathname != NULL) // was a source file pathname supplied ? |
|
- | 804 | { |
|
- | 805 | memcpy (&default_parms, entry_parms, sizeof (parms_t)); // apply current entry parameters when including a directory recursively |
|
- | 806 | add_directory_contents_recursively (fsentries, fsentry_count, buildhost_pathname, strlen (buildhost_pathname), &default_parms); // if so, add this diretory contents recursively |
|
- | 807 | } |
|
804 | LOG_INFO ("directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname); |
808 | LOG_INFO ("directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname); |
805 | } |
809 | } |
806 | else if ( |
810 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
807 | { |
811 | { |
- | 812 | // do we already know the data for this data blob ? |
|
- | 813 | if (entry_parms->data.bytes != NULL) |
|
- | 814 | { |
|
- | 815 | entry_parms->mtime = entry_parms->mtime_for_inline_files; // if so, set it a mtime equal to the mtime to use for inline files |
|
- | 816 | LOG_INFO ("symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes); |
|
- | 817 | } |
|
- | 818 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ? |
|
- | 819 | { |
|
- | 820 | entry_parms->data.bytes = malloc (MAXPATHLEN); // allocate enough space for symlink data |
|
- | 821 | ASSERT_WITH_ERRNO (entry_parms->data.bytes); |
|
- | 822 | retval = readlink (buildhost_pathname, entry_parms->data.bytes, MAXPATHLEN); // read symlink contents |
|
- | 823 | ASSERT_WITH_ERRNO (retval > 0); |
|
- | 824 | entry_parms->data.size = retval; // save symlink target length |
|
- | 825 | } |
|
- | 826 | else |
|
- | 827 | DIE_WITH_EXITCODE (1, "unexpected code path: can't store a symlink without neither explicit contents nor a host pathname. This is a bug in the program. Please contact the author."); |
|
- | 828 | } |
|
- | 829 | else if (S_ISFIFO (entry_parms->st_mode)) // else are we storing a FIFO ? |
|
- | 830 | { |
|
- | 831 | if ((entry_parms->data.bytes == NULL) || (strchr (entry_parms->data.bytes, ':') == NULL)) |
|
- | 832 | DIE_WITH_EXITCODE (1, "device entry \"%s\" malformed (no 'dev:rdev' pair)", stored_pathname); |
|
- | 833 | LOG_INFO ("fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev:rdev %s)", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes); |
|
- | 834 | } |
|
- | 835 | else // necessarily a regular file (either S_IFREG is specified, or st_mode is zero) |
|
- | 836 | { |
|
- | 837 | entry_parms->st_mode |= S_IFREG; // make this explicit |
|
- | 838 | ||
808 | if (entry_parms->is_bootstrap_file) // is it the bootstrap file ? |
839 | if (entry_parms->is_bootstrap_file) // is it the bootstrap file ? |
809 | { |
840 | { |
810 | // parse each line of contents |
841 | // parse each line of contents |
811 | ASSERT (entry_parms->data.size > 0, "kernel specification without inline contents"); |
842 | ASSERT (entry_parms->data.size > 0, "kernel specification without inline contents"); |
812 | 843 | ||
Line 1145... | Line 1176... | ||
1145 | Buffer_StripELFFile (&entry_parms->data, (const char **) saved_ELF_sections, saved_ELF_section_count, false, stored_pathname); // strip the ELF file à la mkifs |
1176 | Buffer_StripELFFile (&entry_parms->data, (const char **) saved_ELF_sections, saved_ELF_section_count, false, stored_pathname); // strip the ELF file à la mkifs |
1146 | entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file |
1177 | entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file |
1147 | } // end if the file is not yet a processed ELF |
1178 | } // end if the file is not yet a processed ELF |
1148 | } // end if the file we're storing is an ELF file |
1179 | } // end if the file we're storing is an ELF file |
1149 | #undef ELFHDR // undefine the macro that used to always point to the ELF header at the beginning of the file |
1180 | #undef ELFHDR // undefine the macro that used to always point to the ELF header at the beginning of the file |
1150 | } |
- | |
1151 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
- | |
1152 | { |
- | |
1153 | // do we already know the data for this data blob ? |
- | |
1154 | if (entry_parms->data.bytes != NULL) |
- | |
1155 | { |
- | |
1156 | entry_parms->mtime = entry_parms->mtime_for_inline_files; // if so, set it a mtime equal to the mtime to use for inline files |
- | |
1157 | LOG_INFO ("symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes); |
- | |
1158 | } |
- | |
1159 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ? |
- | |
1160 | { |
- | |
1161 | entry_parms->data.bytes = malloc (MAXPATHLEN); // allocate enough space for symlink data |
- | |
1162 | ASSERT_WITH_ERRNO (entry_parms->data.bytes); |
- | |
1163 | retval = readlink (buildhost_pathname, entry_parms->data.bytes, MAXPATHLEN); // read symlink contents |
- | |
1164 | ASSERT_WITH_ERRNO (retval > 0); |
- | |
1165 | entry_parms->data.size = retval; // save symlink target length |
- | |
1166 | } |
- | |
1167 | else |
- | |
1168 | DIE_WITH_EXITCODE (1, "unexpected code path: can't store a symlink without neither explicit contents nor a host pathname. This is a bug in the program. Please contact the author."); |
- | |
1169 | } |
- | |
1170 | else // we must be storing a FIFO |
- | |
1171 | { |
- | |
1172 | if ((entry_parms->data.bytes == NULL) || (strchr (entry_parms->data.bytes, ':') == NULL)) |
- | |
1173 | DIE_WITH_EXITCODE (1, "device entry \"%s\" malformed (no 'dev:rdev' pair)", stored_pathname); |
- | |
1174 | LOG_INFO ("fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev:rdev %s)", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes); |
- | |
1175 | } |
1181 | } |
1176 | 1182 | ||
1177 | // have a pointer to where the stored pathname actually starts, without the leading slash |
1183 | // have a pointer to where the stored pathname actually starts, without the leading slash |
1178 | stored_pathname_without_leading_slash = stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname; |
1184 | stored_pathname_without_leading_slash = stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname; |
1179 | 1185 | ||
Line 1688... | Line 1694... | ||
1688 | fsentry_t *fsentries = NULL; // output IFS's filesystem entries |
1694 | fsentry_t *fsentries = NULL; // output IFS's filesystem entries |
1689 | size_t fsentry_count = 0; // number of entries in the IFS filesystem |
1695 | size_t fsentry_count = 0; // number of entries in the IFS filesystem |
1690 | parms_t default_parms = { // default parameters for a filesystem entry |
1696 | parms_t default_parms = { // default parameters for a filesystem entry |
1691 | .dperms = 0755, |
1697 | .dperms = 0755, |
1692 | .perms = 0644, |
1698 | .perms = 0644, |
1693 | .uid = 0, |
- | |
1694 | .gid = 0, |
- | |
1695 | .st_mode = S_IFREG, |
- | |
1696 | .mtime = UINT32_MAX, |
1699 | .mtime = UINT32_MAX, |
1697 | .mtime_for_inline_files = UINT32_MAX, |
1700 | .mtime_for_inline_files = UINT32_MAX, |
1698 | .prefix = "/proc/boot", |
1701 | .prefix = "/proc/boot", |
1699 | .should_follow_symlinks = true, // [+|-followlink] |
1702 | .should_follow_symlinks = true, // [+|-followlink] |
1700 | .should_autosymlink_dylib = true, // [+|-autolink] |
1703 | .should_autosymlink_dylib = true, // [+|-autolink] |
1701 | .is_compiled_bootscript = false, // [+|-script] |
- | |
1702 | .extra_ino_flags = 0, |
- | |
1703 | .search = NULL, |
- | |
1704 | .data = { NULL, 0 } |
- | |
1705 | }; |
1704 | }; |
1706 | parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file) |
1705 | parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file) |
1707 | 1706 | ||
1708 | char path_on_buildhost[MAXPATHLEN] = ""; |
1707 | char path_on_buildhost[MAXPATHLEN] = ""; |
1709 | char path_in_ifs[MAXPATHLEN] = ""; |
1708 | char path_in_ifs[MAXPATHLEN] = ""; |
Line 1830... | Line 1829... | ||
1830 | fprintf (out, " ifstool --info [--everything] <ifs file>\n"); |
1829 | fprintf (out, " ifstool --info [--everything] <ifs file>\n"); |
1831 | fprintf (out, " ifstool --dump [--outdir <path>] <ifs file>\n"); |
1830 | fprintf (out, " ifstool --dump [--outdir <path>] <ifs file>\n"); |
1832 | fprintf (out, " ifstool --strip [--outfile <pathname>] <ELF file>\n"); |
1831 | fprintf (out, " ifstool --strip [--outfile <pathname>] <ELF file>\n"); |
1833 | fprintf (out, " ifstool [-?|--help]\n"); |
1832 | fprintf (out, " ifstool [-?|--help]\n"); |
1834 | // mkifs [-?] [-l inputline] [-n[n]] [-o directory] [-p patchfile] [-r rootdir] [-s section] [-v] [buildfile] [directory] [outputfile] |
1833 | // mkifs [-?] [-l inputline] [-n[n]] [-o directory] [-p patchfile] [-r rootdir] [-s section] [-v] [buildfile] [directory] [outputfile] |
1835 | fprintf (out, " ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [-- |
1834 | 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"); |
1836 | fprintf (out, "NOTE: the compiler mode requires predigested |
1835 | fprintf (out, "NOTE: the compiler mode requires predigested boot and startup files produced by mkifs.\n"); |
1837 | fprintf (out, "options:\n"); |
1836 | fprintf (out, "options:\n"); |
1838 | fprintf (out, " -? Display some help information.\n"); |
1837 | fprintf (out, " -? Display some help information.\n"); |
1839 | fprintf (out, " -a .ext Append a suffix to symbol files generated via [+keeplinked].\n"); |
1838 | fprintf (out, " -a .ext Append a suffix to symbol files generated via [+keeplinked].\n"); |
1840 | fprintf (out, " -l line Process line before interpreting the buildfile. Input lines given\n"); |
1839 | fprintf (out, " -l line Process line before interpreting the buildfile. Input lines given\n"); |
1841 | fprintf (out, " to mkifs should be quoted to prevent interpretation by the shell\n"); |
1840 | fprintf (out, " to mkifs should be quoted to prevent interpretation by the shell\n"); |