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