]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOCatalogue.cpp
xnu-7195.101.1.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
CommitLineData
1c79356b 1/*
39236c6e 2 * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 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.
0a7de745 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.
0a7de745 17 *
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
0a7de745 29 * Copyright (c) 1998 Apple Inc. All rights reserved.
1c79356b
A
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 40
f427ee49
A
41#define IOKIT_ENABLE_SHARED_PTR
42
1c79356b
A
43extern "C" {
44#include <machine/machine_routines.h>
b0d623f7 45#include <libkern/kernel_mach_header.h>
9bccf70c 46#include <kern/host.h>
2d21ac55 47#include <security/mac_data.h>
1c79356b
A
48};
49
b0d623f7
A
50#include <libkern/c++/OSContainers.h>
51#include <libkern/c++/OSUnserialize.h>
52#include <libkern/c++/OSKext.h>
f427ee49 53#include <libkern/c++/OSSharedPtr.h>
b0d623f7 54#include <libkern/OSKextLibPrivate.h>
316670eb 55#include <libkern/OSDebug.h>
1c79356b 56
b0d623f7
A
57#include <IOKit/IODeviceTreeSupport.h>
58#include <IOKit/IOService.h>
59#include <IOKit/IOCatalogue.h>
1c79356b 60
b0d623f7
A
61#include <IOKit/IOLib.h>
62#include <IOKit/assert.h>
f427ee49 63#include <IOKit/IOKitKeysPrivate.h>
1c79356b 64
b0d623f7
A
65#if PRAGMA_MARK
66#pragma mark Internal Declarations
67#endif
68/*********************************************************************
69*********************************************************************/
1c79356b 70
f427ee49
A
71OSSharedPtr<IOCatalogue> gIOCatalogue;
72OSSharedPtr<const OSSymbol> gIOClassKey;
73OSSharedPtr<const OSSymbol> gIOProbeScoreKey;
74OSSharedPtr<const OSSymbol> gIOModuleIdentifierKey;
75OSSharedPtr<const OSSymbol> gIOModuleIdentifierKernelKey;
c3c9b80d 76OSSharedPtr<const OSSymbol> gIOHIDInterfaceClassName;
cb323159 77IORWLock * gIOCatalogLock;
55e303ae 78
b0d623f7
A
79#if PRAGMA_MARK
80#pragma mark Utility functions
2d21ac55 81#endif
55e303ae 82
b0d623f7
A
83#if PRAGMA_MARK
84#pragma mark IOCatalogue class implementation
85#endif
55e303ae 86/*********************************************************************
55e303ae
A
87*********************************************************************/
88
b0d623f7
A
89#define super OSObject
90OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
55e303ae 91
fe8ab488 92static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
0a7de745 93 OSDictionary *theModuleDict);
fe8ab488
A
94
95
55e303ae
A
96/*********************************************************************
97*********************************************************************/
0a7de745
A
98void
99IOCatalogue::initialize(void)
1c79356b 100{
f427ee49
A
101 OSSharedPtr<OSArray> array;
102 OSSharedPtr<OSString> errorString;
0a7de745 103 bool rc;
1c79356b 104
0a7de745 105 extern const char * gIOKernelConfigTables;
1c79356b 106
f427ee49 107 array = OSDynamicPtrCast<OSArray>(OSUnserialize(gIOKernelConfigTables, errorString));
0a7de745
A
108 if (!array && errorString) {
109 IOLog("KernelConfigTables syntax error: %s\n",
110 errorString->getCStringNoCopy());
0a7de745 111 }
1c79356b 112
cb323159
A
113 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
114 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
115 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey );
116 gIOModuleIdentifierKernelKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKernelKey );
c3c9b80d 117 gIOHIDInterfaceClassName = OSSymbol::withCStringNoCopy( "IOHIDInterface" );
cb323159 118
55e303ae 119
0a7de745 120 assert( array && gIOClassKey && gIOProbeScoreKey
b0d623f7 121 && gIOModuleIdentifierKey);
1c79356b 122
f427ee49 123 gIOCatalogue = OSMakeShared<IOCatalogue>();
0a7de745 124 assert(gIOCatalogue);
f427ee49 125 rc = gIOCatalogue->init(array.get());
0a7de745 126 assert(rc);
1c79356b
A
127}
128
316670eb
A
129/*********************************************************************
130* Initialize the IOCatalog object.
131*********************************************************************/
0a7de745
A
132OSArray *
133IOCatalogue::arrayForPersonality(OSDictionary * dict)
316670eb 134{
0a7de745 135 const OSSymbol * sym;
316670eb 136
0a7de745
A
137 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
138 if (!sym) {
cb323159 139 return NULL;
0a7de745 140 }
316670eb 141
0a7de745 142 return (OSArray *) personalities->getObject(sym);
316670eb
A
143}
144
0a7de745
A
145void
146IOCatalogue::addPersonality(OSDictionary * dict)
316670eb 147{
0a7de745
A
148 const OSSymbol * sym;
149 OSArray * arr;
150
151 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
152 if (!sym) {
153 return;
154 }
155 arr = (OSArray *) personalities->getObject(sym);
156 if (arr) {
157 arr->setObject(dict);
158 } else {
f427ee49
A
159 OSSharedPtr<OSArray> sharedArr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
160 personalities->setObject(sym, sharedArr.get());
0a7de745 161 }
316670eb
A
162}
163
b0d623f7
A
164/*********************************************************************
165* Initialize the IOCatalog object.
166*********************************************************************/
0a7de745
A
167bool
168IOCatalogue::init(OSArray * initArray)
1c79356b 169{
0a7de745
A
170 OSDictionary * dict;
171 OSObject * obj;
172
173 if (!super::init()) {
174 return false;
175 }
176
177 generation = 1;
178
179 personalities = OSDictionary::withCapacity(32);
180 personalities->setOptions(OSCollection::kSort, OSCollection::kSort);
181 for (unsigned int idx = 0; (obj = initArray->getObject(idx)); idx++) {
182 dict = OSDynamicCast(OSDictionary, obj);
183 if (!dict) {
184 continue;
185 }
186 OSKext::uniquePersonalityProperties(dict);
f427ee49 187 if (NULL == dict->getObject( gIOClassKey.get())) {
0a7de745
A
188 IOLog("Missing or bad \"%s\" key\n",
189 gIOClassKey->getCStringNoCopy());
190 continue;
191 }
192 dict->setObject("KernelConfigTable", kOSBooleanTrue);
193 addPersonality(dict);
194 }
195
196 gIOCatalogLock = IORWLockAlloc();
197 lock = gIOCatalogLock;
198
199 return true;
1c79356b
A
200}
201
b0d623f7
A
202/*********************************************************************
203* Release all resources used by IOCatalogue and deallocate.
204* This will probably never be called.
205*********************************************************************/
0a7de745
A
206void
207IOCatalogue::free( void )
1c79356b 208{
0a7de745 209 panic("");
1c79356b 210}
1c79356b 211
b0d623f7
A
212/*********************************************************************
213*********************************************************************/
f427ee49 214OSPtr<OSOrderedSet>
b0d623f7 215IOCatalogue::findDrivers(
0a7de745
A
216 IOService * service,
217 SInt32 * generationCount)
1c79356b 218{
0a7de745 219 OSDictionary * nextTable;
f427ee49 220 OSSharedPtr<OSOrderedSet> set;
0a7de745
A
221 OSArray * array;
222 const OSMetaClass * meta;
223 unsigned int idx;
224
225 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
f427ee49 226 (void *)(gIOProbeScoreKey.get()));
0a7de745 227 if (!set) {
cb323159 228 return NULL;
0a7de745 229 }
1c79356b 230
0a7de745 231 IORWLockRead(lock);
1c79356b 232
0a7de745
A
233 meta = service->getMetaClass();
234 while (meta) {
235 array = (OSArray *) personalities->getObject(meta->getClassNameSymbol());
236 if (array) {
237 for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++) {
238 set->setObject(nextTable);
239 }
240 }
241 if (meta == &IOService::gMetaClass) {
242 break;
243 }
244 meta = meta->getSuperClass();
316670eb 245 }
1c79356b 246
0a7de745 247 *generationCount = getGenerationCount();
1c79356b 248
0a7de745 249 IORWLockUnlock(lock);
1c79356b 250
0a7de745 251 return set;
1c79356b
A
252}
253
b0d623f7
A
254/*********************************************************************
255* Is personality already in the catalog?
256*********************************************************************/
f427ee49 257OSPtr<OSOrderedSet>
b0d623f7 258IOCatalogue::findDrivers(
0a7de745
A
259 OSDictionary * matching,
260 SInt32 * generationCount)
1c79356b 261{
f427ee49 262 OSSharedPtr<OSCollectionIterator> iter;
0a7de745 263 OSDictionary * dict;
f427ee49 264 OSSharedPtr<OSOrderedSet> set;
0a7de745
A
265 OSArray * array;
266 const OSSymbol * key;
267 unsigned int idx;
268
269 OSKext::uniquePersonalityProperties(matching);
270
271 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
f427ee49 272 (void *)(gIOProbeScoreKey.get()));
0a7de745 273 if (!set) {
cb323159 274 return NULL;
0a7de745 275 }
f427ee49 276 iter = OSCollectionIterator::withCollection(personalities.get());
0a7de745 277 if (!iter) {
f427ee49 278 return nullptr;
0a7de745
A
279 }
280
281 IORWLockRead(lock);
282 while ((key = (const OSSymbol *) iter->getNextObject())) {
283 array = (OSArray *) personalities->getObject(key);
284 if (array) {
285 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
286 /* This comparison must be done with only the keys in the
287 * "matching" dict to enable general searches.
288 */
289 if (dict->isEqualTo(matching, matching)) {
290 set->setObject(dict);
291 }
292 }
293 }
294 }
295 *generationCount = getGenerationCount();
296 IORWLockUnlock(lock);
297
0a7de745 298 return set;
1c79356b
A
299}
300
b0d623f7
A
301/*********************************************************************
302* Add driver config tables to catalog and start matching process.
303*
304* Important that existing personalities are kept (not replaced)
305* if duplicates found. Personalities can come from OSKext objects
306* or from userland kext library. We want to minimize distinct
307* copies between OSKext & IOCatalogue.
308*
309* xxx - userlib used to refuse to send personalities with IOKitDebug
310* xxx - during safe boot. That would be better implemented here.
311*********************************************************************/
316670eb 312
0a7de745
A
313bool
314IOCatalogue::addDrivers(
315 OSArray * drivers,
316 bool doNubMatching)
1c79356b 317{
0a7de745 318 bool result = false;
f427ee49
A
319 OSSharedPtr<OSOrderedSet> set;
320 OSSharedPtr<OSCollectionIterator> iter;
0a7de745
A
321 OSObject * object = NULL; // do not release
322 OSArray * persons = NULL;// do not release
323
324 persons = OSDynamicCast(OSArray, drivers);
325 if (!persons) {
326 goto finish;
327 }
328
329 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
f427ee49 330 (void *)(gIOProbeScoreKey.get()));
0a7de745
A
331 if (!set) {
332 goto finish;
333 }
334
335 iter = OSCollectionIterator::withCollection(persons);
336 if (!iter) {
337 goto finish;
338 }
339
340 /* Start with success; clear it on an error.
341 */
342 result = true;
343
344 IORWLockWrite(lock);
345 while ((object = iter->getNextObject())) {
346 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
347
348 OSDictionary * personality = OSDynamicCast(OSDictionary, object);
349
350 SInt count;
351
352 if (!personality) {
353 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
354 result = false;
355 break;
316670eb 356 }
0a7de745
A
357
358 OSKext::uniquePersonalityProperties(personality);
359
360 // Add driver personality to catalogue.
361
362 OSArray * array = arrayForPersonality(personality);
363 if (!array) {
364 addPersonality(personality);
365 } else {
366 count = array->getCount();
367 while (count--) {
368 OSDictionary * driver;
369
370 // Be sure not to double up on personalities.
371 driver = (OSDictionary *)array->getObject(count);
372
373 /* Unlike in other functions, this comparison must be exact!
374 * The catalogue must be able to contain personalities that
375 * are proper supersets of others.
376 * Do not compare just the properties present in one driver
377 * personality or the other.
378 */
379 if (personality->isEqualTo(driver)) {
380 break;
381 }
382 }
383 if (count >= 0) {
384 // its a dup
385 continue;
386 }
387 result = array->setObject(personality);
388 if (!result) {
389 break;
390 }
391 }
392
393 set->setObject(personality);
394 }
395 // Start device matching.
396 if (result && doNubMatching && (set->getCount() > 0)) {
f427ee49 397 IOService::catalogNewDrivers(set.get());
0a7de745
A
398 generation++;
399 }
400 IORWLockUnlock(lock);
1c79356b 401
b0d623f7 402finish:
b0d623f7 403
0a7de745 404 return result;
1c79356b
A
405}
406
b0d623f7 407bool
f427ee49 408IOCatalogue::removeDrivers(bool doNubMatching, bool (^shouldRemove)(OSDictionary *personality))
1c79356b 409{
f427ee49
A
410 OSSharedPtr<OSOrderedSet> set;
411 OSSharedPtr<OSCollectionIterator> iter;
0a7de745
A
412 OSDictionary * dict;
413 OSArray * array;
414 const OSSymbol * key;
415 unsigned int idx;
416
0a7de745
A
417 set = OSOrderedSet::withCapacity(10,
418 IOServiceOrdering,
f427ee49 419 (void *)(gIOProbeScoreKey.get()));
0a7de745
A
420 if (!set) {
421 return false;
422 }
f427ee49 423 iter = OSCollectionIterator::withCollection(personalities.get());
0a7de745 424 if (!iter) {
0a7de745
A
425 return false;
426 }
427
428 IORWLockWrite(lock);
429 while ((key = (const OSSymbol *) iter->getNextObject())) {
430 array = (OSArray *) personalities->getObject(key);
431 if (array) {
432 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
f427ee49 433 if (shouldRemove(dict)) {
0a7de745
A
434 set->setObject(dict);
435 array->removeObject(idx);
436 idx--;
437 }
438 }
439 }
440 // Start device matching.
441 if (doNubMatching && (set->getCount() > 0)) {
f427ee49 442 IOService::catalogNewDrivers(set.get());
0a7de745
A
443 generation++;
444 }
445 }
446 IORWLockUnlock(lock);
447
0a7de745 448 return true;
1c79356b
A
449}
450
f427ee49
A
451/*********************************************************************
452* Remove drivers from the catalog which match the
453* properties in the matching dictionary.
454*********************************************************************/
455bool
456IOCatalogue::removeDrivers(
457 OSDictionary * matching,
458 bool doNubMatching)
459{
460 if (!matching) {
461 return false;
462 }
463 return removeDrivers(doNubMatching, ^(OSDictionary *dict) {
464 /* This comparison must be done with only the keys in the
465 * "matching" dict to enable general searches.
466 */
467 return dict->isEqualTo(matching, matching);
468 });
469}
470
1c79356b 471// Return the generation count.
0a7de745
A
472SInt32
473IOCatalogue::getGenerationCount(void) const
1c79356b 474{
0a7de745 475 return generation;
1c79356b
A
476}
477
cb323159 478// Check to see if kernel module has been loaded already, and request its load.
0a7de745 479bool
cb323159 480IOCatalogue::isModuleLoaded(OSDictionary * driver, OSObject ** kextRef) const
1c79356b 481{
cb323159
A
482 OSString * moduleName = NULL;
483 OSString * publisherName = NULL;
484 OSReturn ret;
1c79356b 485
cb323159
A
486 if (kextRef) {
487 *kextRef = NULL;
0a7de745 488 }
0a7de745
A
489 if (!driver) {
490 return false;
491 }
492
493 /* The personalities of codeless kexts often contain the bundle ID of the
494 * kext they reference, and not the bundle ID of the codeless kext itself.
495 * The prelinked kernel needs to know the bundle ID of the codeless kext
496 * so it can include these personalities, so OSKext stores that bundle ID
497 * in the IOPersonalityPublisher key, and we record it as requested here.
498 */
499 publisherName = OSDynamicCast(OSString,
500 driver->getObject(kIOPersonalityPublisherKey));
501 OSKext::recordIdentifierRequest(publisherName);
502
f427ee49 503 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKernelKey.get()));
0a7de745 504 if (moduleName) {
cb323159
A
505 ret = OSKext::loadKextWithIdentifier(moduleName, kextRef);
506 if (kOSKextReturnDeferred == ret) {
507 // a request has been queued but the module isn't necessarily
508 // loaded yet, so stall.
509 return false;
510 }
f427ee49 511 OSString *moduleDextName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey.get()));
cb323159 512 if (moduleDextName && !(moduleName->isEqualTo(moduleDextName))) {
f427ee49
A
513 OSSharedPtr<OSObject> dextRef;
514 ret = OSKext::loadKextWithIdentifier(moduleDextName, dextRef);
cb323159
A
515 }
516 // module is present or never will be
517 return true;
0a7de745
A
518 }
519
cb323159 520 /* If a personality doesn't hold the "CFBundleIdentifier" or "CFBundleIdentifierKernel" key
0a7de745
A
521 * it is assumed to be an "in-kernel" driver.
522 */
523 return true;
1c79356b
A
524}
525
f427ee49
A
526bool
527IOCatalogue::isModuleLoaded(OSDictionary * driver, OSSharedPtr<OSObject>& kextRef) const
528{
529 OSObject* kextRefRaw = NULL;
530 bool result = isModuleLoaded(driver, &kextRefRaw);
531 kextRef.reset(kextRefRaw, OSNoRetain);
532 return result;
533}
534
b0d623f7
A
535/* This function is called after a module has been loaded.
536 * Is invoked from user client call, ultimately from IOKitLib's
537 * IOCatalogueModuleLoaded(). Sent from kextd.
538 */
0a7de745 539void
cb323159 540IOCatalogue::moduleHasLoaded(const OSSymbol * moduleName)
1c79356b 541{
cb323159 542 startMatching(moduleName);
b0d623f7 543
0a7de745
A
544 (void) OSKext::setDeferredLoadSucceeded();
545 (void) OSKext::considerRebuildOfPrelinkedKernel();
1c79356b
A
546}
547
0a7de745
A
548void
549IOCatalogue::moduleHasLoaded(const char * moduleName)
1c79356b 550{
f427ee49 551 OSSharedPtr<const OSSymbol> name;
1c79356b 552
cb323159 553 name = OSSymbol::withCString(moduleName);
f427ee49 554 moduleHasLoaded(name.get());
1c79356b
A
555}
556
b0d623f7 557// xxx - return is really OSReturn/kern_return_t
0a7de745
A
558IOReturn
559IOCatalogue::unloadModule(OSString * moduleName) const
1c79356b 560{
0a7de745 561 return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
1c79356b
A
562}
563
0a7de745 564IOReturn
ea3f0419 565IOCatalogue::terminateDrivers(OSDictionary * matching, io_name_t className)
1c79356b 566{
0a7de745 567 OSDictionary * dict;
f427ee49 568 OSSharedPtr<OSIterator> iter;
0a7de745
A
569 IOService * service;
570 IOReturn ret;
571
0a7de745 572 ret = kIOReturnSuccess;
cb323159 573 dict = NULL;
0a7de745
A
574 iter = IORegistryIterator::iterateOver(gIOServicePlane,
575 kIORegistryIterateRecursively);
576 if (!iter) {
577 return kIOReturnNoMemory;
578 }
579
ea3f0419 580 if (matching) {
f427ee49 581 OSKext::uniquePersonalityProperties( matching, false );
ea3f0419 582 }
0a7de745
A
583
584 // terminate instances.
585 do {
586 iter->reset();
587 while ((service = (IOService *)iter->getNextObject())) {
ea3f0419 588 if (className && !service->metaCast(className)) {
0a7de745
A
589 continue;
590 }
ea3f0419
A
591 if (matching) {
592 /* Terminate only for personalities that match the matching dictionary.
593 * This comparison must be done with only the keys in the
594 * "matching" dict to enable general matching.
595 */
596 dict = service->getPropertyTable();
597 if (!dict) {
598 continue;
599 }
600 if (!dict->isEqualTo(matching, matching)) {
601 continue;
602 }
0a7de745
A
603 }
604
ea3f0419 605 OSKext * kext;
f427ee49 606 OSSharedPtr<OSString> dextBundleID;
ea3f0419
A
607 const char * bundleIDStr;
608 OSObject * prop;
609 bool okToTerminate;
f427ee49 610 bool isDext = service->hasUserServer();
ea3f0419 611 for (okToTerminate = true;;) {
f427ee49
A
612 if (isDext) {
613 dextBundleID = OSDynamicPtrCast<OSString>(service->copyProperty(gIOModuleIdentifierKey.get()));
614 if (!dextBundleID) {
615 break;
616 }
617 bundleIDStr = dextBundleID->getCStringNoCopy();
618 } else {
619 kext = service->getMetaClass()->getKext();
620 if (!kext) {
621 break;
622 }
623 bundleIDStr = kext->getIdentifierCString();
624 prop = kext->getPropertyForHostArch(kOSBundleAllowUserTerminateKey);
625 if (prop) {
626 okToTerminate = (kOSBooleanTrue == prop);
627 break;
628 }
ea3f0419 629 }
ea3f0419
A
630 if (!bundleIDStr) {
631 break;
632 }
ea3f0419
A
633 if (!strcmp(kOSKextKernelIdentifier, bundleIDStr)) {
634 okToTerminate = false;
635 break;
636 }
637 if (!strncmp("com.apple.", bundleIDStr, strlen("com.apple."))) {
638 okToTerminate = false;
639 break;
640 }
641 break;
642 }
643 if (!okToTerminate) {
644#if DEVELOPMENT || DEBUG
645 okToTerminate = true;
646#endif /* DEVELOPMENT || DEBUG */
647 IOLog("%sallowing kextunload terminate for bundleID %s\n",
648 okToTerminate ? "" : "dis", bundleIDStr ? bundleIDStr : "?");
649 if (!okToTerminate) {
650 ret = kIOReturnUnsupported;
651 break;
652 }
653 }
f427ee49
A
654 IOOptionBits terminateOptions = kIOServiceRequired | kIOServiceSynchronous;
655 if (isDext) {
656 terminateOptions |= kIOServiceTerminateNeedWillTerminate;
657 }
658 if (!service->terminate(terminateOptions)) {
0a7de745
A
659 ret = kIOReturnUnsupported;
660 break;
661 }
662 }
663 } while (!service && !iter->isValid());
0a7de745
A
664
665 return ret;
91447636
A
666}
667
0a7de745
A
668IOReturn
669IOCatalogue::_removeDrivers(OSDictionary * matching)
91447636 670{
0a7de745 671 IOReturn ret = kIOReturnSuccess;
f427ee49 672 OSSharedPtr<OSCollectionIterator> iter;
0a7de745
A
673 OSDictionary * dict;
674 OSArray * array;
675 const OSSymbol * key;
676 unsigned int idx;
677
678 // remove configs from catalog.
679
f427ee49 680 iter = OSCollectionIterator::withCollection(personalities.get());
0a7de745
A
681 if (!iter) {
682 return kIOReturnNoMemory;
683 }
684
685 while ((key = (const OSSymbol *) iter->getNextObject())) {
686 array = (OSArray *) personalities->getObject(key);
687 if (array) {
688 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
689 /* Remove from the catalogue's array any personalities
690 * that match the matching dictionary.
691 * This comparison must be done with only the keys in the
692 * "matching" dict to enable general matching.
693 */
694 if (dict->isEqualTo(matching, matching)) {
695 array->removeObject(idx);
696 idx--;
697 }
698 }
699 }
700 }
0a7de745
A
701
702 return ret;
1c79356b
A
703}
704
0a7de745
A
705IOReturn
706IOCatalogue::terminateDrivers(OSDictionary * matching)
1c79356b 707{
0a7de745 708 IOReturn ret;
1c79356b 709
ea3f0419
A
710 if (!matching) {
711 return kIOReturnBadArgument;
712 }
713 ret = terminateDrivers(matching, NULL);
0a7de745
A
714 IORWLockWrite(lock);
715 if (kIOReturnSuccess == ret) {
716 ret = _removeDrivers(matching);
717 }
718 IORWLockUnlock(lock);
1c79356b 719
0a7de745 720 return ret;
1c79356b
A
721}
722
f427ee49
A
723IOReturn
724IOCatalogue::terminateDriversForUserspaceReboot()
725{
726 IOReturn ret = kIOReturnSuccess;
727
728#if !NO_KEXTD
729 OSSharedPtr<OSIterator> iter;
730 IOService * service;
731 bool isDeferredMatch;
732 bool isDext;
733 IOOptionBits terminateOptions;
734
735 iter = IORegistryIterator::iterateOver(gIOServicePlane,
736 kIORegistryIterateRecursively);
737 if (!iter) {
738 return kIOReturnNoMemory;
739 }
740
741 do {
742 iter->reset();
743 while ((service = (IOService *)iter->getNextObject())) {
744 isDeferredMatch = service->propertyHasValue(gIOMatchDeferKey, kOSBooleanTrue);
745 isDext = service->hasUserServer();
746 if (isDeferredMatch || isDext) {
747 if (isDext) {
748 OSSharedPtr<OSString> name = OSDynamicPtrCast<OSString>(service->copyProperty(gIOUserServerNameKey));
749 const char *userServerName = NULL;
750 if (name) {
751 userServerName = name->getCStringNoCopy();
752 }
753 IOLog("terminating service %s-0x%llx [dext %s]\n", service->getName(), service->getRegistryEntryID(), userServerName ? userServerName : "(null)");
754 } else {
755 OSKext *kext = service->getMetaClass()->getKext();
756 const char *bundleID = NULL;
757 if (kext) {
758 bundleID = kext->getIdentifierCString();
759 }
760 IOLog("terminating service %s-0x%llx [kext %s]\n", service->getName(), service->getRegistryEntryID(), bundleID ? bundleID : "(null)");
761 }
762 terminateOptions = kIOServiceRequired | kIOServiceSynchronous;
763 if (isDext) {
764 terminateOptions |= kIOServiceTerminateNeedWillTerminate;
765 }
766 if (!service->terminate(terminateOptions)) {
767 IOLog("failed to terminate service %s-0x%llx\n", service->getName(), service->getRegistryEntryID());
768 ret = kIOReturnUnsupported;
769 break;
770 }
771 }
772 }
773 } while (!service && !iter->isValid());
774#endif
775
776 return ret;
777}
778
779IOReturn
780IOCatalogue::resetAfterUserspaceReboot(void)
781{
782 OSSharedPtr<OSIterator> iter;
783 IOService * service;
784
785 iter = IORegistryIterator::iterateOver(gIOServicePlane,
786 kIORegistryIterateRecursively);
787 if (!iter) {
788 return kIOReturnNoMemory;
789 }
790
791 do {
792 iter->reset();
793 while ((service = (IOService *)iter->getNextObject())) {
794 service->resetRematchProperties();
795 }
796 } while (!service && !iter->isValid());
797
798 /* Remove all dext personalities */
799 removeDrivers(false, ^(OSDictionary *dict) {
800 return dict->getObject(gIOUserServerNameKey) != NULL;
801 });
802
803 return kIOReturnSuccess;
804}
805
0a7de745
A
806IOReturn
807IOCatalogue::terminateDriversForModule(
808 OSString * moduleName,
809 bool unload)
1c79356b 810{
0a7de745 811 IOReturn ret;
f427ee49 812 OSSharedPtr<OSDictionary> dict;
c3c9b80d 813 OSSharedPtr<OSKext> kext;
0a7de745 814 bool isLoaded = false;
c3c9b80d 815 bool isDext = false;
0a7de745
A
816
817 /* Check first if the kext currently has any linkage dependents;
818 * in such a case the unload would fail so let's not terminate any
819 * IOServices (since doing so typically results in a panic when there
820 * are loaded dependencies). Note that we aren't locking the kext here
821 * so it might lose or gain dependents by the time we call unloadModule();
822 * I think that's ok, our unload can fail if a kext comes in on top of
823 * this one even after we've torn down IOService objects. Conversely,
824 * if we fail the unload here and then lose a library, the autounload
825 * thread will get us in short order.
826 */
827 if (OSKext::isKextWithIdentifierLoaded(moduleName->getCStringNoCopy())) {
828 isLoaded = true;
829
830 if (!OSKext::canUnloadKextWithIdentifier(moduleName,
831 /* checkClasses */ false)) {
832 ret = kOSKextReturnInUse;
833 goto finish;
834 }
835 }
c3c9b80d
A
836 kext = OSKext::lookupKextWithIdentifier(moduleName->getCStringNoCopy());
837 if (kext) {
838 isDext = kext->isDriverKit();
839 }
840
0a7de745
A
841 dict = OSDictionary::withCapacity(1);
842 if (!dict) {
843 ret = kIOReturnNoMemory;
844 goto finish;
845 }
846
f427ee49 847 dict->setObject(gIOModuleIdentifierKey.get(), moduleName);
0a7de745 848
f427ee49 849 ret = terminateDrivers(dict.get(), NULL);
0a7de745 850
c3c9b80d
A
851 if (isDext) {
852 /* Force rematching after removing personalities. Dexts are never considered to be "loaded" (from OSKext),
853 * so we can't call unloadModule() to remove personalities and start rematching. */
854 removeDrivers(dict.get(), true);
855 } else {
856 /* No goto between IOLock calls!
857 */
858 IORWLockWrite(lock);
859 if (kIOReturnSuccess == ret) {
860 ret = _removeDrivers(dict.get());
861 }
0a7de745 862
c3c9b80d
A
863 // Unload the module itself.
864 if (unload && isLoaded && ret == kIOReturnSuccess) {
865 ret = unloadModule(moduleName);
866 }
867 IORWLockUnlock(lock);
0a7de745
A
868 }
869
b0d623f7 870finish:
0a7de745 871 return ret;
1c79356b
A
872}
873
0a7de745
A
874IOReturn
875IOCatalogue::terminateDriversForModule(
876 const char * moduleName,
877 bool unload)
1c79356b 878{
f427ee49 879 OSSharedPtr<OSString> name;
0a7de745 880 IOReturn ret;
1c79356b 881
0a7de745
A
882 name = OSString::withCString(moduleName);
883 if (!name) {
884 return kIOReturnNoMemory;
885 }
1c79356b 886
f427ee49 887 ret = terminateDriversForModule(name.get(), unload);
9bccf70c 888
0a7de745 889 return ret;
1c79356b
A
890}
891
cb323159 892#if defined(__i386__) || defined(__x86_64__)
0a7de745
A
893bool
894IOCatalogue::startMatching( OSDictionary * matching )
1c79356b 895{
f427ee49 896 OSSharedPtr<OSOrderedSet> set;
0a7de745
A
897
898 if (!matching) {
899 return false;
900 }
901
902 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
f427ee49 903 (void *)(gIOProbeScoreKey.get()));
0a7de745
A
904 if (!set) {
905 return false;
906 }
907
cb323159
A
908 IORWLockRead(lock);
909
910 personalities->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
911 OSArray * array;
912 OSDictionary * dict;
913 unsigned int idx;
914
915 array = (OSArray *) value;
916 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
917 /* This comparison must be done with only the keys in the
918 * "matching" dict to enable general matching.
919 */
920 if (dict->isEqualTo(matching, matching)) {
921 set->setObject(dict);
922 }
923 }
924 return false;
925 });
926
927 // Start device matching.
928 if (set->getCount() > 0) {
f427ee49 929 IOService::catalogNewDrivers(set.get());
cb323159
A
930 generation++;
931 }
932
933 IORWLockUnlock(lock);
934
cb323159
A
935 return true;
936}
937#endif /* defined(__i386__) || defined(__x86_64__) */
938
939bool
940IOCatalogue::startMatching( const OSSymbol * moduleName )
941{
f427ee49 942 OSSharedPtr<OSOrderedSet> set;
c3c9b80d
A
943 OSSharedPtr<OSKext> kext;
944 OSSharedPtr<OSArray> servicesToTerminate;
cb323159
A
945
946 if (!moduleName) {
947 return false;
948 }
949
950 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
f427ee49 951 (void *)(gIOProbeScoreKey.get()));
cb323159 952 if (!set) {
0a7de745
A
953 return false;
954 }
955
956 IORWLockRead(lock);
957
c3c9b80d
A
958 kext = OSKext::lookupKextWithIdentifier(moduleName->getCStringNoCopy());
959 if (kext && kext->isDriverKit()) {
960 /* We're here because kernelmanagerd called IOCatalogueModuleLoaded after launching a dext.
961 * Determine what providers the dext would match against. If there's something already attached
962 * to the provider, terminate it.
963 *
964 * This is only safe to do for HID dexts.
965 */
966 OSSharedPtr<OSArray> dextPersonalities = kext->copyPersonalitiesArray();
967
968 if (!dextPersonalities) {
969 return false;
970 }
971
972 servicesToTerminate = OSArray::withCapacity(1);
973 if (!servicesToTerminate) {
974 return false;
975 }
976
977 dextPersonalities->iterateObjects(^bool (OSObject * obj) {
978 OSDictionary * personality = OSDynamicCast(OSDictionary, obj);
979 OSSharedPtr<OSIterator> iter;
980 IOService * provider;
981 OSSharedPtr<IOService> service;
982 const OSSymbol * category;
983
984 if (personality) {
985 category = OSDynamicCast(OSSymbol, personality->getObject(gIOMatchCategoryKey));
986 if (!category) {
987 category = gIODefaultMatchCategoryKey;
988 }
989 iter = IOService::getMatchingServices(personality);
990
991 while (iter && (provider = OSDynamicCast(IOService, iter->getNextObject()))) {
992 if (provider->metaCast(gIOHIDInterfaceClassName.get()) != NULL) {
993 service.reset(provider->copyClientWithCategory(category), OSNoRetain);
994 if (service) {
995 servicesToTerminate->setObject(service);
996 }
997 }
998 }
999 }
1000
1001 return false;
1002 });
1003 }
1004
cb323159
A
1005 personalities->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
1006 OSArray * array;
1007 OSDictionary * dict;
f427ee49
A
1008 OSObject * moduleIdentifierKernel;
1009 OSObject * moduleIdentifier;
cb323159
A
1010 unsigned int idx;
1011
1012 array = (OSArray *) value;
1013 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
f427ee49
A
1014 moduleIdentifierKernel = dict->getObject(gIOModuleIdentifierKernelKey.get());
1015 moduleIdentifier = dict->getObject(gIOModuleIdentifierKey.get());
1016 if ((moduleIdentifierKernel && moduleName->isEqualTo(moduleIdentifierKernel)) ||
1017 (moduleIdentifier && moduleName->isEqualTo(moduleIdentifier))) {
cb323159 1018 set->setObject(dict);
0a7de745
A
1019 }
1020 }
cb323159
A
1021 return false;
1022 });
0a7de745 1023
c3c9b80d
A
1024 if (servicesToTerminate) {
1025 servicesToTerminate->iterateObjects(^bool (OSObject * obj) {
1026 IOService * service = OSDynamicCast(IOService, obj);
1027 if (service) {
1028 IOOptionBits terminateOptions = kIOServiceRequired;
1029 if (service->hasUserServer()) {
1030 terminateOptions |= kIOServiceTerminateNeedWillTerminate;
1031 }
1032 if (!service->terminate(terminateOptions)) {
1033 IOLog("%s: failed to terminate service %s-0x%qx with options %08llx for new dext %s\n", __FUNCTION__, service->getName(), service->getRegistryEntryID(), (long long)terminateOptions, moduleName->getCStringNoCopy());
1034 }
1035 }
1036 return false;
1037 });
1038 }
1039
0a7de745
A
1040 // Start device matching.
1041 if (set->getCount() > 0) {
f427ee49 1042 IOService::catalogNewDrivers(set.get());
0a7de745
A
1043 generation++;
1044 }
1045
1046 IORWLockUnlock(lock);
1047
0a7de745 1048 return true;
1c79356b
A
1049}
1050
0a7de745
A
1051void
1052IOCatalogue::reset(void)
1c79356b 1053{
0a7de745
A
1054 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL,
1055 /* doMatching */ false);
1056 return;
6d2010ae
A
1057}
1058
0a7de745
A
1059bool
1060IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching)
6d2010ae 1061{
0a7de745
A
1062 bool result = false;
1063 OSArray * newPersonalities = NULL;// do not release
0a7de745
A
1064 const OSSymbol * key;
1065 OSArray * array;
1066 OSDictionary * thisNewPersonality = NULL;// do not release
1067 OSDictionary * thisOldPersonality = NULL;// do not release
f427ee49
A
1068 OSSharedPtr<OSDictionary> myKexts;
1069 OSSharedPtr<OSCollectionIterator> iter;
1070 OSSharedPtr<OSOrderedSet> matchSet;
0a7de745
A
1071 signed int idx, newIdx;
1072
1073 if (drivers) {
1074 newPersonalities = OSDynamicCast(OSArray, drivers);
1075 if (!newPersonalities) {
1076 goto finish;
1077 }
1078 }
1079 matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering,
f427ee49 1080 (void *)(gIOProbeScoreKey.get()));
0a7de745
A
1081 if (!matchSet) {
1082 goto finish;
1083 }
f427ee49 1084 iter = OSCollectionIterator::withCollection(personalities.get());
0a7de745
A
1085 if (!iter) {
1086 goto finish;
1087 }
1088
1089 /* need copy of loaded kexts so we can check if for loaded modules without
1090 * taking the OSKext lock. There is a potential of deadlocking if we get
1091 * an OSKext via the normal path. See 14672140.
1092 */
1093 myKexts = OSKext::copyKexts();
1094
1095 result = true;
1096
1097 IOLog("Resetting IOCatalogue.\n");
1098
1099 /* No goto finish from here to unlock.
1100 */
1101 IORWLockWrite(lock);
1102
1103 while ((key = (const OSSymbol *) iter->getNextObject())) {
1104 array = (OSArray *) personalities->getObject(key);
1105 if (!array) {
1106 continue;
1107 }
1108
1109 for (idx = 0;
1110 (thisOldPersonality = (OSDictionary *) array->getObject(idx));
1111 idx++) {
1112 if (thisOldPersonality->getObject("KernelConfigTable")) {
1113 continue;
1114 }
1115 thisNewPersonality = NULL;
1116
1117 if (newPersonalities) {
1118 for (newIdx = 0;
1119 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
1120 newIdx++) {
1121 /* Unlike in other functions, this comparison must be exact!
1122 * The catalogue must be able to contain personalities that
1123 * are proper supersets of others.
1124 * Do not compare just the properties present in one driver
1125 * personality or the other.
1126 */
1127 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
1128 /* skip thisNewPersonality if it is not an OSDictionary */
1129 continue;
1130 }
1131 if (thisNewPersonality->isEqualTo(thisOldPersonality)) {
1132 break;
1133 }
1134 }
1135 }
1136 if (thisNewPersonality) {
1137 // dup, ignore
1138 newPersonalities->removeObject(newIdx);
1139 } else {
1140 // not in new set - remove
1141 // only remove dictionary if this module in not loaded - 9953845
f427ee49 1142 if (isModuleLoadedNoOSKextLock(myKexts.get(), thisOldPersonality) == false) {
0a7de745
A
1143 if (matchSet) {
1144 matchSet->setObject(thisOldPersonality);
1145 }
1146 array->removeObject(idx);
1147 idx--;
1148 }
1149 }
1150 } // for...
1151 } // while...
1152
1153 // add new
1154 if (newPersonalities) {
1155 for (newIdx = 0;
1156 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
1157 newIdx++) {
1158 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
1159 /* skip thisNewPersonality if it is not an OSDictionary */
1160 continue;
1161 }
1162
1163 OSKext::uniquePersonalityProperties(thisNewPersonality);
1164 addPersonality(thisNewPersonality);
1165 matchSet->setObject(thisNewPersonality);
1166 }
1167 }
1168
1169 /* Finally, start device matching on all new & removed personalities.
1170 */
1171 if (result && doNubMatching && (matchSet->getCount() > 0)) {
f427ee49 1172 IOService::catalogNewDrivers(matchSet.get());
0a7de745
A
1173 generation++;
1174 }
1175
1176 IORWLockUnlock(lock);
6d2010ae
A
1177
1178finish:
6d2010ae 1179
0a7de745 1180 return result;
1c79356b
A
1181}
1182
0a7de745
A
1183bool
1184IOCatalogue::serialize(OSSerialize * s) const
1c79356b 1185{
0a7de745
A
1186 if (!s) {
1187 return false;
1188 }
1c79356b 1189
0a7de745 1190 return super::serialize(s);
1c79356b
A
1191}
1192
0a7de745
A
1193bool
1194IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
55e303ae 1195{
0a7de745 1196 kern_return_t kr = kIOReturnSuccess;
55e303ae 1197
0a7de745
A
1198 switch (kind) {
1199 case kIOCatalogGetContents:
1200 kr = KERN_NOT_SUPPORTED;
1201 break;
55e303ae 1202
0a7de745
A
1203 case kIOCatalogGetModuleDemandList:
1204 kr = KERN_NOT_SUPPORTED;
1205 break;
55e303ae 1206
0a7de745
A
1207 case kIOCatalogGetCacheMissList:
1208 kr = KERN_NOT_SUPPORTED;
1209 break;
55e303ae 1210
0a7de745
A
1211 case kIOCatalogGetROMMkextList:
1212 kr = KERN_NOT_SUPPORTED;
1213 break;
55e303ae 1214
0a7de745
A
1215 default:
1216 kr = kIOReturnBadArgument;
1217 break;
1218 }
55e303ae 1219
0a7de745 1220 return kr;
55e303ae
A
1221}
1222
0a7de745 1223/* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
fe8ab488
A
1224 * without taking the OSKext lock. We use this to avoid the problem
1225 * where taking the IOCatalog lock then the OSKext lock will dealock when
1226 * a kext load or unload is happening at the same time as IOCatalog changing.
1227 *
1228 * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
1229 * key set to the kext bundle ID and value set to an OSKext object
1230 * theModuleDict - is an IOKit personality dictionary for a given module (kext)
1231 */
0a7de745
A
1232static bool
1233isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
1234 OSDictionary *theModuleDict)
fe8ab488 1235{
0a7de745
A
1236 bool myResult = false;
1237 const OSString * myBundleID = NULL;// do not release
1238 OSKext * myKext = NULL; // do not release
1239
1240 if (theKexts == NULL || theModuleDict == NULL) {
1241 return myResult;
1242 }
1243
1244 // gIOModuleIdentifierKey is "CFBundleIdentifier"
1245 myBundleID = OSDynamicCast(OSString,
f427ee49 1246 theModuleDict->getObject(gIOModuleIdentifierKey.get()));
0a7de745
A
1247 if (myBundleID == NULL) {
1248 return myResult;
1249 }
1250
1251 myKext = OSDynamicCast(OSKext, theKexts->getObject(myBundleID->getCStringNoCopy()));
1252 if (myKext) {
1253 myResult = myKext->isLoaded();
1254 }
1255
1256 return myResult;
fe8ab488
A
1257}
1258
1259
b0d623f7
A
1260#if PRAGMA_MARK
1261#pragma mark Obsolete Kext Loading Stuff
0c530ab8 1262#endif
91447636 1263/*********************************************************************
0a7de745
A
1264 **********************************************************************
1265 *** BINARY COMPATIBILITY SECTION ***
1266 **********************************************************************
1267 **********************************************************************
1268 * These functions are no longer used are necessary for C++ binary
1269 * compatibility on i386.
1270 **********************************************************************/