xref: /xnu-11215/libkern/libkern/mkext.h (revision a5e72196)
1 /*
2  * Copyright (c) 2008 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #ifndef _MKEXT_H_
30 #define _MKEXT_H_ 1
31 
32 #include <sys/cdefs.h>
33 #include <sys/types.h>
34 
35 #include <mach/machine.h>
36 
37 /*********************************************************************
38 * Mkext File Format
39 *
40 * ALL BINARY VALUES ARE BIG-ENDIAN.
41 *********************************************************************/
42 #if PRAGMA_MARK
43 #pragma mark Constants
44 #endif
45 
46 #define MKEXT_MAGIC 0x4D4B5854 /* 'MKXT' */
47 #define MKEXT_SIGN  0x4D4F5358 /* 'MOSX' */
48 
49 #define MKEXT_EXTN  ".mkext"
50 
51 #define MKEXT_VERS_1  (0x01008000)
52 
53 // Used during development/bringup: v 2.0d1
54 #define MKEXT_VERS_2  (0x02002001)
55 // xxx - Will use this when format is final
56 // #define MKEXT_VERS_2  (0x02008000)
57 
58 #if PRAGMA_MARK
59 #pragma mark Core Header
60 #endif
61 /*********************************************************************
62 * Core Header
63 *
64 * All versions of mkext files have this basic header:
65 *
66 * - magic & signature - always 'MKXT' and 'MOSX' as defined above.
67 * - length - the length of the whole file
68 * - adler32 - checksum from &version to end of file
69 * - version - a 'vers' style value
70 * - numkexts - how many kexts are in the archive (only needed in v.1)
71 * - cputype & cpusubtype - in version 1 could be CPU_TYPE_ANY
72 *     and CPU_SUBTYPE_MULTIPLE if the archive contained fat kexts;
73 *     version 2 does not allow this and all kexts must be of a single
74 *     arch. For either version, mkexts of specific arches can be
75 *     embedded in a fat Mach-O file to combine them.
76 *********************************************************************/
77 
78 #define MKEXT_HEADER_CORE      \
79     uint32_t      magic;       \
80     uint32_t      signature;   \
81     uint32_t      length;      \
82     uint32_t      adler32;     \
83     uint32_t      version;     \
84     uint32_t      numkexts;    \
85     cpu_type_t    cputype;     \
86     cpu_subtype_t cpusubtype;
87 
88 typedef struct mkext_basic_header {
89 	MKEXT_HEADER_CORE
90 } mkext_basic_header;
91 
92 #define MKEXT_HDR_CAST(hdr)        ((mkext_basic_header *)(hdr))
93 
94 #define MKEXT_SWAP(num)            OSSwapBigToHostInt32((uint32_t)(num))
95 
96 #define MKEXT_GET_MAGIC(hdr)       (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->magic))
97 #define MKEXT_GET_SIGNATURE(hdr)   (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->signature))
98 #define MKEXT_GET_LENGTH(hdr)      (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->length))
99 #define MKEXT_GET_CHECKSUM(hdr)    (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->adler32))
100 #define MKEXT_GET_VERSION(hdr)     (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->version))
101 #define MKEXT_GET_COUNT(hdr)       (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->numkexts))
102 #define MKEXT_GET_CPUTYPE(hdr)     (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->cputype))
103 #define MKEXT_GET_CPUSUBTYPE(hdr)  (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->cpusubtype))
104 
105 #if PRAGMA_MARK
106 #pragma mark Mkext Version 2 Format Definitions
107 #endif
108 /*********************************************************************
109 * Mkext Version 2 Format Definitions
110 *
111 * The version field here will be some variant of 0x0200....; that is
112 * the  major version byte will be 0x02.
113 *
114 * Version 2 uses zlib for compression, not the lzss compressor used
115 * by version 1.
116 *
117 * In version 2, all executable & resource files are stored in sequence
118 * followed by the combined info dictionaries of all kexts at the end.
119 * This XML plist should be nul-terminated and stored at a page-aligned
120 * offset in the file so that kernel code can unmap it as soon as it's
121 * parsed.
122 *
123 * The info dict for each kext will have inserted into it these
124 * additional properties:
125 *
126 * - _MKEXTBundlePath (string) - full path to the original bundle,
127 *   relative to volume.
128 * - _MKEXTExecutable (integer) - offset to the executable entry.
129 * - _MKEXTResources (dict) - keyed by filename, values integer offsets
130 *   to file entries.
131 *
132 * Mkext2 buffers are used to send load requests to the kernel. When
133 * this is done, the plist will contain an _MKEXTLoadRequest dictionary
134 * whose keys are the bundle IDs to load, and whose values are
135 * dictionaries of flags:
136 *
137 * - "Load Kext" - boolean, whether to load the kext or not (default true).
138 *   May be used to send just personalities for already-loaded kexts,
139 *   but we do have a mechanism to do that from userland already.
140 * - "Start Kext" - boolean, whether to start the kext or not
141 *   (used when debugging). Defaults to true.
142 * - "Add Personalities" - boolean, whether to send personalities to
143 *   the IOCatalogue (used when debugging). Defaults to true.
144 * - "Disable Autounload" - boolean, whether to prevent the reaper
145 *   thread from unloading the kext, so the dev. has time to set up
146 *   the debug session. (Predefined window, or maybe this will be a
147 *   number of seconds to wait.) Defaults to false.
148 *********************************************************************/
149 #define kMKEXTInfoDictionariesKey             "_MKEXTInfoDictionaries"
150 
151 #define kMKEXTBundlePathKey                   "_MKEXTBundlePath"
152 #define kMKEXTExecutableRelativePathKey       "_MKEXTExecutableRelativePath"
153 #define kMKEXTExecutableKey                   "_MKEXTExecutable"
154 
155 #define kMKEXTLoadRequestKey                  "_MKEXTLoadRequest"
156 #define kMKEXTLoadRequestLoadKey              "Load Kext"
157 #define kMKEXTLoadRequestStartKey             "Start Kext"
158 #define kMKEXTLoadRequestAddPersonalitiesKey  "Add Personalities"
159 #define kMKEXTLoadRequestDisableAutounloadKey "Disable Autounload"
160 
161 typedef struct mkext2_file_entry {
162 	uint32_t  compressed_size;// if zero, file is not compressed
163 	uint32_t  full_size;    // full size of data w/o this struct
164 	uint8_t   data[0];      // data is inline to this struct
165 } mkext2_file_entry;
166 
167 typedef struct mkext2_header {
168 	MKEXT_HEADER_CORE
169 	uint32_t plist_offset;
170 	uint32_t plist_compressed_size;
171 	uint32_t plist_full_size;
172 } mkext2_header;
173 
174 #define MKEXT2_GET_ENTRY_COMPSIZE(ptr)   MKEXT_SWAP((ptr)->compressed_size)
175 #define MKEXT2_GET_ENTRY_FULLSIZE(ptr)   MKEXT_SWAP((ptr)->full_size)
176 #define MKEXT2_GET_ENTRY_DATA(ptr)       ((ptr)->data)
177 
178 #define MKEXT2_HDR_CAST(hdr)             ((mkext2_header *)(hdr))
179 #define MKEXT2_GET_PLIST(hdr)            MKEXT_SWAP(MKEXT2_HDR_CAST(hdr)->plist_offset)
180 #define MKEXT2_GET_PLIST_COMPSIZE(hdr)   MKEXT_SWAP(MKEXT2_HDR_CAST(hdr)->plist_compressed_size)
181 #define MKEXT2_GET_PLIST_FULLSIZE(hdr)   MKEXT_SWAP(MKEXT2_HDR_CAST(hdr)->plist_full_size)
182 
183 #if PRAGMA_MARK
184 #pragma mark Mkext Version 1 Format Definitions
185 #endif
186 /*********************************************************************
187 * Mkext Version 1 Format Definitions
188 *
189 * The original mkext format has version 0x01008000 ("1.0").
190 *
191 * In version 1, plists were not nul-terminated, so it's up to the
192 * reader to add that '\0' on the end if it's needed.
193 *
194 * Original bad names preserved for source compatibility.
195 *********************************************************************/
196 
197 // If all fields are 0 then this file slot is empty
198 // If compsize is zero then the file isn't compressed.
199 typedef struct mkext_file {
200 	uint32_t offset;     // 4 bytes
201 	uint32_t compsize;   // 4 bytes
202 	uint32_t realsize;   // 4 bytes
203 	uint32_t modifiedsecs; // 4 bytes; cast to time_t to use
204 } mkext_file;
205 
206 // The plist file entry is mandatory, but module may be empty
207 typedef struct mkext_kext {
208 	mkext_file plist;    // 16 bytes
209 	mkext_file module;   // 16 bytes
210 } mkext_kext;
211 
212 typedef struct mkext_header {
213 	MKEXT_HEADER_CORE
214 	mkext_kext kext[1]; // 32 bytes/entry
215 } mkext_header;
216 
217 typedef mkext_header mkext1_header;
218 
219 #define MKEXT1_ENTRY_CAST(ptr)           ((mkext_file *)(ptr))
220 #define MKEXT1_GET_ENTRY_OFFSET(ptr)     (MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->offset))
221 #define MKEXT1_GET_ENTRY_COMPSIZE(ptr)   (MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->compsize))
222 #define MKEXT1_GET_ENTRY_FULLSIZE(ptr)   (MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->realsize))
223 #define MKEXT1_GET_ENTRY_MODTIME(ptr)    ((time_t)MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->modifiedsecs))
224 #define MKEXT1_ENTRY_EXISTS(ptr)         (MKEXT1_GET_ENTRY_OFFSET(ptr)   ||  \
225 	                                  MKEXT1_GET_ENTRY_FULLSIZE(ptr) ||  \
226 	                                  MKEXT_GET_ENTRY_COMPSIZE(ptr)  ||  \
227 	                                  MKEXT_GET_ENTRY_COMPSIZE(ptr))
228 
229 #define MKEXT1_GET_KEXT(hdr, i)          ((mkext_kext *)&(MKEXT1_HDR_CAST(hdr)->kext[(i)]))
230 #define MKEXT1_GET_KEXT_PLIST(hdr, i)    (MKEXT1_ENTRY_CAST(&(MKEXT1_GET_KEXT((hdr), (i))->plist)))
231 #define MKEXT1_GET_KEXT_EXEC(hdr, i)     (MKEXT1_ENTRY_CAST(&(MKEXT1_GET_KEXT((hdr), (i))->module)
232 
233 #define MKEXT1_HDR_CAST(hdr)             ((mkext1_header *)(hdr))
234 
235 /* These functions are only used for version 1 mkexts.
236  */
237 __BEGIN_DECLS
238 u_int8_t *
239 compress_lzss(u_int8_t * dst, u_int32_t dstlen,
240     u_int8_t * src, u_int32_t srclen);
241 
242 int
243 decompress_lzss(u_int8_t * dst, u_int32_t dstlen,
244     u_int8_t * src, u_int32_t srclen);
245 
246 u_int32_t
247 mkext_adler32(u_int8_t * src, int32_t length);
248 __END_DECLS
249 
250 #endif /* _MKEXT_H_ */
251