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