]> git.saurik.com Git - apple/xnu.git/blob - libsa/kmod.cpp
xnu-792.12.6.tar.gz
[apple/xnu.git] / libsa / kmod.cpp
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
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
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
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.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 #include <libsa/kmod.h>
31 #include <libkern/c++/OSContainers.h>
32 #include <IOKit/IOCatalogue.h>
33 #include <IOKit/IOLib.h>
34 #include <libsa/kmod.h>
35 #include <libsa/catalogue.h>
36
37 extern "C" {
38 #include <mach-o/kld.h>
39 #include <libsa/vers_rsrc.h>
40 #include <libsa/stdlib.h>
41 #include <mach/kmod.h>
42 #include <vm/vm_kern.h>
43 #include <mach/kern_return.h>
44 #include <mach-o/fat.h>
45 #include <mach_loader.h>
46 };
47
48 #include "kld_patch.h"
49
50
51 extern "C" {
52 extern kern_return_t
53 kmod_create_internal(
54 kmod_info_t *info,
55 kmod_t *id);
56
57 extern kern_return_t
58 kmod_destroy_internal(kmod_t id);
59
60 extern kern_return_t
61 kmod_start_or_stop(
62 kmod_t id,
63 int start,
64 kmod_args_t *data,
65 mach_msg_type_number_t *dataCount);
66
67 extern kern_return_t kmod_retain(kmod_t id);
68 extern kern_return_t kmod_release(kmod_t id);
69
70 extern void flush_dcache64(addr64_t addr, unsigned cnt, int phys);
71 extern void invalidate_icache64(addr64_t addr, unsigned cnt, int phys);
72 };
73
74
75 #define LOG_DELAY()
76
77 #define VTYELLOW "\033[33m"
78 #define VTRESET "\033[0m"
79
80
81
82
83 /*********************************************************************
84 *
85 *********************************************************************/
86 bool verifyCompatibility(OSString * extName, OSString * requiredVersion)
87 {
88 OSDictionary * extensionsDict; // don't release
89 OSDictionary * extDict; // don't release
90 OSDictionary * extPlist; // don't release
91 OSString * extVersion; // don't release
92 OSString * extCompatVersion; // don't release
93 UInt32 ext_version;
94 UInt32 ext_compat_version;
95 UInt32 required_version;
96
97 /* Get the dictionary of startup extensions.
98 * This is keyed by module name.
99 */
100 extensionsDict = getStartupExtensions();
101 if (!extensionsDict) {
102 IOLog("verifyCompatibility(): No extensions dictionary.\n");
103 return false;
104 }
105
106 /* Get the requested extension's dictionary entry and its property
107 * list, containing module dependencies.
108 */
109 extDict = OSDynamicCast(OSDictionary,
110 extensionsDict->getObject(extName));
111
112 if (!extDict) {
113 IOLog("verifyCompatibility(): "
114 "Extension \"%s\" cannot be found.\n",
115 extName->getCStringNoCopy());
116 return false;
117 }
118
119 extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
120 if (!extPlist) {
121 IOLog("verifyCompatibility(): "
122 "Extension \"%s\" has no property list.\n",
123 extName->getCStringNoCopy());
124 return false;
125 }
126
127
128 extVersion = OSDynamicCast(OSString,
129 extPlist->getObject("CFBundleVersion"));
130 if (!extVersion) {
131 IOLog("verifyCompatibility(): "
132 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
133 extName->getCStringNoCopy());
134 return false;
135 }
136
137 extCompatVersion = OSDynamicCast(OSString,
138 extPlist->getObject("OSBundleCompatibleVersion"));
139 if (!extCompatVersion) {
140 IOLog("verifyCompatibility(): "
141 "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
142 extName->getCStringNoCopy());
143 return false;
144 }
145
146 if (!VERS_parse_string(requiredVersion->getCStringNoCopy(),
147 &required_version)) {
148 IOLog("verifyCompatibility(): "
149 "Can't parse required version \"%s\" of dependency %s.\n",
150 requiredVersion->getCStringNoCopy(),
151 extName->getCStringNoCopy());
152 return false;
153 }
154 if (!VERS_parse_string(extVersion->getCStringNoCopy(),
155 &ext_version)) {
156 IOLog("verifyCompatibility(): "
157 "Can't parse version \"%s\" of dependency %s.\n",
158 extVersion->getCStringNoCopy(),
159 extName->getCStringNoCopy());
160 return false;
161 }
162 if (!VERS_parse_string(extCompatVersion->getCStringNoCopy(),
163 &ext_compat_version)) {
164 IOLog("verifyCompatibility(): "
165 "Can't parse compatible version \"%s\" of dependency %s.\n",
166 extCompatVersion->getCStringNoCopy(),
167 extName->getCStringNoCopy());
168 return false;
169 }
170
171 if (required_version > ext_version || required_version < ext_compat_version) {
172 return false;
173 }
174
175 return true;
176 }
177
178 /*********************************************************************
179 *********************************************************************/
180 static
181 Boolean kextIsADependency(OSString * name) {
182 Boolean result = true;
183 OSDictionary * extensionsDict = 0; // don't release
184 OSDictionary * extDict = 0; // don't release
185 OSDictionary * extPlist = 0; // don't release
186 OSBoolean * isKernelResourceObj = 0; // don't release
187 OSData * driverCode = 0; // don't release
188 OSData * compressedCode = 0; // don't release
189
190 extensionsDict = getStartupExtensions();
191 if (!extensionsDict) {
192 IOLog("kextIsADependency(): No extensions dictionary.\n");
193 LOG_DELAY();
194 result = false;
195 goto finish;
196 }
197
198
199 extDict = OSDynamicCast(OSDictionary,
200 extensionsDict->getObject(name));
201 if (!extDict) {
202 IOLog("kextIsADependency(): "
203 "Extension \"%s\" cannot be found.\n",
204 name->getCStringNoCopy());
205 LOG_DELAY();
206 result = false;
207 goto finish;
208 }
209
210 extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
211 if (!extPlist) {
212 IOLog("getDependencyListForKmod(): "
213 "Extension \"%s\" has no property list.\n",
214 name->getCStringNoCopy());
215 LOG_DELAY();
216 result = false;
217 goto finish;
218 }
219
220 /* A kext that is a kernel component is still a dependency, as there
221 * are fake kmod entries for them.
222 */
223 isKernelResourceObj = OSDynamicCast(OSBoolean,
224 extPlist->getObject("OSKernelResource"));
225 if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
226 result = true;
227 goto finish;
228 }
229
230 driverCode = OSDynamicCast(OSData, extDict->getObject("code"));
231 compressedCode = OSDynamicCast(OSData,
232 extDict->getObject("compressedCode"));
233
234 if (!driverCode && !compressedCode) {
235 result = false;
236 goto finish;
237 }
238
239 finish:
240
241 return result;
242 }
243
244 /*********************************************************************
245 * This function builds a uniqued, in-order list of modules that need
246 * to be loaded in order for kmod_name to be successfully loaded. This
247 * list ends with kmod_name itself.
248 *********************************************************************/
249 static
250 OSArray * getDependencyListForKmod(const char * kmod_name) {
251
252 int error = 0;
253
254 OSDictionary * extensionsDict; // don't release
255 OSDictionary * extDict; // don't release
256 OSDictionary * extPlist; // don't release
257 OSString * extName; // don't release
258 OSArray * dependencyList = NULL; // return value, caller releases
259 unsigned int i;
260
261 /* These are used to remove duplicates from the dependency list.
262 */
263 OSArray * originalList = NULL; // must be released
264 OSDictionary * encounteredNames = NULL; // must be release
265
266
267 /* Get the dictionary of startup extensions.
268 * This is keyed by module name.
269 */
270 extensionsDict = getStartupExtensions();
271 if (!extensionsDict) {
272 IOLog("getDependencyListForKmod(): No extensions dictionary.\n");
273 LOG_DELAY();
274 error = 1;
275 goto finish;
276 }
277
278
279 /* Get the requested extension's dictionary entry and its property
280 * list, containing module dependencies.
281 */
282 extDict = OSDynamicCast(OSDictionary,
283 extensionsDict->getObject(kmod_name));
284
285 if (!extDict) {
286 IOLog("getDependencyListForKmod(): "
287 "Extension \"%s\" cannot be found.\n",
288 kmod_name);
289 LOG_DELAY();
290 error = 1;
291 goto finish;
292 }
293
294 extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
295 if (!extPlist) {
296 IOLog("getDependencyListForKmod(): "
297 "Extension \"%s\" has no property list.\n",
298 kmod_name);
299 LOG_DELAY();
300 error = 1;
301 goto finish;
302 }
303
304
305 /* Verify that the retrieved entry's "CFBundleIdentifier" property exists.
306 * This will be added to the dependency list.
307 */
308 extName = OSDynamicCast(OSString,
309 extPlist->getObject("CFBundleIdentifier"));
310 if (!extName) {
311 IOLog("getDependencyListForKmod(): "
312 "Extension \"%s\" has no \"CFBundleIdentifier\" property.\n",
313 kmod_name);
314 LOG_DELAY();
315 error = 1;
316 goto finish;
317 }
318
319 dependencyList = OSArray::withCapacity(10);
320 if (!dependencyList) {
321 IOLog("getDependencyListForKmod(): "
322 "Couldn't allocate dependency array for extension \"%s\".\n",
323 kmod_name);
324 LOG_DELAY();
325 error = 1;
326 goto finish;
327 }
328
329
330 /* Okay, let's get started.
331 */
332 dependencyList->setObject(extName);
333
334
335 /* Here's a slightly tricky bit. This loop iterates through
336 * the dependency list until it runs off the end. Each time
337 * through, however, any number of dependencies can be added
338 * to the end of the list. Eventually some extensions won't
339 * have any more dependencies, no more names will be added
340 * to the list, and this loop will terminate.
341 */
342 for (i = 0; i < dependencyList->getCount(); i++) {
343
344 // None of these needs to be released, as they're all from plists.
345 OSString * curName;
346 OSDictionary * curExtDict;
347 OSDictionary * curExtDepDict;
348 OSDictionary * curExtPlist;
349 OSString * curDepName;
350
351
352 /* An arbitrary limit to prevent infinite loops.
353 */
354 if (i > 255) {
355 IOLog("getDependencyListForKmod(): "
356 "max dependency list length exceeded for "
357 "extension \"%s\".\n",
358 kmod_name);
359 LOG_DELAY();
360 error = 1;
361 goto finish;
362 }
363
364 curName = OSDynamicCast(OSString, dependencyList->getObject(i));
365
366 curExtDict = OSDynamicCast(OSDictionary,
367 extensionsDict->getObject(curName));
368 if (!curExtDict) {
369 IOLog("getDependencyListForKmod(): "
370 "Extension \"%s\", required for extension \"%s\", "
371 "is not available.\n",
372 curName->getCStringNoCopy(), kmod_name);
373 LOG_DELAY();
374 error = 1;
375 goto finish;
376 }
377
378 curExtPlist = OSDynamicCast(OSDictionary,
379 curExtDict->getObject("plist"));
380 if (!curExtPlist) {
381 IOLog("getDependencyListForKmod(): "
382 "Extension \"%s\", required for extension \"%s\", "
383 "has no property list.\n",
384 curName->getCStringNoCopy(), kmod_name);
385 LOG_DELAY();
386 error = 1;
387 goto finish;
388 }
389
390 curExtDepDict = OSDynamicCast(OSDictionary,
391 curExtPlist->getObject("OSBundleLibraries"));
392 if (curExtDepDict) {
393 OSCollectionIterator * keyIterator =
394 OSCollectionIterator::withCollection(curExtDepDict);
395
396 if (!keyIterator) {
397 IOLog("getDependencyListForKmod(): "
398 "Couldn't allocate iterator for extension "
399 "\"%s\".\n", kmod_name);
400 LOG_DELAY();
401 error = 1;
402 goto finish;
403 }
404 while ( (curDepName =
405 OSDynamicCast(OSString,
406 keyIterator->getNextObject())) ) {
407
408 OSString * requiredVersion = OSDynamicCast(OSString,
409 curExtDepDict->getObject(curDepName));
410
411 if (!verifyCompatibility(curDepName, requiredVersion)) {
412 IOLog("getDependencyListForKmod(): "
413 "Dependency %s of %s is not compatible or is unavailable.\n",
414 curDepName->getCStringNoCopy(),
415 curName->getCStringNoCopy());
416 LOG_DELAY();
417 error = 1;
418 goto finish;
419 }
420
421 dependencyList->setObject(curDepName);
422 }
423
424 keyIterator->release();
425 }
426 }
427
428
429 /*****
430 * The dependency list now exists in the reverse order of required loads,
431 * and may have duplicates. Now we turn the list around and remove
432 * duplicates.
433 */
434 originalList = dependencyList;
435 dependencyList = OSArray::withCapacity(originalList->getCount());
436 if (!dependencyList) {
437 IOLog("getDependenciesForKmod(): "
438 "Couldn't allocate reversal dependency list for extension "
439 "\"%s\".\n", kmod_name);
440 LOG_DELAY();
441 error = 1;
442 goto finish;
443 }
444 encounteredNames = OSDictionary::withCapacity(originalList->getCount());
445 if (!encounteredNames) {
446 IOLog("getDependenciesForKmod(): "
447 "Couldn't allocate list of encountered names for extension "
448 "\"%s\".\n", kmod_name);
449 LOG_DELAY();
450 error = 1;
451 goto finish;
452 }
453
454
455 /* Go backward through the original list, using the encounteredNames
456 * dictionary to check for duplicates. We put originalList in as the
457 * value because we need some non-NULL value. Here we also drop any
458 * extensions that aren't proper dependencies (that is, any that are
459 * nonkernel kexts without code).
460 */
461 i = originalList->getCount();
462
463 if (i > 0) {
464 do {
465 i--;
466
467 OSString * item = OSDynamicCast(OSString,
468 originalList->getObject(i));
469
470 if ( (!encounteredNames->getObject(item)) &&
471 kextIsADependency(item)) {
472
473 encounteredNames->setObject(item, originalList);
474 dependencyList->setObject(item);
475 }
476 } while (i > 0);
477 }
478
479
480 finish:
481
482 if (originalList) {
483 originalList->release();
484 }
485 if (encounteredNames) {
486 encounteredNames->release();
487 }
488 if (error) {
489 if (dependencyList) {
490 dependencyList->release();
491 dependencyList = NULL;
492 }
493 }
494
495 return dependencyList;
496 }
497
498
499 /*********************************************************************
500 *********************************************************************/
501 /* Used in address_for_loaded_kmod.
502 */
503 static kmod_info_t * g_current_kmod_info = NULL;
504 static const char * g_current_kmod_name = NULL;
505
506 /* Globals to pass link buffer info from
507 * address_for_loaded_kmod() and alloc_for_kmod()
508 * to load_kmod().
509 *
510 * link_load_address is the address used to lay
511 * down the linked code. It gets adjusted by the
512 * pad between the headers size and a full page
513 * multiple. If an error occurs this gets set to
514 * zero so that the kld client code can detect
515 * an address or allocation error even if kld
516 * returns success.
517 *
518 * link_load_size is the size of the image as
519 * created by kld_load_from_memory(). link_buffer_size
520 * is the size of the buffer allocated for the final
521 * laid-down image, and is adjusted by rounding the
522 * load size and header size up to full-page multiples.
523 *
524 * link_buffer_address is set only by alloc_for_kmod();
525 * its value is used as a check if kld_load_from_memory()
526 * fails so that the buffer can be deallocated.
527 */
528 static unsigned long link_load_address = 0;
529 static unsigned long link_load_size = 0;
530 static unsigned long link_buffer_size = 0;
531 static unsigned long link_header_size = 0;
532 static unsigned long link_buffer_address = 0;
533
534
535 /*********************************************************************
536 * This function is registered before kmod_load_from_memory() is
537 * invoked to build symbol table entries for an already-loaded
538 * kmod. This function just checks the g_current_kmod_info variable
539 * to gets its load address, and futzes it by the header offset (pad).
540 * See lower comments for more info on load address futzing.
541 *********************************************************************/
542 static
543 unsigned long address_for_loaded_kmod(
544 unsigned long size,
545 unsigned long headers_size) {
546
547 unsigned long round_headers_size;
548 unsigned long headers_pad;
549
550 if (!g_current_kmod_info) {
551 IOLog("address_for_loaded_kmod(): No current kmod.\n");
552 LOG_DELAY();
553 link_load_address = 0; // error sentinel for kld client
554 return 0;
555 }
556
557 round_headers_size = round_page_32(headers_size);
558 headers_pad = round_headers_size - headers_size;
559
560 link_load_address = (unsigned long)g_current_kmod_info->address +
561 headers_pad;
562
563 return link_load_address;
564 }
565
566
567 /*********************************************************************
568 * This function is registered before kmod_load_from_memory() is
569 * invoked to actually load a new kmod. It rounds up the header and
570 * total sizes and vm_allocates a buffer for the kmod. Now, KLD doesn't
571 * enforce any alignment of headers or segments, and we want to make
572 * sure that the executable code of the kmod lies on a page boundary.
573 * to do so, this function figures the pad between the actual header
574 * size and the page-rounded header size, and returns that offset into
575 * the allocated buffer. After kmod_load_from_memory() returns, its
576 * caller will move the mach_header struct back to the beginning of the
577 * allocated buffer so that the kmod_info_t structure contains the
578 * correct address.
579 *********************************************************************/
580 static
581 unsigned long alloc_for_kmod(
582 unsigned long size,
583 unsigned long headers_size) {
584
585 vm_address_t buffer = 0;
586 kern_return_t k_result;
587
588 unsigned long round_headers_size;
589 unsigned long round_segments_size;
590 unsigned long round_size;
591 unsigned long headers_pad;
592
593 round_headers_size = round_page_32(headers_size);
594 round_segments_size = round_page_32(size - headers_size);
595 round_size = round_headers_size + round_segments_size;
596 headers_pad = round_headers_size - headers_size;
597
598 k_result = vm_allocate(kernel_map, (vm_offset_t *)&buffer,
599 round_size, VM_FLAGS_ANYWHERE);
600 if (k_result != KERN_SUCCESS) {
601 IOLog("alloc_for_kmod(): Can't allocate memory.\n");
602 LOG_DELAY();
603 link_buffer_address = 0; // make sure it's clear
604 link_load_address = 0; // error sentinel for kld client
605 return 0;
606 }
607
608 link_load_size = size;
609
610 link_buffer_address = buffer;
611 link_buffer_size = round_size;
612 link_header_size = headers_size; // NOT rounded!
613
614 link_load_address = link_buffer_address + headers_pad;
615
616 return link_load_address;
617 }
618
619 /*********************************************************************
620 * This function reads the startup extensions dictionary to get the
621 * address and length of the executable data for the requested kmod.
622 *********************************************************************/
623 static
624 int map_and_patch(const char * kmod_name) {
625
626 char *address;
627
628 // Does the kld system already know about this kmod?
629 address = (char *) kld_file_getaddr(kmod_name, NULL);
630 if (address)
631 return 1;
632
633 // None of these needs to be released.
634 OSDictionary * extensionsDict;
635 OSDictionary * kmodDict;
636 OSData * compressedCode = 0;
637
638 // Driver Code may need to be released
639 OSData * driverCode;
640
641 /* Get the requested kmod's info dictionary from the global
642 * startup extensions dictionary.
643 */
644 extensionsDict = getStartupExtensions();
645 if (!extensionsDict) {
646 IOLog("map_and_patch(): No extensions dictionary.\n");
647 LOG_DELAY();
648 return 0;
649 }
650
651 kmodDict = OSDynamicCast(OSDictionary,
652 extensionsDict->getObject(kmod_name));
653 if (!kmodDict) {
654 IOLog("map_and_patch(): "
655 "Extension \"%s\" cannot be found.\n", kmod_name);
656 LOG_DELAY();
657 return 0;
658 }
659
660 Boolean ret = false;
661
662 driverCode = OSDynamicCast(OSData, kmodDict->getObject("code"));
663 if (driverCode) {
664 ret = kld_file_map(kmod_name,
665 (unsigned char *) driverCode->getBytesNoCopy(),
666 (size_t) driverCode->getLength(),
667 /* isKmem */ false);
668 }
669 else { // May be an compressed extension
670
671 // If we have a compressed segment the uncompressModule
672 // will return a new OSData object that points to the kmem_alloced
673 // memory. Note we don't take a reference to driverCode so later
674 // when we release it we will actually free this driver. Ownership
675 // of the kmem has been handed of to kld_file.
676 compressedCode = OSDynamicCast(OSData,
677 kmodDict->getObject("compressedCode"));
678 if (!compressedCode) {
679 IOLog("map_and_patch(): "
680 "Extension \"%s\" has no \"code\" property.\n", kmod_name);
681 LOG_DELAY();
682 return 0;
683 }
684 if (!uncompressModule(compressedCode, &driverCode)) {
685 IOLog("map_and_patch(): "
686 "Extension \"%s\" Couldn't uncompress code.\n", kmod_name);
687 LOG_DELAY();
688 return 0;
689 }
690
691 unsigned char *driver = (unsigned char *) driverCode->getBytesNoCopy();
692 size_t driverSize = driverCode->getLength();
693
694 ret = kld_file_map(kmod_name, driver, driverSize, /* isKmem */ true);
695 driverCode->release();
696 if (!ret)
697 kmem_free(kernel_map, (vm_address_t) driver, driverSize);
698 }
699
700 if (!ret) {
701 IOLog("map_and_patch(): "
702 "Extension \"%s\" Didn't successfully load.\n", kmod_name);
703 LOG_DELAY();
704 return 0;
705 }
706
707 ret = TRUE;
708 if (!kld_file_patch_OSObjects(kmod_name)) {
709 IOLog("map_and_patch(): "
710 "Extension \"%s\" Error binding OSObjects.\n", kmod_name);
711 LOG_DELAY();
712
713 // RY: Instead of returning here, set the return value.
714 // We still need to call kld_file_prepare_for_link because
715 // we might have patched files outside of the driver. Don't
716 // worry, it will know to ignore the damaged file
717 ret = FALSE;
718 }
719
720 // Now repair any damage that the kld patcher may have done to the image
721 kld_file_prepare_for_link();
722
723 return ret;
724 }
725
726 /*********************************************************************
727 *********************************************************************/
728 bool stamp_kmod(const char * kmod_name, kmod_info_t * kmod_info) {
729 bool result = false;
730 OSDictionary * extensionsDict = NULL; // don't release
731 OSDictionary * kmodDict = NULL; // don't release
732 OSDictionary * plist = NULL; // don't release
733 OSString * versionString = NULL; // don't release
734 const char * plist_version = NULL; // don't free
735
736 if (strlen(kmod_name) + 1 > KMOD_MAX_NAME) {
737 IOLog("stamp_kmod(): Kext identifier \"%s\" is too long.\n",
738 kmod_name);
739 LOG_DELAY();
740 result = false;
741 goto finish;
742 }
743
744 strcpy(kmod_info->name, kmod_name);
745
746 /* Get the dictionary of startup extensions.
747 * This is keyed by module name.
748 */
749 extensionsDict = getStartupExtensions();
750 if (!extensionsDict) {
751 IOLog("stamp_kmod(): No extensions dictionary.\n");
752 LOG_DELAY();
753 result = false;
754 goto finish;
755 }
756
757 kmodDict = OSDynamicCast(OSDictionary,
758 extensionsDict->getObject(kmod_name));
759 if (!kmodDict) {
760 IOLog("stamp_kmod(): Can't find record for kmod \"%s\".\n",
761 kmod_name);
762 LOG_DELAY();
763 result = false;
764 goto finish;
765 }
766
767 plist = OSDynamicCast(OSDictionary,
768 kmodDict->getObject("plist"));
769 if (!kmodDict) {
770 IOLog("stamp_kmod(): Kmod \"%s\" has no property list.\n",
771 kmod_name);
772 LOG_DELAY();
773 result = false;
774 goto finish;
775 }
776
777 /*****
778 * Get the kext's version and stuff it into the kmod. This used
779 * to be a check that the kext & kmod had the same version, but
780 * now we just overwrite the kmod's version.
781 */
782
783 versionString = OSDynamicCast(OSString,
784 plist->getObject("CFBundleVersion"));
785 if (!versionString) {
786 IOLog("stamp_kmod(): Kmod \"%s\" has no \"CFBundleVersion\" "
787 "property.\n",
788 kmod_name);
789 LOG_DELAY();
790 result = false;
791 goto finish;
792 }
793
794 plist_version = versionString->getCStringNoCopy();
795 if (!plist_version) {
796 IOLog("stamp_kmod(): Can't get C string for kext version.\n");
797 LOG_DELAY();
798 result = false;
799 goto finish;
800 }
801
802 if (strlen(plist_version) + 1 > KMOD_MAX_NAME) {
803 IOLog("stamp_kmod(): Version \"%s\" of kext \"%s\" is too long.\n",
804 plist_version, kmod_name);
805 LOG_DELAY();
806 result = false;
807 goto finish;
808 }
809
810 strcpy(kmod_info->version, plist_version);
811
812 result = true;
813
814 finish:
815
816 return result;
817 }
818
819
820 /*********************************************************************
821 * This function takes a dependency list containing a series of
822 * already-loaded module names, followed by a single name for a module
823 * that hasn't yet been loaded. It invokes kld_load_from_memory() to
824 * build symbol info for the already-loaded modules, and then finally
825 * loads the actually requested module.
826 *********************************************************************/
827 static
828 kern_return_t load_kmod(OSArray * dependencyList) {
829 kern_return_t result = KERN_SUCCESS;
830
831 unsigned int num_dependencies = 0;
832 kmod_info_t ** kmod_dependencies = NULL;
833 unsigned int i;
834 OSString * requestedKmodName; // don't release
835 const char * requested_kmod_name;
836 OSString * currentKmodName; // don't release
837 char * kmod_address;
838 unsigned long kmod_size;
839 struct mach_header * kmod_header;
840 unsigned long kld_result;
841 int do_kld_unload = 0;
842 kmod_info_t * kmod_info_freeme = 0;
843 kmod_info_t * kmod_info = 0;
844 kmod_t kmod_id;
845
846
847 /* Separate the requested kmod from its dependencies.
848 */
849 i = dependencyList->getCount();
850 if (i == 0) {
851 IOLog("load_kmod(): Called with empty list.\n");
852 LOG_DELAY();
853 result = KERN_FAILURE;
854 goto finish;
855 } else {
856 i--; // make i be the index of the last entry
857 }
858
859 requestedKmodName = OSDynamicCast(OSString, dependencyList->getObject(i));
860 if (!requestedKmodName) {
861 IOLog("load_kmod(): Called with invalid list of kmod names.\n");
862 LOG_DELAY();
863 result = KERN_FAILURE;
864 goto finish;
865 }
866 requested_kmod_name = requestedKmodName->getCStringNoCopy();
867 dependencyList->removeObject(i);
868
869 /* If the requested kmod is already loaded, there's no work to do.
870 */
871 kmod_info_freeme = kmod_lookupbyname_locked(requested_kmod_name);
872 if (kmod_info_freeme) {
873 // FIXME: Need to check for version mismatch if already loaded.
874 result = KERN_SUCCESS;
875 goto finish;
876 }
877
878
879 /* Do the KLD loads for the already-loaded modules in order to get
880 * their symbols.
881 */
882 kld_address_func(&address_for_loaded_kmod);
883
884 num_dependencies = dependencyList->getCount();
885 kmod_dependencies = (kmod_info_t **)kalloc(num_dependencies *
886 sizeof(kmod_info_t *));
887 if (!kmod_dependencies) {
888 IOLog("load_kmod(): Failed to allocate memory for dependency array "
889 "during load of kmod \"%s\".\n", requested_kmod_name);
890 LOG_DELAY();
891 result = KERN_FAILURE;
892 goto finish;
893 }
894
895 bzero(kmod_dependencies, num_dependencies *
896 sizeof(kmod_info_t *));
897
898 for (i = 0; i < num_dependencies; i++) {
899
900 currentKmodName = OSDynamicCast(OSString,
901 dependencyList->getObject(i));
902
903 if (!currentKmodName) {
904 IOLog("load_kmod(): Invalid dependency name at index %d for "
905 "kmod \"%s\".\n", i, requested_kmod_name);
906 LOG_DELAY();
907 result = KERN_FAILURE;
908 goto finish;
909 }
910
911 const char * current_kmod_name = currentKmodName->getCStringNoCopy();
912
913 // These globals are needed by the kld_address functions
914 g_current_kmod_info = kmod_lookupbyname_locked(current_kmod_name);
915 g_current_kmod_name = current_kmod_name;
916
917 if (!g_current_kmod_info) {
918 IOLog("load_kmod(): Missing dependency \"%s\".\n",
919 current_kmod_name);
920 LOG_DELAY();
921 result = KERN_FAILURE;
922 goto finish;
923 }
924
925 /* Record the current kmod as a dependency of the requested
926 * one. This will be used in building references after the
927 * load is complete.
928 */
929 kmod_dependencies[i] = g_current_kmod_info;
930
931 /* If the current kmod's size is zero it means that we have a
932 * fake in-kernel dependency. If so then don't have to arrange
933 * for its symbol table to be reloaded as it is
934 * part of the kernel's symbol table..
935 */
936 if (!g_current_kmod_info->size)
937 continue;
938
939 if (!kld_file_merge_OSObjects(current_kmod_name)) {
940 IOLog("load_kmod(): Can't merge OSObjects \"%s\".\n",
941 current_kmod_name);
942 LOG_DELAY();
943 result = KERN_FAILURE;
944 goto finish;
945 }
946
947 kmod_address = (char *)
948 kld_file_getaddr(current_kmod_name, (long *) &kmod_size);
949 if (!kmod_address) {
950
951 IOLog("load_kmod() failed for dependency kmod "
952 "\"%s\".\n", current_kmod_name);
953 LOG_DELAY();
954 result = KERN_FAILURE;
955 goto finish;
956 }
957
958 kld_result = kld_load_from_memory(&kmod_header,
959 current_kmod_name, kmod_address, kmod_size);
960
961 if (kld_result) {
962 do_kld_unload = 1;
963 }
964
965 if (!kld_result || !link_load_address) {
966 IOLog("kld_load_from_memory() failed for dependency kmod "
967 "\"%s\".\n", current_kmod_name);
968 LOG_DELAY();
969 result = KERN_FAILURE;
970 goto finish;
971 }
972
973 kld_forget_symbol("_kmod_info");
974 }
975
976 /*****
977 * Now that we've done all the dependencies, which should have already
978 * been loaded, we do the last requested module, which should not have
979 * already been loaded.
980 */
981 kld_address_func(&alloc_for_kmod);
982
983 g_current_kmod_name = requested_kmod_name;
984 g_current_kmod_info = 0; // there is no kmod yet
985
986 if (!map_and_patch(requested_kmod_name)) {
987 IOLog("load_kmod: map_and_patch() failed for "
988 "kmod \"%s\".\n", requested_kmod_name);
989 LOG_DELAY();
990 result = KERN_FAILURE;
991 goto finish;
992 }
993
994 kmod_address = (char *)
995 kld_file_getaddr(requested_kmod_name, (long *) &kmod_size);
996 if (!kmod_address) {
997 IOLog("load_kmod: kld_file_getaddr() failed internal error "
998 "on \"%s\".\n", requested_kmod_name);
999 LOG_DELAY();
1000 result = KERN_FAILURE;
1001 goto finish;
1002 }
1003
1004 kld_result = kld_load_from_memory(&kmod_header,
1005 requested_kmod_name, kmod_address, kmod_size);
1006
1007 if (kld_result) {
1008 do_kld_unload = 1;
1009 }
1010
1011 if (!kld_result || !link_load_address) {
1012 IOLog("load_kmod(): kld_load_from_memory() failed for "
1013 "kmod \"%s\".\n", requested_kmod_name);
1014 LOG_DELAY();
1015 result = KERN_FAILURE;
1016 goto finish;
1017 }
1018
1019
1020 /* Copy the linked header and image into the vm_allocated buffer.
1021 * Move each onto the appropriate page-aligned boundary as given
1022 * by the global link_... variables.
1023 */
1024 bzero((char *)link_buffer_address, link_buffer_size);
1025 // bcopy() is (from, to, length)
1026 bcopy((char *)kmod_header, (char *)link_buffer_address, link_header_size);
1027 bcopy((char *)kmod_header + link_header_size,
1028 (char *)link_buffer_address + round_page_32(link_header_size),
1029 link_load_size - link_header_size);
1030
1031
1032 /* Get the kmod_info struct for the newly-loaded kmod.
1033 */
1034 if (!kld_lookup("_kmod_info", (unsigned long *)&kmod_info)) {
1035 IOLog("kld_lookup() of \"_kmod_info\" failed for "
1036 "kmod \"%s\".\n", requested_kmod_name);
1037 LOG_DELAY();
1038 result = KERN_FAILURE;
1039 goto finish;
1040 }
1041
1042
1043 if (!stamp_kmod(requested_kmod_name, kmod_info)) {
1044 // stamp_kmod() logs a meaningful message
1045 result = KERN_FAILURE;
1046 goto finish;
1047 }
1048
1049
1050 /* kld_lookup of _kmod_info yielded the actual linked address,
1051 * so now that we've copied the data into its real place,
1052 * we can set this stuff.
1053 */
1054 kmod_info->address = link_buffer_address;
1055 kmod_info->size = link_buffer_size;
1056 kmod_info->hdr_size = round_page_32(link_header_size);
1057
1058 /* We've written data and instructions, so *flush* the data cache
1059 * and *invalidate* the instruction cache.
1060 */
1061 flush_dcache64((addr64_t)link_buffer_address, link_buffer_size, false);
1062 invalidate_icache64((addr64_t)link_buffer_address, link_buffer_size, false);
1063
1064
1065 /* Register the new kmod with the kernel proper.
1066 */
1067 if (kmod_create_internal(kmod_info, &kmod_id) != KERN_SUCCESS) {
1068 IOLog("load_kmod(): kmod_create() failed for "
1069 "kmod \"%s\".\n", requested_kmod_name);
1070 LOG_DELAY();
1071 result = KERN_FAILURE;
1072 goto finish;
1073 }
1074
1075 #if DEBUG
1076 IOLog("kmod id %d successfully created at 0x%lx, size %ld.\n",
1077 (unsigned int)kmod_id, link_buffer_address, link_buffer_size);
1078 LOG_DELAY();
1079 #endif /* DEBUG */
1080
1081 /* Record dependencies for the newly-loaded kmod.
1082 */
1083 for (i = 0; i < num_dependencies; i++) {
1084 kmod_info_t * cur_dependency_info;
1085 kmod_t packed_id;
1086 cur_dependency_info = kmod_dependencies[i];
1087 packed_id = KMOD_PACK_IDS(kmod_id, cur_dependency_info->id);
1088 if (kmod_retain(packed_id) != KERN_SUCCESS) {
1089 IOLog("load_kmod(): kmod_retain() failed for "
1090 "kmod \"%s\".\n", requested_kmod_name);
1091 LOG_DELAY();
1092 kmod_destroy_internal(kmod_id);
1093 result = KERN_FAILURE;
1094 goto finish;
1095 }
1096 }
1097
1098 /* Start the kmod (which invokes constructors for I/O Kit
1099 * drivers.
1100 */
1101 // kmod_start_or_stop(id, start?, user data, datalen)
1102 if (kmod_start_or_stop(kmod_id, 1, 0, 0) != KERN_SUCCESS) {
1103 IOLog("load_kmod(): kmod_start_or_stop() failed for "
1104 "kmod \"%s\".\n", requested_kmod_name);
1105 LOG_DELAY();
1106 kmod_destroy_internal(kmod_id);
1107 result = KERN_FAILURE;
1108 goto finish;
1109 }
1110
1111 finish:
1112
1113 if (kmod_info_freeme) {
1114 kfree((unsigned int)kmod_info_freeme, sizeof(kmod_info_t));
1115 }
1116
1117 /* Only do a kld_unload_all() if at least one load happened.
1118 */
1119 if (do_kld_unload) {
1120 kld_unload_all(/* deallocate sets */ 1);
1121 }
1122
1123 /* If the link failed, blow away the allocated link buffer.
1124 */
1125 if (result != KERN_SUCCESS && link_buffer_address) {
1126 vm_deallocate(kernel_map, link_buffer_address, link_buffer_size);
1127 }
1128
1129 if (kmod_dependencies) {
1130 for (i = 0; i < num_dependencies; i++) {
1131 if (kmod_dependencies[i]) {
1132 kfree((unsigned int)kmod_dependencies[i], sizeof(kmod_info_t));
1133 }
1134 }
1135 kfree((unsigned int)kmod_dependencies,
1136 num_dependencies * sizeof(kmod_info_t *));
1137 }
1138
1139 /* Reset these static global variables for the next call.
1140 */
1141 g_current_kmod_name = NULL;
1142 g_current_kmod_info = NULL;
1143 link_buffer_address = 0;
1144 link_load_address = 0;
1145 link_load_size = 0;
1146 link_buffer_size = 0;
1147 link_header_size = 0;
1148
1149 return result;
1150 }
1151
1152
1153 /*********************************************************************
1154 * This is the function that IOCatalogue calls in order to load a kmod.
1155 * It first checks whether the kmod is already loaded. If the kmod
1156 * isn't loaded, this function builds a dependency list and calls
1157 * load_kmod() repeatedly to guarantee that each dependency is in fact
1158 * loaded.
1159 *********************************************************************/
1160 __private_extern__
1161 kern_return_t load_kernel_extension(char * kmod_name) {
1162 kern_return_t result = KERN_SUCCESS;
1163 kmod_info_t * kmod_info = 0; // must free
1164 OSArray * dependencyList = NULL; // must release
1165 OSArray * curDependencyList = NULL; // must release
1166
1167 /* See if the kmod is already loaded.
1168 */
1169 kmod_info = kmod_lookupbyname_locked(kmod_name);
1170 if (kmod_info) { // NOT checked
1171 result = KERN_SUCCESS;
1172 goto finish;
1173 }
1174
1175 /* It isn't loaded; build a dependency list and
1176 * load those.
1177 */
1178 unsigned int count;
1179 unsigned int i;
1180 dependencyList = getDependencyListForKmod(kmod_name);
1181 if (!dependencyList) {
1182 IOLog("load_kernel_extension(): "
1183 "Can't get dependencies for kernel extension \"%s\".\n",
1184 kmod_name);
1185 LOG_DELAY();
1186 result = KERN_FAILURE;
1187 goto finish;
1188 }
1189
1190 count = dependencyList->getCount();
1191 for (i = 0; i < count; i++) {
1192 kern_return_t load_result;
1193 OSString * curKmodName; // don't release
1194 const char * cur_kmod_name;
1195
1196 curKmodName = OSDynamicCast(OSString,
1197 dependencyList->getObject(i));
1198 cur_kmod_name = curKmodName->getCStringNoCopy();
1199 curDependencyList = getDependencyListForKmod(cur_kmod_name);
1200 if (!curDependencyList) {
1201 IOLog("load_kernel_extension(): "
1202 "Can't get dependencies for kernel extension \"%s\".\n",
1203 cur_kmod_name);
1204 LOG_DELAY();
1205 result = KERN_FAILURE;
1206 goto finish;
1207 } else {
1208 load_result = load_kmod(curDependencyList);
1209 if (load_result != KERN_SUCCESS) {
1210 IOLog("load_kernel_extension(): "
1211 "load_kmod() failed for kmod \"%s\".\n",
1212 cur_kmod_name);
1213 LOG_DELAY();
1214 result = load_result;
1215 goto finish;
1216 }
1217 curDependencyList->release();
1218 curDependencyList = NULL;
1219 }
1220 }
1221
1222
1223 finish:
1224
1225 if (kmod_info) {
1226 kfree((unsigned int)kmod_info, sizeof(kmod_info_t));
1227 }
1228
1229 if (dependencyList) {
1230 dependencyList->release();
1231 dependencyList = NULL;
1232 }
1233 if (curDependencyList) {
1234 curDependencyList->release();
1235 curDependencyList = NULL;
1236 }
1237
1238 return result;
1239 }