1/*
2 *  kextcache_main.h
3 *  kext_tools
4 *
5 *  Created by nik on 5/20/08.
6 *  Copyright 2008 __MyCompanyName__. All rights reserved.
7 *
8 */
9#ifndef _KEXTCACHE_MAIN_H
10#define _KEXTCACHE_MAIN_H
11
12#include <CoreFoundation/CoreFoundation.h>
13#include <IOKit/kext/OSKext.h>
14
15#include <getopt.h>
16#include <sysexits.h>
17
18#include <IOKit/kext/OSKext.h>
19
20#include "kext_tools_util.h"
21#include "kernelcache.h"
22
23#pragma mark Basic Types & Constants
24/*******************************************************************************
25* Constants
26*******************************************************************************/
27
28enum {
29    kKextcacheExitOK          = EX_OK,
30    kKextcacheExitNotFound,
31    kKextcacheExitArchNotFound,
32    kKextcacheExitKextBad,
33    kKextcacheExitStale,
34
35    // don't think we use it
36    kKextcacheExitUnspecified = 11,
37
38    // don't actually exit with this, it's just a sentinel value
39    kKextcacheExitHelp        = 33,
40    kKextcacheExitNoStart
41};
42
43#pragma mark Command-line Option Definitions
44/*******************************************************************************
45* Command-line options. This data is used by getopt_long_only().
46*
47* Options common to all kext tools are in kext_tools_util.h.
48*******************************************************************************/
49
50/* Mkext-generation flags.
51 */
52// kOptNameMkext always represents most recent format supported
53#define kOptNameMkext                   "mkext"
54#define kOptNameMkext1                  "mkext1"
55#define kOptNameMkext2                  "mkext2"
56#define kOptNameSystemMkext             "system-mkext"
57#define kOptNameVolumeRoot              "volume-root"
58
59// kOptNameBundleIdentifier in kext_tools_util.h
60// kOptNameSystemExtensions in kext_tools_util.h
61
62#define kOptNameLocalRoot               "local-root"
63#define kOptNameLocalRootAll            "local-root-all"
64#define kOptNameNetworkRoot             "network-root"
65#define kOptNameNetworkRootAll          "network-root-all"
66#define kOptNameSafeBoot                "safe-boot"
67#define kOptNameSafeBootAll             "safe-boot-all"
68
69/* Prelinked-kernel-generation flags.
70 */
71#define kOptNamePrelinkedKernel         "prelinked-kernel"
72#define kOptNameSystemPrelinkedKernel   "system-prelinked-kernel"
73#define kOptNameKernel                  "kernel"
74#define kOptNameAllLoaded               "all-loaded"
75#define kOptNameSymbols                 "symbols"
76
77/* Embedded prelinked-kernel-generation flags.
78 */
79#define kOptNameAllPersonalities        "all-personalities"
80#define kOptNameNoLinkFailures          "no-link-failures"
81#define kOptNameStripSymbols            "strip-symbols"
82
83/* Misc. cache update flags.
84 */
85#define kOptNameSystemCaches            "system-caches"
86
87/* Boot!=root flags.
88 */
89#define kOptNameUpdate                  "update-volume"
90#define kOptNameForce                   "force"
91#define kOptNameInstaller               "Installer"
92#define kOptNameCachesOnly              "caches-only"
93
94/* Misc flags.
95 */
96#define kOptNameNoAuthentication        "no-authentication"
97#define kOptNameTests                   "print-diagnostics"
98#define kOptNameCompressed              "compressed"
99#define kOptNameUncompressed            "uncompressed"
100
101#define kOptArch                  'a'
102// 'b' in kext_tools_util.h
103#define kOptPrelinkedKernel       'c'
104#define kOptSystemMkext           'e'
105#if !NO_BOOT_ROOT
106#define kOptForce                 'f'
107#endif /* !NO_BOOT_ROOT */
108
109// xxx - do we want a longopt for this?
110#define kOptLowPriorityFork       'F'
111// 'h' in kext_tools_util.h
112#define kOptRepositoryCaches      'k'
113#define kOptKernel                'K'
114#define kOptLocalRoot             'l'
115#define kOptLocalRootAll          'L'
116// kOptMkext always represents most recent format supported
117#define kOptMkext                 'm'
118#define kOptNetworkRoot           'n'
119#define kOptNetworkRootAll        'N'
120// 'q' in kext_tools_util.h
121#define kOptAllLoaded             'r'
122#define kOptSafeBoot              's'
123#define kOptSafeBootAll           'S'
124#define kOptTests                 't'
125#if !NO_BOOT_ROOT
126#define kOptUpdate                'u'
127#define kOptCheckUpdate           'U'
128#endif /* !NO_BOOT_ROOT */
129// 'v' in kext_tools_util.h
130#define kOptNoAuthentication      'z'
131
132/* Options with no single-letter variant.  */
133// Do not use -1, that's getopt() end-of-args return value
134// and can cause confusion
135#define kLongOptLongindexHack             (-2)
136#define kLongOptMkext1                    (-3)
137#define kLongOptMkext2                    (-4)
138// kLongOptMkext always represents most recent format supported
139#define kLongOptMkext                     kLongOptMkext2
140#define kLongOptCompressed                (-5)
141#define kLongOptUncompressed              (-6)
142#define kLongOptSymbols                   (-7)
143#define kLongOptSystemCaches              (-8)
144#define kLongOptSystemPrelinkedKernel     (-9)
145#define kLongOptVolumeRoot               (-10)
146#define kLongOptAllPersonalities         (-11)
147#define kLongOptNoLinkFailures           (-12)
148#define kLongOptStripSymbols             (-13)
149#define kLongOptInstaller                (-14)
150#define kLongOptCachesOnly               (-15)
151
152#if !NO_BOOT_ROOT
153#define kOptChars                ":a:b:c:efFhkK:lLm:nNqrsStu:U:vz"
154#else
155#define kOptChars                ":a:b:c:eFhkK:lLm:nNqrsStvz"
156#endif /* !NO_BOOT_ROOT */
157/* Some options are now obsolete:
158 *     -F (fork)
159 *     -k (update plist cache)
160 */
161
162int longopt = 0;
163
164struct option sOptInfo[] = {
165    { kOptNameLongindexHack,         no_argument,        &longopt, kLongOptLongindexHack },
166
167    { kOptNameHelp,                  no_argument,        NULL,     kOptHelp },
168    { kOptNameQuiet,                 no_argument,        NULL,     kOptQuiet },
169    { kOptNameVerbose,               optional_argument,  NULL,     kOptVerbose },
170    { kOptNameCompressed,            no_argument,        &longopt, kLongOptCompressed },
171    { kOptNameUncompressed,          no_argument,        &longopt, kLongOptUncompressed },
172
173    { kOptNameArch,                  required_argument,  NULL,     kOptArch },
174
175    { kOptNameMkext1,                required_argument,  &longopt, kLongOptMkext1 },
176    { kOptNameMkext2,                required_argument,  &longopt, kLongOptMkext2 },
177    { kOptNameMkext,                 required_argument,  NULL,     kOptMkext },
178    { kOptNameSystemMkext,           no_argument,        NULL,     kOptSystemMkext },
179    { kOptNameVolumeRoot,            required_argument,  &longopt, kLongOptVolumeRoot },
180
181    { kOptNameSystemCaches,          no_argument,        &longopt, kLongOptSystemCaches },
182
183    { kOptNameBundleIdentifier,      required_argument,  NULL,     kOptBundleIdentifier },
184
185    { kOptNameLocalRoot,             no_argument,        NULL,     kOptLocalRoot },
186    { kOptNameLocalRootAll,          no_argument,        NULL,     kOptLocalRootAll },
187    { kOptNameNetworkRoot,           no_argument,        NULL,     kOptNetworkRoot },
188    { kOptNameNetworkRootAll,        no_argument,        NULL,     kOptNetworkRootAll, },
189    { kOptNameSafeBoot,              no_argument,        NULL,     kOptSafeBoot },
190    { kOptNameSafeBootAll,           no_argument,        NULL,     kOptSafeBootAll },
191
192    { kOptNamePrelinkedKernel,       optional_argument,  NULL,     kOptPrelinkedKernel },
193    { kOptNameSystemPrelinkedKernel, no_argument,        &longopt, kLongOptSystemPrelinkedKernel },
194    { kOptNameKernel,                required_argument,  NULL,     kOptKernel },
195    { kOptNameAllLoaded,             no_argument,        NULL,     kOptAllLoaded },
196    { kOptNameSymbols,               required_argument,  &longopt, kLongOptSymbols },
197
198    { kOptNameAllPersonalities,      no_argument,        &longopt, kLongOptAllPersonalities },
199    { kOptNameNoLinkFailures,        no_argument,        &longopt, kLongOptNoLinkFailures },
200    { kOptNameStripSymbols,          no_argument,        &longopt, kLongOptStripSymbols },
201
202#if !NO_BOOT_ROOT
203    { kOptNameUpdate,                required_argument,  NULL,     kOptUpdate },
204    { kOptNameForce,                 no_argument,        NULL,     kOptForce },
205    { kOptNameInstaller,             no_argument,        &longopt, kLongOptInstaller },
206    { kOptNameCachesOnly,            no_argument,        &longopt, kLongOptCachesOnly },
207#endif /* !NO_BOOT_ROOT */
208
209    { kOptNameNoAuthentication,      no_argument,        NULL,     kOptNoAuthentication },
210    { kOptNameTests,                 no_argument,        NULL,     kOptTests },
211
212#if !NO_BOOT_ROOT
213    { NULL,                          required_argument,  NULL,     kOptCheckUpdate },
214#endif /* !NO_BOOT_ROOT */
215    { NULL,                          no_argument,        NULL,     kOptLowPriorityFork },
216
217    { NULL, 0, NULL, 0 }  // sentinel to terminate list
218};
219
220typedef struct {
221    OSKextRequiredFlags requiredFlagsRepositoriesOnly;  // -l/-n/-s
222    OSKextRequiredFlags requiredFlagsAll;              // -L/-N/-S
223
224    Boolean   updateSystemCaches;   // -system-caches
225    Boolean   lowPriorityFlag;      // -F
226    Boolean   printTestResults;     // -t
227    Boolean   skipAuthentication;   // -z
228
229    CFURLRef  volumeRootURL;        // for mkext/prelinked kernel
230
231    char    * mkextPath;         // mkext option arg
232    int       mkextVersion;      // -mkext1/-mkext2  0 (no mkext, 1 (old format),
233                                    // or 2 (new format)
234
235    char    * prelinkedKernelPath;            // -c option
236    Boolean   needDefaultPrelinkedKernelInfo; // -c option w/o arg;
237                                              // prelinkedKernelURL is parent
238                                              // directory of final kernelcache
239                                              // until we create the cache
240
241    Boolean   needLoadedKextInfo;           // -r option
242    Boolean   generatePrelinkedSymbols;     // -symbols option
243    Boolean   includeAllPersonalities;      // -all-personalities option
244    Boolean   noLinkFailures;               // -no-link-failures option
245    Boolean   stripSymbols;                 // -strip-symbols option
246    CFURLRef  compressedPrelinkedKernelURL; // -uncompress option
247
248    CFURLRef  updateVolumeURL;  // -u/-U options
249    Boolean   expectUpToDate;   // -U
250    Boolean   forceUpdateFlag;  // -f
251    Boolean   installerCalled;  // -Installer
252    Boolean   cachesOnly;   // -caches-only
253
254    char    * kernelPath;    // overriden by -k option
255    CFDataRef kernelFile;    // contents of kernelURL
256    CFURLRef  symbolDirURL;  // -s option;
257
258    CFMutableSetRef    kextIDs;          // -b; must release
259    CFMutableArrayRef  argURLs;          // directories & kexts in order
260    CFMutableArrayRef  repositoryURLs;  // array of CFURLRefs for extensions dirs
261    CFMutableArrayRef  namedKextURLs;
262    CFMutableArrayRef  targetArchs;
263    Boolean            explicitArch;  // user-provided instead of inferred host arches
264
265    CFArrayRef         allKexts;         // directories + named
266    CFArrayRef         repositoryKexts;  // all from directories (may include named)
267    CFArrayRef         namedKexts;
268    CFArrayRef         loadedKexts;
269
270    struct timeval     kernelTimes[2];          // access and mod times of kernel file
271    struct timeval     extensionsDirTimes[2];   // access and mod times of extensions directory with most recent change
272    Boolean     compress;
273    Boolean     uncompress;
274} KextcacheArgs;
275
276#pragma mark Function Prototypes
277/*******************************************************************************
278* Function Prototypes
279*******************************************************************************/
280ExitStatus readArgs(
281    int            * argc,
282    char * const  ** argv,
283    KextcacheArgs  * toolArgs);
284void setDefaultArchesIfNeeded(KextcacheArgs * toolArgs);
285void addArch(
286    KextcacheArgs * toolArgs,
287    const NXArchInfo  * arch);
288const NXArchInfo * addArchForName(
289    KextcacheArgs * toolArgs,
290    const char    * archname);
291ExitStatus readPrelinkedKernelArgs(
292    KextcacheArgs * toolArgs,
293    int             argc,
294    char * const  * argv,
295    Boolean         isLongopt);
296ExitStatus setPrelinkedKernelArgs(
297    KextcacheArgs * toolArgs,
298    char          * filename);
299Boolean setDefaultKernel(KextcacheArgs * toolArgs);
300Boolean setDefaultPrelinkedKernel(KextcacheArgs * toolArgs);
301void setSystemExtensionsFolders(KextcacheArgs * toolArgs);
302ExitStatus doUpdateVolume(KextcacheArgs *toolArgs);
303
304void checkKextdSpawnedFilter(Boolean kernelFlag);
305ExitStatus checkArgs(KextcacheArgs * toolArgs);
306
307ExitStatus getLoadedKextInfo(KextcacheArgs *toolArgs);
308ExitStatus updateSystemPlistCaches(KextcacheArgs * toolArgs);
309ExitStatus updateDirectoryCaches(
310    KextcacheArgs * toolArgs,
311    CFURLRef folderURL);
312ExitStatus createMkext(
313    KextcacheArgs * toolArgs,
314    Boolean       * fatalOut);
315ExitStatus filterKextsForCache(
316    KextcacheArgs     * toolArgs,
317    CFMutableArrayRef   kextArray,
318    const NXArchInfo  * arch,
319    Boolean           * fatalOut);
320Boolean checkKextForArchive(
321    KextcacheArgs       toolArgs,
322    OSKextRef           aKext,
323    const char        * archiveTypeName,
324    const NXArchInfo  * archInfo,
325    OSKextRequiredFlags requiredFlags);
326Boolean kextMatchesFilter(
327    KextcacheArgs             * toolArgs,
328    OSKextRef                   theKext,
329    OSKextRequiredFlags         requiredFlags);
330ExitStatus getFileURLModTimePlusOne(
331    CFURLRef            fileURL,
332    struct timeval    * origModTime,
333    struct timeval      cacheFileTimes[2]);
334ExitStatus getFilePathModTimePlusOne(
335    const char        * filePath,
336    struct timeval    * origModTime,
337    struct timeval      cacheFileTimes[2]);
338Boolean kextMatchesLoadedKextInfo(
339    KextcacheArgs     * toolArgs,
340    OSKextRef           theKext);
341ExitStatus createPrelinkedKernelArchs(
342    KextcacheArgs     * toolArgs,
343    CFMutableArrayRef * prelinkArchsOut);
344ExitStatus createExistingPrelinkedSlices(
345    KextcacheArgs     * toolArgs,
346    CFMutableArrayRef * prelinkedSlicesOut,
347    CFMutableArrayRef * prelinkedArchsOut);
348ExitStatus createPrelinkedKernel(
349    KextcacheArgs     * toolArgs);
350CFArrayRef mergeArchs(
351    CFArrayRef  archSet1,
352    CFArrayRef  archSet2);
353ExitStatus createPrelinkedKernelForArch(
354    KextcacheArgs       * toolArgs,
355    CFDataRef           * prelinkedKernelOut,
356    CFDictionaryRef     * prelinkedSymbolsOut,
357    const NXArchInfo    * archInfo);
358ExitStatus getExpectedPrelinkedKernelModTime(
359    KextcacheArgs  * toolArgs,
360    struct timeval   cacheFileTimes[2],
361    Boolean        * updateModTimeOut);
362ExitStatus compressPrelinkedKernel(
363    const char        * prelinkedKernelPath,
364    Boolean             compress);
365
366void usage(UsageLevel usageLevel);
367
368#endif /* _KEXTCACHE_MAIN_H */
369