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
88typedef 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
161typedef 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
167typedef 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.
199typedef 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
207typedef struct mkext_kext {
208 mkext_file plist; // 16 bytes
209 mkext_file module; // 16 bytes
210} mkext_kext;
211
212typedef struct mkext_header {
213 MKEXT_HEADER_CORE
214 mkext_kext kext[1]; // 32 bytes/entry
215} mkext_header;
216
217typedef 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
238u_int8_t *
239compress_lzss(u_int8_t * dst, u_int32_t dstlen,
240 u_int8_t * src, u_int32_t srclen);
241
242int
243decompress_lzss(u_int8_t * dst, u_int32_t dstlen,
244 u_int8_t * src, u_int32_t srclen);
245
246u_int32_t
247mkext_adler32(u_int8_t * src, int32_t length);
248__END_DECLS
249
250#endif /* _MKEXT_H_ */
251