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