]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOCatalogue.cpp
xnu-1228.15.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
30 *
31 * HISTORY
32 *
33 */
2d21ac55
A
34/*
35 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
36 * support for mandatory and extensible security protections. This notice
37 * is included in support of clause 2.2 (b) of the Apple Public License,
38 * Version 2.0.
39 */
1c79356b
A
40
41#include <IOKit/IODeviceTreeSupport.h>
42#include <IOKit/IOService.h>
43#include <libkern/c++/OSContainers.h>
44#include <IOKit/IOCatalogue.h>
45#include <libkern/c++/OSUnserialize.h>
46extern "C" {
47#include <machine/machine_routines.h>
48#include <mach/kmod.h>
49#include <mach-o/mach_header.h>
9bccf70c 50#include <kern/host.h>
2d21ac55 51#include <security/mac_data.h>
1c79356b
A
52};
53
54#include <IOKit/IOLib.h>
55
56#include <IOKit/assert.h>
57
58
59extern "C" {
60int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
61extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
91447636
A
62/* operates on 32 bit segments */
63extern void OSRuntimeUnloadCPPForSegment(struct segment_command * segment);
1c79356b
A
64};
65
66
67/*****
68 * At startup these function pointers are set to use the libsa in-kernel
69 * linker for recording and loading kmods. Once the root filesystem
70 * is available, the kmod_load_function pointer gets switched to point
71 * at the kmod_load_extension() function built into the kernel, and the
72 * others are set to zero. Those two functions must *always* be checked
73 * before being invoked.
74 */
75extern "C" {
76kern_return_t (*kmod_load_function)(char *extension_name) =
77 &kmod_load_extension;
78bool (*record_startup_extensions_function)(void) = 0;
79bool (*add_from_mkext_function)(OSData * mkext) = 0;
80void (*remove_startup_extension_function)(const char * name) = 0;
81};
82
83
84/*****
85 * A few parts of IOCatalogue require knowledge of
86 * whether the in-kernel linker is present. This
87 * variable is set by libsa's bootstrap code.
88 */
89int kernelLinkerPresent = 0;
90
1c79356b
A
91#define kModuleKey "CFBundleIdentifier"
92
55e303ae 93#define super OSObject
1c79356b
A
94OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
95
96#define CATALOGTEST 0
97
55e303ae
A
98IOCatalogue * gIOCatalogue;
99const OSSymbol * gIOClassKey;
100const OSSymbol * gIOProbeScoreKey;
101const OSSymbol * gIOModuleIdentifierKey;
102OSSet * gIOCatalogModuleRequests;
103OSSet * gIOCatalogCacheMisses;
104OSSet * gIOCatalogROMMkexts;
105IOLock * gIOCatalogLock;
106IOLock * gIOKLDLock;
107
108/*********************************************************************
109*********************************************************************/
110
111OSArray * gIOPrelinkedModules = 0;
112
113extern "C" kern_return_t
114kmod_create_internal(
115 kmod_info_t *info,
116 kmod_t *id);
117
118extern "C" kern_return_t
119kmod_destroy_internal(kmod_t id);
120
121extern "C" kern_return_t
122kmod_start_or_stop(
123 kmod_t id,
124 int start,
125 kmod_args_t *data,
126 mach_msg_type_number_t *dataCount);
127
128extern "C" kern_return_t kmod_retain(kmod_t id);
129extern "C" kern_return_t kmod_release(kmod_t id);
130
2d21ac55
A
131#if CONFIG_MACF_KEXT
132/* MAC Framework support */
133
134/*
135 * define IOC_DEBUG to display run-time debugging information
136 * #define IOC_DEBUG 1
137 */
138
139#ifdef IOC_DEBUG
140#define DPRINTF(x) printf x
141#else
142#define IOC_DEBUG
143#define DPRINTF(x)
144#endif
145
146static bool
147primitive_type(OSObject *obj)
148{
149 const OSMetaClass *typeID;
150
151 typeID = OSTypeIDInst(obj);
152 if (typeID == OSTypeID(OSString) || typeID == OSTypeID(OSNumber) ||
153 typeID == OSTypeID(OSBoolean) || typeID == OSTypeID(OSData))
154 return(true);
155 else
156 return(false);
157}
158
159static int
160primitive_type_length(OSObject *obj)
161{
162 const OSMetaClass *typeID;
163 int len;
164
165 typeID = OSTypeIDInst(obj);
166 if (typeID == OSTypeID(OSString)) {
167 OSString * stringObj = OSDynamicCast(OSString, obj);
168 len = stringObj->getLength() + 1;
169 }
170 else if (typeID == OSTypeID(OSNumber)) {
171 len = sizeof("4294967295"); /* UINT32_MAX */
172 }
173 else if (typeID == OSTypeID(OSBoolean)) {
174 OSBoolean * boolObj = OSDynamicCast(OSBoolean, obj);
175 len = boolObj->isTrue() ? sizeof("true") : sizeof("false");
176 }
177 else if (typeID == OSTypeID(OSData)) {
178 OSData * dataObj = OSDynamicCast(OSData, obj);
179 len = dataObj->getLength();
180 }
181 else {
182 len = 0;
183 }
184 return(len);
185}
186
187static void
188primitive_type_collect(struct mac_module_data_element *element, OSObject *value)
189{
190 const OSMetaClass *typeID;
191
192 typeID = OSTypeIDInst(value);
193 if (typeID == OSTypeID(OSString)) {
194 OSString *stringObj = OSDynamicCast(OSString, value);
195 element->value_type = MAC_DATA_TYPE_PRIMITIVE;
196 element->value_size = stringObj->getLength() + 1;
197 DPRINTF(("osdict: string %s size %d\n",
198 stringObj->getCStringNoCopy(), element->value_size));
199 memcpy(element->value, stringObj->getCStringNoCopy(),
200 element->value_size);
201 } else if (typeID == OSTypeID(OSNumber)) {
202 OSNumber *numberObj = OSDynamicCast(OSNumber, value);
203 element->value_type = MAC_DATA_TYPE_PRIMITIVE;
204 element->value_size = sprintf(element->value, "%u",
205 numberObj->unsigned32BitValue()) + 1;
206 } else if (typeID == OSTypeID(OSBoolean)) {
207 OSBoolean *boolObj = OSDynamicCast(OSBoolean, value);
208 element->value_type = MAC_DATA_TYPE_PRIMITIVE;
209 if (boolObj->isTrue()) {
210 strcpy(element->value, "true");
211 element->value_size = 5;
212 } else {
213 strcpy(element->value, "false");
214 element->value_size = 6;
215 }
216 } else if (typeID == OSTypeID(OSData)) {
217 OSData *dataObj = OSDynamicCast(OSData, value);
218 element->value_type = MAC_DATA_TYPE_PRIMITIVE;
219 element->value_size = dataObj->getLength();
220 DPRINTF(("osdict: data size %d\n", dataObj->getLength()));
221 memcpy(element->value, dataObj->getBytesNoCopy(),
222 element->value_size);
223 }
224}
225
226/*********************************************************************
227* This function takes an OSDictionary and returns a struct mac_module_data
228* list.
229*********************************************************************/
230struct mac_module_data *
231osdict_encode(OSDictionary *dict)
232{
233 const OSMetaClass * typeID; // don't release
234 OSString * key = NULL; // don't release
235 OSCollectionIterator * keyIterator = 0; // must release
236 struct mac_module_data * module_data = 0;
237 struct mac_module_data_element * element;
238 unsigned int strtabsize = 0;
239 unsigned int listtabsize = 0;
240 unsigned int dicttabsize = 0;
241 unsigned int nkeys = 0;
242 unsigned int datalen;
243 char *strtab = NULL;
244 char *listtab = NULL;
245 char *dicttab = NULL;
246 vm_offset_t data_addr;
247
248 keyIterator = OSCollectionIterator::withCollection(dict);
249 if (!keyIterator)
250 goto finish;
251
252 /* Iterate over OSModuleData to figure out total size */
253 while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) {
254
255 // Get the key's value and determine its type
256 OSObject * value = dict->getObject(key);
257 if (!value)
258 continue;
259
260 typeID = OSTypeIDInst(value);
261 if (primitive_type(value)) {
262 strtabsize += primitive_type_length(value);
263 }
264 else if (typeID == OSTypeID(OSArray)) {
265 unsigned int k, cnt, nents;
266 OSArray *arrayObj = OSDynamicCast(OSArray, value);
267
268 nents = 0;
269 cnt = arrayObj->getCount();
270 for (k = 0; k < cnt; k++) {
271 value = arrayObj->getObject(k);
272 typeID = OSTypeIDInst(value);
273 if (primitive_type(value)) {
274 listtabsize += primitive_type_length(value);
275 nents++;
276 }
277 else if (typeID == OSTypeID(OSDictionary)) {
278 unsigned int dents;
279 OSDictionary *dictObj;
280 OSString *dictkey;
281 OSCollectionIterator *dictIterator;
282
283 dents = 0;
284 dictObj = OSDynamicCast(OSDictionary, value);
285 dictIterator = OSCollectionIterator::withCollection(dictObj);
286 if (!dictIterator)
287 goto finish;
288 while ((dictkey = OSDynamicCast(OSString,
289 dictIterator->getNextObject()))) {
290 OSObject *dictvalue;
291
292 dictvalue = dictObj->getObject(dictkey);
293 if (!dictvalue)
294 continue;
295 if (primitive_type(dictvalue)) {
296 strtabsize += primitive_type_length(dictvalue);
297 }
298 else {
299 continue; /* Only handle primitive types here. */
300 }
301 /*
302 * Allow for the "arraynnn/" prefix in the key length.
303 */
304 strtabsize += dictkey->getLength() + 1;
305 dents++;
306 }
307 dictIterator->release();
308 if (dents-- > 0) {
309 dicttabsize += sizeof(struct mac_module_data_list) +
310 dents * sizeof(struct mac_module_data_element);
311 nents++;
312 }
313 }
314 else {
315 continue; /* Skip everything else. */
316 }
317 }
318 if (nents == 0)
319 continue;
320 listtabsize += sizeof(struct mac_module_data_list) +
321 (nents - 1) * sizeof(struct mac_module_data_element);
322 }
323 else {
324 continue; /* skip anything else */
325 }
326 strtabsize += key->getLength() + 1;
327 nkeys++;
328 }
329 if (nkeys == 0)
330 goto finish;
331
332 /*
333 * Allocate and fill in the module data structures.
334 */
335 datalen = sizeof(struct mac_module_data) +
336 sizeof(mac_module_data_element) * (nkeys - 1) +
337 strtabsize + listtabsize + dicttabsize;
338 DPRINTF(("osdict: datalen %d strtabsize %d listtabsize %d dicttabsize %d\n",
339 datalen, strtabsize, listtabsize, dicttabsize));
340 if (kmem_alloc(kernel_map, &data_addr, datalen) != KERN_SUCCESS)
341 goto finish;
342 module_data = (mac_module_data *)data_addr;
343 module_data->base_addr = data_addr;
344 module_data->size = datalen;
345 module_data->count = nkeys;
346 strtab = (char *)&module_data->data[nkeys];
347 listtab = strtab + strtabsize;
348 dicttab = listtab + listtabsize;
349 DPRINTF(("osdict: data_addr %p strtab %p listtab %p dicttab %p end %p\n",
350 data_addr, strtab, listtab, dicttab, data_addr + datalen));
351
352 keyIterator->reset();
353 nkeys = 0;
354 element = &module_data->data[0];
355 DPRINTF(("osdict: element %p\n", element));
356 while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) {
357
358 // Get the key's value and determine its type
359 OSObject * value = dict->getObject(key);
360 if (!value)
361 continue;
362
363 /* Store key */
364 DPRINTF(("osdict: element @%p\n", element));
365 element->key = strtab;
366 element->key_size = key->getLength() + 1;
367 DPRINTF(("osdict: key %s size %d @%p\n", key->getCStringNoCopy(), element->key_size, strtab));
368 memcpy(element->key, key->getCStringNoCopy(), element->key_size);
369
370 typeID = OSTypeIDInst(value);
371 if (primitive_type(value)) {
372 /* Store value */
373 element->value = element->key + element->key_size;
374 DPRINTF(("osdict: primitive element value %p\n", element->value));
375 primitive_type_collect(element, value);
376 strtab += element->key_size + element->value_size;
377 DPRINTF(("osdict: new strtab %p\n", strtab));
378 }
379 else if (typeID == OSTypeID(OSArray)) {
380 unsigned int k, cnt, nents;
381 char *astrtab;
382 struct mac_module_data_list *arrayhd;
383 struct mac_module_data_element *ele;
384 OSArray *arrayObj = OSDynamicCast(OSArray, value);
385
386 element->value = listtab;
387 DPRINTF(("osdict: array element value %p\n", element->value));
388 element->value_type = MAC_DATA_TYPE_ARRAY;
389 arrayhd = (struct mac_module_data_list *)element->value;
390 arrayhd->type = 0;
391 DPRINTF(("osdict: arrayhd %p\n", arrayhd));
392 nents = 0;
393 astrtab = strtab + element->key_size;
394 ele = &(arrayhd->list[0]);
395 cnt = arrayObj->getCount();
396 for (k = 0; k < cnt; k++) {
397 value = arrayObj->getObject(k);
398 DPRINTF(("osdict: array ele %d @%p\n", nents, ele));
399 ele->key = NULL;
400 ele->key_size = 0;
401 typeID = OSTypeIDInst(value);
402 if (primitive_type(value)) {
403 if (arrayhd->type != 0 &&
404 arrayhd->type != MAC_DATA_TYPE_PRIMITIVE)
405 continue;
406 arrayhd->type = MAC_DATA_TYPE_PRIMITIVE;
407 ele->value = astrtab;
408 primitive_type_collect(ele, value);
409 astrtab += ele->value_size;
410 DPRINTF(("osdict: array new astrtab %p\n", astrtab));
411 }
412 else if (typeID == OSTypeID(OSDictionary)) {
413 unsigned int dents;
414 char *dstrtab;
415 OSDictionary *dictObj;
416 OSString *dictkey;
417 OSCollectionIterator *dictIterator;
418 struct mac_module_data_list *dicthd;
419 struct mac_module_data_element *dele;
420
421 if (arrayhd->type != 0 &&
422 arrayhd->type != MAC_DATA_TYPE_DICT)
423 continue;
424 dictObj = OSDynamicCast(OSDictionary, value);
425 dictIterator = OSCollectionIterator::withCollection(dictObj);
426 if (!dictIterator)
427 goto finish;
428 DPRINTF(("osdict: dict\n"));
429 ele->value = dicttab;
430 ele->value_type = MAC_DATA_TYPE_DICT;
431 dicthd = (struct mac_module_data_list *)ele->value;
432 DPRINTF(("osdict: dicthd %p\n", dicthd));
433 dstrtab = astrtab;
434 dents = 0;
435 while ((dictkey = OSDynamicCast(OSString,
436 dictIterator->getNextObject()))) {
437 OSObject *dictvalue;
438
439 dictvalue = dictObj->getObject(dictkey);
440 if (!dictvalue)
441 continue;
442 dele = &(dicthd->list[dents]);
443 DPRINTF(("osdict: dict ele %d @%p\n", dents, dele));
444 if (primitive_type(dictvalue)) {
445 dele->key = dstrtab;
446 dele->key_size = dictkey->getLength() + 1;
447 DPRINTF(("osdict: dictkey %s size %d @%p\n",
448 dictkey->getCStringNoCopy(), dictkey->getLength(), dstrtab));
449 memcpy(dele->key, dictkey->getCStringNoCopy(),
450 dele->key_size);
451 dele->value = dele->key + dele->key_size;
452 primitive_type_collect(dele, dictvalue);
453 dstrtab += dele->key_size + dele->value_size;
454 DPRINTF(("osdict: dict new dstrtab %p\n", dstrtab));
455 }
456 else {
457 continue; /* Only handle primitive types here. */
458 }
459 dents++;
460 }
461 dictIterator->release();
462 if (dents == 0)
463 continue;
464 arrayhd->type = MAC_DATA_TYPE_DICT;
465 ele->value_size = sizeof(struct mac_module_data_list) +
466 (dents - 1) * sizeof(struct mac_module_data_element);
467 DPRINTF(("osdict: dict ele size %d ents %d\n", ele->value_size, dents));
468 dicttab += ele->value_size;
469 DPRINTF(("osdict: new dicttab %p\n", dicttab));
470 dicthd->count = dents;
471 astrtab = dstrtab;
472 }
473 else {
474 continue; /* Skip everything else. */
475 }
476 nents++;
477 ele++;
478 }
479 if (nents == 0)
480 continue;
481 element->value_size = sizeof(struct mac_module_data_list) +
482 (nents - 1) * sizeof(struct mac_module_data_element);
483 listtab += element->value_size;
484 DPRINTF(("osdict: new listtab %p\n", listtab));
485 arrayhd->count = nents;
486 strtab = astrtab;
487 DPRINTF(("osdict: new strtab %p\n", strtab));
488 }
489 else {
490 continue; /* skip anything else */
491 }
492 element++;
493 }
494 DPRINTF(("module_data list @%p, key %p value %p\n",
495 module_data, module_data->data[0].key, module_data->data[0].value));
496finish:
497 if (keyIterator)
498 keyIterator->release();
499 return(module_data);
500}
501
502/*********************************************************************
503* This function takes a plist and looks for an OSModuleData dictionary.
504* If it is found, an encoded copy is returned.
505*********************************************************************/
506kmod_args_t
507get_module_data(OSDictionary * kextPlist, mach_msg_type_number_t * datalen)
508{
509
510 OSDictionary * kextModuleData = 0; // don't release
511 struct mac_module_data * module_data = 0;
512 vm_map_copy_t copy = 0;
513
514 kextModuleData = OSDynamicCast(OSDictionary,
515 kextPlist->getObject("OSModuleData"));
516 if (!kextModuleData)
517 goto finish;
518
519 module_data = osdict_encode(kextModuleData);
520 if (!module_data)
521 goto finish;
522 *datalen = module_data->size;
523 /*
524 * Make a CoW copy of data and free the original. The copy is
525 * consumed by a call to vm_map_copyout() in kmod_start_or_stop().
526 */
527 vm_map_copyin(kernel_map, (vm_offset_t)module_data, *datalen, FALSE, &copy);
528 kmem_free(kernel_map, (vm_offset_t)module_data, *datalen);
529 DPRINTF(("get_module_data: copy @ %p\n", copy));
530finish:
531 return (kmod_args_t)copy;
532}
533#endif /* MAC */
534
55e303ae
A
535static
536kern_return_t start_prelink_module(UInt32 moduleIndex)
537{
538 kern_return_t kr = KERN_SUCCESS;
539 UInt32 * togo;
540 SInt32 count, where, end;
541 UInt32 * prelink;
542 SInt32 next, lastDep;
543 OSData * data;
544 OSString * str;
545 OSDictionary * dict;
546
547 OSArray *
548 prelinkedModules = gIOPrelinkedModules;
549
550 togo = IONew(UInt32, prelinkedModules->getCount());
551 togo[0] = moduleIndex;
552 count = 1;
553
554 for (next = 0; next < count; next++)
555 {
556 dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
557
558 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
559 if (!data)
560 {
561 // already started or no code
562 if (togo[next] == moduleIndex)
563 {
564 kr = KERN_FAILURE;
565 break;
566 }
567 continue;
568 }
569 prelink = (UInt32 *) data->getBytesNoCopy();
570 lastDep = OSReadBigInt32(prelink, 12);
571 for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
572 {
573 UInt32 depIdx = OSReadBigInt32(prelink, idx) - 1;
574
575 for (where = next + 1;
576 (where < count) && (togo[where] > depIdx);
577 where++) {}
578
579 if (where != count)
580 {
581 if (togo[where] == depIdx)
582 continue;
583 for (end = count; end != where; end--)
584 togo[end] = togo[end - 1];
585 }
586 count++;
587 togo[where] = depIdx;
588 }
589 }
590
591 if (KERN_SUCCESS != kr)
592 return kr;
593
594 for (next = (count - 1); next >= 0; next--)
595 {
596 dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
597
598 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
599 if (!data)
600 continue;
601 prelink = (UInt32 *) data->getBytesNoCopy();
602
603 kmod_t id;
604 kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
605
606 kr = kmod_create_internal(kmod_info, &id);
607 if (KERN_SUCCESS != kr)
608 break;
609
610 lastDep = OSReadBigInt32(prelink, 12);
611 for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
612 {
613 OSDictionary * depDict;
614 kmod_info_t * depInfo;
615
616 depDict = (OSDictionary *) prelinkedModules->getObject(OSReadBigInt32(prelink, idx) - 1);
617 str = OSDynamicCast(OSString, depDict->getObject(kModuleKey));
618 depInfo = kmod_lookupbyname_locked(str->getCStringNoCopy());
619 if (depInfo)
620 {
621 kr = kmod_retain(KMOD_PACK_IDS(id, depInfo->id));
91447636 622 kfree(depInfo, sizeof(kmod_info_t));
55e303ae
A
623 } else
624 IOLog("%s: NO DEP %s\n", kmod_info->name, str->getCStringNoCopy());
625 }
626 dict->removeObject("OSBundlePrelink");
627
628 if (kmod_info->start)
629 kr = kmod_start_or_stop(kmod_info->id, 1, 0, 0);
630 }
631
632 IODelete(togo, UInt32, prelinkedModules->getCount());
633
634 return kr;
635}
636
637/*********************************************************************
638* This is a function that IOCatalogue calls in order to load a kmod.
639*********************************************************************/
640
641static
642kern_return_t kmod_load_from_cache_sym(const OSSymbol * kmod_name)
643{
644 OSArray * prelinkedModules = gIOPrelinkedModules;
645 kern_return_t result = KERN_FAILURE;
646 OSDictionary * dict;
647 OSObject * ident;
648 UInt32 idx;
649
650 if (!gIOPrelinkedModules)
651 return KERN_FAILURE;
652
653 for (idx = 0;
654 (dict = (OSDictionary *) prelinkedModules->getObject(idx));
655 idx++)
656 {
657 if ((ident = dict->getObject(kModuleKey))
658 && kmod_name->isEqualTo(ident))
659 break;
660 }
661 if (dict)
662 {
663 if (kernelLinkerPresent && dict->getObject("OSBundleDefer"))
664 {
665 kmod_load_extension((char *) kmod_name->getCStringNoCopy());
666 result = kIOReturnOffline;
667 }
668 else
669 result = start_prelink_module(idx);
670 }
671
672 return result;
673}
674
675extern "C" Boolean kmod_load_request(const char * moduleName, Boolean make_request)
676{
677 bool ret, cacheMiss = false;
678 kern_return_t kr;
679 const OSSymbol * sym = 0;
680 kmod_info_t * kmod_info;
681
682 if (!moduleName)
683 return false;
684
685 /* To make sure this operation completes even if a bad extension needs
686 * to be removed, take the kld lock for this whole block, spanning the
687 * kmod_load_function() and remove_startup_extension_function() calls.
688 */
689 IOLockLock(gIOKLDLock);
690 do
691 {
692 // Is the module already loaded?
693 ret = (0 != (kmod_info = kmod_lookupbyname_locked((char *)moduleName)));
694 if (ret) {
91447636 695 kfree(kmod_info, sizeof(kmod_info_t));
55e303ae
A
696 break;
697 }
698 sym = OSSymbol::withCString(moduleName);
699 if (!sym) {
700 ret = false;
701 break;
702 }
703
704 kr = kmod_load_from_cache_sym(sym);
705 ret = (kIOReturnSuccess == kr);
706 cacheMiss = !ret;
707 if (ret || !make_request || (kr == kIOReturnOffline))
708 break;
709
710 // If the module hasn't been loaded, then load it.
711 if (!kmod_load_function) {
712 IOLog("IOCatalogue: %s cannot be loaded "
713 "(kmod load function not set).\n",
714 moduleName);
91447636 715 ret = true;
55e303ae
A
716 break;
717 }
718
719 kr = kmod_load_function((char *)moduleName);
720
721 if (ret != kIOReturnSuccess) {
722 IOLog("IOCatalogue: %s cannot be loaded.\n", moduleName);
723
724 /* If the extension couldn't be loaded this time,
725 * make it unavailable so that no more requests are
726 * made in vain. This also enables other matching
727 * extensions to have a chance.
728 */
729 if (kernelLinkerPresent && remove_startup_extension_function) {
730 (*remove_startup_extension_function)(moduleName);
731 }
732 ret = false;
733
734 } else if (kernelLinkerPresent) {
735 // If kern linker is here, the driver is actually loaded,
736 // so return true.
737 ret = true;
738
739 } else {
740 // kern linker isn't here, a request has been queued
741 // but the module isn't necessarily loaded yet, so stall.
742 ret = false;
743 }
744 }
745 while (false);
746
747 IOLockUnlock(gIOKLDLock);
748
749 if (sym)
750 {
751 IOLockLock(gIOCatalogLock);
752 gIOCatalogModuleRequests->setObject(sym);
753 if (cacheMiss)
754 gIOCatalogCacheMisses->setObject(sym);
755 IOLockUnlock(gIOCatalogLock);
756 }
757
758 return ret;
759}
760
761extern "C" kern_return_t kmod_unload_cache(void)
762{
763 OSArray * prelinkedModules = gIOPrelinkedModules;
764 kern_return_t result = KERN_FAILURE;
765 OSDictionary * dict;
766 UInt32 idx;
767 UInt32 * prelink;
768 OSData * data;
769
770 if (!gIOPrelinkedModules)
771 return KERN_SUCCESS;
772
773 IOLockLock(gIOKLDLock);
774 for (idx = 0;
775 (dict = (OSDictionary *) prelinkedModules->getObject(idx));
776 idx++)
777 {
778 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
779 if (!data)
780 continue;
781 prelink = (UInt32 *) data->getBytesNoCopy();
782
783 kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
784 vm_offset_t
785 virt = ml_static_ptovirt(kmod_info->address);
786 if( virt) {
787 ml_static_mfree(virt, kmod_info->size);
788 }
789 }
790
791 gIOPrelinkedModules->release();
792 gIOPrelinkedModules = 0;
793
794 IOLockUnlock(gIOKLDLock);
795
796 return result;
797}
798
799extern "C" kern_return_t kmod_load_from_cache(const char * kmod_name)
800{
801 kern_return_t kr;
802 const OSSymbol * sym = OSSymbol::withCStringNoCopy(kmod_name);
803
804 if (sym)
805 {
806 kr = kmod_load_from_cache_sym(sym);
807 sym->release();
808 }
809 else
810 kr = kIOReturnNoMemory;
811
812 return kr;
813}
814
815/*********************************************************************
816*********************************************************************/
1c79356b
A
817
818static void UniqueProperties( OSDictionary * dict )
819{
820 OSString * data;
821
822 data = OSDynamicCast( OSString, dict->getObject( gIOClassKey ));
823 if( data) {
824 const OSSymbol *classSymbol = OSSymbol::withString(data);
825
826 dict->setObject( gIOClassKey, (OSSymbol *) classSymbol);
827 classSymbol->release();
828 }
829
830 data = OSDynamicCast( OSString, dict->getObject( gIOMatchCategoryKey ));
831 if( data) {
832 const OSSymbol *classSymbol = OSSymbol::withString(data);
833
834 dict->setObject( gIOMatchCategoryKey, (OSSymbol *) classSymbol);
835 classSymbol->release();
836 }
837}
838
839void IOCatalogue::initialize( void )
840{
841 OSArray * array;
842 OSString * errorString;
843 bool rc;
844
845 extern const char * gIOKernelConfigTables;
846
847 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
848 if (!array && errorString) {
849 IOLog("KernelConfigTables syntax error: %s\n",
850 errorString->getCStringNoCopy());
851 errorString->release();
852 }
853
55e303ae
A
854 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
855 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
856 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kModuleKey );
857 gIOCatalogModuleRequests = OSSet::withCapacity(16);
858 gIOCatalogCacheMisses = OSSet::withCapacity(16);
859 gIOCatalogROMMkexts = OSSet::withCapacity(4);
860
861 assert( array && gIOClassKey && gIOProbeScoreKey
862 && gIOModuleIdentifierKey && gIOCatalogModuleRequests);
1c79356b
A
863
864 gIOCatalogue = new IOCatalogue;
865 assert(gIOCatalogue);
866 rc = gIOCatalogue->init(array);
867 assert(rc);
868 array->release();
869}
870
871// Initialize the IOCatalog object.
872bool IOCatalogue::init(OSArray * initArray)
873{
1c79356b
A
874 OSDictionary * dict;
875
876 if ( !super::init() )
877 return false;
878
879 generation = 1;
880
881 array = initArray;
882 array->retain();
883 kernelTables = OSCollectionIterator::withCollection( array );
884
55e303ae
A
885 gIOCatalogLock = IOLockAlloc();
886 gIOKLDLock = IOLockAlloc();
887
888 lock = gIOCatalogLock;
889 kld_lock = gIOKLDLock;
1c79356b
A
890
891 kernelTables->reset();
892 while( (dict = (OSDictionary *) kernelTables->getNextObject())) {
893 UniqueProperties(dict);
894 if( 0 == dict->getObject( gIOClassKey ))
895 IOLog("Missing or bad \"%s\" key\n",
896 gIOClassKey->getCStringNoCopy());
897 }
898
899#if CATALOGTEST
900 AbsoluteTime deadline;
901 clock_interval_to_deadline( 1000, kMillisecondScale );
902 thread_call_func_delayed( ping, this, deadline );
903#endif
904
1c79356b
A
905 return true;
906}
907
908// Release all resources used by IOCatalogue and deallocate.
909// This will probably never be called.
910void IOCatalogue::free( void )
911{
912 if ( array )
913 array->release();
914
915 if ( kernelTables )
916 kernelTables->release();
917
918 super::free();
919}
920
921#if CATALOGTEST
922
923static int hackLimit;
924
925enum { kDriversPerIter = 4 };
926
927void IOCatalogue::ping( thread_call_param_t arg, thread_call_param_t)
928{
929 IOCatalogue * self = (IOCatalogue *) arg;
930 OSOrderedSet * set;
931 OSDictionary * table;
932 int newLimit;
933
934 set = OSOrderedSet::withCapacity( 1 );
935
55e303ae 936 IOLockLock( &self->lock );
1c79356b
A
937
938 for( newLimit = 0; newLimit < kDriversPerIter; newLimit++) {
939 table = (OSDictionary *) self->array->getObject(
940 hackLimit + newLimit );
941 if( table) {
942 set->setLastObject( table );
943
944 OSSymbol * sym = (OSSymbol *) table->getObject( gIOClassKey );
945 kprintf("enabling %s\n", sym->getCStringNoCopy());
946
947 } else {
948 newLimit--;
949 break;
950 }
951 }
952
953 IOService::catalogNewDrivers( set );
954
955 hackLimit += newLimit;
956 self->generation++;
957
55e303ae 958 IOLockUnlock( &self->lock );
1c79356b
A
959
960 if( kDriversPerIter == newLimit) {
961 AbsoluteTime deadline;
962 clock_interval_to_deadline( 500, kMillisecondScale );
963 thread_call_func_delayed( ping, this, deadline );
964 }
965}
966#endif
967
968OSOrderedSet * IOCatalogue::findDrivers( IOService * service,
969 SInt32 * generationCount )
970{
971 OSDictionary * nextTable;
972 OSOrderedSet * set;
973 OSString * imports;
974
975 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
976 (void *)gIOProbeScoreKey );
977 if( !set )
978 return( 0 );
979
55e303ae 980 IOLockLock( lock );
1c79356b
A
981 kernelTables->reset();
982
983#if CATALOGTEST
984 int hackIndex = 0;
985#endif
986 while( (nextTable = (OSDictionary *) kernelTables->getNextObject())) {
987#if CATALOGTEST
988 if( hackIndex++ > hackLimit)
989 break;
990#endif
991 imports = OSDynamicCast( OSString,
992 nextTable->getObject( gIOProviderClassKey ));
993 if( imports && service->metaCast( imports ))
994 set->setObject( nextTable );
995 }
996
997 *generationCount = getGenerationCount();
998
55e303ae 999 IOLockUnlock( lock );
1c79356b
A
1000
1001 return( set );
1002}
1003
1004// Is personality already in the catalog?
1005OSOrderedSet * IOCatalogue::findDrivers( OSDictionary * matching,
1006 SInt32 * generationCount)
1007{
1008 OSDictionary * dict;
1009 OSOrderedSet * set;
1010
1011 UniqueProperties(matching);
1012
1013 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
1014 (void *)gIOProbeScoreKey );
1015
55e303ae 1016 IOLockLock( lock );
1c79356b
A
1017 kernelTables->reset();
1018 while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
9bccf70c
A
1019
1020 /* This comparison must be done with only the keys in the
1021 * "matching" dict to enable general searches.
1022 */
1c79356b
A
1023 if ( dict->isEqualTo(matching, matching) )
1024 set->setObject(dict);
1025 }
1026 *generationCount = getGenerationCount();
55e303ae 1027 IOLockUnlock( lock );
1c79356b
A
1028
1029 return set;
1030}
1031
1032// Add a new personality to the set if it has a unique IOResourceMatchKey value.
1033// XXX -- svail: This should be optimized.
1034// esb - There doesn't seem like any reason to do this - it causes problems
1035// esb - when there are more than one loadable driver matching on the same provider class
1036static void AddNewImports( OSOrderedSet * set, OSDictionary * dict )
1037{
1038 set->setObject(dict);
1039}
1040
1041// Add driver config tables to catalog and start matching process.
1042bool IOCatalogue::addDrivers(OSArray * drivers,
55e303ae 1043 bool doNubMatching )
1c79356b
A
1044{
1045 OSCollectionIterator * iter;
1046 OSDictionary * dict;
1047 OSOrderedSet * set;
1048 OSArray * persons;
55e303ae 1049 OSString * moduleName;
1c79356b
A
1050 bool ret;
1051
1052 ret = true;
1053 persons = OSDynamicCast(OSArray, drivers);
1054 if ( !persons )
1055 return false;
1056
1057 iter = OSCollectionIterator::withCollection( persons );
1058 if (!iter )
1059 return false;
1060
1061 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
1062 (void *)gIOProbeScoreKey );
1063 if ( !set ) {
1064 iter->release();
1065 return false;
1066 }
1067
55e303ae
A
1068 IOLockLock( lock );
1069 while ( (dict = (OSDictionary *) iter->getNextObject()) )
1070 {
1071 if ((moduleName = OSDynamicCast(OSString, dict->getObject("OSBundleModuleDemand"))))
1072 {
1073 IOLockUnlock( lock );
1074 ret = kmod_load_request(moduleName->getCStringNoCopy(), false);
1075 IOLockLock( lock );
1076 ret = true;
1077 }
1078 else
1079 {
1080 SInt count;
1081
1082 UniqueProperties( dict );
1083
1084 // Add driver personality to catalogue.
1085 count = array->getCount();
1086 while ( count-- ) {
1087 OSDictionary * driver;
1088
1089 // Be sure not to double up on personalities.
1090 driver = (OSDictionary *)array->getObject(count);
1091
1092 /* Unlike in other functions, this comparison must be exact!
1093 * The catalogue must be able to contain personalities that
1094 * are proper supersets of others.
1095 * Do not compare just the properties present in one driver
1096 * pesonality or the other.
1097 */
1098 if (dict->isEqualTo(driver))
1099 break;
1100 }
1101 if (count >= 0)
1102 // its a dup
1103 continue;
1104
1105 ret = array->setObject( dict );
1106 if (!ret)
1107 break;
1108
1109 AddNewImports( set, dict );
1110 }
1c79356b
A
1111 }
1112 // Start device matching.
55e303ae 1113 if (doNubMatching && (set->getCount() > 0)) {
1c79356b
A
1114 IOService::catalogNewDrivers( set );
1115 generation++;
1116 }
55e303ae 1117 IOLockUnlock( lock );
1c79356b 1118
1c79356b
A
1119 set->release();
1120 iter->release();
1121
1122 return ret;
1123}
1124
1125// Remove drivers from the catalog which match the
1126// properties in the matching dictionary.
1127bool IOCatalogue::removeDrivers( OSDictionary * matching,
55e303ae 1128 bool doNubMatching)
1c79356b
A
1129{
1130 OSCollectionIterator * tables;
1131 OSDictionary * dict;
1132 OSOrderedSet * set;
1133 OSArray * arrayCopy;
1134
1135 if ( !matching )
1136 return false;
1137
1138 set = OSOrderedSet::withCapacity(10,
1139 IOServiceOrdering,
1140 (void *)gIOProbeScoreKey);
1141 if ( !set )
1142 return false;
1143
1144 arrayCopy = OSArray::withCapacity(100);
1145 if ( !arrayCopy ) {
1146 set->release();
1147 return false;
1148 }
1149
1150 tables = OSCollectionIterator::withCollection(arrayCopy);
1151 arrayCopy->release();
1152 if ( !tables ) {
1153 set->release();
1154 return false;
1155 }
1156
1157 UniqueProperties( matching );
1158
55e303ae 1159 IOLockLock( lock );
1c79356b
A
1160 kernelTables->reset();
1161 arrayCopy->merge(array);
1162 array->flushCollection();
1163 tables->reset();
1164 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
9bccf70c
A
1165
1166 /* This comparison must be done with only the keys in the
1167 * "matching" dict to enable general searches.
1168 */
1c79356b
A
1169 if ( dict->isEqualTo(matching, matching) ) {
1170 AddNewImports( set, dict );
1171 continue;
1172 }
1173
1174 array->setObject(dict);
1175 }
1176 // Start device matching.
1177 if ( doNubMatching && (set->getCount() > 0) ) {
1178 IOService::catalogNewDrivers(set);
1179 generation++;
1180 }
55e303ae 1181 IOLockUnlock( lock );
1c79356b
A
1182
1183 set->release();
1184 tables->release();
1185
1186 return true;
1187}
1188
1189// Return the generation count.
1190SInt32 IOCatalogue::getGenerationCount( void ) const
1191{
1192 return( generation );
1193}
1194
1195bool IOCatalogue::isModuleLoaded( OSString * moduleName ) const
1196{
1197 return isModuleLoaded(moduleName->getCStringNoCopy());
1198}
1199
1200bool IOCatalogue::isModuleLoaded( const char * moduleName ) const
1201{
55e303ae 1202 return (kmod_load_request(moduleName, true));
1c79356b
A
1203}
1204
1205// Check to see if module has been loaded already.
1206bool IOCatalogue::isModuleLoaded( OSDictionary * driver ) const
1207{
1208 OSString * moduleName = NULL;
1209
1210 if ( !driver )
1211 return false;
1212
55e303ae 1213 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
1c79356b
A
1214 if ( moduleName )
1215 return isModuleLoaded(moduleName);
1216
1217 /* If a personality doesn't hold the "CFBundleIdentifier" key
1218 * it is assumed to be an "in-kernel" driver.
1219 */
1220 return true;
1221}
1222
1223// This function is called after a module has been loaded.
1224void IOCatalogue::moduleHasLoaded( OSString * moduleName )
1225{
1226 OSDictionary * dict;
1227
1228 dict = OSDictionary::withCapacity(2);
55e303ae 1229 dict->setObject(gIOModuleIdentifierKey, moduleName);
1c79356b
A
1230 startMatching(dict);
1231 dict->release();
1232}
1233
1234void IOCatalogue::moduleHasLoaded( const char * moduleName )
1235{
1236 OSString * name;
1237
1238 name = OSString::withCString(moduleName);
1239 moduleHasLoaded(name);
1240 name->release();
1241}
1242
1243IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const
1244{
9bccf70c 1245 kmod_info_t * k_info = 0;
1c79356b
A
1246 kern_return_t ret;
1247 const char * name;
1248
1249 ret = kIOReturnBadArgument;
1250 if ( moduleName ) {
1251 name = moduleName->getCStringNoCopy();
9bccf70c 1252 k_info = kmod_lookupbyname_locked((char *)name);
1c79356b 1253 if ( k_info && (k_info->reference_count < 1) ) {
c910b4d9 1254 record_kext_unload(k_info->id);
1c79356b 1255 if ( k_info->stop &&
9bccf70c
A
1256 !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) {
1257
91447636 1258 kfree(k_info, sizeof(kmod_info_t));
1c79356b 1259 return ret;
9bccf70c 1260 }
1c79356b
A
1261
1262 ret = kmod_destroy(host_priv_self(), k_info->id);
1263 }
1264 }
9bccf70c
A
1265
1266 if (k_info) {
91447636 1267 kfree(k_info, sizeof(kmod_info_t));
9bccf70c 1268 }
1c79356b
A
1269
1270 return ret;
1271}
1272
91447636 1273static IOReturn _terminateDrivers( OSDictionary * matching )
1c79356b 1274{
1c79356b
A
1275 OSDictionary * dict;
1276 OSIterator * iter;
1c79356b
A
1277 IOService * service;
1278 IOReturn ret;
1279
1280 if ( !matching )
1281 return kIOReturnBadArgument;
1282
1283 ret = kIOReturnSuccess;
1284 dict = 0;
1285 iter = IORegistryIterator::iterateOver(gIOServicePlane,
1286 kIORegistryIterateRecursively);
1287 if ( !iter )
1288 return kIOReturnNoMemory;
1289
1290 UniqueProperties( matching );
1291
1c79356b
A
1292 // terminate instances.
1293 do {
1294 iter->reset();
1295 while( (service = (IOService *)iter->getNextObject()) ) {
1296 dict = service->getPropertyTable();
1297 if ( !dict )
1298 continue;
1299
9bccf70c
A
1300 /* Terminate only for personalities that match the matching dictionary.
1301 * This comparison must be done with only the keys in the
1302 * "matching" dict to enable general matching.
1303 */
1c79356b
A
1304 if ( !dict->isEqualTo(matching, matching) )
1305 continue;
1306
1307 if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
1308 ret = kIOReturnUnsupported;
1309 break;
1310 }
1311 }
1312 } while( !service && !iter->isValid());
1313 iter->release();
1314
91447636
A
1315 return ret;
1316}
1317
1318static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
1319{
1320 OSCollectionIterator * tables;
1321 OSDictionary * dict;
1322 OSArray * arrayCopy;
1323 IOReturn ret = kIOReturnSuccess;
1324
1c79356b 1325 // remove configs from catalog.
1c79356b
A
1326
1327 arrayCopy = OSArray::withCapacity(100);
1328 if ( !arrayCopy )
1329 return kIOReturnNoMemory;
1330
1331 tables = OSCollectionIterator::withCollection(arrayCopy);
1332 arrayCopy->release();
1333 if ( !tables )
1334 return kIOReturnNoMemory;
1335
1336 arrayCopy->merge(array);
1337 array->flushCollection();
1338 tables->reset();
1339 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
9bccf70c
A
1340
1341 /* Remove from the catalogue's array any personalities
1342 * that match the matching dictionary.
1343 * This comparison must be done with only the keys in the
1344 * "matching" dict to enable general matching.
1345 */
1c79356b
A
1346 if ( dict->isEqualTo(matching, matching) )
1347 continue;
1348
1349 array->setObject(dict);
1350 }
1351
1352 tables->release();
1353
1354 return ret;
1355}
1356
1357IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching )
1358{
1359 IOReturn ret;
1360
91447636 1361 ret = _terminateDrivers(matching);
55e303ae 1362 IOLockLock( lock );
91447636
A
1363 if (kIOReturnSuccess == ret)
1364 ret = _removeDrivers(array, matching);
1c79356b 1365 kernelTables->reset();
55e303ae 1366 IOLockUnlock( lock );
1c79356b
A
1367
1368 return ret;
1369}
1370
1371IOReturn IOCatalogue::terminateDriversForModule(
1372 OSString * moduleName,
1373 bool unload )
1374{
1375 IOReturn ret;
1376 OSDictionary * dict;
1377
1378 dict = OSDictionary::withCapacity(1);
1379 if ( !dict )
1380 return kIOReturnNoMemory;
1381
55e303ae 1382 dict->setObject(gIOModuleIdentifierKey, moduleName);
9bccf70c 1383
91447636 1384 ret = _terminateDrivers(dict);
55e303ae 1385 IOLockLock( lock );
91447636
A
1386 if (kIOReturnSuccess == ret)
1387 ret = _removeDrivers(array, dict);
1c79356b
A
1388 kernelTables->reset();
1389
1390 // Unload the module itself.
1391 if ( unload && ret == kIOReturnSuccess ) {
1392 // Do kmod stop first.
1393 ret = unloadModule(moduleName);
1394 }
1395
55e303ae 1396 IOLockUnlock( lock );
1c79356b
A
1397
1398 dict->release();
1399
1400 return ret;
1401}
1402
1403IOReturn IOCatalogue::terminateDriversForModule(
1404 const char * moduleName,
1405 bool unload )
1406{
1407 OSString * name;
1408 IOReturn ret;
1409
1410 name = OSString::withCString(moduleName);
1411 if ( !name )
1412 return kIOReturnNoMemory;
1413
1414 ret = terminateDriversForModule(name, unload);
1415 name->release();
9bccf70c 1416
1c79356b
A
1417 return ret;
1418}
1419
1420bool IOCatalogue::startMatching( OSDictionary * matching )
1421{
1422 OSDictionary * dict;
1423 OSOrderedSet * set;
1424
1425 if ( !matching )
1426 return false;
1427
1428 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
1429 (void *)gIOProbeScoreKey);
1430 if ( !set )
1431 return false;
1432
55e303ae 1433 IOLockLock( lock );
1c79356b
A
1434 kernelTables->reset();
1435
1436 while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
9bccf70c
A
1437
1438 /* This comparison must be done with only the keys in the
1439 * "matching" dict to enable general matching.
1440 */
1c79356b
A
1441 if ( dict->isEqualTo(matching, matching) )
1442 AddNewImports(set, dict);
1443 }
1444 // Start device matching.
1445 if ( set->getCount() > 0 ) {
1446 IOService::catalogNewDrivers(set);
1447 generation++;
1448 }
1449
55e303ae 1450 IOLockUnlock( lock );
1c79356b
A
1451
1452 set->release();
1453
1454 return true;
1455}
1456
1457void IOCatalogue::reset(void)
1458{
1c79356b 1459 IOLog("Resetting IOCatalogue.\n");
1c79356b
A
1460}
1461
1462bool IOCatalogue::serialize(OSSerialize * s) const
1463{
1c79356b
A
1464 if ( !s )
1465 return false;
1466
91447636 1467 return super::serialize(s);
1c79356b
A
1468}
1469
55e303ae
A
1470bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
1471{
1472 kern_return_t kr = kIOReturnSuccess;
1473
1474 switch ( kind )
1475 {
1476 case kIOCatalogGetContents:
2d21ac55 1477 if (!array->serialize(s))
55e303ae
A
1478 kr = kIOReturnNoMemory;
1479 break;
1480
1481 case kIOCatalogGetModuleDemandList:
1482 IOLockLock( lock );
1483 if (!gIOCatalogModuleRequests->serialize(s))
1484 kr = kIOReturnNoMemory;
1485 IOLockUnlock( lock );
1486 break;
1487
1488 case kIOCatalogGetCacheMissList:
1489 IOLockLock( lock );
1490 if (!gIOCatalogCacheMisses->serialize(s))
1491 kr = kIOReturnNoMemory;
1492 IOLockUnlock( lock );
1493 break;
1494
1495 case kIOCatalogGetROMMkextList:
1496 IOLockLock( lock );
1497
1498 if (!gIOCatalogROMMkexts || !gIOCatalogROMMkexts->getCount())
1499 kr = kIOReturnNoResources;
1500 else if (!gIOCatalogROMMkexts->serialize(s))
1501 kr = kIOReturnNoMemory;
1502
1503 if (gIOCatalogROMMkexts)
1504 {
1505 gIOCatalogROMMkexts->release();
1506 gIOCatalogROMMkexts = 0;
1507 }
1508
1509 IOLockUnlock( lock );
1510 break;
1511
1512 default:
1513 kr = kIOReturnBadArgument;
1514 break;
1515 }
1516
1517 return kr;
1518}
1519
1c79356b
A
1520
1521bool IOCatalogue::recordStartupExtensions(void) {
1522 bool result = false;
1523
0b4e3aa0
A
1524 IOLockLock(kld_lock);
1525 if (kernelLinkerPresent && record_startup_extensions_function) {
1c79356b
A
1526 result = (*record_startup_extensions_function)();
1527 } else {
1528 IOLog("Can't record startup extensions; "
1529 "kernel linker is not present.\n");
1530 result = false;
1531 }
0b4e3aa0 1532 IOLockUnlock(kld_lock);
1c79356b
A
1533
1534 return result;
1535}
1536
1537
1538/*********************************************************************
91447636
A
1539* This function operates on sections retrieved from the currently running
1540* 32 bit mach kernel.
1c79356b 1541*********************************************************************/
55e303ae
A
1542bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
1543{
1544 OSData * copyData;
1c79356b 1545 bool result = false;
55e303ae 1546 bool prelinked;
1c79356b 1547
55e303ae
A
1548 /* The mkext we've been handed (or the data it references) can go away,
1549 * so we need to make a local copy to keep around as long as it might
1550 * be needed.
1551 */
1552 copyData = OSData::withData(mkext);
1553 if (copyData)
1554 {
1555 struct section * infosect;
1556
1557 infosect = getsectbyname("__PRELINK", "__info");
1558 prelinked = (infosect && infosect->addr && infosect->size);
1559
1560 IOLockLock(kld_lock);
1561
1562 if (gIOCatalogROMMkexts)
1563 gIOCatalogROMMkexts->setObject(copyData);
1564
1565 if (prelinked) {
1566 result = true;
1567 } else if (kernelLinkerPresent && add_from_mkext_function) {
1568 result = (*add_from_mkext_function)(copyData);
1569 } else {
1570 IOLog("Can't add startup extensions from archive; "
1571 "kernel linker is not present.\n");
1572 result = false;
1573 }
1574
1575 IOLockUnlock(kld_lock);
1576
1577 copyData->release();
1c79356b
A
1578 }
1579
1580 return result;
1581}
1582
1c79356b
A
1583/*********************************************************************
1584* This function clears out all references to the in-kernel linker,
1585* frees the list of startup extensions in extensionDict, and
1586* deallocates the kernel's __KLD segment to reclaim that memory.
91447636
A
1587*
1588* The segments it operates on are strictly 32 bit segments.
1c79356b
A
1589*********************************************************************/
1590kern_return_t IOCatalogue::removeKernelLinker(void) {
1591 kern_return_t result = KERN_SUCCESS;
0c530ab8
A
1592 struct segment_command * segmentLE, *segmentKLD;
1593 boolean_t keepsyms = FALSE;
2d21ac55 1594#if __ppc__ || __arm__
1c79356b
A
1595 char * dt_segment_name;
1596 void * segment_paddress;
1597 int segment_size;
0c530ab8 1598#endif
1c79356b
A
1599
1600 /* This must be the very first thing done by this function.
1601 */
0b4e3aa0 1602 IOLockLock(kld_lock);
1c79356b
A
1603
1604
1605 /* If the kernel linker isn't here, that's automatically
1606 * a success.
1607 */
1608 if (!kernelLinkerPresent) {
1609 result = KERN_SUCCESS;
1610 goto finish;
1611 }
1612
593a1d5f 1613 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms));
0c530ab8 1614
1c79356b
A
1615 IOLog("Jettisoning kernel linker.\n");
1616
1617 kernelLinkerPresent = 0;
1618
1619 /* Set the kmod_load_extension function as the means for loading
1620 * a kernel extension.
1621 */
1622 kmod_load_function = &kmod_load_extension;
1623
1624 record_startup_extensions_function = 0;
1625 add_from_mkext_function = 0;
1626 remove_startup_extension_function = 0;
1627
1628
1629 /* Invoke destructors for the __KLD and __LINKEDIT segments.
1630 * Do this for all segments before actually freeing their
1631 * memory so that any cross-dependencies (not that there
1632 * should be any) are handled.
1633 */
0c530ab8
A
1634 segmentKLD = getsegbyname("__KLD");
1635 if (!segmentKLD) {
2d21ac55 1636 IOLog("error removing kernel linker: can't find __KLD segment\n");
1c79356b
A
1637 result = KERN_FAILURE;
1638 goto finish;
1639 }
0c530ab8 1640 OSRuntimeUnloadCPPForSegment(segmentKLD);
1c79356b 1641
2d21ac55 1642#if __ppc__ || __arm__
1c79356b
A
1643 /* Free the memory that was set up by bootx.
1644 */
1645 dt_segment_name = "Kernel-__KLD";
1646 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1647 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1648 (int)segment_size);
1649 }
0c530ab8
A
1650#elif __i386__
1651 /* On x86, use the mapping data from the segment load command to
2d21ac55
A
1652 * unload KLD directly, unless the keepsyms boot-arg was enabled.
1653 * This may invalidate any assumptions about "avail_start"
1654 * defining the lower bound for valid physical addresses.
0c530ab8
A
1655 */
1656 if (!keepsyms && segmentKLD->vmaddr && segmentKLD->vmsize)
1657 ml_static_mfree(segmentKLD->vmaddr, segmentKLD->vmsize);
1658#else
1659#error arch
0c530ab8 1660#endif
1c79356b 1661
55e303ae
A
1662 struct section * sect;
1663 sect = getsectbyname("__PRELINK", "__symtab");
2d21ac55
A
1664 if (sect && sect->addr) {
1665 ml_static_mfree(sect->addr, sect->size);
55e303ae 1666 }
1c79356b
A
1667
1668finish:
1669
1670 /* This must be the very last thing done before returning.
1671 */
0b4e3aa0 1672 IOLockUnlock(kld_lock);
1c79356b
A
1673
1674 return result;
1675}
91447636
A
1676
1677/*********************************************************************
1678* This function stops the catalogue from making kextd requests during
1679* shutdown.
1680*********************************************************************/
1681void IOCatalogue::disableExternalLinker(void) {
1682 IOLockLock(gIOKLDLock);
1683 /* If kmod_load_extension (the kextd requester function) is in use,
1684 * disable new module requests.
1685 */
1686 if (kmod_load_function == &kmod_load_extension) {
1687 kmod_load_function = NULL;
1688 }
1689
1690 IOLockUnlock(gIOKLDLock);
1691}
1692
2d21ac55
A
1693extern "C"
1694void jettison_kernel_linker(void)
1695{
1696 if (gIOCatalogue != NULL)
1697 gIOCatalogue->removeKernelLinker();
1698}