]> git.saurik.com Git - apple/xnu.git/blame - libsa/kmod.cpp
xnu-344.26.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 *
de355530
A
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.
1c79356b 11 *
de355530
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
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.
1c79356b
A
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
de355530
A
62extern void flush_dcache(vm_offset_t addr, unsigned cnt, int phys);
63extern void invalidate_icache(vm_offset_t addr, unsigned cnt, int phys);
1c79356b
A
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
de355530 525 round_headers_size = round_page(headers_size);
1c79356b
A
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
de355530
A
561 round_headers_size = round_page(headers_size);
562 round_segments_size = round_page(size - headers_size);
1c79356b
A
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
9bccf70c 675 ret = TRUE;
0b4e3aa0
A
676 if (!kld_file_patch_OSObjects(kmod_name)) {
677 IOLog("map_and_patch(): "
678 "Extension \"%s\" Error binding OSObjects.\n", kmod_name);
1c79356b 679 LOG_DELAY();
9bccf70c
A
680
681 // RY: Instead of returning here, set the return value.
682 // We still need to call kld_file_prepare_for_link because
683 // we might have patched files outside of the driver. Don't
684 // worry, it will know to ignore the damaged file
685 ret = FALSE;
1c79356b
A
686 }
687
0b4e3aa0
A
688 // Now repair any damage that the kld patcher may have done to the image
689 kld_file_prepare_for_link();
690
9bccf70c 691 return ret;
1c79356b
A
692}
693
1c79356b
A
694/*********************************************************************
695*********************************************************************/
9bccf70c 696bool stamp_kmod(const char * kmod_name, kmod_info_t * kmod_info) {
1c79356b
A
697 bool result = false;
698 OSDictionary * extensionsDict = NULL; // don't release
699 OSDictionary * kmodDict = NULL; // don't release
700 OSDictionary * plist = NULL; // don't release
701 OSString * versionString = NULL; // don't release
9bccf70c 702 const char * plist_version = NULL; // don't free
1c79356b 703
9bccf70c
A
704 if (strlen(kmod_name) + 1 > KMOD_MAX_NAME) {
705 IOLog("stamp_kmod(): Kext identifier \"%s\" is too long.\n",
706 kmod_name);
1c79356b
A
707 LOG_DELAY();
708 result = false;
709 goto finish;
710 }
711
9bccf70c 712 strcpy(kmod_info->name, kmod_name);
1c79356b
A
713
714 /* Get the dictionary of startup extensions.
715 * This is keyed by module name.
716 */
717 extensionsDict = getStartupExtensions();
718 if (!extensionsDict) {
9bccf70c 719 IOLog("stamp_kmod(): No extensions dictionary.\n");
1c79356b
A
720 LOG_DELAY();
721 result = false;
722 goto finish;
723 }
724
725 kmodDict = OSDynamicCast(OSDictionary,
726 extensionsDict->getObject(kmod_name));
727 if (!kmodDict) {
9bccf70c 728 IOLog("stamp_kmod(): Can't find record for kmod \"%s\".\n",
1c79356b
A
729 kmod_name);
730 LOG_DELAY();
731 result = false;
732 goto finish;
733 }
734
735 plist = OSDynamicCast(OSDictionary,
0b4e3aa0 736 kmodDict->getObject("plist"));
1c79356b 737 if (!kmodDict) {
9bccf70c 738 IOLog("stamp_kmod(): Kmod \"%s\" has no property list.\n",
1c79356b
A
739 kmod_name);
740 LOG_DELAY();
741 result = false;
742 goto finish;
743 }
744
9bccf70c
A
745 /*****
746 * Get the kext's version and stuff it into the kmod. This used
747 * to be a check that the kext & kmod had the same version, but
748 * now we just overwrite the kmod's version.
749 */
750
1c79356b 751 versionString = OSDynamicCast(OSString,
0b4e3aa0 752 plist->getObject("CFBundleVersion"));
1c79356b 753 if (!versionString) {
9bccf70c 754 IOLog("stamp_kmod(): Kmod \"%s\" has no \"CFBundleVersion\" "
0b4e3aa0 755 "property.\n",
1c79356b
A
756 kmod_name);
757 LOG_DELAY();
758 result = false;
759 goto finish;
760 }
761
9bccf70c
A
762 plist_version = versionString->getCStringNoCopy();
763 if (!plist_version) {
764 IOLog("stamp_kmod(): Can't get C string for kext version.\n");
1c79356b
A
765 LOG_DELAY();
766 result = false;
767 goto finish;
768 }
769
9bccf70c
A
770 if (strlen(plist_version) + 1 > KMOD_MAX_NAME) {
771 IOLog("stamp_kmod(): Version \"%s\" of kext \"%s\" is too long.\n",
772 plist_version, kmod_name);
1c79356b
A
773 LOG_DELAY();
774 result = false;
775 goto finish;
776 }
777
9bccf70c
A
778 strcpy(kmod_info->version, plist_version);
779
0b4e3aa0 780 result = true;
1c79356b
A
781
782finish:
783
1c79356b
A
784 return result;
785}
786
787
788/*********************************************************************
789* This function takes a dependency list containing a series of
790* already-loaded module names, followed by a single name for a module
791* that hasn't yet been loaded. It invokes kld_load_from_memory() to
792* build symbol info for the already-loaded modules, and then finally
793* loads the actually requested module.
794*********************************************************************/
795static
796kern_return_t load_kmod(OSArray * dependencyList) {
797 kern_return_t result = KERN_SUCCESS;
798
799 unsigned int num_dependencies = 0;
800 kmod_info_t ** kmod_dependencies = NULL;
801 unsigned int i;
802 OSString * requestedKmodName; // don't release
803 const char * requested_kmod_name;
804 OSString * currentKmodName; // don't release
805 char * kmod_address;
806 unsigned long kmod_size;
807 struct mach_header * kmod_header;
808 unsigned long kld_result;
809 int do_kld_unload = 0;
9bccf70c
A
810 kmod_info_t * kmod_info_freeme = 0;
811 kmod_info_t * kmod_info = 0;
1c79356b
A
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 */
9bccf70c
A
839 kmod_info_freeme = kmod_lookupbyname_locked(requested_kmod_name);
840 if (kmod_info_freeme) {
1c79356b
A
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
9bccf70c
A
863 bzero(kmod_dependencies, num_dependencies *
864 sizeof(kmod_info_t *));
865
1c79356b
A
866 for (i = 0; i < num_dependencies; i++) {
867
868 currentKmodName = OSDynamicCast(OSString,
869 dependencyList->getObject(i));
870
871 if (!currentKmodName) {
872 IOLog("load_kmod(): Invalid dependency name at index %d for "
873 "kmod \"%s\".\n", i, requested_kmod_name);
874 LOG_DELAY();
875 result = KERN_FAILURE;
876 goto finish;
877 }
878
879 const char * current_kmod_name = currentKmodName->getCStringNoCopy();
880
881 // These globals are needed by the kld_address functions
9bccf70c 882 g_current_kmod_info = kmod_lookupbyname_locked(current_kmod_name);
1c79356b
A
883 g_current_kmod_name = current_kmod_name;
884
885 if (!g_current_kmod_info) {
886 IOLog("load_kmod(): Missing dependency \"%s\".\n",
887 current_kmod_name);
888 LOG_DELAY();
889 result = KERN_FAILURE;
890 goto finish;
891 }
892
893 /* Record the current kmod as a dependency of the requested
894 * one. This will be used in building references after the
895 * load is complete.
896 */
897 kmod_dependencies[i] = g_current_kmod_info;
898
899 /* If the current kmod's size is zero it means that we have a
900 * fake in-kernel dependency. If so then don't have to arrange
901 * for its symbol table to be reloaded as it is
902 * part of the kernel's symbol table..
903 */
904 if (!g_current_kmod_info->size)
905 continue;
906
0b4e3aa0 907 if (!kld_file_merge_OSObjects(current_kmod_name)) {
9bccf70c 908 IOLog("load_kmod(): Can't merge OSObjects \"%s\".\n",
0b4e3aa0
A
909 current_kmod_name);
910 LOG_DELAY();
911 result = KERN_FAILURE;
912 goto finish;
913 }
914
915 kmod_address = (char *)
916 kld_file_getaddr(current_kmod_name, (long *) &kmod_size);
917 if (!kmod_address) {
1c79356b 918
9bccf70c 919 IOLog("load_kmod() failed for dependency kmod "
1c79356b
A
920 "\"%s\".\n", current_kmod_name);
921 LOG_DELAY();
922 result = KERN_FAILURE;
923 goto finish;
924 }
925
926 kld_result = kld_load_from_memory(&kmod_header,
0b4e3aa0 927 current_kmod_name, kmod_address, kmod_size);
1c79356b
A
928
929 if (kld_result) {
930 do_kld_unload = 1;
931 }
932
933 if (!kld_result || !link_load_address) {
934 IOLog("kld_load_from_memory() failed for dependency kmod "
935 "\"%s\".\n", current_kmod_name);
936 LOG_DELAY();
937 result = KERN_FAILURE;
938 goto finish;
939 }
940
941 kld_forget_symbol("_kmod_info");
942 }
943
944 /*****
945 * Now that we've done all the dependencies, which should have already
946 * been loaded, we do the last requested module, which should not have
947 * already been loaded.
948 */
949 kld_address_func(&alloc_for_kmod);
950
951 g_current_kmod_name = requested_kmod_name;
952 g_current_kmod_info = 0; // there is no kmod yet
953
0b4e3aa0
A
954 if (!map_and_patch(requested_kmod_name)) {
955 IOLog("load_kmod: map_and_patch() failed for "
956 "kmod \"%s\".\n", requested_kmod_name);
957 LOG_DELAY();
958 result = KERN_FAILURE;
959 goto finish;
960 }
961
962 kmod_address = (char *)
963 kld_file_getaddr(requested_kmod_name, (long *) &kmod_size);
964 if (!kmod_address) {
965 IOLog("load_kmod: kld_file_getaddr() failed internal error "
966 "on \"%s\".\n", requested_kmod_name);
1c79356b
A
967 LOG_DELAY();
968 result = KERN_FAILURE;
969 goto finish;
970 }
971
972 kld_result = kld_load_from_memory(&kmod_header,
0b4e3aa0 973 requested_kmod_name, kmod_address, kmod_size);
1c79356b
A
974
975 if (kld_result) {
976 do_kld_unload = 1;
977 }
978
979 if (!kld_result || !link_load_address) {
980 IOLog("load_kmod(): kld_load_from_memory() failed for "
981 "kmod \"%s\".\n", requested_kmod_name);
982 LOG_DELAY();
983 result = KERN_FAILURE;
984 goto finish;
985 }
986
987
988 /* Copy the linked header and image into the vm_allocated buffer.
989 * Move each onto the appropriate page-aligned boundary as given
990 * by the global link_... variables.
991 */
992 bzero((char *)link_buffer_address, link_buffer_size);
993 // bcopy() is (from, to, length)
994 bcopy((char *)kmod_header, (char *)link_buffer_address, link_header_size);
995 bcopy((char *)kmod_header + link_header_size,
de355530 996 (char *)link_buffer_address + round_page(link_header_size),
1c79356b
A
997 link_load_size - link_header_size);
998
999
1000 /* Get the kmod_info struct for the newly-loaded kmod.
1001 */
1002 if (!kld_lookup("_kmod_info", (unsigned long *)&kmod_info)) {
1003 IOLog("kld_lookup() of \"_kmod_info\" failed for "
1004 "kmod \"%s\".\n", requested_kmod_name);
1005 LOG_DELAY();
1006 result = KERN_FAILURE;
1007 goto finish;
1008 }
1009
1010
9bccf70c
A
1011 if (!stamp_kmod(requested_kmod_name, kmod_info)) {
1012 // stamp_kmod() logs a meaningful message
1c79356b
A
1013 result = KERN_FAILURE;
1014 goto finish;
1015 }
1016
1017
1018 /* kld_lookup of _kmod_info yielded the actual linked address,
1019 * so now that we've copied the data into its real place,
1020 * we can set this stuff.
1021 */
1022 kmod_info->address = link_buffer_address;
1023 kmod_info->size = link_buffer_size;
de355530 1024 kmod_info->hdr_size = round_page(link_header_size);
1c79356b
A
1025
1026 /* We've written data and instructions, so *flush* the data cache
1027 * and *invalidate* the instruction cache.
1028 */
de355530
A
1029 flush_dcache(link_buffer_address, link_buffer_size, false);
1030 invalidate_icache(link_buffer_address, link_buffer_size, false);
1c79356b
A
1031
1032
1033 /* Register the new kmod with the kernel proper.
1034 */
1035 if (kmod_create_internal(kmod_info, &kmod_id) != KERN_SUCCESS) {
1036 IOLog("load_kmod(): kmod_create() failed for "
1037 "kmod \"%s\".\n", requested_kmod_name);
1038 LOG_DELAY();
1039 result = KERN_FAILURE;
1040 goto finish;
1041 }
1042
0b4e3aa0 1043#if DEBUG
1c79356b
A
1044 IOLog("kmod id %d successfully created at 0x%lx, size %ld.\n",
1045 (unsigned int)kmod_id, link_buffer_address, link_buffer_size);
1046 LOG_DELAY();
0b4e3aa0 1047#endif DEBUG
1c79356b
A
1048
1049 /* Record dependencies for the newly-loaded kmod.
1050 */
1051 for (i = 0; i < num_dependencies; i++) {
1052 kmod_info_t * cur_dependency_info;
1053 kmod_t packed_id;
1054 cur_dependency_info = kmod_dependencies[i];
1055 packed_id = KMOD_PACK_IDS(kmod_id, cur_dependency_info->id);
1056 if (kmod_retain(packed_id) != KERN_SUCCESS) {
1057 IOLog("load_kmod(): kmod_retain() failed for "
1058 "kmod \"%s\".\n", requested_kmod_name);
1059 LOG_DELAY();
1060 kmod_destroy_internal(kmod_id);
1061 result = KERN_FAILURE;
1062 goto finish;
1063 }
1064 }
1065
1066 /* Start the kmod (which invokes constructors for I/O Kit
1067 * drivers.
1068 */
1069 // kmod_start_or_stop(id, start?, user data, datalen)
1070 if (kmod_start_or_stop(kmod_id, 1, 0, 0) != KERN_SUCCESS) {
1071 IOLog("load_kmod(): kmod_start_or_stop() failed for "
1072 "kmod \"%s\".\n", requested_kmod_name);
1073 LOG_DELAY();
1074 kmod_destroy_internal(kmod_id);
1075 result = KERN_FAILURE;
1076 goto finish;
1077 }
1078
1079finish:
1080
9bccf70c
A
1081 if (kmod_info_freeme) {
1082 kfree(kmod_info_freeme, sizeof(kmod_info_t));
1083 }
1084
1c79356b
A
1085 /* Only do a kld_unload_all() if at least one load happened.
1086 */
1087 if (do_kld_unload) {
1088 kld_unload_all(/* deallocate sets */ 1);
1c79356b
A
1089 }
1090
1091 /* If the link failed, blow away the allocated link buffer.
1092 */
1093 if (result != KERN_SUCCESS && link_buffer_address) {
1094 vm_deallocate(kernel_map, link_buffer_address, link_buffer_size);
1095 }
1096
1097 if (kmod_dependencies) {
9bccf70c
A
1098 for (i = 0; i < num_dependencies; i++) {
1099 if (kmod_dependencies[i]) {
1100 kfree(kmod_dependencies[i], sizeof(kmod_info_t));
1101 }
1102 }
1c79356b
A
1103 kfree((unsigned int)kmod_dependencies,
1104 num_dependencies * sizeof(kmod_info_t *));
1105 }
1106
1107 /* Reset these static global variables for the next call.
1108 */
1109 g_current_kmod_name = NULL;
1110 g_current_kmod_info = NULL;
1111 link_buffer_address = 0;
1112 link_load_address = 0;
1113 link_load_size = 0;
1114 link_buffer_size = 0;
1115 link_header_size = 0;
1116
1117 return result;
1118}
1119
1120
1121/*********************************************************************
1122* This is the function that IOCatalogue calls in order to load a kmod.
1123* It first checks whether the kmod is already loaded. If the kmod
1124* isn't loaded, this function builds a dependency list and calls
1125* load_kmod() repeatedly to guarantee that each dependency is in fact
1126* loaded.
1127*********************************************************************/
1128__private_extern__
1129kern_return_t load_kernel_extension(char * kmod_name) {
1130 kern_return_t result = KERN_SUCCESS;
9bccf70c 1131 kmod_info_t * kmod_info = 0; // must free
1c79356b
A
1132 OSArray * dependencyList = NULL; // must release
1133 OSArray * curDependencyList = NULL; // must release
1c79356b
A
1134
1135 /* See if the kmod is already loaded.
1136 */
9bccf70c 1137 kmod_info = kmod_lookupbyname_locked(kmod_name);
1c79356b
A
1138 if (kmod_info) { // NOT checked
1139 result = KERN_SUCCESS;
1140 goto finish;
1141 }
1142
1c79356b
A
1143 /* It isn't loaded; build a dependency list and
1144 * load those.
1145 */
1146 unsigned int count;
1147 unsigned int i;
1148 dependencyList = getDependencyListForKmod(kmod_name);
1149 if (!dependencyList) {
1150 IOLog("load_kernel_extension(): "
1151 "Can't get dependencies for kernel extension \"%s\".\n",
1152 kmod_name);
1153 LOG_DELAY();
1154 result = KERN_FAILURE;
1155 goto finish;
1156 }
1157
1c79356b
A
1158 count = dependencyList->getCount();
1159 for (i = 0; i < count; i++) {
1160 kern_return_t load_result;
1161 OSString * curKmodName; // don't release
1162 const char * cur_kmod_name;
1163
1164 curKmodName = OSDynamicCast(OSString,
1165 dependencyList->getObject(i));
1166 cur_kmod_name = curKmodName->getCStringNoCopy();
1167 curDependencyList = getDependencyListForKmod(cur_kmod_name);
0b4e3aa0 1168 if (!curDependencyList) {
1c79356b 1169 IOLog("load_kernel_extension(): "
0b4e3aa0 1170 "Can't get dependencies for kernel extension \"%s\".\n",
1c79356b
A
1171 cur_kmod_name);
1172 LOG_DELAY();
0b4e3aa0 1173 result = KERN_FAILURE;
1c79356b 1174 goto finish;
0b4e3aa0
A
1175 } else {
1176 load_result = load_kmod(curDependencyList);
1177 if (load_result != KERN_SUCCESS) {
1178 IOLog("load_kernel_extension(): "
1179 "load_kmod() failed for kmod \"%s\".\n",
1180 cur_kmod_name);
1181 LOG_DELAY();
1182 result = load_result;
1183 goto finish;
1184 }
1185 curDependencyList->release();
1186 curDependencyList = NULL;
1c79356b 1187 }
1c79356b
A
1188 }
1189
1190
1191finish:
1192
9bccf70c
A
1193 if (kmod_info) {
1194 kfree(kmod_info, sizeof(kmod_info_t));
1195 }
1196
1c79356b
A
1197 if (dependencyList) {
1198 dependencyList->release();
1199 dependencyList = NULL;
1200 }
1201 if (curDependencyList) {
1202 curDependencyList->release();
1203 curDependencyList = NULL;
1204 }
1205
1c79356b
A
1206 return result;
1207}