2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 #include <libkern/c++/OSContainers.h>
31 #include <IOKit/IODeviceTreeSupport.h>
32 #include <IOKit/IORegistryEntry.h>
33 #include <IOKit/IOCatalogue.h>
34 #include <IOKit/IOKitKeysPrivate.h>
35 #include <libkern/c++/OSUnserialize.h>
36 #include <libkern/OSByteOrder.h>
37 #include <libsa/catalogue.h>
40 #include <machine/machine_routines.h>
41 #include <mach/host_info.h>
42 #include <mach/kmod.h>
43 #include <libsa/mkext.h>
44 #include <libsa/vers_rsrc.h>
45 #include <mach-o/loader.h>
48 #include <IOKit/IOLib.h>
50 #include <IOKit/assert.h>
53 extern void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
);
54 // extern kern_return_t host_info(host_t host,
55 // host_flavor_t flavor,
57 // mach_msg_type_number_t *count);
58 extern int grade_binary(cpu_type_t exectype
, cpu_subtype_t execsubtype
);
59 // Return the address of the named Mach-O segment from the currently
60 // executing 32 bit kernel, or NULL.
61 extern struct segment_command
*getsegbyname(char *seg_name
);
62 // Return the address of the named section from the named Mach-O segment
63 // from the currently executing 32 bit kernel, or NULL.
64 extern struct section
*getsectbyname(char *segname
, char *sectname
);
70 #define VTYELLOW "\033[33m"
71 #define VTRESET "\033[0m"
77 /*********************************************************************
78 *********************************************************************/
79 static OSDictionary
* gStartupExtensions
= 0;
80 static OSArray
* gBootLoaderObjects
= 0;
81 extern OSArray
* gIOPrelinkedModules
;
83 OSDictionary
* getStartupExtensions(void) {
84 if (gStartupExtensions
) {
85 return gStartupExtensions
;
87 gStartupExtensions
= OSDictionary::withCapacity(1);
88 assert (gStartupExtensions
);
90 return gStartupExtensions
;
93 /* This array holds objects that are needed to be held around during
94 * boot before kextd starts up. Currently it contains OSData objects
95 * copied from OF entries for mkext archives in device ROMs. Because
96 * the Device Tree support code dumps these after initially handing
97 * them to us, we have to be able to clean them up later.
99 OSArray
* getBootLoaderObjects(void) {
100 if (gBootLoaderObjects
) {
101 return gBootLoaderObjects
;
103 gBootLoaderObjects
= OSArray::withCapacity(1);
104 assert (gBootLoaderObjects
);
106 return gBootLoaderObjects
;
109 /*********************************************************************
110 * This function checks that a driver dict has all the required
111 * entries and does a little bit of value checking too.
113 * index is nonnegative if the index of an entry from an mkext
115 *********************************************************************/
116 bool validateExtensionDict(OSDictionary
* extension
, int index
) {
119 bool not_a_dict
= false;
120 bool id_missing
= false;
121 bool is_kernel_resource
= false;
122 bool has_executable
= false;
123 bool ineligible_for_safe_boot
= false;
124 OSString
* bundleIdentifier
= NULL
; // do not release
125 OSObject
* rawValue
= NULL
; // do not release
126 OSString
* stringValue
= NULL
; // do not release
127 OSBoolean
* booleanValue
= NULL
; // do not release
128 OSDictionary
* personalities
= NULL
; // do not release
129 OSDictionary
* libraries
= NULL
; // do not release
130 OSCollectionIterator
* keyIterator
= NULL
; // must release
131 OSString
* key
= NULL
; // do not release
133 VERS_version compatible_vers
;
134 char namep
[16]; // unused but needed for PE_parse_boot_arg()
136 // Info dict is a dictionary
137 if (!OSDynamicCast(OSDictionary
, extension
)) {
143 // CFBundleIdentifier is a string - REQUIRED
144 bundleIdentifier
= OSDynamicCast(OSString
,
145 extension
->getObject("CFBundleIdentifier"));
146 if (!bundleIdentifier
) {
152 // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME
153 if (bundleIdentifier
->getLength() >= KMOD_MAX_NAME
) {
158 // CFBundlePackageType is "KEXT" - REQUIRED
159 stringValue
= OSDynamicCast(OSString
,
160 extension
->getObject("CFBundlePackageType"));
165 if (!stringValue
->isEqualTo("KEXT")) {
170 // CFBundleVersion is a string - REQUIRED
171 stringValue
= OSDynamicCast(OSString
,
172 extension
->getObject("CFBundleVersion"));
177 // CFBundleVersion is of valid form
178 vers
= VERS_parse_string(stringValue
->getCStringNoCopy());
184 // OSBundleCompatibleVersion is a string - OPTIONAL
185 rawValue
= extension
->getObject("OSBundleCompatibleVersion");
187 stringValue
= OSDynamicCast(OSString
, rawValue
);
193 // OSBundleCompatibleVersion is of valid form
194 compatible_vers
= VERS_parse_string(stringValue
->getCStringNoCopy());
195 if (compatible_vers
< 0) {
200 // OSBundleCompatibleVersion <= CFBundleVersion
201 if (compatible_vers
> vers
) {
207 // CFBundleExecutable is a string - OPTIONAL
208 rawValue
= extension
->getObject("CFBundleExecutable");
210 stringValue
= OSDynamicCast(OSString
, rawValue
);
211 if (!stringValue
|| stringValue
->getLength() == 0) {
215 has_executable
= true;
218 // OSKernelResource is a boolean value - OPTIONAL
219 rawValue
= extension
->getObject("OSKernelResource");
221 booleanValue
= OSDynamicCast(OSBoolean
, rawValue
);
226 is_kernel_resource
= booleanValue
->isTrue();
229 // IOKitPersonalities is a dictionary - OPTIONAL
230 rawValue
= extension
->getObject("IOKitPersonalities");
232 personalities
= OSDynamicCast(OSDictionary
, rawValue
);
233 if (!personalities
) {
238 keyIterator
= OSCollectionIterator::withCollection(personalities
);
240 IOLog("Error: Failed to allocate iterator for personalities.\n");
246 while ((key
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
247 OSDictionary
* personality
= NULL
; // do not release
249 // Each personality is a dictionary
250 personality
= OSDynamicCast(OSDictionary
,
251 personalities
->getObject(key
));
257 // IOClass exists as a string - REQUIRED
258 if (!OSDynamicCast(OSString
, personality
->getObject("IOClass"))) {
263 // IOProviderClass exists as a string - REQUIRED
264 if (!OSDynamicCast(OSString
,
265 personality
->getObject("IOProviderClass"))) {
271 // CFBundleIdentifier is a string - OPTIONAL - INSERT IF ABSENT!
272 rawValue
= personality
->getObject("CFBundleIdentifier");
274 personality
->setObject("CFBundleIdentifier", bundleIdentifier
);
276 OSString
* personalityID
= NULL
; // do not release
277 personalityID
= OSDynamicCast(OSString
, rawValue
);
278 if (!personalityID
) {
282 // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME
283 if (personalityID
->getLength() >= KMOD_MAX_NAME
) {
290 // IOKitDebug is a number - OPTIONAL
291 rawValue
= personality
->getObject("IOKitDebug");
292 if (rawValue
&& !OSDynamicCast(OSNumber
, rawValue
)) {
298 keyIterator
->release();
303 // OSBundleLibraries is a dictionary - REQUIRED if
304 // not kernel resource & has executable
306 rawValue
= extension
->getObject("OSBundleLibraries");
307 if (!rawValue
&& !is_kernel_resource
&& has_executable
) {
313 libraries
= OSDynamicCast(OSDictionary
, rawValue
);
319 keyIterator
= OSCollectionIterator::withCollection(libraries
);
321 IOLog("Error: Failed to allocate iterator for libraries.\n");
327 while ((key
= OSDynamicCast(OSString
,
328 keyIterator
->getNextObject()))) {
330 OSString
* libraryVersion
= NULL
; // do not release
332 // Each key's length is not >= KMOD_MAX_NAME
333 if (key
->getLength() >= KMOD_MAX_NAME
) {
338 libraryVersion
= OSDynamicCast(OSString
,
339 libraries
->getObject(key
));
340 if (!libraryVersion
) {
345 // Each value is a valid version string
346 vers
= VERS_parse_string(libraryVersion
->getCStringNoCopy());
353 keyIterator
->release();
357 // OSBundleRequired, if present, must have a legal value.
358 // If it is not present and if we are safe-booting,
359 // then the kext is not eligible.
361 rawValue
= extension
->getObject("OSBundleRequired");
363 stringValue
= OSDynamicCast(OSString
, rawValue
);
368 if (!stringValue
->isEqualTo("Root") &&
369 !stringValue
->isEqualTo("Local-Root") &&
370 !stringValue
->isEqualTo("Network-Root") &&
371 !stringValue
->isEqualTo("Safe Boot") &&
372 !stringValue
->isEqualTo("Console")) {
378 } else if (PE_parse_boot_arg("-x", namep
)) { /* safe boot */
379 ineligible_for_safe_boot
= true;
386 if (keyIterator
) keyIterator
->release();
389 if (ineligible_for_safe_boot
) {
390 IOLog(VTYELLOW
"Skipping extension \"%s\" during safe boot "
391 "(no OSBundleRequired property)\n"
393 bundleIdentifier
->getCStringNoCopy());
394 } else if (not_a_dict
) {
396 IOLog(VTYELLOW
"mkext entry %d: " VTRESET
, index
);
398 IOLog(VTYELLOW
"kernel extension " VTRESET
);
400 IOLog(VTYELLOW
"info dictionary isn't a dictionary\n"
402 } else if (id_missing
) {
404 IOLog(VTYELLOW
"mkext entry %d: " VTRESET
, index
);
406 IOLog(VTYELLOW
"kernel extension " VTRESET
);
408 IOLog(VTYELLOW
"\"CFBundleIdentifier\" property is "
409 "missing or not a string\n"
412 IOLog(VTYELLOW
"kernel extension \"%s\": info dictionary is invalid\n"
413 VTRESET
, bundleIdentifier
->getCStringNoCopy());
422 /*********************************************************************
423 *********************************************************************/
424 OSDictionary
* compareExtensionVersions(
425 OSDictionary
* incumbent
,
426 OSDictionary
* candidate
) {
428 OSDictionary
* winner
= NULL
;
430 OSDictionary
* incumbentPlist
= NULL
;
431 OSDictionary
* candidatePlist
= NULL
;
432 OSString
* incumbentName
= NULL
;
433 OSString
* candidateName
= NULL
;
434 OSString
* incumbentVersionString
= NULL
;
435 OSString
* candidateVersionString
= NULL
;
436 VERS_version incumbent_vers
= 0;
437 VERS_version candidate_vers
= 0;
439 incumbentPlist
= OSDynamicCast(OSDictionary
,
440 incumbent
->getObject("plist"));
441 candidatePlist
= OSDynamicCast(OSDictionary
,
442 candidate
->getObject("plist"));
444 if (!incumbentPlist
|| !candidatePlist
) {
445 IOLog("compareExtensionVersions() called with invalid "
446 "extension dictionaries.\n");
452 incumbentName
= OSDynamicCast(OSString
,
453 incumbentPlist
->getObject("CFBundleIdentifier"));
454 candidateName
= OSDynamicCast(OSString
,
455 candidatePlist
->getObject("CFBundleIdentifier"));
456 incumbentVersionString
= OSDynamicCast(OSString
,
457 incumbentPlist
->getObject("CFBundleVersion"));
458 candidateVersionString
= OSDynamicCast(OSString
,
459 candidatePlist
->getObject("CFBundleVersion"));
461 if (!incumbentName
|| !candidateName
||
462 !incumbentVersionString
|| !candidateVersionString
) {
464 IOLog("compareExtensionVersions() called with invalid "
465 "extension dictionaries.\n");
471 if (strcmp(incumbentName
->getCStringNoCopy(),
472 candidateName
->getCStringNoCopy())) {
474 IOLog("compareExtensionVersions() called with different "
475 "extension names (%s and %s).\n",
476 incumbentName
->getCStringNoCopy(),
477 candidateName
->getCStringNoCopy());
483 incumbent_vers
= VERS_parse_string(incumbentVersionString
->getCStringNoCopy());
484 if (incumbent_vers
< 0) {
486 IOLog(VTYELLOW
"Error parsing version string for extension %s (%s)\n"
488 incumbentName
->getCStringNoCopy(),
489 incumbentVersionString
->getCStringNoCopy());
495 candidate_vers
= VERS_parse_string(candidateVersionString
->getCStringNoCopy());
496 if (candidate_vers
< 0) {
498 IOLog(VTYELLOW
"Error parsing version string for extension %s (%s)\n"
500 candidateName
->getCStringNoCopy(),
501 candidateVersionString
->getCStringNoCopy());
507 if (candidate_vers
> incumbent_vers
) {
508 IOLog(VTYELLOW
"Replacing extension \"%s\" with newer version "
509 "(%s -> %s).\n" VTRESET
,
510 incumbentName
->getCStringNoCopy(),
511 incumbentVersionString
->getCStringNoCopy(),
512 candidateVersionString
->getCStringNoCopy());
517 IOLog(VTYELLOW
"Skipping duplicate extension \"%s\" with older/same "
518 " version (%s -> %s).\n" VTRESET
,
519 candidateName
->getCStringNoCopy(),
520 candidateVersionString
->getCStringNoCopy(),
521 incumbentVersionString
->getCStringNoCopy());
529 // no cleanup, how nice
534 /*********************************************************************
535 * This function merges entries in the mergeFrom dictionary into the
536 * mergeInto dictionary. If it returns false, the two dictionaries are
537 * not altered. If it returns true, then mergeInto may have new
538 * entries; any keys that were already present in mergeInto are
539 * removed from mergeFrom, so that the caller can see what was
541 *********************************************************************/
542 bool mergeExtensionDictionaries(OSDictionary
* mergeInto
,
543 OSDictionary
* mergeFrom
) {
546 OSDictionary
* mergeIntoCopy
= NULL
; // must release
547 OSDictionary
* mergeFromCopy
= NULL
; // must release
548 OSCollectionIterator
* keyIterator
= NULL
; // must release
549 OSString
* key
; // don't release
551 /* Add 1 to count to guarantee copy can grow (grr).
553 mergeIntoCopy
= OSDictionary::withDictionary(mergeInto
,
554 mergeInto
->getCount() + 1);
555 if (!mergeIntoCopy
) {
556 IOLog("Error: Failed to copy 'into' extensions dictionary "
563 /* Add 1 to count to guarantee copy can grow (grr).
565 mergeFromCopy
= OSDictionary::withDictionary(mergeFrom
,
566 mergeFrom
->getCount() + 1);
567 if (!mergeFromCopy
) {
568 IOLog("Error: Failed to copy 'from' extensions dictionary "
575 keyIterator
= OSCollectionIterator::withCollection(mergeFrom
);
577 IOLog("Error: Failed to allocate iterator for extensions.\n");
585 * Loop through "from" dictionary, checking if the identifier already
586 * exists in the "into" dictionary and checking versions if it does.
588 while ((key
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
589 OSDictionary
* incumbentExt
= OSDynamicCast(OSDictionary
,
590 mergeIntoCopy
->getObject(key
));
591 OSDictionary
* candidateExt
= OSDynamicCast(OSDictionary
,
592 mergeFrom
->getObject(key
));
595 if (!mergeIntoCopy
->setObject(key
, candidateExt
)) {
597 /* This is a fatal error, so bail.
599 IOLog("mergeExtensionDictionaries(): Failed to add "
601 key
->getCStringNoCopy());
607 OSDictionary
* mostRecentExtension
=
608 compareExtensionVersions(incumbentExt
, candidateExt
);
610 if (mostRecentExtension
== incumbentExt
) {
611 mergeFromCopy
->removeObject(key
);
612 } else if (mostRecentExtension
== candidateExt
) {
614 if (!mergeIntoCopy
->setObject(key
, candidateExt
)) {
616 /* This is a fatal error, so bail.
618 IOLog("mergeExtensionDictionaries(): Failed to add "
620 key
->getCStringNoCopy());
625 } else /* should be NULL */ {
627 /* This is a nonfatal error, so continue doing others.
629 IOLog("mergeExtensionDictionaries(): Error comparing "
630 "versions of duplicate extensions %s.\n",
631 key
->getCStringNoCopy());
640 /* If successful, replace the contents of the original
641 * dictionaries with those of the modified copies.
644 mergeInto
->flushCollection();
645 mergeInto
->merge(mergeIntoCopy
);
646 mergeFrom
->flushCollection();
647 mergeFrom
->merge(mergeFromCopy
);
650 if (mergeIntoCopy
) mergeIntoCopy
->release();
651 if (mergeFromCopy
) mergeFromCopy
->release();
652 if (keyIterator
) keyIterator
->release();
659 * These bits are used to parse data made available by bootx.
661 #define BOOTX_KEXT_PREFIX "Driver-"
662 #define BOOTX_MULTIKEXT_PREFIX "DriversPackage-"
664 typedef struct MemoryMapFileInfo
{
669 typedef struct BootxDriverInfo
{
676 typedef struct MkextEntryInfo
{
677 vm_address_t base_address
;
678 mkext_file
* fileinfo
;
682 /*********************************************************************
683 * This private function reads the data for a single extension from
684 * the bootx memory-map's propery dict, returning a dictionary with
685 * keys "plist" for the extension's Info.plist as a parsed OSDictionary
686 * and "code" for the extension's executable code as an OSData.
687 *********************************************************************/
688 OSDictionary
* readExtension(OSDictionary
* propertyDict
,
689 const char * memory_map_name
) {
692 OSData
* bootxDriverDataObject
= NULL
;
693 OSDictionary
* driverPlist
= NULL
;
694 OSString
* driverName
= NULL
;
695 OSData
* driverCode
= NULL
;
696 OSString
* errorString
= NULL
;
697 OSDictionary
* driverDict
= NULL
;
699 MemoryMapFileInfo
* driverInfo
= 0;
700 BootxDriverInfo
* dataBuffer
;
702 kmod_info_t
* loaded_kmod
= NULL
;
704 bootxDriverDataObject
= OSDynamicCast(OSData
,
705 propertyDict
->getObject(memory_map_name
));
706 // don't release bootxDriverDataObject
708 if (!bootxDriverDataObject
) {
709 IOLog("Error: No driver data object "
710 "for device tree entry \"%s\".\n",
717 driverDict
= OSDictionary::withCapacity(2);
719 IOLog("Error: Couldn't allocate dictionary "
720 "for device tree entry \"%s\".\n", memory_map_name
);
726 driverInfo
= (MemoryMapFileInfo
*)
727 bootxDriverDataObject
->getBytesNoCopy(0,
728 sizeof(MemoryMapFileInfo
));
729 #if defined (__ppc__)
730 dataBuffer
= (BootxDriverInfo
*)ml_static_ptovirt(driverInfo
->paddr
);
731 #elif defined (__i386__)
732 dataBuffer
= (BootxDriverInfo
*)ml_boot_ptovirt(driverInfo
->paddr
);
733 dataBuffer
->plistAddr
= (char *)ml_boot_ptovirt((vm_address_t
)dataBuffer
->plistAddr
);
734 if (dataBuffer
->moduleAddr
)
735 dataBuffer
->moduleAddr
= (void *)ml_boot_ptovirt((vm_address_t
)dataBuffer
->moduleAddr
);
737 #error unsupported architecture
740 IOLog("Error: No data buffer "
741 "for device tree entry \"%s\".\n", memory_map_name
);
747 driverPlist
= OSDynamicCast(OSDictionary
,
748 OSUnserializeXML(dataBuffer
->plistAddr
, &errorString
));
750 IOLog("Error: Couldn't read XML property list "
751 "for device tree entry \"%s\".\n", memory_map_name
);
754 IOLog("XML parse error: %s.\n",
755 errorString
->getCStringNoCopy());
763 driverName
= OSDynamicCast(OSString
,
764 driverPlist
->getObject("CFBundleIdentifier")); // do not release
766 IOLog("Error: Device tree entry \"%s\" has "
767 "no \"CFBundleIdentifier\" property.\n", memory_map_name
);
773 /* Check if kmod is already loaded and is a real loadable one (has
776 loaded_kmod
= kmod_lookupbyname_locked(driverName
->getCStringNoCopy());
777 if (loaded_kmod
&& loaded_kmod
->address
) {
778 IOLog("Skipping new extension \"%s\"; an extension named "
779 "\"%s\" is already loaded.\n",
780 driverName
->getCStringNoCopy(),
787 if (!validateExtensionDict(driverPlist
, -1)) {
788 // validateExtensionsDict() logs an error
793 driverDict
->setObject("plist", driverPlist
);
795 /* It's perfectly okay for a KEXT to have no executable.
796 * Check that moduleAddr is nonzero before attempting to
799 * NOTE: The driverCode object is created "no-copy", so
800 * it doesn't own that memory. The memory must be freed
801 * separately from the OSData object (see
802 * clearStartupExtensionsAndLoaderInfo() at the end of this file).
804 if (dataBuffer
->moduleAddr
&& dataBuffer
->moduleLength
) {
805 driverCode
= OSData::withBytesNoCopy(dataBuffer
->moduleAddr
,
806 dataBuffer
->moduleLength
);
808 IOLog("Error: Couldn't allocate data object "
809 "to hold code for device tree entry \"%s\".\n",
817 driverDict
->setObject("code", driverCode
);
824 kfree(loaded_kmod
, sizeof(kmod_info_t
));
827 // do not release bootxDriverDataObject
828 // do not release driverName
831 driverPlist
->release();
834 errorString
->release();
837 driverCode
->release();
841 driverDict
->release();
849 /*********************************************************************
850 * Used to uncompress a single file entry in an mkext archive.
852 * The OSData returned does not own its memory! You must deallocate
853 * that memory using kmem_free() before releasing the OSData().
854 *********************************************************************/
855 static bool uncompressFile(u_int8_t
*base_address
, mkext_file
* fileinfo
,
856 /* out */ OSData
** file
) {
859 kern_return_t kern_result
;
860 u_int8_t
* uncompressed_file
= 0; // kmem_free() on error
861 OSData
* uncompressedFile
= 0; // returned
862 size_t uncompressed_size
= 0;
864 size_t offset
= OSSwapBigToHostInt32(fileinfo
->offset
);
865 size_t compsize
= OSSwapBigToHostInt32(fileinfo
->compsize
);
866 size_t realsize
= OSSwapBigToHostInt32(fileinfo
->realsize
);
867 time_t modifiedsecs
= OSSwapBigToHostInt32(fileinfo
->modifiedsecs
);
871 /* If these four fields are zero there's no file, but that isn't
874 if (offset
== 0 && compsize
== 0 &&
875 realsize
== 0 && modifiedsecs
== 0) {
879 // Add 1 for '\0' to terminate XML string!
880 kern_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&uncompressed_file
,
882 if (kern_result
!= KERN_SUCCESS
) {
883 IOLog("Error: Couldn't allocate data buffer "
884 "to uncompress file.\n");
890 uncompressedFile
= OSData::withBytesNoCopy(uncompressed_file
,
892 if (!uncompressedFile
) {
893 IOLog("Error: Couldn't allocate data object "
894 "to uncompress file.\n");
901 uncompressed_size
= decompress_lzss(uncompressed_file
,
902 base_address
+ offset
,
904 if (uncompressed_size
!= realsize
) {
905 IOLog("Error: Uncompressed file is not the length "
911 uncompressed_file
[uncompressed_size
] = '\0';
913 bcopy(base_address
+ offset
, uncompressed_file
,
915 uncompressed_file
[realsize
] = '\0';
918 *file
= uncompressedFile
;
922 if (uncompressed_file
) {
923 kmem_free(kernel_map
, (vm_address_t
)uncompressed_file
,
926 if (uncompressedFile
) {
927 uncompressedFile
->release();
934 bool uncompressModule(OSData
*compData
, /* out */ OSData
** file
) {
936 MkextEntryInfo
*info
= (MkextEntryInfo
*) compData
->getBytesNoCopy();
938 return uncompressFile((u_int8_t
*) info
->base_address
,
939 info
->fileinfo
, file
);
943 /*********************************************************************
944 * Does the work of pulling extensions out of an mkext archive located
946 *********************************************************************/
947 bool extractExtensionsFromArchive(MemoryMapFileInfo
* mkext_file_info
,
948 OSDictionary
* extensions
) {
952 u_int8_t
* crc_address
= 0;
954 mkext_header
* mkext_data
= 0; // don't free
955 mkext_kext
* onekext_data
= 0; // don't free
956 mkext_file
* plist_file
= 0; // don't free
957 mkext_file
* module_file
= 0; // don't free
958 kmod_info_t
* loaded_kmod
= 0; // must free
960 OSData
* driverPlistDataObject
= 0; // must release
961 OSDictionary
* driverPlist
= 0; // must release
962 OSData
* driverCode
= 0; // must release
963 OSDictionary
* driverDict
= 0; // must release
964 OSString
* moduleName
= 0; // don't release
965 OSString
* errorString
= NULL
; // must release
967 OSData
* moduleInfo
= 0; // must release
968 MkextEntryInfo module_info
;
971 #if defined (__ppc__)
972 mkext_data
= (mkext_header
*)mkext_file_info
->paddr
;
973 #elif defined (__i386__)
974 mkext_data
= (mkext_header
*)ml_boot_ptovirt(mkext_file_info
->paddr
);
976 #error unsupported architecture
978 if (OSSwapBigToHostInt32(mkext_data
->magic
) != MKEXT_MAGIC
||
979 OSSwapBigToHostInt32(mkext_data
->signature
) != MKEXT_SIGN
) {
980 IOLog("Error: Extension archive has invalid magic or signature.\n");
986 if (OSSwapBigToHostInt32(mkext_data
->length
) != mkext_file_info
->length
) {
987 IOLog("Error: Mismatch between extension archive & "
988 "recorded length.\n");
994 crc_address
= (u_int8_t
*)&mkext_data
->version
;
995 checksum
= adler32(crc_address
,
996 (unsigned int)mkext_data
+
997 OSSwapBigToHostInt32(mkext_data
->length
) - (unsigned int)crc_address
);
999 if (OSSwapBigToHostInt32(mkext_data
->adler32
) != checksum
) {
1000 IOLog("Error: Extension archive has a bad checksum.\n");
1006 IORegistryEntry
* root
= IORegistryEntry::getRegistryRoot();
1008 OSData
* checksumObj
= OSData::withBytes((void *)&checksum
,
1010 assert(checksumObj
);
1012 root
->setProperty(kIOStartupMkextCRC
, checksumObj
);
1013 checksumObj
->release();
1016 /* If the MKEXT archive isn't fat, check that the CPU type & subtype
1017 * match that of the running kernel.
1019 if (OSSwapBigToHostInt32(mkext_data
->cputype
) != (UInt32
)CPU_TYPE_ANY
) {
1020 kern_return_t kresult
= KERN_FAILURE
;
1021 host_basic_info_data_t hostinfo
;
1022 host_info_t hostinfo_ptr
= (host_info_t
)&hostinfo
;
1023 mach_msg_type_number_t count
= sizeof(hostinfo
)/sizeof(integer_t
);
1025 kresult
= host_info((host_t
)1, HOST_BASIC_INFO
,
1026 hostinfo_ptr
, &count
);
1027 if (kresult
!= KERN_SUCCESS
) {
1028 IOLog("Error: Couldn't get current host info.\n");
1033 if ((UInt32
)hostinfo
.cpu_type
!=
1034 OSSwapBigToHostInt32(mkext_data
->cputype
)) {
1036 IOLog("Error: Extension archive doesn't contain software "
1037 "for this computer's CPU type.\n");
1042 if (!grade_binary(OSSwapBigToHostInt32(mkext_data
->cputype
),
1043 OSSwapBigToHostInt32(mkext_data
->cpusubtype
))) {
1044 IOLog("Error: Extension archive doesn't contain software "
1045 "for this computer's CPU subtype.\n");
1052 for (unsigned int i
= 0;
1053 i
< OSSwapBigToHostInt32(mkext_data
->numkexts
);
1057 kfree(loaded_kmod
, sizeof(kmod_info_t
));
1061 if (driverPlistDataObject
) {
1062 kmem_free(kernel_map
,
1063 (unsigned int)driverPlistDataObject
->getBytesNoCopy(),
1064 driverPlistDataObject
->getLength());
1066 driverPlistDataObject
->release();
1067 driverPlistDataObject
= NULL
;
1070 driverPlist
->release();
1074 driverCode
->release();
1078 driverDict
->release();
1082 errorString
->release();
1086 onekext_data
= &mkext_data
->kext
[i
];
1087 plist_file
= &onekext_data
->plist
;
1088 module_file
= &onekext_data
->module;
1090 if (!uncompressFile((u_int8_t
*)mkext_data
, plist_file
,
1091 &driverPlistDataObject
)) {
1093 IOLog("Error: couldn't uncompress plist file "
1094 "from multikext archive entry %d.\n", i
);
1099 if (!driverPlistDataObject
) {
1100 IOLog("Error: No property list present "
1101 "for multikext archive entry %d.\n", i
);
1105 driverPlist
= OSDynamicCast(OSDictionary
,
1107 (char *)driverPlistDataObject
->getBytesNoCopy(),
1110 IOLog("Error: Couldn't read XML property list "
1111 "for multikext archive entry %d.\n", i
);
1114 IOLog("XML parse error: %s.\n",
1115 errorString
->getCStringNoCopy());
1121 if (!validateExtensionDict(driverPlist
, i
)) {
1122 // validateExtensionsDict() logs an error
1128 /* Get the extension's module name. This is used to record
1131 moduleName
= OSDynamicCast(OSString
,
1132 driverPlist
->getObject("CFBundleIdentifier")); // do not release
1134 IOLog("Error: Multikext archive entry %d has "
1135 "no \"CFBundleIdentifier\" property.\n", i
);
1137 continue; // assume a kext config error & continue
1140 /* Check if kmod is already loaded and is a real loadable one (has
1143 loaded_kmod
= kmod_lookupbyname_locked(moduleName
->getCStringNoCopy());
1144 if (loaded_kmod
&& loaded_kmod
->address
) {
1145 IOLog("Skipping new extension \"%s\"; an extension named "
1146 "\"%s\" is already loaded.\n",
1147 moduleName
->getCStringNoCopy(),
1153 driverDict
= OSDictionary::withCapacity(2);
1155 IOLog("Error: Couldn't allocate dictionary "
1156 "for multikext archive entry %d.\n", i
);
1162 driverDict
->setObject("plist", driverPlist
);
1165 * Prepare an entry to hold the mkext entry info for the
1166 * compressed binary module, if there is one. If all four fields
1167 * of the module entry are zero, there isn't one.
1169 if (!(loaded_kmod
&& loaded_kmod
->address
) && (OSSwapBigToHostInt32(module_file
->offset
) ||
1170 OSSwapBigToHostInt32(module_file
->compsize
) ||
1171 OSSwapBigToHostInt32(module_file
->realsize
) ||
1172 OSSwapBigToHostInt32(module_file
->modifiedsecs
))) {
1174 moduleInfo
= OSData::withCapacity(sizeof(MkextEntryInfo
));
1176 IOLog("Error: Couldn't allocate data object "
1177 "for multikext archive entry %d.\n", i
);
1183 module_info
.base_address
= (vm_address_t
)mkext_data
;
1184 module_info
.fileinfo
= module_file
;
1186 if (!moduleInfo
->appendBytes(&module_info
, sizeof(module_info
))) {
1187 IOLog("Error: Couldn't record info "
1188 "for multikext archive entry %d.\n", i
);
1194 driverDict
->setObject("compressedCode", moduleInfo
);
1197 OSDictionary
* incumbentExt
= OSDynamicCast(OSDictionary
,
1198 extensions
->getObject(moduleName
));
1200 if (!incumbentExt
) {
1201 extensions
->setObject(moduleName
, driverDict
);
1203 OSDictionary
* mostRecentExtension
=
1204 compareExtensionVersions(incumbentExt
, driverDict
);
1206 if (mostRecentExtension
== incumbentExt
) {
1207 /* Do nothing, we've got the most recent. */
1208 } else if (mostRecentExtension
== driverDict
) {
1209 if (!extensions
->setObject(moduleName
, driverDict
)) {
1211 /* This is a fatal error, so bail.
1213 IOLog("extractExtensionsFromArchive(): Failed to add "
1215 moduleName
->getCStringNoCopy());
1220 } else /* should be NULL */ {
1222 /* This is a nonfatal error, so continue.
1224 IOLog("extractExtensionsFromArchive(): Error comparing "
1225 "versions of duplicate extensions %s.\n",
1226 moduleName
->getCStringNoCopy());
1235 if (loaded_kmod
) kfree(loaded_kmod
, sizeof(kmod_info_t
));
1236 if (driverPlistDataObject
) {
1237 kmem_free(kernel_map
,
1238 (unsigned int)driverPlistDataObject
->getBytesNoCopy(),
1239 driverPlistDataObject
->getLength());
1240 driverPlistDataObject
->release();
1242 if (driverPlist
) driverPlist
->release();
1243 if (driverCode
) driverCode
->release();
1244 if (moduleInfo
) moduleInfo
->release();
1245 if (driverDict
) driverDict
->release();
1246 if (errorString
) errorString
->release();
1251 /*********************************************************************
1253 *********************************************************************/
1254 bool readExtensions(OSDictionary
* propertyDict
,
1255 const char * memory_map_name
,
1256 OSDictionary
* extensions
) {
1259 OSData
* mkextDataObject
= 0; // don't release
1260 MemoryMapFileInfo
* mkext_file_info
= 0; // don't free
1262 mkextDataObject
= OSDynamicCast(OSData
,
1263 propertyDict
->getObject(memory_map_name
));
1264 // don't release mkextDataObject
1266 if (!mkextDataObject
) {
1267 IOLog("Error: No mkext data object "
1268 "for device tree entry \"%s\".\n",
1275 mkext_file_info
= (MemoryMapFileInfo
*)mkextDataObject
->getBytesNoCopy();
1276 if (!mkext_file_info
) {
1281 result
= extractExtensionsFromArchive(mkext_file_info
, extensions
);
1285 if (!result
&& extensions
) {
1286 extensions
->flushCollection();
1293 /*********************************************************************
1294 * Adds the personalities for an extensions dictionary to the global
1296 *********************************************************************/
1297 bool addPersonalities(OSDictionary
* extensions
) {
1299 OSCollectionIterator
* keyIterator
= NULL
; // must release
1300 OSString
* key
; // don't release
1301 OSDictionary
* driverDict
= NULL
; // don't release
1302 OSDictionary
* driverPlist
= NULL
; // don't release
1303 OSDictionary
* thisDriverPersonalities
= NULL
; // don't release
1304 OSArray
* allDriverPersonalities
= NULL
; // must release
1306 allDriverPersonalities
= OSArray::withCapacity(1);
1307 if (!allDriverPersonalities
) {
1308 IOLog("Error: Couldn't allocate personality dictionary.\n");
1314 /* Record all personalities found so that they can be
1315 * added to the catalogue.
1316 * Note: Not all extensions have personalities.
1319 keyIterator
= OSCollectionIterator::withCollection(extensions
);
1321 IOLog("Error: Couldn't allocate iterator to record personalities.\n");
1327 while ( ( key
= OSDynamicCast(OSString
,
1328 keyIterator
->getNextObject() ))) {
1330 driverDict
= OSDynamicCast(OSDictionary
,
1331 extensions
->getObject(key
));
1332 driverPlist
= OSDynamicCast(OSDictionary
,
1333 driverDict
->getObject("plist"));
1334 thisDriverPersonalities
= OSDynamicCast(OSDictionary
,
1335 driverPlist
->getObject("IOKitPersonalities"));
1337 if (thisDriverPersonalities
) {
1338 OSCollectionIterator
* pIterator
;
1339 OSString
* locakKey
;
1340 pIterator
= OSCollectionIterator::withCollection(
1341 thisDriverPersonalities
);
1343 IOLog("Error: Couldn't allocate iterator "
1344 "to record extension personalities.\n");
1348 while ( (locakKey
= OSDynamicCast(OSString
,
1349 pIterator
->getNextObject())) ) {
1351 OSDictionary
* personality
= OSDynamicCast(
1353 thisDriverPersonalities
->getObject(locakKey
));
1355 allDriverPersonalities
->setObject(personality
);
1358 pIterator
->release();
1360 } /* extract personalities */
1363 /* Add all personalities found to the IOCatalogue,
1364 * but don't start matching.
1366 gIOCatalogue
->addDrivers(allDriverPersonalities
, false);
1370 if (allDriverPersonalities
) allDriverPersonalities
->release();
1371 if (keyIterator
) keyIterator
->release();
1377 /*********************************************************************
1378 * Called from IOCatalogue to add extensions from an mkext archive.
1379 * This function makes a copy of the mkext object passed in because
1380 * the device tree support code dumps it after calling us (indirectly
1381 * through the IOCatalogue).
1382 *********************************************************************/
1383 bool addExtensionsFromArchive(OSData
* mkextDataObject
) {
1386 OSDictionary
* startupExtensions
= NULL
; // don't release
1387 OSArray
* bootLoaderObjects
= NULL
; // don't release
1388 OSDictionary
* extensions
= NULL
; // must release
1389 MemoryMapFileInfo mkext_file_info
;
1390 OSCollectionIterator
* keyIterator
= NULL
; // must release
1391 OSString
* key
= NULL
; // don't release
1393 startupExtensions
= getStartupExtensions();
1394 if (!startupExtensions
) {
1395 IOLog("Can't record extension archive; there is no"
1396 " extensions dictionary.\n");
1402 bootLoaderObjects
= getBootLoaderObjects();
1403 if (! bootLoaderObjects
) {
1404 IOLog("Error: Couldn't allocate array to hold temporary objects.\n");
1410 extensions
= OSDictionary::withCapacity(2);
1412 IOLog("Error: Couldn't allocate dictionary to unpack "
1413 "extension archive.\n");
1419 mkext_file_info
.paddr
= (UInt32
)mkextDataObject
->getBytesNoCopy();
1420 mkext_file_info
.length
= mkextDataObject
->getLength();
1422 /* Save the local mkext data object so that we can deallocate it later.
1424 bootLoaderObjects
->setObject(mkextDataObject
);
1426 result
= extractExtensionsFromArchive(&mkext_file_info
, extensions
);
1428 IOLog("Error: Failed to extract extensions from archive.\n");
1434 result
= mergeExtensionDictionaries(startupExtensions
, extensions
);
1436 IOLog("Error: Failed to merge new extensions into existing set.\n");
1441 result
= addPersonalities(extensions
);
1443 IOLog("Error: Failed to add personalities for extensions extracted "
1453 IOLog("Error: Failed to record extensions from archive.\n");
1456 keyIterator
= OSCollectionIterator::withCollection(
1460 while ( (key
= OSDynamicCast(OSString
,
1461 keyIterator
->getNextObject())) ) {
1463 IOLog("Added extension \"%s\" from archive.\n",
1464 key
->getCStringNoCopy());
1467 keyIterator
->release();
1471 if (extensions
) extensions
->release();
1477 /*********************************************************************
1478 * This function builds dictionaries for the startup extensions
1479 * put into memory by bootx, recording each in the startup extensions
1480 * dictionary. The dictionary format is this:
1483 * "plist" = (the extension's Info.plist as an OSDictionary)
1484 * "code" = (an OSData containing the executable file)
1487 * This function returns true if any extensions were found and
1488 * recorded successfully, or if there are no start extensions,
1489 * and false if an unrecoverable error occurred. An error reading
1490 * a single extension is not considered fatal, and this function
1491 * will simply skip the problematic extension to try the next one.
1492 *********************************************************************/
1494 bool recordStartupExtensions(void) {
1496 OSDictionary
* startupExtensions
= NULL
; // must release
1497 OSDictionary
* existingExtensions
= NULL
; // don't release
1498 OSDictionary
* mkextExtensions
= NULL
; // must release
1499 IORegistryEntry
* bootxMemoryMap
= NULL
; // must release
1500 OSDictionary
* propertyDict
= NULL
; // must release
1501 OSCollectionIterator
* keyIterator
= NULL
; // must release
1502 OSString
* key
= NULL
; // don't release
1504 OSDictionary
* newDriverDict
= NULL
; // must release
1505 OSDictionary
* driverPlist
= NULL
; // don't release
1507 struct section
* infosect
;
1508 struct section
* symsect
;
1509 unsigned int prelinkedCount
= 0;
1511 existingExtensions
= getStartupExtensions();
1512 if (!existingExtensions
) {
1513 IOLog("Error: There is no dictionary for startup extensions.\n");
1519 startupExtensions
= OSDictionary::withCapacity(1);
1520 if (!startupExtensions
) {
1521 IOLog("Error: Couldn't allocate dictionary "
1522 "to record startup extensions.\n");
1529 // add any prelinked modules as startup extensions
1531 infosect
= getsectbyname("__PRELINK", "__info");
1532 symsect
= getsectbyname("__PRELINK", "__symtab");
1533 if (infosect
&& infosect
->addr
&& infosect
->size
1534 && symsect
&& symsect
->addr
&& symsect
->size
) do
1536 gIOPrelinkedModules
= OSDynamicCast(OSArray
,
1537 OSUnserializeXML((const char *) infosect
->addr
, NULL
));
1539 if (!gIOPrelinkedModules
)
1541 for( unsigned int idx
= 0;
1542 (propertyDict
= OSDynamicCast(OSDictionary
, gIOPrelinkedModules
->getObject(idx
)));
1545 enum { kPrelinkReservedCount
= 4 };
1547 /* Get the extension's module name. This is used to record
1548 * the extension. Do *not* release the moduleName.
1550 OSString
* moduleName
= OSDynamicCast(OSString
,
1551 propertyDict
->getObject("CFBundleIdentifier"));
1553 IOLog("Error: Prelinked module entry has "
1554 "no \"CFBundleIdentifier\" property.\n");
1559 /* Add the kext, & its plist.
1561 newDriverDict
= OSDictionary::withCapacity(4);
1562 assert(newDriverDict
);
1563 newDriverDict
->setObject("plist", propertyDict
);
1564 startupExtensions
->setObject(moduleName
, newDriverDict
);
1565 newDriverDict
->release();
1567 /* Add the code if present.
1569 OSData
* data
= OSDynamicCast(OSData
, propertyDict
->getObject("OSBundlePrelink"));
1571 if (data
->getLength() < (kPrelinkReservedCount
* sizeof(UInt32
))) {
1572 IOLog("Error: Prelinked module entry has "
1573 "invalid \"OSBundlePrelink\" property.\n");
1578 prelink
= (UInt32
*) data
->getBytesNoCopy();
1579 kmod_info_t
* kmod_info
= (kmod_info_t
*) OSReadBigInt32(prelink
, 0);
1580 // end of "file" is end of symbol sect
1581 data
= OSData::withBytesNoCopy((void *) kmod_info
->address
,
1582 symsect
->addr
+ symsect
->size
- kmod_info
->address
);
1583 newDriverDict
->setObject("code", data
);
1588 /* Add the symbols if present.
1590 OSNumber
* num
= OSDynamicCast(OSNumber
, propertyDict
->getObject("OSBundlePrelinkSymbols"));
1592 UInt32 offset
= num
->unsigned32BitValue();
1593 data
= OSData::withBytesNoCopy((void *) (symsect
->addr
+ offset
), symsect
->size
- offset
);
1594 newDriverDict
->setObject("code", data
);
1600 if (gIOPrelinkedModules
)
1601 IOLog("%d prelinked modules\n", prelinkedCount
);
1605 virt
= ml_static_ptovirt(infosect
->addr
);
1607 ml_static_mfree(virt
, infosect
->size
);
1609 newDriverDict
= NULL
;
1615 IORegistryEntry::fromPath(
1616 "/chosen/memory-map", // path
1619 // return value is retained so be sure to release it
1621 if (!bootxMemoryMap
) {
1622 IOLog("Error: Couldn't read booter memory map.\n");
1628 propertyDict
= bootxMemoryMap
->dictionaryWithProperties();
1629 if (!propertyDict
) {
1630 IOLog("Error: Couldn't get property dictionary "
1631 "from memory map.\n");
1637 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
1639 IOLog("Error: Couldn't allocate iterator for driver images.\n");
1645 while ( (key
= OSDynamicCast(OSString
,
1646 keyIterator
->getNextObject())) ) {
1647 /* Clear newDriverDict & mkextExtensions upon entry to the loop,
1648 * handling both successful and unsuccessful iterations.
1650 if (newDriverDict
) {
1651 newDriverDict
->release();
1652 newDriverDict
= NULL
;
1654 if (mkextExtensions
) {
1655 mkextExtensions
->release();
1656 mkextExtensions
= NULL
;
1659 const char * keyValue
= key
->getCStringNoCopy();
1661 if ( !strncmp(keyValue
, BOOTX_KEXT_PREFIX
,
1662 strlen(BOOTX_KEXT_PREFIX
)) ) {
1664 /* Read the extension from the bootx-supplied memory.
1666 newDriverDict
= readExtension(propertyDict
, keyValue
);
1667 if (!newDriverDict
) {
1668 IOLog("Error: Couldn't read data "
1669 "for device tree entry \"%s\".\n", keyValue
);
1675 /* Preprare to record the extension by getting its info plist.
1677 driverPlist
= OSDynamicCast(OSDictionary
,
1678 newDriverDict
->getObject("plist"));
1680 IOLog("Error: Extension in device tree entry \"%s\" "
1681 "has no property list.\n", keyValue
);
1687 /* Get the extension's module name. This is used to record
1688 * the extension. Do *not* release the moduleName.
1690 OSString
* moduleName
= OSDynamicCast(OSString
,
1691 driverPlist
->getObject("CFBundleIdentifier"));
1693 IOLog("Error: Device tree entry \"%s\" has "
1694 "no \"CFBundleIdentifier\" property.\n", keyValue
);
1700 /* All has gone well so far, so record the extension under
1701 * its module name, checking for an existing duplicate.
1703 * Do not release moduleName, as it's part of the extension's
1706 OSDictionary
* incumbentExt
= OSDynamicCast(OSDictionary
,
1707 startupExtensions
->getObject(moduleName
));
1709 if (!incumbentExt
) {
1710 startupExtensions
->setObject(moduleName
, newDriverDict
);
1712 OSDictionary
* mostRecentExtension
=
1713 compareExtensionVersions(incumbentExt
, newDriverDict
);
1715 if (mostRecentExtension
== incumbentExt
) {
1716 /* Do nothing, we've got the most recent. */
1717 } else if (mostRecentExtension
== newDriverDict
) {
1718 if (!startupExtensions
->setObject(moduleName
,
1721 /* This is a fatal error, so bail.
1723 IOLog("recordStartupExtensions(): Failed to add "
1725 moduleName
->getCStringNoCopy());
1730 } else /* should be NULL */ {
1732 /* This is a nonfatal error, so continue.
1734 IOLog("recordStartupExtensions(): Error comparing "
1735 "versions of duplicate extensions %s.\n",
1736 moduleName
->getCStringNoCopy());
1743 } else if ( !strncmp(keyValue
, BOOTX_MULTIKEXT_PREFIX
,
1744 strlen(BOOTX_MULTIKEXT_PREFIX
)) ) {
1746 mkextExtensions
= OSDictionary::withCapacity(10);
1747 if (!mkextExtensions
) {
1748 IOLog("Error: Couldn't allocate dictionary to unpack "
1749 "multi-extension archive.\n");
1752 goto finish
; // allocation failure is fatal for this routine
1754 if (!readExtensions(propertyDict
, keyValue
, mkextExtensions
)) {
1755 IOLog("Error: Couldn't unpack multi-extension archive.\n");
1759 if (!mergeExtensionDictionaries(startupExtensions
,
1762 IOLog("Error: Failed to merge new extensions into "
1766 goto finish
; // merge error is fatal for this routine
1771 // Do not release key.
1773 } /* while ( (key = OSDynamicCast(OSString, ...) ) ) */
1775 if (!mergeExtensionDictionaries(existingExtensions
, startupExtensions
)) {
1776 IOLog("Error: Failed to merge new extensions into existing set.\n");
1782 result
= addPersonalities(startupExtensions
);
1784 IOLog("Error: Failed to add personalities for extensions extracted "
1793 // reused so clear first!
1795 keyIterator
->release();
1800 IOLog("Error: Failed to record startup extensions.\n");
1804 keyIterator
= OSCollectionIterator::withCollection(
1808 while ( (key
= OSDynamicCast(OSString
,
1809 keyIterator
->getNextObject())) ) {
1811 IOLog("Found extension \"%s\".\n",
1812 key
->getCStringNoCopy());
1815 keyIterator
->release();
1821 if (newDriverDict
) newDriverDict
->release();
1822 if (propertyDict
) propertyDict
->release();
1823 if (bootxMemoryMap
) bootxMemoryMap
->release();
1824 if (mkextExtensions
) mkextExtensions
->release();
1825 if (startupExtensions
) startupExtensions
->release();
1831 /*********************************************************************
1832 * This function removes an entry from the dictionary of startup
1833 * extensions. It's used when an extension can't be loaded, for
1834 * whatever reason. For drivers, this allows another matching driver
1835 * to be loaded, so that, for example, a driver for the root device
1837 *********************************************************************/
1838 void removeStartupExtension(const char * extensionName
) {
1839 OSDictionary
* startupExtensions
= NULL
; // don't release
1840 OSDictionary
* extensionDict
= NULL
; // don't release
1841 OSDictionary
* extensionPlist
= NULL
; // don't release
1842 OSDictionary
* extensionPersonalities
= NULL
; // don't release
1843 OSDictionary
* personality
= NULL
; // don't release
1844 OSCollectionIterator
* keyIterator
= NULL
; // must release
1845 OSString
* key
= NULL
; // don't release
1847 startupExtensions
= getStartupExtensions();
1848 if (!startupExtensions
) goto finish
;
1851 /* Find the extension's entry in the dictionary of
1852 * startup extensions.
1854 extensionDict
= OSDynamicCast(OSDictionary
,
1855 startupExtensions
->getObject(extensionName
));
1856 if (!extensionDict
) goto finish
;
1858 extensionPlist
= OSDynamicCast(OSDictionary
,
1859 extensionDict
->getObject("plist"));
1860 if (!extensionPlist
) goto finish
;
1862 extensionPersonalities
= OSDynamicCast(OSDictionary
,
1863 extensionPlist
->getObject("IOKitPersonalities"));
1864 if (!extensionPersonalities
) goto finish
;
1866 /* If it was there, remove it from the catalogue proper
1867 * by calling removeDrivers(). Pass true for the second
1868 * argument to trigger a new round of matching, and
1869 * then remove the extension from the dictionary of startup
1872 keyIterator
= OSCollectionIterator::withCollection(
1873 extensionPersonalities
);
1875 IOLog("Error: Couldn't allocate iterator to scan"
1876 " personalities for %s.\n", extensionName
);
1880 while ((key
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
1881 personality
= OSDynamicCast(OSDictionary
,
1882 extensionPersonalities
->getObject(key
));
1886 gIOCatalogue
->removeDrivers(personality
, true);
1890 startupExtensions
->removeObject(extensionName
);
1894 if (keyIterator
) keyIterator
->release();
1898 /*********************************************************************
1899 * FIXME: This function invalidates the globals gStartupExtensions and
1900 * FIXME: ...gBootLoaderObjects without setting them to NULL. Since
1901 * FIXME: ...the code itself is immediately unloaded, there may not be
1902 * FIXME: ...any reason to worry about that!
1903 *********************************************************************/
1904 void clearStartupExtensionsAndLoaderInfo(void)
1906 OSDictionary
* startupExtensions
= NULL
; // must release
1907 OSArray
* bootLoaderObjects
= NULL
; // must release
1909 IORegistryEntry
* bootxMemoryMap
= NULL
; // must release
1910 OSDictionary
* propertyDict
= NULL
; // must release
1911 OSCollectionIterator
* keyIterator
= NULL
; // must release
1912 OSString
* key
= NULL
; // don't release
1915 * Drop any temporarily held data objects.
1917 bootLoaderObjects
= getBootLoaderObjects();
1918 if (bootLoaderObjects
) {
1919 bootLoaderObjects
->release();
1923 * If any "code" entries in driver dictionaries are accompanied
1924 * by "compressedCode" entries, then those data objects were
1925 * created based of of kmem_alloc()'ed memory, which must be
1928 startupExtensions
= getStartupExtensions();
1929 if (startupExtensions
) {
1931 OSCollectionIterator::withCollection(startupExtensions
);
1933 IOLog("Error: Couldn't allocate iterator for startup "
1936 goto memory_map
; // bail to the memory_map label
1939 while ( (key
= OSDynamicCast(OSString
,
1940 keyIterator
->getNextObject())) ) {
1942 OSDictionary
* driverDict
= 0;
1943 OSData
* codeData
= 0;
1945 driverDict
= OSDynamicCast(OSDictionary
,
1946 startupExtensions
->getObject(key
));
1948 codeData
= OSDynamicCast(OSData
,
1949 driverDict
->getObject("code"));
1952 driverDict
->getObject("compressedCode")) {
1954 kmem_free(kernel_map
,
1955 (unsigned int)codeData
->getBytesNoCopy(),
1956 codeData
->getLength());
1961 keyIterator
->release();
1962 startupExtensions
->release();
1968 * Go through the device tree's memory map and remove any driver
1972 IORegistryEntry::fromPath(
1973 "/chosen/memory-map", // path
1976 // return value is retained so be sure to release it
1978 if (!bootxMemoryMap
) {
1979 IOLog("Error: Couldn't read booter memory map.\n");
1984 propertyDict
= bootxMemoryMap
->dictionaryWithProperties();
1985 if (!propertyDict
) {
1986 IOLog("Error: Couldn't get property dictionary "
1987 "from memory map.\n");
1992 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
1994 IOLog("Error: Couldn't allocate iterator for driver images.\n");
1999 while ( (key
= OSDynamicCast(OSString
,
2000 keyIterator
->getNextObject())) ) {
2002 const char * keyValue
= key
->getCStringNoCopy();
2004 if ( !strncmp(keyValue
, BOOTX_KEXT_PREFIX
,
2005 strlen(BOOTX_KEXT_PREFIX
)) ||
2006 !strncmp(keyValue
, BOOTX_MULTIKEXT_PREFIX
,
2007 strlen(BOOTX_MULTIKEXT_PREFIX
)) ) {
2009 OSData
* bootxDriverDataObject
= NULL
;
2010 MemoryMapFileInfo
* driverInfo
= 0;
2012 bootxDriverDataObject
= OSDynamicCast(OSData
,
2013 propertyDict
->getObject(keyValue
));
2014 // don't release bootxDriverDataObject
2016 if (!bootxDriverDataObject
) {
2019 driverInfo
= (MemoryMapFileInfo
*)
2020 bootxDriverDataObject
->getBytesNoCopy(0,
2021 sizeof(MemoryMapFileInfo
));
2022 IODTFreeLoaderInfo((char *)keyValue
,
2023 (void *)driverInfo
->paddr
,
2024 (int)driverInfo
->length
);
2029 if (bootxMemoryMap
) bootxMemoryMap
->release();
2030 if (propertyDict
) propertyDict
->release();
2031 if (keyIterator
) keyIterator
->release();