2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 #include <libkern/c++/OSContainers.h>
29 #include <IOKit/IODeviceTreeSupport.h>
30 #include <IOKit/IORegistryEntry.h>
31 #include <IOKit/IOCatalogue.h>
32 #include <IOKit/IOKitKeysPrivate.h>
33 #include <libkern/c++/OSUnserialize.h>
34 #include <libkern/OSByteOrder.h>
35 #include <libsa/catalogue.h>
38 #include <machine/machine_routines.h>
39 #include <mach/host_info.h>
40 #include <mach/kmod.h>
41 #include <libsa/mkext.h>
42 #include <libsa/vers_rsrc.h>
43 #include <mach-o/loader.h>
46 #include <IOKit/IOLib.h>
48 #include <IOKit/assert.h>
51 extern void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
);
52 // extern kern_return_t host_info(host_t host,
53 // host_flavor_t flavor,
55 // mach_msg_type_number_t *count);
56 extern int grade_binary(cpu_type_t exectype
, cpu_subtype_t execsubtype
);
57 // Return the address of the named Mach-O segment from the currently
58 // executing 32 bit kernel, or NULL.
59 extern struct segment_command
*getsegbyname(char *seg_name
);
60 // Return the address of the named section from the named Mach-O segment
61 // from the currently executing 32 bit kernel, or NULL.
62 extern struct section
*getsectbyname(const char *segname
, const char *sectname
);
68 #define VTYELLOW "\033[33m"
69 #define VTRESET "\033[0m"
75 /*********************************************************************
76 *********************************************************************/
77 static OSDictionary
* gStartupExtensions
= 0;
78 static OSArray
* gBootLoaderObjects
= 0;
79 extern OSArray
* gIOPrelinkedModules
;
81 OSDictionary
* getStartupExtensions(void) {
82 if (gStartupExtensions
) {
83 return gStartupExtensions
;
85 gStartupExtensions
= OSDictionary::withCapacity(1);
86 assert (gStartupExtensions
);
88 return gStartupExtensions
;
91 /* This array holds objects that are needed to be held around during
92 * boot before kextd starts up. Currently it contains OSData objects
93 * copied from OF entries for mkext archives in device ROMs. Because
94 * the Device Tree support code dumps these after initially handing
95 * them to us, we have to be able to clean them up later.
97 OSArray
* getBootLoaderObjects(void) {
98 if (gBootLoaderObjects
) {
99 return gBootLoaderObjects
;
101 gBootLoaderObjects
= OSArray::withCapacity(1);
102 assert (gBootLoaderObjects
);
104 return gBootLoaderObjects
;
107 /*********************************************************************
108 * This function checks that a driver dict has all the required
109 * entries and does a little bit of value checking too.
111 * index is nonnegative if the index of an entry from an mkext
113 *********************************************************************/
114 bool validateExtensionDict(OSDictionary
* extension
, int index
) {
117 bool not_a_dict
= false;
118 bool id_missing
= false;
119 bool is_kernel_resource
= false;
120 bool has_executable
= false;
121 bool ineligible_for_safe_boot
= false;
122 OSString
* bundleIdentifier
= NULL
; // do not release
123 OSObject
* rawValue
= NULL
; // do not release
124 OSString
* stringValue
= NULL
; // do not release
125 OSBoolean
* booleanValue
= NULL
; // do not release
126 OSDictionary
* personalities
= NULL
; // do not release
127 OSDictionary
* libraries
= NULL
; // do not release
128 OSCollectionIterator
* keyIterator
= NULL
; // must release
129 OSString
* key
= NULL
; // do not release
131 VERS_version compatible_vers
;
132 char namep
[16]; // unused but needed for PE_parse_boot_arg()
134 // Info dict is a dictionary
135 if (!OSDynamicCast(OSDictionary
, extension
)) {
141 // CFBundleIdentifier is a string - REQUIRED
142 bundleIdentifier
= OSDynamicCast(OSString
,
143 extension
->getObject("CFBundleIdentifier"));
144 if (!bundleIdentifier
) {
150 // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME
151 if (bundleIdentifier
->getLength() >= KMOD_MAX_NAME
) {
156 // CFBundlePackageType is "KEXT" - REQUIRED
157 stringValue
= OSDynamicCast(OSString
,
158 extension
->getObject("CFBundlePackageType"));
163 if (!stringValue
->isEqualTo("KEXT")) {
168 // CFBundleVersion is a string - REQUIRED
169 stringValue
= OSDynamicCast(OSString
,
170 extension
->getObject("CFBundleVersion"));
175 // CFBundleVersion is of valid form
176 vers
= VERS_parse_string(stringValue
->getCStringNoCopy());
182 // OSBundleCompatibleVersion is a string - OPTIONAL
183 rawValue
= extension
->getObject("OSBundleCompatibleVersion");
185 stringValue
= OSDynamicCast(OSString
, rawValue
);
191 // OSBundleCompatibleVersion is of valid form
192 compatible_vers
= VERS_parse_string(stringValue
->getCStringNoCopy());
193 if (compatible_vers
< 0) {
198 // OSBundleCompatibleVersion <= CFBundleVersion
199 if (compatible_vers
> vers
) {
205 // CFBundleExecutable is a string - OPTIONAL
206 rawValue
= extension
->getObject("CFBundleExecutable");
208 stringValue
= OSDynamicCast(OSString
, rawValue
);
209 if (!stringValue
|| stringValue
->getLength() == 0) {
213 has_executable
= true;
216 // OSKernelResource is a boolean value - OPTIONAL
217 rawValue
= extension
->getObject("OSKernelResource");
219 booleanValue
= OSDynamicCast(OSBoolean
, rawValue
);
224 is_kernel_resource
= booleanValue
->isTrue();
227 // IOKitPersonalities is a dictionary - OPTIONAL
228 rawValue
= extension
->getObject("IOKitPersonalities");
230 personalities
= OSDynamicCast(OSDictionary
, rawValue
);
231 if (!personalities
) {
236 keyIterator
= OSCollectionIterator::withCollection(personalities
);
238 IOLog("Error: Failed to allocate iterator for personalities.\n");
244 while ((key
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
245 OSDictionary
* personality
= NULL
; // do not release
247 // Each personality is a dictionary
248 personality
= OSDynamicCast(OSDictionary
,
249 personalities
->getObject(key
));
255 // IOClass exists as a string - REQUIRED
256 if (!OSDynamicCast(OSString
, personality
->getObject("IOClass"))) {
261 // IOProviderClass exists as a string - REQUIRED
262 if (!OSDynamicCast(OSString
,
263 personality
->getObject("IOProviderClass"))) {
269 // CFBundleIdentifier is a string - OPTIONAL - INSERT IF ABSENT!
270 rawValue
= personality
->getObject("CFBundleIdentifier");
272 personality
->setObject("CFBundleIdentifier", bundleIdentifier
);
274 OSString
* personalityID
= NULL
; // do not release
275 personalityID
= OSDynamicCast(OSString
, rawValue
);
276 if (!personalityID
) {
280 // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME
281 if (personalityID
->getLength() >= KMOD_MAX_NAME
) {
288 // IOKitDebug is a number - OPTIONAL
289 rawValue
= personality
->getObject("IOKitDebug");
290 if (rawValue
&& !OSDynamicCast(OSNumber
, rawValue
)) {
296 keyIterator
->release();
301 // OSBundleLibraries is a dictionary - REQUIRED if
302 // not kernel resource & has executable
304 rawValue
= extension
->getObject("OSBundleLibraries");
305 if (!rawValue
&& !is_kernel_resource
&& has_executable
) {
311 libraries
= OSDynamicCast(OSDictionary
, rawValue
);
317 keyIterator
= OSCollectionIterator::withCollection(libraries
);
319 IOLog("Error: Failed to allocate iterator for libraries.\n");
325 while ((key
= OSDynamicCast(OSString
,
326 keyIterator
->getNextObject()))) {
328 OSString
* libraryVersion
= NULL
; // do not release
330 // Each key's length is not >= KMOD_MAX_NAME
331 if (key
->getLength() >= KMOD_MAX_NAME
) {
336 libraryVersion
= OSDynamicCast(OSString
,
337 libraries
->getObject(key
));
338 if (!libraryVersion
) {
343 // Each value is a valid version string
344 vers
= VERS_parse_string(libraryVersion
->getCStringNoCopy());
351 keyIterator
->release();
355 // OSBundleRequired, if present, must have a legal value.
356 // If it is not present and if we are safe-booting,
357 // then the kext is not eligible.
359 rawValue
= extension
->getObject("OSBundleRequired");
361 stringValue
= OSDynamicCast(OSString
, rawValue
);
366 if (!stringValue
->isEqualTo("Root") &&
367 !stringValue
->isEqualTo("Local-Root") &&
368 !stringValue
->isEqualTo("Network-Root") &&
369 !stringValue
->isEqualTo("Safe Boot") &&
370 !stringValue
->isEqualTo("Console")) {
376 } else if (PE_parse_boot_argn("-x", namep
, sizeof (namep
))) { /* safe boot */
377 ineligible_for_safe_boot
= true;
384 if (keyIterator
) keyIterator
->release();
387 if (ineligible_for_safe_boot
) {
388 IOLog(VTYELLOW
"Skipping extension \"%s\" during safe boot "
389 "(no OSBundleRequired property)\n"
391 bundleIdentifier
->getCStringNoCopy());
392 } else if (not_a_dict
) {
394 IOLog(VTYELLOW
"mkext entry %d: " VTRESET
, index
);
396 IOLog(VTYELLOW
"kernel extension " VTRESET
);
398 IOLog(VTYELLOW
"info dictionary isn't a dictionary\n"
400 } else if (id_missing
) {
402 IOLog(VTYELLOW
"mkext entry %d: " VTRESET
, index
);
404 IOLog(VTYELLOW
"kernel extension " VTRESET
);
406 IOLog(VTYELLOW
"\"CFBundleIdentifier\" property is "
407 "missing or not a string\n"
410 IOLog(VTYELLOW
"kernel extension \"%s\": info dictionary is invalid\n"
411 VTRESET
, bundleIdentifier
->getCStringNoCopy());
420 /*********************************************************************
421 *********************************************************************/
422 OSDictionary
* compareExtensionVersions(
423 OSDictionary
* incumbent
,
424 OSDictionary
* candidate
) {
426 OSDictionary
* winner
= NULL
;
428 OSDictionary
* incumbentPlist
= NULL
;
429 OSDictionary
* candidatePlist
= NULL
;
430 OSString
* incumbentName
= NULL
;
431 OSString
* candidateName
= NULL
;
432 OSString
* incumbentVersionString
= NULL
;
433 OSString
* candidateVersionString
= NULL
;
434 VERS_version incumbent_vers
= 0;
435 VERS_version candidate_vers
= 0;
437 incumbentPlist
= OSDynamicCast(OSDictionary
,
438 incumbent
->getObject("plist"));
439 candidatePlist
= OSDynamicCast(OSDictionary
,
440 candidate
->getObject("plist"));
442 if (!incumbentPlist
|| !candidatePlist
) {
443 IOLog("compareExtensionVersions() called with invalid "
444 "extension dictionaries.\n");
450 incumbentName
= OSDynamicCast(OSString
,
451 incumbentPlist
->getObject("CFBundleIdentifier"));
452 candidateName
= OSDynamicCast(OSString
,
453 candidatePlist
->getObject("CFBundleIdentifier"));
454 incumbentVersionString
= OSDynamicCast(OSString
,
455 incumbentPlist
->getObject("CFBundleVersion"));
456 candidateVersionString
= OSDynamicCast(OSString
,
457 candidatePlist
->getObject("CFBundleVersion"));
459 if (!incumbentName
|| !candidateName
||
460 !incumbentVersionString
|| !candidateVersionString
) {
462 IOLog("compareExtensionVersions() called with invalid "
463 "extension dictionaries.\n");
469 if (strcmp(incumbentName
->getCStringNoCopy(),
470 candidateName
->getCStringNoCopy())) {
472 IOLog("compareExtensionVersions() called with different "
473 "extension names (%s and %s).\n",
474 incumbentName
->getCStringNoCopy(),
475 candidateName
->getCStringNoCopy());
481 incumbent_vers
= VERS_parse_string(incumbentVersionString
->getCStringNoCopy());
482 if (incumbent_vers
< 0) {
484 IOLog(VTYELLOW
"Error parsing version string for extension %s (%s)\n"
486 incumbentName
->getCStringNoCopy(),
487 incumbentVersionString
->getCStringNoCopy());
493 candidate_vers
= VERS_parse_string(candidateVersionString
->getCStringNoCopy());
494 if (candidate_vers
< 0) {
496 IOLog(VTYELLOW
"Error parsing version string for extension %s (%s)\n"
498 candidateName
->getCStringNoCopy(),
499 candidateVersionString
->getCStringNoCopy());
505 if (candidate_vers
> incumbent_vers
) {
506 IOLog(VTYELLOW
"Replacing extension \"%s\" with newer version "
507 "(%s -> %s).\n" VTRESET
,
508 incumbentName
->getCStringNoCopy(),
509 incumbentVersionString
->getCStringNoCopy(),
510 candidateVersionString
->getCStringNoCopy());
515 IOLog(VTYELLOW
"Skipping duplicate extension \"%s\" with older/same "
516 " version (%s -> %s).\n" VTRESET
,
517 candidateName
->getCStringNoCopy(),
518 candidateVersionString
->getCStringNoCopy(),
519 incumbentVersionString
->getCStringNoCopy());
527 // no cleanup, how nice
532 /*********************************************************************
533 * This function merges entries in the mergeFrom dictionary into the
534 * mergeInto dictionary. If it returns false, the two dictionaries are
535 * not altered. If it returns true, then mergeInto may have new
536 * entries; any keys that were already present in mergeInto are
537 * removed from mergeFrom, so that the caller can see what was
539 *********************************************************************/
540 bool mergeExtensionDictionaries(OSDictionary
* mergeInto
,
541 OSDictionary
* mergeFrom
) {
544 OSDictionary
* mergeIntoCopy
= NULL
; // must release
545 OSDictionary
* mergeFromCopy
= NULL
; // must release
546 OSCollectionIterator
* keyIterator
= NULL
; // must release
547 OSString
* key
; // don't release
549 /* Add 1 to count to guarantee copy can grow (grr).
551 mergeIntoCopy
= OSDictionary::withDictionary(mergeInto
,
552 mergeInto
->getCount() + 1);
553 if (!mergeIntoCopy
) {
554 IOLog("Error: Failed to copy 'into' extensions dictionary "
561 /* Add 1 to count to guarantee copy can grow (grr).
563 mergeFromCopy
= OSDictionary::withDictionary(mergeFrom
,
564 mergeFrom
->getCount() + 1);
565 if (!mergeFromCopy
) {
566 IOLog("Error: Failed to copy 'from' extensions dictionary "
573 keyIterator
= OSCollectionIterator::withCollection(mergeFrom
);
575 IOLog("Error: Failed to allocate iterator for extensions.\n");
583 * Loop through "from" dictionary, checking if the identifier already
584 * exists in the "into" dictionary and checking versions if it does.
586 while ((key
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
587 OSDictionary
* incumbentExt
= OSDynamicCast(OSDictionary
,
588 mergeIntoCopy
->getObject(key
));
589 OSDictionary
* candidateExt
= OSDynamicCast(OSDictionary
,
590 mergeFrom
->getObject(key
));
593 if (!mergeIntoCopy
->setObject(key
, candidateExt
)) {
595 /* This is a fatal error, so bail.
597 IOLog("mergeExtensionDictionaries(): Failed to add "
599 key
->getCStringNoCopy());
605 OSDictionary
* mostRecentExtension
=
606 compareExtensionVersions(incumbentExt
, candidateExt
);
608 if (mostRecentExtension
== incumbentExt
) {
609 mergeFromCopy
->removeObject(key
);
610 } else if (mostRecentExtension
== candidateExt
) {
612 if (!mergeIntoCopy
->setObject(key
, candidateExt
)) {
614 /* This is a fatal error, so bail.
616 IOLog("mergeExtensionDictionaries(): Failed to add "
618 key
->getCStringNoCopy());
623 } else /* should be NULL */ {
625 /* This is a nonfatal error, so continue doing others.
627 IOLog("mergeExtensionDictionaries(): Error comparing "
628 "versions of duplicate extensions %s.\n",
629 key
->getCStringNoCopy());
638 /* If successful, replace the contents of the original
639 * dictionaries with those of the modified copies.
642 mergeInto
->flushCollection();
643 mergeInto
->merge(mergeIntoCopy
);
644 mergeFrom
->flushCollection();
645 mergeFrom
->merge(mergeFromCopy
);
648 if (mergeIntoCopy
) mergeIntoCopy
->release();
649 if (mergeFromCopy
) mergeFromCopy
->release();
650 if (keyIterator
) keyIterator
->release();
657 * These bits are used to parse data made available by bootx.
659 #define BOOTX_KEXT_PREFIX "Driver-"
660 #define BOOTX_MULTIKEXT_PREFIX "DriversPackage-"
662 typedef struct MemoryMapFileInfo
{
667 typedef struct BootxDriverInfo
{
674 typedef struct MkextEntryInfo
{
675 vm_address_t base_address
;
676 mkext_file
* fileinfo
;
680 /*********************************************************************
681 * This private function reads the data for a single extension from
682 * the bootx memory-map's propery dict, returning a dictionary with
683 * keys "plist" for the extension's Info.plist as a parsed OSDictionary
684 * and "code" for the extension's executable code as an OSData.
685 *********************************************************************/
686 OSDictionary
* readExtension(OSDictionary
* propertyDict
,
687 const char * memory_map_name
) {
690 OSData
* bootxDriverDataObject
= NULL
;
691 OSDictionary
* driverPlist
= NULL
;
692 OSString
* driverName
= NULL
;
693 OSData
* driverCode
= NULL
;
694 OSString
* errorString
= NULL
;
695 OSDictionary
* driverDict
= NULL
;
697 const MemoryMapFileInfo
* driverInfo
= 0;
698 BootxDriverInfo
* dataBuffer
;
700 kmod_info_t
* loaded_kmod
= NULL
;
702 bootxDriverDataObject
= OSDynamicCast(OSData
,
703 propertyDict
->getObject(memory_map_name
));
704 // don't release bootxDriverDataObject
706 if (!bootxDriverDataObject
) {
707 IOLog("Error: No driver data object "
708 "for device tree entry \"%s\".\n",
715 driverDict
= OSDictionary::withCapacity(2);
717 IOLog("Error: Couldn't allocate dictionary "
718 "for device tree entry \"%s\".\n", memory_map_name
);
724 driverInfo
= (const MemoryMapFileInfo
*)
725 bootxDriverDataObject
->getBytesNoCopy(0,
726 sizeof(MemoryMapFileInfo
));
727 #if defined (__ppc__) || defined (__arm__)
728 dataBuffer
= (BootxDriverInfo
*)ml_static_ptovirt(driverInfo
->paddr
);
729 #elif defined (__i386__)
730 dataBuffer
= (BootxDriverInfo
*)ml_boot_ptovirt(driverInfo
->paddr
);
731 dataBuffer
->plistAddr
= (char *)ml_boot_ptovirt((vm_address_t
)dataBuffer
->plistAddr
);
732 if (dataBuffer
->moduleAddr
)
733 dataBuffer
->moduleAddr
= (void *)ml_boot_ptovirt((vm_address_t
)dataBuffer
->moduleAddr
);
735 #error unsupported architecture
738 IOLog("Error: No data buffer "
739 "for device tree entry \"%s\".\n", memory_map_name
);
745 driverPlist
= OSDynamicCast(OSDictionary
,
746 OSUnserializeXML(dataBuffer
->plistAddr
, &errorString
));
748 IOLog("Error: Couldn't read XML property list "
749 "for device tree entry \"%s\".\n", memory_map_name
);
752 IOLog("XML parse error: %s.\n",
753 errorString
->getCStringNoCopy());
761 driverName
= OSDynamicCast(OSString
,
762 driverPlist
->getObject("CFBundleIdentifier")); // do not release
764 IOLog("Error: Device tree entry \"%s\" has "
765 "no \"CFBundleIdentifier\" property.\n", memory_map_name
);
771 /* Check if kmod is already loaded and is a real loadable one (has
774 loaded_kmod
= kmod_lookupbyname_locked(driverName
->getCStringNoCopy());
775 if (loaded_kmod
&& loaded_kmod
->address
) {
776 IOLog("Skipping new extension \"%s\"; an extension named "
777 "\"%s\" is already loaded.\n",
778 driverName
->getCStringNoCopy(),
785 if (!validateExtensionDict(driverPlist
, -1)) {
786 // validateExtensionsDict() logs an error
791 driverDict
->setObject("plist", driverPlist
);
793 /* It's perfectly okay for a KEXT to have no executable.
794 * Check that moduleAddr is nonzero before attempting to
797 * NOTE: The driverCode object is created "no-copy", so
798 * it doesn't own that memory. The memory must be freed
799 * separately from the OSData object (see
800 * clearStartupExtensionsAndLoaderInfo() at the end of this file).
802 if (dataBuffer
->moduleAddr
&& dataBuffer
->moduleLength
) {
803 driverCode
= OSData::withBytesNoCopy(dataBuffer
->moduleAddr
,
804 dataBuffer
->moduleLength
);
806 IOLog("Error: Couldn't allocate data object "
807 "to hold code for device tree entry \"%s\".\n",
815 driverDict
->setObject("code", driverCode
);
822 kfree(loaded_kmod
, sizeof(kmod_info_t
));
825 // do not release bootxDriverDataObject
826 // do not release driverName
829 driverPlist
->release();
832 errorString
->release();
835 driverCode
->release();
839 driverDict
->release();
847 /*********************************************************************
848 * Used to uncompress a single file entry in an mkext archive.
850 * The OSData returned does not own its memory! You must deallocate
851 * that memory using kmem_free() before releasing the OSData().
852 *********************************************************************/
853 static bool uncompressFile(u_int8_t
*base_address
, mkext_file
* fileinfo
,
854 /* out */ OSData
** file
) {
857 kern_return_t kern_result
;
858 u_int8_t
* uncompressed_file
= 0; // kmem_free() on error
859 OSData
* uncompressedFile
= 0; // returned
860 size_t uncompressed_size
= 0;
862 size_t offset
= OSSwapBigToHostInt32(fileinfo
->offset
);
863 size_t compsize
= OSSwapBigToHostInt32(fileinfo
->compsize
);
864 size_t realsize
= OSSwapBigToHostInt32(fileinfo
->realsize
);
865 time_t modifiedsecs
= OSSwapBigToHostInt32(fileinfo
->modifiedsecs
);
869 /* If these four fields are zero there's no file, but that isn't
872 if (offset
== 0 && compsize
== 0 &&
873 realsize
== 0 && modifiedsecs
== 0) {
877 // Add 1 for '\0' to terminate XML string!
878 kern_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&uncompressed_file
,
880 if (kern_result
!= KERN_SUCCESS
) {
881 IOLog("Error: Couldn't allocate data buffer "
882 "to uncompress file.\n");
888 uncompressedFile
= OSData::withBytesNoCopy(uncompressed_file
,
890 if (!uncompressedFile
) {
891 IOLog("Error: Couldn't allocate data object "
892 "to uncompress file.\n");
899 uncompressed_size
= decompress_lzss(uncompressed_file
,
900 base_address
+ offset
,
902 if (uncompressed_size
!= realsize
) {
903 IOLog("Error: Uncompressed file is not the length "
909 uncompressed_file
[uncompressed_size
] = '\0';
911 bcopy(base_address
+ offset
, uncompressed_file
,
913 uncompressed_file
[realsize
] = '\0';
916 *file
= uncompressedFile
;
920 if (uncompressed_file
) {
921 kmem_free(kernel_map
, (vm_address_t
)uncompressed_file
,
924 if (uncompressedFile
) {
925 uncompressedFile
->release();
932 bool uncompressModule(OSData
*compData
, /* out */ OSData
** file
) {
934 const MkextEntryInfo
*info
= (const MkextEntryInfo
*) compData
->getBytesNoCopy();
936 return uncompressFile((u_int8_t
*) info
->base_address
,
937 info
->fileinfo
, file
);
941 /*********************************************************************
942 * Does the work of pulling extensions out of an mkext archive located
944 *********************************************************************/
945 bool extractExtensionsFromArchive(const MemoryMapFileInfo
* mkext_file_info
,
947 OSDictionary
* extensions
) {
951 u_int8_t
* crc_address
= 0;
953 mkext_header
* mkext_data
= 0; // don't free
954 mkext_kext
* onekext_data
= 0; // don't free
955 mkext_file
* plist_file
= 0; // don't free
956 mkext_file
* module_file
= 0; // don't free
957 kmod_info_t
* loaded_kmod
= 0; // must free
959 OSData
* driverPlistDataObject
= 0; // must release
960 OSDictionary
* driverPlist
= 0; // must release
961 OSData
* driverCode
= 0; // must release
962 OSDictionary
* driverDict
= 0; // must release
963 OSString
* moduleName
= 0; // don't release
964 OSString
* errorString
= NULL
; // must release
966 OSData
* moduleInfo
= 0; // must release
967 MkextEntryInfo module_info
;
969 IORegistryEntry
* root
;
970 OSData
* checksumObj
;
973 // addExtensionsFromArchive passes a kernel virtual address
974 mkext_data
= (mkext_header
*)mkext_file_info
->paddr
;
976 #if defined (__ppc__) || defined (__arm__)
977 mkext_data
= (mkext_header
*)ml_static_ptovirt(mkext_file_info
->paddr
);
978 #elif defined (__i386__)
979 mkext_data
= (mkext_header
*)ml_boot_ptovirt(mkext_file_info
->paddr
);
981 #error unsupported architecture
985 if (OSSwapBigToHostInt32(mkext_data
->magic
) != MKEXT_MAGIC
||
986 OSSwapBigToHostInt32(mkext_data
->signature
) != MKEXT_SIGN
) {
987 IOLog("Error: Extension archive has invalid magic or signature.\n");
993 if (OSSwapBigToHostInt32(mkext_data
->length
) != mkext_file_info
->length
) {
994 IOLog("Error: Mismatch between extension archive & "
995 "recorded length.\n");
1001 crc_address
= (u_int8_t
*)&mkext_data
->version
;
1002 checksum
= adler32(crc_address
,
1003 (unsigned int)mkext_data
+
1004 OSSwapBigToHostInt32(mkext_data
->length
) - (unsigned int)crc_address
);
1006 if (OSSwapBigToHostInt32(mkext_data
->adler32
) != checksum
) {
1007 IOLog("Error: Extension archive has a bad checksum.\n");
1013 root
= IORegistryEntry::getRegistryRoot();
1015 checksumObj
= OSData::withBytes((void *)&checksum
,
1017 assert(checksumObj
);
1019 root
->setProperty(kIOStartupMkextCRC
, checksumObj
);
1020 checksumObj
->release();
1023 /* If the MKEXT archive isn't fat, check that the CPU type & subtype
1024 * match that of the running kernel.
1026 if (OSSwapBigToHostInt32(mkext_data
->cputype
) != (UInt32
)CPU_TYPE_ANY
) {
1027 kern_return_t kresult
= KERN_FAILURE
;
1028 host_basic_info_data_t hostinfo
;
1029 host_info_t hostinfo_ptr
= (host_info_t
)&hostinfo
;
1030 mach_msg_type_number_t count
= sizeof(hostinfo
)/sizeof(integer_t
);
1032 kresult
= host_info((host_t
)1, HOST_BASIC_INFO
,
1033 hostinfo_ptr
, &count
);
1034 if (kresult
!= KERN_SUCCESS
) {
1035 IOLog("Error: Couldn't get current host info.\n");
1040 if ((UInt32
)hostinfo
.cpu_type
!=
1041 OSSwapBigToHostInt32(mkext_data
->cputype
)) {
1043 IOLog("Error: Extension archive doesn't contain software "
1044 "for this computer's CPU type.\n");
1049 if (!grade_binary(OSSwapBigToHostInt32(mkext_data
->cputype
),
1050 OSSwapBigToHostInt32(mkext_data
->cpusubtype
))) {
1051 IOLog("Error: Extension archive doesn't contain software "
1052 "for this computer's CPU subtype.\n");
1059 for (unsigned int i
= 0;
1060 i
< OSSwapBigToHostInt32(mkext_data
->numkexts
);
1064 kfree(loaded_kmod
, sizeof(kmod_info_t
));
1068 if (driverPlistDataObject
) {
1069 kmem_free(kernel_map
,
1070 (unsigned int)driverPlistDataObject
->getBytesNoCopy(),
1071 driverPlistDataObject
->getLength());
1073 driverPlistDataObject
->release();
1074 driverPlistDataObject
= NULL
;
1077 driverPlist
->release();
1081 driverCode
->release();
1085 driverDict
->release();
1089 errorString
->release();
1093 onekext_data
= &mkext_data
->kext
[i
];
1094 plist_file
= &onekext_data
->plist
;
1095 module_file
= &onekext_data
->module;
1097 if (!uncompressFile((u_int8_t
*)mkext_data
, plist_file
,
1098 &driverPlistDataObject
)) {
1100 IOLog("Error: couldn't uncompress plist file "
1101 "from multikext archive entry %d.\n", i
);
1106 if (!driverPlistDataObject
) {
1107 IOLog("Error: No property list present "
1108 "for multikext archive entry %d.\n", i
);
1112 driverPlist
= OSDynamicCast(OSDictionary
,
1114 (const char *)driverPlistDataObject
->getBytesNoCopy(),
1117 IOLog("Error: Couldn't read XML property list "
1118 "for multikext archive entry %d.\n", i
);
1121 IOLog("XML parse error: %s.\n",
1122 errorString
->getCStringNoCopy());
1128 if (!validateExtensionDict(driverPlist
, i
)) {
1129 // validateExtensionsDict() logs an error
1135 /* Get the extension's module name. This is used to record
1138 moduleName
= OSDynamicCast(OSString
,
1139 driverPlist
->getObject("CFBundleIdentifier")); // do not release
1141 IOLog("Error: Multikext archive entry %d has "
1142 "no \"CFBundleIdentifier\" property.\n", i
);
1144 continue; // assume a kext config error & continue
1147 /* Check if kmod is already loaded and is a real loadable one (has
1150 loaded_kmod
= kmod_lookupbyname_locked(moduleName
->getCStringNoCopy());
1151 if (loaded_kmod
&& loaded_kmod
->address
) {
1152 IOLog("Skipping new extension \"%s\"; an extension named "
1153 "\"%s\" is already loaded.\n",
1154 moduleName
->getCStringNoCopy(),
1160 driverDict
= OSDictionary::withCapacity(2);
1162 IOLog("Error: Couldn't allocate dictionary "
1163 "for multikext archive entry %d.\n", i
);
1169 driverDict
->setObject("plist", driverPlist
);
1172 * Prepare an entry to hold the mkext entry info for the
1173 * compressed binary module, if there is one. If all four fields
1174 * of the module entry are zero, there isn't one.
1176 if (!(loaded_kmod
&& loaded_kmod
->address
) && (OSSwapBigToHostInt32(module_file
->offset
) ||
1177 OSSwapBigToHostInt32(module_file
->compsize
) ||
1178 OSSwapBigToHostInt32(module_file
->realsize
) ||
1179 OSSwapBigToHostInt32(module_file
->modifiedsecs
))) {
1181 moduleInfo
= OSData::withCapacity(sizeof(MkextEntryInfo
));
1183 IOLog("Error: Couldn't allocate data object "
1184 "for multikext archive entry %d.\n", i
);
1190 module_info
.base_address
= (vm_address_t
)mkext_data
;
1191 module_info
.fileinfo
= module_file
;
1193 if (!moduleInfo
->appendBytes(&module_info
, sizeof(module_info
))) {
1194 IOLog("Error: Couldn't record info "
1195 "for multikext archive entry %d.\n", i
);
1201 driverDict
->setObject("compressedCode", moduleInfo
);
1204 OSDictionary
* incumbentExt
= OSDynamicCast(OSDictionary
,
1205 extensions
->getObject(moduleName
));
1207 if (!incumbentExt
) {
1208 extensions
->setObject(moduleName
, driverDict
);
1210 OSDictionary
* mostRecentExtension
=
1211 compareExtensionVersions(incumbentExt
, driverDict
);
1213 if (mostRecentExtension
== incumbentExt
) {
1214 /* Do nothing, we've got the most recent. */
1215 } else if (mostRecentExtension
== driverDict
) {
1216 if (!extensions
->setObject(moduleName
, driverDict
)) {
1218 /* This is a fatal error, so bail.
1220 IOLog("extractExtensionsFromArchive(): Failed to add "
1222 moduleName
->getCStringNoCopy());
1227 } else /* should be NULL */ {
1229 /* This is a nonfatal error, so continue.
1231 IOLog("extractExtensionsFromArchive(): Error comparing "
1232 "versions of duplicate extensions %s.\n",
1233 moduleName
->getCStringNoCopy());
1242 if (loaded_kmod
) kfree(loaded_kmod
, sizeof(kmod_info_t
));
1243 if (driverPlistDataObject
) {
1244 kmem_free(kernel_map
,
1245 (unsigned int)driverPlistDataObject
->getBytesNoCopy(),
1246 driverPlistDataObject
->getLength());
1247 driverPlistDataObject
->release();
1249 if (driverPlist
) driverPlist
->release();
1250 if (driverCode
) driverCode
->release();
1251 if (moduleInfo
) moduleInfo
->release();
1252 if (driverDict
) driverDict
->release();
1253 if (errorString
) errorString
->release();
1258 /*********************************************************************
1260 *********************************************************************/
1261 bool readExtensions(OSDictionary
* propertyDict
,
1262 const char * memory_map_name
,
1263 OSDictionary
* extensions
) {
1266 OSData
* mkextDataObject
= 0; // don't release
1267 const MemoryMapFileInfo
* mkext_file_info
= 0; // don't free
1269 mkextDataObject
= OSDynamicCast(OSData
,
1270 propertyDict
->getObject(memory_map_name
));
1271 // don't release mkextDataObject
1273 if (!mkextDataObject
) {
1274 IOLog("Error: No mkext data object "
1275 "for device tree entry \"%s\".\n",
1282 mkext_file_info
= (const MemoryMapFileInfo
*)mkextDataObject
->getBytesNoCopy();
1283 if (!mkext_file_info
) {
1288 result
= extractExtensionsFromArchive(mkext_file_info
, false /*physical*/, extensions
);
1292 if (!result
&& extensions
) {
1293 extensions
->flushCollection();
1300 /*********************************************************************
1301 * Adds the personalities for an extensions dictionary to the global
1303 *********************************************************************/
1304 bool addPersonalities(OSDictionary
* extensions
) {
1306 OSCollectionIterator
* keyIterator
= NULL
; // must release
1307 OSString
* key
; // don't release
1308 OSDictionary
* driverDict
= NULL
; // don't release
1309 OSDictionary
* driverPlist
= NULL
; // don't release
1310 OSDictionary
* thisDriverPersonalities
= NULL
; // don't release
1311 OSArray
* allDriverPersonalities
= NULL
; // must release
1313 allDriverPersonalities
= OSArray::withCapacity(1);
1314 if (!allDriverPersonalities
) {
1315 IOLog("Error: Couldn't allocate personality dictionary.\n");
1321 /* Record all personalities found so that they can be
1322 * added to the catalogue.
1323 * Note: Not all extensions have personalities.
1326 keyIterator
= OSCollectionIterator::withCollection(extensions
);
1328 IOLog("Error: Couldn't allocate iterator to record personalities.\n");
1334 while ( ( key
= OSDynamicCast(OSString
,
1335 keyIterator
->getNextObject() ))) {
1337 driverDict
= OSDynamicCast(OSDictionary
,
1338 extensions
->getObject(key
));
1339 driverPlist
= OSDynamicCast(OSDictionary
,
1340 driverDict
->getObject("plist"));
1341 thisDriverPersonalities
= OSDynamicCast(OSDictionary
,
1342 driverPlist
->getObject("IOKitPersonalities"));
1344 if (thisDriverPersonalities
) {
1345 OSCollectionIterator
* pIterator
;
1346 OSString
* locakKey
;
1347 pIterator
= OSCollectionIterator::withCollection(
1348 thisDriverPersonalities
);
1350 IOLog("Error: Couldn't allocate iterator "
1351 "to record extension personalities.\n");
1355 while ( (locakKey
= OSDynamicCast(OSString
,
1356 pIterator
->getNextObject())) ) {
1358 OSDictionary
* personality
= OSDynamicCast(
1360 thisDriverPersonalities
->getObject(locakKey
));
1362 allDriverPersonalities
->setObject(personality
);
1365 pIterator
->release();
1367 } /* extract personalities */
1370 /* Add all personalities found to the IOCatalogue,
1371 * but don't start matching.
1373 gIOCatalogue
->addDrivers(allDriverPersonalities
, false);
1377 if (allDriverPersonalities
) allDriverPersonalities
->release();
1378 if (keyIterator
) keyIterator
->release();
1384 /*********************************************************************
1385 * Called from IOCatalogue to add extensions from an mkext archive.
1386 * This function makes a copy of the mkext object passed in because
1387 * the device tree support code dumps it after calling us (indirectly
1388 * through the IOCatalogue).
1389 *********************************************************************/
1390 bool addExtensionsFromArchive(OSData
* mkextDataObject
) {
1393 OSDictionary
* startupExtensions
= NULL
; // don't release
1394 OSArray
* bootLoaderObjects
= NULL
; // don't release
1395 OSDictionary
* extensions
= NULL
; // must release
1396 MemoryMapFileInfo mkext_file_info
;
1397 OSCollectionIterator
* keyIterator
= NULL
; // must release
1398 OSString
* key
= NULL
; // don't release
1400 startupExtensions
= getStartupExtensions();
1401 if (!startupExtensions
) {
1402 IOLog("Can't record extension archive; there is no"
1403 " extensions dictionary.\n");
1409 bootLoaderObjects
= getBootLoaderObjects();
1410 if (! bootLoaderObjects
) {
1411 IOLog("Error: Couldn't allocate array to hold temporary objects.\n");
1417 extensions
= OSDictionary::withCapacity(2);
1419 IOLog("Error: Couldn't allocate dictionary to unpack "
1420 "extension archive.\n");
1426 mkext_file_info
.paddr
= (UInt32
)mkextDataObject
->getBytesNoCopy();
1427 mkext_file_info
.length
= mkextDataObject
->getLength();
1429 /* Save the local mkext data object so that we can deallocate it later.
1431 bootLoaderObjects
->setObject(mkextDataObject
);
1433 result
= extractExtensionsFromArchive(&mkext_file_info
, true /*virtual*/, extensions
);
1435 IOLog("Error: Failed to extract extensions from archive.\n");
1441 result
= mergeExtensionDictionaries(startupExtensions
, extensions
);
1443 IOLog("Error: Failed to merge new extensions into existing set.\n");
1448 result
= addPersonalities(extensions
);
1450 IOLog("Error: Failed to add personalities for extensions extracted "
1460 IOLog("Error: Failed to record extensions from archive.\n");
1463 keyIterator
= OSCollectionIterator::withCollection(
1467 while ( (key
= OSDynamicCast(OSString
,
1468 keyIterator
->getNextObject())) ) {
1470 IOLog("Added extension \"%s\" from archive.\n",
1471 key
->getCStringNoCopy());
1474 keyIterator
->release();
1478 if (extensions
) extensions
->release();
1484 /*********************************************************************
1485 * This function builds dictionaries for the startup extensions
1486 * put into memory by bootx, recording each in the startup extensions
1487 * dictionary. The dictionary format is this:
1490 * "plist" = (the extension's Info.plist as an OSDictionary)
1491 * "code" = (an OSData containing the executable file)
1494 * This function returns true if any extensions were found and
1495 * recorded successfully, or if there are no start extensions,
1496 * and false if an unrecoverable error occurred. An error reading
1497 * a single extension is not considered fatal, and this function
1498 * will simply skip the problematic extension to try the next one.
1499 *********************************************************************/
1501 bool recordStartupExtensions(void) {
1503 OSDictionary
* startupExtensions
= NULL
; // must release
1504 OSDictionary
* existingExtensions
= NULL
; // don't release
1505 OSDictionary
* mkextExtensions
= NULL
; // must release
1506 IORegistryEntry
* bootxMemoryMap
= NULL
; // must release
1507 OSDictionary
* propertyDict
= NULL
; // must release
1508 OSCollectionIterator
* keyIterator
= NULL
; // must release
1509 OSString
* key
= NULL
; // don't release
1511 OSDictionary
* newDriverDict
= NULL
; // must release
1512 OSDictionary
* driverPlist
= NULL
; // don't release
1514 struct section
* infosect
;
1515 struct section
* symsect
;
1516 unsigned int prelinkedCount
= 0;
1518 existingExtensions
= getStartupExtensions();
1519 if (!existingExtensions
) {
1520 IOLog("Error: There is no dictionary for startup extensions.\n");
1526 startupExtensions
= OSDictionary::withCapacity(1);
1527 if (!startupExtensions
) {
1528 IOLog("Error: Couldn't allocate dictionary "
1529 "to record startup extensions.\n");
1536 // add any prelinked modules as startup extensions
1538 infosect
= getsectbyname("__PRELINK", "__info");
1539 symsect
= getsectbyname("__PRELINK", "__symtab");
1540 if (infosect
&& infosect
->addr
&& infosect
->size
1541 && symsect
&& symsect
->addr
&& symsect
->size
) do
1543 gIOPrelinkedModules
= OSDynamicCast(OSArray
,
1544 OSUnserializeXML((const char *) infosect
->addr
, NULL
));
1546 if (!gIOPrelinkedModules
)
1548 for( unsigned int idx
= 0;
1549 (propertyDict
= OSDynamicCast(OSDictionary
, gIOPrelinkedModules
->getObject(idx
)));
1552 enum { kPrelinkReservedCount
= 4 };
1554 /* Get the extension's module name. This is used to record
1555 * the extension. Do *not* release the moduleName.
1557 OSString
* moduleName
= OSDynamicCast(OSString
,
1558 propertyDict
->getObject("CFBundleIdentifier"));
1560 IOLog("Error: Prelinked module entry has "
1561 "no \"CFBundleIdentifier\" property.\n");
1566 /* Add the kext, & its plist.
1568 newDriverDict
= OSDictionary::withCapacity(4);
1569 assert(newDriverDict
);
1570 newDriverDict
->setObject("plist", propertyDict
);
1571 startupExtensions
->setObject(moduleName
, newDriverDict
);
1572 newDriverDict
->release();
1574 /* Add the code if present.
1576 OSData
* data
= OSDynamicCast(OSData
, propertyDict
->getObject("OSBundlePrelink"));
1578 if (data
->getLength() < (kPrelinkReservedCount
* sizeof(UInt32
))) {
1579 IOLog("Error: Prelinked module entry has "
1580 "invalid \"OSBundlePrelink\" property.\n");
1584 const UInt32
* prelink
;
1585 prelink
= (const UInt32
*) data
->getBytesNoCopy();
1586 kmod_info_t
* kmod_info
= (kmod_info_t
*) OSReadBigInt32(prelink
, 0);
1587 // end of "file" is end of symbol sect
1588 data
= OSData::withBytesNoCopy((void *) kmod_info
->address
,
1589 symsect
->addr
+ symsect
->size
- kmod_info
->address
);
1590 newDriverDict
->setObject("code", data
);
1595 /* Add the symbols if present.
1597 OSNumber
* num
= OSDynamicCast(OSNumber
, propertyDict
->getObject("OSBundlePrelinkSymbols"));
1599 UInt32 offset
= num
->unsigned32BitValue();
1600 data
= OSData::withBytesNoCopy((void *) (symsect
->addr
+ offset
), symsect
->size
- offset
);
1601 newDriverDict
->setObject("code", data
);
1607 if (gIOPrelinkedModules
)
1608 IOLog("%d prelinked modules\n", prelinkedCount
);
1612 virt
= ml_static_ptovirt(infosect
->addr
);
1614 ml_static_mfree(virt
, infosect
->size
);
1616 newDriverDict
= NULL
;
1622 IORegistryEntry::fromPath(
1623 "/chosen/memory-map", // path
1626 // return value is retained so be sure to release it
1628 if (!bootxMemoryMap
) {
1629 IOLog("Error: Couldn't read booter memory map.\n");
1635 propertyDict
= bootxMemoryMap
->dictionaryWithProperties();
1636 if (!propertyDict
) {
1637 IOLog("Error: Couldn't get property dictionary "
1638 "from memory map.\n");
1644 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
1646 IOLog("Error: Couldn't allocate iterator for driver images.\n");
1652 while ( (key
= OSDynamicCast(OSString
,
1653 keyIterator
->getNextObject())) ) {
1654 /* Clear newDriverDict & mkextExtensions upon entry to the loop,
1655 * handling both successful and unsuccessful iterations.
1657 if (newDriverDict
) {
1658 newDriverDict
->release();
1659 newDriverDict
= NULL
;
1661 if (mkextExtensions
) {
1662 mkextExtensions
->release();
1663 mkextExtensions
= NULL
;
1666 const char * keyValue
= key
->getCStringNoCopy();
1668 if ( !strncmp(keyValue
, BOOTX_KEXT_PREFIX
,
1669 strlen(BOOTX_KEXT_PREFIX
)) ) {
1671 /* Read the extension from the bootx-supplied memory.
1673 newDriverDict
= readExtension(propertyDict
, keyValue
);
1674 if (!newDriverDict
) {
1675 IOLog("Error: Couldn't read data "
1676 "for device tree entry \"%s\".\n", keyValue
);
1682 /* Preprare to record the extension by getting its info plist.
1684 driverPlist
= OSDynamicCast(OSDictionary
,
1685 newDriverDict
->getObject("plist"));
1687 IOLog("Error: Extension in device tree entry \"%s\" "
1688 "has no property list.\n", keyValue
);
1694 /* Get the extension's module name. This is used to record
1695 * the extension. Do *not* release the moduleName.
1697 OSString
* moduleName
= OSDynamicCast(OSString
,
1698 driverPlist
->getObject("CFBundleIdentifier"));
1700 IOLog("Error: Device tree entry \"%s\" has "
1701 "no \"CFBundleIdentifier\" property.\n", keyValue
);
1707 /* All has gone well so far, so record the extension under
1708 * its module name, checking for an existing duplicate.
1710 * Do not release moduleName, as it's part of the extension's
1713 OSDictionary
* incumbentExt
= OSDynamicCast(OSDictionary
,
1714 startupExtensions
->getObject(moduleName
));
1716 if (!incumbentExt
) {
1717 startupExtensions
->setObject(moduleName
, newDriverDict
);
1719 OSDictionary
* mostRecentExtension
=
1720 compareExtensionVersions(incumbentExt
, newDriverDict
);
1722 if (mostRecentExtension
== incumbentExt
) {
1723 /* Do nothing, we've got the most recent. */
1724 } else if (mostRecentExtension
== newDriverDict
) {
1725 if (!startupExtensions
->setObject(moduleName
,
1728 /* This is a fatal error, so bail.
1730 IOLog("recordStartupExtensions(): Failed to add "
1732 moduleName
->getCStringNoCopy());
1737 } else /* should be NULL */ {
1739 /* This is a nonfatal error, so continue.
1741 IOLog("recordStartupExtensions(): Error comparing "
1742 "versions of duplicate extensions %s.\n",
1743 moduleName
->getCStringNoCopy());
1750 } else if ( !strncmp(keyValue
, BOOTX_MULTIKEXT_PREFIX
,
1751 strlen(BOOTX_MULTIKEXT_PREFIX
)) ) {
1753 mkextExtensions
= OSDictionary::withCapacity(10);
1754 if (!mkextExtensions
) {
1755 IOLog("Error: Couldn't allocate dictionary to unpack "
1756 "multi-extension archive.\n");
1759 goto finish
; // allocation failure is fatal for this routine
1761 if (!readExtensions(propertyDict
, keyValue
, mkextExtensions
)) {
1762 IOLog("Error: Couldn't unpack multi-extension archive.\n");
1766 if (!mergeExtensionDictionaries(startupExtensions
,
1769 IOLog("Error: Failed to merge new extensions into "
1773 goto finish
; // merge error is fatal for this routine
1778 // Do not release key.
1780 } /* while ( (key = OSDynamicCast(OSString, ...) ) ) */
1782 if (!mergeExtensionDictionaries(existingExtensions
, startupExtensions
)) {
1783 IOLog("Error: Failed to merge new extensions into existing set.\n");
1789 result
= addPersonalities(startupExtensions
);
1791 IOLog("Error: Failed to add personalities for extensions extracted "
1800 // reused so clear first!
1802 keyIterator
->release();
1807 IOLog("Error: Failed to record startup extensions.\n");
1811 keyIterator
= OSCollectionIterator::withCollection(
1815 while ( (key
= OSDynamicCast(OSString
,
1816 keyIterator
->getNextObject())) ) {
1818 IOLog("Found extension \"%s\".\n",
1819 key
->getCStringNoCopy());
1822 keyIterator
->release();
1828 if (newDriverDict
) newDriverDict
->release();
1829 if (propertyDict
) propertyDict
->release();
1830 if (bootxMemoryMap
) bootxMemoryMap
->release();
1831 if (mkextExtensions
) mkextExtensions
->release();
1832 if (startupExtensions
) startupExtensions
->release();
1838 /*********************************************************************
1839 * This function removes an entry from the dictionary of startup
1840 * extensions. It's used when an extension can't be loaded, for
1841 * whatever reason. For drivers, this allows another matching driver
1842 * to be loaded, so that, for example, a driver for the root device
1844 *********************************************************************/
1845 void removeStartupExtension(const char * extensionName
) {
1846 OSDictionary
* startupExtensions
= NULL
; // don't release
1847 OSDictionary
* extensionDict
= NULL
; // don't release
1848 OSDictionary
* extensionPlist
= NULL
; // don't release
1849 OSDictionary
* extensionPersonalities
= NULL
; // don't release
1850 OSDictionary
* personality
= NULL
; // don't release
1851 OSCollectionIterator
* keyIterator
= NULL
; // must release
1852 OSString
* key
= NULL
; // don't release
1854 startupExtensions
= getStartupExtensions();
1855 if (!startupExtensions
) goto finish
;
1858 /* Find the extension's entry in the dictionary of
1859 * startup extensions.
1861 extensionDict
= OSDynamicCast(OSDictionary
,
1862 startupExtensions
->getObject(extensionName
));
1863 if (!extensionDict
) goto finish
;
1865 extensionPlist
= OSDynamicCast(OSDictionary
,
1866 extensionDict
->getObject("plist"));
1867 if (!extensionPlist
) goto finish
;
1869 extensionPersonalities
= OSDynamicCast(OSDictionary
,
1870 extensionPlist
->getObject("IOKitPersonalities"));
1871 if (!extensionPersonalities
) goto finish
;
1873 /* If it was there, remove it from the catalogue proper
1874 * by calling removeDrivers(). Pass true for the second
1875 * argument to trigger a new round of matching, and
1876 * then remove the extension from the dictionary of startup
1879 keyIterator
= OSCollectionIterator::withCollection(
1880 extensionPersonalities
);
1882 IOLog("Error: Couldn't allocate iterator to scan"
1883 " personalities for %s.\n", extensionName
);
1887 while ((key
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
1888 personality
= OSDynamicCast(OSDictionary
,
1889 extensionPersonalities
->getObject(key
));
1893 gIOCatalogue
->removeDrivers(personality
, true);
1897 startupExtensions
->removeObject(extensionName
);
1901 if (keyIterator
) keyIterator
->release();
1905 /*********************************************************************
1906 * FIXME: This function invalidates the globals gStartupExtensions and
1907 * FIXME: ...gBootLoaderObjects without setting them to NULL. Since
1908 * FIXME: ...the code itself is immediately unloaded, there may not be
1909 * FIXME: ...any reason to worry about that!
1910 *********************************************************************/
1911 void clearStartupExtensionsAndLoaderInfo(void)
1913 OSDictionary
* startupExtensions
= NULL
; // must release
1914 OSArray
* bootLoaderObjects
= NULL
; // must release
1916 IORegistryEntry
* bootxMemoryMap
= NULL
; // must release
1917 OSDictionary
* propertyDict
= NULL
; // must release
1918 OSCollectionIterator
* keyIterator
= NULL
; // must release
1919 OSString
* key
= NULL
; // don't release
1922 * Drop any temporarily held data objects.
1924 bootLoaderObjects
= getBootLoaderObjects();
1925 if (bootLoaderObjects
) {
1926 bootLoaderObjects
->release();
1930 * If any "code" entries in driver dictionaries are accompanied
1931 * by "compressedCode" entries, then those data objects were
1932 * created based of of kmem_alloc()'ed memory, which must be
1935 startupExtensions
= getStartupExtensions();
1936 if (startupExtensions
) {
1938 OSCollectionIterator::withCollection(startupExtensions
);
1940 IOLog("Error: Couldn't allocate iterator for startup "
1943 goto memory_map
; // bail to the memory_map label
1946 while ( (key
= OSDynamicCast(OSString
,
1947 keyIterator
->getNextObject())) ) {
1949 OSDictionary
* driverDict
= 0;
1950 OSData
* codeData
= 0;
1952 driverDict
= OSDynamicCast(OSDictionary
,
1953 startupExtensions
->getObject(key
));
1955 codeData
= OSDynamicCast(OSData
,
1956 driverDict
->getObject("code"));
1959 driverDict
->getObject("compressedCode")) {
1961 kmem_free(kernel_map
,
1962 (unsigned int)codeData
->getBytesNoCopy(),
1963 codeData
->getLength());
1968 keyIterator
->release();
1969 startupExtensions
->release();
1975 * Go through the device tree's memory map and remove any driver
1979 IORegistryEntry::fromPath(
1980 "/chosen/memory-map", // path
1983 // return value is retained so be sure to release it
1985 if (!bootxMemoryMap
) {
1986 IOLog("Error: Couldn't read booter memory map.\n");
1991 propertyDict
= bootxMemoryMap
->dictionaryWithProperties();
1992 if (!propertyDict
) {
1993 IOLog("Error: Couldn't get property dictionary "
1994 "from memory map.\n");
1999 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
2001 IOLog("Error: Couldn't allocate iterator for driver images.\n");
2006 while ( (key
= OSDynamicCast(OSString
,
2007 keyIterator
->getNextObject())) ) {
2009 const char * keyValue
= key
->getCStringNoCopy();
2011 if ( !strncmp(keyValue
, BOOTX_KEXT_PREFIX
,
2012 strlen(BOOTX_KEXT_PREFIX
)) ||
2013 !strncmp(keyValue
, BOOTX_MULTIKEXT_PREFIX
,
2014 strlen(BOOTX_MULTIKEXT_PREFIX
)) ) {
2016 OSData
* bootxDriverDataObject
= NULL
;
2017 const MemoryMapFileInfo
* driverInfo
= 0;
2019 bootxDriverDataObject
= OSDynamicCast(OSData
,
2020 propertyDict
->getObject(keyValue
));
2021 // don't release bootxDriverDataObject
2023 if (!bootxDriverDataObject
) {
2026 driverInfo
= (const MemoryMapFileInfo
*)
2027 bootxDriverDataObject
->getBytesNoCopy(0,
2028 sizeof(MemoryMapFileInfo
));
2029 IODTFreeLoaderInfo((char *)keyValue
,
2030 (void *)driverInfo
->paddr
,
2031 (int)driverInfo
->length
);
2036 if (bootxMemoryMap
) bootxMemoryMap
->release();
2037 if (propertyDict
) propertyDict
->release();
2038 if (keyIterator
) keyIterator
->release();