2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 #include <libkern/c++/OSContainers.h>
24 #include <IOKit/IOCatalogue.h>
25 #include <IOKit/IOLib.h>
26 #include <libsa/kext.h>
27 #include <libsa/catalogue.h>
30 #include <mach-o/kld.h>
31 #include <libsa/vers_rsrc.h>
32 #include <libsa/stdlib.h>
33 #include <mach/kmod.h>
34 #include <vm/vm_kern.h>
35 #include <mach/kern_return.h>
36 #include <mach-o/fat.h>
37 #include <mach_loader.h>
39 #include "kld_patch.h"
52 kmod_destroy_internal(kmod_t id
);
59 mach_msg_type_number_t
*dataCount
);
61 extern kern_return_t
kmod_retain(kmod_t id
);
62 extern kern_return_t
kmod_release(kmod_t id
);
64 extern void flush_dcache(vm_offset_t addr
, unsigned cnt
, int phys
);
65 extern void invalidate_icache(vm_offset_t addr
, unsigned cnt
, int phys
);
70 #define LOG_DELAY(x) IODelay((x) * 1000000)
71 #define VTYELLOW "\033[33m"
72 #define VTRESET "\033[0m"
79 /*********************************************************************
81 *********************************************************************/
84 const char * bundleid
,
85 OSDictionary
** plist
,
86 unsigned char ** code
,
87 unsigned long * code_size
,
88 bool * caller_owns_code
)
91 OSDictionary
* extensionsDict
; // don't release
92 OSDictionary
* extDict
; // don't release
93 OSDictionary
* extPlist
; // don't release
94 unsigned long code_size_local
;
96 /* Get the dictionary of startup extensions.
97 * This is keyed by module name.
99 extensionsDict
= getStartupExtensions();
100 if (!extensionsDict
) {
101 IOLog("startup extensions dictionary is missing\n");
106 /* Get the requested extension's dictionary entry and its property
107 * list, containing module dependencies.
109 extDict
= OSDynamicCast(OSDictionary
,
110 extensionsDict
->getObject(bundleid
));
113 IOLog("extension \"%s\" cannot be found\n",
120 extPlist
= OSDynamicCast(OSDictionary
, extDict
->getObject("plist"));
122 IOLog("extension \"%s\" has no info dictionary\n",
132 /* If asking for code, the caller must provide a return buffer
135 if (!caller_owns_code
) {
136 IOLog("getKext(): invalid usage (caller_owns_code not provided)\n");
145 *caller_owns_code
= false;
147 *code
= (unsigned char *)kld_file_getaddr(bundleid
,
148 (long *)&code_size_local
);
151 *code_size
= code_size_local
;
154 OSData
* driverCode
= 0; // release only if uncompressing!
156 driverCode
= OSDynamicCast(OSData
, extDict
->getObject("code"));
158 *code
= (unsigned char *)driverCode
->getBytesNoCopy();
160 *code_size
= driverCode
->getLength();
162 } else { // Look for compressed code and uncompress it
163 OSData
* compressedCode
= 0;
164 compressedCode
= OSDynamicCast(OSData
,
165 extDict
->getObject("compressedCode"));
166 if (compressedCode
) {
167 if (!uncompressModule(compressedCode
, &driverCode
)) {
168 IOLog("extension \"%s\": couldn't uncompress code\n",
174 *caller_owns_code
= true;
175 *code
= (unsigned char *)driverCode
->getBytesNoCopy();
177 *code_size
= driverCode
->getLength();
179 driverCode
->release();
191 /*********************************************************************
193 *********************************************************************/
195 bool verifyCompatibility(OSString
* extName
, OSString
* requiredVersion
)
197 OSDictionary
* extPlist
; // don't release
198 OSString
* extVersion
; // don't release
199 OSString
* extCompatVersion
; // don't release
200 VERS_version ext_version
;
201 VERS_version ext_compat_version
;
202 VERS_version required_version
;
204 if (!getKext(extName
->getCStringNoCopy(), &extPlist
, NULL
, NULL
, NULL
)) {
208 extVersion
= OSDynamicCast(OSString
,
209 extPlist
->getObject("CFBundleVersion"));
211 IOLog("verifyCompatibility(): "
212 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
213 extName
->getCStringNoCopy());
217 extCompatVersion
= OSDynamicCast(OSString
,
218 extPlist
->getObject("OSBundleCompatibleVersion"));
219 if (!extCompatVersion
) {
220 IOLog("verifyCompatibility(): "
221 "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
222 extName
->getCStringNoCopy());
226 required_version
= VERS_parse_string(requiredVersion
->getCStringNoCopy());
227 if (required_version
< 0) {
228 IOLog("verifyCompatibility(): "
229 "Can't parse required version \"%s\" of dependency %s.\n",
230 requiredVersion
->getCStringNoCopy(),
231 extName
->getCStringNoCopy());
234 ext_version
= VERS_parse_string(extVersion
->getCStringNoCopy());
235 if (ext_version
< 0) {
236 IOLog("verifyCompatibility(): "
237 "Can't parse version \"%s\" of dependency %s.\n",
238 extVersion
->getCStringNoCopy(),
239 extName
->getCStringNoCopy());
242 ext_compat_version
= VERS_parse_string(extCompatVersion
->getCStringNoCopy());
243 if (ext_compat_version
< 0) {
244 IOLog("verifyCompatibility(): "
245 "Can't parse compatible version \"%s\" of dependency %s.\n",
246 extCompatVersion
->getCStringNoCopy(),
247 extName
->getCStringNoCopy());
251 if (required_version
> ext_version
|| required_version
< ext_compat_version
) {
258 /*********************************************************************
259 *********************************************************************/
261 bool kextIsDependency(const char * kext_name
, char * is_kernel
) {
263 OSDictionary
* extensionsDict
= 0; // don't release
264 OSDictionary
* extDict
= 0; // don't release
265 OSDictionary
* extPlist
= 0; // don't release
266 OSBoolean
* isKernelResourceObj
= 0; // don't release
267 OSData
* driverCode
= 0; // don't release
268 OSData
* compressedCode
= 0; // don't release
274 /* Get the dictionary of startup extensions.
275 * This is keyed by module name.
277 extensionsDict
= getStartupExtensions();
278 if (!extensionsDict
) {
279 IOLog("startup extensions dictionary is missing\n");
284 /* Get the requested extension's dictionary entry and its property
285 * list, containing module dependencies.
287 extDict
= OSDynamicCast(OSDictionary
,
288 extensionsDict
->getObject(kext_name
));
291 IOLog("extension \"%s\" cannot be found\n",
297 extPlist
= OSDynamicCast(OSDictionary
, extDict
->getObject("plist"));
299 IOLog("extension \"%s\" has no info dictionary\n",
305 /* A kext that is a kernel component is still a dependency, as there
306 * are fake kmod entries for them.
308 isKernelResourceObj
= OSDynamicCast(OSBoolean
,
309 extPlist
->getObject("OSKernelResource"));
310 if (isKernelResourceObj
&& isKernelResourceObj
->isTrue()) {
316 driverCode
= OSDynamicCast(OSData
, extDict
->getObject("code"));
317 compressedCode
= OSDynamicCast(OSData
,
318 extDict
->getObject("compressedCode"));
320 if ((driverCode
|| compressedCode
) && is_kernel
&& *is_kernel
) {
324 if (!driverCode
&& !compressedCode
&& !isKernelResourceObj
) {
334 /*********************************************************************
335 *********************************************************************/
337 figureDependenciesForKext(OSDictionary
* kextPlist
,
338 OSDictionary
* dependencies
,
339 OSString
* trueParent
,
340 Boolean skipKernelDependencies
)
343 bool hasDirectKernelDependency
= false;
344 OSString
* kextName
= 0; // don't release
345 OSDictionary
* libraries
= 0; // don't release
346 OSCollectionIterator
* keyIterator
= 0; // must release
347 OSString
* libraryName
= 0; // don't release
349 kextName
= OSDynamicCast(OSString
,
350 kextPlist
->getObject("CFBundleIdentifier"));
352 // XXX: Add log message
357 libraries
= OSDynamicCast(OSDictionary
,
358 kextPlist
->getObject("OSBundleLibraries"));
364 keyIterator
= OSCollectionIterator::withCollection(libraries
);
366 // XXX: Add log message
371 while ( (libraryName
= OSDynamicCast(OSString
,
372 keyIterator
->getNextObject())) ) {
374 OSString
* libraryVersion
= OSDynamicCast(OSString
,
375 libraries
->getObject(libraryName
));
376 if (!libraryVersion
) {
377 // XXX: Add log message
381 if (!verifyCompatibility(libraryName
, libraryVersion
)) {
385 char is_kernel_component
;
387 if (!kextIsDependency(libraryName
->getCStringNoCopy(), &is_kernel_component
))
388 is_kernel_component
= false;
390 if (!skipKernelDependencies
|| !is_kernel_component
) {
391 dependencies
->setObject(libraryName
,
392 trueParent
? trueParent
: kextName
);
394 if (!hasDirectKernelDependency
&& is_kernel_component
) {
395 hasDirectKernelDependency
= true;
399 if (!hasDirectKernelDependency
) {
400 /* a kext without any kernel dependency is assumed dependent on 6.0 */
401 dependencies
->setObject("com.apple.kernel.libkern",
402 trueParent
? trueParent
: kextName
);
403 IOLog("Extension \"%s\" has no kernel dependency.\n",
404 kextName
->getCStringNoCopy());
408 if (keyIterator
) keyIterator
->release();
412 /*********************************************************************
413 *********************************************************************/
415 bool getVersionForKext(OSDictionary
* kextPlist
, char ** version
)
417 OSString
* kextName
= 0; // don't release
418 OSString
* kextVersion
; // don't release
420 kextName
= OSDynamicCast(OSString
,
421 kextPlist
->getObject("CFBundleIdentifier"));
423 // XXX: Add log message
427 kextVersion
= OSDynamicCast(OSString
,
428 kextPlist
->getObject("CFBundleVersion"));
430 IOLog("getVersionForKext(): "
431 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
432 kextName
->getCStringNoCopy());
437 *version
= (char *)kextVersion
->getCStringNoCopy();
443 /*********************************************************************
444 *********************************************************************/
446 bool add_dependencies_for_kmod(const char * kmod_name
, dgraph_t
* dgraph
)
449 OSDictionary
* kextPlist
= 0; // don't release
450 OSDictionary
* workingDependencies
= 0; // must release
451 OSDictionary
* pendingDependencies
= 0; // must release
452 OSDictionary
* swapDict
= 0; // don't release
453 OSString
* dependentName
= 0; // don't release
454 const char * dependent_name
= 0; // don't free
455 OSString
* libraryName
= 0; // don't release
456 const char * library_name
= 0; // don't free
457 OSCollectionIterator
* dependencyIterator
= 0; // must release
458 unsigned char * code
= 0;
459 unsigned long code_length
= 0;
460 bool code_is_kmem
= false;
461 char * kmod_vers
= 0; // from plist, don't free
462 char is_kernel_component
= false;
463 dgraph_entry_t
* dgraph_entry
= 0; // don't free
464 dgraph_entry_t
* dgraph_dependency
= 0; // don't free
465 unsigned int graph_depth
= 0;
466 bool kext_is_dependency
= true;
468 if (!getKext(kmod_name
, &kextPlist
, &code
, &code_length
,
470 IOLog("can't find extension %s\n", kmod_name
);
475 if (!kextIsDependency(kmod_name
, &is_kernel_component
)) {
476 IOLog("extension %s is not loadable\n", kmod_name
);
481 if (!getVersionForKext(kextPlist
, &kmod_vers
)) {
482 IOLog("can't get version for extension %s\n", kmod_name
);
487 dgraph_entry
= dgraph_add_dependent(dgraph
, kmod_name
,
488 code
, code_length
, code_is_kmem
,
489 kmod_name
, kmod_vers
,
490 0 /* load_address not yet known */, is_kernel_component
);
492 IOLog("can't record %s in dependency graph\n", kmod_name
);
494 // kmem_alloc()ed code is freed in finish: block.
498 // pass ownership of code to kld patcher
501 if (kload_map_entry(dgraph_entry
) != kload_error_none
) {
502 IOLog("can't map %s in preparation for loading\n", kmod_name
);
504 // kmem_alloc()ed code is freed in finish: block.
508 // clear local record of code
511 code_is_kmem
= false;
513 workingDependencies
= OSDictionary::withCapacity(5);
514 if (!workingDependencies
) {
515 IOLog("memory allocation failure\n");
520 pendingDependencies
= OSDictionary::withCapacity(5);
521 if (!pendingDependencies
) {
522 IOLog("memory allocation failure\n");
527 if (!figureDependenciesForKext(kextPlist
, workingDependencies
, NULL
, false)) {
528 IOLog("can't determine immediate dependencies for extension %s\n",
535 while (workingDependencies
->getCount()) {
536 if (graph_depth
> 255) {
537 IOLog("extension dependency graph ridiculously long, indicating a loop\n");
542 if (dependencyIterator
) {
543 dependencyIterator
->release();
544 dependencyIterator
= 0;
547 dependencyIterator
= OSCollectionIterator::withCollection(
548 workingDependencies
);
549 if (!dependencyIterator
) {
550 IOLog("memory allocation failure\n");
555 while ( (libraryName
=
556 OSDynamicCast(OSString
, dependencyIterator
->getNextObject())) ) {
558 library_name
= libraryName
->getCStringNoCopy();
560 dependentName
= OSDynamicCast(OSString
,
561 workingDependencies
->getObject(libraryName
));
563 dependent_name
= dependentName
->getCStringNoCopy();
565 if (!getKext(library_name
, &kextPlist
, NULL
, NULL
, NULL
)) {
566 IOLog("can't find extension %s\n", library_name
);
572 if ((string
= OSDynamicCast(OSString
,
573 kextPlist
->getObject("OSBundleSharedExecutableIdentifier"))))
575 library_name
= string
->getCStringNoCopy();
576 if (!getKext(library_name
, &kextPlist
, NULL
, NULL
, NULL
)) {
577 IOLog("can't find extension %s\n", library_name
);
583 kext_is_dependency
= kextIsDependency(library_name
,
584 &is_kernel_component
);
586 if (!kext_is_dependency
) {
588 /* For binaryless kexts, add a new pending dependency from the
589 * original dependent onto the dependencies of the current,
590 * binaryless, dependency.
592 if (!figureDependenciesForKext(kextPlist
, pendingDependencies
,
593 dependentName
, true)) {
595 IOLog("can't determine immediate dependencies for extension %s\n",
602 dgraph_entry
= dgraph_find_dependent(dgraph
, dependent_name
);
604 IOLog("internal error with dependency graph\n");
610 if (!getVersionForKext(kextPlist
, &kmod_vers
)) {
611 IOLog("can't get version for extension %s\n", library_name
);
616 /* It's okay for code to be zero, as for a pseudokext
617 * representing a kernel component.
619 if (!getKext(library_name
, NULL
/* already got it */,
620 &code
, &code_length
, &code_is_kmem
)) {
621 IOLog("can't find extension %s\n", library_name
);
626 dgraph_dependency
= dgraph_add_dependency(dgraph
, dgraph_entry
,
627 library_name
, code
, code_length
, code_is_kmem
,
628 library_name
, kmod_vers
,
629 0 /* load_address not yet known */, is_kernel_component
);
631 if (!dgraph_dependency
) {
632 IOLog("can't record dependency %s -> %s\n", dependent_name
,
635 // kmem_alloc()ed code is freed in finish: block.
639 // pass ownership of code to kld patcher
641 if (kload_map_entry(dgraph_dependency
) != kload_error_none
) {
642 IOLog("can't map %s in preparation for loading\n", library_name
);
644 // kmem_alloc()ed code is freed in finish: block.
648 // clear local record of code
651 code_is_kmem
= false;
654 /* Now put the library's dependencies onto the pending set.
656 if (!figureDependenciesForKext(kextPlist
, pendingDependencies
,
659 IOLog("can't determine immediate dependencies for extension %s\n",
666 dependencyIterator
->release();
667 dependencyIterator
= 0;
669 workingDependencies
->flushCollection();
670 swapDict
= workingDependencies
;
671 workingDependencies
= pendingDependencies
;
672 pendingDependencies
= swapDict
;
677 if (code
&& code_is_kmem
) {
678 kmem_free(kernel_map
, (unsigned int)code
, code_length
);
680 if (workingDependencies
) workingDependencies
->release();
681 if (pendingDependencies
) pendingDependencies
->release();
682 if (dependencyIterator
) dependencyIterator
->release();
686 /*********************************************************************
687 * This is the function that IOCatalogue calls in order to load a kmod.
688 * It first checks whether the kmod is already loaded. If the kmod
689 * isn't loaded, this function builds a dependency list and calls
690 * load_kmod() repeatedly to guarantee that each dependency is in fact
692 *********************************************************************/
694 kern_return_t
load_kernel_extension(char * kmod_name
)
696 kern_return_t result
= KERN_SUCCESS
;
697 kload_error load_result
= kload_error_none
;
699 bool free_dgraph
= false;
700 kmod_info_t
* kmod_info
;
702 // Put this in for lots of messages about kext loading.
704 kload_set_log_level(kload_log_level_load_details
);
707 /* See if the kmod is already loaded.
709 if ((kmod_info
= kmod_lookupbyname_locked(kmod_name
))) {
710 kfree((vm_offset_t
) kmod_info
, sizeof(kmod_info_t
));
714 if (dgraph_init(&dgraph
) != dgraph_valid
) {
715 IOLog("Can't initialize dependency graph to load %s.\n",
717 result
= KERN_FAILURE
;
722 if (!add_dependencies_for_kmod(kmod_name
, &dgraph
)) {
723 IOLog("Can't determine dependencies for %s.\n",
725 result
= KERN_FAILURE
;
729 dgraph
.root
= dgraph_find_root(&dgraph
);
732 IOLog("Dependency graph to load %s has no root.\n",
734 result
= KERN_FAILURE
;
738 /* A kernel component is built in and need not be loaded.
740 if (dgraph
.root
->is_kernel_component
) {
741 result
= KERN_SUCCESS
;
745 dgraph_establish_load_order(&dgraph
);
747 load_result
= kload_load_dgraph(&dgraph
);
748 if (load_result
!= kload_error_none
&&
749 load_result
!= kload_error_already_loaded
) {
751 IOLog(VTYELLOW
"Failed to load extension %s.\n" VTRESET
, kmod_name
);
753 result
= KERN_FAILURE
;
760 dgraph_free(&dgraph
, 0 /* don't free dgraph itself */);