2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 #include <libkern/c++/OSContainers.h>
23 #include <IOKit/IOCatalogue.h>
24 #include <IOKit/IOLib.h>
25 #include <libsa/kext.h>
26 #include <libsa/catalogue.h>
29 #include <mach-o/kld.h>
30 #include <libsa/vers_rsrc.h>
31 #include <libsa/stdlib.h>
32 #include <mach/kmod.h>
33 #include <vm/vm_kern.h>
34 #include <mach/kern_return.h>
35 #include <mach-o/fat.h>
36 #include <mach_loader.h>
38 #include "kld_patch.h"
51 kmod_destroy_internal(kmod_t id
);
58 mach_msg_type_number_t
*dataCount
);
60 extern kern_return_t
kmod_retain(kmod_t id
);
61 extern kern_return_t
kmod_release(kmod_t id
);
63 extern void flush_dcache(vm_offset_t addr
, unsigned cnt
, int phys
);
64 extern void invalidate_icache(vm_offset_t addr
, unsigned cnt
, int phys
);
69 #define LOG_DELAY(x) IODelay((x) * 1000000)
70 #define VTYELLOW "\033[33m"
71 #define VTRESET "\033[0m"
78 /*********************************************************************
80 *********************************************************************/
83 const char * bundleid
,
84 OSDictionary
** plist
,
85 unsigned char ** code
,
86 unsigned long * code_size
,
87 bool * caller_owns_code
)
90 OSDictionary
* extensionsDict
; // don't release
91 OSDictionary
* extDict
; // don't release
92 OSDictionary
* extPlist
; // don't release
93 unsigned long code_size_local
;
95 /* Get the dictionary of startup extensions.
96 * This is keyed by module name.
98 extensionsDict
= getStartupExtensions();
99 if (!extensionsDict
) {
100 IOLog("startup extensions dictionary is missing\n");
105 /* Get the requested extension's dictionary entry and its property
106 * list, containing module dependencies.
108 extDict
= OSDynamicCast(OSDictionary
,
109 extensionsDict
->getObject(bundleid
));
112 IOLog("extension \"%s\" cannot be found\n",
119 extPlist
= OSDynamicCast(OSDictionary
, extDict
->getObject("plist"));
121 IOLog("extension \"%s\" has no info dictionary\n",
131 /* If asking for code, the caller must provide a return buffer
134 if (!caller_owns_code
) {
135 IOLog("getKext(): invalid usage (caller_owns_code not provided)\n");
144 *caller_owns_code
= false;
146 *code
= (unsigned char *)kld_file_getaddr(bundleid
,
147 (long *)&code_size_local
);
150 *code_size
= code_size_local
;
153 OSData
* driverCode
= 0; // release only if uncompressing!
155 driverCode
= OSDynamicCast(OSData
, extDict
->getObject("code"));
157 *code
= (unsigned char *)driverCode
->getBytesNoCopy();
159 *code_size
= driverCode
->getLength();
161 } else { // Look for compressed code and uncompress it
162 OSData
* compressedCode
= 0;
163 compressedCode
= OSDynamicCast(OSData
,
164 extDict
->getObject("compressedCode"));
165 if (compressedCode
) {
166 if (!uncompressModule(compressedCode
, &driverCode
)) {
167 IOLog("extension \"%s\": couldn't uncompress code\n",
173 *caller_owns_code
= true;
174 *code
= (unsigned char *)driverCode
->getBytesNoCopy();
176 *code_size
= driverCode
->getLength();
178 driverCode
->release();
190 /*********************************************************************
192 *********************************************************************/
194 bool verifyCompatibility(OSString
* extName
, OSString
* requiredVersion
)
196 OSDictionary
* extPlist
; // don't release
197 OSString
* extVersion
; // don't release
198 OSString
* extCompatVersion
; // don't release
199 VERS_version ext_version
;
200 VERS_version ext_compat_version
;
201 VERS_version required_version
;
203 if (!getKext(extName
->getCStringNoCopy(), &extPlist
, NULL
, NULL
, NULL
)) {
207 extVersion
= OSDynamicCast(OSString
,
208 extPlist
->getObject("CFBundleVersion"));
210 IOLog("verifyCompatibility(): "
211 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
212 extName
->getCStringNoCopy());
216 extCompatVersion
= OSDynamicCast(OSString
,
217 extPlist
->getObject("OSBundleCompatibleVersion"));
218 if (!extCompatVersion
) {
219 IOLog("verifyCompatibility(): "
220 "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
221 extName
->getCStringNoCopy());
225 required_version
= VERS_parse_string(requiredVersion
->getCStringNoCopy());
226 if (required_version
< 0) {
227 IOLog("verifyCompatibility(): "
228 "Can't parse required version \"%s\" of dependency %s.\n",
229 requiredVersion
->getCStringNoCopy(),
230 extName
->getCStringNoCopy());
233 ext_version
= VERS_parse_string(extVersion
->getCStringNoCopy());
234 if (ext_version
< 0) {
235 IOLog("verifyCompatibility(): "
236 "Can't parse version \"%s\" of dependency %s.\n",
237 extVersion
->getCStringNoCopy(),
238 extName
->getCStringNoCopy());
241 ext_compat_version
= VERS_parse_string(extCompatVersion
->getCStringNoCopy());
242 if (ext_compat_version
< 0) {
243 IOLog("verifyCompatibility(): "
244 "Can't parse compatible version \"%s\" of dependency %s.\n",
245 extCompatVersion
->getCStringNoCopy(),
246 extName
->getCStringNoCopy());
250 if (required_version
> ext_version
|| required_version
< ext_compat_version
) {
257 /*********************************************************************
258 *********************************************************************/
260 bool kextIsDependency(const char * kext_name
, char * is_kernel
) {
262 OSDictionary
* extensionsDict
= 0; // don't release
263 OSDictionary
* extDict
= 0; // don't release
264 OSDictionary
* extPlist
= 0; // don't release
265 OSBoolean
* isKernelResourceObj
= 0; // don't release
266 OSData
* driverCode
= 0; // don't release
267 OSData
* compressedCode
= 0; // don't release
273 /* Get the dictionary of startup extensions.
274 * This is keyed by module name.
276 extensionsDict
= getStartupExtensions();
277 if (!extensionsDict
) {
278 IOLog("startup extensions dictionary is missing\n");
283 /* Get the requested extension's dictionary entry and its property
284 * list, containing module dependencies.
286 extDict
= OSDynamicCast(OSDictionary
,
287 extensionsDict
->getObject(kext_name
));
290 IOLog("extension \"%s\" cannot be found\n",
296 extPlist
= OSDynamicCast(OSDictionary
, extDict
->getObject("plist"));
298 IOLog("extension \"%s\" has no info dictionary\n",
304 /* A kext that is a kernel component is still a dependency, as there
305 * are fake kmod entries for them.
307 isKernelResourceObj
= OSDynamicCast(OSBoolean
,
308 extPlist
->getObject("OSKernelResource"));
309 if (isKernelResourceObj
&& isKernelResourceObj
->isTrue()) {
315 driverCode
= OSDynamicCast(OSData
, extDict
->getObject("code"));
316 compressedCode
= OSDynamicCast(OSData
,
317 extDict
->getObject("compressedCode"));
319 if ((driverCode
|| compressedCode
) && is_kernel
&& *is_kernel
) {
323 if (!driverCode
&& !compressedCode
&& !isKernelResourceObj
) {
333 /*********************************************************************
334 *********************************************************************/
336 figureDependenciesForKext(OSDictionary
* kextPlist
,
337 OSDictionary
* dependencies
,
338 OSString
* trueParent
,
339 Boolean skipKernelDependencies
)
342 bool hasDirectKernelDependency
= false;
343 OSString
* kextName
= 0; // don't release
344 OSDictionary
* libraries
= 0; // don't release
345 OSCollectionIterator
* keyIterator
= 0; // must release
346 OSString
* libraryName
= 0; // don't release
348 kextName
= OSDynamicCast(OSString
,
349 kextPlist
->getObject("CFBundleIdentifier"));
351 // XXX: Add log message
356 libraries
= OSDynamicCast(OSDictionary
,
357 kextPlist
->getObject("OSBundleLibraries"));
363 keyIterator
= OSCollectionIterator::withCollection(libraries
);
365 // XXX: Add log message
370 while ( (libraryName
= OSDynamicCast(OSString
,
371 keyIterator
->getNextObject())) ) {
373 OSString
* libraryVersion
= OSDynamicCast(OSString
,
374 libraries
->getObject(libraryName
));
375 if (!libraryVersion
) {
376 // XXX: Add log message
380 if (!verifyCompatibility(libraryName
, libraryVersion
)) {
384 char is_kernel_component
;
386 if (!kextIsDependency(libraryName
->getCStringNoCopy(), &is_kernel_component
))
387 is_kernel_component
= false;
389 if (!skipKernelDependencies
|| !is_kernel_component
) {
390 dependencies
->setObject(libraryName
,
391 trueParent
? trueParent
: kextName
);
393 if (!hasDirectKernelDependency
&& is_kernel_component
) {
394 hasDirectKernelDependency
= true;
398 if (!hasDirectKernelDependency
) {
399 /* a kext without any kernel dependency is assumed dependent on 6.0 */
400 dependencies
->setObject("com.apple.kernel.libkern",
401 trueParent
? trueParent
: kextName
);
402 IOLog("Extension \"%s\" has no kernel dependency.\n",
403 kextName
->getCStringNoCopy());
407 if (keyIterator
) keyIterator
->release();
411 /*********************************************************************
412 *********************************************************************/
414 bool getVersionForKext(OSDictionary
* kextPlist
, char ** version
)
416 OSString
* kextName
= 0; // don't release
417 OSString
* kextVersion
; // don't release
419 kextName
= OSDynamicCast(OSString
,
420 kextPlist
->getObject("CFBundleIdentifier"));
422 // XXX: Add log message
426 kextVersion
= OSDynamicCast(OSString
,
427 kextPlist
->getObject("CFBundleVersion"));
429 IOLog("getVersionForKext(): "
430 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
431 kextName
->getCStringNoCopy());
436 *version
= (char *)kextVersion
->getCStringNoCopy();
442 /*********************************************************************
443 *********************************************************************/
445 bool add_dependencies_for_kmod(const char * kmod_name
, dgraph_t
* dgraph
)
448 OSDictionary
* kextPlist
= 0; // don't release
449 OSDictionary
* workingDependencies
= 0; // must release
450 OSDictionary
* pendingDependencies
= 0; // must release
451 OSDictionary
* swapDict
= 0; // don't release
452 OSString
* dependentName
= 0; // don't release
453 const char * dependent_name
= 0; // don't free
454 OSString
* libraryName
= 0; // don't release
455 const char * library_name
= 0; // don't free
456 OSCollectionIterator
* dependencyIterator
= 0; // must release
457 unsigned char * code
= 0;
458 unsigned long code_length
= 0;
459 bool code_is_kmem
= false;
460 char * kmod_vers
= 0; // from plist, don't free
461 char is_kernel_component
= false;
462 dgraph_entry_t
* dgraph_entry
= 0; // don't free
463 dgraph_entry_t
* dgraph_dependency
= 0; // don't free
464 unsigned int graph_depth
= 0;
465 bool kext_is_dependency
= true;
467 if (!getKext(kmod_name
, &kextPlist
, &code
, &code_length
,
469 IOLog("can't find extension %s\n", kmod_name
);
474 if (!kextIsDependency(kmod_name
, &is_kernel_component
)) {
475 IOLog("extension %s is not loadable\n", kmod_name
);
480 if (!getVersionForKext(kextPlist
, &kmod_vers
)) {
481 IOLog("can't get version for extension %s\n", kmod_name
);
486 dgraph_entry
= dgraph_add_dependent(dgraph
, kmod_name
,
487 code
, code_length
, code_is_kmem
,
488 kmod_name
, kmod_vers
,
489 0 /* load_address not yet known */, is_kernel_component
);
491 IOLog("can't record %s in dependency graph\n", kmod_name
);
493 // kmem_alloc()ed code is freed in finish: block.
497 // pass ownership of code to kld patcher
500 if (kload_map_entry(dgraph_entry
) != kload_error_none
) {
501 IOLog("can't map %s in preparation for loading\n", kmod_name
);
503 // kmem_alloc()ed code is freed in finish: block.
507 // clear local record of code
510 code_is_kmem
= false;
512 workingDependencies
= OSDictionary::withCapacity(5);
513 if (!workingDependencies
) {
514 IOLog("memory allocation failure\n");
519 pendingDependencies
= OSDictionary::withCapacity(5);
520 if (!pendingDependencies
) {
521 IOLog("memory allocation failure\n");
526 if (!figureDependenciesForKext(kextPlist
, workingDependencies
, NULL
, false)) {
527 IOLog("can't determine immediate dependencies for extension %s\n",
534 while (workingDependencies
->getCount()) {
535 if (graph_depth
> 255) {
536 IOLog("extension dependency graph ridiculously long, indicating a loop\n");
541 if (dependencyIterator
) {
542 dependencyIterator
->release();
543 dependencyIterator
= 0;
546 dependencyIterator
= OSCollectionIterator::withCollection(
547 workingDependencies
);
548 if (!dependencyIterator
) {
549 IOLog("memory allocation failure\n");
554 while ( (libraryName
=
555 OSDynamicCast(OSString
, dependencyIterator
->getNextObject())) ) {
557 library_name
= libraryName
->getCStringNoCopy();
559 dependentName
= OSDynamicCast(OSString
,
560 workingDependencies
->getObject(libraryName
));
562 dependent_name
= dependentName
->getCStringNoCopy();
564 if (!getKext(library_name
, &kextPlist
, NULL
, NULL
, NULL
)) {
565 IOLog("can't find extension %s\n", library_name
);
571 if ((string
= OSDynamicCast(OSString
,
572 kextPlist
->getObject("OSBundleSharedExecutableIdentifier"))))
574 library_name
= string
->getCStringNoCopy();
575 if (!getKext(library_name
, &kextPlist
, NULL
, NULL
, NULL
)) {
576 IOLog("can't find extension %s\n", library_name
);
582 kext_is_dependency
= kextIsDependency(library_name
,
583 &is_kernel_component
);
585 if (!kext_is_dependency
) {
587 /* For binaryless kexts, add a new pending dependency from the
588 * original dependent onto the dependencies of the current,
589 * binaryless, dependency.
591 if (!figureDependenciesForKext(kextPlist
, pendingDependencies
,
592 dependentName
, true)) {
594 IOLog("can't determine immediate dependencies for extension %s\n",
601 dgraph_entry
= dgraph_find_dependent(dgraph
, dependent_name
);
603 IOLog("internal error with dependency graph\n");
609 if (!getVersionForKext(kextPlist
, &kmod_vers
)) {
610 IOLog("can't get version for extension %s\n", library_name
);
615 /* It's okay for code to be zero, as for a pseudokext
616 * representing a kernel component.
618 if (!getKext(library_name
, NULL
/* already got it */,
619 &code
, &code_length
, &code_is_kmem
)) {
620 IOLog("can't find extension %s\n", library_name
);
625 dgraph_dependency
= dgraph_add_dependency(dgraph
, dgraph_entry
,
626 library_name
, code
, code_length
, code_is_kmem
,
627 library_name
, kmod_vers
,
628 0 /* load_address not yet known */, is_kernel_component
);
630 if (!dgraph_dependency
) {
631 IOLog("can't record dependency %s -> %s\n", dependent_name
,
634 // kmem_alloc()ed code is freed in finish: block.
638 // pass ownership of code to kld patcher
640 if (kload_map_entry(dgraph_dependency
) != kload_error_none
) {
641 IOLog("can't map %s in preparation for loading\n", library_name
);
643 // kmem_alloc()ed code is freed in finish: block.
647 // clear local record of code
650 code_is_kmem
= false;
653 /* Now put the library's dependencies onto the pending set.
655 if (!figureDependenciesForKext(kextPlist
, pendingDependencies
,
658 IOLog("can't determine immediate dependencies for extension %s\n",
665 dependencyIterator
->release();
666 dependencyIterator
= 0;
668 workingDependencies
->flushCollection();
669 swapDict
= workingDependencies
;
670 workingDependencies
= pendingDependencies
;
671 pendingDependencies
= swapDict
;
676 if (code
&& code_is_kmem
) {
677 kmem_free(kernel_map
, (unsigned int)code
, code_length
);
679 if (workingDependencies
) workingDependencies
->release();
680 if (pendingDependencies
) pendingDependencies
->release();
681 if (dependencyIterator
) dependencyIterator
->release();
685 /*********************************************************************
686 * This is the function that IOCatalogue calls in order to load a kmod.
687 * It first checks whether the kmod is already loaded. If the kmod
688 * isn't loaded, this function builds a dependency list and calls
689 * load_kmod() repeatedly to guarantee that each dependency is in fact
691 *********************************************************************/
693 kern_return_t
load_kernel_extension(char * kmod_name
)
695 kern_return_t result
= KERN_SUCCESS
;
696 kload_error load_result
= kload_error_none
;
698 bool free_dgraph
= false;
699 kmod_info_t
* kmod_info
;
701 // Put this in for lots of messages about kext loading.
703 kload_set_log_level(kload_log_level_load_details
);
706 /* See if the kmod is already loaded.
708 if ((kmod_info
= kmod_lookupbyname_locked(kmod_name
))) {
709 kfree((vm_offset_t
) kmod_info
, sizeof(kmod_info_t
));
713 if (dgraph_init(&dgraph
) != dgraph_valid
) {
714 IOLog("Can't initialize dependency graph to load %s.\n",
716 result
= KERN_FAILURE
;
721 if (!add_dependencies_for_kmod(kmod_name
, &dgraph
)) {
722 IOLog("Can't determine dependencies for %s.\n",
724 result
= KERN_FAILURE
;
728 dgraph
.root
= dgraph_find_root(&dgraph
);
731 IOLog("Dependency graph to load %s has no root.\n",
733 result
= KERN_FAILURE
;
737 /* A kernel component is built in and need not be loaded.
739 if (dgraph
.root
->is_kernel_component
) {
740 result
= KERN_SUCCESS
;
744 dgraph_establish_load_order(&dgraph
);
746 load_result
= kload_load_dgraph(&dgraph
);
747 if (load_result
!= kload_error_none
&&
748 load_result
!= kload_error_already_loaded
) {
750 IOLog(VTYELLOW
"Failed to load extension %s.\n" VTRESET
, kmod_name
);
752 result
= KERN_FAILURE
;
759 dgraph_free(&dgraph
, 0 /* don't free dgraph itself */);