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