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