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",
172 *caller_owns_code
= true;
173 *code
= (unsigned char *)driverCode
->getBytesNoCopy();
175 *code_size
= driverCode
->getLength();
177 driverCode
->release();
189 /*********************************************************************
191 *********************************************************************/
193 bool verifyCompatibility(OSString
* extName
, OSString
* requiredVersion
)
195 OSDictionary
* extPlist
; // don't release
196 OSString
* extVersion
; // don't release
197 OSString
* extCompatVersion
; // don't release
198 VERS_version ext_version
;
199 VERS_version ext_compat_version
;
200 VERS_version required_version
;
202 if (!getKext(extName
->getCStringNoCopy(), &extPlist
, NULL
, NULL
, NULL
)) {
206 extVersion
= OSDynamicCast(OSString
,
207 extPlist
->getObject("CFBundleVersion"));
209 IOLog("verifyCompatibility(): "
210 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
211 extName
->getCStringNoCopy());
215 extCompatVersion
= OSDynamicCast(OSString
,
216 extPlist
->getObject("OSBundleCompatibleVersion"));
217 if (!extCompatVersion
) {
218 IOLog("verifyCompatibility(): "
219 "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
220 extName
->getCStringNoCopy());
224 required_version
= VERS_parse_string(requiredVersion
->getCStringNoCopy());
225 if (required_version
< 0) {
226 IOLog("verifyCompatibility(): "
227 "Can't parse required version \"%s\" of dependency %s.\n",
228 requiredVersion
->getCStringNoCopy(),
229 extName
->getCStringNoCopy());
232 ext_version
= VERS_parse_string(extVersion
->getCStringNoCopy());
233 if (ext_version
< 0) {
234 IOLog("verifyCompatibility(): "
235 "Can't parse version \"%s\" of dependency %s.\n",
236 extVersion
->getCStringNoCopy(),
237 extName
->getCStringNoCopy());
240 ext_compat_version
= VERS_parse_string(extCompatVersion
->getCStringNoCopy());
241 if (ext_compat_version
< 0) {
242 IOLog("verifyCompatibility(): "
243 "Can't parse compatible version \"%s\" of dependency %s.\n",
244 extCompatVersion
->getCStringNoCopy(),
245 extName
->getCStringNoCopy());
249 if (required_version
> ext_version
|| required_version
< ext_compat_version
) {
256 /*********************************************************************
257 *********************************************************************/
259 bool kextIsDependency(const char * kext_name
, char * is_kernel
) {
261 OSDictionary
* extensionsDict
= 0; // don't release
262 OSDictionary
* extDict
= 0; // don't release
263 OSDictionary
* extPlist
= 0; // don't release
264 OSBoolean
* isKernelResourceObj
= 0; // don't release
265 OSData
* driverCode
= 0; // don't release
266 OSData
* compressedCode
= 0; // don't release
272 /* Get the dictionary of startup extensions.
273 * This is keyed by module name.
275 extensionsDict
= getStartupExtensions();
276 if (!extensionsDict
) {
277 IOLog("startup extensions dictionary is missing\n");
282 /* Get the requested extension's dictionary entry and its property
283 * list, containing module dependencies.
285 extDict
= OSDynamicCast(OSDictionary
,
286 extensionsDict
->getObject(kext_name
));
289 IOLog("extension \"%s\" cannot be found\n",
295 extPlist
= OSDynamicCast(OSDictionary
, extDict
->getObject("plist"));
297 IOLog("extension \"%s\" has no info dictionary\n",
303 /* A kext that is a kernel component is still a dependency, as there
304 * are fake kmod entries for them.
306 isKernelResourceObj
= OSDynamicCast(OSBoolean
,
307 extPlist
->getObject("OSKernelResource"));
308 if (isKernelResourceObj
&& isKernelResourceObj
->isTrue()) {
314 driverCode
= OSDynamicCast(OSData
, extDict
->getObject("code"));
315 compressedCode
= OSDynamicCast(OSData
,
316 extDict
->getObject("compressedCode"));
318 if ((driverCode
|| compressedCode
) && is_kernel
&& *is_kernel
) {
322 if (!driverCode
&& !compressedCode
&& !isKernelResourceObj
) {
332 /*********************************************************************
333 *********************************************************************/
335 addDependenciesForKext(OSDictionary
* kextPlist
,
336 OSArray
* dependencyList
,
337 OSString
* trueParent
,
338 Boolean skipKernelDependencies
)
341 bool hasDirectKernelDependency
= false;
342 OSString
* kextName
= 0; // don't release
343 OSDictionary
* libraries
= 0; // don't release
344 OSCollectionIterator
* keyIterator
= 0; // must release
345 OSString
* libraryName
= 0; // don't release
346 OSString
* dependentName
= 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 dependentName
= trueParent
? trueParent
: kextName
;
372 while ( (libraryName
= OSDynamicCast(OSString
,
373 keyIterator
->getNextObject())) ) {
375 OSString
* libraryVersion
= OSDynamicCast(OSString
,
376 libraries
->getObject(libraryName
));
377 if (!libraryVersion
) {
378 // XXX: Add log message
382 if (!verifyCompatibility(libraryName
, libraryVersion
)) {
386 char is_kernel_component
;
388 if (!kextIsDependency(libraryName
->getCStringNoCopy(),
389 &is_kernel_component
)) {
391 is_kernel_component
= false;
394 if (!skipKernelDependencies
|| !is_kernel_component
) {
395 dependencyList
->setObject(dependentName
);
396 dependencyList
->setObject(libraryName
);
398 if (!hasDirectKernelDependency
&& is_kernel_component
) {
399 hasDirectKernelDependency
= true;
403 if (!hasDirectKernelDependency
) {
404 const OSSymbol
* kernelName
= 0;
406 /* a kext without any kernel dependency is assumed dependent on 6.0 */
407 dependencyList
->setObject(dependentName
);
409 kernelName
= OSSymbol::withCString("com.apple.kernel.libkern");
411 // XXX: Add log message
415 dependencyList
->setObject(kernelName
);
416 kernelName
->release();
418 IOLog("Extension \"%s\" has no kernel dependency.\n",
419 kextName
->getCStringNoCopy());
423 if (keyIterator
) keyIterator
->release();
427 /*********************************************************************
428 *********************************************************************/
430 bool getVersionForKext(OSDictionary
* kextPlist
, char ** version
)
432 OSString
* kextName
= 0; // don't release
433 OSString
* kextVersion
; // don't release
435 kextName
= OSDynamicCast(OSString
,
436 kextPlist
->getObject("CFBundleIdentifier"));
438 // XXX: Add log message
442 kextVersion
= OSDynamicCast(OSString
,
443 kextPlist
->getObject("CFBundleVersion"));
445 IOLog("getVersionForKext(): "
446 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
447 kextName
->getCStringNoCopy());
452 *version
= (char *)kextVersion
->getCStringNoCopy();
458 /*********************************************************************
459 *********************************************************************/
461 bool add_dependencies_for_kmod(const char * kmod_name
, dgraph_t
* dgraph
)
464 OSDictionary
* kextPlist
= 0; // don't release
465 unsigned int index
= 0;
466 OSArray
* dependencyList
= 0; // must release
467 unsigned char * code
= 0;
468 unsigned long code_length
= 0;
469 bool code_is_kmem
= false;
470 char * kmod_vers
= 0; // from plist, don't free
471 char is_kernel_component
= false;
472 dgraph_entry_t
* dgraph_entry
= 0; // don't free
473 dgraph_entry_t
* dgraph_dependency
= 0; // don't free
474 bool kext_is_dependency
= true;
477 * Set up the root kmod.
479 if (!getKext(kmod_name
, &kextPlist
, &code
, &code_length
,
481 IOLog("can't find extension %s\n", kmod_name
);
486 if (!kextIsDependency(kmod_name
, &is_kernel_component
)) {
487 IOLog("extension %s is not loadable\n", kmod_name
);
492 if (!getVersionForKext(kextPlist
, &kmod_vers
)) {
493 IOLog("can't get version for extension %s\n", kmod_name
);
498 dgraph_entry
= dgraph_add_dependent(dgraph
, kmod_name
,
499 code
, code_length
, code_is_kmem
,
500 kmod_name
, kmod_vers
,
501 0 /* load_address not yet known */, is_kernel_component
);
503 IOLog("can't record %s in dependency graph\n", kmod_name
);
505 // kmem_alloc()ed code is freed in finish: block.
509 // pass ownership of code to kld patcher
511 if (kload_map_entry(dgraph_entry
) != kload_error_none
) {
512 IOLog("can't map %s in preparation for loading\n", kmod_name
);
514 // kmem_alloc()ed code is freed in finish: block.
518 // clear local record of code
521 code_is_kmem
= false;
524 * Now handle all the dependencies.
526 dependencyList
= OSArray::withCapacity(5);
527 if (!dependencyList
) {
528 IOLog("memory allocation failure\n");
534 if (!addDependenciesForKext(kextPlist
, dependencyList
, NULL
, false)) {
535 IOLog("can't determine immediate dependencies for extension %s\n",
541 /* IMPORTANT: loop condition gets list count every time through, as the
542 * array CAN change each iteration.
544 for (index
= 0; index
< dependencyList
->getCount(); index
+= 2) {
545 OSString
* dependentName
= 0;
546 OSString
* libraryName
= 0;
547 const char * dependent_name
= 0;
548 const char * library_name
= 0;
550 /* 255 is an arbitrary limit. Multiplied by 2 because the dependency
551 * list is stocked with pairs (dependent -> dependency).
553 if (index
> (2 * 255)) {
554 IOLog("extension dependency graph ridiculously long, indicating a loop\n");
559 dependentName
= OSDynamicCast(OSString
,
560 dependencyList
->getObject(index
));
561 libraryName
= OSDynamicCast(OSString
,
562 dependencyList
->getObject(index
+ 1));
564 if (!dependentName
|| !libraryName
) {
565 IOLog("malformed dependency list\n");
570 dependent_name
= dependentName
->getCStringNoCopy();
571 library_name
= libraryName
->getCStringNoCopy();
573 if (!getKext(library_name
, &kextPlist
, NULL
, NULL
, NULL
)) {
575 IOLog("can't find extension %s\n", library_name
);
580 OSString
* string
= OSDynamicCast(OSString
,
581 kextPlist
->getObject("OSBundleSharedExecutableIdentifier"));
583 library_name
= string
->getCStringNoCopy();
584 if (!getKext(library_name
, &kextPlist
, NULL
, NULL
, NULL
)) {
585 IOLog("can't find extension %s\n", library_name
);
591 kext_is_dependency
= kextIsDependency(library_name
,
592 &is_kernel_component
);
594 if (kext_is_dependency
) {
595 dgraph_entry
= dgraph_find_dependent(dgraph
, dependent_name
);
597 IOLog("internal error with dependency graph\n");
603 if (!getVersionForKext(kextPlist
, &kmod_vers
)) {
604 IOLog("can't get version for extension %s\n", library_name
);
609 /* It's okay for code to be zero, as for a pseudokext
610 * representing a kernel component.
612 if (!getKext(library_name
, NULL
/* already got it */,
613 &code
, &code_length
, &code_is_kmem
)) {
614 IOLog("can't find extension %s\n", library_name
);
619 dgraph_dependency
= dgraph_add_dependency(dgraph
, dgraph_entry
,
620 library_name
, code
, code_length
, code_is_kmem
,
621 library_name
, kmod_vers
,
622 0 /* load_address not yet known */, is_kernel_component
);
624 if (!dgraph_dependency
) {
625 IOLog("can't record dependency %s -> %s\n", dependent_name
,
628 // kmem_alloc()ed code is freed in finish: block.
632 // pass ownership of code to kld patcher
634 if (kload_map_entry(dgraph_dependency
) != kload_error_none
) {
635 IOLog("can't map %s in preparation for loading\n", library_name
);
637 // kmem_alloc()ed code is freed in finish: block.
641 // clear local record of code
644 code_is_kmem
= false;
647 /* Now put the library's dependencies onto the pending set.
649 if (!addDependenciesForKext(kextPlist
, dependencyList
,
650 kext_is_dependency
? NULL
: dependentName
, !kext_is_dependency
)) {
652 IOLog("can't determine immediate dependencies for extension %s\n",
660 if (code
&& code_is_kmem
) {
661 kmem_free(kernel_map
, (unsigned int)code
, code_length
);
663 if (dependencyList
) dependencyList
->release();
668 /*********************************************************************
669 * This is the function that IOCatalogue calls in order to load a kmod.
670 * It first checks whether the kmod is already loaded. If the kmod
671 * isn't loaded, this function builds a dependency list and calls
672 * load_kmod() repeatedly to guarantee that each dependency is in fact
674 *********************************************************************/
676 kern_return_t
load_kernel_extension(char * kmod_name
)
678 kern_return_t result
= KERN_SUCCESS
;
679 kload_error load_result
= kload_error_none
;
681 bool free_dgraph
= false;
682 kmod_info_t
* kmod_info
;
684 // Put this in for lots of messages about kext loading.
686 kload_set_log_level(kload_log_level_load_details
);
689 /* See if the kmod is already loaded.
691 if ((kmod_info
= kmod_lookupbyname_locked(kmod_name
))) {
692 kfree(kmod_info
, sizeof(kmod_info_t
));
696 if (dgraph_init(&dgraph
) != dgraph_valid
) {
697 IOLog("Can't initialize dependency graph to load %s.\n",
699 result
= KERN_FAILURE
;
704 if (!add_dependencies_for_kmod(kmod_name
, &dgraph
)) {
705 IOLog("Can't determine dependencies for %s.\n",
707 result
= KERN_FAILURE
;
711 dgraph
.root
= dgraph_find_root(&dgraph
);
714 IOLog("Dependency graph to load %s has no root.\n",
716 result
= KERN_FAILURE
;
720 /* A kernel component is built in and need not be loaded.
722 if (dgraph
.root
->is_kernel_component
) {
723 result
= KERN_SUCCESS
;
727 dgraph_establish_load_order(&dgraph
);
729 load_result
= kload_load_dgraph(&dgraph
);
730 if (load_result
!= kload_error_none
&&
731 load_result
!= kload_error_already_loaded
) {
733 IOLog(VTYELLOW
"Failed to load extension %s.\n" VTRESET
, kmod_name
);
735 result
= KERN_FAILURE
;
742 dgraph_free(&dgraph
, 0 /* don't free dgraph itself */);