1c1dac77fSApple OSS Distributions /*
2186b8fceSApple OSS Distributions * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
3c1dac77fSApple OSS Distributions *
4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5c1dac77fSApple OSS Distributions *
6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement.
14c1dac77fSApple OSS Distributions *
15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions *
18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions * limitations under the License.
25c1dac77fSApple OSS Distributions *
26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27c1dac77fSApple OSS Distributions */
283ca3bd55SApple OSS Distributions extern "C" {
29c1dac77fSApple OSS Distributions #include <mach/kmod.h>
303ca3bd55SApple OSS Distributions #include <libkern/kernel_mach_header.h>
313ca3bd55SApple OSS Distributions #include <libkern/prelink.h>
32bb611c8fSApple OSS Distributions #include <libkern/crypto/sha2.h>
33c1dac77fSApple OSS Distributions }
34c1dac77fSApple OSS Distributions
35bb611c8fSApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR
36bb611c8fSApple OSS Distributions
373ca3bd55SApple OSS Distributions #include <libkern/version.h>
383ca3bd55SApple OSS Distributions #include <libkern/c++/OSContainers.h>
393ca3bd55SApple OSS Distributions #include <libkern/OSKextLibPrivate.h>
403ca3bd55SApple OSS Distributions #include <libkern/c++/OSKext.h>
413ca3bd55SApple OSS Distributions #include <IOKit/IOLib.h>
42855239e5SApple OSS Distributions #include <IOKit/IOService.h>
433ca3bd55SApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h>
443ca3bd55SApple OSS Distributions #include <IOKit/IOCatalogue.h>
45c1dac77fSApple OSS Distributions
46d0c1fef6SApple OSS Distributions #if __x86_64__
47d0c1fef6SApple OSS Distributions #define KASLR_KEXT_DEBUG 0
48d0c1fef6SApple OSS Distributions #endif
49d0c1fef6SApple OSS Distributions
503ca3bd55SApple OSS Distributions #if PRAGMA_MARK
513ca3bd55SApple OSS Distributions #pragma mark Bootstrap Declarations
523ca3bd55SApple OSS Distributions #endif
533ca3bd55SApple OSS Distributions /*********************************************************************
543ca3bd55SApple OSS Distributions * Bootstrap Declarations
553ca3bd55SApple OSS Distributions *
563ca3bd55SApple OSS Distributions * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
573ca3bd55SApple OSS Distributions * code from other parts of the kernel, so function symbols are not
583ca3bd55SApple OSS Distributions * exported; rather pointers to those functions are exported.
593ca3bd55SApple OSS Distributions *
603ca3bd55SApple OSS Distributions * xxx - need to think about locking for handling the 'weak' refs.
613ca3bd55SApple OSS Distributions * xxx - do export a non-KLD function that says you've called a
623ca3bd55SApple OSS Distributions * xxx - bootstrap function that has been removed.
633ca3bd55SApple OSS Distributions *
643ca3bd55SApple OSS Distributions * ALL call-ins to this segment of the kernel must be done through
653ca3bd55SApple OSS Distributions * exported pointers. The symbols themselves are private and not to
663ca3bd55SApple OSS Distributions * be linked against.
673ca3bd55SApple OSS Distributions *********************************************************************/
683ca3bd55SApple OSS Distributions extern "C" {
693ca3bd55SApple OSS Distributions extern void (*record_startup_extensions_function)(void);
703ca3bd55SApple OSS Distributions extern void (*load_security_extensions_function)(void);
713ca3bd55SApple OSS Distributions };
72c1dac77fSApple OSS Distributions
733ca3bd55SApple OSS Distributions static void bootstrapRecordStartupExtensions(void);
743ca3bd55SApple OSS Distributions static void bootstrapLoadSecurityExtensions(void);
75c1dac77fSApple OSS Distributions
76855239e5SApple OSS Distributions
77186b8fceSApple OSS Distributions #if NO_KEXTD
78186b8fceSApple OSS Distributions extern "C" bool IORamDiskBSDRoot(void);
79186b8fceSApple OSS Distributions #endif
80186b8fceSApple OSS Distributions
813ca3bd55SApple OSS Distributions #if PRAGMA_MARK
823ca3bd55SApple OSS Distributions #pragma mark Macros
833ca3bd55SApple OSS Distributions #endif
843ca3bd55SApple OSS Distributions /*********************************************************************
853ca3bd55SApple OSS Distributions * Macros
863ca3bd55SApple OSS Distributions *********************************************************************/
873ca3bd55SApple OSS Distributions #define CONST_STRLEN(str) (sizeof(str) - 1)
883ca3bd55SApple OSS Distributions
893ca3bd55SApple OSS Distributions #if PRAGMA_MARK
903ca3bd55SApple OSS Distributions #pragma mark Kernel Component Kext Identifiers
913ca3bd55SApple OSS Distributions #endif
923ca3bd55SApple OSS Distributions /*********************************************************************
933ca3bd55SApple OSS Distributions * Kernel Component Kext Identifiers
943ca3bd55SApple OSS Distributions *
953ca3bd55SApple OSS Distributions * We could have each kernel resource kext automatically "load" as
963ca3bd55SApple OSS Distributions * it's created, but it's nicer to have them listed in kextstat in
973ca3bd55SApple OSS Distributions * the order of this list. We'll walk through this after setting up
983ca3bd55SApple OSS Distributions * all the boot kexts and have them load up.
993ca3bd55SApple OSS Distributions *********************************************************************/
1003ca3bd55SApple OSS Distributions static const char * sKernelComponentNames[] = {
1013ca3bd55SApple OSS Distributions // The kexts for these IDs must have a version matching 'osrelease'.
1023ca3bd55SApple OSS Distributions "com.apple.kernel",
1033ca3bd55SApple OSS Distributions "com.apple.kpi.bsd",
1043ca3bd55SApple OSS Distributions "com.apple.kpi.dsep",
1053ca3bd55SApple OSS Distributions "com.apple.kpi.iokit",
106cc9a6355SApple OSS Distributions "com.apple.kpi.kasan",
107e6231be0SApple OSS Distributions "com.apple.kpi.kcov",
1083ca3bd55SApple OSS Distributions "com.apple.kpi.libkern",
1093ca3bd55SApple OSS Distributions "com.apple.kpi.mach",
1103ca3bd55SApple OSS Distributions "com.apple.kpi.private",
1113ca3bd55SApple OSS Distributions "com.apple.kpi.unsupported",
1123ca3bd55SApple OSS Distributions "com.apple.iokit.IONVRAMFamily",
1133ca3bd55SApple OSS Distributions "com.apple.driver.AppleNMI",
1143ca3bd55SApple OSS Distributions "com.apple.iokit.IOSystemManagementFamily",
1153ca3bd55SApple OSS Distributions "com.apple.iokit.ApplePlatformFamily",
1163ca3bd55SApple OSS Distributions NULL
1173ca3bd55SApple OSS Distributions };
1183ca3bd55SApple OSS Distributions
1193ca3bd55SApple OSS Distributions #if PRAGMA_MARK
1203ca3bd55SApple OSS Distributions #pragma mark KLDBootstrap Class
1213ca3bd55SApple OSS Distributions #endif
1223ca3bd55SApple OSS Distributions /*********************************************************************
1233ca3bd55SApple OSS Distributions * KLDBootstrap Class
1243ca3bd55SApple OSS Distributions *
1253ca3bd55SApple OSS Distributions * We use a C++ class here so that it can be a friend of OSKext and
1263ca3bd55SApple OSS Distributions * get at private stuff. We can't hide the class itself, but we can
1273ca3bd55SApple OSS Distributions * hide the instance through which we invoke the functions.
1283ca3bd55SApple OSS Distributions *********************************************************************/
1293ca3bd55SApple OSS Distributions class KLDBootstrap {
1303ca3bd55SApple OSS Distributions friend void bootstrapRecordStartupExtensions(void);
1313ca3bd55SApple OSS Distributions friend void bootstrapLoadSecurityExtensions(void);
1323ca3bd55SApple OSS Distributions
1333ca3bd55SApple OSS Distributions private:
1343ca3bd55SApple OSS Distributions void readStartupExtensions(void);
1353ca3bd55SApple OSS Distributions
136bb611c8fSApple OSS Distributions void readPrelinkedExtensions(kernel_mach_header_t *mh, kc_kind_t type);
1373ca3bd55SApple OSS Distributions void readBooterExtensions(void);
1383ca3bd55SApple OSS Distributions
1393ca3bd55SApple OSS Distributions OSReturn loadKernelComponentKexts(void);
140d0c1fef6SApple OSS Distributions void loadKernelExternalComponents(void);
1413ca3bd55SApple OSS Distributions void readBuiltinPersonalities(void);
1423ca3bd55SApple OSS Distributions
1433ca3bd55SApple OSS Distributions void loadSecurityExtensions(void);
1443ca3bd55SApple OSS Distributions
1453ca3bd55SApple OSS Distributions public:
1463ca3bd55SApple OSS Distributions KLDBootstrap(void);
1473ca3bd55SApple OSS Distributions ~KLDBootstrap(void);
1483ca3bd55SApple OSS Distributions };
1493ca3bd55SApple OSS Distributions
150a5e72196SApple OSS Distributions LIBKERN_ALWAYS_DESTROY static KLDBootstrap sBootstrapObject;
1513ca3bd55SApple OSS Distributions
1523ca3bd55SApple OSS Distributions /*********************************************************************
1533ca3bd55SApple OSS Distributions * Set the function pointers for the entry points into the bootstrap
1543ca3bd55SApple OSS Distributions * segment upon C++ static constructor invocation.
1553ca3bd55SApple OSS Distributions *********************************************************************/
KLDBootstrap(void)1563ca3bd55SApple OSS Distributions KLDBootstrap::KLDBootstrap(void)
1573ca3bd55SApple OSS Distributions {
1583ca3bd55SApple OSS Distributions if (this != &sBootstrapObject) {
1593ca3bd55SApple OSS Distributions panic("Attempt to access bootstrap segment.");
1603ca3bd55SApple OSS Distributions }
1613ca3bd55SApple OSS Distributions record_startup_extensions_function = &bootstrapRecordStartupExtensions;
1623ca3bd55SApple OSS Distributions load_security_extensions_function = &bootstrapLoadSecurityExtensions;
1633ca3bd55SApple OSS Distributions }
1643ca3bd55SApple OSS Distributions
1653ca3bd55SApple OSS Distributions /*********************************************************************
1663ca3bd55SApple OSS Distributions * Clear the function pointers for the entry points into the bootstrap
1673ca3bd55SApple OSS Distributions * segment upon C++ static destructor invocation.
1683ca3bd55SApple OSS Distributions *********************************************************************/
~KLDBootstrap(void)1693ca3bd55SApple OSS Distributions KLDBootstrap::~KLDBootstrap(void)
1703ca3bd55SApple OSS Distributions {
1713ca3bd55SApple OSS Distributions if (this != &sBootstrapObject) {
1723ca3bd55SApple OSS Distributions panic("Attempt to access bootstrap segment.");
1733ca3bd55SApple OSS Distributions }
174855239e5SApple OSS Distributions
175855239e5SApple OSS Distributions
176a5e72196SApple OSS Distributions record_startup_extensions_function = NULL;
177a5e72196SApple OSS Distributions load_security_extensions_function = NULL;
1783ca3bd55SApple OSS Distributions }
1793ca3bd55SApple OSS Distributions
1803ca3bd55SApple OSS Distributions /*********************************************************************
1813ca3bd55SApple OSS Distributions *********************************************************************/
1823ca3bd55SApple OSS Distributions void
readStartupExtensions(void)1833ca3bd55SApple OSS Distributions KLDBootstrap::readStartupExtensions(void)
1843ca3bd55SApple OSS Distributions {
1853ca3bd55SApple OSS Distributions kernel_section_t * prelinkInfoSect = NULL; // do not free
1863ca3bd55SApple OSS Distributions
1873ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
1883ca3bd55SApple OSS Distributions kOSKextLogProgressLevel |
1893ca3bd55SApple OSS Distributions kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag |
1903ca3bd55SApple OSS Distributions kOSKextLogKextBookkeepingFlag,
1913ca3bd55SApple OSS Distributions "Reading startup extensions.");
1923ca3bd55SApple OSS Distributions
193bb611c8fSApple OSS Distributions kc_format_t kc_format;
194bb611c8fSApple OSS Distributions kernel_mach_header_t *mh = &_mh_execute_header;
195bb611c8fSApple OSS Distributions if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
196bb611c8fSApple OSS Distributions mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
197bb611c8fSApple OSS Distributions }
198bb611c8fSApple OSS Distributions
1993ca3bd55SApple OSS Distributions /* If the prelink info segment has a nonzero size, we are prelinked
2003ca3bd55SApple OSS Distributions * and won't have any individual kexts or mkexts to read.
2013ca3bd55SApple OSS Distributions * Otherwise, we need to read kexts or the mkext from what the booter
2023ca3bd55SApple OSS Distributions * has handed us.
2033ca3bd55SApple OSS Distributions */
204bb611c8fSApple OSS Distributions prelinkInfoSect = getsectbynamefromheader(mh, kPrelinkInfoSegment, kPrelinkInfoSection);
2053ca3bd55SApple OSS Distributions if (prelinkInfoSect->size) {
206bb611c8fSApple OSS Distributions readPrelinkedExtensions(mh, KCKindPrimary);
2073ca3bd55SApple OSS Distributions } else {
2083ca3bd55SApple OSS Distributions readBooterExtensions();
2093ca3bd55SApple OSS Distributions }
2103ca3bd55SApple OSS Distributions
211bb611c8fSApple OSS Distributions kernel_mach_header_t *akc_mh;
212bb611c8fSApple OSS Distributions akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
213bb611c8fSApple OSS Distributions if (akc_mh) {
214bb611c8fSApple OSS Distributions readPrelinkedExtensions(akc_mh, KCKindAuxiliary);
215bb611c8fSApple OSS Distributions }
216bb611c8fSApple OSS Distributions
2173ca3bd55SApple OSS Distributions loadKernelComponentKexts();
218d0c1fef6SApple OSS Distributions loadKernelExternalComponents();
2193ca3bd55SApple OSS Distributions readBuiltinPersonalities();
220bb611c8fSApple OSS Distributions OSKext::sendAllKextPersonalitiesToCatalog(true);
2213ca3bd55SApple OSS Distributions
2223ca3bd55SApple OSS Distributions return;
2233ca3bd55SApple OSS Distributions }
2243ca3bd55SApple OSS Distributions
2253ca3bd55SApple OSS Distributions /*********************************************************************
2263ca3bd55SApple OSS Distributions *********************************************************************/
2273ca3bd55SApple OSS Distributions void
readPrelinkedExtensions(kernel_mach_header_t * mh,kc_kind_t type)228bb611c8fSApple OSS Distributions KLDBootstrap::readPrelinkedExtensions(kernel_mach_header_t *mh, kc_kind_t type)
2293ca3bd55SApple OSS Distributions {
230bb611c8fSApple OSS Distributions bool ret;
231bb611c8fSApple OSS Distributions OSSharedPtr<OSData> loaded_kcUUID;
232bb611c8fSApple OSS Distributions OSSharedPtr<OSString> errorString;
233bb611c8fSApple OSS Distributions OSSharedPtr<OSObject> parsedXML;
234bb611c8fSApple OSS Distributions kernel_section_t *infoPlistSection = NULL;
2353ca3bd55SApple OSS Distributions OSDictionary *infoDict = NULL; // do not release
2363ca3bd55SApple OSS Distributions
2373ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
2383ca3bd55SApple OSS Distributions kOSKextLogProgressLevel |
2393ca3bd55SApple OSS Distributions kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
2403ca3bd55SApple OSS Distributions "Starting from prelinked kernel.");
2413ca3bd55SApple OSS Distributions
242bb611c8fSApple OSS Distributions /*
243bb611c8fSApple OSS Distributions * The 'infoPlistSection' should contains an XML dictionary that
244bb611c8fSApple OSS Distributions * contains some meta data about the KC, and also describes each kext
245bb611c8fSApple OSS Distributions * included in the kext collection. Unserialize this dictionary and
246bb611c8fSApple OSS Distributions * then iterate over each kext.
2473ca3bd55SApple OSS Distributions */
248bb611c8fSApple OSS Distributions infoPlistSection = getsectbynamefromheader(mh, kPrelinkInfoSegment, kPrelinkInfoSection);
249bb611c8fSApple OSS Distributions parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
2503ca3bd55SApple OSS Distributions if (parsedXML) {
251bb611c8fSApple OSS Distributions infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2523ca3bd55SApple OSS Distributions }
253bb611c8fSApple OSS Distributions
254bb611c8fSApple OSS Distributions if (!infoDict) {
2553ca3bd55SApple OSS Distributions const char *errorCString = "(unknown error)";
2563ca3bd55SApple OSS Distributions
2573ca3bd55SApple OSS Distributions if (errorString && errorString->getCStringNoCopy()) {
2583ca3bd55SApple OSS Distributions errorCString = errorString->getCStringNoCopy();
2593ca3bd55SApple OSS Distributions } else if (parsedXML) {
2603ca3bd55SApple OSS Distributions errorCString = "not a dictionary";
2613ca3bd55SApple OSS Distributions }
2623ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
263bb611c8fSApple OSS Distributions "Error unserializing kext info plist section: %s.", errorCString);
264bb611c8fSApple OSS Distributions return;
2653ca3bd55SApple OSS Distributions }
2663ca3bd55SApple OSS Distributions
267bb611c8fSApple OSS Distributions /* Validate that the Kext Collection is prelinked to the loaded KC */
268bb611c8fSApple OSS Distributions if (type == KCKindAuxiliary) {
269bb611c8fSApple OSS Distributions if (OSKext::validateKCFileSetUUID(infoDict, KCKindAuxiliary) != 0) {
270bb611c8fSApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
271bb611c8fSApple OSS Distributions "Early boot AuxKC doesn't appear to be linked against the loaded BootKC.");
272bb611c8fSApple OSS Distributions return;
273bb611c8fSApple OSS Distributions }
274186b8fceSApple OSS Distributions
275bb611c8fSApple OSS Distributions /*
276bb611c8fSApple OSS Distributions * Defer further processing of the AuxKC, but keep the
277bb611c8fSApple OSS Distributions * processed info dictionary around so we can ml_static_free
278bb611c8fSApple OSS Distributions * the segment.
279bb611c8fSApple OSS Distributions */
280bb611c8fSApple OSS Distributions if (!OSKext::registerDeferredKextCollection(mh, parsedXML, KCKindAuxiliary)) {
281bb611c8fSApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
282bb611c8fSApple OSS Distributions "Error deferring AuxKC kext processing: Kexts in this collection will be unusable.");
283bb611c8fSApple OSS Distributions }
284bb611c8fSApple OSS Distributions goto skip_adding_kexts;
285bb611c8fSApple OSS Distributions }
286bb611c8fSApple OSS Distributions
287bb611c8fSApple OSS Distributions /*
288bb611c8fSApple OSS Distributions * this function does all the heavy lifting of adding OSKext objects
289bb611c8fSApple OSS Distributions * and potentially sliding them if necessary
290bb611c8fSApple OSS Distributions */
291bb611c8fSApple OSS Distributions ret = OSKext::addKextsFromKextCollection(mh, infoDict,
292bb611c8fSApple OSS Distributions kPrelinkTextSegment, loaded_kcUUID, (mh->filetype == MH_FILESET) ? type : KCKindUnknown);
293bb611c8fSApple OSS Distributions
294bb611c8fSApple OSS Distributions if (!ret) {
295bb611c8fSApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
296bb611c8fSApple OSS Distributions "Error loading kext info from prelinked primary KC");
297bb611c8fSApple OSS Distributions return;
298bb611c8fSApple OSS Distributions }
299d0c1fef6SApple OSS Distributions
30076e12aa3SApple OSS Distributions /* Copy in the kernelcache UUID */
301bb611c8fSApple OSS Distributions if (!loaded_kcUUID) {
3023ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
303bb611c8fSApple OSS Distributions "WARNING: did not find UUID in %s KC!", (type == KCKindAuxiliary) ? "Aux" : "Primary");
304bb611c8fSApple OSS Distributions } else if (type != KCKindAuxiliary) {
305bb611c8fSApple OSS Distributions kernelcache_uuid_valid = TRUE;
306bb611c8fSApple OSS Distributions memcpy((void *)&kernelcache_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
307bb611c8fSApple OSS Distributions uuid_unparse_upper(kernelcache_uuid, kernelcache_uuid_string);
308a5e72196SApple OSS Distributions } else {
309bb611c8fSApple OSS Distributions auxkc_uuid_valid = TRUE;
310bb611c8fSApple OSS Distributions memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
311bb611c8fSApple OSS Distributions uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
31288cc0b97SApple OSS Distributions }
31388cc0b97SApple OSS Distributions
314bb611c8fSApple OSS Distributions skip_adding_kexts:
315d0c1fef6SApple OSS Distributions #if CONFIG_KEXT_BASEMENT
316bb611c8fSApple OSS Distributions if (mh->filetype != MH_FILESET) {
317bb611c8fSApple OSS Distributions /*
318bb611c8fSApple OSS Distributions * On CONFIG_KEXT_BASEMENT systems which do _not_ boot the new
319bb611c8fSApple OSS Distributions * MH_FILESET kext collection, kexts are copied to their own
320bb611c8fSApple OSS Distributions * special VM region during OSKext init time, so we can free
321bb611c8fSApple OSS Distributions * the whole segment now.
3223ca3bd55SApple OSS Distributions */
323bb611c8fSApple OSS Distributions kernel_segment_command_t *prelinkTextSegment = NULL;
324bb611c8fSApple OSS Distributions prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
325bb611c8fSApple OSS Distributions if (!prelinkTextSegment) {
326bb611c8fSApple OSS Distributions OSKextLog(/* kext */ NULL,
327bb611c8fSApple OSS Distributions kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
328bb611c8fSApple OSS Distributions "Can't find prelinked kexts' text segment.");
329bb611c8fSApple OSS Distributions return;
330bb611c8fSApple OSS Distributions }
3313ca3bd55SApple OSS Distributions
332bb611c8fSApple OSS Distributions ml_static_mfree((vm_offset_t)prelinkTextSegment->vmaddr, prelinkTextSegment->vmsize);
333bb611c8fSApple OSS Distributions }
334bb611c8fSApple OSS Distributions #endif /* CONFIG_KEXT_BASEMENT */
335bb611c8fSApple OSS Distributions
336bb611c8fSApple OSS Distributions /*
337bb611c8fSApple OSS Distributions * Free the prelink info segment, we're done with it.
3383ca3bd55SApple OSS Distributions */
339*5c2921b0SApple OSS Distributions
340*5c2921b0SApple OSS Distributions #if !XNU_TARGET_OS_OSX
341*5c2921b0SApple OSS Distributions /*
342*5c2921b0SApple OSS Distributions * For now, we are limiting this freeing to embedded platforms.
343*5c2921b0SApple OSS Distributions * To enable freeing of prelink info segment on macOS, we need to
344*5c2921b0SApple OSS Distributions * fix rdar://88929016
345*5c2921b0SApple OSS Distributions */
346*5c2921b0SApple OSS Distributions bool freedPrelinkInfo = false;
347bb611c8fSApple OSS Distributions kernel_segment_command_t *prelinkInfoSegment = NULL;
348*5c2921b0SApple OSS Distributions prelinkInfoSegment = getsegbynamefromheader(mh, kPrelinkInfoSegment);
3493ca3bd55SApple OSS Distributions if (prelinkInfoSegment) {
350*5c2921b0SApple OSS Distributions if (prelinkInfoSegment->vmsize != 0) {
351*5c2921b0SApple OSS Distributions freedPrelinkInfo = true;
3523ca3bd55SApple OSS Distributions ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
3533ca3bd55SApple OSS Distributions (vm_size_t)prelinkInfoSegment->vmsize);
3543ca3bd55SApple OSS Distributions }
355*5c2921b0SApple OSS Distributions }
3563ca3bd55SApple OSS Distributions
357*5c2921b0SApple OSS Distributions if (!freedPrelinkInfo) {
358*5c2921b0SApple OSS Distributions OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "Failed to free prelink info.");
359*5c2921b0SApple OSS Distributions }
360*5c2921b0SApple OSS Distributions #endif
3613ca3bd55SApple OSS Distributions return;
3623ca3bd55SApple OSS Distributions }
3633ca3bd55SApple OSS Distributions
36488cc0b97SApple OSS Distributions
3653ca3bd55SApple OSS Distributions /*********************************************************************
3663ca3bd55SApple OSS Distributions *********************************************************************/
3673ca3bd55SApple OSS Distributions #define BOOTER_KEXT_PREFIX "Driver-"
3683ca3bd55SApple OSS Distributions
3693ca3bd55SApple OSS Distributions typedef struct _DeviceTreeBuffer {
3703ca3bd55SApple OSS Distributions uint32_t paddr;
3713ca3bd55SApple OSS Distributions uint32_t length;
3723ca3bd55SApple OSS Distributions } _DeviceTreeBuffer;
3733ca3bd55SApple OSS Distributions
3743ca3bd55SApple OSS Distributions void
readBooterExtensions(void)3753ca3bd55SApple OSS Distributions KLDBootstrap::readBooterExtensions(void)
3763ca3bd55SApple OSS Distributions {
377bb611c8fSApple OSS Distributions OSSharedPtr<IORegistryEntry> booterMemoryMap;
378bb611c8fSApple OSS Distributions OSSharedPtr<OSDictionary> propertyDict;
379bb611c8fSApple OSS Distributions OSSharedPtr<OSCollectionIterator> keyIterator;
3803ca3bd55SApple OSS Distributions OSString * deviceTreeName = NULL;// do not release
3813ca3bd55SApple OSS Distributions
3823ca3bd55SApple OSS Distributions const _DeviceTreeBuffer * deviceTreeBuffer = NULL;// do not free
3833ca3bd55SApple OSS Distributions char * booterDataPtr = NULL;// do not free
384bb611c8fSApple OSS Distributions OSSharedPtr<OSData> booterData;
385bb611c8fSApple OSS Distributions OSSharedPtr<OSKext> aKext;
3863ca3bd55SApple OSS Distributions
3873ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
3883ca3bd55SApple OSS Distributions kOSKextLogProgressLevel |
3893ca3bd55SApple OSS Distributions kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
390a3bb9fccSApple OSS Distributions "Reading startup extensions from booter memory.");
3913ca3bd55SApple OSS Distributions
3923ca3bd55SApple OSS Distributions booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);
3933ca3bd55SApple OSS Distributions
3943ca3bd55SApple OSS Distributions if (!booterMemoryMap) {
3953ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
3963ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
3973ca3bd55SApple OSS Distributions kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag,
3983ca3bd55SApple OSS Distributions "Can't read booter memory map.");
3993ca3bd55SApple OSS Distributions goto finish;
4003ca3bd55SApple OSS Distributions }
4013ca3bd55SApple OSS Distributions
4023ca3bd55SApple OSS Distributions propertyDict = booterMemoryMap->dictionaryWithProperties();
4033ca3bd55SApple OSS Distributions if (!propertyDict) {
4043ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
4053ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
4063ca3bd55SApple OSS Distributions kOSKextLogDirectoryScanFlag,
4073ca3bd55SApple OSS Distributions "Can't get property dictionary from memory map.");
4083ca3bd55SApple OSS Distributions goto finish;
4093ca3bd55SApple OSS Distributions }
4103ca3bd55SApple OSS Distributions
411bb611c8fSApple OSS Distributions keyIterator = OSCollectionIterator::withCollection(propertyDict.get());
4123ca3bd55SApple OSS Distributions if (!keyIterator) {
4133ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
4143ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
4153ca3bd55SApple OSS Distributions kOSKextLogGeneralFlag,
4163ca3bd55SApple OSS Distributions "Can't allocate iterator for driver images.");
4173ca3bd55SApple OSS Distributions goto finish;
4183ca3bd55SApple OSS Distributions }
4193ca3bd55SApple OSS Distributions
420186b8fceSApple OSS Distributions /* Create dictionary of excluded kexts
421186b8fceSApple OSS Distributions */
42276e12aa3SApple OSS Distributions #ifndef CONFIG_EMBEDDED
423bb611c8fSApple OSS Distributions OSKext::createExcludeListFromBooterData(propertyDict.get(), keyIterator.get());
42476e12aa3SApple OSS Distributions #endif
425bb611c8fSApple OSS Distributions // !! reset the iterator, not the pointer
426186b8fceSApple OSS Distributions keyIterator->reset();
427186b8fceSApple OSS Distributions
4283ca3bd55SApple OSS Distributions while ((deviceTreeName =
4293ca3bd55SApple OSS Distributions OSDynamicCast(OSString, keyIterator->getNextObject()))) {
4303ca3bd55SApple OSS Distributions const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
4313ca3bd55SApple OSS Distributions OSData * deviceTreeEntry = OSDynamicCast(OSData,
4323ca3bd55SApple OSS Distributions propertyDict->getObject(deviceTreeName));
4333ca3bd55SApple OSS Distributions
4343ca3bd55SApple OSS Distributions /* If there is no entry for the name, we can't do much with it. */
4353ca3bd55SApple OSS Distributions if (!deviceTreeEntry) {
4363ca3bd55SApple OSS Distributions continue;
4373ca3bd55SApple OSS Distributions }
4383ca3bd55SApple OSS Distributions
439a3bb9fccSApple OSS Distributions /* Make sure it is a kext */
440a3bb9fccSApple OSS Distributions if (strncmp(devTreeNameCString,
441a3bb9fccSApple OSS Distributions BOOTER_KEXT_PREFIX,
4423ca3bd55SApple OSS Distributions CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
4433ca3bd55SApple OSS Distributions continue;
4443ca3bd55SApple OSS Distributions }
4453ca3bd55SApple OSS Distributions
4463ca3bd55SApple OSS Distributions deviceTreeBuffer = (const _DeviceTreeBuffer *)
4473ca3bd55SApple OSS Distributions deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4483ca3bd55SApple OSS Distributions if (!deviceTreeBuffer) {
4493ca3bd55SApple OSS Distributions /* We can't get to the data, so we can't do anything,
4503ca3bd55SApple OSS Distributions * not even free it from physical memory (if it's there).
4513ca3bd55SApple OSS Distributions */
4523ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
4533ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
4543ca3bd55SApple OSS Distributions kOSKextLogDirectoryScanFlag,
4553ca3bd55SApple OSS Distributions "Device tree entry %s has NULL pointer.",
4563ca3bd55SApple OSS Distributions devTreeNameCString);
4573ca3bd55SApple OSS Distributions goto finish; // xxx - continue, panic?
4583ca3bd55SApple OSS Distributions }
4593ca3bd55SApple OSS Distributions
4603ca3bd55SApple OSS Distributions booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4613ca3bd55SApple OSS Distributions if (!booterDataPtr) {
4623ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
4633ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
4643ca3bd55SApple OSS Distributions kOSKextLogDirectoryScanFlag,
465a3bb9fccSApple OSS Distributions "Can't get virtual address for device tree entry %s.",
4663ca3bd55SApple OSS Distributions devTreeNameCString);
4673ca3bd55SApple OSS Distributions goto finish;
4683ca3bd55SApple OSS Distributions }
4693ca3bd55SApple OSS Distributions
4703ca3bd55SApple OSS Distributions /* Wrap the booter data buffer in an OSData and set a dealloc function
4713ca3bd55SApple OSS Distributions * so it will take care of the physical memory when freed. Kexts will
4723ca3bd55SApple OSS Distributions * retain the booterData for as long as they need it. Remove the entry
4733ca3bd55SApple OSS Distributions * from the booter memory map after this is done.
4743ca3bd55SApple OSS Distributions */
4753ca3bd55SApple OSS Distributions booterData = OSData::withBytesNoCopy(booterDataPtr,
4763ca3bd55SApple OSS Distributions deviceTreeBuffer->length);
4773ca3bd55SApple OSS Distributions if (!booterData) {
4783ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
4793ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
4803ca3bd55SApple OSS Distributions kOSKextLogGeneralFlag,
4813ca3bd55SApple OSS Distributions "Error - Can't allocate OSData wrapper for device tree entry %s.",
4823ca3bd55SApple OSS Distributions devTreeNameCString);
4833ca3bd55SApple OSS Distributions goto finish;
4843ca3bd55SApple OSS Distributions }
4853ca3bd55SApple OSS Distributions booterData->setDeallocFunction(osdata_phys_free);
4863ca3bd55SApple OSS Distributions
4873ca3bd55SApple OSS Distributions /* Create the kext for the entry, then release it, because the
4883ca3bd55SApple OSS Distributions * kext system keeps them around until explicitly removed.
4893ca3bd55SApple OSS Distributions * Any creation/registration failures are already logged for us.
4903ca3bd55SApple OSS Distributions */
491bb611c8fSApple OSS Distributions OSSharedPtr<OSKext> newKext = OSKext::withBooterData(deviceTreeName, booterData.get());
4923ca3bd55SApple OSS Distributions
4933ca3bd55SApple OSS Distributions booterMemoryMap->removeProperty(deviceTreeName);
4943ca3bd55SApple OSS Distributions } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
4953ca3bd55SApple OSS Distributions
4963ca3bd55SApple OSS Distributions finish:
4973ca3bd55SApple OSS Distributions return;
4983ca3bd55SApple OSS Distributions }
4993ca3bd55SApple OSS Distributions
5003ca3bd55SApple OSS Distributions /*********************************************************************
5013ca3bd55SApple OSS Distributions *********************************************************************/
5023ca3bd55SApple OSS Distributions #define COM_APPLE "com.apple."
5033ca3bd55SApple OSS Distributions
5043ca3bd55SApple OSS Distributions void
loadSecurityExtensions(void)5053ca3bd55SApple OSS Distributions KLDBootstrap::loadSecurityExtensions(void)
5063ca3bd55SApple OSS Distributions {
507bb611c8fSApple OSS Distributions OSSharedPtr<OSDictionary> extensionsDict;
508bb611c8fSApple OSS Distributions OSSharedPtr<OSCollectionIterator> keyIterator;
5093ca3bd55SApple OSS Distributions OSString * bundleID = NULL;// don't release
5103ca3bd55SApple OSS Distributions OSKext * theKext = NULL;// don't release
5113ca3bd55SApple OSS Distributions
5123ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
5133ca3bd55SApple OSS Distributions kOSKextLogStepLevel |
5143ca3bd55SApple OSS Distributions kOSKextLogLoadFlag,
5153ca3bd55SApple OSS Distributions "Loading security extensions.");
5163ca3bd55SApple OSS Distributions
5173ca3bd55SApple OSS Distributions extensionsDict = OSKext::copyKexts();
5183ca3bd55SApple OSS Distributions if (!extensionsDict) {
5193ca3bd55SApple OSS Distributions return;
5203ca3bd55SApple OSS Distributions }
5213ca3bd55SApple OSS Distributions
522bb611c8fSApple OSS Distributions keyIterator = OSCollectionIterator::withCollection(extensionsDict.get());
5233ca3bd55SApple OSS Distributions if (!keyIterator) {
5243ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
5253ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
5263ca3bd55SApple OSS Distributions kOSKextLogGeneralFlag,
5273ca3bd55SApple OSS Distributions "Failed to allocate iterator for security extensions.");
5283ca3bd55SApple OSS Distributions goto finish;
5293ca3bd55SApple OSS Distributions }
5303ca3bd55SApple OSS Distributions
5313ca3bd55SApple OSS Distributions while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
5323ca3bd55SApple OSS Distributions const char * bundle_id = bundleID->getCStringNoCopy();
5333ca3bd55SApple OSS Distributions
5343ca3bd55SApple OSS Distributions /* Skip extensions whose bundle IDs don't start with "com.apple.".
5353ca3bd55SApple OSS Distributions */
5363ca3bd55SApple OSS Distributions if (!bundle_id ||
5373ca3bd55SApple OSS Distributions (strncmp(bundle_id, COM_APPLE, CONST_STRLEN(COM_APPLE)) != 0)) {
5383ca3bd55SApple OSS Distributions continue;
5393ca3bd55SApple OSS Distributions }
5403ca3bd55SApple OSS Distributions
5413ca3bd55SApple OSS Distributions theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
5423ca3bd55SApple OSS Distributions if (!theKext) {
5433ca3bd55SApple OSS Distributions continue;
5443ca3bd55SApple OSS Distributions }
5453ca3bd55SApple OSS Distributions
546a5e72196SApple OSS Distributions if (kOSBooleanTrue == theKext->getPropertyForHostArch(kAppleSecurityExtensionKey)) {
5473ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
5483ca3bd55SApple OSS Distributions kOSKextLogStepLevel |
5493ca3bd55SApple OSS Distributions kOSKextLogLoadFlag,
5503ca3bd55SApple OSS Distributions "Loading security extension %s.", bundleID->getCStringNoCopy());
5513ca3bd55SApple OSS Distributions OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
5523ca3bd55SApple OSS Distributions /* allowDefer */ false);
5533ca3bd55SApple OSS Distributions }
5543ca3bd55SApple OSS Distributions }
5553ca3bd55SApple OSS Distributions
5563ca3bd55SApple OSS Distributions finish:
5573ca3bd55SApple OSS Distributions return;
5583ca3bd55SApple OSS Distributions }
5593ca3bd55SApple OSS Distributions
5603ca3bd55SApple OSS Distributions /*********************************************************************
5613ca3bd55SApple OSS Distributions * We used to require that all listed kernel components load, but
5623ca3bd55SApple OSS Distributions * nowadays we can get them from userland so we only try to load the
5633ca3bd55SApple OSS Distributions * ones we have. If an error occurs later, such is life.
5643ca3bd55SApple OSS Distributions *
5653ca3bd55SApple OSS Distributions * Note that we look the kexts up first, so we can avoid spurious
5663ca3bd55SApple OSS Distributions * (in this context, anyhow) log messages about kexts not being found.
5673ca3bd55SApple OSS Distributions *
5683ca3bd55SApple OSS Distributions * xxx - do we even need to do this any more? Check if the kernel
5693ca3bd55SApple OSS Distributions * xxx - compoonents just load in the regular paths
5703ca3bd55SApple OSS Distributions *********************************************************************/
5713ca3bd55SApple OSS Distributions OSReturn
loadKernelComponentKexts(void)5723ca3bd55SApple OSS Distributions KLDBootstrap::loadKernelComponentKexts(void)
5733ca3bd55SApple OSS Distributions {
5743ca3bd55SApple OSS Distributions OSReturn result = kOSReturnSuccess;// optimistic
575bb611c8fSApple OSS Distributions OSSharedPtr<OSKext> theKext;
5763ca3bd55SApple OSS Distributions const char ** kextIDPtr = NULL; // do not release
5773ca3bd55SApple OSS Distributions
5783ca3bd55SApple OSS Distributions for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) {
5793ca3bd55SApple OSS Distributions theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr);
5803ca3bd55SApple OSS Distributions
5813ca3bd55SApple OSS Distributions if (theKext) {
5823ca3bd55SApple OSS Distributions if (kOSReturnSuccess != OSKext::loadKextWithIdentifier(
5833ca3bd55SApple OSS Distributions *kextIDPtr, /* allowDefer */ false)) {
5843ca3bd55SApple OSS Distributions // xxx - check KextBookkeeping, might be redundant
5853ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
5863ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
5873ca3bd55SApple OSS Distributions kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
5883ca3bd55SApple OSS Distributions "Failed to initialize kernel component %s.", *kextIDPtr);
5893ca3bd55SApple OSS Distributions result = kOSReturnError;
5903ca3bd55SApple OSS Distributions }
5913ca3bd55SApple OSS Distributions }
5923ca3bd55SApple OSS Distributions }
5933ca3bd55SApple OSS Distributions
5943ca3bd55SApple OSS Distributions return result;
5953ca3bd55SApple OSS Distributions }
5963ca3bd55SApple OSS Distributions
5973ca3bd55SApple OSS Distributions /*********************************************************************
598d0c1fef6SApple OSS Distributions * Ensure that Kernel External Components are loaded early in boot,
599d0c1fef6SApple OSS Distributions * before other kext personalities get sent to the IOCatalogue. These
600d0c1fef6SApple OSS Distributions * kexts are treated specially because they may provide the implementation
601d0c1fef6SApple OSS Distributions * for kernel-vended KPI, so they must register themselves before
602d0c1fef6SApple OSS Distributions * general purpose IOKit probing begins.
603d0c1fef6SApple OSS Distributions *********************************************************************/
604d0c1fef6SApple OSS Distributions
605d0c1fef6SApple OSS Distributions #define COM_APPLE_KEC "com.apple.kec."
606d0c1fef6SApple OSS Distributions
607d0c1fef6SApple OSS Distributions void
loadKernelExternalComponents(void)608d0c1fef6SApple OSS Distributions KLDBootstrap::loadKernelExternalComponents(void)
609d0c1fef6SApple OSS Distributions {
610bb611c8fSApple OSS Distributions OSSharedPtr<OSDictionary> extensionsDict;
611bb611c8fSApple OSS Distributions OSSharedPtr<OSCollectionIterator> keyIterator;
612d0c1fef6SApple OSS Distributions OSString * bundleID = NULL;// don't release
613d0c1fef6SApple OSS Distributions OSKext * theKext = NULL;// don't release
614d0c1fef6SApple OSS Distributions OSBoolean * isKernelExternalComponent = NULL;// don't release
615d0c1fef6SApple OSS Distributions
616d0c1fef6SApple OSS Distributions OSKextLog(/* kext */ NULL,
617d0c1fef6SApple OSS Distributions kOSKextLogStepLevel |
618d0c1fef6SApple OSS Distributions kOSKextLogLoadFlag,
619d0c1fef6SApple OSS Distributions "Loading Kernel External Components.");
620d0c1fef6SApple OSS Distributions
621d0c1fef6SApple OSS Distributions extensionsDict = OSKext::copyKexts();
622d0c1fef6SApple OSS Distributions if (!extensionsDict) {
623d0c1fef6SApple OSS Distributions return;
624d0c1fef6SApple OSS Distributions }
625d0c1fef6SApple OSS Distributions
626bb611c8fSApple OSS Distributions keyIterator = OSCollectionIterator::withCollection(extensionsDict.get());
627d0c1fef6SApple OSS Distributions if (!keyIterator) {
628d0c1fef6SApple OSS Distributions OSKextLog(/* kext */ NULL,
629d0c1fef6SApple OSS Distributions kOSKextLogErrorLevel |
630d0c1fef6SApple OSS Distributions kOSKextLogGeneralFlag,
631d0c1fef6SApple OSS Distributions "Failed to allocate iterator for Kernel External Components.");
632d0c1fef6SApple OSS Distributions goto finish;
633d0c1fef6SApple OSS Distributions }
634d0c1fef6SApple OSS Distributions
635d0c1fef6SApple OSS Distributions while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
636d0c1fef6SApple OSS Distributions const char * bundle_id = bundleID->getCStringNoCopy();
637d0c1fef6SApple OSS Distributions
638d0c1fef6SApple OSS Distributions /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
639d0c1fef6SApple OSS Distributions */
640d0c1fef6SApple OSS Distributions if (!bundle_id ||
641d0c1fef6SApple OSS Distributions (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) {
642d0c1fef6SApple OSS Distributions continue;
643d0c1fef6SApple OSS Distributions }
644d0c1fef6SApple OSS Distributions
645d0c1fef6SApple OSS Distributions theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
646d0c1fef6SApple OSS Distributions if (!theKext) {
647d0c1fef6SApple OSS Distributions continue;
648d0c1fef6SApple OSS Distributions }
649d0c1fef6SApple OSS Distributions
650d0c1fef6SApple OSS Distributions isKernelExternalComponent = OSDynamicCast(OSBoolean,
651d0c1fef6SApple OSS Distributions theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey));
652d0c1fef6SApple OSS Distributions if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) {
653d0c1fef6SApple OSS Distributions OSKextLog(/* kext */ NULL,
654d0c1fef6SApple OSS Distributions kOSKextLogStepLevel |
655d0c1fef6SApple OSS Distributions kOSKextLogLoadFlag,
656d0c1fef6SApple OSS Distributions "Loading kernel external component %s.", bundleID->getCStringNoCopy());
657d0c1fef6SApple OSS Distributions OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
658d0c1fef6SApple OSS Distributions /* allowDefer */ false);
659d0c1fef6SApple OSS Distributions }
660d0c1fef6SApple OSS Distributions }
661d0c1fef6SApple OSS Distributions
662d0c1fef6SApple OSS Distributions finish:
663d0c1fef6SApple OSS Distributions return;
664d0c1fef6SApple OSS Distributions }
665d0c1fef6SApple OSS Distributions
666d0c1fef6SApple OSS Distributions /*********************************************************************
6673ca3bd55SApple OSS Distributions *********************************************************************/
6683ca3bd55SApple OSS Distributions void
readBuiltinPersonalities(void)6693ca3bd55SApple OSS Distributions KLDBootstrap::readBuiltinPersonalities(void)
6703ca3bd55SApple OSS Distributions {
671bb611c8fSApple OSS Distributions OSSharedPtr<OSObject> parsedXML;
6723ca3bd55SApple OSS Distributions OSArray * builtinExtensions = NULL;// do not release
673bb611c8fSApple OSS Distributions OSSharedPtr<OSArray> allPersonalities;
674bb611c8fSApple OSS Distributions OSSharedPtr<OSString> errorString;
6753ca3bd55SApple OSS Distributions kernel_section_t * infosect = NULL;// do not free
676bb611c8fSApple OSS Distributions OSSharedPtr<OSCollectionIterator> personalitiesIterator;
6773ca3bd55SApple OSS Distributions unsigned int count, i;
6783ca3bd55SApple OSS Distributions
6793ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
6803ca3bd55SApple OSS Distributions kOSKextLogStepLevel |
6813ca3bd55SApple OSS Distributions kOSKextLogLoadFlag,
6823ca3bd55SApple OSS Distributions "Reading built-in kernel personalities for I/O Kit drivers.");
6833ca3bd55SApple OSS Distributions
6843ca3bd55SApple OSS Distributions /* Look in the __BUILTIN __info segment for an array of Info.plist
6853ca3bd55SApple OSS Distributions * entries. For each one, extract the personalities dictionary, add
6863ca3bd55SApple OSS Distributions * it to our array, then push them all (without matching) to
6873ca3bd55SApple OSS Distributions * the IOCatalogue. This can be used to augment the personalities
6883ca3bd55SApple OSS Distributions * in gIOKernelConfigTables, especially when linking entire kexts into
6893ca3bd55SApple OSS Distributions * the mach_kernel image.
6903ca3bd55SApple OSS Distributions */
6913ca3bd55SApple OSS Distributions infosect = getsectbyname("__BUILTIN", "__info");
6923ca3bd55SApple OSS Distributions if (!infosect) {
6933ca3bd55SApple OSS Distributions // this isn't fatal
6943ca3bd55SApple OSS Distributions goto finish;
6953ca3bd55SApple OSS Distributions }
6963ca3bd55SApple OSS Distributions
6973ca3bd55SApple OSS Distributions parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
698bb611c8fSApple OSS Distributions errorString);
6993ca3bd55SApple OSS Distributions if (parsedXML) {
700bb611c8fSApple OSS Distributions builtinExtensions = OSDynamicCast(OSArray, parsedXML.get());
7013ca3bd55SApple OSS Distributions }
7023ca3bd55SApple OSS Distributions if (!builtinExtensions) {
7033ca3bd55SApple OSS Distributions const char * errorCString = "(unknown error)";
7043ca3bd55SApple OSS Distributions
7053ca3bd55SApple OSS Distributions if (errorString && errorString->getCStringNoCopy()) {
7063ca3bd55SApple OSS Distributions errorCString = errorString->getCStringNoCopy();
7073ca3bd55SApple OSS Distributions } else if (parsedXML) {
7083ca3bd55SApple OSS Distributions errorCString = "not an array";
7093ca3bd55SApple OSS Distributions }
7103ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
7113ca3bd55SApple OSS Distributions kOSKextLogErrorLevel |
7123ca3bd55SApple OSS Distributions kOSKextLogLoadFlag,
7133ca3bd55SApple OSS Distributions "Error unserializing built-in personalities: %s.", errorCString);
7143ca3bd55SApple OSS Distributions goto finish;
7153ca3bd55SApple OSS Distributions }
7163ca3bd55SApple OSS Distributions
7173ca3bd55SApple OSS Distributions // estimate 3 personalities per Info.plist/kext
7183ca3bd55SApple OSS Distributions count = builtinExtensions->getCount();
7193ca3bd55SApple OSS Distributions allPersonalities = OSArray::withCapacity(count * 3);
7203ca3bd55SApple OSS Distributions
7213ca3bd55SApple OSS Distributions for (i = 0; i < count; i++) {
7223ca3bd55SApple OSS Distributions OSDictionary * infoDict = NULL;// do not release
7233ca3bd55SApple OSS Distributions OSString * moduleName = NULL;// do not release
7243ca3bd55SApple OSS Distributions OSDictionary * personalities;// do not release
7253ca3bd55SApple OSS Distributions OSString * personalityName;// do not release
7263ca3bd55SApple OSS Distributions
7273ca3bd55SApple OSS Distributions infoDict = OSDynamicCast(OSDictionary,
7283ca3bd55SApple OSS Distributions builtinExtensions->getObject(i));
7293ca3bd55SApple OSS Distributions if (!infoDict) {
7303ca3bd55SApple OSS Distributions continue;
7313ca3bd55SApple OSS Distributions }
7323ca3bd55SApple OSS Distributions
7333ca3bd55SApple OSS Distributions moduleName = OSDynamicCast(OSString,
7343ca3bd55SApple OSS Distributions infoDict->getObject(kCFBundleIdentifierKey));
7353ca3bd55SApple OSS Distributions if (!moduleName) {
7363ca3bd55SApple OSS Distributions continue;
7373ca3bd55SApple OSS Distributions }
7383ca3bd55SApple OSS Distributions
7393ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
7403ca3bd55SApple OSS Distributions kOSKextLogStepLevel |
7413ca3bd55SApple OSS Distributions kOSKextLogLoadFlag,
7423ca3bd55SApple OSS Distributions "Adding personalities for built-in driver %s:",
7433ca3bd55SApple OSS Distributions moduleName->getCStringNoCopy());
7443ca3bd55SApple OSS Distributions
7453ca3bd55SApple OSS Distributions personalities = OSDynamicCast(OSDictionary,
7463ca3bd55SApple OSS Distributions infoDict->getObject("IOKitPersonalities"));
7473ca3bd55SApple OSS Distributions if (!personalities) {
7483ca3bd55SApple OSS Distributions continue;
7493ca3bd55SApple OSS Distributions }
7503ca3bd55SApple OSS Distributions
7513ca3bd55SApple OSS Distributions personalitiesIterator = OSCollectionIterator::withCollection(personalities);
7523ca3bd55SApple OSS Distributions if (!personalitiesIterator) {
7533ca3bd55SApple OSS Distributions continue; // xxx - well really, what can we do? should we panic?
7543ca3bd55SApple OSS Distributions }
7553ca3bd55SApple OSS Distributions
7563ca3bd55SApple OSS Distributions while ((personalityName = OSDynamicCast(OSString,
7573ca3bd55SApple OSS Distributions personalitiesIterator->getNextObject()))) {
7583ca3bd55SApple OSS Distributions OSDictionary * personality = OSDynamicCast(OSDictionary,
7593ca3bd55SApple OSS Distributions personalities->getObject(personalityName));
7603ca3bd55SApple OSS Distributions
7613ca3bd55SApple OSS Distributions OSKextLog(/* kext */ NULL,
7623ca3bd55SApple OSS Distributions kOSKextLogDetailLevel |
7633ca3bd55SApple OSS Distributions kOSKextLogLoadFlag,
7643ca3bd55SApple OSS Distributions "Adding built-in driver personality %s.",
7653ca3bd55SApple OSS Distributions personalityName->getCStringNoCopy());
7663ca3bd55SApple OSS Distributions
7673ca3bd55SApple OSS Distributions if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
7683ca3bd55SApple OSS Distributions personality->setObject(kCFBundleIdentifierKey, moduleName);
7693ca3bd55SApple OSS Distributions }
7703ca3bd55SApple OSS Distributions allPersonalities->setObject(personality);
7713ca3bd55SApple OSS Distributions }
7723ca3bd55SApple OSS Distributions }
7733ca3bd55SApple OSS Distributions
774bb611c8fSApple OSS Distributions gIOCatalogue->addDrivers(allPersonalities.get(), false);
7753ca3bd55SApple OSS Distributions
7763ca3bd55SApple OSS Distributions finish:
7773ca3bd55SApple OSS Distributions return;
7783ca3bd55SApple OSS Distributions }
7793ca3bd55SApple OSS Distributions
7803ca3bd55SApple OSS Distributions #if PRAGMA_MARK
7813ca3bd55SApple OSS Distributions #pragma mark Bootstrap Functions
7823ca3bd55SApple OSS Distributions #endif
7833ca3bd55SApple OSS Distributions /*********************************************************************
7843ca3bd55SApple OSS Distributions * Bootstrap Functions
7853ca3bd55SApple OSS Distributions *********************************************************************/
786a5e72196SApple OSS Distributions static void
bootstrapRecordStartupExtensions(void)787a5e72196SApple OSS Distributions bootstrapRecordStartupExtensions(void)
7883ca3bd55SApple OSS Distributions {
7893ca3bd55SApple OSS Distributions sBootstrapObject.readStartupExtensions();
7903ca3bd55SApple OSS Distributions return;
7913ca3bd55SApple OSS Distributions }
7923ca3bd55SApple OSS Distributions
793a5e72196SApple OSS Distributions static void
bootstrapLoadSecurityExtensions(void)794a5e72196SApple OSS Distributions bootstrapLoadSecurityExtensions(void)
7953ca3bd55SApple OSS Distributions {
7963ca3bd55SApple OSS Distributions sBootstrapObject.loadSecurityExtensions();
7973ca3bd55SApple OSS Distributions return;
798c1dac77fSApple OSS Distributions }
799855239e5SApple OSS Distributions
800