1*a325d9c4SApple OSS Distributions /*
2*a325d9c4SApple OSS Distributions * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
3*a325d9c4SApple OSS Distributions *
4*a325d9c4SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*a325d9c4SApple OSS Distributions *
6*a325d9c4SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*a325d9c4SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*a325d9c4SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*a325d9c4SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*a325d9c4SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*a325d9c4SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*a325d9c4SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*a325d9c4SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*a325d9c4SApple OSS Distributions *
15*a325d9c4SApple OSS Distributions * Please obtain a copy of the License at
16*a325d9c4SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*a325d9c4SApple OSS Distributions *
18*a325d9c4SApple OSS Distributions * The Original Code and all software distributed under the License are
19*a325d9c4SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*a325d9c4SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*a325d9c4SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*a325d9c4SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*a325d9c4SApple OSS Distributions * Please see the License for the specific language governing rights and
24*a325d9c4SApple OSS Distributions * limitations under the License.
25*a325d9c4SApple OSS Distributions *
26*a325d9c4SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*a325d9c4SApple OSS Distributions */
28*a325d9c4SApple OSS Distributions extern "C" {
29*a325d9c4SApple OSS Distributions #include <mach/kmod.h>
30*a325d9c4SApple OSS Distributions #include <libkern/kernel_mach_header.h>
31*a325d9c4SApple OSS Distributions #include <libkern/prelink.h>
32*a325d9c4SApple OSS Distributions #include <libkern/crypto/sha2.h>
33*a325d9c4SApple OSS Distributions }
34*a325d9c4SApple OSS Distributions
35*a325d9c4SApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR
36*a325d9c4SApple OSS Distributions
37*a325d9c4SApple OSS Distributions #include <libkern/version.h>
38*a325d9c4SApple OSS Distributions #include <libkern/c++/OSContainers.h>
39*a325d9c4SApple OSS Distributions #include <libkern/OSKextLibPrivate.h>
40*a325d9c4SApple OSS Distributions #include <libkern/c++/OSKext.h>
41*a325d9c4SApple OSS Distributions #include <IOKit/IOLib.h>
42*a325d9c4SApple OSS Distributions #include <IOKit/IOService.h>
43*a325d9c4SApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h>
44*a325d9c4SApple OSS Distributions #include <IOKit/IOCatalogue.h>
45*a325d9c4SApple OSS Distributions
46*a325d9c4SApple OSS Distributions #if __x86_64__
47*a325d9c4SApple OSS Distributions #define KASLR_KEXT_DEBUG 0
48*a325d9c4SApple OSS Distributions #endif
49*a325d9c4SApple OSS Distributions
50*a325d9c4SApple OSS Distributions #if PRAGMA_MARK
51*a325d9c4SApple OSS Distributions #pragma mark Bootstrap Declarations
52*a325d9c4SApple OSS Distributions #endif
53*a325d9c4SApple OSS Distributions /*********************************************************************
54*a325d9c4SApple OSS Distributions * Bootstrap Declarations
55*a325d9c4SApple OSS Distributions *
56*a325d9c4SApple OSS Distributions * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
57*a325d9c4SApple OSS Distributions * code from other parts of the kernel, so function symbols are not
58*a325d9c4SApple OSS Distributions * exported; rather pointers to those functions are exported.
59*a325d9c4SApple OSS Distributions *
60*a325d9c4SApple OSS Distributions * xxx - need to think about locking for handling the 'weak' refs.
61*a325d9c4SApple OSS Distributions * xxx - do export a non-KLD function that says you've called a
62*a325d9c4SApple OSS Distributions * xxx - bootstrap function that has been removed.
63*a325d9c4SApple OSS Distributions *
64*a325d9c4SApple OSS Distributions * ALL call-ins to this segment of the kernel must be done through
65*a325d9c4SApple OSS Distributions * exported pointers. The symbols themselves are private and not to
66*a325d9c4SApple OSS Distributions * be linked against.
67*a325d9c4SApple OSS Distributions *********************************************************************/
68*a325d9c4SApple OSS Distributions extern "C" {
69*a325d9c4SApple OSS Distributions extern void (*record_startup_extensions_function)(void);
70*a325d9c4SApple OSS Distributions extern void (*load_security_extensions_function)(void);
71*a325d9c4SApple OSS Distributions };
72*a325d9c4SApple OSS Distributions
73*a325d9c4SApple OSS Distributions static void bootstrapRecordStartupExtensions(void);
74*a325d9c4SApple OSS Distributions static void bootstrapLoadSecurityExtensions(void);
75*a325d9c4SApple OSS Distributions
76*a325d9c4SApple OSS Distributions
77*a325d9c4SApple OSS Distributions #if NO_KEXTD
78*a325d9c4SApple OSS Distributions extern "C" bool IORamDiskBSDRoot(void);
79*a325d9c4SApple OSS Distributions #endif
80*a325d9c4SApple OSS Distributions
81*a325d9c4SApple OSS Distributions #if PRAGMA_MARK
82*a325d9c4SApple OSS Distributions #pragma mark Macros
83*a325d9c4SApple OSS Distributions #endif
84*a325d9c4SApple OSS Distributions /*********************************************************************
85*a325d9c4SApple OSS Distributions * Macros
86*a325d9c4SApple OSS Distributions *********************************************************************/
87*a325d9c4SApple OSS Distributions #define CONST_STRLEN(str) (sizeof(str) - 1)
88*a325d9c4SApple OSS Distributions
89*a325d9c4SApple OSS Distributions #if PRAGMA_MARK
90*a325d9c4SApple OSS Distributions #pragma mark Kernel Component Kext Identifiers
91*a325d9c4SApple OSS Distributions #endif
92*a325d9c4SApple OSS Distributions /*********************************************************************
93*a325d9c4SApple OSS Distributions * Kernel Component Kext Identifiers
94*a325d9c4SApple OSS Distributions *
95*a325d9c4SApple OSS Distributions * We could have each kernel resource kext automatically "load" as
96*a325d9c4SApple OSS Distributions * it's created, but it's nicer to have them listed in kextstat in
97*a325d9c4SApple OSS Distributions * the order of this list. We'll walk through this after setting up
98*a325d9c4SApple OSS Distributions * all the boot kexts and have them load up.
99*a325d9c4SApple OSS Distributions *********************************************************************/
100*a325d9c4SApple OSS Distributions static const char * sKernelComponentNames[] = {
101*a325d9c4SApple OSS Distributions // The kexts for these IDs must have a version matching 'osrelease'.
102*a325d9c4SApple OSS Distributions "com.apple.kernel",
103*a325d9c4SApple OSS Distributions "com.apple.kpi.bsd",
104*a325d9c4SApple OSS Distributions "com.apple.kpi.dsep",
105*a325d9c4SApple OSS Distributions "com.apple.kpi.iokit",
106*a325d9c4SApple OSS Distributions "com.apple.kpi.kasan",
107*a325d9c4SApple OSS Distributions "com.apple.kpi.kcov",
108*a325d9c4SApple OSS Distributions "com.apple.kpi.libkern",
109*a325d9c4SApple OSS Distributions "com.apple.kpi.mach",
110*a325d9c4SApple OSS Distributions "com.apple.kpi.private",
111*a325d9c4SApple OSS Distributions "com.apple.kpi.unsupported",
112*a325d9c4SApple OSS Distributions "com.apple.iokit.IONVRAMFamily",
113*a325d9c4SApple OSS Distributions "com.apple.driver.AppleNMI",
114*a325d9c4SApple OSS Distributions "com.apple.iokit.IOSystemManagementFamily",
115*a325d9c4SApple OSS Distributions "com.apple.iokit.ApplePlatformFamily",
116*a325d9c4SApple OSS Distributions NULL
117*a325d9c4SApple OSS Distributions };
118*a325d9c4SApple OSS Distributions
119*a325d9c4SApple OSS Distributions #if PRAGMA_MARK
120*a325d9c4SApple OSS Distributions #pragma mark KLDBootstrap Class
121*a325d9c4SApple OSS Distributions #endif
122*a325d9c4SApple OSS Distributions /*********************************************************************
123*a325d9c4SApple OSS Distributions * KLDBootstrap Class
124*a325d9c4SApple OSS Distributions *
125*a325d9c4SApple OSS Distributions * We use a C++ class here so that it can be a friend of OSKext and
126*a325d9c4SApple OSS Distributions * get at private stuff. We can't hide the class itself, but we can
127*a325d9c4SApple OSS Distributions * hide the instance through which we invoke the functions.
128*a325d9c4SApple OSS Distributions *********************************************************************/
129*a325d9c4SApple OSS Distributions class KLDBootstrap {
130*a325d9c4SApple OSS Distributions friend void bootstrapRecordStartupExtensions(void);
131*a325d9c4SApple OSS Distributions friend void bootstrapLoadSecurityExtensions(void);
132*a325d9c4SApple OSS Distributions
133*a325d9c4SApple OSS Distributions private:
134*a325d9c4SApple OSS Distributions void readStartupExtensions(void);
135*a325d9c4SApple OSS Distributions
136*a325d9c4SApple OSS Distributions void readPrelinkedExtensions(kernel_mach_header_t *mh, kc_kind_t type);
137*a325d9c4SApple OSS Distributions void readBooterExtensions(void);
138*a325d9c4SApple OSS Distributions
139*a325d9c4SApple OSS Distributions OSReturn loadKernelComponentKexts(void);
140*a325d9c4SApple OSS Distributions void loadKernelExternalComponents(void);
141*a325d9c4SApple OSS Distributions void readBuiltinPersonalities(void);
142*a325d9c4SApple OSS Distributions
143*a325d9c4SApple OSS Distributions void loadSecurityExtensions(void);
144*a325d9c4SApple OSS Distributions
145*a325d9c4SApple OSS Distributions public:
146*a325d9c4SApple OSS Distributions KLDBootstrap(void);
147*a325d9c4SApple OSS Distributions ~KLDBootstrap(void);
148*a325d9c4SApple OSS Distributions };
149*a325d9c4SApple OSS Distributions
150*a325d9c4SApple OSS Distributions LIBKERN_ALWAYS_DESTROY static KLDBootstrap sBootstrapObject;
151*a325d9c4SApple OSS Distributions
152*a325d9c4SApple OSS Distributions /*********************************************************************
153*a325d9c4SApple OSS Distributions * Set the function pointers for the entry points into the bootstrap
154*a325d9c4SApple OSS Distributions * segment upon C++ static constructor invocation.
155*a325d9c4SApple OSS Distributions *********************************************************************/
KLDBootstrap(void)156*a325d9c4SApple OSS Distributions KLDBootstrap::KLDBootstrap(void)
157*a325d9c4SApple OSS Distributions {
158*a325d9c4SApple OSS Distributions if (this != &sBootstrapObject) {
159*a325d9c4SApple OSS Distributions panic("Attempt to access bootstrap segment.");
160*a325d9c4SApple OSS Distributions }
161*a325d9c4SApple OSS Distributions record_startup_extensions_function = &bootstrapRecordStartupExtensions;
162*a325d9c4SApple OSS Distributions load_security_extensions_function = &bootstrapLoadSecurityExtensions;
163*a325d9c4SApple OSS Distributions }
164*a325d9c4SApple OSS Distributions
165*a325d9c4SApple OSS Distributions /*********************************************************************
166*a325d9c4SApple OSS Distributions * Clear the function pointers for the entry points into the bootstrap
167*a325d9c4SApple OSS Distributions * segment upon C++ static destructor invocation.
168*a325d9c4SApple OSS Distributions *********************************************************************/
~KLDBootstrap(void)169*a325d9c4SApple OSS Distributions KLDBootstrap::~KLDBootstrap(void)
170*a325d9c4SApple OSS Distributions {
171*a325d9c4SApple OSS Distributions if (this != &sBootstrapObject) {
172*a325d9c4SApple OSS Distributions panic("Attempt to access bootstrap segment.");
173*a325d9c4SApple OSS Distributions }
174*a325d9c4SApple OSS Distributions
175*a325d9c4SApple OSS Distributions
176*a325d9c4SApple OSS Distributions record_startup_extensions_function = NULL;
177*a325d9c4SApple OSS Distributions load_security_extensions_function = NULL;
178*a325d9c4SApple OSS Distributions }
179*a325d9c4SApple OSS Distributions
180*a325d9c4SApple OSS Distributions /*********************************************************************
181*a325d9c4SApple OSS Distributions *********************************************************************/
182*a325d9c4SApple OSS Distributions void
readStartupExtensions(void)183*a325d9c4SApple OSS Distributions KLDBootstrap::readStartupExtensions(void)
184*a325d9c4SApple OSS Distributions {
185*a325d9c4SApple OSS Distributions kernel_section_t * prelinkInfoSect = NULL; // do not free
186*a325d9c4SApple OSS Distributions
187*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
188*a325d9c4SApple OSS Distributions kOSKextLogProgressLevel |
189*a325d9c4SApple OSS Distributions kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag |
190*a325d9c4SApple OSS Distributions kOSKextLogKextBookkeepingFlag,
191*a325d9c4SApple OSS Distributions "Reading startup extensions.");
192*a325d9c4SApple OSS Distributions
193*a325d9c4SApple OSS Distributions kc_format_t kc_format;
194*a325d9c4SApple OSS Distributions kernel_mach_header_t *mh = &_mh_execute_header;
195*a325d9c4SApple OSS Distributions if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
196*a325d9c4SApple OSS Distributions mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
197*a325d9c4SApple OSS Distributions }
198*a325d9c4SApple OSS Distributions
199*a325d9c4SApple OSS Distributions /* If the prelink info segment has a nonzero size, we are prelinked
200*a325d9c4SApple OSS Distributions * and won't have any individual kexts or mkexts to read.
201*a325d9c4SApple OSS Distributions * Otherwise, we need to read kexts or the mkext from what the booter
202*a325d9c4SApple OSS Distributions * has handed us.
203*a325d9c4SApple OSS Distributions */
204*a325d9c4SApple OSS Distributions prelinkInfoSect = getsectbynamefromheader(mh, kPrelinkInfoSegment, kPrelinkInfoSection);
205*a325d9c4SApple OSS Distributions if (prelinkInfoSect->size) {
206*a325d9c4SApple OSS Distributions readPrelinkedExtensions(mh, KCKindPrimary);
207*a325d9c4SApple OSS Distributions } else {
208*a325d9c4SApple OSS Distributions readBooterExtensions();
209*a325d9c4SApple OSS Distributions }
210*a325d9c4SApple OSS Distributions
211*a325d9c4SApple OSS Distributions kernel_mach_header_t *akc_mh;
212*a325d9c4SApple OSS Distributions akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
213*a325d9c4SApple OSS Distributions if (akc_mh) {
214*a325d9c4SApple OSS Distributions readPrelinkedExtensions(akc_mh, KCKindAuxiliary);
215*a325d9c4SApple OSS Distributions }
216*a325d9c4SApple OSS Distributions
217*a325d9c4SApple OSS Distributions loadKernelComponentKexts();
218*a325d9c4SApple OSS Distributions loadKernelExternalComponents();
219*a325d9c4SApple OSS Distributions readBuiltinPersonalities();
220*a325d9c4SApple OSS Distributions OSKext::sendAllKextPersonalitiesToCatalog(true);
221*a325d9c4SApple OSS Distributions
222*a325d9c4SApple OSS Distributions return;
223*a325d9c4SApple OSS Distributions }
224*a325d9c4SApple OSS Distributions
225*a325d9c4SApple OSS Distributions /*********************************************************************
226*a325d9c4SApple OSS Distributions *********************************************************************/
227*a325d9c4SApple OSS Distributions void
readPrelinkedExtensions(kernel_mach_header_t * mh,kc_kind_t type)228*a325d9c4SApple OSS Distributions KLDBootstrap::readPrelinkedExtensions(kernel_mach_header_t *mh, kc_kind_t type)
229*a325d9c4SApple OSS Distributions {
230*a325d9c4SApple OSS Distributions bool ret;
231*a325d9c4SApple OSS Distributions OSSharedPtr<OSData> loaded_kcUUID;
232*a325d9c4SApple OSS Distributions OSSharedPtr<OSString> errorString;
233*a325d9c4SApple OSS Distributions OSSharedPtr<OSObject> parsedXML;
234*a325d9c4SApple OSS Distributions kernel_section_t *infoPlistSection = NULL;
235*a325d9c4SApple OSS Distributions OSDictionary *infoDict = NULL; // do not release
236*a325d9c4SApple OSS Distributions
237*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
238*a325d9c4SApple OSS Distributions kOSKextLogProgressLevel |
239*a325d9c4SApple OSS Distributions kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
240*a325d9c4SApple OSS Distributions "Starting from prelinked kernel.");
241*a325d9c4SApple OSS Distributions
242*a325d9c4SApple OSS Distributions /*
243*a325d9c4SApple OSS Distributions * The 'infoPlistSection' should contains an XML dictionary that
244*a325d9c4SApple OSS Distributions * contains some meta data about the KC, and also describes each kext
245*a325d9c4SApple OSS Distributions * included in the kext collection. Unserialize this dictionary and
246*a325d9c4SApple OSS Distributions * then iterate over each kext.
247*a325d9c4SApple OSS Distributions */
248*a325d9c4SApple OSS Distributions infoPlistSection = getsectbynamefromheader(mh, kPrelinkInfoSegment, kPrelinkInfoSection);
249*a325d9c4SApple OSS Distributions parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
250*a325d9c4SApple OSS Distributions if (parsedXML) {
251*a325d9c4SApple OSS Distributions infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
252*a325d9c4SApple OSS Distributions }
253*a325d9c4SApple OSS Distributions
254*a325d9c4SApple OSS Distributions if (!infoDict) {
255*a325d9c4SApple OSS Distributions const char *errorCString = "(unknown error)";
256*a325d9c4SApple OSS Distributions
257*a325d9c4SApple OSS Distributions if (errorString && errorString->getCStringNoCopy()) {
258*a325d9c4SApple OSS Distributions errorCString = errorString->getCStringNoCopy();
259*a325d9c4SApple OSS Distributions } else if (parsedXML) {
260*a325d9c4SApple OSS Distributions errorCString = "not a dictionary";
261*a325d9c4SApple OSS Distributions }
262*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
263*a325d9c4SApple OSS Distributions "Error unserializing kext info plist section: %s.", errorCString);
264*a325d9c4SApple OSS Distributions return;
265*a325d9c4SApple OSS Distributions }
266*a325d9c4SApple OSS Distributions
267*a325d9c4SApple OSS Distributions /* Validate that the Kext Collection is prelinked to the loaded KC */
268*a325d9c4SApple OSS Distributions if (type == KCKindAuxiliary) {
269*a325d9c4SApple OSS Distributions if (OSKext::validateKCFileSetUUID(infoDict, KCKindAuxiliary) != 0) {
270*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
271*a325d9c4SApple OSS Distributions "Early boot AuxKC doesn't appear to be linked against the loaded BootKC.");
272*a325d9c4SApple OSS Distributions return;
273*a325d9c4SApple OSS Distributions }
274*a325d9c4SApple OSS Distributions
275*a325d9c4SApple OSS Distributions /*
276*a325d9c4SApple OSS Distributions * Defer further processing of the AuxKC, but keep the
277*a325d9c4SApple OSS Distributions * processed info dictionary around so we can ml_static_free
278*a325d9c4SApple OSS Distributions * the segment.
279*a325d9c4SApple OSS Distributions */
280*a325d9c4SApple OSS Distributions if (!OSKext::registerDeferredKextCollection(mh, parsedXML, KCKindAuxiliary)) {
281*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
282*a325d9c4SApple OSS Distributions "Error deferring AuxKC kext processing: Kexts in this collection will be unusable.");
283*a325d9c4SApple OSS Distributions }
284*a325d9c4SApple OSS Distributions goto skip_adding_kexts;
285*a325d9c4SApple OSS Distributions }
286*a325d9c4SApple OSS Distributions
287*a325d9c4SApple OSS Distributions /*
288*a325d9c4SApple OSS Distributions * this function does all the heavy lifting of adding OSKext objects
289*a325d9c4SApple OSS Distributions * and potentially sliding them if necessary
290*a325d9c4SApple OSS Distributions */
291*a325d9c4SApple OSS Distributions ret = OSKext::addKextsFromKextCollection(mh, infoDict,
292*a325d9c4SApple OSS Distributions kPrelinkTextSegment, loaded_kcUUID, (mh->filetype == MH_FILESET) ? type : KCKindUnknown);
293*a325d9c4SApple OSS Distributions
294*a325d9c4SApple OSS Distributions if (!ret) {
295*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
296*a325d9c4SApple OSS Distributions "Error loading kext info from prelinked primary KC");
297*a325d9c4SApple OSS Distributions return;
298*a325d9c4SApple OSS Distributions }
299*a325d9c4SApple OSS Distributions
300*a325d9c4SApple OSS Distributions /* Copy in the kernelcache UUID */
301*a325d9c4SApple OSS Distributions if (!loaded_kcUUID) {
302*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
303*a325d9c4SApple OSS Distributions "WARNING: did not find UUID in %s KC!", (type == KCKindAuxiliary) ? "Aux" : "Primary");
304*a325d9c4SApple OSS Distributions } else if (type != KCKindAuxiliary) {
305*a325d9c4SApple OSS Distributions kernelcache_uuid_valid = TRUE;
306*a325d9c4SApple OSS Distributions memcpy((void *)&kernelcache_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
307*a325d9c4SApple OSS Distributions uuid_unparse_upper(kernelcache_uuid, kernelcache_uuid_string);
308*a325d9c4SApple OSS Distributions } else {
309*a325d9c4SApple OSS Distributions auxkc_uuid_valid = TRUE;
310*a325d9c4SApple OSS Distributions memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
311*a325d9c4SApple OSS Distributions uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
312*a325d9c4SApple OSS Distributions }
313*a325d9c4SApple OSS Distributions
314*a325d9c4SApple OSS Distributions skip_adding_kexts:
315*a325d9c4SApple OSS Distributions #if CONFIG_KEXT_BASEMENT
316*a325d9c4SApple OSS Distributions if (mh->filetype != MH_FILESET) {
317*a325d9c4SApple OSS Distributions /*
318*a325d9c4SApple OSS Distributions * On CONFIG_KEXT_BASEMENT systems which do _not_ boot the new
319*a325d9c4SApple OSS Distributions * MH_FILESET kext collection, kexts are copied to their own
320*a325d9c4SApple OSS Distributions * special VM region during OSKext init time, so we can free
321*a325d9c4SApple OSS Distributions * the whole segment now.
322*a325d9c4SApple OSS Distributions */
323*a325d9c4SApple OSS Distributions kernel_segment_command_t *prelinkTextSegment = NULL;
324*a325d9c4SApple OSS Distributions prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
325*a325d9c4SApple OSS Distributions if (!prelinkTextSegment) {
326*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
327*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
328*a325d9c4SApple OSS Distributions "Can't find prelinked kexts' text segment.");
329*a325d9c4SApple OSS Distributions return;
330*a325d9c4SApple OSS Distributions }
331*a325d9c4SApple OSS Distributions
332*a325d9c4SApple OSS Distributions ml_static_mfree((vm_offset_t)prelinkTextSegment->vmaddr, prelinkTextSegment->vmsize);
333*a325d9c4SApple OSS Distributions }
334*a325d9c4SApple OSS Distributions #endif /* CONFIG_KEXT_BASEMENT */
335*a325d9c4SApple OSS Distributions
336*a325d9c4SApple OSS Distributions /*
337*a325d9c4SApple OSS Distributions * Free the prelink info segment, we're done with it.
338*a325d9c4SApple OSS Distributions */
339*a325d9c4SApple OSS Distributions kernel_segment_command_t *prelinkInfoSegment = NULL;
340*a325d9c4SApple OSS Distributions prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
341*a325d9c4SApple OSS Distributions if (prelinkInfoSegment) {
342*a325d9c4SApple OSS Distributions ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
343*a325d9c4SApple OSS Distributions (vm_size_t)prelinkInfoSegment->vmsize);
344*a325d9c4SApple OSS Distributions }
345*a325d9c4SApple OSS Distributions
346*a325d9c4SApple OSS Distributions return;
347*a325d9c4SApple OSS Distributions }
348*a325d9c4SApple OSS Distributions
349*a325d9c4SApple OSS Distributions
350*a325d9c4SApple OSS Distributions /*********************************************************************
351*a325d9c4SApple OSS Distributions *********************************************************************/
352*a325d9c4SApple OSS Distributions #define BOOTER_KEXT_PREFIX "Driver-"
353*a325d9c4SApple OSS Distributions
354*a325d9c4SApple OSS Distributions typedef struct _DeviceTreeBuffer {
355*a325d9c4SApple OSS Distributions uint32_t paddr;
356*a325d9c4SApple OSS Distributions uint32_t length;
357*a325d9c4SApple OSS Distributions } _DeviceTreeBuffer;
358*a325d9c4SApple OSS Distributions
359*a325d9c4SApple OSS Distributions void
readBooterExtensions(void)360*a325d9c4SApple OSS Distributions KLDBootstrap::readBooterExtensions(void)
361*a325d9c4SApple OSS Distributions {
362*a325d9c4SApple OSS Distributions OSSharedPtr<IORegistryEntry> booterMemoryMap;
363*a325d9c4SApple OSS Distributions OSSharedPtr<OSDictionary> propertyDict;
364*a325d9c4SApple OSS Distributions OSSharedPtr<OSCollectionIterator> keyIterator;
365*a325d9c4SApple OSS Distributions OSString * deviceTreeName = NULL;// do not release
366*a325d9c4SApple OSS Distributions
367*a325d9c4SApple OSS Distributions const _DeviceTreeBuffer * deviceTreeBuffer = NULL;// do not free
368*a325d9c4SApple OSS Distributions char * booterDataPtr = NULL;// do not free
369*a325d9c4SApple OSS Distributions OSSharedPtr<OSData> booterData;
370*a325d9c4SApple OSS Distributions OSSharedPtr<OSKext> aKext;
371*a325d9c4SApple OSS Distributions
372*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
373*a325d9c4SApple OSS Distributions kOSKextLogProgressLevel |
374*a325d9c4SApple OSS Distributions kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
375*a325d9c4SApple OSS Distributions "Reading startup extensions from booter memory.");
376*a325d9c4SApple OSS Distributions
377*a325d9c4SApple OSS Distributions booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);
378*a325d9c4SApple OSS Distributions
379*a325d9c4SApple OSS Distributions if (!booterMemoryMap) {
380*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
381*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
382*a325d9c4SApple OSS Distributions kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag,
383*a325d9c4SApple OSS Distributions "Can't read booter memory map.");
384*a325d9c4SApple OSS Distributions goto finish;
385*a325d9c4SApple OSS Distributions }
386*a325d9c4SApple OSS Distributions
387*a325d9c4SApple OSS Distributions propertyDict = booterMemoryMap->dictionaryWithProperties();
388*a325d9c4SApple OSS Distributions if (!propertyDict) {
389*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
390*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
391*a325d9c4SApple OSS Distributions kOSKextLogDirectoryScanFlag,
392*a325d9c4SApple OSS Distributions "Can't get property dictionary from memory map.");
393*a325d9c4SApple OSS Distributions goto finish;
394*a325d9c4SApple OSS Distributions }
395*a325d9c4SApple OSS Distributions
396*a325d9c4SApple OSS Distributions keyIterator = OSCollectionIterator::withCollection(propertyDict.get());
397*a325d9c4SApple OSS Distributions if (!keyIterator) {
398*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
399*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
400*a325d9c4SApple OSS Distributions kOSKextLogGeneralFlag,
401*a325d9c4SApple OSS Distributions "Can't allocate iterator for driver images.");
402*a325d9c4SApple OSS Distributions goto finish;
403*a325d9c4SApple OSS Distributions }
404*a325d9c4SApple OSS Distributions
405*a325d9c4SApple OSS Distributions /* Create dictionary of excluded kexts
406*a325d9c4SApple OSS Distributions */
407*a325d9c4SApple OSS Distributions #ifndef CONFIG_EMBEDDED
408*a325d9c4SApple OSS Distributions OSKext::createExcludeListFromBooterData(propertyDict.get(), keyIterator.get());
409*a325d9c4SApple OSS Distributions #endif
410*a325d9c4SApple OSS Distributions // !! reset the iterator, not the pointer
411*a325d9c4SApple OSS Distributions keyIterator->reset();
412*a325d9c4SApple OSS Distributions
413*a325d9c4SApple OSS Distributions while ((deviceTreeName =
414*a325d9c4SApple OSS Distributions OSDynamicCast(OSString, keyIterator->getNextObject()))) {
415*a325d9c4SApple OSS Distributions const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
416*a325d9c4SApple OSS Distributions OSData * deviceTreeEntry = OSDynamicCast(OSData,
417*a325d9c4SApple OSS Distributions propertyDict->getObject(deviceTreeName));
418*a325d9c4SApple OSS Distributions
419*a325d9c4SApple OSS Distributions /* If there is no entry for the name, we can't do much with it. */
420*a325d9c4SApple OSS Distributions if (!deviceTreeEntry) {
421*a325d9c4SApple OSS Distributions continue;
422*a325d9c4SApple OSS Distributions }
423*a325d9c4SApple OSS Distributions
424*a325d9c4SApple OSS Distributions /* Make sure it is a kext */
425*a325d9c4SApple OSS Distributions if (strncmp(devTreeNameCString,
426*a325d9c4SApple OSS Distributions BOOTER_KEXT_PREFIX,
427*a325d9c4SApple OSS Distributions CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
428*a325d9c4SApple OSS Distributions continue;
429*a325d9c4SApple OSS Distributions }
430*a325d9c4SApple OSS Distributions
431*a325d9c4SApple OSS Distributions deviceTreeBuffer = (const _DeviceTreeBuffer *)
432*a325d9c4SApple OSS Distributions deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
433*a325d9c4SApple OSS Distributions if (!deviceTreeBuffer) {
434*a325d9c4SApple OSS Distributions /* We can't get to the data, so we can't do anything,
435*a325d9c4SApple OSS Distributions * not even free it from physical memory (if it's there).
436*a325d9c4SApple OSS Distributions */
437*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
438*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
439*a325d9c4SApple OSS Distributions kOSKextLogDirectoryScanFlag,
440*a325d9c4SApple OSS Distributions "Device tree entry %s has NULL pointer.",
441*a325d9c4SApple OSS Distributions devTreeNameCString);
442*a325d9c4SApple OSS Distributions goto finish; // xxx - continue, panic?
443*a325d9c4SApple OSS Distributions }
444*a325d9c4SApple OSS Distributions
445*a325d9c4SApple OSS Distributions booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
446*a325d9c4SApple OSS Distributions if (!booterDataPtr) {
447*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
448*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
449*a325d9c4SApple OSS Distributions kOSKextLogDirectoryScanFlag,
450*a325d9c4SApple OSS Distributions "Can't get virtual address for device tree entry %s.",
451*a325d9c4SApple OSS Distributions devTreeNameCString);
452*a325d9c4SApple OSS Distributions goto finish;
453*a325d9c4SApple OSS Distributions }
454*a325d9c4SApple OSS Distributions
455*a325d9c4SApple OSS Distributions /* Wrap the booter data buffer in an OSData and set a dealloc function
456*a325d9c4SApple OSS Distributions * so it will take care of the physical memory when freed. Kexts will
457*a325d9c4SApple OSS Distributions * retain the booterData for as long as they need it. Remove the entry
458*a325d9c4SApple OSS Distributions * from the booter memory map after this is done.
459*a325d9c4SApple OSS Distributions */
460*a325d9c4SApple OSS Distributions booterData = OSData::withBytesNoCopy(booterDataPtr,
461*a325d9c4SApple OSS Distributions deviceTreeBuffer->length);
462*a325d9c4SApple OSS Distributions if (!booterData) {
463*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
464*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
465*a325d9c4SApple OSS Distributions kOSKextLogGeneralFlag,
466*a325d9c4SApple OSS Distributions "Error - Can't allocate OSData wrapper for device tree entry %s.",
467*a325d9c4SApple OSS Distributions devTreeNameCString);
468*a325d9c4SApple OSS Distributions goto finish;
469*a325d9c4SApple OSS Distributions }
470*a325d9c4SApple OSS Distributions booterData->setDeallocFunction(osdata_phys_free);
471*a325d9c4SApple OSS Distributions
472*a325d9c4SApple OSS Distributions /* Create the kext for the entry, then release it, because the
473*a325d9c4SApple OSS Distributions * kext system keeps them around until explicitly removed.
474*a325d9c4SApple OSS Distributions * Any creation/registration failures are already logged for us.
475*a325d9c4SApple OSS Distributions */
476*a325d9c4SApple OSS Distributions OSSharedPtr<OSKext> newKext = OSKext::withBooterData(deviceTreeName, booterData.get());
477*a325d9c4SApple OSS Distributions
478*a325d9c4SApple OSS Distributions booterMemoryMap->removeProperty(deviceTreeName);
479*a325d9c4SApple OSS Distributions } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
480*a325d9c4SApple OSS Distributions
481*a325d9c4SApple OSS Distributions finish:
482*a325d9c4SApple OSS Distributions return;
483*a325d9c4SApple OSS Distributions }
484*a325d9c4SApple OSS Distributions
485*a325d9c4SApple OSS Distributions /*********************************************************************
486*a325d9c4SApple OSS Distributions *********************************************************************/
487*a325d9c4SApple OSS Distributions #define COM_APPLE "com.apple."
488*a325d9c4SApple OSS Distributions
489*a325d9c4SApple OSS Distributions void
loadSecurityExtensions(void)490*a325d9c4SApple OSS Distributions KLDBootstrap::loadSecurityExtensions(void)
491*a325d9c4SApple OSS Distributions {
492*a325d9c4SApple OSS Distributions OSSharedPtr<OSDictionary> extensionsDict;
493*a325d9c4SApple OSS Distributions OSSharedPtr<OSCollectionIterator> keyIterator;
494*a325d9c4SApple OSS Distributions OSString * bundleID = NULL;// don't release
495*a325d9c4SApple OSS Distributions OSKext * theKext = NULL;// don't release
496*a325d9c4SApple OSS Distributions
497*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
498*a325d9c4SApple OSS Distributions kOSKextLogStepLevel |
499*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
500*a325d9c4SApple OSS Distributions "Loading security extensions.");
501*a325d9c4SApple OSS Distributions
502*a325d9c4SApple OSS Distributions extensionsDict = OSKext::copyKexts();
503*a325d9c4SApple OSS Distributions if (!extensionsDict) {
504*a325d9c4SApple OSS Distributions return;
505*a325d9c4SApple OSS Distributions }
506*a325d9c4SApple OSS Distributions
507*a325d9c4SApple OSS Distributions keyIterator = OSCollectionIterator::withCollection(extensionsDict.get());
508*a325d9c4SApple OSS Distributions if (!keyIterator) {
509*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
510*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
511*a325d9c4SApple OSS Distributions kOSKextLogGeneralFlag,
512*a325d9c4SApple OSS Distributions "Failed to allocate iterator for security extensions.");
513*a325d9c4SApple OSS Distributions goto finish;
514*a325d9c4SApple OSS Distributions }
515*a325d9c4SApple OSS Distributions
516*a325d9c4SApple OSS Distributions while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
517*a325d9c4SApple OSS Distributions const char * bundle_id = bundleID->getCStringNoCopy();
518*a325d9c4SApple OSS Distributions
519*a325d9c4SApple OSS Distributions /* Skip extensions whose bundle IDs don't start with "com.apple.".
520*a325d9c4SApple OSS Distributions */
521*a325d9c4SApple OSS Distributions if (!bundle_id ||
522*a325d9c4SApple OSS Distributions (strncmp(bundle_id, COM_APPLE, CONST_STRLEN(COM_APPLE)) != 0)) {
523*a325d9c4SApple OSS Distributions continue;
524*a325d9c4SApple OSS Distributions }
525*a325d9c4SApple OSS Distributions
526*a325d9c4SApple OSS Distributions theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
527*a325d9c4SApple OSS Distributions if (!theKext) {
528*a325d9c4SApple OSS Distributions continue;
529*a325d9c4SApple OSS Distributions }
530*a325d9c4SApple OSS Distributions
531*a325d9c4SApple OSS Distributions if (kOSBooleanTrue == theKext->getPropertyForHostArch(kAppleSecurityExtensionKey)) {
532*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
533*a325d9c4SApple OSS Distributions kOSKextLogStepLevel |
534*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
535*a325d9c4SApple OSS Distributions "Loading security extension %s.", bundleID->getCStringNoCopy());
536*a325d9c4SApple OSS Distributions OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
537*a325d9c4SApple OSS Distributions /* allowDefer */ false);
538*a325d9c4SApple OSS Distributions }
539*a325d9c4SApple OSS Distributions }
540*a325d9c4SApple OSS Distributions
541*a325d9c4SApple OSS Distributions finish:
542*a325d9c4SApple OSS Distributions return;
543*a325d9c4SApple OSS Distributions }
544*a325d9c4SApple OSS Distributions
545*a325d9c4SApple OSS Distributions /*********************************************************************
546*a325d9c4SApple OSS Distributions * We used to require that all listed kernel components load, but
547*a325d9c4SApple OSS Distributions * nowadays we can get them from userland so we only try to load the
548*a325d9c4SApple OSS Distributions * ones we have. If an error occurs later, such is life.
549*a325d9c4SApple OSS Distributions *
550*a325d9c4SApple OSS Distributions * Note that we look the kexts up first, so we can avoid spurious
551*a325d9c4SApple OSS Distributions * (in this context, anyhow) log messages about kexts not being found.
552*a325d9c4SApple OSS Distributions *
553*a325d9c4SApple OSS Distributions * xxx - do we even need to do this any more? Check if the kernel
554*a325d9c4SApple OSS Distributions * xxx - compoonents just load in the regular paths
555*a325d9c4SApple OSS Distributions *********************************************************************/
556*a325d9c4SApple OSS Distributions OSReturn
loadKernelComponentKexts(void)557*a325d9c4SApple OSS Distributions KLDBootstrap::loadKernelComponentKexts(void)
558*a325d9c4SApple OSS Distributions {
559*a325d9c4SApple OSS Distributions OSReturn result = kOSReturnSuccess;// optimistic
560*a325d9c4SApple OSS Distributions OSSharedPtr<OSKext> theKext;
561*a325d9c4SApple OSS Distributions const char ** kextIDPtr = NULL; // do not release
562*a325d9c4SApple OSS Distributions
563*a325d9c4SApple OSS Distributions for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) {
564*a325d9c4SApple OSS Distributions theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr);
565*a325d9c4SApple OSS Distributions
566*a325d9c4SApple OSS Distributions if (theKext) {
567*a325d9c4SApple OSS Distributions if (kOSReturnSuccess != OSKext::loadKextWithIdentifier(
568*a325d9c4SApple OSS Distributions *kextIDPtr, /* allowDefer */ false)) {
569*a325d9c4SApple OSS Distributions // xxx - check KextBookkeeping, might be redundant
570*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
571*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
572*a325d9c4SApple OSS Distributions kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
573*a325d9c4SApple OSS Distributions "Failed to initialize kernel component %s.", *kextIDPtr);
574*a325d9c4SApple OSS Distributions result = kOSReturnError;
575*a325d9c4SApple OSS Distributions }
576*a325d9c4SApple OSS Distributions }
577*a325d9c4SApple OSS Distributions }
578*a325d9c4SApple OSS Distributions
579*a325d9c4SApple OSS Distributions return result;
580*a325d9c4SApple OSS Distributions }
581*a325d9c4SApple OSS Distributions
582*a325d9c4SApple OSS Distributions /*********************************************************************
583*a325d9c4SApple OSS Distributions * Ensure that Kernel External Components are loaded early in boot,
584*a325d9c4SApple OSS Distributions * before other kext personalities get sent to the IOCatalogue. These
585*a325d9c4SApple OSS Distributions * kexts are treated specially because they may provide the implementation
586*a325d9c4SApple OSS Distributions * for kernel-vended KPI, so they must register themselves before
587*a325d9c4SApple OSS Distributions * general purpose IOKit probing begins.
588*a325d9c4SApple OSS Distributions *********************************************************************/
589*a325d9c4SApple OSS Distributions
590*a325d9c4SApple OSS Distributions #define COM_APPLE_KEC "com.apple.kec."
591*a325d9c4SApple OSS Distributions
592*a325d9c4SApple OSS Distributions void
loadKernelExternalComponents(void)593*a325d9c4SApple OSS Distributions KLDBootstrap::loadKernelExternalComponents(void)
594*a325d9c4SApple OSS Distributions {
595*a325d9c4SApple OSS Distributions OSSharedPtr<OSDictionary> extensionsDict;
596*a325d9c4SApple OSS Distributions OSSharedPtr<OSCollectionIterator> keyIterator;
597*a325d9c4SApple OSS Distributions OSString * bundleID = NULL;// don't release
598*a325d9c4SApple OSS Distributions OSKext * theKext = NULL;// don't release
599*a325d9c4SApple OSS Distributions OSBoolean * isKernelExternalComponent = NULL;// don't release
600*a325d9c4SApple OSS Distributions
601*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
602*a325d9c4SApple OSS Distributions kOSKextLogStepLevel |
603*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
604*a325d9c4SApple OSS Distributions "Loading Kernel External Components.");
605*a325d9c4SApple OSS Distributions
606*a325d9c4SApple OSS Distributions extensionsDict = OSKext::copyKexts();
607*a325d9c4SApple OSS Distributions if (!extensionsDict) {
608*a325d9c4SApple OSS Distributions return;
609*a325d9c4SApple OSS Distributions }
610*a325d9c4SApple OSS Distributions
611*a325d9c4SApple OSS Distributions keyIterator = OSCollectionIterator::withCollection(extensionsDict.get());
612*a325d9c4SApple OSS Distributions if (!keyIterator) {
613*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
614*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
615*a325d9c4SApple OSS Distributions kOSKextLogGeneralFlag,
616*a325d9c4SApple OSS Distributions "Failed to allocate iterator for Kernel External Components.");
617*a325d9c4SApple OSS Distributions goto finish;
618*a325d9c4SApple OSS Distributions }
619*a325d9c4SApple OSS Distributions
620*a325d9c4SApple OSS Distributions while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
621*a325d9c4SApple OSS Distributions const char * bundle_id = bundleID->getCStringNoCopy();
622*a325d9c4SApple OSS Distributions
623*a325d9c4SApple OSS Distributions /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
624*a325d9c4SApple OSS Distributions */
625*a325d9c4SApple OSS Distributions if (!bundle_id ||
626*a325d9c4SApple OSS Distributions (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) {
627*a325d9c4SApple OSS Distributions continue;
628*a325d9c4SApple OSS Distributions }
629*a325d9c4SApple OSS Distributions
630*a325d9c4SApple OSS Distributions theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
631*a325d9c4SApple OSS Distributions if (!theKext) {
632*a325d9c4SApple OSS Distributions continue;
633*a325d9c4SApple OSS Distributions }
634*a325d9c4SApple OSS Distributions
635*a325d9c4SApple OSS Distributions isKernelExternalComponent = OSDynamicCast(OSBoolean,
636*a325d9c4SApple OSS Distributions theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey));
637*a325d9c4SApple OSS Distributions if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) {
638*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
639*a325d9c4SApple OSS Distributions kOSKextLogStepLevel |
640*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
641*a325d9c4SApple OSS Distributions "Loading kernel external component %s.", bundleID->getCStringNoCopy());
642*a325d9c4SApple OSS Distributions OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
643*a325d9c4SApple OSS Distributions /* allowDefer */ false);
644*a325d9c4SApple OSS Distributions }
645*a325d9c4SApple OSS Distributions }
646*a325d9c4SApple OSS Distributions
647*a325d9c4SApple OSS Distributions finish:
648*a325d9c4SApple OSS Distributions return;
649*a325d9c4SApple OSS Distributions }
650*a325d9c4SApple OSS Distributions
651*a325d9c4SApple OSS Distributions /*********************************************************************
652*a325d9c4SApple OSS Distributions *********************************************************************/
653*a325d9c4SApple OSS Distributions void
readBuiltinPersonalities(void)654*a325d9c4SApple OSS Distributions KLDBootstrap::readBuiltinPersonalities(void)
655*a325d9c4SApple OSS Distributions {
656*a325d9c4SApple OSS Distributions OSSharedPtr<OSObject> parsedXML;
657*a325d9c4SApple OSS Distributions OSArray * builtinExtensions = NULL;// do not release
658*a325d9c4SApple OSS Distributions OSSharedPtr<OSArray> allPersonalities;
659*a325d9c4SApple OSS Distributions OSSharedPtr<OSString> errorString;
660*a325d9c4SApple OSS Distributions kernel_section_t * infosect = NULL;// do not free
661*a325d9c4SApple OSS Distributions OSSharedPtr<OSCollectionIterator> personalitiesIterator;
662*a325d9c4SApple OSS Distributions unsigned int count, i;
663*a325d9c4SApple OSS Distributions
664*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
665*a325d9c4SApple OSS Distributions kOSKextLogStepLevel |
666*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
667*a325d9c4SApple OSS Distributions "Reading built-in kernel personalities for I/O Kit drivers.");
668*a325d9c4SApple OSS Distributions
669*a325d9c4SApple OSS Distributions /* Look in the __BUILTIN __info segment for an array of Info.plist
670*a325d9c4SApple OSS Distributions * entries. For each one, extract the personalities dictionary, add
671*a325d9c4SApple OSS Distributions * it to our array, then push them all (without matching) to
672*a325d9c4SApple OSS Distributions * the IOCatalogue. This can be used to augment the personalities
673*a325d9c4SApple OSS Distributions * in gIOKernelConfigTables, especially when linking entire kexts into
674*a325d9c4SApple OSS Distributions * the mach_kernel image.
675*a325d9c4SApple OSS Distributions */
676*a325d9c4SApple OSS Distributions infosect = getsectbyname("__BUILTIN", "__info");
677*a325d9c4SApple OSS Distributions if (!infosect) {
678*a325d9c4SApple OSS Distributions // this isn't fatal
679*a325d9c4SApple OSS Distributions goto finish;
680*a325d9c4SApple OSS Distributions }
681*a325d9c4SApple OSS Distributions
682*a325d9c4SApple OSS Distributions parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
683*a325d9c4SApple OSS Distributions errorString);
684*a325d9c4SApple OSS Distributions if (parsedXML) {
685*a325d9c4SApple OSS Distributions builtinExtensions = OSDynamicCast(OSArray, parsedXML.get());
686*a325d9c4SApple OSS Distributions }
687*a325d9c4SApple OSS Distributions if (!builtinExtensions) {
688*a325d9c4SApple OSS Distributions const char * errorCString = "(unknown error)";
689*a325d9c4SApple OSS Distributions
690*a325d9c4SApple OSS Distributions if (errorString && errorString->getCStringNoCopy()) {
691*a325d9c4SApple OSS Distributions errorCString = errorString->getCStringNoCopy();
692*a325d9c4SApple OSS Distributions } else if (parsedXML) {
693*a325d9c4SApple OSS Distributions errorCString = "not an array";
694*a325d9c4SApple OSS Distributions }
695*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
696*a325d9c4SApple OSS Distributions kOSKextLogErrorLevel |
697*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
698*a325d9c4SApple OSS Distributions "Error unserializing built-in personalities: %s.", errorCString);
699*a325d9c4SApple OSS Distributions goto finish;
700*a325d9c4SApple OSS Distributions }
701*a325d9c4SApple OSS Distributions
702*a325d9c4SApple OSS Distributions // estimate 3 personalities per Info.plist/kext
703*a325d9c4SApple OSS Distributions count = builtinExtensions->getCount();
704*a325d9c4SApple OSS Distributions allPersonalities = OSArray::withCapacity(count * 3);
705*a325d9c4SApple OSS Distributions
706*a325d9c4SApple OSS Distributions for (i = 0; i < count; i++) {
707*a325d9c4SApple OSS Distributions OSDictionary * infoDict = NULL;// do not release
708*a325d9c4SApple OSS Distributions OSString * moduleName = NULL;// do not release
709*a325d9c4SApple OSS Distributions OSDictionary * personalities;// do not release
710*a325d9c4SApple OSS Distributions OSString * personalityName;// do not release
711*a325d9c4SApple OSS Distributions
712*a325d9c4SApple OSS Distributions infoDict = OSDynamicCast(OSDictionary,
713*a325d9c4SApple OSS Distributions builtinExtensions->getObject(i));
714*a325d9c4SApple OSS Distributions if (!infoDict) {
715*a325d9c4SApple OSS Distributions continue;
716*a325d9c4SApple OSS Distributions }
717*a325d9c4SApple OSS Distributions
718*a325d9c4SApple OSS Distributions moduleName = OSDynamicCast(OSString,
719*a325d9c4SApple OSS Distributions infoDict->getObject(kCFBundleIdentifierKey));
720*a325d9c4SApple OSS Distributions if (!moduleName) {
721*a325d9c4SApple OSS Distributions continue;
722*a325d9c4SApple OSS Distributions }
723*a325d9c4SApple OSS Distributions
724*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
725*a325d9c4SApple OSS Distributions kOSKextLogStepLevel |
726*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
727*a325d9c4SApple OSS Distributions "Adding personalities for built-in driver %s:",
728*a325d9c4SApple OSS Distributions moduleName->getCStringNoCopy());
729*a325d9c4SApple OSS Distributions
730*a325d9c4SApple OSS Distributions personalities = OSDynamicCast(OSDictionary,
731*a325d9c4SApple OSS Distributions infoDict->getObject("IOKitPersonalities"));
732*a325d9c4SApple OSS Distributions if (!personalities) {
733*a325d9c4SApple OSS Distributions continue;
734*a325d9c4SApple OSS Distributions }
735*a325d9c4SApple OSS Distributions
736*a325d9c4SApple OSS Distributions personalitiesIterator = OSCollectionIterator::withCollection(personalities);
737*a325d9c4SApple OSS Distributions if (!personalitiesIterator) {
738*a325d9c4SApple OSS Distributions continue; // xxx - well really, what can we do? should we panic?
739*a325d9c4SApple OSS Distributions }
740*a325d9c4SApple OSS Distributions
741*a325d9c4SApple OSS Distributions while ((personalityName = OSDynamicCast(OSString,
742*a325d9c4SApple OSS Distributions personalitiesIterator->getNextObject()))) {
743*a325d9c4SApple OSS Distributions OSDictionary * personality = OSDynamicCast(OSDictionary,
744*a325d9c4SApple OSS Distributions personalities->getObject(personalityName));
745*a325d9c4SApple OSS Distributions
746*a325d9c4SApple OSS Distributions OSKextLog(/* kext */ NULL,
747*a325d9c4SApple OSS Distributions kOSKextLogDetailLevel |
748*a325d9c4SApple OSS Distributions kOSKextLogLoadFlag,
749*a325d9c4SApple OSS Distributions "Adding built-in driver personality %s.",
750*a325d9c4SApple OSS Distributions personalityName->getCStringNoCopy());
751*a325d9c4SApple OSS Distributions
752*a325d9c4SApple OSS Distributions if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
753*a325d9c4SApple OSS Distributions personality->setObject(kCFBundleIdentifierKey, moduleName);
754*a325d9c4SApple OSS Distributions }
755*a325d9c4SApple OSS Distributions allPersonalities->setObject(personality);
756*a325d9c4SApple OSS Distributions }
757*a325d9c4SApple OSS Distributions }
758*a325d9c4SApple OSS Distributions
759*a325d9c4SApple OSS Distributions gIOCatalogue->addDrivers(allPersonalities.get(), false);
760*a325d9c4SApple OSS Distributions
761*a325d9c4SApple OSS Distributions finish:
762*a325d9c4SApple OSS Distributions return;
763*a325d9c4SApple OSS Distributions }
764*a325d9c4SApple OSS Distributions
765*a325d9c4SApple OSS Distributions #if PRAGMA_MARK
766*a325d9c4SApple OSS Distributions #pragma mark Bootstrap Functions
767*a325d9c4SApple OSS Distributions #endif
768*a325d9c4SApple OSS Distributions /*********************************************************************
769*a325d9c4SApple OSS Distributions * Bootstrap Functions
770*a325d9c4SApple OSS Distributions *********************************************************************/
771*a325d9c4SApple OSS Distributions static void
bootstrapRecordStartupExtensions(void)772*a325d9c4SApple OSS Distributions bootstrapRecordStartupExtensions(void)
773*a325d9c4SApple OSS Distributions {
774*a325d9c4SApple OSS Distributions sBootstrapObject.readStartupExtensions();
775*a325d9c4SApple OSS Distributions return;
776*a325d9c4SApple OSS Distributions }
777*a325d9c4SApple OSS Distributions
778*a325d9c4SApple OSS Distributions static void
bootstrapLoadSecurityExtensions(void)779*a325d9c4SApple OSS Distributions bootstrapLoadSecurityExtensions(void)
780*a325d9c4SApple OSS Distributions {
781*a325d9c4SApple OSS Distributions sBootstrapObject.loadSecurityExtensions();
782*a325d9c4SApple OSS Distributions return;
783*a325d9c4SApple OSS Distributions }
784*a325d9c4SApple OSS Distributions
785