xref: /xnu-12377.1.9/iokit/Kernel/IOService.cpp (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1 /*
2  * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
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.
14  *
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
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <IOKit/system.h>
30 #include <IOKit/IOService.h>
31 #include <libkern/OSDebug.h>
32 #include <libkern/c++/OSAllocation.h>
33 #include <libkern/c++/OSContainers.h>
34 #include <libkern/c++/OSKext.h>
35 #include <libkern/c++/OSUnserialize.h>
36 #include <libkern/c++/OSKext.h>
37 #include <libkern/c++/OSSharedPtr.h>
38 #include <libkern/Block.h>
39 #include <IOKit/IOCatalogue.h>
40 #include <IOKit/IOCommand.h>
41 #include <IOKit/IODeviceTreeSupport.h>
42 #include <IOKit/IODeviceMemory.h>
43 #include <IOKit/IOInterrupts.h>
44 #include <IOKit/IOInterruptController.h>
45 #include <IOKit/IOPlatformExpert.h>
46 #include <IOKit/IOMessage.h>
47 #include <IOKit/IOLib.h>
48 #include <IOKit/IOKitKeysPrivate.h>
49 #include <IOKit/IOBSD.h>
50 #include <IOKit/IOUserClient.h>
51 #include <IOKit/IOUserServer.h>
52 #include <IOKit/IOWorkLoop.h>
53 #include <IOKit/IOTimeStamp.h>
54 #include <IOKit/IOHibernatePrivate.h>
55 #include <IOKit/IOInterruptAccountingPrivate.h>
56 #include <IOKit/IOKernelReporters.h>
57 #include <IOKit/AppleKeyStoreInterface.h>
58 #include <IOKit/pwr_mgt/RootDomain.h>
59 #include <IOKit/IOCPU.h>
60 #include <Exclaves/Exclaves.h>
61 #include <kern/cs_blobs.h>
62 #include <mach/sync_policy.h>
63 #include <mach/thread_info.h>
64 #include <machine/atomic.h>
65 #include <IOKit/assert.h>
66 #include <sys/errno.h>
67 #include <sys/kdebug.h>
68 #include <string.h>
69 
70 #include <machine/pal_routines.h>
71 
72 #define LOG kprintf
73 //#define LOG IOLog
74 #define MATCH_DEBUG     0
75 #define IOSERVICE_OBFUSCATE(x) ((void *)(VM_KERNEL_ADDRPERM(x)))
76 
77 // disabled since lockForArbitration() can be held externally
78 #define DEBUG_NOTIFIER_LOCKED   0
79 
80 enum{
81 	kIOUserServerCheckInTimeoutSecs = 120ULL
82 };
83 
84 #include "IOServicePrivate.h"
85 #include "IOServicePMPrivate.h"
86 #include "IOKitKernelInternal.h"
87 
88 // take lockForArbitration before LOCKNOTIFY
89 
90 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
91 
92 #define super IORegistryEntry
93 
94 OSDefineMetaClassAndStructors(IOService, IORegistryEntry)
95 
96 OSDefineMetaClassAndStructors(_IOServiceNotifier, IONotifier)
97 OSDefineMetaClassAndStructors(_IOServiceNullNotifier, IONotifier)
98 
99 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier, IONotifier)
100 
101 OSDefineMetaClassAndStructors(_IOConfigThread, OSObject)
102 
103 OSDefineMetaClassAndStructors(_IOServiceJob, OSObject)
104 
105 OSDefineMetaClassAndStructors(IOResources, IOService)
106 OSDefineMetaClassAndStructors(IOUserResources, IOService)
107 OSDefineMetaClassAndStructors(IOExclaveProxy, IOService)
108 
109 OSDefineMetaClassAndStructors(_IOOpenServiceIterator, OSIterator)
110 
111 OSDefineMetaClassAndStructors(_IOServiceStateNotification, IOService)
112 
113 OSDefineMetaClassAndAbstractStructors(IONotifier, OSObject)
114 
115 OSDefineMetaClassAndStructors(IOServiceCompatibility, IOService)
116 
117 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
118 
119 static IOPlatformExpert *       gIOPlatform;
120 class IOPMrootDomain *          gIOPMRootDomain;
121 const IORegistryPlane *         gIOServicePlane;
122 const IORegistryPlane *         gIOPowerPlane;
123 const OSSymbol *                gIODeviceMemoryKey;
124 const OSSymbol *                gIOInterruptControllersKey;
125 const OSSymbol *                gIOInterruptSpecifiersKey;
126 
127 const OSSymbol *                gIOResourcesKey;
128 const OSSymbol *                gIOUserResourcesKey;
129 const OSSymbol *                gIOResourceMatchKey;
130 const OSSymbol *                gIOResourceMatchedKey;
131 const OSSymbol *                gIOResourceIOKitKey;
132 
133 const OSSymbol *                gIOProviderClassKey;
134 const OSSymbol *                gIONameMatchKey;
135 const OSSymbol *                gIONameMatchedKey;
136 const OSSymbol *                gIOPropertyMatchKey;
137 const OSSymbol *                gIOPropertyExistsMatchKey;
138 const OSSymbol *                gIOLocationMatchKey;
139 const OSSymbol *                gIOParentMatchKey;
140 const OSSymbol *                gIOPathMatchKey;
141 const OSSymbol *                gIOMatchCategoryKey;
142 const OSSymbol *                gIODefaultMatchCategoryKey;
143 const OSSymbol *                gIOMatchedAtBootKey;
144 const OSSymbol *                gIOMatchedServiceCountKey;
145 const OSSymbol *                gIOMatchedPersonalityKey;
146 const OSSymbol *                gIORematchPersonalityKey;
147 const OSSymbol *                gIORematchCountKey;
148 const OSSymbol *                gIODEXTMatchCountKey;
149 const OSSymbol *                gIOSupportedPropertiesKey;
150 const OSSymbol *                gIOUserServicePropertiesKey;
151 #if defined(XNU_TARGET_OS_OSX)
152 const OSSymbol *                gIOServiceLegacyMatchingRegistryIDKey;
153 #endif /* defined(XNU_TARGET_OS_OSX) */
154 
155 const OSSymbol *                gIOCompatibilityMatchKey;
156 const OSSymbol *                gIOCompatibilityPropertiesKey;
157 const OSSymbol *                gIOPathKey;
158 
159 const OSSymbol *                gIOMapperIDKey;
160 const OSSymbol *                gIOUserClientClassKey;
161 
162 const OSSymbol *                gIOUserClassKey;
163 const OSSymbol *                gIOUserClassesKey;
164 const OSSymbol *                gIOUserServerClassKey;
165 const OSSymbol *                gIOUserServerNameKey;
166 const OSSymbol *                gIOUserServerTagKey;
167 const OSSymbol *                gIOUserUserClientKey;
168 const OSSymbol *                gIOUserServerOneProcessKey;
169 const OSSymbol *                gIOUserServerPreserveUserspaceRebootKey;
170 
171 const OSSymbol *                gIOKitDebugKey;
172 
173 const OSSymbol *                gIOCommandPoolSizeKey;
174 
175 const OSSymbol *                gIOConsoleLockedKey;
176 const OSSymbol *                gIOConsoleUsersKey;
177 const OSSymbol *                gIOConsoleSessionUIDKey;
178 const OSSymbol *                gIOConsoleSessionAuditIDKey;
179 const OSSymbol *                gIOConsoleUsersSeedKey;
180 const OSSymbol *                gIOConsoleSessionOnConsoleKey;
181 const OSSymbol *                gIOConsoleSessionLoginDoneKey;
182 const OSSymbol *                gIOConsoleSessionSecureInputPIDKey;
183 const OSSymbol *                gIOConsoleSessionScreenLockedTimeKey;
184 const OSSymbol *                gIOConsoleSessionScreenIsLockedKey;
185 clock_sec_t                     gIOConsoleLockTime;
186 static bool                     gIOConsoleLoggedIn;
187 #if HIBERNATION
188 static OSBoolean *              gIOConsoleBooterLockState;
189 static uint32_t                 gIOScreenLockState;
190 #endif
191 static IORegistryEntry *        gIOChosenEntry;
192 
193 static int                      gIOResourceGenerationCount;
194 
195 const OSSymbol *                gIOServiceKey;
196 const OSSymbol *                gIOPublishNotification;
197 const OSSymbol *                gIOFirstPublishNotification;
198 const OSSymbol *                gIOMatchedNotification;
199 const OSSymbol *                gIOFirstMatchNotification;
200 const OSSymbol *                gIOTerminatedNotification;
201 const OSSymbol *                gIOWillTerminateNotification;
202 
203 const OSSymbol *                gIOUserClientEntitlementsKey;
204 const OSSymbol *                gIOServiceDEXTEntitlementsKey;
205 const OSSymbol *                gIODriverKitEntitlementKey;
206 const OSSymbol *                gIODriverKitUserClientEntitlementsKey;
207 const OSSymbol *                gIODriverKitUserClientEntitlementAllowAnyKey;
208 const OSSymbol *                gIODriverKitRequiredEntitlementsKey;
209 const OSSymbol *                gIODriverKitTestDriverEntitlementKey;
210 const OSSymbol *                gIODriverKitUserClientEntitlementCommunicatesWithDriversKey;
211 const OSSymbol *                gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey;
212 const OSSymbol *                gIOMatchDeferKey;
213 const OSSymbol *                gIOServiceMatchDeferredKey;
214 const OSSymbol *                gIOServiceNotificationUserKey;
215 
216 const OSSymbol *                gIOExclaveAssignedKey;
217 const OSSymbol *                gIOExclaveProxyKey;
218 
219 const OSSymbol *                gIOPrimaryDriverTerminateOptionsKey;
220 const OSSymbol *                gIOMediaKey;
221 const OSSymbol *                gIOBlockStorageDriverKey;
222 static const OSSymbol *         gPhysicalInterconnectKey;
223 static const OSSymbol *         gVirtualInterfaceKey;
224 
225 const OSSymbol *                gIOAllCPUInitializedKey;
226 
227 const OSSymbol *                gIOGeneralInterest;
228 const OSSymbol *                gIOBusyInterest;
229 const OSSymbol *                gIOAppPowerStateInterest;
230 const OSSymbol *                gIOPriorityPowerStateInterest;
231 const OSSymbol *                gIOConsoleSecurityInterest;
232 
233 const OSSymbol *                gIOBSDKey;
234 const OSSymbol *                gIOBSDNameKey;
235 const OSSymbol *                gIOBSDMajorKey;
236 const OSSymbol *                gIOBSDMinorKey;
237 const OSSymbol *                gIOBSDUnitKey;
238 
239 const  OSSymbol *               gAKSGetKey;
240 #if defined(__i386__) || defined(__x86_64__)
241 const OSSymbol *                gIOCreateEFIDevicePathSymbol;
242 #endif
243 
244 static OSDictionary *           gNotifications;
245 static IORecursiveLock *        gNotificationLock;
246 
247 static IOService *              gIOResources;
248 static IOService *              gIOUserResources;
249 static IOService *              gIOServiceRoot;
250 
251 static OSOrderedSet *           gJobs;
252 static semaphore_port_t         gJobsSemaphore;
253 static IOLock *                 gJobsLock;
254 static int                      gOutstandingJobs;
255 static int                      gNumConfigThreads;
256 static int                      gHighNumConfigThreads;
257 static int                      gMaxConfigThreads = kMaxConfigThreads;
258 static int                      gNumWaitingThreads;
259 static IOLock *                 gIOServiceBusyLock;
260 bool                            gCPUsRunning;
261 bool                            gIOKitWillTerminate;
262 atomic_bool                     gInUserspaceReboot;
263 
264 #define kIOServiceRootMediaParentInvalid ((IOService *) -1UL)
265 #if NO_KEXTD
266 static bool                     gIOServiceHideIOMedia = false;
267 static IOService *              gIOServiceRootMediaParent = NULL;
268 #else /* NO_KEXTD */
269 static bool                     gIOServiceHideIOMedia = true;
270 static IOService *              gIOServiceRootMediaParent = kIOServiceRootMediaParentInvalid;
271 #endif /* !NO_KEXTD */
272 
273 static thread_t                 gIOTerminateThread;
274 static thread_t                 gIOTerminateWorkerThread;
275 static UInt32                   gIOTerminateWork;
276 static OSArray *                gIOTerminatePhase2List;
277 static OSArray *                gIOStopList;
278 static OSArray *                gIOStopProviderList;
279 static OSArray *                gIOFinalizeList;
280 
281 #if !NO_KEXTD
282 static OSArray *                gIOMatchDeferList;
283 #endif
284 
285 static SInt32                   gIOConsoleUsersSeed;
286 static OSData *                 gIOConsoleUsersSeedValue;
287 
288 extern const OSSymbol *         gIODTPHandleKey;
289 
290 const OSSymbol *                gIOPlatformFunctionHandlerSet;
291 
292 
293 static IOLock *                 gIOConsoleUsersLock;
294 static thread_call_t            gIOConsoleLockCallout;
295 static IONotifier *             gIOServiceNullNotifier;
296 
297 static SECURITY_READ_ONLY_LATE(uint32_t) gIODextRelaunchMax;
298 
299 #if DEVELOPMENT || DEBUG
300 uint64_t                        driverkit_checkin_timed_out = 0;
301 #endif
302 
303 IORecursiveLock               * gDriverKitLaunchLock;
304 OSSet                         * gDriverKitLaunches;
305 const OSSymbol                * gIOAssociatedServicesKey;
306 
307 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
308 
309 #define LOCKREADNOTIFY()        \
310     IORecursiveLockLock( gNotificationLock )
311 #define LOCKWRITENOTIFY()       \
312     IORecursiveLockLock( gNotificationLock )
313 #define LOCKWRITE2READNOTIFY()
314 #define UNLOCKNOTIFY()          \
315     IORecursiveLockUnlock( gNotificationLock )
316 #define SLEEPNOTIFY(event) \
317     IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
318 #define SLEEPNOTIFYTO(event, deadline) \
319     IORecursiveLockSleepDeadline( gNotificationLock, (void *)(event), deadline, THREAD_UNINT )
320 #define WAKEUPNOTIFY(event) \
321 	IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
322 
323 #define randomDelay()   \
324 	int del = read_processor_clock();                               \
325 	del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff;      \
326 	IOSleep( del );
327 
328 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
329 
330 #define queue_element(entry, element, type, field) do { \
331 	vm_address_t __ele = (vm_address_t) (entry);    \
332 	__ele -= -4 + ((size_t)(&((type) 4)->field));   \
333 	(element) = (type) __ele;                       \
334     } while(0)
335 
336 #define iterqueue(que, elt)                             \
337 	for (queue_entry_t elt = queue_first(que);      \
338 	     !queue_end(que, elt);                      \
339 	     elt = queue_next(elt))
340 
341 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
342 
343 struct IOInterruptAccountingReporter {
344 	IOSimpleReporter * reporter; /* Reporter responsible for communicating the statistics */
345 	IOInterruptAccountingData * statistics; /* The live statistics values, if any */
346 };
347 
348 struct ArbitrationLockQueueElement {
349 	queue_chain_t link;
350 	IOThread      thread;
351 	IOService *   service;
352 	unsigned      count;
353 	bool          required;
354 	bool          aborted;
355 };
356 
357 static queue_head_t gArbitrationLockQueueActive;
358 static queue_head_t gArbitrationLockQueueWaiting;
359 static queue_head_t gArbitrationLockQueueFree;
360 static IOLock *     gArbitrationLockQueueLock;
361 
362 bool
isInactive(void) const363 IOService::isInactive( void ) const
364 {
365 	return 0 != (kIOServiceInactiveState & getState());
366 }
367 
368 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
369 
370 // Only used by the intel implementation of
371 //     IOService::requireMaxBusStall(UInt32 ns)
372 //     IOService::requireMaxInterruptDelay(uint32_t ns)
373 struct CpuDelayEntry {
374 	IOService * fService;
375 	UInt32      fMaxDelay;
376 	UInt32      fDelayType;
377 };
378 
379 enum {
380 	kCpuDelayBusStall,
381 #if defined(__x86_64__)
382 	kCpuDelayInterrupt,
383 #endif /* defined(__x86_64__) */
384 	kCpuNumDelayTypes
385 };
386 
387 static OSData          *sCpuDelayData = OSData::withCapacity(8 * sizeof(CpuDelayEntry));
388 static IORecursiveLock *sCpuDelayLock = IORecursiveLockAlloc();
389 static OSArray         *sCpuLatencyHandlers[kCpuNumDelayTypes];
390 const OSSymbol         *sCPULatencyFunctionName[kCpuNumDelayTypes];
391 static OSNumber * sCPULatencyHolder[kCpuNumDelayTypes];
392 static char sCPULatencyHolderName[kCpuNumDelayTypes][128];
393 static OSNumber * sCPULatencySet[kCpuNumDelayTypes];
394 
395 static void
396 requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType);
397 static IOReturn
398 setLatencyHandler(UInt32 delayType, IOService * target, bool enable);
399 
400 static bool IOServiceMatchingNotificationHandlerToBlock(void * target __unused,
401     void * refCon, IOService * newService, IONotifier * notifier);
402 
403 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
404 
405 IOCoreAnalyticsSendEventProc gIOCoreAnalyticsSendEventProc;
406 
407 kern_return_t
IOSetCoreAnalyticsSendEventProc(IOCoreAnalyticsSendEventProc proc)408 IOSetCoreAnalyticsSendEventProc(IOCoreAnalyticsSendEventProc proc)
409 {
410 	if (gIOCoreAnalyticsSendEventProc) {
411 		return kIOReturnNotPermitted;
412 	}
413 	gIOCoreAnalyticsSendEventProc = proc;
414 
415 	return kIOReturnSuccess;
416 }
417 
418 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
419 
420 
421 static IOMessage  sSystemPower;
422 extern "C" bool restore_boot;
423 
424 namespace IOServicePH
425 {
426 IONotifier          * fRootNotifier;
427 OSArray             * fUserServers;
428 OSArray             * fUserServersWait;
429 OSArray             * fMatchingWork;
430 OSArray             * fMatchingDelayed;
431 IOService           * fSystemPowerAckTo;
432 uint32_t              fSystemPowerAckRef;
433 IOService           * fSystemPowerAckTo2;
434 uint8_t               fSystemState = kIOServiceSystemStateOn;
435 uint8_t               fUserServerSystemState;
436 bool                  fWaitingUserServers;
437 thread_call_t         fUserServerAckTimer;
438 
439 void lock();
440 void unlock();
441 
442 void init(IOPMrootDomain * root);
443 
444 void systemPowerChange(uint8_t newState,
445     IOService * ackTo,
446     uint32_t ackRef,
447     uint32_t * pMaxWaitForReply);
448 IOReturn systemPowerChange(
449 	void * target,
450 	void * refCon,
451 	UInt32 messageType, IOService * service,
452 	void * messageArgument, vm_size_t argSize);
453 IOReturn rootWillChangeTo(IOPMPowerFlags flags, unsigned long state);
454 bool matchingStart(IOService * service);
455 void matchingEnd(IOService * service);
456 void userServerAckTimerExpired(void *, void *);
457 };
458 
459 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
460 
461 void
initialize(void)462 IOService::initialize( void )
463 {
464 	kern_return_t       err;
465 
466 	gIOServicePlane     = IORegistryEntry::makePlane( kIOServicePlane );
467 	gIOPowerPlane       = IORegistryEntry::makePlane( kIOPowerPlane );
468 
469 	gIOProviderClassKey = OSSymbol::withCStringNoCopy( kIOProviderClassKey );
470 	gIONameMatchKey     = OSSymbol::withCStringNoCopy( kIONameMatchKey );
471 	gIONameMatchedKey   = OSSymbol::withCStringNoCopy( kIONameMatchedKey );
472 	gIOPropertyMatchKey = OSSymbol::withCStringNoCopy( kIOPropertyMatchKey );
473 	gIOPropertyExistsMatchKey = OSSymbol::withCStringNoCopy( kIOPropertyExistsMatchKey );
474 	gIOPathMatchKey     = OSSymbol::withCStringNoCopy( kIOPathMatchKey );
475 	gIOLocationMatchKey = OSSymbol::withCStringNoCopy( kIOLocationMatchKey );
476 	gIOParentMatchKey   = OSSymbol::withCStringNoCopy( kIOParentMatchKey );
477 
478 	gIOMatchCategoryKey = OSSymbol::withCStringNoCopy( kIOMatchCategoryKey );
479 	gIODefaultMatchCategoryKey  = OSSymbol::withCStringNoCopy(
480 		kIODefaultMatchCategoryKey );
481 	gIOMatchedAtBootKey  = OSSymbol::withCStringNoCopy(
482 		kIOMatchedAtBootKey );
483 
484 	gIOMatchedServiceCountKey   = OSSymbol::withCStringNoCopy(
485 		kIOMatchedServiceCountKey );
486 	gIOMatchedPersonalityKey = OSSymbol::withCStringNoCopy(
487 		kIOMatchedPersonalityKey );
488 	gIORematchPersonalityKey = OSSymbol::withCStringNoCopy(
489 		kIORematchPersonalityKey );
490 	gIORematchCountKey = OSSymbol::withCStringNoCopy(
491 		kIORematchCountKey );
492 	gIODEXTMatchCountKey = OSSymbol::withCStringNoCopy(
493 		kIODEXTMatchCountKey );
494 
495 #if defined(XNU_TARGET_OS_OSX)
496 	gIOServiceLegacyMatchingRegistryIDKey = OSSymbol::withCStringNoCopy(
497 		kIOServiceLegacyMatchingRegistryIDKey );
498 #endif /* defined(XNU_TARGET_OS_OSX) */
499 
500 	if (!PE_parse_boot_argn("dextrelaunch", &gIODextRelaunchMax, sizeof(gIODextRelaunchMax))) {
501 		if (restore_boot) {
502 			// Limit dext relaunches in the restore environment
503 			gIODextRelaunchMax = 10;
504 		} else {
505 			gIODextRelaunchMax = 1000;
506 		}
507 	}
508 	PE_parse_boot_argn("iocthreads", &gMaxConfigThreads, sizeof(gMaxConfigThreads));
509 
510 	gIOUserClientClassKey = OSSymbol::withCStringNoCopy( kIOUserClientClassKey );
511 
512 	gIOUserClassKey       = OSSymbol::withCStringNoCopy(kIOUserClassKey);
513 	gIOUserClassesKey     = OSSymbol::withCStringNoCopy(kIOUserClassesKey);
514 
515 	gIOUserServerClassKey  = OSSymbol::withCStringNoCopy(kIOUserServerClassKey);
516 	gIOUserServerNameKey   = OSSymbol::withCStringNoCopy(kIOUserServerNameKey);
517 	gIOUserServerTagKey    = OSSymbol::withCStringNoCopy(kIOUserServerTagKey);
518 	gIOUserUserClientKey   = OSSymbol::withCStringNoCopy(kIOUserUserClientKey);
519 
520 	gIOUserServerOneProcessKey = OSSymbol::withCStringNoCopy(kIOUserServerOneProcessKey);
521 
522 	gIOUserServerPreserveUserspaceRebootKey = OSSymbol::withCStringNoCopy(kIOUserServerPreserveUserspaceRebootKey);
523 
524 	gIOResourcesKey       = OSSymbol::withCStringNoCopy( kIOResourcesClass );
525 	gIOResourceMatchKey   = OSSymbol::withCStringNoCopy( kIOResourceMatchKey );
526 	gIOResourceMatchedKey = OSSymbol::withCStringNoCopy( kIOResourceMatchedKey );
527 	gIOResourceIOKitKey   = OSSymbol::withCStringNoCopy("IOKit");
528 
529 	gIODeviceMemoryKey  = OSSymbol::withCStringNoCopy( "IODeviceMemory" );
530 	gIOInterruptControllersKey
531 	        = OSSymbol::withCStringNoCopy("IOInterruptControllers");
532 	gIOInterruptSpecifiersKey
533 	        = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
534 
535 	gIOCompatibilityMatchKey = OSSymbol::withCStringNoCopy(kIOCompatibilityMatchKey);
536 	gIOCompatibilityPropertiesKey = OSSymbol::withCStringNoCopy(kIOCompatibilityPropertiesKey);
537 	gIOPathKey = OSSymbol::withCStringNoCopy(kIOPathKey);
538 	gIOSupportedPropertiesKey = OSSymbol::withCStringNoCopy(kIOSupportedPropertiesKey);
539 	gIOUserServicePropertiesKey = OSSymbol::withCStringNoCopy(kIOUserServicePropertiesKey);
540 
541 	gIOMapperIDKey = OSSymbol::withCStringNoCopy(kIOMapperIDKey);
542 
543 	gIOKitDebugKey      = OSSymbol::withCStringNoCopy( kIOKitDebugKey );
544 
545 	gIOCommandPoolSizeKey       = OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey );
546 
547 	gIOGeneralInterest          = OSSymbol::withCStringNoCopy( kIOGeneralInterest );
548 	gIOBusyInterest             = OSSymbol::withCStringNoCopy( kIOBusyInterest );
549 	gIOAppPowerStateInterest    = OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest );
550 	gIOPriorityPowerStateInterest       = OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest );
551 	gIOConsoleSecurityInterest  = OSSymbol::withCStringNoCopy( kIOConsoleSecurityInterest );
552 
553 	gIOBSDKey      = OSSymbol::withCStringNoCopy(kIOBSDKey);
554 	gIOBSDNameKey  = OSSymbol::withCStringNoCopy(kIOBSDNameKey);
555 	gIOBSDMajorKey = OSSymbol::withCStringNoCopy(kIOBSDMajorKey);
556 	gIOBSDMinorKey = OSSymbol::withCStringNoCopy(kIOBSDMinorKey);
557 	gIOBSDUnitKey  = OSSymbol::withCStringNoCopy(kIOBSDUnitKey);
558 
559 	gNotifications              = OSDictionary::withCapacity( 1 );
560 	gIOPublishNotification      = OSSymbol::withCStringNoCopy(
561 		kIOPublishNotification );
562 	gIOFirstPublishNotification = OSSymbol::withCStringNoCopy(
563 		kIOFirstPublishNotification );
564 	gIOMatchedNotification      = OSSymbol::withCStringNoCopy(
565 		kIOMatchedNotification );
566 	gIOFirstMatchNotification   = OSSymbol::withCStringNoCopy(
567 		kIOFirstMatchNotification );
568 	gIOTerminatedNotification   = OSSymbol::withCStringNoCopy(
569 		kIOTerminatedNotification );
570 	gIOWillTerminateNotification = OSSymbol::withCStringNoCopy(
571 		kIOWillTerminateNotification );
572 	gIOServiceKey               = OSSymbol::withCStringNoCopy( kIOServiceClass);
573 
574 
575 	gIOConsoleLockedKey         = OSSymbol::withCStringNoCopy( kIOConsoleLockedKey);
576 	gIOConsoleUsersKey          = OSSymbol::withCStringNoCopy( kIOConsoleUsersKey);
577 	gIOConsoleSessionUIDKey     = OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey);
578 	gIOConsoleSessionAuditIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionAuditIDKey);
579 
580 	gIOConsoleUsersSeedKey               = OSSymbol::withCStringNoCopy(kIOConsoleUsersSeedKey);
581 	gIOConsoleSessionOnConsoleKey        = OSSymbol::withCStringNoCopy(kIOConsoleSessionOnConsoleKey);
582 	gIOConsoleSessionLoginDoneKey        = OSSymbol::withCStringNoCopy(kIOConsoleSessionLoginDoneKey);
583 	gIOConsoleSessionSecureInputPIDKey   = OSSymbol::withCStringNoCopy(kIOConsoleSessionSecureInputPIDKey);
584 	gIOConsoleSessionScreenLockedTimeKey = OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenLockedTimeKey);
585 	gIOConsoleSessionScreenIsLockedKey   = OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenIsLockedKey);
586 
587 	gIOConsoleUsersSeedValue           = OSData::withValueNoCopy(gIOConsoleUsersSeed);
588 
589 	gIOUserClientEntitlementsKey           = OSSymbol::withCStringNoCopy( kIOUserClientEntitlementsKey );
590 	gIOServiceDEXTEntitlementsKey           = OSSymbol::withCStringNoCopy( kIOServiceDEXTEntitlementsKey );
591 	gIODriverKitEntitlementKey             = OSSymbol::withCStringNoCopy( kIODriverKitEntitlementKey );
592 	gIODriverKitUserClientEntitlementsKey   = OSSymbol::withCStringNoCopy( kIODriverKitUserClientEntitlementsKey );
593 #if XNU_TARGET_OS_OSX
594 	gIODriverKitUserClientEntitlementAllowAnyKey   = OSSymbol::withCStringNoCopy( kIODriverKitUserClientEntitlementAllowAnyKey );
595 #else
596 	gIODriverKitUserClientEntitlementAllowAnyKey   = NULL;
597 #endif
598 	gIODriverKitRequiredEntitlementsKey   = OSSymbol::withCStringNoCopy( kIODriverKitRequiredEntitlementsKey );
599 	gIODriverKitTestDriverEntitlementKey  = OSSymbol::withCStringNoCopy( kIODriverKitTestDriverEntitlementKey );
600 	gIODriverKitUserClientEntitlementCommunicatesWithDriversKey = OSSymbol::withCStringNoCopy(kIODriverKitUserClientEntitlementCommunicatesWithDriversKey);
601 	gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey = OSSymbol::withCStringNoCopy(kIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey);
602 
603 	gIOMatchDeferKey                    = OSSymbol::withCStringNoCopy( kIOMatchDeferKey );
604 	gIOServiceMatchDeferredKey          = OSSymbol::withCStringNoCopy( kIOServiceMatchDeferredKey );
605 	gIOServiceNotificationUserKey       = OSSymbol::withCStringNoCopy( kIOServiceNotificationUserKey );
606 	gIOExclaveAssignedKey               = OSSymbol::withCStringNoCopy(kIOExclaveAssignedKey);
607 	gIOExclaveProxyKey                  = OSSymbol::withCStringNoCopy(kIOExclaveProxyKey);
608 
609 	gIOPrimaryDriverTerminateOptionsKey = OSSymbol::withCStringNoCopy(kIOPrimaryDriverTerminateOptionsKey);
610 	gIOMediaKey                         = OSSymbol::withCStringNoCopy("IOMedia");
611 	gIOBlockStorageDriverKey            = OSSymbol::withCStringNoCopy("IOBlockStorageDriver");
612 	gPhysicalInterconnectKey            = OSSymbol::withCStringNoCopy("Physical Interconnect");
613 	gVirtualInterfaceKey                = OSSymbol::withCStringNoCopy("Virtual Interface");
614 
615 	gIOAllCPUInitializedKey                 = OSSymbol::withCStringNoCopy( kIOAllCPUInitializedKey );
616 
617 	gIOPlatformFunctionHandlerSet               = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerSet);
618 	sCPULatencyFunctionName[kCpuDelayBusStall]  = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxBusDelay);
619 #if defined(__x86_64__)
620 	sCPULatencyFunctionName[kCpuDelayInterrupt] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxInterruptDelay);
621 #endif /* defined(__x86_64__) */
622 	uint32_t  idx;
623 	for (idx = 0; idx < kCpuNumDelayTypes; idx++) {
624 		sCPULatencySet[idx]    = OSNumber::withNumber(UINT_MAX, 32);
625 		sCPULatencyHolder[idx] = OSNumber::withNumber(0ULL, 64);
626 		assert(sCPULatencySet[idx] && sCPULatencyHolder[idx]);
627 	}
628 
629 #if defined(__x86_64__)
630 	gIOCreateEFIDevicePathSymbol = OSSymbol::withCString("CreateEFIDevicePath");
631 #endif /* defined(__x86_64__) */
632 
633 	gNotificationLock           = IORecursiveLockAlloc();
634 
635 	gAKSGetKey                   = OSSymbol::withCStringNoCopy(AKS_PLATFORM_FUNCTION_GETKEY);
636 
637 #if CONFIG_EXCLAVES
638 	gExclaveProxyStates          = OSDictionary::withCapacity( 1 );
639 
640 	gExclaveProxyStateLock           = IORecursiveLockAlloc();
641 	assert( gExclaveProxyStates && gExclaveProxyStateLock);
642 #endif /* CONFIG_EXCLAVES */
643 
644 	assert( gIOServicePlane && gIODeviceMemoryKey
645 	    && gIOInterruptControllersKey && gIOInterruptSpecifiersKey
646 	    && gIOResourcesKey && gNotifications && gNotificationLock
647 	    && gIOProviderClassKey && gIONameMatchKey && gIONameMatchedKey
648 	    && gIOMatchCategoryKey && gIODefaultMatchCategoryKey
649 	    && gIOPublishNotification && gIOMatchedNotification
650 	    && gIOTerminatedNotification && gIOServiceKey
651 	    && gIOConsoleUsersKey && gIOConsoleSessionUIDKey
652 	    && gIOConsoleSessionOnConsoleKey && gIOConsoleSessionSecureInputPIDKey
653 	    && gIOConsoleUsersSeedKey && gIOConsoleUsersSeedValue);
654 
655 	gJobsLock   = IOLockAlloc();
656 	gJobs       = OSOrderedSet::withCapacity( 10 );
657 
658 	gIOServiceBusyLock = IOLockAlloc();
659 
660 	gIOConsoleUsersLock = IOLockAlloc();
661 
662 	err = semaphore_create(kernel_task, &gJobsSemaphore, SYNC_POLICY_FIFO, 0);
663 
664 	gIOConsoleLockCallout = thread_call_allocate(&IOService::consoleLockTimer, NULL);
665 
666 	IORegistryEntry::getRegistryRoot()->setProperty(gIOConsoleLockedKey, kOSBooleanTrue);
667 
668 	assert( gIOServiceBusyLock && gJobs && gJobsLock && gIOConsoleUsersLock
669 	    && gIOConsoleLockCallout && (err == KERN_SUCCESS));
670 
671 	gIOResources = IOResources::resources();
672 	gIOUserResources = IOUserResources::resources();
673 	assert( gIOResources && gIOUserResources );
674 
675 	gIOServiceNullNotifier = OSTypeAlloc(_IOServiceNullNotifier);
676 	assert(gIOServiceNullNotifier);
677 
678 	gArbitrationLockQueueLock = IOLockAlloc();
679 	queue_init(&gArbitrationLockQueueActive);
680 	queue_init(&gArbitrationLockQueueWaiting);
681 	queue_init(&gArbitrationLockQueueFree);
682 
683 	assert( gArbitrationLockQueueLock );
684 
685 	allocPMInitLock();
686 
687 	gIOTerminatePhase2List = OSArray::withCapacity( 2 );
688 	gIOStopList            = OSArray::withCapacity( 16 );
689 	gIOStopProviderList    = OSArray::withCapacity( 16 );
690 	gIOFinalizeList        = OSArray::withCapacity( 16 );
691 #if !NO_KEXTD
692 	if (OSKext::iokitDaemonAvailable()) {
693 		gIOMatchDeferList      = OSArray::withCapacity( 16 );
694 	} else {
695 		gIOMatchDeferList      = NULL;
696 	}
697 #endif
698 	assert( gIOTerminatePhase2List && gIOStopList && gIOStopProviderList && gIOFinalizeList );
699 
700 	gDriverKitLaunches = OSSet::withCapacity(0);
701 	gDriverKitLaunchLock = IORecursiveLockAlloc();
702 	gIOAssociatedServicesKey = OSSymbol::withCStringNoCopy( "IOAssociatedServices" );
703 #if CONFIG_EXCLAVES
704 	gDARTMapperFunctionSetActive = OSSymbol::withCStringNoCopy("setActive");
705 #endif /* CONFIG_EXCLAVES */
706 
707 	// worker thread that is responsible for terminating / cleaning up threads
708 	kernel_thread_start(&terminateThread, NULL, &gIOTerminateWorkerThread);
709 	assert(gIOTerminateWorkerThread);
710 	thread_set_thread_name(gIOTerminateWorkerThread, "IOServiceTerminateThread");
711 }
712 
713 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
714 
715 #if defined(__x86_64__)
716 extern "C" {
717 const char *getCpuDelayBusStallHolderName(void);
718 const char *
getCpuDelayBusStallHolderName(void)719 getCpuDelayBusStallHolderName(void)
720 {
721 	return sCPULatencyHolderName[kCpuDelayBusStall];
722 }
723 
724 const char *getCpuInterruptDelayHolderName(void);
725 const char *
getCpuInterruptDelayHolderName(void)726 getCpuInterruptDelayHolderName(void)
727 {
728 	return sCPULatencyHolderName[kCpuDelayInterrupt];
729 }
730 }
731 #endif /* defined(__x86_64__) */
732 
733 
734 
735 #if IOMATCHDEBUG
736 static UInt64
getDebugFlags(OSDictionary * props)737 getDebugFlags( OSDictionary * props )
738 {
739 	OSNumber *  debugProp;
740 	UInt64      debugFlags;
741 
742 	debugProp = OSDynamicCast( OSNumber,
743 	    props->getObject( gIOKitDebugKey ));
744 	if (debugProp) {
745 		debugFlags = debugProp->unsigned64BitValue();
746 	} else {
747 		debugFlags = gIOKitDebug;
748 	}
749 
750 	return debugFlags;
751 }
752 
753 static UInt64
getDebugFlags(IOService * inst)754 getDebugFlags( IOService * inst )
755 {
756 	OSObject *  prop;
757 	OSNumber *  debugProp;
758 	UInt64      debugFlags;
759 
760 	prop = inst->copyProperty(gIOKitDebugKey);
761 	debugProp = OSDynamicCast(OSNumber, prop);
762 	if (debugProp) {
763 		debugFlags = debugProp->unsigned64BitValue();
764 	} else {
765 		debugFlags = gIOKitDebug;
766 	}
767 
768 	OSSafeReleaseNULL(prop);
769 
770 	return debugFlags;
771 }
772 #endif
773 
774 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
775 
776 // Probe a matched service and return an instance to be started.
777 // The default score is from the property table, & may be altered
778 // during probe to change the start order.
779 
780 IOService *
probe(IOService * provider,SInt32 * score)781 IOService::probe(   IOService * provider,
782     SInt32    * score )
783 {
784 	return this;
785 }
786 
787 bool
start(IOService * provider)788 IOService::start( IOService * provider )
789 {
790 	return true;
791 }
792 
793 void
stop(IOService * provider)794 IOService::stop( IOService * provider )
795 {
796 	if (reserved->uvars && reserved->uvars->userServer) {
797 		reserved->uvars->userServer->serviceStop(this, provider);
798 	}
799 }
800 
801 bool
init(OSDictionary * dictionary)802 IOService::init( OSDictionary * dictionary )
803 {
804 	bool ret;
805 
806 	ret = super::init(dictionary);
807 	if (!ret) {
808 		return false;
809 	}
810 	if (reserved) {
811 		return true;
812 	}
813 
814 	reserved = IOMallocType(ExpansionData);
815 	IOLockInlineInit(&reserved->interruptStatisticsLock);
816 	return true;
817 }
818 
819 bool
init(IORegistryEntry * from,const IORegistryPlane * inPlane)820 IOService::init( IORegistryEntry * from,
821     const IORegistryPlane * inPlane )
822 {
823 	bool ret;
824 
825 	ret = super::init(from, inPlane);
826 	if (!ret) {
827 		return false;
828 	}
829 	if (reserved) {
830 		return true;
831 	}
832 
833 	reserved = IOMallocType(ExpansionData);
834 	IOLockInlineInit(&reserved->interruptStatisticsLock);
835 
836 	return true;
837 }
838 
839 void
free(void)840 IOService::free( void )
841 {
842 	IOInterruptSourcePrivate *sourcesPrivate = NULL;
843 	int i = 0;
844 	requireMaxBusStall(0);
845 #if defined(__x86_64__)
846 	requireMaxInterruptDelay(0);
847 #endif /* defined(__x86_64__) */
848 	if (getPropertyTable()) {
849 		unregisterAllInterest();
850 	}
851 	PMfree();
852 
853 	if (reserved) {
854 		if (reserved->interruptStatisticsArray) {
855 			for (i = 0; i < reserved->interruptStatisticsArrayCount; i++) {
856 				if (reserved->interruptStatisticsArray[i].reporter) {
857 					reserved->interruptStatisticsArray[i].reporter->release();
858 				}
859 			}
860 
861 			IODelete(reserved->interruptStatisticsArray, IOInterruptAccountingReporter, reserved->interruptStatisticsArrayCount);
862 		}
863 
864 		if (reserved->uvars && reserved->uvars->userServer) {
865 			reserved->uvars->userServer->serviceFree(this);
866 		}
867 		sourcesPrivate = reserved->interruptSourcesPrivate;
868 		IOLockInlineDestroy(&reserved->interruptStatisticsLock);
869 		IOFreeType(reserved, ExpansionData);
870 	}
871 
872 	if (_numInterruptSources && _interruptSources) {
873 		assert(sourcesPrivate);
874 		for (i = 0; i < _numInterruptSources; i++) {
875 			void * block = sourcesPrivate[i].vectorBlock;
876 			if (block) {
877 				Block_release(block);
878 			}
879 		}
880 		IODelete(_interruptSources, IOInterruptSource, _numInterruptSources);
881 		_interruptSources = NULL;
882 		IODelete(sourcesPrivate, IOInterruptSourcePrivate, _numInterruptSources);
883 	}
884 
885 	super::free();
886 }
887 
888 /*
889  * Attach in service plane
890  */
891 bool
attach(IOService * provider)892 IOService::attach( IOService * provider )
893 {
894 	bool         ok;
895 	uint32_t     count;
896 	AbsoluteTime deadline;
897 	int          waitResult = THREAD_AWAKENED;
898 	bool         wait, computeDeadline = true;
899 
900 	if (provider) {
901 		if (gIOKitDebug & kIOLogAttach) {
902 			LOG( "%s[0x%qx]::attach(%s[0x%qx])\n", getName(), getRegistryEntryID(),
903 			    provider->getName(), provider->getRegistryEntryID());
904 		}
905 
906 		ok   = false;
907 		do{
908 			wait = false;
909 			provider->lockForArbitration();
910 			if (provider->__state[0] & kIOServiceInactiveState) {
911 				ok = false;
912 			} else {
913 				count = provider->getChildCount(gIOServicePlane);
914 				wait = (count > (kIOServiceBusyMax - 4));
915 				if (!wait) {
916 					ok = attachToParent(provider, gIOServicePlane);
917 				} else {
918 					IOLog("stalling for detach from %s\n", provider->getName());
919 					IOLockLock( gIOServiceBusyLock );
920 					provider->__state[1] |= kIOServiceWaitDetachState;
921 				}
922 			}
923 			provider->unlockForArbitration();
924 			if (wait) {
925 				if (computeDeadline) {
926 					clock_interval_to_deadline(15, kSecondScale, &deadline);
927 					computeDeadline = false;
928 				}
929 				assert_wait_deadline((event_t)&provider->__provider, THREAD_UNINT, deadline);
930 				IOLockUnlock( gIOServiceBusyLock );
931 				waitResult = thread_block(THREAD_CONTINUE_NULL);
932 				wait = (waitResult != THREAD_TIMED_OUT);
933 			}
934 		}while (wait);
935 	} else {
936 		gIOServiceRoot = this;
937 		ok = attachToParent( getRegistryRoot(), gIOServicePlane);
938 	}
939 
940 	if (ok && !__provider) {
941 		(void) getProvider();
942 	}
943 
944 	return ok;
945 }
946 
947 IOService *
getServiceRoot(void)948 IOService::getServiceRoot( void )
949 {
950 	return gIOServiceRoot;
951 }
952 
953 void
detach(IOService * provider)954 IOService::detach( IOService * provider )
955 {
956 	IOService * newProvider = NULL;
957 	SInt32      busy;
958 	bool        adjParent;
959 
960 	if (gIOKitDebug & kIOLogAttach) {
961 		LOG("%s[0x%qx]::detach(%s[0x%qx])\n", getName(), getRegistryEntryID(), provider->getName(), provider->getRegistryEntryID());
962 	}
963 
964 #if !NO_KEXTD
965 	IOLockLock(gJobsLock);
966 	if (gIOMatchDeferList) {
967 		auto idx = gIOMatchDeferList->getNextIndexOfObject(this, 0);
968 		if (-1U != idx) {
969 			gIOMatchDeferList->removeObject(idx);
970 		}
971 	}
972 	if (IOServicePH::fMatchingDelayed) {
973 		auto idx = IOServicePH::fMatchingDelayed->getNextIndexOfObject(this, 0);
974 		if (-1U != idx) {
975 			IOServicePH::fMatchingDelayed->removeObject(idx);
976 		}
977 	}
978 	IOLockUnlock(gJobsLock);
979 #endif /* NO_KEXTD */
980 
981 	lockForArbitration();
982 
983 	uint64_t regID1 = provider->getRegistryEntryID();
984 	uint64_t regID2 = getRegistryEntryID();
985 	IOServiceTrace(
986 		IOSERVICE_DETACH,
987 		(uintptr_t) regID1,
988 		(uintptr_t) (regID1 >> 32),
989 		(uintptr_t) regID2,
990 		(uintptr_t) (regID2 >> 32));
991 
992 	adjParent = ((busy = (__state[1] & kIOServiceBusyStateMask))
993 	    && (provider == getProvider()));
994 
995 	detachFromParent( provider, gIOServicePlane );
996 
997 	if (busy) {
998 		newProvider = getProvider();
999 		if (busy && (__state[1] & kIOServiceTermPhase3State) && (NULL == newProvider)) {
1000 			_adjustBusy( -busy );
1001 		}
1002 	}
1003 
1004 	if (kIOServiceInactiveState & __state[0]) {
1005 		getMetaClass()->removeInstance(this);
1006 		IORemoveServicePlatformActions(this);
1007 	}
1008 
1009 	unlockForArbitration();
1010 
1011 	if (newProvider && adjParent) {
1012 		newProvider->lockForArbitration();
1013 		newProvider->_adjustBusy(1);
1014 		newProvider->unlockForArbitration();
1015 	}
1016 
1017 	// check for last client detach from a terminated service
1018 	if (provider->lockForArbitration( true )) {
1019 		if (kIOServiceStartState & __state[1]) {
1020 			provider->scheduleTerminatePhase2();
1021 		}
1022 		if (adjParent) {
1023 			provider->_adjustBusy( -1 );
1024 		}
1025 		if ((provider->__state[1] & kIOServiceTermPhase3State)
1026 		    && (NULL == provider->getClient())) {
1027 			provider->scheduleFinalize(false);
1028 		}
1029 
1030 		IOLockLock( gIOServiceBusyLock );
1031 		if (kIOServiceWaitDetachState & provider->__state[1]) {
1032 			provider->__state[1] &= ~kIOServiceWaitDetachState;
1033 			thread_wakeup(&provider->__provider);
1034 		}
1035 		IOLockUnlock( gIOServiceBusyLock );
1036 
1037 		provider->unlockForArbitration();
1038 	}
1039 
1040 	if (kIOServiceRematchOnDetach & __state[1]) {
1041 		provider->registerService();
1042 	}
1043 }
1044 
1045 /*
1046  * Register instance - publish it for matching
1047  */
1048 
1049 void
registerService(IOOptionBits options)1050 IOService::registerService( IOOptionBits options )
1051 {
1052 	OSDataAllocation<char> pathBuf;
1053 	const char *        path;
1054 	const char *        skip;
1055 	int                 len;
1056 	enum { kMaxPathLen  = 256 };
1057 	enum { kMaxChars    = 63 };
1058 
1059 	IORegistryEntry * parent = this;
1060 	IORegistryEntry * root = getRegistryRoot();
1061 	while (parent && (parent != root)) {
1062 		parent = parent->getParentEntry( gIOServicePlane);
1063 	}
1064 
1065 	if (parent != root) {
1066 		IOLog("%s: not registry member at registerService()\n", getName());
1067 		return;
1068 	}
1069 
1070 	// Allow the Platform Expert to adjust this node.
1071 	if (gIOPlatform && (!gIOPlatform->platformAdjustService(this))) {
1072 		return;
1073 	}
1074 
1075 	IOInstallServicePlatformActions(this);
1076 	IOInstallServiceSleepPlatformActions(this);
1077 
1078 	if ((this != gIOResources)
1079 	    && (kIOLogRegister & gIOKitDebug)) {
1080 		pathBuf = OSDataAllocation<char>( kMaxPathLen, OSAllocateMemory );
1081 
1082 		IOLog( "Registering: " );
1083 
1084 		len = kMaxPathLen;
1085 		if (pathBuf && getPath( pathBuf.data(), &len, gIOServicePlane)) {
1086 			path = pathBuf.data();
1087 			if (len > kMaxChars) {
1088 				IOLog("..");
1089 				len -= kMaxChars;
1090 				path += len;
1091 				if ((skip = strchr( path, '/'))) {
1092 					path = skip;
1093 				}
1094 			}
1095 		} else {
1096 			path = getName();
1097 		}
1098 
1099 		IOLog( "%s\n", path );
1100 	}
1101 
1102 	startMatching( options );
1103 }
1104 
1105 void
startMatching(IOOptionBits options)1106 IOService::startMatching( IOOptionBits options )
1107 {
1108 	IOService * provider;
1109 	UInt32      prevBusy = 0;
1110 	bool        needConfig;
1111 	bool        needWake = false;
1112 	bool        sync;
1113 	bool        waitAgain;
1114 	bool        releaseAssertion = false;
1115 
1116 	if (options & kIOServiceDextRequirePowerForMatching) {
1117 		bool ok = gIOPMRootDomain->acquireDriverKitMatchingAssertion() == kIOReturnSuccess;
1118 		if (!ok) {
1119 			panic("%s: Failed to acquire power assertion for matching", getName());
1120 		}
1121 		releaseAssertion = true;
1122 	}
1123 
1124 	lockForArbitration();
1125 
1126 	sync = (options & kIOServiceSynchronous)
1127 	    || ((provider = getProvider())
1128 	    && (provider->__state[1] & kIOServiceSynchronousState));
1129 
1130 	if (options & kIOServiceAsynchronous) {
1131 		sync = false;
1132 	}
1133 
1134 	needConfig =  (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigRunning)))
1135 	    && (0 == (__state[0] & kIOServiceInactiveState));
1136 
1137 	__state[1] |= kIOServiceNeedConfigState;
1138 
1139 //    __state[0] &= ~kIOServiceInactiveState;
1140 
1141 //    if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
1142 //			OSKernelStackRemaining(), getName());
1143 
1144 	if (needConfig) {
1145 		needWake = (0 != (kIOServiceSyncPubState & __state[1]));
1146 	}
1147 
1148 	if (sync) {
1149 		__state[1] |= kIOServiceSynchronousState;
1150 	} else {
1151 		__state[1] &= ~kIOServiceSynchronousState;
1152 	}
1153 
1154 	if (needConfig) {
1155 		prevBusy = _adjustBusy( 1 );
1156 	}
1157 
1158 	unlockForArbitration();
1159 
1160 	if (needConfig) {
1161 		if (needWake) {
1162 			IOLockLock( gIOServiceBusyLock );
1163 			thread_wakeup((event_t) this /*&__state[1]*/ );
1164 			IOLockUnlock( gIOServiceBusyLock );
1165 		} else if (!sync || (kIOServiceAsynchronous & options)) {
1166 			// assertion will be released when matching job is complete
1167 			releaseAssertion = false;
1168 			_IOServiceJob::startJob( this, kMatchNubJob, options );
1169 		} else {
1170 			do {
1171 				if ((__state[1] & kIOServiceNeedConfigState)) {
1172 					doServiceMatch( options );
1173 				}
1174 
1175 				lockForArbitration();
1176 				IOLockLock( gIOServiceBusyLock );
1177 
1178 				waitAgain = ((prevBusy < (__state[1] & kIOServiceBusyStateMask))
1179 				    && (0 == (__state[0] & kIOServiceInactiveState)));
1180 
1181 				if (waitAgain) {
1182 					__state[1] |= kIOServiceSyncPubState | kIOServiceBusyWaiterState;
1183 				} else {
1184 					__state[1] &= ~kIOServiceSyncPubState;
1185 				}
1186 
1187 				unlockForArbitration();
1188 
1189 				if (waitAgain) {
1190 					assert_wait((event_t) this /*&__state[1]*/, THREAD_UNINT);
1191 				}
1192 
1193 				IOLockUnlock( gIOServiceBusyLock );
1194 				if (waitAgain) {
1195 					thread_block(THREAD_CONTINUE_NULL);
1196 				}
1197 			} while (waitAgain);
1198 		}
1199 	}
1200 
1201 	if (releaseAssertion) {
1202 		gIOPMRootDomain->releaseDriverKitMatchingAssertion();
1203 	}
1204 }
1205 
1206 
1207 void
startDeferredMatches(void)1208 IOService::startDeferredMatches(void)
1209 {
1210 #if !NO_KEXTD
1211 	OSArray * array;
1212 
1213 	IOLockLock(gJobsLock);
1214 	array = gIOMatchDeferList;
1215 	gIOMatchDeferList = NULL;
1216 	IOLockUnlock(gJobsLock);
1217 
1218 	if (array) {
1219 		IOLog("deferred rematching count %d\n", array->getCount());
1220 		array->iterateObjects(^bool (OSObject * obj)
1221 		{
1222 			((IOService *)obj)->startMatching(kIOServiceAsynchronous);
1223 			return false;
1224 		});
1225 		array->release();
1226 	}
1227 #endif /* !NO_KEXTD */
1228 }
1229 
1230 void
iokitDaemonLaunched(void)1231 IOService::iokitDaemonLaunched(void)
1232 {
1233 #if !NO_KEXTD
1234 	if (!OSKext::iokitDaemonAvailable()) {
1235 		panic(kIOKitDaemonName " is unavailable in this environment, but it was launched");
1236 	}
1237 	IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0);
1238 	startDeferredMatches();
1239 	getServiceRoot()->adjustBusy(-1);
1240 	IOService::publishUserResource(gIOResourceIOKitKey);
1241 #endif /* !NO_KEXTD */
1242 }
1243 
1244 /*
1245  * Possibly called with IORWLock from IOCatalog held.
1246  * This means that no calls to OSKext that could take
1247  * sKextLock can be performed from this function.
1248  */
1249 IOReturn
catalogNewDrivers(OSOrderedSet * newTables)1250 IOService::catalogNewDrivers( OSOrderedSet * newTables )
1251 {
1252 	OSDictionary *      table;
1253 	OSSet *             set;
1254 	OSSet *             allSet = NULL;
1255 	IOService *         service;
1256 #if IOMATCHDEBUG
1257 	SInt32              count = 0;
1258 #endif
1259 
1260 	newTables->retain();
1261 
1262 	while ((table = (OSDictionary *) newTables->getFirstObject())) {
1263 		LOCKWRITENOTIFY();
1264 		set = (OSSet *) copyExistingServices( table,
1265 		    kIOServiceRegisteredState,
1266 		    kIOServiceExistingSet);
1267 		UNLOCKNOTIFY();
1268 		if (set) {
1269 #if IOMATCHDEBUG
1270 			count += set->getCount();
1271 #endif
1272 			if (allSet) {
1273 				allSet->merge((const OSSet *) set);
1274 				set->release();
1275 			} else {
1276 				allSet = set;
1277 			}
1278 		}
1279 
1280 #if IOMATCHDEBUG
1281 		if (getDebugFlags( table ) & kIOLogMatch) {
1282 			LOG("Matching service count = %ld\n", (long)count);
1283 		}
1284 #endif
1285 		newTables->removeObject(table);
1286 	}
1287 
1288 	if (allSet) {
1289 		while ((service = (IOService *) allSet->getAnyObject())) {
1290 			service->startMatching(kIOServiceAsynchronous);
1291 			allSet->removeObject(service);
1292 		}
1293 		allSet->release();
1294 	}
1295 
1296 	newTables->release();
1297 
1298 	return kIOReturnSuccess;
1299 }
1300 
1301 _IOServiceJob *
startJob(IOService * nub,int type,IOOptionBits options)1302 _IOServiceJob::startJob( IOService * nub, int type,
1303     IOOptionBits options )
1304 {
1305 	_IOServiceJob *     job;
1306 
1307 	job = new _IOServiceJob;
1308 	if (job && !job->init()) {
1309 		job->release();
1310 		job = NULL;
1311 	}
1312 
1313 	if (job) {
1314 		job->type       = type;
1315 		job->nub        = nub;
1316 		job->options    = options;
1317 		nub->retain();          // thread will release()
1318 		pingConfig( job );
1319 	}
1320 
1321 	return job;
1322 }
1323 
1324 /*
1325  * Called on a registered service to see if it matches
1326  * a property table.
1327  */
1328 
1329 bool
matchPropertyTable(OSDictionary * table,SInt32 * score)1330 IOService::matchPropertyTable( OSDictionary * table, SInt32 * score )
1331 {
1332 	return matchPropertyTable(table);
1333 }
1334 
1335 bool
matchPropertyTable(OSDictionary * table)1336 IOService::matchPropertyTable( OSDictionary * table )
1337 {
1338 	return true;
1339 }
1340 
1341 /*
1342  * Called on a matched service to allocate resources
1343  * before first driver is attached.
1344  */
1345 
1346 IOReturn
getResources(void)1347 IOService::getResources( void )
1348 {
1349 	return kIOReturnSuccess;
1350 }
1351 
1352 /*
1353  * Client/provider accessors
1354  */
1355 
1356 IOService *
getProvider(void) const1357 IOService::getProvider( void ) const
1358 {
1359 	IOService * self = (IOService *) this;
1360 	IOService * parent;
1361 	SInt32      generation;
1362 
1363 	generation = getRegistryEntryParentGenerationCount();
1364 	if (__providerGeneration == generation) {
1365 		return __provider;
1366 	}
1367 
1368 	parent = (IOService *) getParentEntry( gIOServicePlane);
1369 	if (parent == IORegistryEntry::getRegistryRoot()) {
1370 		/* root is not an IOService */
1371 		parent = NULL;
1372 	}
1373 
1374 	self->__provider = parent;
1375 	OSMemoryBarrier();
1376 	// save the count from before call to getParentEntry()
1377 	self->__providerGeneration = generation;
1378 
1379 	return parent;
1380 }
1381 
1382 IOWorkLoop *
getWorkLoop() const1383 IOService::getWorkLoop() const
1384 {
1385 	IOService *provider = getProvider();
1386 
1387 	if (provider) {
1388 		return provider->getWorkLoop();
1389 	} else {
1390 		return NULL;
1391 	}
1392 }
1393 
1394 OSIterator *
getProviderIterator(void) const1395 IOService::getProviderIterator( void ) const
1396 {
1397 	return getParentIterator( gIOServicePlane);
1398 }
1399 
1400 IOService *
getClient(void) const1401 IOService::getClient( void ) const
1402 {
1403 	return (IOService *) getChildEntry( gIOServicePlane);
1404 }
1405 
1406 OSIterator *
getClientIterator(void) const1407 IOService::getClientIterator( void ) const
1408 {
1409 	return getChildIterator( gIOServicePlane);
1410 }
1411 
1412 OSIterator *
iterator(OSIterator * _iter,const IOService * client,const IOService * provider)1413 _IOOpenServiceIterator::iterator( OSIterator * _iter,
1414     const IOService * client,
1415     const IOService * provider )
1416 {
1417 	_IOOpenServiceIterator * inst;
1418 
1419 	if (!_iter) {
1420 		return NULL;
1421 	}
1422 
1423 	inst = new _IOOpenServiceIterator;
1424 
1425 	if (inst && !inst->init()) {
1426 		inst->release();
1427 		inst = NULL;
1428 	}
1429 	if (inst) {
1430 		inst->iter = _iter;
1431 		inst->client = client;
1432 		inst->provider = provider;
1433 	} else {
1434 		OSSafeReleaseNULL(_iter);
1435 	}
1436 
1437 	return inst;
1438 }
1439 
1440 void
free()1441 _IOOpenServiceIterator::free()
1442 {
1443 	iter->release();
1444 	if (last) {
1445 		last->unlockForArbitration();
1446 	}
1447 	OSIterator::free();
1448 }
1449 
1450 OSObject *
getNextObject()1451 _IOOpenServiceIterator::getNextObject()
1452 {
1453 	IOService * next;
1454 
1455 	if (last) {
1456 		last->unlockForArbitration();
1457 	}
1458 
1459 	while ((next = (IOService *) iter->getNextObject())) {
1460 		next->lockForArbitration();
1461 		if ((client && (next->isOpen( client )))
1462 		    || (provider && (provider->isOpen( next )))) {
1463 			break;
1464 		}
1465 		next->unlockForArbitration();
1466 	}
1467 
1468 	last = next;
1469 
1470 	return next;
1471 }
1472 
1473 bool
isValid()1474 _IOOpenServiceIterator::isValid()
1475 {
1476 	return iter->isValid();
1477 }
1478 
1479 void
reset()1480 _IOOpenServiceIterator::reset()
1481 {
1482 	if (last) {
1483 		last->unlockForArbitration();
1484 		last = NULL;
1485 	}
1486 	iter->reset();
1487 }
1488 
1489 OSIterator *
getOpenProviderIterator(void) const1490 IOService::getOpenProviderIterator( void ) const
1491 {
1492 	return _IOOpenServiceIterator::iterator( getProviderIterator(), this, NULL );
1493 }
1494 
1495 OSIterator *
getOpenClientIterator(void) const1496 IOService::getOpenClientIterator( void ) const
1497 {
1498 	return _IOOpenServiceIterator::iterator( getClientIterator(), NULL, this );
1499 }
1500 
1501 
1502 IOReturn
callPlatformFunction(const OSSymbol * functionName,bool waitForFunction,void * param1,void * param2,void * param3,void * param4)1503 IOService::callPlatformFunction( const OSSymbol * functionName,
1504     bool waitForFunction,
1505     void *param1, void *param2,
1506     void *param3, void *param4 )
1507 {
1508 	IOReturn  result = kIOReturnUnsupported;
1509 	IOService *provider;
1510 
1511 	if (functionName == gIOPlatformQuiesceActionKey ||
1512 	    functionName == gIOPlatformActiveActionKey ||
1513 	    functionName == gIOPlatformPanicActionKey) {
1514 		/*
1515 		 * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction / IOPlatformPanicAction
1516 		 * must consume that event themselves, without passing it up to super/IOService.
1517 		 */
1518 		if (gEnforcePlatformActionSafety) {
1519 			panic("Class %s passed the %s action to IOService",
1520 			    getMetaClass()->getClassName(), functionName->getCStringNoCopy());
1521 		}
1522 	}
1523 
1524 	if (gIOPlatformFunctionHandlerSet == functionName) {
1525 		const OSSymbol * functionHandlerName = (const OSSymbol *) param1;
1526 		IOService *      target              = (IOService *) param2;
1527 		bool             enable              = (param3 != NULL);
1528 
1529 		if (sCPULatencyFunctionName[kCpuDelayBusStall] == functionHandlerName) {
1530 			result = setLatencyHandler(kCpuDelayBusStall, target, enable);
1531 		}
1532 #if defined(__x86_64__)
1533 		else if (sCPULatencyFunctionName[kCpuDelayInterrupt] == param1) {
1534 			result = setLatencyHandler(kCpuDelayInterrupt, target, enable);
1535 		}
1536 #endif /* defined(__x86_64__) */
1537 	}
1538 
1539 	if ((kIOReturnUnsupported == result) && (provider = getProvider())) {
1540 		result = provider->callPlatformFunction(functionName, waitForFunction,
1541 		    param1, param2, param3, param4);
1542 	}
1543 
1544 	return result;
1545 }
1546 
1547 IOReturn
callPlatformFunction(const char * functionName,bool waitForFunction,void * param1,void * param2,void * param3,void * param4)1548 IOService::callPlatformFunction( const char * functionName,
1549     bool waitForFunction,
1550     void *param1, void *param2,
1551     void *param3, void *param4 )
1552 {
1553 	IOReturn result = kIOReturnNoMemory;
1554 	const OSSymbol *functionSymbol = OSSymbol::withCString(functionName);
1555 
1556 	if (functionSymbol != NULL) {
1557 		result = callPlatformFunction(functionSymbol, waitForFunction,
1558 		    param1, param2, param3, param4);
1559 		functionSymbol->release();
1560 	}
1561 
1562 	return result;
1563 }
1564 
1565 
1566 /*
1567  * Accessors for global services
1568  */
1569 
1570 IOPlatformExpert *
getPlatform(void)1571 IOService::getPlatform( void )
1572 {
1573 	return gIOPlatform;
1574 }
1575 
1576 class IOPMrootDomain *
getPMRootDomain(void)1577 	IOService::getPMRootDomain( void )
1578 {
1579 	return gIOPMRootDomain;
1580 }
1581 
1582 IOService *
getResourceService(void)1583 IOService::getResourceService( void )
1584 {
1585 	return gIOResources;
1586 }
1587 
1588 IOService * gIOSystemStateNotificationService;
1589 
1590 IOService *
getSystemStateNotificationService(void)1591 IOService::getSystemStateNotificationService(void)
1592 {
1593 	return gIOSystemStateNotificationService;
1594 }
1595 
1596 void
setPlatform(IOPlatformExpert * platform)1597 IOService::setPlatform( IOPlatformExpert * platform)
1598 {
1599 	gIOPlatform = platform;
1600 	gIOResources->attachToParent( gIOServiceRoot, gIOServicePlane );
1601 
1602 	gIOUserResources->attachToParent( gIOServiceRoot, gIOServicePlane );
1603 
1604 #if DEVELOPMENT || DEBUG
1605 	// Test object that will be terminated for dext to match
1606 	{
1607 		IOService * ios;
1608 		ios = OSTypeAlloc(IOService);
1609 		ios->init();
1610 		ios->attach(gIOUserResources);
1611 		ios->setProperty(gIOMatchCategoryKey->getCStringNoCopy(), "com.apple.iokit.test");
1612 		ios->setProperty(gIOModuleIdentifierKey->getCStringNoCopy(), "com.apple.kpi.iokit");
1613 		ios->setProperty(gIOMatchedAtBootKey, kOSBooleanTrue);
1614 		ios->setProperty(gIOPrimaryDriverTerminateOptionsKey, kOSBooleanTrue);
1615 		ios->release();
1616 	}
1617 #endif
1618 
1619 	gIOSystemStateNotificationService = IOSystemStateNotification::initialize();
1620 	gIOSystemStateNotificationService->attachToParent(platform, gIOServicePlane);
1621 	gIOSystemStateNotificationService->registerService();
1622 
1623 	static const char * keys[kCpuNumDelayTypes] = {
1624 		kIOPlatformMaxBusDelay,
1625 #if defined(__x86_64__)
1626 		kIOPlatformMaxInterruptDelay
1627 #endif /* defined(__x86_64__) */
1628 	};
1629 	const OSObject * objs[2];
1630 	OSArray * array;
1631 	uint32_t  idx;
1632 
1633 	for (idx = 0; idx < kCpuNumDelayTypes; idx++) {
1634 		objs[0] = sCPULatencySet[idx];
1635 		objs[1] = sCPULatencyHolder[idx];
1636 		array   = OSArray::withObjects(objs, 2);
1637 		if (!array) {
1638 			break;
1639 		}
1640 		platform->setProperty(keys[idx], array);
1641 		array->release();
1642 	}
1643 }
1644 
1645 void
setPMRootDomain(class IOPMrootDomain * rootDomain)1646 IOService::setPMRootDomain( class IOPMrootDomain * rootDomain)
1647 {
1648 	gIOPMRootDomain = rootDomain;
1649 }
1650 
1651 void
publishPMRootDomain(void)1652 IOService::publishPMRootDomain( void )
1653 {
1654 	assert(getPMRootDomain() != NULL);
1655 	publishResource(gIOResourceIOKitKey);
1656 #if NO_KEXTD
1657 	// Publish IOUserResources now since there is no IOKit daemon.
1658 	publishUserResource(gIOResourceIOKitKey);
1659 #endif
1660 	IOServicePH::init(getPMRootDomain());
1661 }
1662 
1663 /*
1664  * Stacking change
1665  */
1666 
1667 bool
lockForArbitration(bool isSuccessRequired)1668 IOService::lockForArbitration( bool isSuccessRequired )
1669 {
1670 	bool                          found;
1671 	bool                          success;
1672 	ArbitrationLockQueueElement * element;
1673 	ArbitrationLockQueueElement * owner;
1674 	ArbitrationLockQueueElement * active;
1675 	ArbitrationLockQueueElement * waiting;
1676 
1677 	enum { kPutOnFreeQueue, kPutOnActiveQueue, kPutOnWaitingQueue } action;
1678 
1679 	// lock global access
1680 	IOTakeLock( gArbitrationLockQueueLock );
1681 
1682 	// obtain an unused queue element
1683 	if (!queue_empty( &gArbitrationLockQueueFree )) {
1684 		queue_remove_first( &gArbitrationLockQueueFree,
1685 		    element,
1686 		    ArbitrationLockQueueElement *,
1687 		    link );
1688 	} else {
1689 		element = IOMallocType(ArbitrationLockQueueElement);
1690 		assert( element );
1691 	}
1692 
1693 	// prepare the queue element
1694 	element->thread   = IOThreadSelf();
1695 	element->service  = this;
1696 	element->count    = 1;
1697 	element->required = isSuccessRequired;
1698 	element->aborted  = false;
1699 
1700 	// determine whether this object is already locked (ie. on active queue)
1701 	found = false;
1702 	queue_iterate( &gArbitrationLockQueueActive,
1703 	    owner,
1704 	    ArbitrationLockQueueElement *,
1705 	    link )
1706 	{
1707 		if (owner->service == element->service) {
1708 			found = true;
1709 			break;
1710 		}
1711 	}
1712 
1713 	if (found) { // this object is already locked
1714 		active = owner;
1715 		// determine whether it is the same or a different thread trying to lock
1716 		if (active->thread != element->thread) { // it is a different thread
1717 			ArbitrationLockQueueElement * victim = NULL;
1718 
1719 			// before placing this new thread on the waiting queue, we look for
1720 			// a deadlock cycle...
1721 
1722 			while (1) {
1723 				// determine whether the active thread holding the object we
1724 				// want is waiting for another object to be unlocked
1725 				found = false;
1726 				queue_iterate( &gArbitrationLockQueueWaiting,
1727 				    waiting,
1728 				    ArbitrationLockQueueElement *,
1729 				    link )
1730 				{
1731 					if (waiting->thread == active->thread) {
1732 						assert( false == waiting->aborted );
1733 						found = true;
1734 						break;
1735 					}
1736 				}
1737 
1738 				if (found) { // yes, active thread waiting for another object
1739 					// this may be a candidate for rejection if the required
1740 					// flag is not set, should we detect a deadlock later on
1741 					if (false == waiting->required) {
1742 						victim = waiting;
1743 					}
1744 
1745 					// find the thread that is holding this other object, that
1746 					// is blocking the active thread from proceeding (fun :-)
1747 					found = false;
1748 					queue_iterate( &gArbitrationLockQueueActive,
1749 					    active, // (reuse active queue element)
1750 					    ArbitrationLockQueueElement *,
1751 					    link )
1752 					{
1753 						if (active->service == waiting->service) {
1754 							found = true;
1755 							break;
1756 						}
1757 					}
1758 
1759 					// someone must be holding it or it wouldn't be waiting
1760 					assert( found );
1761 
1762 					if (active->thread == element->thread) {
1763 						// doh, it's waiting for the thread that originated
1764 						// this whole lock (ie. current thread) -> deadlock
1765 						if (false == element->required) { // willing to fail?
1766 							// the originating thread doesn't have the required
1767 							// flag, so it can fail
1768 							success = false; // (fail originating lock request)
1769 							break; // (out of while)
1770 						} else { // originating thread is not willing to fail
1771 							// see if we came across a waiting thread that did
1772 							// not have the 'required' flag set: we'll fail it
1773 							if (victim) {
1774 								// we do have a willing victim, fail it's lock
1775 								victim->aborted = true;
1776 
1777 								// take the victim off the waiting queue
1778 								queue_remove( &gArbitrationLockQueueWaiting,
1779 								    victim,
1780 								    ArbitrationLockQueueElement *,
1781 								    link );
1782 
1783 								// wake the victim
1784 								wakeup_thread_with_inheritor(&victim->service->__machPortHoldDestroy, // event
1785 								    THREAD_AWAKENED, LCK_WAKE_DEFAULT, victim->thread);
1786 
1787 								// allow this thread to proceed (ie. wait)
1788 								success = true; // (put request on wait queue)
1789 								break; // (out of while)
1790 							} else {
1791 								// all the waiting threads we came across in
1792 								// finding this loop had the 'required' flag
1793 								// set, so we've got a deadlock we can't avoid
1794 								panic("I/O Kit: Unrecoverable deadlock.");
1795 							}
1796 						}
1797 					} else {
1798 						// repeat while loop, redefining active thread to be the
1799 						// thread holding "this other object" (see above), and
1800 						// looking for threads waiting on it; note the active
1801 						// variable points to "this other object" already... so
1802 						// there nothing to do in this else clause.
1803 					}
1804 				} else { // no, active thread is not waiting for another object
1805 					success = true; // (put request on wait queue)
1806 					break; // (out of while)
1807 				}
1808 			} // while forever
1809 
1810 			if (success) { // put the request on the waiting queue?
1811 				kern_return_t wait_result;
1812 
1813 				// place this thread on the waiting queue and put it to sleep;
1814 				// we place it at the tail of the queue...
1815 				queue_enter( &gArbitrationLockQueueWaiting,
1816 				    element,
1817 				    ArbitrationLockQueueElement *,
1818 				    link );
1819 
1820 				// declare that this thread will wait for a given event
1821 restart_sleep:
1822 				// unlock global access
1823 				// & put thread to sleep, waiting for our event to fire...
1824 				wait_result = IOLockSleepWithInheritor(gArbitrationLockQueueLock,
1825 				    LCK_SLEEP_UNLOCK,
1826 				    &element->service->__machPortHoldDestroy,     // event
1827 				    owner->thread,
1828 				    element->required ? THREAD_UNINT : THREAD_INTERRUPTIBLE, TIMEOUT_WAIT_FOREVER);
1829 
1830 				// ...and we've been woken up; we might be in one of two states:
1831 				// (a) we've been aborted and our queue element is not on
1832 				//     any of the three queues, but is floating around
1833 				// (b) we're allowed to proceed with the lock and we have
1834 				//     already been moved from the waiting queue to the
1835 				//     active queue.
1836 				// ...plus a 3rd state, should the thread have been interrupted:
1837 				// (c) we're still on the waiting queue
1838 
1839 				// determine whether we were interrupted out of our sleep
1840 				if (THREAD_INTERRUPTED == wait_result) {
1841 					// re-lock global access
1842 					IOTakeLock( gArbitrationLockQueueLock );
1843 
1844 					// determine whether we're still on the waiting queue
1845 					found = false;
1846 					queue_iterate( &gArbitrationLockQueueWaiting,
1847 					    waiting, // (reuse waiting queue element)
1848 					    ArbitrationLockQueueElement *,
1849 					    link )
1850 					{
1851 						if (waiting == element) {
1852 							found = true;
1853 							break;
1854 						}
1855 					}
1856 
1857 					if (found) { // yes, we're still on the waiting queue
1858 						// determine whether we're willing to fail
1859 						if (false == element->required) {
1860 							// mark us as aborted
1861 							element->aborted = true;
1862 
1863 							// take us off the waiting queue
1864 							queue_remove( &gArbitrationLockQueueWaiting,
1865 							    element,
1866 							    ArbitrationLockQueueElement *,
1867 							    link );
1868 						} else { // we are not willing to fail
1869 							// ignore interruption, go back to sleep
1870 							goto restart_sleep;
1871 						}
1872 					}
1873 
1874 					// unlock global access
1875 					IOUnlock( gArbitrationLockQueueLock );
1876 
1877 					// proceed as though this were a normal wake up
1878 					wait_result = THREAD_AWAKENED;
1879 				}
1880 
1881 				assert( THREAD_AWAKENED == wait_result );
1882 
1883 				// determine whether we've been aborted while we were asleep
1884 				if (element->aborted) {
1885 					assert( false == element->required );
1886 					// re-lock global access
1887 					IOTakeLock( gArbitrationLockQueueLock );
1888 
1889 					action = kPutOnFreeQueue;
1890 					success = false;
1891 				} else { // we weren't aborted, so we must be ready to go :-)
1892 					// we've already been moved from waiting to active queue
1893 					return true;
1894 				}
1895 			} else { // the lock request is to be failed
1896 				// return unused queue element to queue
1897 				action = kPutOnFreeQueue;
1898 			}
1899 		} else { // it is the same thread, recursive access is allowed
1900 			// add one level of recursion
1901 			active->count++;
1902 
1903 			// return unused queue element to queue
1904 			action = kPutOnFreeQueue;
1905 			success = true;
1906 		}
1907 	} else { // this object is not already locked, so let this thread through
1908 		action = kPutOnActiveQueue;
1909 		success = true;
1910 	}
1911 
1912 	// put the new element on a queue
1913 	if (kPutOnActiveQueue == action) {
1914 		queue_enter( &gArbitrationLockQueueActive,
1915 		    element,
1916 		    ArbitrationLockQueueElement *,
1917 		    link );
1918 	} else if (kPutOnFreeQueue == action) {
1919 		queue_enter( &gArbitrationLockQueueFree,
1920 		    element,
1921 		    ArbitrationLockQueueElement *,
1922 		    link );
1923 	} else {
1924 		assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
1925 	}
1926 
1927 	// unlock global access
1928 	IOUnlock( gArbitrationLockQueueLock );
1929 
1930 	return success;
1931 }
1932 
1933 void
unlockForArbitration(void)1934 IOService::unlockForArbitration( void )
1935 {
1936 	bool                          found;
1937 	ArbitrationLockQueueElement * element;
1938 
1939 	// lock global access
1940 	IOTakeLock( gArbitrationLockQueueLock );
1941 
1942 	// find the lock element for this object (ie. on active queue)
1943 	found = false;
1944 	queue_iterate( &gArbitrationLockQueueActive,
1945 	    element,
1946 	    ArbitrationLockQueueElement *,
1947 	    link )
1948 	{
1949 		if (element->service == this) {
1950 			found = true;
1951 			break;
1952 		}
1953 	}
1954 
1955 	assert( found );
1956 
1957 	// determine whether the lock has been taken recursively
1958 	if (element->count > 1) {
1959 		// undo one level of recursion
1960 		element->count--;
1961 	} else {
1962 		// remove it from the active queue
1963 		queue_remove( &gArbitrationLockQueueActive,
1964 		    element,
1965 		    ArbitrationLockQueueElement *,
1966 		    link );
1967 
1968 		// put it on the free queue
1969 		queue_enter( &gArbitrationLockQueueFree,
1970 		    element,
1971 		    ArbitrationLockQueueElement *,
1972 		    link );
1973 
1974 		// determine whether a thread is waiting for object
1975 		thread_t woken;
1976 		kern_return_t kr =
1977 		    wakeup_one_with_inheritor(&__machPortHoldDestroy, // event
1978 		    THREAD_AWAKENED, LCK_WAKE_DEFAULT, &woken);
1979 
1980 		if (KERN_SUCCESS == kr) {
1981 			found = false;
1982 			queue_iterate( &gArbitrationLockQueueWaiting,
1983 			    element,
1984 			    ArbitrationLockQueueElement *,
1985 			    link )
1986 			{
1987 				if (element->thread == woken) {
1988 					found = true;
1989 					break;
1990 				}
1991 			}
1992 			assert(found); // we found an interested thread on waiting queue
1993 			// remove it from the waiting queue
1994 			queue_remove( &gArbitrationLockQueueWaiting,
1995 			    element,
1996 			    ArbitrationLockQueueElement *,
1997 			    link );
1998 
1999 			// put it on the active queue
2000 			queue_enter( &gArbitrationLockQueueActive,
2001 			    element,
2002 			    ArbitrationLockQueueElement *,
2003 			    link );
2004 
2005 			thread_deallocate(woken);
2006 		}
2007 	}
2008 
2009 	// unlock global access
2010 	IOUnlock( gArbitrationLockQueueLock );
2011 }
2012 
2013 uint32_t
isLockedForArbitration(IOService * service)2014 IOService::isLockedForArbitration(IOService * service)
2015 {
2016 #if DEBUG_NOTIFIER_LOCKED
2017 	uint32_t                      count;
2018 	ArbitrationLockQueueElement * active;
2019 
2020 	// lock global access
2021 	IOLockLock(gArbitrationLockQueueLock);
2022 
2023 	// determine whether this object is already locked (ie. on active queue)
2024 	count = 0;
2025 	queue_iterate(&gArbitrationLockQueueActive,
2026 	    active,
2027 	    ArbitrationLockQueueElement *,
2028 	    link)
2029 	{
2030 		if ((active->thread == IOThreadSelf())
2031 		    && (!service || (active->service == service))) {
2032 			count += 0x10000;
2033 			count += active->count;
2034 		}
2035 	}
2036 
2037 	IOLockUnlock(gArbitrationLockQueueLock);
2038 
2039 	return count;
2040 
2041 #else /* DEBUG_NOTIFIER_LOCKED */
2042 
2043 	return 0;
2044 
2045 #endif /* DEBUG_NOTIFIER_LOCKED */
2046 }
2047 
2048 void
setMachPortHoldDestroy(bool holdDestroy)2049 IOService::setMachPortHoldDestroy(bool holdDestroy)
2050 {
2051 	__machPortHoldDestroy = holdDestroy;
2052 }
2053 
2054 bool
machPortHoldDestroy()2055 IOService::machPortHoldDestroy()
2056 {
2057 	return __machPortHoldDestroy;
2058 }
2059 
2060 void
applyToProviders(IOServiceApplierFunction applier,void * context)2061 IOService::applyToProviders( IOServiceApplierFunction applier,
2062     void * context )
2063 {
2064 	applyToParents((IORegistryEntryApplierFunction) applier,
2065 	    context, gIOServicePlane );
2066 }
2067 
2068 void
applyToClients(IOServiceApplierFunction applier,void * context)2069 IOService::applyToClients( IOServiceApplierFunction applier,
2070     void * context )
2071 {
2072 	applyToChildren((IORegistryEntryApplierFunction) applier,
2073 	    context, gIOServicePlane );
2074 }
2075 
2076 
2077 static void
IOServiceApplierToBlock(IOService * next,void * context)2078 IOServiceApplierToBlock(IOService * next, void * context)
2079 {
2080 	IOServiceApplierBlock block = (IOServiceApplierBlock) context;
2081 	block(next);
2082 }
2083 
2084 void
applyToProviders(IOServiceApplierBlock applier)2085 IOService::applyToProviders(IOServiceApplierBlock applier)
2086 {
2087 	applyToProviders(&IOServiceApplierToBlock, applier);
2088 }
2089 
2090 void
applyToClients(IOServiceApplierBlock applier)2091 IOService::applyToClients(IOServiceApplierBlock applier)
2092 {
2093 	applyToClients(&IOServiceApplierToBlock, applier);
2094 }
2095 
2096 /*
2097  * Client messages
2098  */
2099 
2100 
2101 // send a message to a client or interested party of this service
2102 IOReturn
messageClient(UInt32 type,OSObject * client,void * argument,vm_size_t argSize)2103 IOService::messageClient( UInt32 type, OSObject * client,
2104     void * argument, vm_size_t argSize )
2105 {
2106 	IOReturn                            ret;
2107 	IOService *                         service;
2108 	_IOServiceInterestNotifier *        notify;
2109 
2110 	if ((service = OSDynamicCast( IOService, client))) {
2111 		ret = service->message( type, this, argument );
2112 	} else if ((notify = OSDynamicCast( _IOServiceInterestNotifier, client))) {
2113 		_IOServiceNotifierInvocation invocation;
2114 		bool                     willNotify;
2115 
2116 		invocation.thread = current_thread();
2117 
2118 		LOCKWRITENOTIFY();
2119 		willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
2120 
2121 		if (willNotify) {
2122 			queue_enter( &notify->handlerInvocations, &invocation,
2123 			    _IOServiceNotifierInvocation *, link );
2124 		}
2125 		UNLOCKNOTIFY();
2126 
2127 		if (willNotify) {
2128 			ret = (*notify->handler)( notify->target, notify->ref,
2129 			    type, this, argument, argSize );
2130 
2131 			LOCKWRITENOTIFY();
2132 			queue_remove( &notify->handlerInvocations, &invocation,
2133 			    _IOServiceNotifierInvocation *, link );
2134 			if (kIOServiceNotifyWaiter & notify->state) {
2135 				notify->state &= ~kIOServiceNotifyWaiter;
2136 				WAKEUPNOTIFY( notify );
2137 			}
2138 			UNLOCKNOTIFY();
2139 		} else {
2140 			ret = kIOReturnSuccess;
2141 		}
2142 	} else {
2143 		ret = kIOReturnBadArgument;
2144 	}
2145 
2146 	return ret;
2147 }
2148 
2149 static void
applyToInterestNotifiers(const IORegistryEntry * target,const OSSymbol * typeOfInterest,OSObjectApplierFunction applier,void * context)2150 applyToInterestNotifiers(const IORegistryEntry *target,
2151     const OSSymbol * typeOfInterest,
2152     OSObjectApplierFunction applier,
2153     void * context )
2154 {
2155 	OSArray *  copyArray = NULL;
2156 	OSObject * prop;
2157 
2158 	LOCKREADNOTIFY();
2159 
2160 	prop = target->copyProperty(typeOfInterest);
2161 	IOCommand *notifyList = OSDynamicCast(IOCommand, prop);
2162 
2163 	if (notifyList) {
2164 		copyArray = OSArray::withCapacity(1);
2165 
2166 		// iterate over queue, entry is set to each element in the list
2167 		iterqueue(&notifyList->fCommandChain, entry) {
2168 			_IOServiceInterestNotifier * notify;
2169 
2170 			queue_element(entry, notify, _IOServiceInterestNotifier *, chain);
2171 			copyArray->setObject(notify);
2172 		}
2173 	}
2174 	UNLOCKNOTIFY();
2175 
2176 	if (copyArray) {
2177 		unsigned int    index;
2178 		OSObject *      next;
2179 
2180 		for (index = 0; (next = copyArray->getObject( index )); index++) {
2181 			(*applier)(next, context);
2182 		}
2183 		copyArray->release();
2184 	}
2185 
2186 	OSSafeReleaseNULL(prop);
2187 }
2188 
2189 void
applyToInterested(const OSSymbol * typeOfInterest,OSObjectApplierFunction applier,void * context)2190 IOService::applyToInterested( const OSSymbol * typeOfInterest,
2191     OSObjectApplierFunction applier,
2192     void * context )
2193 {
2194 	if (gIOGeneralInterest == typeOfInterest) {
2195 		applyToClients((IOServiceApplierFunction) applier, context );
2196 	}
2197 	applyToInterestNotifiers(this, typeOfInterest, applier, context);
2198 }
2199 
2200 struct MessageClientsContext {
2201 	IOService * service;
2202 	UInt32      type;
2203 	void *      argument;
2204 	vm_size_t   argSize;
2205 	IOReturn    ret;
2206 };
2207 
2208 static void
messageClientsApplier(OSObject * object,void * ctx)2209 messageClientsApplier( OSObject * object, void * ctx )
2210 {
2211 	IOReturn                ret;
2212 	MessageClientsContext * context = (MessageClientsContext *) ctx;
2213 
2214 	ret = context->service->messageClient( context->type,
2215 	    object, context->argument, context->argSize );
2216 	if (kIOReturnSuccess != ret) {
2217 		context->ret = ret;
2218 	}
2219 }
2220 
2221 // send a message to all clients
2222 IOReturn
messageClients(UInt32 type,void * argument,vm_size_t argSize)2223 IOService::messageClients( UInt32 type,
2224     void * argument, vm_size_t argSize )
2225 {
2226 	MessageClientsContext       context;
2227 
2228 	context.service     = this;
2229 	context.type        = type;
2230 	context.argument    = argument;
2231 	context.argSize     = argSize;
2232 	context.ret         = kIOReturnSuccess;
2233 
2234 	applyToInterested( gIOGeneralInterest,
2235 	    &messageClientsApplier, &context );
2236 
2237 	return context.ret;
2238 }
2239 
2240 IOReturn
acknowledgeNotification(IONotificationRef notification,IOOptionBits response)2241 IOService::acknowledgeNotification( IONotificationRef notification,
2242     IOOptionBits response )
2243 {
2244 	return kIOReturnUnsupported;
2245 }
2246 
2247 IONotifier *
registerInterest(const OSSymbol * typeOfInterest,IOServiceInterestHandler handler,void * target,void * ref)2248 IOService::registerInterest( const OSSymbol * typeOfInterest,
2249     IOServiceInterestHandler handler, void * target, void * ref )
2250 {
2251 	_IOServiceInterestNotifier * notify = NULL;
2252 	IOReturn rc = kIOReturnError;
2253 
2254 	notify = new _IOServiceInterestNotifier;
2255 	if (!notify) {
2256 		return NULL;
2257 	}
2258 
2259 	if (notify->init()) {
2260 		rc = registerInterestForNotifier(notify, typeOfInterest,
2261 		    handler, target, ref);
2262 	}
2263 
2264 	if (rc != kIOReturnSuccess) {
2265 		notify->release();
2266 		notify = NULL;
2267 	}
2268 
2269 	return notify;
2270 }
2271 
2272 
2273 
2274 static IOReturn
IOServiceInterestHandlerToBlock(void * target __unused,void * refCon,UInt32 messageType,IOService * provider,void * messageArgument,vm_size_t argSize)2275 IOServiceInterestHandlerToBlock( void * target __unused, void * refCon,
2276     UInt32 messageType, IOService * provider,
2277     void * messageArgument, vm_size_t argSize )
2278 {
2279 	return ((IOServiceInterestHandlerBlock) refCon)(messageType, provider, messageArgument, argSize);
2280 }
2281 
2282 IONotifier *
registerInterest(const OSSymbol * typeOfInterest,IOServiceInterestHandlerBlock handler)2283 IOService::registerInterest(const OSSymbol * typeOfInterest,
2284     IOServiceInterestHandlerBlock handler)
2285 {
2286 	IONotifier * notify;
2287 
2288 	notify = registerInterest(typeOfInterest, &IOServiceInterestHandlerToBlock, NULL, handler);
2289 	return notify;
2290 }
2291 
2292 IOReturn
registerInterestForNotifier(IONotifier * svcNotify,const OSSymbol * typeOfInterest,IOServiceInterestHandler handler,void * target,void * ref)2293 IOService::registerInterestForNotifier( IONotifier *svcNotify, const OSSymbol * typeOfInterest,
2294     IOServiceInterestHandler handler, void * target, void * ref )
2295 {
2296 	IOReturn rc = kIOReturnSuccess;
2297 	_IOServiceInterestNotifier  *notify = NULL;
2298 
2299 
2300 	if (!svcNotify || !(notify = OSDynamicCast(_IOServiceInterestNotifier, svcNotify)) || !handler) {
2301 		return kIOReturnBadArgument;
2302 	}
2303 
2304 	notify->handler = handler;
2305 	notify->target = target;
2306 	if (handler == &IOServiceInterestHandlerToBlock) {
2307 		notify->ref = Block_copy(ref);
2308 	} else {
2309 		notify->ref = ref;
2310 	}
2311 
2312 	if ((typeOfInterest != gIOGeneralInterest)
2313 	    && (typeOfInterest != gIOBusyInterest)
2314 	    && (typeOfInterest != gIOAppPowerStateInterest)
2315 	    && (typeOfInterest != gIOConsoleSecurityInterest)
2316 	    && (typeOfInterest != gIOPriorityPowerStateInterest)) {
2317 		return kIOReturnBadArgument;
2318 	}
2319 
2320 	lockForArbitration();
2321 	if (0 == (__state[0] & kIOServiceInactiveState)) {
2322 		notify->state = kIOServiceNotifyEnable;
2323 
2324 		////// queue
2325 
2326 		LOCKWRITENOTIFY();
2327 
2328 		// Get the head of the notifier linked list
2329 		IOCommand * notifyList;
2330 		OSObject  * obj = copyProperty( typeOfInterest );
2331 		if (!(notifyList = OSDynamicCast(IOCommand, obj))) {
2332 			notifyList = OSTypeAlloc(IOCommand);
2333 			if (notifyList) {
2334 				notifyList->init();
2335 				bool ok = setProperty( typeOfInterest, notifyList);
2336 				notifyList->release();
2337 				if (!ok) {
2338 					notifyList = NULL;
2339 				}
2340 			}
2341 		}
2342 		if (obj) {
2343 			obj->release();
2344 		}
2345 
2346 		if (notifyList) {
2347 			enqueue(&notifyList->fCommandChain, &notify->chain);
2348 			notify->retain(); // ref'ed while in list
2349 		}
2350 
2351 		UNLOCKNOTIFY();
2352 	} else {
2353 		rc = kIOReturnNotReady;
2354 	}
2355 	unlockForArbitration();
2356 
2357 	return rc;
2358 }
2359 
2360 static void
cleanInterestList(OSObject * head)2361 cleanInterestList( OSObject * head )
2362 {
2363 	IOCommand *notifyHead = OSDynamicCast(IOCommand, head);
2364 	if (!notifyHead) {
2365 		return;
2366 	}
2367 
2368 	LOCKWRITENOTIFY();
2369 	while (queue_entry_t entry = dequeue(&notifyHead->fCommandChain)) {
2370 		queue_next(entry) = queue_prev(entry) = NULL;
2371 
2372 		_IOServiceInterestNotifier * notify;
2373 
2374 		queue_element(entry, notify, _IOServiceInterestNotifier *, chain);
2375 		notify->release();
2376 	}
2377 	UNLOCKNOTIFY();
2378 }
2379 
2380 void
unregisterAllInterest(void)2381 IOService::unregisterAllInterest( void )
2382 {
2383 	OSObject * prop;
2384 
2385 	prop = copyProperty(gIOGeneralInterest);
2386 	cleanInterestList(prop);
2387 	OSSafeReleaseNULL(prop);
2388 
2389 	prop = copyProperty(gIOBusyInterest);
2390 	cleanInterestList(prop);
2391 	OSSafeReleaseNULL(prop);
2392 
2393 	prop = copyProperty(gIOAppPowerStateInterest);
2394 	cleanInterestList(prop);
2395 	OSSafeReleaseNULL(prop);
2396 
2397 	prop = copyProperty(gIOPriorityPowerStateInterest);
2398 	cleanInterestList(prop);
2399 	OSSafeReleaseNULL(prop);
2400 
2401 	prop = copyProperty(gIOConsoleSecurityInterest);
2402 	cleanInterestList(prop);
2403 	OSSafeReleaseNULL(prop);
2404 }
2405 
2406 /*
2407  * _IOServiceInterestNotifier
2408  */
2409 
2410 // wait for all threads, other than the current one,
2411 //  to exit the handler
2412 
2413 void
wait()2414 _IOServiceInterestNotifier::wait()
2415 {
2416 	_IOServiceNotifierInvocation * next;
2417 	bool doWait;
2418 
2419 	do {
2420 		doWait = false;
2421 		queue_iterate( &handlerInvocations, next,
2422 		    _IOServiceNotifierInvocation *, link) {
2423 			if (next->thread != current_thread()) {
2424 				doWait = true;
2425 				break;
2426 			}
2427 		}
2428 		if (doWait) {
2429 			state |= kIOServiceNotifyWaiter;
2430 			SLEEPNOTIFY(this);
2431 		}
2432 	} while (doWait);
2433 }
2434 
2435 void
free()2436 _IOServiceInterestNotifier::free()
2437 {
2438 	assert( queue_empty( &handlerInvocations ));
2439 
2440 	if (handler == &IOServiceInterestHandlerToBlock) {
2441 		Block_release(ref);
2442 	}
2443 
2444 	OSObject::free();
2445 }
2446 
2447 void
remove()2448 _IOServiceInterestNotifier::remove()
2449 {
2450 	LOCKWRITENOTIFY();
2451 
2452 	if (queue_next( &chain )) {
2453 		remqueue(&chain);
2454 		queue_next( &chain) = queue_prev( &chain) = NULL;
2455 		release();
2456 	}
2457 
2458 	state &= ~kIOServiceNotifyEnable;
2459 
2460 	wait();
2461 
2462 	UNLOCKNOTIFY();
2463 
2464 	release();
2465 }
2466 
2467 bool
disable()2468 _IOServiceInterestNotifier::disable()
2469 {
2470 	bool        ret;
2471 
2472 	LOCKWRITENOTIFY();
2473 
2474 	ret = (0 != (kIOServiceNotifyEnable & state));
2475 	state &= ~kIOServiceNotifyEnable;
2476 	if (ret) {
2477 		wait();
2478 	}
2479 
2480 	UNLOCKNOTIFY();
2481 
2482 	return ret;
2483 }
2484 
2485 void
enable(bool was)2486 _IOServiceInterestNotifier::enable( bool was )
2487 {
2488 	LOCKWRITENOTIFY();
2489 	if (was) {
2490 		state |= kIOServiceNotifyEnable;
2491 	} else {
2492 		state &= ~kIOServiceNotifyEnable;
2493 	}
2494 	UNLOCKNOTIFY();
2495 }
2496 
2497 bool
init()2498 _IOServiceInterestNotifier::init()
2499 {
2500 	queue_init( &handlerInvocations );
2501 	return OSObject::init();
2502 }
2503 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2504 
2505 /*
2506  * Termination
2507  */
2508 
2509 #define tailQ(o)                setObject(o)
2510 #define headQ(o)                setObject(0, o)
2511 #define TLOG(fmt, args...)      { if(kIOLogYield & gIOKitDebug) { IOLog("[%llx] ", thread_tid(current_thread())); IOLog(fmt, ## args); }}
2512 
2513 static void
_workLoopAction(IOWorkLoop::Action action,IOService * service,void * p0=NULL,void * p1=NULL,void * p2=NULL,void * p3=NULL)2514 _workLoopAction( IOWorkLoop::Action action,
2515     IOService * service,
2516     void * p0 = NULL, void * p1 = NULL,
2517     void * p2 = NULL, void * p3 = NULL )
2518 {
2519 	IOWorkLoop * wl;
2520 
2521 	if ((wl = service->getWorkLoop())) {
2522 		wl->retain();
2523 		wl->runAction( action, service, p0, p1, p2, p3 );
2524 		wl->release();
2525 	} else {
2526 		(*action)( service, p0, p1, p2, p3 );
2527 	}
2528 }
2529 
2530 bool
requestTerminate(IOService * provider,IOOptionBits options)2531 IOService::requestTerminate( IOService * provider, IOOptionBits options )
2532 {
2533 	bool ok;
2534 
2535 	// if its our only provider
2536 	ok = isParent( provider, gIOServicePlane, true);
2537 
2538 	// -- compat
2539 	if (ok) {
2540 		provider->terminateClient( this, options | kIOServiceRecursing );
2541 		ok = (0 != (kIOServiceInactiveState & __state[0]));
2542 	}
2543 	// --
2544 
2545 	return ok;
2546 }
2547 
2548 bool
terminatePhase1(IOOptionBits options)2549 IOService::terminatePhase1( IOOptionBits options )
2550 {
2551 	IOService *  victim;
2552 	IOService *  client;
2553 	IOService *  rematchProvider;
2554 	OSIterator * iter;
2555 	OSArray *    makeInactive;
2556 	OSArray *    waitingInactive;
2557 	IOOptionBits callerOptions;
2558 	int          waitResult = THREAD_AWAKENED;
2559 	bool         wait;
2560 	bool                 ok;
2561 	bool                 didInactive;
2562 	bool                 startPhase2 = false;
2563 
2564 	TLOG("%s[0x%qx]::terminatePhase1(%08llx)\n", getName(), getRegistryEntryID(), (long long)options);
2565 
2566 	callerOptions = options;
2567 	rematchProvider = NULL;
2568 	uint64_t regID = getRegistryEntryID();
2569 	IOServiceTrace(
2570 		IOSERVICE_TERMINATE_PHASE1,
2571 		(uintptr_t) regID,
2572 		(uintptr_t) (regID >> 32),
2573 		(uintptr_t) this,
2574 		(uintptr_t) options);
2575 
2576 	// -- compat
2577 	if (options & kIOServiceRecursing) {
2578 		lockForArbitration();
2579 		if (0 == (kIOServiceInactiveState & __state[0])) {
2580 			__state[0] |= kIOServiceInactiveState;
2581 			__state[1] |= kIOServiceRecursing | kIOServiceTermPhase1State;
2582 		}
2583 		unlockForArbitration();
2584 
2585 		return true;
2586 	}
2587 	// --
2588 
2589 	makeInactive    = OSArray::withCapacity( 16 );
2590 	waitingInactive = OSArray::withCapacity( 16 );
2591 	if (!makeInactive || !waitingInactive) {
2592 		OSSafeReleaseNULL(makeInactive);
2593 		OSSafeReleaseNULL(waitingInactive);
2594 		return false;
2595 	}
2596 
2597 	victim = this;
2598 	victim->retain();
2599 
2600 	while (victim) {
2601 		didInactive = victim->lockForArbitration( true );
2602 		if (didInactive) {
2603 			uint64_t regID1 = victim->getRegistryEntryID();
2604 			IOServiceTrace(IOSERVICE_TERM_SET_INACTIVE,
2605 			    (uintptr_t) regID1,
2606 			    (uintptr_t) (regID1 >> 32),
2607 			    (uintptr_t) victim->__state[1],
2608 			    (uintptr_t) 0);
2609 
2610 			enum { kRP1 = kIOServiceRecursing | kIOServiceTermPhase1State };
2611 			didInactive = (kRP1 == (victim->__state[1] & kRP1))
2612 			    || (0 == (victim->__state[0] & kIOServiceInactiveState));
2613 
2614 			if (!didInactive) {
2615 				// a multiply attached IOService can be visited twice
2616 				if (-1U == waitingInactive->getNextIndexOfObject(victim, 0)) {
2617 					do{
2618 						IOLockLock(gIOServiceBusyLock);
2619 						wait = (victim->__state[1] & kIOServiceTermPhase1State);
2620 						if (wait) {
2621 							TLOG("%s[0x%qx]::waitPhase1(%s[0x%qx])\n",
2622 							    getName(), getRegistryEntryID(), victim->getName(), victim->getRegistryEntryID());
2623 							victim->__state[1] |= kIOServiceTerm1WaiterState;
2624 							victim->unlockForArbitration();
2625 							assert_wait((event_t)&victim->__state[1], THREAD_UNINT);
2626 						}
2627 						IOLockUnlock(gIOServiceBusyLock);
2628 						if (wait) {
2629 							waitResult = thread_block(THREAD_CONTINUE_NULL);
2630 							TLOG("%s[0x%qx]::did waitPhase1(%s[0x%qx])\n",
2631 							    getName(), getRegistryEntryID(), victim->getName(), victim->getRegistryEntryID());
2632 							victim->lockForArbitration();
2633 						}
2634 					}while (wait && (waitResult != THREAD_TIMED_OUT));
2635 				}
2636 			} else {
2637 				victim->__state[0] |= kIOServiceInactiveState;
2638 				victim->__state[0] &= ~(kIOServiceRegisteredState | kIOServiceMatchedState
2639 				    | kIOServiceFirstPublishState | kIOServiceFirstMatchState);
2640 				victim->__state[1] &= ~kIOServiceRecursing;
2641 				victim->__state[1] |= kIOServiceTermPhase1State;
2642 				waitingInactive->headQ(victim);
2643 				if (victim == this) {
2644 					if (kIOServiceTerminateNeedWillTerminate & options) {
2645 						victim->__state[1] |= kIOServiceNeedWillTerminate;
2646 					}
2647 				}
2648 				victim->_adjustBusy( 1 );
2649 
2650 				if ((options & kIOServiceTerminateWithRematch) && (victim == this)) {
2651 					if ((options & kIOServiceTerminateWithRematchCurrentDext)) {
2652 						OSObject     * obj;
2653 						OSObject     * rematchProps;
2654 						OSNumber     * num;
2655 						uint32_t       count;
2656 
2657 						rematchProvider = getProvider();
2658 						if (rematchProvider) {
2659 							obj = rematchProvider->copyProperty(gIORematchCountKey);
2660 							num = OSDynamicCast(OSNumber, obj);
2661 							count = 0;
2662 							if (num) {
2663 								count = num->unsigned32BitValue();
2664 								count++;
2665 							}
2666 							num = OSNumber::withNumber(count, 32);
2667 							rematchProvider->setProperty(gIORematchCountKey, num);
2668 							rematchProps = copyProperty(gIOMatchedPersonalityKey);
2669 							rematchProvider->setProperty(gIORematchPersonalityKey, rematchProps);
2670 							OSSafeReleaseNULL(num);
2671 							OSSafeReleaseNULL(rematchProps);
2672 							OSSafeReleaseNULL(obj);
2673 						}
2674 					}
2675 					victim->__state[1] |= kIOServiceRematchOnDetach;
2676 				}
2677 			}
2678 			victim->unlockForArbitration();
2679 		}
2680 		if (victim == this) {
2681 			options &= ~(kIOServiceTerminateWithRematch | kIOServiceTerminateWithRematchCurrentDext);
2682 			startPhase2 = didInactive;
2683 		}
2684 		if (didInactive) {
2685 			OSArray * notifiers;
2686 			notifiers = victim->copyNotifiers(gIOTerminatedNotification, 0, 0xffffffff);
2687 			victim->invokeNotifiers(&notifiers);
2688 
2689 			IOUserClient::destroyUserReferences( victim );
2690 
2691 			iter = victim->getClientIterator();
2692 			if (iter) {
2693 				while ((client = (IOService *) iter->getNextObject())) {
2694 					TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], %08llx)\n",
2695 					    client->getName(), client->getRegistryEntryID(),
2696 					    victim->getName(), victim->getRegistryEntryID(), (long long)options);
2697 					ok = client->requestTerminate( victim, options );
2698 					TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], ok = %d)\n",
2699 					    client->getName(), client->getRegistryEntryID(),
2700 					    victim->getName(), victim->getRegistryEntryID(), ok);
2701 
2702 					uint64_t regID1 = client->getRegistryEntryID();
2703 					uint64_t regID2 = victim->getRegistryEntryID();
2704 					IOServiceTrace(
2705 						(ok ? IOSERVICE_TERMINATE_REQUEST_OK
2706 						: IOSERVICE_TERMINATE_REQUEST_FAIL),
2707 						(uintptr_t) regID1,
2708 						(uintptr_t) (regID1 >> 32),
2709 						(uintptr_t) regID2,
2710 						(uintptr_t) (regID2 >> 32));
2711 
2712 					if (ok) {
2713 						makeInactive->setObject( client );
2714 					}
2715 				}
2716 				iter->release();
2717 			}
2718 		}
2719 		victim->release();
2720 		victim = (IOService *) makeInactive->getObject(0);
2721 		if (victim) {
2722 			victim->retain();
2723 			makeInactive->removeObject(0);
2724 		}
2725 	}
2726 
2727 	makeInactive->release();
2728 
2729 	while ((victim = (IOService *) waitingInactive->getObject(0))) {
2730 		victim->retain();
2731 		waitingInactive->removeObject(0);
2732 
2733 		victim->lockForArbitration();
2734 		victim->__state[1] &= ~kIOServiceTermPhase1State;
2735 		if (kIOServiceTerm1WaiterState & victim->__state[1]) {
2736 			victim->__state[1] &= ~kIOServiceTerm1WaiterState;
2737 			TLOG("%s[0x%qx]::wakePhase1\n", victim->getName(), victim->getRegistryEntryID());
2738 			IOLockLock( gIOServiceBusyLock );
2739 			thread_wakeup((event_t) &victim->__state[1]);
2740 			IOLockUnlock( gIOServiceBusyLock );
2741 		}
2742 		victim->unlockForArbitration();
2743 		victim->release();
2744 	}
2745 
2746 	waitingInactive->release();
2747 
2748 	if (startPhase2) {
2749 		retain();
2750 		lockForArbitration();
2751 		__state[1] |= kIOServiceTermPhase2ReadyState;
2752 		scheduleTerminatePhase2(options);
2753 		unlockForArbitration();
2754 		release();
2755 	}
2756 
2757 	if (rematchProvider) {
2758 		DKLOG(DKS " rematching after dext crash\n", DKN(rematchProvider));
2759 	}
2760 
2761 	return true;
2762 }
2763 
2764 void
setTerminateDefer(IOService * provider,bool defer)2765 IOService::setTerminateDefer(IOService * provider, bool defer)
2766 {
2767 	lockForArbitration();
2768 	if (defer) {
2769 		__state[1] |= kIOServiceStartState;
2770 	} else {
2771 		__state[1] &= ~kIOServiceStartState;
2772 	}
2773 	unlockForArbitration();
2774 
2775 	if (provider && !defer) {
2776 		provider->lockForArbitration();
2777 		provider->scheduleTerminatePhase2();
2778 		provider->unlockForArbitration();
2779 	}
2780 }
2781 
2782 // Must call this while holding gJobsLock
2783 void
waitToBecomeTerminateThread(void)2784 IOService::waitToBecomeTerminateThread(void)
2785 {
2786 	IOLockAssert(gJobsLock, kIOLockAssertOwned);
2787 	bool wait;
2788 	do {
2789 		wait = (gIOTerminateThread != THREAD_NULL);
2790 		if (wait) {
2791 			IOLockSleepWithInheritor(
2792 				gJobsLock,
2793 				LCK_SLEEP_DEFAULT,
2794 				&gIOTerminateThread,
2795 				gIOTerminateThread,
2796 				THREAD_UNINT,
2797 				TIMEOUT_WAIT_FOREVER);
2798 		}
2799 	} while (wait);
2800 	gIOTerminateThread = current_thread();
2801 }
2802 
2803 // call with lockForArbitration
2804 void
scheduleTerminatePhase2(IOOptionBits options)2805 IOService::scheduleTerminatePhase2( IOOptionBits options )
2806 {
2807 	AbsoluteTime        deadline;
2808 	uint64_t            regID1;
2809 	int                 waitResult = THREAD_AWAKENED;
2810 	bool                wait = false, haveDeadline = false;
2811 
2812 	if (!(__state[0] & kIOServiceInactiveState)) {
2813 		return;
2814 	}
2815 
2816 	regID1 = getRegistryEntryID();
2817 	IOServiceTrace(
2818 		IOSERVICE_TERM_SCHED_PHASE2,
2819 		(uintptr_t) regID1,
2820 		(uintptr_t) (regID1 >> 32),
2821 		(uintptr_t) __state[1],
2822 		(uintptr_t) options);
2823 
2824 	if (0 == (__state[1] & kIOServiceTermPhase2ReadyState)) {
2825 		return;
2826 	}
2827 
2828 	retain();
2829 	unlockForArbitration();
2830 	options |= kIOServiceRequired;
2831 	IOLockLock( gJobsLock );
2832 
2833 	if ((options & kIOServiceSynchronous)
2834 	    && (current_thread() != gIOTerminateThread)) {
2835 		waitToBecomeTerminateThread();
2836 		gIOTerminatePhase2List->setObject( this );
2837 		gIOTerminateWork++;
2838 
2839 		do {
2840 			while (gIOTerminateWork) {
2841 				terminateWorker( options );
2842 			}
2843 			wait = (0 != (__state[1] & kIOServiceBusyStateMask));
2844 			if (wait) {
2845 				/* wait for the victim to go non-busy */
2846 				if (!haveDeadline) {
2847 					clock_interval_to_deadline( 15, kSecondScale, &deadline );
2848 					haveDeadline = true;
2849 				}
2850 				/* let others do work while we wait */
2851 				gIOTerminateThread = NULL;
2852 				IOLockWakeupAllWithInheritor(gJobsLock, &gIOTerminateThread);
2853 				waitResult = IOLockSleepDeadline( gJobsLock, &gIOTerminateWork,
2854 				    deadline, THREAD_UNINT );
2855 				if (__improbable(waitResult == THREAD_TIMED_OUT)) {
2856 					IOLog("%s[0x%qx]::terminate(kIOServiceSynchronous): THREAD_TIMED_OUT. "
2857 					    "Attempting to auto-resolve your deadlock. PLEASE FIX!\n", getName(), getRegistryEntryID());
2858 				}
2859 				waitToBecomeTerminateThread();
2860 			}
2861 		} while (gIOTerminateWork || (wait && (waitResult != THREAD_TIMED_OUT)));
2862 
2863 		gIOTerminateThread = NULL;
2864 		IOLockWakeupAllWithInheritor(gJobsLock, &gIOTerminateThread);
2865 	} else {
2866 		// ! kIOServiceSynchronous
2867 
2868 		gIOTerminatePhase2List->setObject( this );
2869 		if (0 == gIOTerminateWork++) {
2870 			assert(gIOTerminateWorkerThread);
2871 			IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
2872 		}
2873 	}
2874 
2875 	IOLockUnlock( gJobsLock );
2876 	lockForArbitration();
2877 	release();
2878 }
2879 
2880 __attribute__((__noreturn__))
2881 void
terminateThread(void * arg,wait_result_t waitResult)2882 IOService::terminateThread( void * arg, wait_result_t waitResult )
2883 {
2884 	// IOLockSleep re-acquires the lock on wakeup, so we only need to do this once
2885 	IOLockLock(gJobsLock);
2886 	while (true) {
2887 		if (gIOTerminateThread != gIOTerminateWorkerThread) {
2888 			waitToBecomeTerminateThread();
2889 		}
2890 
2891 		while (gIOTerminateWork) {
2892 			terminateWorker((IOOptionBits)(uintptr_t)arg );
2893 		}
2894 
2895 		gIOTerminateThread = NULL;
2896 		IOLockWakeupAllWithInheritor(gJobsLock, &gIOTerminateThread);
2897 		IOLockSleep(gJobsLock, &gIOTerminateWork, THREAD_UNINT);
2898 	}
2899 }
2900 
2901 void
scheduleStop(IOService * provider)2902 IOService::scheduleStop( IOService * provider )
2903 {
2904 	uint64_t regID1 = getRegistryEntryID();
2905 	uint64_t regID2 = provider->getRegistryEntryID();
2906 
2907 	TLOG("%s[0x%qx]::scheduleStop(%s[0x%qx])\n", getName(), regID1, provider->getName(), regID2);
2908 	IOServiceTrace(
2909 		IOSERVICE_TERMINATE_SCHEDULE_STOP,
2910 		(uintptr_t) regID1,
2911 		(uintptr_t) (regID1 >> 32),
2912 		(uintptr_t) regID2,
2913 		(uintptr_t) (regID2 >> 32));
2914 
2915 	IOLockLock( gJobsLock );
2916 	gIOStopList->tailQ( this );
2917 	gIOStopProviderList->tailQ( provider );
2918 
2919 	if (0 == gIOTerminateWork++) {
2920 		assert(gIOTerminateWorkerThread);
2921 		IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
2922 	}
2923 
2924 	IOLockUnlock( gJobsLock );
2925 }
2926 
2927 void
scheduleFinalize(bool now)2928 IOService::scheduleFinalize(bool now)
2929 {
2930 	uint64_t regID1 = getRegistryEntryID();
2931 
2932 	TLOG("%s[0x%qx]::scheduleFinalize\n", getName(), regID1);
2933 	IOServiceTrace(
2934 		IOSERVICE_TERMINATE_SCHEDULE_FINALIZE,
2935 		(uintptr_t) regID1,
2936 		(uintptr_t) (regID1 >> 32),
2937 		0, 0);
2938 
2939 	if (now || IOUserClient::finalizeUserReferences(this)) {
2940 		IOLockLock( gJobsLock );
2941 		gIOFinalizeList->tailQ(this);
2942 		if (0 == gIOTerminateWork++) {
2943 			assert(gIOTerminateWorkerThread);
2944 			IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
2945 		}
2946 		IOLockUnlock( gJobsLock );
2947 	}
2948 }
2949 
2950 bool
willTerminate(IOService * provider,IOOptionBits options)2951 IOService::willTerminate( IOService * provider, IOOptionBits options )
2952 {
2953 	if (reserved->uvars) {
2954 		IOUserServer::serviceWillTerminate(this, provider, options);
2955 	} else if (kIODKLogSetup & gIODKDebug) {
2956 		DKLOG("%s[0x%qx]::willTerminate serviceWillTerminate not called\n", getName(), getRegistryEntryID());
2957 	}
2958 	return true;
2959 }
2960 
2961 bool
didTerminate(IOService * provider,IOOptionBits options,bool * defer)2962 IOService::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
2963 {
2964 	if (reserved->uvars) {
2965 		IOUserServer::serviceDidTerminate(this, provider, options, defer);
2966 	}
2967 
2968 	if (false == *defer) {
2969 		if (lockForArbitration( true )) {
2970 			if (false == provider->handleIsOpen( this )) {
2971 				scheduleStop( provider );
2972 			}
2973 			// -- compat
2974 			else {
2975 				message( kIOMessageServiceIsRequestingClose, provider, (void *)(uintptr_t) options );
2976 				if (false == provider->handleIsOpen( this )) {
2977 					scheduleStop( provider );
2978 				}
2979 			}
2980 			// --
2981 			unlockForArbitration();
2982 		}
2983 	}
2984 
2985 	return true;
2986 }
2987 
2988 void
actionWillTerminate(IOService * victim,IOOptionBits options,OSArray * doPhase2List,bool user,void * unused3 __unused)2989 IOService::actionWillTerminate( IOService * victim, IOOptionBits options,
2990     OSArray * doPhase2List,
2991     bool user,
2992     void *unused3 __unused)
2993 {
2994 	OSIterator * iter;
2995 	IOService *  client;
2996 	bool         ok;
2997 	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
2998 
2999 	iter = victim->getClientIterator();
3000 	if (iter) {
3001 		while ((client = (IOService *) iter->getNextObject())) {
3002 			if (user != (NULL != client->reserved->uvars)) {
3003 				continue;
3004 			}
3005 			regID1 = client->getRegistryEntryID();
3006 			TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
3007 			    client->getName(), regID1,
3008 			    victim->getName(), regID2, (long long)options);
3009 			IOServiceTrace(
3010 				IOSERVICE_TERMINATE_WILL,
3011 				(uintptr_t) regID1,
3012 				(uintptr_t) (regID1 >> 32),
3013 				(uintptr_t) regID2,
3014 				(uintptr_t) (regID2 >> 32));
3015 
3016 			ok = client->willTerminate( victim, options );
3017 			doPhase2List->tailQ( client );
3018 		}
3019 		iter->release();
3020 	}
3021 }
3022 
3023 void
actionDidTerminate(IOService * victim,IOOptionBits options,void * unused1 __unused,void * unused2 __unused,void * unused3 __unused)3024 IOService::actionDidTerminate( IOService * victim, IOOptionBits options,
3025     void *unused1 __unused, void *unused2 __unused,
3026     void *unused3 __unused )
3027 {
3028 	OSIterator * iter;
3029 	IOService *  client;
3030 	bool         defer;
3031 	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
3032 
3033 	victim->messageClients( kIOMessageServiceIsTerminated, (void *)(uintptr_t) options );
3034 
3035 	iter = victim->getClientIterator();
3036 	if (iter) {
3037 		while ((client = (IOService *) iter->getNextObject())) {
3038 			regID1 = client->getRegistryEntryID();
3039 			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
3040 			    client->getName(), regID1,
3041 			    victim->getName(), regID2, (long long)options);
3042 			defer = false;
3043 			client->didTerminate( victim, options, &defer );
3044 
3045 			IOServiceTrace(
3046 				(defer ? IOSERVICE_TERMINATE_DID_DEFER
3047 				: IOSERVICE_TERMINATE_DID),
3048 				(uintptr_t) regID1,
3049 				(uintptr_t) (regID1 >> 32),
3050 				(uintptr_t) regID2,
3051 				(uintptr_t) (regID2 >> 32));
3052 
3053 			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
3054 			    client->getName(), regID1,
3055 			    victim->getName(), regID2, defer);
3056 		}
3057 		iter->release();
3058 	}
3059 }
3060 
3061 
3062 void
actionWillStop(IOService * victim,IOOptionBits options,void * unused1 __unused,void * unused2 __unused,void * unused3 __unused)3063 IOService::actionWillStop( IOService * victim, IOOptionBits options,
3064     void *unused1 __unused, void *unused2 __unused,
3065     void *unused3 __unused )
3066 {
3067 	OSIterator * iter;
3068 	IOService *  provider;
3069 	bool         ok;
3070 	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
3071 
3072 	iter = victim->getProviderIterator();
3073 	if (iter) {
3074 		while ((provider = (IOService *) iter->getNextObject())) {
3075 			regID1 = provider->getRegistryEntryID();
3076 			TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
3077 			    victim->getName(), regID2,
3078 			    provider->getName(), regID1, (long long)options);
3079 			IOServiceTrace(
3080 				IOSERVICE_TERMINATE_WILL,
3081 				(uintptr_t) regID2,
3082 				(uintptr_t) (regID2 >> 32),
3083 				(uintptr_t) regID1,
3084 				(uintptr_t) (regID1 >> 32));
3085 
3086 			ok = victim->willTerminate( provider, options );
3087 		}
3088 		iter->release();
3089 	}
3090 }
3091 
3092 void
actionDidStop(IOService * victim,IOOptionBits options,void * unused1 __unused,void * unused2 __unused,void * unused3 __unused)3093 IOService::actionDidStop( IOService * victim, IOOptionBits options,
3094     void *unused1 __unused, void *unused2 __unused,
3095     void *unused3 __unused )
3096 {
3097 	OSIterator * iter;
3098 	IOService *  provider;
3099 	bool defer = false;
3100 	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
3101 
3102 	iter = victim->getProviderIterator();
3103 	if (iter) {
3104 		while ((provider = (IOService *) iter->getNextObject())) {
3105 			regID1 = provider->getRegistryEntryID();
3106 			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
3107 			    victim->getName(), regID2,
3108 			    provider->getName(), regID1, (long long)options);
3109 			victim->didTerminate( provider, options, &defer );
3110 
3111 			IOServiceTrace(
3112 				(defer ? IOSERVICE_TERMINATE_DID_DEFER
3113 				: IOSERVICE_TERMINATE_DID),
3114 				(uintptr_t) regID2,
3115 				(uintptr_t) (regID2 >> 32),
3116 				(uintptr_t) regID1,
3117 				(uintptr_t) (regID1 >> 32));
3118 
3119 			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
3120 			    victim->getName(), regID2,
3121 			    provider->getName(), regID1, defer);
3122 		}
3123 		iter->release();
3124 	}
3125 }
3126 
3127 
3128 void
actionFinalize(IOService * victim,IOOptionBits options,void * unused1 __unused,void * unused2 __unused,void * unused3 __unused)3129 IOService::actionFinalize( IOService * victim, IOOptionBits options,
3130     void *unused1 __unused, void *unused2 __unused,
3131     void *unused3 __unused )
3132 {
3133 	uint64_t regID1 = victim->getRegistryEntryID();
3134 	TLOG("%s[0x%qx]::finalize(%08llx)\n", victim->getName(), regID1, (long long)options);
3135 	IOServiceTrace(
3136 		IOSERVICE_TERMINATE_FINALIZE,
3137 		(uintptr_t) regID1,
3138 		(uintptr_t) (regID1 >> 32),
3139 		0, 0);
3140 
3141 	victim->finalize( options );
3142 }
3143 
3144 void
actionStop(IOService * provider,IOService * client,void * unused1 __unused,void * unused2 __unused,void * unused3 __unused)3145 IOService::actionStop( IOService * provider, IOService * client,
3146     void *unused1 __unused, void *unused2 __unused,
3147     void *unused3 __unused )
3148 {
3149 	uint64_t regID1 = provider->getRegistryEntryID();
3150 	uint64_t regID2 = client->getRegistryEntryID();
3151 
3152 	TLOG("%s[0x%qx]::stop(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
3153 	IOServiceTrace(
3154 		IOSERVICE_TERMINATE_STOP,
3155 		(uintptr_t) regID1,
3156 		(uintptr_t) (regID1 >> 32),
3157 		(uintptr_t) regID2,
3158 		(uintptr_t) (regID2 >> 32));
3159 
3160 	client->stop( provider );
3161 	if (provider->isOpen( client )) {
3162 		provider->close( client );
3163 	}
3164 
3165 	TLOG("%s[0x%qx]::detach(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
3166 	client->detach( provider );
3167 }
3168 
3169 #pragma clang diagnostic push
3170 #pragma clang diagnostic ignored "-Wcast-function-type"
3171 
3172 void
terminateWorker(IOOptionBits options)3173 IOService::terminateWorker( IOOptionBits options )
3174 {
3175 	OSArray *           doPhase2List;
3176 	OSArray *           didPhase2List;
3177 	OSSet *             freeList;
3178 	OSIterator *        iter;
3179 	UInt32              workDone;
3180 	IOService *         victim;
3181 	IOService *         client;
3182 	IOService *         provider;
3183 	unsigned int        idx;
3184 	bool                moreToDo;
3185 	bool                doPhase2;
3186 	bool                doPhase3;
3187 
3188 	options |= kIOServiceRequired;
3189 
3190 	doPhase2List  = OSArray::withCapacity( 16 );
3191 	didPhase2List = OSArray::withCapacity( 16 );
3192 	freeList      = OSSet::withCapacity( 16 );
3193 	if ((NULL == doPhase2List) || (NULL == didPhase2List) || (NULL == freeList)) {
3194 		OSSafeReleaseNULL(doPhase2List);
3195 		OSSafeReleaseNULL(didPhase2List);
3196 		OSSafeReleaseNULL(freeList);
3197 		return;
3198 	}
3199 
3200 	do {
3201 		workDone = gIOTerminateWork;
3202 
3203 		while ((victim = (IOService *) gIOTerminatePhase2List->getObject(0))) {
3204 			victim->retain();
3205 			gIOTerminatePhase2List->removeObject(0);
3206 			IOLockUnlock( gJobsLock );
3207 
3208 			uint64_t regID1 = victim->getRegistryEntryID();
3209 			IOServiceTrace(
3210 				IOSERVICE_TERM_START_PHASE2,
3211 				(uintptr_t) regID1,
3212 				(uintptr_t) (regID1 >> 32),
3213 				(uintptr_t) 0,
3214 				(uintptr_t) 0);
3215 
3216 			while (victim) {
3217 				doPhase2 = victim->lockForArbitration( true );
3218 				if (doPhase2) {
3219 					doPhase2 = (0 != (kIOServiceInactiveState & victim->__state[0]));
3220 					if (doPhase2) {
3221 						victim->__state[1] |= kIOServiceTermPhase2ReadyState;
3222 
3223 						uint64_t regID1 = victim->getRegistryEntryID();
3224 						IOServiceTrace(
3225 							IOSERVICE_TERM_TRY_PHASE2,
3226 							(uintptr_t) regID1,
3227 							(uintptr_t) (regID1 >> 32),
3228 							(uintptr_t) victim->__state[1],
3229 							(uintptr_t) 0);
3230 
3231 						doPhase2 = (0 == (victim->__state[1] &
3232 						    (kIOServiceTermPhase1State
3233 						    | kIOServiceTermPhase2State
3234 						    | kIOServiceConfigState)));
3235 
3236 						if (doPhase2 && (iter = victim->getClientIterator())) {
3237 							while (doPhase2 && (client = (IOService *) iter->getNextObject())) {
3238 								doPhase2 = (0 == (client->__state[1] & kIOServiceStartState));
3239 								if (!doPhase2) {
3240 									uint64_t regID1 = client->getRegistryEntryID();
3241 									IOServiceTrace(
3242 										IOSERVICE_TERM_UC_DEFER,
3243 										(uintptr_t) regID1,
3244 										(uintptr_t) (regID1 >> 32),
3245 										(uintptr_t) client->__state[1],
3246 										(uintptr_t) 0);
3247 									TLOG("%s[0x%qx]::defer phase2(%s[0x%qx])\n",
3248 									    victim->getName(), victim->getRegistryEntryID(),
3249 									    client->getName(), client->getRegistryEntryID());
3250 								}
3251 							}
3252 							iter->release();
3253 						}
3254 						if (doPhase2) {
3255 							victim->__state[1] |= kIOServiceTermPhase2State;
3256 						}
3257 					}
3258 					victim->unlockForArbitration();
3259 				}
3260 				if (doPhase2) {
3261 					if (kIOServiceNeedWillTerminate & victim->__state[1]) {
3262 						if (NULL == victim->reserved->uvars) {
3263 							_workLoopAction((IOWorkLoop::Action) &actionWillStop,
3264 							    victim, (void *)(uintptr_t) options);
3265 						} else {
3266 							actionWillStop(victim, options, NULL, NULL, NULL);
3267 						}
3268 					}
3269 
3270 					OSArray * notifiers;
3271 					notifiers = victim->copyNotifiers(gIOWillTerminateNotification, 0, 0xffffffff);
3272 					victim->invokeNotifiers(&notifiers);
3273 
3274 					_workLoopAction((IOWorkLoop::Action) &actionWillTerminate,
3275 					    victim,
3276 					    (void *)(uintptr_t) options,
3277 					    (void *)(uintptr_t) doPhase2List,
3278 					    (void *)(uintptr_t) false);
3279 
3280 					actionWillTerminate(
3281 						victim, options, doPhase2List, true, NULL);
3282 
3283 					didPhase2List->headQ( victim );
3284 				}
3285 				victim->release();
3286 				victim = (IOService *) doPhase2List->getObject(0);
3287 				if (victim) {
3288 					victim->retain();
3289 					doPhase2List->removeObject(0);
3290 				}
3291 			}
3292 
3293 			while ((victim = (IOService *) didPhase2List->getObject(0))) {
3294 				bool scheduleFinalize = false;
3295 				if (victim->lockForArbitration( true )) {
3296 					victim->__state[1] |= kIOServiceTermPhase3State;
3297 					scheduleFinalize = (NULL == victim->getClient());
3298 					victim->unlockForArbitration();
3299 				}
3300 				_workLoopAction((IOWorkLoop::Action) &actionDidTerminate,
3301 				    victim, (void *)(uintptr_t) options );
3302 				if (kIOServiceNeedWillTerminate & victim->__state[1]) {
3303 					_workLoopAction((IOWorkLoop::Action) &actionDidStop,
3304 					    victim, (void *)(uintptr_t) options, NULL );
3305 				}
3306 				// no clients - will go to finalize
3307 				if (scheduleFinalize) {
3308 					victim->scheduleFinalize(false);
3309 				}
3310 				didPhase2List->removeObject(0);
3311 			}
3312 			IOLockLock( gJobsLock );
3313 		}
3314 
3315 		// phase 3
3316 		do {
3317 			doPhase3 = false;
3318 			// finalize leaves
3319 			while ((victim = (IOService *) gIOFinalizeList->getObject(0))) {
3320 				bool sendFinal = false;
3321 				IOLockUnlock( gJobsLock );
3322 				if (victim->lockForArbitration(true)) {
3323 					sendFinal = (0 == (victim->__state[1] & kIOServiceFinalized));
3324 					if (sendFinal) {
3325 						victim->__state[1] |= kIOServiceFinalized;
3326 					}
3327 					victim->unlockForArbitration();
3328 				}
3329 				if (sendFinal) {
3330 					_workLoopAction((IOWorkLoop::Action) &actionFinalize,
3331 					    victim, (void *)(uintptr_t) options );
3332 				}
3333 				IOLockLock( gJobsLock );
3334 				// hold off free
3335 				freeList->setObject( victim );
3336 				// safe if finalize list is append only
3337 				gIOFinalizeList->removeObject(0);
3338 			}
3339 
3340 			for (idx = 0;
3341 			    (!doPhase3) && (client = (IOService *) gIOStopList->getObject(idx));) {
3342 				provider = (IOService *) gIOStopProviderList->getObject(idx);
3343 				assert( provider );
3344 
3345 				uint64_t regID1 = provider->getRegistryEntryID();
3346 				uint64_t regID2 = client->getRegistryEntryID();
3347 
3348 				if (!provider->isChild( client, gIOServicePlane )) {
3349 					// may be multiply queued - nop it
3350 					TLOG("%s[0x%qx]::nop stop(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
3351 					IOServiceTrace(
3352 						IOSERVICE_TERMINATE_STOP_NOP,
3353 						(uintptr_t) regID1,
3354 						(uintptr_t) (regID1 >> 32),
3355 						(uintptr_t) regID2,
3356 						(uintptr_t) (regID2 >> 32));
3357 				} else {
3358 					// a terminated client is not ready for stop if it has clients, skip it
3359 					bool deferStop = (0 != (kIOServiceInactiveState & client->__state[0]));
3360 					IOLockUnlock( gJobsLock );
3361 					if (deferStop && client->lockForArbitration(true)) {
3362 						deferStop = (0 == (client->__state[1] & kIOServiceFinalized));
3363 						//deferStop = (!deferStop && (0 != client->getClient()));
3364 						//deferStop = (0 != client->getClient());
3365 						client->unlockForArbitration();
3366 						if (deferStop) {
3367 							TLOG("%s[0x%qx]::defer stop()\n", client->getName(), regID2);
3368 							IOServiceTrace(IOSERVICE_TERMINATE_STOP_DEFER,
3369 							    (uintptr_t) regID1,
3370 							    (uintptr_t) (regID1 >> 32),
3371 							    (uintptr_t) regID2,
3372 							    (uintptr_t) (regID2 >> 32));
3373 
3374 							idx++;
3375 							IOLockLock( gJobsLock );
3376 							continue;
3377 						}
3378 					}
3379 					_workLoopAction((IOWorkLoop::Action) &actionStop,
3380 					    provider, (void *) client );
3381 					IOLockLock( gJobsLock );
3382 					// check the finalize list now
3383 					doPhase3 = true;
3384 				}
3385 				// hold off free
3386 				freeList->setObject( client );
3387 				freeList->setObject( provider );
3388 
3389 				// safe if stop list is append only
3390 				gIOStopList->removeObject( idx );
3391 				gIOStopProviderList->removeObject( idx );
3392 				idx = 0;
3393 			}
3394 		} while (doPhase3);
3395 
3396 		gIOTerminateWork -= workDone;
3397 		moreToDo = (gIOTerminateWork != 0);
3398 
3399 		if (!moreToDo) {
3400 			TLOG("iokit terminate done, %d stops remain\n", gIOStopList->getCount());
3401 			IOServiceTrace(
3402 				IOSERVICE_TERMINATE_DONE,
3403 				(uintptr_t) gIOStopList->getCount(), 0, 0, 0);
3404 		}
3405 	} while (moreToDo);
3406 
3407 	IOLockUnlock( gJobsLock );
3408 
3409 	freeList->release();
3410 	doPhase2List->release();
3411 	didPhase2List->release();
3412 
3413 	IOLockLock( gJobsLock );
3414 }
3415 
3416 #pragma clang diagnostic pop
3417 
3418 bool
finalize(IOOptionBits options)3419 IOService::finalize( IOOptionBits options )
3420 {
3421 	OSIterator *  iter;
3422 	IOService *   provider;
3423 	uint64_t      regID1, regID2 = getRegistryEntryID();
3424 
3425 	iter = getProviderIterator();
3426 	assert( iter );
3427 
3428 	if (iter) {
3429 		while ((provider = (IOService *) iter->getNextObject())) {
3430 			// -- compat
3431 			if (0 == (__state[1] & kIOServiceTermPhase3State)) {
3432 				/* we come down here on programmatic terminate */
3433 
3434 				regID1 = provider->getRegistryEntryID();
3435 				TLOG("%s[0x%qx]::stop1(%s[0x%qx])\n", getName(), regID2, provider->getName(), regID1);
3436 				IOServiceTrace(
3437 					IOSERVICE_TERMINATE_STOP,
3438 					(uintptr_t) regID1,
3439 					(uintptr_t) (regID1 >> 32),
3440 					(uintptr_t) regID2,
3441 					(uintptr_t) (regID2 >> 32));
3442 
3443 				stop( provider );
3444 				if (provider->isOpen( this )) {
3445 					provider->close( this );
3446 				}
3447 				detach( provider );
3448 			} else {
3449 				//--
3450 				if (provider->lockForArbitration( true )) {
3451 					if (0 == (provider->__state[1] & kIOServiceTermPhase3State)) {
3452 						scheduleStop( provider );
3453 					}
3454 					provider->unlockForArbitration();
3455 				}
3456 			}
3457 		}
3458 		iter->release();
3459 	}
3460 
3461 	return true;
3462 }
3463 
3464 #undef tailQ
3465 #undef headQ
3466 
3467 /*
3468  * Terminate
3469  */
3470 
3471 void
doServiceTerminate(IOOptionBits options)3472 IOService::doServiceTerminate( IOOptionBits options )
3473 {
3474 }
3475 
3476 // a method in case someone needs to override it
3477 bool
terminateClient(IOService * client,IOOptionBits options)3478 IOService::terminateClient( IOService * client, IOOptionBits options )
3479 {
3480 	bool ok;
3481 
3482 	if (client->isParent( this, gIOServicePlane, true)) {
3483 		// we are the clients only provider
3484 		ok = client->terminate( options );
3485 	} else {
3486 		ok = true;
3487 	}
3488 
3489 	return ok;
3490 }
3491 
3492 bool
terminate(IOOptionBits options)3493 IOService::terminate( IOOptionBits options )
3494 {
3495 	options |= kIOServiceTerminate;
3496 
3497 	return terminatePhase1( options );
3498 }
3499 
3500 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3501 
3502 /*
3503  * Open & close
3504  */
3505 
3506 struct ServiceOpenMessageContext {
3507 	IOService *  service;
3508 	UInt32       type;
3509 	IOService *  excludeClient;
3510 	IOOptionBits options;
3511 };
3512 
3513 static void
serviceOpenMessageApplier(OSObject * object,void * ctx)3514 serviceOpenMessageApplier( OSObject * object, void * ctx )
3515 {
3516 	ServiceOpenMessageContext * context = (ServiceOpenMessageContext *) ctx;
3517 
3518 	if (object != context->excludeClient) {
3519 		context->service->messageClient( context->type, object, (void *)(uintptr_t) context->options );
3520 	}
3521 }
3522 
3523 bool
open(IOService * forClient,IOOptionBits options,void * arg)3524 IOService::open(   IOService *     forClient,
3525     IOOptionBits    options,
3526     void *          arg )
3527 {
3528 	bool                        ok;
3529 	kern_return_t               ret = kIOReturnSuccess;
3530 	ServiceOpenMessageContext   context;
3531 
3532 	context.service             = this;
3533 	context.type                = kIOMessageServiceIsAttemptingOpen;
3534 	context.excludeClient       = forClient;
3535 	context.options             = options;
3536 
3537 	applyToInterested( gIOGeneralInterest,
3538 	    &serviceOpenMessageApplier, &context );
3539 
3540 	if (false == lockForArbitration(false)) {
3541 		return false;
3542 	}
3543 
3544 	ok = (0 == (__state[0] & kIOServiceInactiveState));
3545 
3546 	if (ok && forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
3547 		ret = forClient->reserved->uvars->userServer->serviceOpen(this, forClient);
3548 		if (ret != kIOReturnSuccess) {
3549 			ok = false;
3550 		}
3551 	}
3552 
3553 	if (ok) {
3554 		ok = handleOpen( forClient, options, arg );
3555 
3556 		if (!ok && forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
3557 			forClient->reserved->uvars->userServer->serviceClose(this, forClient);
3558 		}
3559 	}
3560 
3561 	unlockForArbitration();
3562 
3563 	return ok;
3564 }
3565 
3566 void
close(IOService * forClient,IOOptionBits options)3567 IOService::close(  IOService *     forClient,
3568     IOOptionBits    options )
3569 {
3570 	bool                wasClosed;
3571 	bool                last = false;
3572 
3573 	lockForArbitration();
3574 
3575 	wasClosed = handleIsOpen( forClient );
3576 	if (wasClosed) {
3577 		handleClose( forClient, options );
3578 		last = (__state[1] & kIOServiceTermPhase3State);
3579 
3580 		if (forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
3581 			forClient->reserved->uvars->userServer->serviceClose(this, forClient);
3582 		}
3583 	}
3584 
3585 	unlockForArbitration();
3586 
3587 	if (last) {
3588 		forClient->scheduleStop( this );
3589 	} else if (wasClosed) {
3590 		ServiceOpenMessageContext context;
3591 
3592 		context.service         = this;
3593 		context.type            = kIOMessageServiceWasClosed;
3594 		context.excludeClient   = forClient;
3595 		context.options         = options;
3596 
3597 		applyToInterested( gIOGeneralInterest,
3598 		    &serviceOpenMessageApplier, &context );
3599 	}
3600 }
3601 
3602 bool
isOpen(const IOService * forClient) const3603 IOService::isOpen( const IOService * forClient ) const
3604 {
3605 	IOService * self = (IOService *) this;
3606 	bool ok;
3607 
3608 	self->lockForArbitration();
3609 
3610 	ok = handleIsOpen( forClient );
3611 
3612 	self->unlockForArbitration();
3613 
3614 	return ok;
3615 }
3616 
3617 bool
handleOpen(IOService * forClient,IOOptionBits options,void * arg)3618 IOService::handleOpen(     IOService *     forClient,
3619     IOOptionBits    options,
3620     void *          arg )
3621 {
3622 	bool        ok;
3623 
3624 	ok = (NULL == __owner);
3625 	if (ok) {
3626 		__owner = forClient;
3627 	} else if (options & kIOServiceSeize) {
3628 		ok = (kIOReturnSuccess == messageClient( kIOMessageServiceIsRequestingClose,
3629 		    __owner, (void *)(uintptr_t) options ));
3630 		if (ok && (NULL == __owner)) {
3631 			__owner = forClient;
3632 		} else {
3633 			ok = false;
3634 		}
3635 	}
3636 	return ok;
3637 }
3638 
3639 void
handleClose(IOService * forClient,IOOptionBits options)3640 IOService::handleClose(    IOService *     forClient,
3641     IOOptionBits    options )
3642 {
3643 	if (__owner == forClient) {
3644 		__owner = NULL;
3645 	}
3646 }
3647 
3648 bool
handleIsOpen(const IOService * forClient) const3649 IOService::handleIsOpen(   const IOService * forClient ) const
3650 {
3651 	if (forClient) {
3652 		return __owner == forClient;
3653 	} else {
3654 		return __owner != forClient;
3655 	}
3656 }
3657 
3658 /*
3659  * Probing & starting
3660  */
3661 static SInt32
IONotifyOrdering(const OSMetaClassBase * inObj1,const OSMetaClassBase * inObj2,void * ref)3662 IONotifyOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
3663 {
3664 	const _IOServiceNotifier * obj1 = (const _IOServiceNotifier *) inObj1;
3665 	const _IOServiceNotifier * obj2 = (const _IOServiceNotifier *) inObj2;
3666 	SInt32             val1;
3667 	SInt32             val2;
3668 
3669 	val1 = 0;
3670 	val2 = 0;
3671 	if (obj1) {
3672 		val1 = obj1->priority;
3673 	}
3674 	if (obj2) {
3675 		val2 = obj2->priority;
3676 	}
3677 	if (val1 > val2) {
3678 		return 1;
3679 	}
3680 	if (val1 < val2) {
3681 		return -1;
3682 	}
3683 	return 0;
3684 }
3685 
3686 static SInt32
IOServiceObjectOrder(const OSObject * entry,void * ref)3687 IOServiceObjectOrder( const OSObject * entry, void * ref)
3688 {
3689 	OSDictionary *      dict;
3690 	IOService *         service;
3691 	_IOServiceNotifier * notify;
3692 	OSSymbol *          key = (OSSymbol *) ref;
3693 	OSNumber *          offset;
3694 	OSObject *          prop;
3695 	SInt32              result;
3696 
3697 	prop = NULL;
3698 	result = kIODefaultProbeScore;
3699 	if ((dict = OSDynamicCast( OSDictionary, entry))) {
3700 		offset = OSDynamicCast(OSNumber, dict->getObject( key ));
3701 	} else if ((notify = OSDynamicCast( _IOServiceNotifier, entry))) {
3702 		return notify->priority;
3703 	} else if ((service = OSDynamicCast( IOService, entry))) {
3704 		prop = service->copyProperty(key);
3705 		offset = OSDynamicCast(OSNumber, prop);
3706 	} else {
3707 		assert( false );
3708 		offset = NULL;
3709 	}
3710 
3711 	if (offset) {
3712 		result = offset->unsigned32BitValue();
3713 	}
3714 
3715 	OSSafeReleaseNULL(prop);
3716 
3717 	return result;
3718 }
3719 
3720 __attribute__((no_sanitize("signed-integer-overflow"))) SInt32
IOServiceOrdering(const OSMetaClassBase * inObj1,const OSMetaClassBase * inObj2,void * ref)3721 IOServiceOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
3722 {
3723 	const OSObject *    obj1 = (const OSObject *) inObj1;
3724 	const OSObject *    obj2 = (const OSObject *) inObj2;
3725 	SInt32               val1;
3726 	SInt32               val2;
3727 
3728 	val1 = 0;
3729 	val2 = 0;
3730 
3731 	if (obj1) {
3732 		val1 = IOServiceObjectOrder( obj1, ref );
3733 	}
3734 
3735 	if (obj2) {
3736 		val2 = IOServiceObjectOrder( obj2, ref );
3737 	}
3738 
3739 	return val1 - val2;
3740 }
3741 
3742 IOService *
copyClientWithCategory(const OSSymbol * category)3743 IOService::copyClientWithCategory( const OSSymbol * category )
3744 {
3745 	IOService *         service = NULL;
3746 	OSIterator *        iter;
3747 	const OSSymbol *    nextCat;
3748 
3749 	iter = getClientIterator();
3750 	if (iter) {
3751 		while ((service = (IOService *) iter->getNextObject())) {
3752 			if (kIOServiceInactiveState & service->__state[0]) {
3753 				if (!(kIOServiceRematchOnDetach & service->__state[1])) {
3754 					continue;
3755 				}
3756 			}
3757 			nextCat = (const OSSymbol *) OSDynamicCast( OSSymbol,
3758 			    service->getProperty( gIOMatchCategoryKey ));
3759 			if (category == nextCat) {
3760 				service->retain();
3761 				break;
3762 			}
3763 		}
3764 		iter->release();
3765 	}
3766 	return service;
3767 }
3768 
3769 IOService *
getClientWithCategory(const OSSymbol * category)3770 IOService::getClientWithCategory( const OSSymbol * category )
3771 {
3772 	IOService *
3773 	    service = copyClientWithCategory(category);
3774 	if (service) {
3775 		service->release();
3776 	}
3777 	return service;
3778 }
3779 
3780 bool
invokeNotifier(_IOServiceNotifier * notify)3781 IOService::invokeNotifier( _IOServiceNotifier * notify )
3782 {
3783 	_IOServiceNotifierInvocation invocation;
3784 	bool                         willNotify;
3785 	bool                         ret = true;
3786 	invocation.thread = current_thread();
3787 
3788 #if DEBUG_NOTIFIER_LOCKED
3789 	uint32_t count;
3790 	if ((count = isLockedForArbitration(0))) {
3791 		IOLog("[%s, 0x%x]\n", notify->type->getCStringNoCopy(), count);
3792 		panic("[%s, 0x%x]", notify->type->getCStringNoCopy(), count);
3793 	}
3794 #endif /* DEBUG_NOTIFIER_LOCKED */
3795 
3796 	LOCKWRITENOTIFY();
3797 	willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
3798 
3799 	if (willNotify) {
3800 		queue_enter( &notify->handlerInvocations, &invocation,
3801 		    _IOServiceNotifierInvocation *, link );
3802 	}
3803 	UNLOCKNOTIFY();
3804 
3805 	if (willNotify) {
3806 		ret = (*notify->handler)(notify->target, notify->ref, this, notify);
3807 
3808 		LOCKWRITENOTIFY();
3809 		queue_remove( &notify->handlerInvocations, &invocation,
3810 		    _IOServiceNotifierInvocation *, link );
3811 		if (kIOServiceNotifyWaiter & notify->state) {
3812 			notify->state &= ~kIOServiceNotifyWaiter;
3813 			WAKEUPNOTIFY( notify );
3814 		}
3815 		UNLOCKNOTIFY();
3816 	}
3817 
3818 	return ret;
3819 }
3820 
3821 bool
invokeNotifiers(OSArray * willSend[])3822 IOService::invokeNotifiers(OSArray * willSend[])
3823 {
3824 	OSArray *            array;
3825 	_IOServiceNotifier * notify;
3826 	bool                 ret = true;
3827 
3828 	array = *willSend;
3829 	if (!array) {
3830 		return true;
3831 	}
3832 	*willSend = NULL;
3833 
3834 	for (unsigned int idx = 0;
3835 	    (notify = (_IOServiceNotifier *) array->getObject(idx));
3836 	    idx++) {
3837 		ret &= invokeNotifier(notify);
3838 	}
3839 	array->release();
3840 
3841 	return ret;
3842 }
3843 
3844 
3845 TUNABLE(bool, iokit_print_verbose_match_logs, "iokit_print_verbose_match_logs", false);
3846 
3847 /*
3848  * Alloc and probe matching classes,
3849  * called on the provider instance
3850  */
3851 
3852 void
probeCandidates(OSOrderedSet * matches)3853 IOService::probeCandidates( OSOrderedSet * matches )
3854 {
3855 	OSDictionary        *       match = NULL;
3856 	OSSymbol            *       symbol;
3857 	IOService           *       inst;
3858 	IOService           *       newInst;
3859 	OSDictionary        *       props;
3860 	SInt32                      score;
3861 	OSNumber            *       newPri;
3862 	OSOrderedSet        *       familyMatches = NULL;
3863 	OSOrderedSet        *       startList;
3864 	OSSet               *       kexts = NULL;
3865 	OSObject            *       kextRef;
3866 
3867 	OSDictionary        *       startDict = NULL;
3868 	const OSSymbol      *       category;
3869 	OSIterator          *       iter;
3870 	_IOServiceNotifier  *       notify;
3871 	OSObject            *       nextMatch = NULL;
3872 	bool                        started;
3873 	bool                        needReloc = false;
3874 	bool                        matchDeferred = false;
3875 #if IOMATCHDEBUG
3876 	SInt64                      debugFlags;
3877 #endif
3878 	IOService           *       client = NULL;
3879 	OSObject            *       prop1;
3880 	OSObject            *       rematchCountProp;
3881 	OSDictionary        *       rematchPersonality;
3882 	OSNumber            *       num;
3883 	uint32_t                    count;
3884 	uint32_t                    dextCount;
3885 	bool                        isDext;
3886 	bool                        categoryConsumed;
3887 
3888 	rematchCountProp = NULL;
3889 	count = 0;
3890 	prop1 = copyProperty(gIORematchPersonalityKey);
3891 	rematchPersonality = OSDynamicCast(OSDictionary, prop1);
3892 	if (rematchPersonality) {
3893 		rematchCountProp = copyProperty(gIORematchCountKey);
3894 		num = OSDynamicCast(OSNumber, rematchCountProp);
3895 		if (num) {
3896 			count = num->unsigned32BitValue();
3897 		}
3898 		removeProperty(gIORematchPersonalityKey);
3899 	}
3900 	dextCount = 0;
3901 
3902 	assert( matches );
3903 	while (!needReloc
3904 	    && (nextMatch = matches->getFirstObject())) {
3905 		nextMatch->retain();
3906 		matches->removeObject(nextMatch);
3907 
3908 		if ((notify = OSDynamicCast( _IOServiceNotifier, nextMatch ))) {
3909 			if (0 == (__state[0] & kIOServiceInactiveState)) {
3910 				invokeNotifier( notify );
3911 			}
3912 			nextMatch->release();
3913 			nextMatch = NULL;
3914 			continue;
3915 		} else if (!(match = OSDynamicCast( OSDictionary, nextMatch ))) {
3916 			nextMatch->release();
3917 			nextMatch = NULL;
3918 			continue;
3919 		}
3920 
3921 		props = NULL;
3922 #if IOMATCHDEBUG
3923 		debugFlags = getDebugFlags( match );
3924 #endif
3925 
3926 		bool newIsBoot = false;
3927 		bool existingIsBoot = false;
3928 		bool isReplacementCandidate = false;
3929 
3930 		do {
3931 			client = NULL;
3932 			isDext = (NULL != match->getObject(gIOUserServerNameKey));
3933 			if (isDext && !(kIODKEnable & gIODKDebug)) {
3934 				continue;
3935 			}
3936 			if (isDext && !OSKext::iokitDaemonAvailable()) {
3937 				continue;
3938 			}
3939 			if (isDext && !gIODextRelaunchMax && rematchCountProp) {
3940 				continue;
3941 			}
3942 			if (isDext && isInactive()) {
3943 				continue;
3944 			}
3945 			newIsBoot = gIOCatalogue->personalityIsBoot(match);
3946 
3947 			category = OSDynamicCast( OSSymbol,
3948 			    match->getObject( gIOMatchCategoryKey ));
3949 			if (NULL == category) {
3950 				category = gIODefaultMatchCategoryKey;
3951 			}
3952 			client = copyClientWithCategory(category);
3953 
3954 			categoryConsumed = (client != NULL);
3955 			if (categoryConsumed) {
3956 #if IOMATCHDEBUG
3957 				if ((debugFlags & kIOLogMatch) && (this != gIOResources)) {
3958 					LOG("%s: match category %s exists\n", getName(),
3959 					    category->getCStringNoCopy());
3960 				}
3961 #endif
3962 				existingIsBoot = client->propertyExists(gIOMatchedAtBootKey);
3963 				isReplacementCandidate = existingIsBoot && !newIsBoot;
3964 				if (!isDext && !isReplacementCandidate) {
3965 					break;
3966 				}
3967 			}
3968 
3969 			// create a copy now in case its modified during matching
3970 			props = OSDictionary::withDictionary(match, match->getCount());
3971 			if (NULL == props) {
3972 				break;
3973 			}
3974 			props->setCapacityIncrement(1);
3975 
3976 			// check the nub matches
3977 			if (false == matchPassive(props, kIOServiceChangesOK | kIOServiceClassDone)) {
3978 				break;
3979 			}
3980 			if (isReplacementCandidate) {
3981 				if (canTerminateForReplacement(client)) {
3982 					client->terminate(kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch);
3983 					break;
3984 				}
3985 			}
3986 
3987 			if (isDext || isReplacementCandidate) {
3988 				if (isDext) {
3989 					dextCount++;
3990 				}
3991 				if (categoryConsumed) {
3992 					break;
3993 				}
3994 			}
3995 			if (rematchPersonality) {
3996 				bool personalityMatch = match->isEqualTo(rematchPersonality);
3997 				if (count > gIODextRelaunchMax) {
3998 					personalityMatch = !personalityMatch;
3999 				}
4000 				if (!personalityMatch) {
4001 					break;
4002 				}
4003 			}
4004 
4005 			// Check to see if driver reloc has been loaded.
4006 			needReloc = (false == gIOCatalogue->isModuleLoaded( match, &kextRef ));
4007 			if (needReloc) {
4008 #if IOMATCHDEBUG
4009 				if (debugFlags & kIOLogCatalogue) {
4010 					LOG("%s: stalling for module\n", getName());
4011 				}
4012 #endif
4013 				// If reloc hasn't been loaded, exit;
4014 				// reprobing will occur after reloc has been loaded.
4015 				break;
4016 			}
4017 			if (kextRef) {
4018 				if (NULL == kexts) {
4019 					kexts = OSSet::withCapacity(1);
4020 				}
4021 				if (kexts) {
4022 					kexts->setObject(kextRef);
4023 					kextRef->release();
4024 				}
4025 			}
4026 			if (newIsBoot) {
4027 				props->setObject(gIOMatchedAtBootKey, kOSBooleanTrue);
4028 			}
4029 			if (isDext) {
4030 				// copy saved for rematchng
4031 				props->setObject(gIOMatchedPersonalityKey, match);
4032 			}
4033 			// reorder on family matchPropertyTable score.
4034 			if (NULL == familyMatches) {
4035 				familyMatches = OSOrderedSet::withCapacity( 1,
4036 				    IOServiceOrdering, (void *) gIOProbeScoreKey );
4037 			}
4038 			if (familyMatches) {
4039 				familyMatches->setObject( props );
4040 			}
4041 		} while (false);
4042 
4043 		OSSafeReleaseNULL(client);
4044 		OSSafeReleaseNULL(nextMatch);
4045 		OSSafeReleaseNULL(props);
4046 	}
4047 	OSSafeReleaseNULL(matches);
4048 	OSSafeReleaseNULL(rematchCountProp);
4049 
4050 	if (familyMatches) {
4051 		while (!needReloc
4052 		    && (props = (OSDictionary *) familyMatches->getFirstObject())) {
4053 			props->retain();
4054 			familyMatches->removeObject( props );
4055 
4056 			inst = NULL;
4057 			newInst = NULL;
4058 #if IOMATCHDEBUG
4059 			debugFlags = getDebugFlags( props );
4060 #endif
4061 			do {
4062 				symbol = OSDynamicCast( OSSymbol,
4063 				    props->getObject( gIOClassKey));
4064 				if (!symbol) {
4065 					continue;
4066 				}
4067 
4068 				//IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), IOSERVICE_OBFUSCATE(symbol), IOSERVICE_OBFUSCATE(props));
4069 
4070 				// alloc the driver instance
4071 				inst = (IOService *) OSMetaClass::allocClassWithName( symbol);
4072 
4073 				if (!inst || !OSDynamicCast(IOService, inst)) {
4074 					IOLog("Couldn't alloc class \"%s\"\n",
4075 					    symbol->getCStringNoCopy());
4076 					continue;
4077 				}
4078 
4079 				// init driver instance
4080 				if (!(inst->init( props ))) {
4081 #if IOMATCHDEBUG
4082 					if (debugFlags & kIOLogStart) {
4083 						IOLog("%s::init in provider %s[0x%qx] fails\n", symbol->getCStringNoCopy(), getName(), getRegistryEntryID());
4084 					}
4085 #endif
4086 					continue;
4087 				}
4088 				if (__state[1] & kIOServiceSynchronousState) {
4089 					inst->__state[1] |= kIOServiceSynchronousState;
4090 				}
4091 
4092 				// give the driver the default match category if not specified
4093 				category = OSDynamicCast( OSSymbol,
4094 				    props->getObject( gIOMatchCategoryKey ));
4095 				if (NULL == category) {
4096 					category = gIODefaultMatchCategoryKey;
4097 				}
4098 				inst->setProperty( gIOMatchCategoryKey, (OSObject *) category );
4099 				// attach driver instance
4100 				if (!(inst->attach( this ))) {
4101 					continue;
4102 				}
4103 
4104 				// pass in score from property table
4105 				score = familyMatches->orderObject( props );
4106 
4107 				// & probe the new driver instance
4108 #if IOMATCHDEBUG
4109 				if (debugFlags & kIOLogProbe) {
4110 					LOG("%s[0x%qx]::probe(%s)\n",
4111 					    inst->getMetaClass()->getClassName(), inst->getRegistryEntryID(), getName());
4112 				}
4113 #endif
4114 				newInst = inst->probe( this, &score );
4115 				inst->detach( this );
4116 				if (NULL == newInst) {
4117 #if IOMATCHDEBUG
4118 					if (debugFlags & kIOLogProbe) {
4119 						IOLog("%s[0x%qx]::probe fails\n", symbol->getCStringNoCopy(), inst->getRegistryEntryID());
4120 					}
4121 #endif
4122 					continue;
4123 				}
4124 
4125 				// save the score
4126 				newPri = OSNumber::withNumber( score, 32 );
4127 				if (newPri) {
4128 					newInst->setProperty( gIOProbeScoreKey, newPri );
4129 					newPri->release();
4130 				}
4131 
4132 				// add to start list for the match category
4133 				if (NULL == startDict) {
4134 					startDict = OSDictionary::withCapacity( 1 );
4135 				}
4136 				assert( startDict );
4137 				startList = (OSOrderedSet *)
4138 				    startDict->getObject( category );
4139 				if (NULL == startList) {
4140 					startList = OSOrderedSet::withCapacity( 1,
4141 					    IOServiceOrdering, (void *) gIOProbeScoreKey );
4142 					if (startDict && startList) {
4143 						startDict->setObject( category, startList );
4144 						startList->release();
4145 					}
4146 				}
4147 				assert( startList );
4148 				if (startList) {
4149 					startList->setObject( newInst );
4150 				}
4151 			} while (false);
4152 
4153 			props->release();
4154 			if (inst) {
4155 				inst->release();
4156 			}
4157 		}
4158 		familyMatches->release();
4159 		familyMatches = NULL;
4160 	}
4161 
4162 	if ((debugFlags & kIOLogMatch) && iokit_print_verbose_match_logs && startDict != NULL) {
4163 		IOLog("%s(0x%qx): %u categories\n", getName(), getRegistryEntryID(), startList->getCount());
4164 		startDict->iterateObjects(^(const OSSymbol *key, OSObject *value) {
4165 			OSOrderedSet *startList = OSDynamicCast(OSOrderedSet, value);
4166 			if (startList) {
4167 			        IOLog("%s(0x%qx): category %s, %u matches\n", getName(), getRegistryEntryID(), key->getCStringNoCopy(), startList->getCount());
4168 			        startList->iterateObjects(^(OSObject *obj) {
4169 					IOService *match = OSDynamicCast(IOService, obj);
4170 					OSNumber *probeScore = OSDynamicCast(OSNumber, match->getProperty(gIOProbeScoreKey));
4171 
4172 					if (match && probeScore) {
4173 					        IOLog("%s(0x%qx): category %s: matched %s, probe score %qd\n", getName(), getRegistryEntryID(), key->getCStringNoCopy(), match->getName(), probeScore->unsigned64BitValue());
4174 					}
4175 					return false;
4176 				});
4177 			}
4178 			return false;
4179 		});
4180 	}
4181 
4182 	// start the best (until success) of each category
4183 
4184 	iter = OSCollectionIterator::withCollection( startDict );
4185 	assert(startDict || !iter);
4186 	if (iter) {
4187 		while ((category = (const OSSymbol *) iter->getNextObject())) {
4188 			startList = (OSOrderedSet *) startDict->getObject( category );
4189 			assert( startList );
4190 			if (!startList) {
4191 				continue;
4192 			}
4193 			started = false;
4194 			while (true // (!started)
4195 			    && !matchDeferred
4196 			    && (inst = (IOService *)startList->getFirstObject())) {
4197 				inst->retain();
4198 				startList->removeObject(inst);
4199 #if IOMATCHDEBUG
4200 				debugFlags = getDebugFlags( inst );
4201 
4202 				if (debugFlags & kIOLogStart) {
4203 					if (started) {
4204 						LOG( "match category exists, skipping " );
4205 					}
4206 					LOG( "%s[0x%qx]::start(%s) <%d>\n", inst->getName(), inst->getRegistryEntryID(),
4207 					    getName(), inst->getRetainCount());
4208 				}
4209 #endif
4210 				if (false == started) {
4211 #if !NO_KEXTD
4212 					IOLockLock(gJobsLock);
4213 					matchDeferred = (gIOMatchDeferList
4214 					    && kOSBooleanTrue == inst->getProperty(gIOMatchDeferKey));
4215 					if (matchDeferred && (-1U == gIOMatchDeferList->getNextIndexOfObject(this, 0))) {
4216 						gIOMatchDeferList->setObject(this);
4217 					}
4218 					if (matchDeferred) {
4219 						symbol = OSDynamicCast(OSSymbol, inst->getProperty(gIOClassKey));
4220 						IOLog("%s(0x%qx): matching deferred by %s%s\n",
4221 						    getName(), getRegistryEntryID(),
4222 						    symbol ? symbol->getCStringNoCopy() : "",
4223 						    IOService::getWillUserspaceReboot() ? " in userspace reboot" : "");
4224 						// rematching will occur after the IOKit daemon loads all plists
4225 					}
4226 					IOLockUnlock(gJobsLock);
4227 #endif
4228 					if (!matchDeferred) {
4229 						/* TODO
4230 						 * If a dext fails to start because an upgrade happened
4231 						 * concurrently, then the matching process has to restart
4232 						 */
4233 						started = startCandidate( inst );
4234 #if IOMATCHDEBUG
4235 						if ((debugFlags & kIOLogStart) && (false == started)) {
4236 							LOG( "%s[0x%qx]::start(%s[0x%qx]) <%d> failed\n", inst->getName(), inst->getRegistryEntryID(), getName(), getRegistryEntryID(),
4237 							    inst->getRetainCount());
4238 						}
4239 #endif
4240 						if (!started) {
4241 							if (inst->propertyExists(gIOServiceMatchDeferredKey)) {
4242 								matchDeferred = true;
4243 							} else if (inst->reserved->uvars && inst->reserved->uvars->userServer && !inst->reserved->uvars->instantiated &&
4244 							    (0 != (__state[1] & kIOServiceNeedConfigState))) {
4245 								// Start failed with no object instantiation
4246 								// Dext will be rematched as this nub got re-registered
4247 								// Do not start the next candidate, otherwise the rematched dext might not be able to replace it
4248 								OSString * bundleID = OSDynamicCast(OSString, inst->getProperty(gIOModuleIdentifierKey));
4249 								IOLog("%s(0x%qx): stop matching as %s will be relaunched\n",
4250 								    getName(), getRegistryEntryID(),
4251 								    bundleID ? bundleID->getCStringNoCopy() : "(null)");
4252 								matchDeferred = true;
4253 							}
4254 						}
4255 					}
4256 				}
4257 				inst->release();
4258 			}
4259 		}
4260 		iter->release();
4261 	}
4262 
4263 	OSSafeReleaseNULL(prop1);
4264 
4265 	if (dextCount) {
4266 		num = OSNumber::withNumber(dextCount, 32);
4267 		setProperty(gIODEXTMatchCountKey, num);
4268 		OSSafeReleaseNULL(num);
4269 	} else if (rematchPersonality) {
4270 		removeProperty(gIODEXTMatchCountKey);
4271 	}
4272 
4273 	// now that instances are created, drop the refs on any kexts allowing unload
4274 	if (kexts) {
4275 		OSKext::dropMatchingReferences(kexts);
4276 		OSSafeReleaseNULL(kexts);
4277 	}
4278 
4279 	// adjust the busy count by +1 if matching is stalled for a module,
4280 	// or -1 if a previously stalled matching is complete.
4281 	lockForArbitration();
4282 	SInt32 adjBusy = 0;
4283 	uint64_t regID = getRegistryEntryID();
4284 
4285 	if (needReloc) {
4286 		adjBusy = (__state[1] & kIOServiceModuleStallState) ? 0 : 1;
4287 		if (adjBusy) {
4288 			IOServiceTrace(
4289 				IOSERVICE_MODULESTALL,
4290 				(uintptr_t) regID,
4291 				(uintptr_t) (regID >> 32),
4292 				(uintptr_t) this,
4293 				0);
4294 
4295 			__state[1] |= kIOServiceModuleStallState;
4296 		}
4297 	} else if (__state[1] & kIOServiceModuleStallState) {
4298 		IOServiceTrace(
4299 			IOSERVICE_MODULEUNSTALL,
4300 			(uintptr_t) regID,
4301 			(uintptr_t) (regID >> 32),
4302 			(uintptr_t) this,
4303 			0);
4304 
4305 		__state[1] &= ~kIOServiceModuleStallState;
4306 		adjBusy = -1;
4307 	}
4308 	if (adjBusy) {
4309 		_adjustBusy( adjBusy );
4310 	}
4311 	unlockForArbitration();
4312 
4313 	if (startDict) {
4314 		startDict->release();
4315 	}
4316 }
4317 
4318 /*
4319  * Wait for a IOUserServer to check in
4320  */
4321 
4322 static
4323 __attribute__((noinline, not_tail_called))
4324 IOUserServer *
__WAITING_FOR_USER_SERVER__(IOUserServerCheckInToken * token)4325 __WAITING_FOR_USER_SERVER__(IOUserServerCheckInToken * token)
4326 {
4327 	IOUserServer * result = NULL;
4328 	IOService * server = NULL;
4329 	const OSSymbol * serverName = token->copyServerName();
4330 	OSNumber       * serverTag = token->copyServerTag();
4331 	OSDictionary   * matching = IOService::serviceMatching(gIOUserServerClassKey);
4332 
4333 	if (!matching || !serverName || !serverTag) {
4334 		goto finish;
4335 	}
4336 	IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
4337 	if (!(kIODKDisableDextTag & gIODKDebug)) {
4338 		IOService::propertyMatching(gIOUserServerTagKey, serverTag, matching);
4339 	}
4340 
4341 	server = IOService::waitForMatchingServiceWithToken(matching, kIOUserServerCheckInTimeoutSecs * NSEC_PER_SEC, token);
4342 	result = OSDynamicCast(IOUserServer, server);
4343 	if (!result) {
4344 		OSSafeReleaseNULL(server);
4345 		token->cancel();
4346 	}
4347 
4348 finish:
4349 	OSSafeReleaseNULL(matching);
4350 	OSSafeReleaseNULL(serverName);
4351 	OSSafeReleaseNULL(serverTag);
4352 
4353 	return result;
4354 }
4355 
4356 void
willShutdown()4357 IOService::willShutdown()
4358 {
4359 	gIOKitWillTerminate = true;
4360 #if !NO_KEXTD
4361 	IOUserServerCheckInToken::cancelAll();
4362 #endif
4363 	OSKext::willShutdown();
4364 }
4365 
4366 bool
getWillUserspaceReboot()4367 IOService::getWillUserspaceReboot()
4368 {
4369 	return os_atomic_load(&gInUserspaceReboot, relaxed);
4370 }
4371 
4372 void
setWillUserspaceReboot()4373 IOService::setWillUserspaceReboot()
4374 {
4375 	IOLockLock(gJobsLock);
4376 #if !NO_KEXTD
4377 	IOService  * provider;
4378 	IOService  * service;
4379 	OSIterator * iter;
4380 
4381 	// Recreate the defer list if it does not exist
4382 	if (!gIOMatchDeferList && OSKext::iokitDaemonAvailable()) {
4383 		gIOMatchDeferList = OSArray::withCapacity( 16 );
4384 	}
4385 
4386 	if (gIOMatchDeferList) {
4387 		iter = IORegistryIterator::iterateOver(gIOServicePlane, kIORegistryIterateRecursively);
4388 		if (iter) {
4389 			do {
4390 				iter->reset();
4391 				while ((service = (IOService *)iter->getNextObject())) {
4392 					/* Rematch providers of services that will be terminated on userspace reboot, after the userspace reboot
4393 					 * is complete. This normally happens automatically as the IOKit daemon sends personalities to the kernel
4394 					 * which triggers rematching. But if this doesn't happen (for example, if a feature flag is turned off),
4395 					 * then these services will never get rematched.
4396 					 */
4397 					if (service->propertyHasValue(gIOMatchDeferKey, kOSBooleanTrue) || service->hasUserServer()) {
4398 						provider = service->getProvider();
4399 						IOLog("deferring %s-%llx (provider of %s-%llx) matching after userspace reboot\n",
4400 						    provider->getName(), provider->getRegistryEntryID(), service->getName(), service->getRegistryEntryID());
4401 						gIOMatchDeferList->setObject(provider);
4402 					}
4403 				}
4404 			} while (!service && !iter->isValid());
4405 
4406 			OSSafeReleaseNULL(iter);
4407 		}
4408 	}
4409 #endif
4410 	os_atomic_store(&gInUserspaceReboot, true, relaxed);
4411 	IOLockUnlock(gJobsLock);
4412 }
4413 
4414 void
userSpaceDidReboot()4415 IOService::userSpaceDidReboot()
4416 {
4417 	os_atomic_store(&gInUserspaceReboot, false, relaxed);
4418 }
4419 
4420 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4421 
4422 void
init(IOPMrootDomain * root)4423 IOServicePH::init(IOPMrootDomain * root)
4424 {
4425 	fUserServers     = OSArray::withCapacity(4);
4426 	fMatchingWork    = OSArray::withCapacity(4);
4427 
4428 	assert(fUserServers && fMatchingWork);
4429 
4430 	fRootNotifier = root->registerInterest(
4431 		gIOPriorityPowerStateInterest, &IOServicePH::systemPowerChange, NULL, NULL);
4432 
4433 	assert(fRootNotifier);
4434 
4435 	gIOUserResources->PMinit();
4436 	root->registerInterestedDriver(gIOUserResources);
4437 
4438 	fUserServerAckTimer = thread_call_allocate(&IOServicePH::userServerAckTimerExpired, (thread_call_param_t)NULL);
4439 }
4440 
4441 void
lock()4442 IOServicePH::lock()
4443 {
4444 	IOLockLock(gJobsLock);
4445 }
4446 
4447 void
unlock()4448 IOServicePH::unlock()
4449 {
4450 	IOLockUnlock(gJobsLock);
4451 }
4452 
4453 void
serverAdd(IOUserServer * server)4454 IOServicePH::serverAdd(IOUserServer * server)
4455 {
4456 	uint32_t idx;
4457 
4458 	lock();
4459 	idx = fUserServers->getNextIndexOfObject(server, 0);
4460 	if (idx == -1U) {
4461 		fUserServers->setObject(server);
4462 	}
4463 	unlock();
4464 }
4465 
4466 void
serverRemove(IOUserServer * server)4467 IOServicePH::serverRemove(IOUserServer * server)
4468 {
4469 	uint32_t idx;
4470 
4471 	lock();
4472 	idx = fUserServers->getNextIndexOfObject(server, 0);
4473 	if (idx != -1U) {
4474 		fUserServers->removeObject(idx);
4475 	}
4476 
4477 	if (fWaitingUserServers) {
4478 		fWaitingUserServers = false;
4479 		IOLockWakeup(gJobsLock, &fWaitingUserServers, /* one-thread */ false);
4480 	}
4481 
4482 	unlock();
4483 }
4484 
4485 void
serverAck(IOUserServer * server)4486 IOServicePH::serverAck(IOUserServer * server)
4487 {
4488 	uint32_t    idx;
4489 	IOService * ackTo;
4490 	uint32_t    ackToRef;
4491 	OSArray *   notifyServers;
4492 
4493 	ackTo = NULL;
4494 	notifyServers = NULL;
4495 	lock();
4496 	if (server && fUserServersWait) {
4497 		idx = fUserServersWait->getNextIndexOfObject(server, 0);
4498 		if (idx != -1U) {
4499 			fUserServersWait->removeObject(idx);
4500 			if (0 == fUserServersWait->getCount()) {
4501 				OSSafeReleaseNULL(fUserServersWait);
4502 			}
4503 		}
4504 	}
4505 	if (!fUserServersWait && !fMatchingWork->getCount()) {
4506 		ackTo             = fSystemPowerAckTo;
4507 		ackToRef          = fSystemPowerAckRef;
4508 		fSystemPowerAckTo = NULL;
4509 		if (ackTo) {
4510 			if (ackTo == gIOUserResources) {
4511 				notifyServers = OSArray::withArray(fUserServers);
4512 			}
4513 			thread_call_cancel(fUserServerAckTimer);
4514 		}
4515 	}
4516 	if (fUserServersWait && fUserServersWait->getCount() > 0 && fMatchingWork && fMatchingWork->getCount() > 0) {
4517 		DKLOG("Waiting for %u user servers, %u matching work\n", fUserServersWait->getCount(), fMatchingWork->getCount());
4518 	}
4519 	unlock();
4520 
4521 	if (ackTo == gIOUserResources) {
4522 		// suspend DK processes all at once since they can talk amongst themselves
4523 		// after SetPowerState()
4524 		if (notifyServers) {
4525 			notifyServers->iterateObjects(^bool (OSObject * obj) {
4526 				IOUserServer * us;
4527 				us = (typeof(us))obj;
4528 				us->systemSuspend();
4529 				return false;
4530 			});
4531 			OSSafeReleaseNULL(notifyServers);
4532 		}
4533 		DKLOG("allowPowerChange(2)\n");
4534 		IOService::getPMRootDomain()->acknowledgePowerChange(gIOUserResources);
4535 	} else if (ackTo) {
4536 		DKLOG("allowPowerChange(1)\n");
4537 		ackTo->allowPowerChange((uintptr_t) ackToRef);
4538 	}
4539 }
4540 
4541 bool
matchingStart(IOService * service)4542 IOServicePH::matchingStart(IOService * service)
4543 {
4544 	uint32_t idx;
4545 	bool assertionActive = gIOPMRootDomain->acquireDriverKitMatchingAssertion() == kIOReturnSuccess;
4546 
4547 	lock();
4548 	bool matchNow = (kIOServiceSystemStateOn == fSystemState) && assertionActive;
4549 	if (matchNow) {
4550 		idx = fMatchingWork->getNextIndexOfObject(service, 0);
4551 		if (idx == -1U) {
4552 			fMatchingWork->setObject(service);
4553 		}
4554 	} else {
4555 		// Delay matching if system is transitioning to sleep
4556 		if (!fMatchingDelayed) {
4557 			fMatchingDelayed = OSArray::withObjects((const OSObject **) &service, 1, 1);
4558 		} else {
4559 			idx = fMatchingDelayed->getNextIndexOfObject(service, 0);
4560 			if (idx == -1U) {
4561 				fMatchingDelayed->setObject(service);
4562 			}
4563 		}
4564 	}
4565 	unlock();
4566 	if (!matchNow && assertionActive) {
4567 		gIOPMRootDomain->releaseDriverKitMatchingAssertion();
4568 	}
4569 
4570 	return matchNow;
4571 }
4572 
4573 void
matchingEnd(IOService * service)4574 IOServicePH::matchingEnd(IOService * service)
4575 {
4576 	uint32_t idx;
4577 	OSArray   * notifyServers;
4578 	OSArray   * deferredMatches;
4579 
4580 	notifyServers   = NULL;
4581 	deferredMatches = NULL;
4582 
4583 	if (service) {
4584 		gIOPMRootDomain->releaseDriverKitMatchingAssertion();
4585 	}
4586 
4587 	lock();
4588 
4589 	if (service) {
4590 		idx = fMatchingWork->getNextIndexOfObject(service, 0);
4591 		if (idx != -1U) {
4592 			fMatchingWork->removeObject(idx);
4593 		}
4594 	}
4595 
4596 
4597 	if ((fUserServerSystemState != fSystemState) && fUserServers->getCount()) {
4598 		if (IsIOServiceSystemStateOff(fSystemState)) {
4599 			if (0 == fMatchingWork->getCount()) {
4600 				fUserServersWait = OSArray::withArray(fUserServers);
4601 				notifyServers = OSArray::withArray(fUserServers);
4602 				fUserServerSystemState = fSystemState;
4603 			}
4604 		} else {
4605 			notifyServers = OSArray::withArray(fUserServers);
4606 			fUserServerSystemState = fSystemState;
4607 		}
4608 	}
4609 
4610 	if ((kIOServiceSystemStateOn == fSystemState) && fMatchingDelayed) {
4611 		deferredMatches = fMatchingDelayed;
4612 		fMatchingDelayed = NULL;
4613 	}
4614 
4615 	unlock();
4616 
4617 	if (notifyServers) {
4618 		uint32_t sleepType = 0;
4619 		uint32_t standbyTimer = 0;
4620 		bool hibernate = false;
4621 		if (IsIOServiceSystemStateOff(fSystemState)
4622 		    && IOService::getPMRootDomain()->getSystemSleepType(&sleepType, &standbyTimer) == kIOReturnSuccess) {
4623 			hibernate = (sleepType == kIOPMSleepTypeHibernate);
4624 		}
4625 		notifyServers->iterateObjects(^bool (OSObject * obj) {
4626 			IOUserServer * us;
4627 			us = (typeof(us))obj;
4628 			us->systemPower(fSystemState, hibernate);
4629 			return false;
4630 		});
4631 		OSSafeReleaseNULL(notifyServers);
4632 	}
4633 
4634 	if (deferredMatches) {
4635 		DKLOG("sleep deferred rematching count %d\n", deferredMatches->getCount());
4636 		deferredMatches->iterateObjects(^bool (OSObject * obj)
4637 		{
4638 			((IOService *)obj)->startMatching(kIOServiceAsynchronous);
4639 			return false;
4640 		});
4641 		deferredMatches->release();
4642 	}
4643 
4644 	serverAck(NULL);
4645 }
4646 
4647 TUNABLE(uint32_t, dk_shutdown_timeout_ms, "dk_shutdown_timeout_ms", 30000);
4648 TUNABLE(bool, dk_panic_on_shutdown_hang, "dk_panic_on_shutdown_hang", false);
4649 #if DEVELOPMENT || DEBUG
4650 #define DK_SETPOWERSTATE_HANG true
4651 #else
4652 #define DK_SETPOWERSTATE_HANG false
4653 #endif
4654 TUNABLE(bool, dk_panic_on_setpowerstate_hang, "dk_panic_on_setpowerstate_hang", DK_SETPOWERSTATE_HANG);
4655 
4656 void
userServerAckTimerExpired(void *,void *)4657 IOServicePH::userServerAckTimerExpired(void *, void *)
4658 {
4659 	OSArray * userServers = NULL;
4660 	lock();
4661 	if (fSystemPowerAckTo) {
4662 		DKLOG("ack timer expired\n");
4663 		if (dk_panic_on_setpowerstate_hang) {
4664 			panic("DK ack timer expired after %u ms", dk_shutdown_timeout_ms);
4665 		}
4666 		userServers = fUserServersWait;
4667 		fUserServersWait = NULL;
4668 	}
4669 	unlock();
4670 
4671 	if (userServers != NULL) {
4672 		userServers->iterateObjects(^bool (OSObject *obj) {
4673 			IOUserServer * us = OSDynamicCast(IOUserServer, obj);
4674 			if (us) {
4675 			        DKLOG(DKS " power state transition failed\n", DKN(us));
4676 			        us->kill("Power Management Failed");
4677 			}
4678 			return false;
4679 		});
4680 		OSSafeReleaseNULL(userServers);
4681 	}
4682 
4683 	serverAck(NULL);
4684 }
4685 
4686 void
systemHalt(int howto)4687 IOServicePH::systemHalt(int howto)
4688 {
4689 	OSArray * notifyServers;
4690 	uint64_t  deadline;
4691 
4692 	lock();
4693 	notifyServers = OSArray::withArray(fUserServers);
4694 	unlock();
4695 
4696 	if (notifyServers) {
4697 		notifyServers->iterateObjects(^bool (OSObject * obj) {
4698 			IOUserServer * us;
4699 			us = (typeof(us))obj;
4700 			us->systemHalt(howto);
4701 			return false;
4702 		});
4703 		OSSafeReleaseNULL(notifyServers);
4704 	}
4705 
4706 	lock();
4707 	clock_interval_to_deadline(dk_shutdown_timeout_ms, kMillisecondScale, &deadline);
4708 	while (0 < fUserServers->getCount()) {
4709 		fWaitingUserServers = true;
4710 		__assert_only int waitResult =
4711 		    IOLockSleepDeadline(gJobsLock, &fWaitingUserServers, deadline, THREAD_UNINT);
4712 		assert((THREAD_AWAKENED == waitResult) || (THREAD_TIMED_OUT == waitResult));
4713 		if (THREAD_TIMED_OUT == waitResult) {
4714 			IOUserServer::beginLeakingObjects();
4715 #if DEVELOPMENT || DEBUG
4716 			if (dk_panic_on_shutdown_hang) {
4717 				panic("Shutdown timed out waiting for DK drivers to stop");
4718 			}
4719 #endif /* DEVELOPMENT || DEBUG */
4720 			break;
4721 		}
4722 	}
4723 	unlock();
4724 }
4725 
4726 bool
serverSlept(void)4727 IOServicePH::serverSlept(void)
4728 {
4729 	bool ret;
4730 
4731 	lock();
4732 	ret = (kIOMessageSystemWillSleep == sSystemPower)
4733 	    || (kIOMessageSystemWillPowerOff == sSystemPower)
4734 	    || (kIOMessageSystemWillRestart == sSystemPower);
4735 	unlock();
4736 
4737 	return ret;
4738 }
4739 
4740 TUNABLE(uint32_t, dk_power_state_timeout_ms, "dk_power_state_timeout_ms", 30000);
4741 
4742 //
4743 // Handle system changes:
4744 //
4745 // kIOServiceSystemStateOn
4746 // kIOServiceSystemStateAOT
4747 // kIOServiceSystemStateOffPhase1 - non-DK user space suspension
4748 // kIOServiceSystemStateOffPhase2 - DK user space suspension
4749 //
4750 
4751 void
systemPowerChange(uint8_t newState,IOService * ackTo,uint32_t ackRef,uint32_t * pMaxWaitForReply)4752 IOServicePH::systemPowerChange(uint8_t newState,
4753     IOService * ackTo,
4754     uint32_t ackRef,
4755     uint32_t * pMaxWaitForReply)
4756 {
4757 	AbsoluteTime deadline;
4758 
4759 	IOLog("IOServicePH::systemPowerChange to 0x%x\n", newState);
4760 
4761 	switch (newState) {
4762 	case kIOServiceSystemStateOffPhase1:
4763 	case kIOServiceSystemStateOffPhase2:
4764 
4765 		lock();
4766 		DKLOG("arming ack timer, %u ms\n", dk_power_state_timeout_ms);
4767 		clock_interval_to_deadline(dk_power_state_timeout_ms, kMillisecondScale, &deadline);
4768 		fSystemState       = newState;
4769 		fSystemPowerAckRef = ackRef;
4770 		fSystemPowerAckTo  = ackTo;
4771 		thread_call_enter_delayed(fUserServerAckTimer, deadline);
4772 		unlock();
4773 		matchingEnd(NULL);
4774 
4775 		*pMaxWaitForReply = dk_power_state_timeout_ms * 2 * 1000;
4776 		break;
4777 
4778 	case kIOServiceSystemStateAOT:
4779 	case kIOServiceSystemStateOn:
4780 
4781 		lock();
4782 		fSystemState = newState;
4783 		unlock();
4784 		matchingEnd(NULL);
4785 		*pMaxWaitForReply = 0;
4786 		break;
4787 
4788 	default:
4789 		assert(false);
4790 		break;
4791 	}
4792 }
4793 
4794 IOReturn
systemPowerChange(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgument,vm_size_t argSize)4795 IOServicePH::systemPowerChange(
4796 	void * target,
4797 	void * refCon,
4798 	UInt32 messageType, IOService * service,
4799 	void * messageArgument, vm_size_t argSize)
4800 {
4801 	IOReturn                               ret;
4802 	IOPMSystemCapabilityChangeParameters * params;
4803 
4804 	switch (messageType) {
4805 	case kIOMessageSystemCapabilityChange:
4806 		params = (typeof params)messageArgument;
4807 
4808 		IOLog("IOServicePH::kIOMessageSystemCapabilityChange: %s%s 0x%x->0x%x\n",
4809 		    params->changeFlags & kIOPMSystemCapabilityWillChange ? "will" : "",
4810 		    params->changeFlags & kIOPMSystemCapabilityDidChange ? "did" : "",
4811 		    params->fromCapabilities,
4812 		    params->toCapabilities);
4813 
4814 		if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
4815 		    (params->fromCapabilities & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)) &&
4816 		    ((params->toCapabilities & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)) == 0)) {
4817 			systemPowerChange(kIOServiceSystemStateOffPhase1, service, params->notifyRef, &params->maxWaitForReply);
4818 			ret = kIOReturnSuccess;
4819 		} else if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
4820 		    (0 != ((params->fromCapabilities ^ params->toCapabilities)
4821 		    & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)))) {
4822 			systemPowerChange((params->toCapabilities & kIOPMSystemCapabilityCPU) ? kIOServiceSystemStateOn : kIOServiceSystemStateAOT,
4823 			    service, params->notifyRef, &params->maxWaitForReply);
4824 			ret = kIOReturnSuccess;
4825 		} else {
4826 			params->maxWaitForReply = 0;
4827 			ret                 = kIOReturnSuccess;
4828 		}
4829 		break;
4830 
4831 	default:
4832 		ret = kIOReturnUnsupported;
4833 		break;
4834 	}
4835 
4836 	return ret;
4837 }
4838 
4839 IOReturn
rootWillChangeTo(IOPMPowerFlags flags,unsigned long state)4840 IOServicePH::rootWillChangeTo(IOPMPowerFlags flags, unsigned long state)
4841 {
4842 	IOReturn ret;
4843 	uint32_t maxWaitForReply = kIOPMAckImplied;
4844 
4845 	if (kIOPMSleepCapability & flags) {
4846 		systemPowerChange(kIOServiceSystemStateOffPhase2, gIOUserResources, 0, &maxWaitForReply);
4847 	} else if (kIOPMAOTCapability & flags) {
4848 		systemPowerChange(kIOServiceSystemStateAOT, NULL, 0, &maxWaitForReply);
4849 	} else if (kIOPMPowerOn & flags) {
4850 		systemPowerChange(kIOServiceSystemStateOn, NULL, 0, &maxWaitForReply);
4851 	}
4852 	ret = maxWaitForReply;
4853 	return ret;
4854 }
4855 
4856 bool
IOSystemStateAOT(void)4857 IOSystemStateAOT(void)
4858 {
4859 	return kIOServiceSystemStateAOT == IOServicePH::fSystemState;
4860 }
4861 
4862 bool
checkPMReady(void)4863 IOServicePH::checkPMReady(void)
4864 {
4865 	bool __block ready = true;
4866 
4867 	lock();
4868 	fUserServers->iterateObjects(^bool (OSObject *obj) {
4869 		IOUserServer * us = OSDynamicCast(IOUserServer, obj);
4870 		if (us) {
4871 		        if (!us->checkPMReady()) {
4872 		                ready = false;
4873 		                return true;
4874 			}
4875 		}
4876 		return false;
4877 	});
4878 	unlock();
4879 
4880 	return ready;
4881 }
4882 
4883 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4884 
4885 #if DEBUG || DEVELOPMENT
4886 void
__patchProperties(void)4887 IOService::__patchProperties(void)
4888 {
4889 #if 0
4890 	if (!strcmp("AppleCentauriManager", getName())) {
4891 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4892 	}
4893 	if (!strcmp("CentauriControl", getName())) {
4894 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4895 	}
4896 	if (!strcmp("CentauriAlpha", getName())) {
4897 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4898 	}
4899 	if (!strcmp("CentauriBeta", getName())) {
4900 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4901 	}
4902 #endif
4903 }
4904 #endif /* DEBUG || DEVELOPMENT */
4905 
4906 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4907 
4908 /*
4909  * Start a previously attached & probed instance,
4910  * called on exporting object instance
4911  */
4912 
4913 bool
startCandidate(IOService * service)4914 IOService::startCandidate( IOService * service )
4915 {
4916 	bool                ok;
4917 	OSObject          * obj;
4918 	OSObject          * prop;
4919 	IOUserServer      * userServer;
4920 	bool                ph;
4921 
4922 	userServer = NULL;
4923 	obj = service->copyProperty(gIOUserServerNameKey);
4924 
4925 	if (obj && (this == gIOResources)) {
4926 		ok = false;
4927 	} else {
4928 		ok = service->attach( this );
4929 	}
4930 	if (!ok) {
4931 		OSSafeReleaseNULL(obj);
4932 		return false;
4933 	}
4934 
4935 	if ((this != gIOResources) && (this != gIOUserResources)) {
4936 		// stall for any nub resources
4937 		checkResources();
4938 		// stall for any driver resources
4939 		service->checkResources();
4940 	}
4941 	ph = false;
4942 	{
4943 		OSString       * bundleID;
4944 		OSString       * serverName;
4945 		OSString       * str;
4946 		const OSSymbol * sym;
4947 		OSNumber       * serverTag;
4948 		uint64_t         entryID;
4949 		IOUserServerCheckInToken * token;
4950 		OSData         * serverDUI;
4951 
4952 		if ((serverName = OSDynamicCast(OSString, obj))) {
4953 			obj       = service->copyProperty(gIOModuleIdentifierKey);
4954 			bundleID  = OSDynamicCast(OSString, obj);
4955 			entryID   = service->getRegistryEntryID();
4956 			serverTag = OSNumber::withNumber(entryID, 64);
4957 			token     = NULL;
4958 
4959 			if (kIODKDisableDextLaunch & gIODKDebug) {
4960 				DKLOG(DKS " dext launches are disabled \n", DKN(service));
4961 				service->detach(this);
4962 				OSSafeReleaseNULL(serverName);
4963 				OSSafeReleaseNULL(obj);
4964 				OSSafeReleaseNULL(serverTag);
4965 				return false;
4966 			}
4967 
4968 			if (gIOKitWillTerminate) {
4969 				DKLOG("%s disabled in shutdown\n", serverName->getCStringNoCopy());
4970 				service->detach(this);
4971 				OSSafeReleaseNULL(serverName);
4972 				OSSafeReleaseNULL(obj);
4973 				OSSafeReleaseNULL(serverTag);
4974 				return false;
4975 			}
4976 
4977 			ph = IOServicePH::matchingStart(this);
4978 			if (!ph) {
4979 				DKLOG("%s deferred in sleep\n", serverName->getCStringNoCopy());
4980 				service->setProperty(gIOServiceMatchDeferredKey, kOSBooleanTrue);
4981 				service->detach(this);
4982 				OSSafeReleaseNULL(serverName);
4983 				OSSafeReleaseNULL(obj);
4984 				OSSafeReleaseNULL(serverTag);
4985 				return false;
4986 			}
4987 
4988 			prop = service->copyProperty(gIOUserClassKey);
4989 			str = OSDynamicCast(OSString, prop);
4990 			if (str) {
4991 				service->setName(str);
4992 			}
4993 			OSSafeReleaseNULL(prop);
4994 
4995 			sym = OSSymbol::withString(serverName);
4996 			bool reuse = service->propertyExists(gIOUserServerOneProcessKey);
4997 			bool reuseRequired = false;
4998 			if (propertyExists(gIOUserServerNameKey)) {
4999 				reuseRequired = reuse && service->propertyHasValue(gIOUserServerNameKey, getProperty(gIOUserServerNameKey));
5000 			}
5001 			serverDUI = OSDynamicCast(OSData, service->getProperty(kOSBundleDextUniqueIdentifierKey));
5002 			userServer = IOUserServer::launchUserServer(bundleID, sym, serverTag, reuse, &token, serverDUI);
5003 			OSSafeReleaseNULL(sym);
5004 			OSSafeReleaseNULL(serverTag);
5005 			OSSafeReleaseNULL(serverName);
5006 			if (userServer) {
5007 				DKLOG(DKS " using existing server " DKS "\n", DKN(service), DKN(userServer));
5008 			} else if (!reuseRequired && token != NULL) {
5009 				const OSSymbol * tokenServerName = token->copyServerName();
5010 				OSNumber * tokenServerTag = token->copyServerTag();
5011 				assert(tokenServerName && tokenServerTag);
5012 				DKLOG(DKS " waiting for server %s-%llx\n", DKN(service), tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue());
5013 				userServer = __WAITING_FOR_USER_SERVER__(token);
5014 				OSSafeReleaseNULL(tokenServerName);
5015 				OSSafeReleaseNULL(tokenServerTag);
5016 			} else if (reuseRequired) {
5017 				DKLOG(DKS " failed to reuse server\n", DKN(service));
5018 			} else {
5019 				DKLOG(DKS " failed to launch server\n", DKN(service));
5020 			}
5021 
5022 
5023 			if (!userServer) {
5024 				service->detach(this);
5025 				IOServicePH::matchingEnd(this);
5026 				OSSafeReleaseNULL(obj);
5027 
5028 				if (token != NULL) {
5029 					DKLOG(DKS " user server timeout\n", DKN(service));
5030 #if DEVELOPMENT || DEBUG
5031 					driverkit_checkin_timed_out = mach_absolute_time();
5032 #endif
5033 				}
5034 
5035 				OSSafeReleaseNULL(token);
5036 				return false;
5037 			}
5038 
5039 			if (token && !(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
5040 				if (!userServer->serviceMatchesCheckInToken(token)) {
5041 					OSSafeReleaseNULL(token);
5042 					service->detach(this);
5043 					IOServicePH::matchingEnd(this);
5044 					OSSafeReleaseNULL(obj);
5045 					userServer->exit("Check In Token verification failed");
5046 					userServer->release();
5047 					return false;
5048 				}
5049 			}
5050 			OSSafeReleaseNULL(token);
5051 			OSSafeReleaseNULL(obj);
5052 
5053 			if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
5054 				if (!userServer->checkEntitlements(this, service)) {
5055 					service->detach(this);
5056 					IOServicePH::matchingEnd(this);
5057 					userServer->exit("Entitlements check failed");
5058 					userServer->release();
5059 					return false;
5060 				}
5061 			}
5062 #if !XNU_TARGET_OS_OSX && !(DEVELOPMENT || DEBUG)
5063 			// Prevent third party drivers from matching IOUserResources/IOResources, except when signed for development
5064 			if (!userServer->isPlatformDriver() &&
5065 			    userServer->getCSValidationCategory() != CS_VALIDATION_CATEGORY_DEVELOPMENT
5066 			    && (this == gIOUserResources || this == gIOResources)) {
5067 				service->detach(this);
5068 				IOServicePH::matchingEnd(this);
5069 				userServer->exit("Third party driver may only match real hardware");
5070 				userServer->release();
5071 				return false;
5072 			}
5073 #endif /* !XNU_TARGET_OS_OSX && !(DEVELOPMENT || DEBUG) */
5074 
5075 			userServer->serviceAttach(service, this);
5076 		} else {
5077 			OSSafeReleaseNULL(obj);
5078 		}
5079 	}
5080 
5081 	AbsoluteTime startTime;
5082 	AbsoluteTime endTime;
5083 	UInt64       nano;
5084 	bool recordTime = (kIOLogStart & gIOKitDebug) != 0;
5085 
5086 	if (recordTime) {
5087 		clock_get_uptime(&startTime);
5088 	}
5089 
5090 #if DEBUG || DEVELOPMENT
5091 	service->__patchProperties();
5092 #endif /* DEBUG || DEVELOPMENT */
5093 
5094 	ok = service->start(this);
5095 
5096 	if (recordTime) {
5097 		clock_get_uptime(&endTime);
5098 
5099 		if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
5100 			SUB_ABSOLUTETIME(&endTime, &startTime);
5101 			absolutetime_to_nanoseconds(endTime, &nano);
5102 			if (nano > 500000000ULL) {
5103 				IOLog("%s[0x%qx]::start took %ld ms\n", service->getName(), service->getRegistryEntryID(), (long)(UInt32)(nano / 1000000ULL));
5104 			}
5105 		}
5106 	}
5107 	if (userServer) {
5108 		userServer->serviceStarted(service, this, ok);
5109 		userServer->release();
5110 	}
5111 
5112 	if (ok) {
5113 		IOInstallServiceSleepPlatformActions(service);
5114 #if 00
5115 		if (!strcmp("XHC1", getName())) {
5116 			service->setProperty(gIOPrimaryDriverTerminateOptionsKey, kOSBooleanTrue);
5117 		}
5118 #endif
5119 	}
5120 
5121 	if (!ok) {
5122 		service->detach( this );
5123 	}
5124 
5125 	if (ph) {
5126 		IOServicePH::matchingEnd(this);
5127 	}
5128 
5129 	return ok;
5130 }
5131 
5132 void
publishResource(const char * key,OSObject * value)5133 IOService::publishResource( const char * key, OSObject * value )
5134 {
5135 	const OSSymbol *    sym;
5136 
5137 	if ((sym = OSSymbol::withCString( key))) {
5138 		publishResource( sym, value);
5139 		sym->release();
5140 	}
5141 }
5142 
5143 void
publishResource(const OSSymbol * key,OSObject * value)5144 IOService::publishResource( const OSSymbol * key, OSObject * value )
5145 {
5146 	if (NULL == value) {
5147 		value = (OSObject *) gIOServiceKey;
5148 	}
5149 
5150 	gIOResources->setProperty( key, value);
5151 
5152 	if (IORecursiveLockHaveLock( gNotificationLock)) {
5153 		return;
5154 	}
5155 
5156 	gIOResourceGenerationCount++;
5157 	gIOResources->registerService();
5158 }
5159 
5160 void
publishUserResource(const OSSymbol * key,OSObject * value)5161 IOService::publishUserResource( const OSSymbol * key, OSObject * value )
5162 {
5163 	if (NULL == value) {
5164 		value = (OSObject *) gIOServiceKey;
5165 	}
5166 
5167 	gIOUserResources->setProperty( key, value);
5168 
5169 	if (IORecursiveLockHaveLock( gNotificationLock)) {
5170 		return;
5171 	}
5172 
5173 	gIOResourceGenerationCount++;
5174 	gIOUserResources->registerService();
5175 }
5176 
5177 bool
addNeededResource(const char * key)5178 IOService::addNeededResource( const char * key )
5179 {
5180 	OSObject *  resourcesProp;
5181 	OSSet *     set;
5182 	OSString *  newKey;
5183 	bool ret;
5184 
5185 	resourcesProp = copyProperty( gIOResourceMatchKey );
5186 	if (!resourcesProp) {
5187 		return false;
5188 	}
5189 
5190 	newKey = OSString::withCString( key );
5191 	if (!newKey) {
5192 		resourcesProp->release();
5193 		return false;
5194 	}
5195 
5196 	set = OSDynamicCast( OSSet, resourcesProp );
5197 	if (!set) {
5198 		set = OSSet::withCapacity( 1 );
5199 		set->setObject( resourcesProp );
5200 	} else {
5201 		set->retain();
5202 	}
5203 
5204 	set->setObject( newKey );
5205 	newKey->release();
5206 	ret = setProperty( gIOResourceMatchKey, set );
5207 	set->release();
5208 	resourcesProp->release();
5209 
5210 	return ret;
5211 }
5212 
5213 bool
checkResource(OSObject * matching)5214 IOService::checkResource( OSObject * matching )
5215 {
5216 	OSString *          str;
5217 	OSDictionary *      table;
5218 
5219 	if ((str = OSDynamicCast( OSString, matching ))) {
5220 		if (gIOResources->getProperty( str )) {
5221 			return true;
5222 		}
5223 	}
5224 
5225 	if (str) {
5226 		table = resourceMatching( str );
5227 	} else if ((table = OSDynamicCast( OSDictionary, matching ))) {
5228 		table->retain();
5229 	} else {
5230 		IOLog("%s: Can't match using: %s\n", getName(),
5231 		    matching->getMetaClass()->getClassName());
5232 		/* false would stall forever */
5233 		return true;
5234 	}
5235 
5236 	if (gIOKitDebug & kIOLogConfig) {
5237 		LOG("config(%p): stalling %s\n", IOSERVICE_OBFUSCATE(IOThreadSelf()), getName());
5238 	}
5239 
5240 	waitForService( table );
5241 
5242 	if (gIOKitDebug & kIOLogConfig) {
5243 		LOG("config(%p): waking\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
5244 	}
5245 
5246 	return true;
5247 }
5248 
5249 bool
checkResources(void)5250 IOService::checkResources( void )
5251 {
5252 	OSObject *          resourcesProp;
5253 	OSSet *             set;
5254 	OSObject *          obj;
5255 	OSIterator *        iter;
5256 	bool                ok;
5257 
5258 	resourcesProp = copyProperty( gIOResourceMatchKey );
5259 	if (NULL == resourcesProp) {
5260 		return true;
5261 	}
5262 
5263 	if ((set = OSDynamicCast( OSSet, resourcesProp ))) {
5264 		iter = OSCollectionIterator::withCollection( set );
5265 		ok = (NULL != iter);
5266 		while (ok && (obj = iter->getNextObject())) {
5267 			ok = checkResource( obj );
5268 		}
5269 		if (iter) {
5270 			iter->release();
5271 		}
5272 	} else {
5273 		ok = checkResource( resourcesProp );
5274 	}
5275 
5276 	OSSafeReleaseNULL(resourcesProp);
5277 
5278 	return ok;
5279 }
5280 
5281 
5282 void
configThread(const char * name)5283 _IOConfigThread::configThread( const char * name )
5284 {
5285 	_IOConfigThread *   inst;
5286 
5287 	do {
5288 		if (!(inst = new _IOConfigThread)) {
5289 			continue;
5290 		}
5291 		if (!inst->init()) {
5292 			continue;
5293 		}
5294 		thread_t thread;
5295 		if (KERN_SUCCESS != kernel_thread_start(&_IOConfigThread::main, inst, &thread)) {
5296 			continue;
5297 		}
5298 
5299 		char threadName[MAXTHREADNAMESIZE];
5300 		snprintf(threadName, sizeof(threadName), "IOConfigThread_'%s'", name);
5301 		thread_set_thread_name(thread, threadName);
5302 		thread_deallocate(thread);
5303 
5304 		return;
5305 	} while (false);
5306 
5307 	if (inst) {
5308 		inst->release();
5309 	}
5310 
5311 	return;
5312 }
5313 
5314 /*
5315  * To support driver replacement of boot matched drivers later in boot, drivers can
5316  * opt-in to be being terminated if a non-boot driver matches their provider, by
5317  * setting the gIOPrimaryDriverTerminateOptionsKey property. The driver providing the
5318  * root disk media may not be terminated.
5319  * IOMedia objects are hidden from user space until all drivers are available, but any
5320  * associated with the root disk must be published immediately.
5321  */
5322 
5323 struct FindRootMediaContext {
5324 	OSArray   * services;
5325 	IOService * parent;
5326 };
5327 
5328 bool
hasParent(IOService * parent)5329 IOService::hasParent(IOService * parent)
5330 {
5331 	IOService * service;
5332 
5333 	for (service = this;
5334 	    service && (service != parent);
5335 	    service = service->getProvider()) {
5336 	}
5337 
5338 	return service != NULL;
5339 }
5340 
5341 bool
publishHiddenMediaApplier(const OSObject * entry,void * context)5342 IOService::publishHiddenMediaApplier(const OSObject * entry, void * context)
5343 {
5344 	FindRootMediaContext * ctx     = (typeof(ctx))context;
5345 	IOService            * service = (typeof(service))entry;
5346 
5347 	do {
5348 		if (ctx->parent && !service->hasParent(ctx->parent)) {
5349 			break;
5350 		}
5351 		if (ctx->services) {
5352 			ctx->services->setObject(service);
5353 		} else {
5354 			ctx->services  = OSArray::withObjects((const OSObject **) &service, 1);
5355 			assert(ctx->services);
5356 		}
5357 	} while (false);
5358 
5359 	return false;
5360 }
5361 
5362 // publish to user space any hidden IOMedia under the 'parent' object, or all
5363 // if 'parent' is NULL
5364 
5365 void
publishHiddenMedia(IOService * parent)5366 IOService::publishHiddenMedia(IOService * parent)
5367 {
5368 	const OSMetaClass * iomediaClass;
5369 	bool                wasHiding;
5370 
5371 	iomediaClass = OSMetaClass::getMetaClassWithName(gIOMediaKey);
5372 	assert(iomediaClass);
5373 
5374 	LOCKWRITENOTIFY();
5375 	wasHiding = gIOServiceHideIOMedia;
5376 	if (wasHiding && !parent) {
5377 		gIOServiceHideIOMedia = false;
5378 	}
5379 	UNLOCKNOTIFY();
5380 
5381 	FindRootMediaContext ctx = { .services = NULL, .parent = parent };
5382 
5383 	if (wasHiding) {
5384 		iomediaClass->applyToInstances(publishHiddenMediaApplier, &ctx);
5385 	}
5386 	if (ctx.services) {
5387 		unsigned int idx, notiIdx;
5388 		IOService * service;
5389 		OSArray   * notifiers[3] = {};
5390 
5391 		for (idx = 0; (service = (IOService *) ctx.services->getObject(idx)); idx++) {
5392 			service->lockForArbitration(true);
5393 			if (!(kIOServiceUserInvisibleMatchState & service->__state[0])) {
5394 				service->unlockForArbitration();
5395 				continue;
5396 			}
5397 			service->__state[0] &= ~kIOServiceUserInvisibleMatchState;
5398 			service->__state[1] |= kIOServiceUserUnhidden;
5399 			notifiers[0] = service->copyNotifiers(gIOFirstPublishNotification, 0, 0xffffffff);
5400 			if (kIOServiceMatchedState & service->__state[0]) {
5401 				notifiers[1] = service->copyNotifiers(gIOMatchedNotification, 0, 0xffffffff);
5402 			}
5403 			if (kIOServiceFirstMatchState & service->__state[0]) {
5404 				notifiers[2] = service->copyNotifiers(gIOFirstMatchNotification, 0, 0xffffffff);
5405 			}
5406 			service->unlockForArbitration();
5407 			for (notiIdx = 0; notiIdx < 3; notiIdx++) {
5408 				service->invokeNotifiers(&notifiers[notiIdx]);
5409 			}
5410 		}
5411 		OSSafeReleaseNULL(ctx.services);
5412 	}
5413 }
5414 
5415 // Find the block storage driver providing the root disk, or NULL if not booting from
5416 // a block device
5417 
5418 void
setRootMedia(IOService * root)5419 IOService::setRootMedia(IOService * root)
5420 {
5421 	const OSMetaClass * ioblockstoragedriverClass;
5422 	bool unhide;
5423 
5424 	ioblockstoragedriverClass = OSMetaClass::getMetaClassWithName(gIOBlockStorageDriverKey);
5425 	assert(ioblockstoragedriverClass);
5426 
5427 	while (root) {
5428 		if (root->metaCast(ioblockstoragedriverClass)) {
5429 			break;
5430 		}
5431 		root = root->getProvider();
5432 	}
5433 
5434 	LOCKWRITENOTIFY();
5435 	unhide = (kIOServiceRootMediaParentInvalid == gIOServiceRootMediaParent);
5436 	if (unhide) {
5437 		gIOServiceRootMediaParent = root;
5438 	}
5439 	UNLOCKNOTIFY();
5440 
5441 	if (unhide) {
5442 		if (root) {
5443 			root->addPMDriverClass(kIOPMDriverClassStorage);
5444 		}
5445 		publishHiddenMedia(root);
5446 	}
5447 }
5448 
5449 // Check if the driver may be terminated when a later driver could be used instead
5450 
5451 bool
canTerminateForReplacement(IOService * client)5452 IOService::canTerminateForReplacement(IOService * client)
5453 {
5454 	IOService * parent;
5455 
5456 	assert(kIOServiceRootMediaParentInvalid != gIOServiceRootMediaParent);
5457 
5458 	if (!gIOServiceHideIOMedia) {
5459 		return false;
5460 	}
5461 	if (!client->propertyExists(gIOPrimaryDriverTerminateOptionsKey)) {
5462 		return false;
5463 	}
5464 	if (!gIOServiceRootMediaParent) {
5465 		return false;
5466 	}
5467 	parent = gIOServiceRootMediaParent;
5468 	while (parent && (parent != client)) {
5469 		parent = parent->getProvider();
5470 	}
5471 	if (parent) {
5472 		IOLog("Can't replace primary matched driver on root media %s-0x%qx\n",
5473 		    client->getName(), client->getRegistryEntryID());
5474 		return false;
5475 	}
5476 	return true;
5477 }
5478 
5479 void
doServiceMatch(IOOptionBits options)5480 IOService::doServiceMatch( IOOptionBits options )
5481 {
5482 	_IOServiceNotifier * notify;
5483 	OSIterator *        iter;
5484 	OSOrderedSet *      matches;
5485 	OSArray *           resourceKeys = NULL;
5486 	SInt32              catalogGeneration;
5487 	bool                keepGuessing = true;
5488 	bool                reRegistered = true;
5489 	bool                didRegister;
5490 	OSArray *           notifiers[2] = {NULL};
5491 
5492 //    job->nub->deliverNotification( gIOPublishNotification,
5493 //                              kIOServiceRegisteredState, 0xffffffff );
5494 
5495 	while (keepGuessing) {
5496 		matches = gIOCatalogue->findDrivers( this, &catalogGeneration );
5497 		// the matches list should always be created by findDrivers()
5498 		if (matches) {
5499 			lockForArbitration();
5500 			if (0 == (__state[0] & kIOServiceFirstPublishState)) {
5501 				getMetaClass()->addInstance(this);
5502 				notifiers[0] = copyNotifiers(gIOFirstPublishNotification,
5503 				    kIOServiceFirstPublishState, 0xffffffff );
5504 			}
5505 			LOCKREADNOTIFY();
5506 			__state[1] &= ~kIOServiceNeedConfigState;
5507 			__state[1] |= kIOServiceConfigState | kIOServiceConfigRunning;
5508 			didRegister = (0 == (kIOServiceRegisteredState & __state[0]));
5509 			__state[0] |= kIOServiceRegisteredState;
5510 
5511 			if (gIOServiceHideIOMedia
5512 			    && metaCast(gIOMediaKey)
5513 			    && !(kIOServiceUserUnhidden & __state[1])
5514 			    && gIOServiceRootMediaParent
5515 			    && !hasParent(gIOServiceRootMediaParent)
5516 			    && propertyExists(gIOPrimaryDriverTerminateOptionsKey, gIOServicePlane)) {
5517 				__state[0] |= kIOServiceUserInvisibleMatchState;
5518 			}
5519 
5520 			keepGuessing &= (0 == (__state[0] & kIOServiceInactiveState));
5521 			if (reRegistered && keepGuessing) {
5522 				iter = OSCollectionIterator::withCollection((OSOrderedSet *)
5523 				    gNotifications->getObject( gIOPublishNotification ));
5524 				if (iter) {
5525 					while ((notify = (_IOServiceNotifier *)
5526 					    iter->getNextObject())) {
5527 						if (matchPassive(notify->matching, 0)
5528 						    && (kIOServiceNotifyEnable & notify->state)) {
5529 							matches->setObject( notify );
5530 						}
5531 					}
5532 					iter->release();
5533 				}
5534 			}
5535 
5536 			UNLOCKNOTIFY();
5537 			unlockForArbitration();
5538 			invokeNotifiers(&notifiers[0]);
5539 			if (keepGuessing && matches->getCount() && (kIOReturnSuccess == getResources())) {
5540 				if ((this == gIOResources) || (this == gIOUserResources)) {
5541 					if (resourceKeys) {
5542 						resourceKeys->release();
5543 					}
5544 					resourceKeys = copyPropertyKeys();
5545 				}
5546 				probeCandidates( matches );
5547 			} else {
5548 				matches->release();
5549 			}
5550 		}
5551 
5552 		lockForArbitration();
5553 		reRegistered = (0 != (__state[1] & kIOServiceNeedConfigState));
5554 		keepGuessing =
5555 		    (reRegistered || (catalogGeneration !=
5556 		    gIOCatalogue->getGenerationCount()))
5557 		    && (0 == (__state[0] & kIOServiceInactiveState));
5558 
5559 		if (keepGuessing) {
5560 			unlockForArbitration();
5561 		}
5562 	}
5563 
5564 	if ((0 == (__state[0] & kIOServiceInactiveState))
5565 	    && (0 == (__state[1] & kIOServiceModuleStallState))) {
5566 		if (resourceKeys) {
5567 			setProperty(gIOResourceMatchedKey, resourceKeys);
5568 		}
5569 
5570 		notifiers[0] = copyNotifiers(gIOMatchedNotification,
5571 		    kIOServiceMatchedState, 0xffffffff);
5572 		if (0 == (__state[0] & kIOServiceFirstMatchState)) {
5573 			notifiers[1] = copyNotifiers(gIOFirstMatchNotification,
5574 			    kIOServiceFirstMatchState, 0xffffffff);
5575 		}
5576 	}
5577 
5578 	__state[1] &= ~kIOServiceConfigRunning;
5579 	unlockForArbitration();
5580 
5581 	if (resourceKeys) {
5582 		resourceKeys->release();
5583 	}
5584 
5585 	invokeNotifiers(&notifiers[0]);
5586 	invokeNotifiers(&notifiers[1]);
5587 
5588 	lockForArbitration();
5589 	__state[1] &= ~kIOServiceConfigState;
5590 	scheduleTerminatePhase2();
5591 
5592 	_adjustBusy(-1, /*unlock*/ true);
5593 	// does	unlockForArbitration();
5594 }
5595 
5596 UInt32
_adjustBusy(SInt32 delta)5597 IOService::_adjustBusy(SInt32 delta)
5598 {
5599 	return _adjustBusy(delta, false);
5600 }
5601 
5602 UInt32
_adjustBusy(SInt32 delta,bool unlock)5603 IOService::_adjustBusy(SInt32 delta, bool unlock)
5604 {
5605 	IOService * next;
5606 	IOService * nextProvider;
5607 	UInt32      count;
5608 	UInt32      result;
5609 	bool        wasQuiet, nowQuiet, needWake;
5610 
5611 	next = this;
5612 	result = __state[1] & kIOServiceBusyStateMask;
5613 
5614 	if (delta) {
5615 		do {
5616 			if (next != this) {
5617 				next->lockForArbitration();
5618 			}
5619 			count = next->__state[1] & kIOServiceBusyStateMask;
5620 			wasQuiet = (0 == count);
5621 			if (((delta < 0) && wasQuiet) || ((delta > 0) && (kIOServiceBusyMax == count))) {
5622 				OSReportWithBacktrace("%s: bad busy count (%d,%d)\n", next->getName(), (uint32_t)count, (int)delta);
5623 			} else {
5624 				count += delta;
5625 			}
5626 			next->__state[1] = (next->__state[1] & ~kIOServiceBusyStateMask) | count;
5627 			nowQuiet = (0 == count);
5628 			needWake = (0 != (kIOServiceBusyWaiterState & next->__state[1]));
5629 
5630 			if (needWake) {
5631 				next->__state[1] &= ~kIOServiceBusyWaiterState;
5632 				IOLockLock( gIOServiceBusyLock );
5633 				thread_wakeup((event_t) next);
5634 				IOLockUnlock( gIOServiceBusyLock );
5635 			}
5636 			if (wasQuiet || nowQuiet) {
5637 				nextProvider = next->getProvider();
5638 				if (nextProvider) {
5639 					nextProvider->retain();
5640 				}
5641 			}
5642 			if ((next != this) || unlock) {
5643 				next->unlockForArbitration();
5644 			}
5645 
5646 			if ((wasQuiet || nowQuiet)) {
5647 				uint64_t regID = next->getRegistryEntryID();
5648 				IOServiceTrace(
5649 					((wasQuiet /*nowBusy*/) ? IOSERVICE_BUSY : IOSERVICE_NONBUSY),
5650 					(uintptr_t) regID,
5651 					(uintptr_t) (regID >> 32),
5652 					(uintptr_t) next,
5653 					0);
5654 
5655 				if (wasQuiet) {
5656 					next->__timeBusy = mach_absolute_time();
5657 				} else {
5658 					next->__accumBusy += mach_absolute_time() - next->__timeBusy;
5659 					next->__timeBusy = 0;
5660 				}
5661 
5662 				MessageClientsContext context;
5663 
5664 				context.service  = next;
5665 				context.type     = kIOMessageServiceBusyStateChange;
5666 				context.argument = (void *) wasQuiet; /*nowBusy*/
5667 				context.argSize  = 0;
5668 
5669 				applyToInterestNotifiers( next, gIOBusyInterest,
5670 				    &messageClientsApplier, &context );
5671 
5672 #if !NO_KEXTD
5673 				if (nowQuiet && (next == gIOServiceRoot)) {
5674 					if (gIOServiceHideIOMedia) {
5675 						publishHiddenMedia(NULL);
5676 					}
5677 
5678 					OSKext::considerUnloads();
5679 					IOServiceTrace(IOSERVICE_REGISTRY_QUIET, 0, 0, 0, 0);
5680 				}
5681 #endif
5682 			}
5683 
5684 			delta = nowQuiet ? -1 : +1;
5685 			if (next != this) {
5686 				next->release();
5687 			}
5688 			next = nextProvider;
5689 			nextProvider = NULL;
5690 		} while ((wasQuiet || nowQuiet) && next);
5691 	}
5692 
5693 	return result;
5694 }
5695 
5696 void
adjustBusy(SInt32 delta)5697 IOService::adjustBusy( SInt32 delta )
5698 {
5699 	lockForArbitration();
5700 	_adjustBusy( delta );
5701 	unlockForArbitration();
5702 }
5703 
5704 uint64_t
getAccumulatedBusyTime(void)5705 IOService::getAccumulatedBusyTime( void )
5706 {
5707 	uint64_t accumBusy = __accumBusy;
5708 	uint64_t timeBusy = __timeBusy;
5709 	uint64_t nano;
5710 
5711 	do{
5712 		accumBusy = __accumBusy;
5713 		timeBusy  = __timeBusy;
5714 		if (timeBusy) {
5715 			accumBusy += mach_absolute_time() - timeBusy;
5716 		}
5717 	}while (timeBusy != __timeBusy);
5718 
5719 	absolutetime_to_nanoseconds(*(AbsoluteTime *)&accumBusy, &nano);
5720 
5721 	return nano;
5722 }
5723 
5724 UInt32
getBusyState(void)5725 IOService::getBusyState( void )
5726 {
5727 	return __state[1] & kIOServiceBusyStateMask;
5728 }
5729 
5730 IOReturn
waitForState(UInt32 mask,UInt32 value,mach_timespec_t * timeout)5731 IOService::waitForState( UInt32 mask, UInt32 value,
5732     mach_timespec_t * timeout )
5733 {
5734 	panic("waitForState");
5735 	return kIOReturnUnsupported;
5736 }
5737 
5738 IOReturn
waitForState(UInt32 mask,UInt32 value,uint64_t timeout)5739 IOService::waitForState( UInt32 mask, UInt32 value,
5740     uint64_t timeout )
5741 {
5742 	bool            wait, done;
5743 	int             waitResult = THREAD_AWAKENED;
5744 	bool            computeDeadline = true;
5745 	AbsoluteTime    abstime;
5746 
5747 	do {
5748 		lockForArbitration();
5749 		IOLockLock( gIOServiceBusyLock );
5750 		done = (value == (__state[1] & mask));
5751 		wait = (waitResult != THREAD_TIMED_OUT) && !done;
5752 		if (wait) {
5753 			__state[1] |= kIOServiceBusyWaiterState;
5754 			unlockForArbitration();
5755 			if (timeout != UINT64_MAX) {
5756 				if (computeDeadline) {
5757 					AbsoluteTime  nsinterval;
5758 					nanoseconds_to_absolutetime(timeout, &nsinterval );
5759 					clock_absolutetime_interval_to_deadline(nsinterval, &abstime);
5760 					computeDeadline = false;
5761 				}
5762 				assert_wait_deadline((event_t)this, THREAD_UNINT, __OSAbsoluteTime(abstime));
5763 			} else {
5764 				assert_wait((event_t)this, THREAD_UNINT );
5765 			}
5766 		} else {
5767 			unlockForArbitration();
5768 		}
5769 		IOLockUnlock( gIOServiceBusyLock );
5770 		if (wait) {
5771 			waitResult = thread_block(THREAD_CONTINUE_NULL);
5772 		}
5773 	} while (wait);
5774 
5775 	if (done) {
5776 		return kIOReturnSuccess;
5777 	} else {
5778 		return kIOReturnTimeout;
5779 	}
5780 }
5781 
5782 IOReturn
waitQuietWithOptions(uint64_t timeout,IOOptionBits options)5783 IOService::waitQuietWithOptions( uint64_t timeout, IOOptionBits options )
5784 {
5785 	IOReturn ret;
5786 	uint32_t loops, timeoutExtensions;
5787 	char *   busyEntriesString = NULL;
5788 	char *   panicString = NULL;
5789 	size_t   busyEntriesStringLen;
5790 	size_t   panicStringLen;
5791 	uint64_t time;
5792 	uint64_t nano;
5793 	bool     pendingRequests;
5794 	bool     registryRootBusy;
5795 	bool     multipleEntries;
5796 	bool     dopanic = false;
5797 
5798 	enum { kIOServiceBusyTimeoutExtensionsMax = 8 };
5799 #if KASAN
5800 	/*
5801 	 * On kasan kernels, everything takes longer, so double the number of
5802 	 * timeout extensions. This should help with issues like 41259215
5803 	 * where WindowServer was timing out waiting for kextd to get all the
5804 	 * kasan kexts loaded and started.
5805 	 *
5806 	 * On legacy/x86 systems give a bit more time since we may be
5807 	 * booting from a HDD.
5808 	 */
5809 	enum { kTimeoutExtensions = 8 };
5810 #define WITH_IOWAITQUIET_EXTENSIONS 1
5811 #elif defined(__x86_64__)
5812 	enum { kTimeoutExtensions = 4 };
5813 #define WITH_IOWAITQUIET_EXTENSIONS 1
5814 #elif  defined(XNU_TARGET_OS_OSX)
5815 	enum { kTimeoutExtensions = 1 };
5816 #define WITH_IOWAITQUIET_EXTENSIONS 1
5817 #else
5818 	enum { kTimeoutExtensions = 1 };
5819 #define WITH_IOWAITQUIET_EXTENSIONS 0
5820 #endif
5821 
5822 	timeoutExtensions = kTimeoutExtensions;
5823 	time = mach_absolute_time();
5824 	pendingRequests = false;
5825 	for (loops = 0; loops < timeoutExtensions; loops++) {
5826 		ret = waitForState( kIOServiceBusyStateMask, 0, timeout );
5827 
5828 		if (loops && (kIOReturnSuccess == ret)) {
5829 			time = mach_absolute_time() - time;
5830 			absolutetime_to_nanoseconds(*(AbsoluteTime *)&time, &nano);
5831 			IOLog("busy extended ok[%d], (%llds, %llds)\n",
5832 			    loops, timeout / 1000000000ULL, nano / 1000000000ULL);
5833 			break;
5834 		} else if (kIOReturnTimeout != ret) {
5835 			break;
5836 		} else if (timeout < (41ull * NSEC_PER_SEC)) {
5837 			break;
5838 		}
5839 
5840 		{
5841 			IORegistryIterator * iter;
5842 			OSOrderedSet       * set;
5843 			OSOrderedSet       * leaves;
5844 			IOService          * next;
5845 			IOService          * nextParent;
5846 			char               * s;
5847 			size_t               l;
5848 			size_t               busyEntriesStringRemaining;
5849 
5850 			busyEntriesStringLen = 256;
5851 			panicStringLen = 256;
5852 			if (!busyEntriesString) {
5853 				busyEntriesString = IONewZeroData(char, busyEntriesStringLen);
5854 				assert(busyEntriesString != NULL);
5855 			}
5856 			if (!panicString) {
5857 				panicString = IONewZeroData(char, panicStringLen);
5858 				assert(panicString != NULL);
5859 			}
5860 
5861 			set = NULL;
5862 			pendingRequests = OSKext::pendingIOKitDaemonRequests();
5863 			iter = IORegistryIterator::iterateOver(this, gIOServicePlane, kIORegistryIterateRecursively);
5864 			leaves = OSOrderedSet::withCapacity(4);
5865 			if (iter) {
5866 				set = iter->iterateAll();
5867 			}
5868 			if (leaves && set) {
5869 				busyEntriesString[0] = panicString[0] = 0;
5870 				set->setObject(this);
5871 				while ((next = (IOService *) set->getLastObject())) {
5872 					if (next->getBusyState()) {
5873 						if (kIOServiceModuleStallState & next->__state[1]) {
5874 							pendingRequests = true;
5875 						}
5876 #if defined(XNU_TARGET_OS_OSX)
5877 						OSObject * prop;
5878 						if ((prop = next->copyProperty(kIOServiceBusyTimeoutExtensionsKey, gIOServicePlane))) {
5879 							OSNumber * num;
5880 							uint32_t   value;
5881 							if ((num = OSDynamicCast(OSNumber, prop))) {
5882 								value = num->unsigned32BitValue();
5883 								if (value
5884 								    && (value <= kIOServiceBusyTimeoutExtensionsMax)
5885 								    && (value > timeoutExtensions)) {
5886 									timeoutExtensions = value;
5887 								}
5888 							}
5889 							OSSafeReleaseNULL(prop);
5890 						}
5891 #endif /* defined(XNU_TARGET_OS_OSX) */
5892 						leaves->setObject(next);
5893 						nextParent = next;
5894 						while ((nextParent = nextParent->getProvider())) {
5895 							set->removeObject(nextParent);
5896 							leaves->removeObject(nextParent);
5897 						}
5898 					}
5899 					set->removeObject(next);
5900 				}
5901 				registryRootBusy = leaves->getCount() == 1 && leaves->getObject(0) == getServiceRoot();
5902 				multipleEntries = leaves->getCount() > 1;
5903 				s = busyEntriesString;
5904 				busyEntriesStringRemaining = busyEntriesStringLen;
5905 
5906 				if (registryRootBusy) {
5907 					snprintf(s, busyEntriesStringRemaining, "registry root held busy, " kIOKitDaemonName " %s checked in", OSKext::iokitDaemonActive() ? "has" : "has not");
5908 				} else {
5909 					while ((next = (IOService *) leaves->getLastObject())) {
5910 						l = snprintf(s, busyEntriesStringRemaining, "%s'%s' (%x,%x)", ((s == busyEntriesString) ? "" : ", "), next->getName(), (uint32_t)next->__state[0], (uint32_t)next->__state[1]);
5911 						if (l >= busyEntriesStringRemaining) {
5912 							break;
5913 						}
5914 						s += l;
5915 						busyEntriesStringRemaining -= l;
5916 						leaves->removeObject(next);
5917 					}
5918 				}
5919 			}
5920 			OSSafeReleaseNULL(leaves);
5921 			OSSafeReleaseNULL(set);
5922 			OSSafeReleaseNULL(iter);
5923 		}
5924 
5925 		dopanic = (kIOWaitQuietPanics & gIOKitDebug) && (options & kIOWaitQuietPanicOnFailure) && !gIOKitWillTerminate;
5926 #if WITH_IOWAITQUIET_EXTENSIONS
5927 		dopanic = (dopanic && (loops >= (timeoutExtensions - 1)));
5928 #endif
5929 		assert(panicString != NULL);
5930 		if (multipleEntries) {
5931 			snprintf(panicString, panicStringLen,
5932 			    "%s[%d], (%llds): multiple entries holding the registry busy, IOKit termination queue depth %u: %s",
5933 			    pendingRequests ? "IOKit Daemon (" kIOKitDaemonName ") stall" : "busy timeout",
5934 			    loops, timeout / 1000000000ULL,
5935 			    (uint32_t)gIOTerminateWork,
5936 			    busyEntriesString ? busyEntriesString : "");
5937 		} else {
5938 			snprintf(panicString, panicStringLen,
5939 			    "%s[%d], (%llds): %s",
5940 			    pendingRequests ? "IOKit Daemon (" kIOKitDaemonName ") stall" : "busy timeout",
5941 			    loops, timeout / 1000000000ULL,
5942 			    busyEntriesString ? busyEntriesString : "");
5943 		}
5944 
5945 		IOLog("%s\n", panicString);
5946 		if (dopanic) {
5947 			panic("%s", panicString);
5948 		} else if (!loops) {
5949 			getPMRootDomain()->startSpinDump(1);
5950 		}
5951 	}
5952 
5953 	if (busyEntriesString) {
5954 		IODeleteData(busyEntriesString, char, busyEntriesStringLen);
5955 	}
5956 	if (panicString) {
5957 		IODeleteData(panicString, char, panicStringLen);
5958 	}
5959 
5960 	return ret;
5961 }
5962 
5963 IOReturn
waitQuiet(uint64_t timeout)5964 IOService::waitQuiet( uint64_t timeout )
5965 {
5966 	return waitQuietWithOptions(timeout);
5967 }
5968 
5969 IOReturn
waitQuiet(mach_timespec_t * timeout)5970 IOService::waitQuiet( mach_timespec_t * timeout )
5971 {
5972 	uint64_t    timeoutNS;
5973 
5974 	if (timeout) {
5975 		timeoutNS = timeout->tv_sec;
5976 		timeoutNS *= kSecondScale;
5977 		timeoutNS += timeout->tv_nsec;
5978 	} else {
5979 		timeoutNS = UINT64_MAX;
5980 	}
5981 
5982 	return waitQuiet(timeoutNS);
5983 }
5984 
5985 bool
serializeProperties(OSSerialize * s) const5986 IOService::serializeProperties( OSSerialize * s ) const
5987 {
5988 #if 0
5989 	((IOService *)this)->setProperty(((IOService *)this)->__state,
5990 	    sizeof(__state), "__state");
5991 #endif
5992 	return super::serializeProperties(s);
5993 }
5994 
5995 void
resetRematchProperties()5996 IOService::resetRematchProperties()
5997 {
5998 	removeProperty(gIORematchCountKey);
5999 	removeProperty(gIORematchPersonalityKey);
6000 }
6001 
6002 
6003 void
main(void * arg,wait_result_t result)6004 _IOConfigThread::main(void * arg, wait_result_t result)
6005 {
6006 	_IOConfigThread * self = (_IOConfigThread *) arg;
6007 	_IOServiceJob * job;
6008 	IOService   *   nub;
6009 	bool            alive = true;
6010 	kern_return_t   kr;
6011 	thread_precedence_policy_data_t precedence = { -1 };
6012 
6013 	kr = thread_policy_set(current_thread(),
6014 	    THREAD_PRECEDENCE_POLICY,
6015 	    (thread_policy_t) &precedence,
6016 	    THREAD_PRECEDENCE_POLICY_COUNT);
6017 	if (KERN_SUCCESS != kr) {
6018 		IOLog("thread_policy_set(%d)\n", kr);
6019 	}
6020 
6021 	do {
6022 //	randomDelay();
6023 
6024 		semaphore_wait( gJobsSemaphore );
6025 
6026 		IOTakeLock( gJobsLock );
6027 		job = (_IOServiceJob *) gJobs->getFirstObject();
6028 		job->retain();
6029 		gJobs->removeObject(job);
6030 		if (job) {
6031 			gOutstandingJobs--;
6032 //	    gNumConfigThreads--;	// we're out of service
6033 			gNumWaitingThreads--; // we're out of service
6034 		}
6035 		IOUnlock( gJobsLock );
6036 
6037 		if (job) {
6038 			nub = job->nub;
6039 
6040 			if (gIOKitDebug & kIOLogConfig) {
6041 				LOG("config(%p): starting on %s, %d\n",
6042 				    IOSERVICE_OBFUSCATE(IOThreadSelf()), job->nub->getName(), job->type);
6043 			}
6044 
6045 			switch (job->type) {
6046 			case kMatchNubJob:
6047 				nub->doServiceMatch( job->options );
6048 				break;
6049 
6050 			default:
6051 				LOG("config(%p): strange type (%d)\n",
6052 				    IOSERVICE_OBFUSCATE(IOThreadSelf()), job->type );
6053 				break;
6054 			}
6055 
6056 			if (job->options & kIOServiceDextRequirePowerForMatching) {
6057 				gIOPMRootDomain->releaseDriverKitMatchingAssertion();
6058 			}
6059 
6060 			OSSafeReleaseNULL(nub);
6061 			OSSafeReleaseNULL(job);
6062 
6063 			IOTakeLock( gJobsLock );
6064 			alive = (gOutstandingJobs > gNumWaitingThreads);
6065 			if (alive) {
6066 				gNumWaitingThreads++; // back in service
6067 			}
6068 //		gNumConfigThreads++;
6069 			else {
6070 				if (0 == --gNumConfigThreads) {
6071 //                    IOLog("MATCH IDLE\n");
6072 					IOLockWakeup( gJobsLock, (event_t) &gNumConfigThreads, /* one-thread */ false );
6073 				}
6074 			}
6075 			IOUnlock( gJobsLock );
6076 		}
6077 	} while (alive);
6078 
6079 	if (gIOKitDebug & kIOLogConfig) {
6080 		LOG("config(%p): terminating\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
6081 	}
6082 
6083 	self->release();
6084 }
6085 
6086 IOReturn
waitMatchIdle(UInt32 msToWait)6087 IOService::waitMatchIdle( UInt32 msToWait )
6088 {
6089 	bool            wait;
6090 	int             waitResult = THREAD_AWAKENED;
6091 	bool            computeDeadline = true;
6092 	AbsoluteTime    deadline;
6093 
6094 	IOLockLock( gJobsLock );
6095 	do {
6096 		wait = (0 != gNumConfigThreads);
6097 		if (wait) {
6098 			if (msToWait) {
6099 				if (computeDeadline) {
6100 					clock_interval_to_deadline(
6101 						msToWait, kMillisecondScale, &deadline );
6102 					computeDeadline = false;
6103 				}
6104 				waitResult = IOLockSleepDeadline( gJobsLock, &gNumConfigThreads,
6105 				    deadline, THREAD_UNINT );
6106 			} else {
6107 				waitResult = IOLockSleep( gJobsLock, &gNumConfigThreads,
6108 				    THREAD_UNINT );
6109 			}
6110 		}
6111 	} while (wait && (waitResult != THREAD_TIMED_OUT));
6112 	IOLockUnlock( gJobsLock );
6113 
6114 	if (waitResult == THREAD_TIMED_OUT) {
6115 		return kIOReturnTimeout;
6116 	} else {
6117 		return kIOReturnSuccess;
6118 	}
6119 }
6120 
6121 void
cpusRunning(void)6122 IOService::cpusRunning(void)
6123 {
6124 	gCPUsRunning = true;
6125 }
6126 
6127 void
pingConfig(_IOServiceJob * job)6128 _IOServiceJob::pingConfig( _IOServiceJob * job )
6129 {
6130 	int         count;
6131 	bool        create;
6132 	IOService * nub;
6133 
6134 	assert( job );
6135 	nub = job->nub;
6136 
6137 	IOTakeLock( gJobsLock );
6138 
6139 	gOutstandingJobs++;
6140 	if (nub == gIOResources) {
6141 		gJobs->setFirstObject( job );
6142 	} else {
6143 		gJobs->setLastObject( job );
6144 	}
6145 
6146 	count = gNumWaitingThreads;
6147 //    if( gNumConfigThreads) count++;// assume we're called from a config thread
6148 
6149 	create = ((gOutstandingJobs > count)
6150 	    && ((gNumConfigThreads < gMaxConfigThreads)
6151 	    || (nub == gIOResources)
6152 	    || !gCPUsRunning));
6153 	if (create) {
6154 		gNumConfigThreads++;
6155 		gNumWaitingThreads++;
6156 		if (gNumConfigThreads > gHighNumConfigThreads) {
6157 			gHighNumConfigThreads = gNumConfigThreads;
6158 		}
6159 	}
6160 
6161 	IOUnlock( gJobsLock );
6162 
6163 	job->release();
6164 
6165 	if (create) {
6166 		if (gIOKitDebug & kIOLogConfig) {
6167 			LOG("config(%d): creating\n", gNumConfigThreads - 1);
6168 		}
6169 		_IOConfigThread::configThread(nub->getName());
6170 	}
6171 
6172 	semaphore_signal( gJobsSemaphore );
6173 }
6174 
6175 struct IOServiceMatchContext {
6176 	OSDictionary * table;
6177 	OSObject *     result;
6178 	uint32_t       options;
6179 	uint32_t       state;
6180 	uint32_t       count;
6181 	uint32_t       done;
6182 };
6183 
6184 bool
instanceMatch(const OSObject * entry,void * context)6185 IOService::instanceMatch(const OSObject * entry, void * context)
6186 {
6187 	IOServiceMatchContext * ctx = (typeof(ctx))context;
6188 	IOService *    service = (typeof(service))entry;
6189 	OSDictionary * table   = ctx->table;
6190 	uint32_t       options = ctx->options;
6191 	uint32_t       state   = ctx->state;
6192 	uint32_t       done;
6193 	bool           match;
6194 
6195 	done = 0;
6196 	do{
6197 		match = ((state == (state & service->__state[0]))
6198 		    && (0 == (service->__state[0] & kIOServiceInactiveState)));
6199 		if (!match) {
6200 			break;
6201 		}
6202 
6203 		match = service->matchInternal(table, options, &done);
6204 		if (match) {
6205 			ctx->count += table->getCount();
6206 			ctx->done += done;
6207 		}
6208 	}while (false);
6209 	if (!match) {
6210 		return false;
6211 	}
6212 
6213 	if ((kIONotifyOnce & options) && (ctx->done == ctx->count)) {
6214 		service->retain();
6215 		ctx->result = service;
6216 		return true;
6217 	} else if (!ctx->result) {
6218 		ctx->result = OSSet::withObjects((const OSObject **) &service, 1, 1);
6219 	} else {
6220 		((OSSet *)ctx->result)->setObject(service);
6221 	}
6222 	return false;
6223 }
6224 
6225 // internal - call with gNotificationLock
6226 OSObject *
copyExistingServices(OSDictionary * matching,IOOptionBits inState,IOOptionBits options)6227 IOService::copyExistingServices( OSDictionary * matching,
6228     IOOptionBits inState, IOOptionBits options )
6229 {
6230 	OSObject *   current = NULL;
6231 	OSIterator * iter;
6232 	IOService *  service;
6233 	OSObject *   obj;
6234 	OSString *   str;
6235 
6236 	if (!matching) {
6237 		return NULL;
6238 	}
6239 
6240 #if MATCH_DEBUG
6241 	OSSerialize * s = OSSerialize::withCapacity(128);
6242 	matching->serialize(s);
6243 #endif
6244 
6245 	if ((obj = matching->getObject(gIOProviderClassKey))
6246 	    && gIOResourcesKey
6247 	    && gIOResourcesKey->isEqualTo(obj)
6248 	    && (service = gIOResources)) {
6249 		if ((inState == (service->__state[0] & inState))
6250 		    && (0 == (service->__state[0] & kIOServiceInactiveState))
6251 		    && service->matchPassive(matching, options)) {
6252 			if (options & kIONotifyOnce) {
6253 				service->retain();
6254 				current = service;
6255 			} else {
6256 				current = OSSet::withObjects((const OSObject **) &service, 1, 1 );
6257 			}
6258 		}
6259 	} else {
6260 		IOServiceMatchContext ctx;
6261 
6262 		options    |= kIOServiceClassDone;
6263 		ctx.table   = matching;
6264 		ctx.state   = inState;
6265 		ctx.count   = 0;
6266 		ctx.done    = 0;
6267 		ctx.options = options;
6268 		ctx.result  = NULL;
6269 
6270 		if ((str = OSDynamicCast(OSString, obj))) {
6271 			const OSSymbol * sym = OSSymbol::withString(str);
6272 			OSMetaClass::applyToInstancesOfClassName(sym, instanceMatch, &ctx);
6273 			sym->release();
6274 		} else {
6275 			IOService::gMetaClass.applyToInstances(instanceMatch, &ctx);
6276 		}
6277 
6278 		if (((!(options & kIONotifyOnce) || !ctx.result))
6279 		    && matching->getObject(gIOCompatibilityMatchKey)) {
6280 			IOServiceCompatibility::gMetaClass.applyToInstances(instanceMatch, &ctx);
6281 		}
6282 
6283 		current = ctx.result;
6284 		options |= kIOServiceInternalDone;
6285 		if (current && (ctx.done != ctx.count)) {
6286 			OSSet * source = OSDynamicCast(OSSet, current);
6287 			current = NULL;
6288 			while ((service = (IOService *) source->getAnyObject())) {
6289 				if (service->matchPassive(matching, options)) {
6290 					if (options & kIONotifyOnce) {
6291 						service->retain();
6292 						current = service;
6293 						break;
6294 					}
6295 					if (current) {
6296 						((OSSet *)current)->setObject( service );
6297 					} else {
6298 						current = OSSet::withObjects(
6299 							(const OSObject **) &service, 1, 1 );
6300 					}
6301 				}
6302 				source->removeObject(service);
6303 			}
6304 			source->release();
6305 		}
6306 	}
6307 
6308 #if MATCH_DEBUG
6309 	{
6310 		OSObject * _current = 0;
6311 
6312 		iter = IORegistryIterator::iterateOver( gIOServicePlane,
6313 		    kIORegistryIterateRecursively );
6314 		if (iter) {
6315 			do {
6316 				iter->reset();
6317 				while ((service = (IOService *) iter->getNextObject())) {
6318 					if ((inState == (service->__state[0] & inState))
6319 					    && (0 == (service->__state[0] & kIOServiceInactiveState))
6320 					    && service->matchPassive(matching, 0)) {
6321 						if (options & kIONotifyOnce) {
6322 							service->retain();
6323 							_current = service;
6324 							break;
6325 						}
6326 						if (_current) {
6327 							((OSSet *)_current)->setObject( service );
6328 						} else {
6329 							_current = OSSet::withObjects(
6330 								(const OSObject **) &service, 1, 1 );
6331 						}
6332 					}
6333 				}
6334 			} while (!service && !iter->isValid());
6335 			iter->release();
6336 		}
6337 
6338 		if (((current != 0) != (_current != 0))
6339 		    || (current && _current && !current->isEqualTo(_current))) {
6340 			OSSerialize * s1 = OSSerialize::withCapacity(128);
6341 			OSSerialize * s2 = OSSerialize::withCapacity(128);
6342 			current->serialize(s1);
6343 			_current->serialize(s2);
6344 			kprintf("**mismatch** %p %p\n%s\n%s\n%s\n", IOSERVICE_OBFUSCATE(current),
6345 			    IOSERVICE_OBFUSCATE(_current), s->text(), s1->text(), s2->text());
6346 			s1->release();
6347 			s2->release();
6348 		}
6349 
6350 		if (_current) {
6351 			_current->release();
6352 		}
6353 	}
6354 
6355 	s->release();
6356 #endif
6357 
6358 	if (current && (0 == (options & (kIONotifyOnce | kIOServiceExistingSet)))) {
6359 		iter = OSCollectionIterator::withCollection((OSSet *)current );
6360 		current->release();
6361 		current = iter;
6362 	}
6363 
6364 	return current;
6365 }
6366 
6367 // public version
6368 OSIterator *
getMatchingServices(OSDictionary * matching)6369 IOService::getMatchingServices( OSDictionary * matching )
6370 {
6371 	OSIterator *        iter;
6372 
6373 	// is a lock even needed?
6374 	LOCKWRITENOTIFY();
6375 
6376 	iter = (OSIterator *) copyExistingServices( matching,
6377 	    kIOServiceMatchedState );
6378 
6379 	UNLOCKNOTIFY();
6380 
6381 	return iter;
6382 }
6383 
6384 IOService *
copyMatchingService(OSDictionary * matching)6385 IOService::copyMatchingService( OSDictionary * matching )
6386 {
6387 	IOService * service;
6388 
6389 	// is a lock even needed?
6390 	LOCKWRITENOTIFY();
6391 
6392 	service = (IOService *) copyExistingServices( matching,
6393 	    kIOServiceMatchedState, kIONotifyOnce );
6394 
6395 	UNLOCKNOTIFY();
6396 
6397 	return service;
6398 }
6399 
6400 struct _IOServiceMatchingNotificationHandlerRef {
6401 	IOServiceNotificationHandler handler;
6402 	void * ref;
6403 };
6404 
6405 static bool
_IOServiceMatchingNotificationHandler(void * target,void * refCon,IOService * newService,IONotifier * notifier)6406 _IOServiceMatchingNotificationHandler( void * target, void * refCon,
6407     IOService * newService,
6408     IONotifier * notifier )
6409 {
6410 	return (*((_IOServiceNotifier *) notifier)->compatHandler)(target, refCon, newService);
6411 }
6412 
6413 // internal - call with gNotificationLock
6414 IONotifier *
setNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority)6415 IOService::setNotification(
6416 	const OSSymbol * type, OSDictionary * matching,
6417 	IOServiceMatchingNotificationHandler handler, void * target, void * ref,
6418 	SInt32 priority )
6419 {
6420 	_IOServiceNotifier * notify = NULL;
6421 	OSOrderedSet *      set;
6422 
6423 	if (!matching) {
6424 		return NULL;
6425 	}
6426 
6427 	notify = new _IOServiceNotifier;
6428 	if (notify && !notify->init()) {
6429 		notify->release();
6430 		notify = NULL;
6431 	}
6432 
6433 	if (notify) {
6434 		notify->handler = handler;
6435 		notify->target = target;
6436 		notify->type = type;
6437 		notify->matching = matching;
6438 		matching->retain();
6439 		if (handler == &_IOServiceMatchingNotificationHandler) {
6440 			notify->compatHandler = ((_IOServiceMatchingNotificationHandlerRef *)ref)->handler;
6441 			notify->ref = ((_IOServiceMatchingNotificationHandlerRef *)ref)->ref;
6442 		} else if (handler == &IOServiceMatchingNotificationHandlerToBlock) {
6443 			notify->ref = Block_copy(ref);
6444 		} else {
6445 			notify->ref = ref;
6446 		}
6447 		notify->priority = priority;
6448 		notify->state = kIOServiceNotifyEnable;
6449 		queue_init( &notify->handlerInvocations );
6450 
6451 		////// queue
6452 
6453 		if (NULL == (set = (OSOrderedSet *) gNotifications->getObject( type ))) {
6454 			set = OSOrderedSet::withCapacity( 1,
6455 			    IONotifyOrdering, NULL );
6456 			if (set) {
6457 				gNotifications->setObject( type, set );
6458 				set->release();
6459 			}
6460 		}
6461 		notify->whence = set;
6462 		if (set) {
6463 			set->setObject( notify );
6464 		}
6465 	}
6466 
6467 	return notify;
6468 }
6469 
6470 // internal - call with gNotificationLock
6471 IONotifier *
doInstallNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority,OSIterator ** existing)6472 IOService::doInstallNotification(
6473 	const OSSymbol * type, OSDictionary * matching,
6474 	IOServiceMatchingNotificationHandler handler,
6475 	void * target, void * ref,
6476 	SInt32 priority, OSIterator ** existing )
6477 {
6478 	OSIterator *        exist;
6479 	IONotifier *        notify;
6480 	IOOptionBits        inState;
6481 
6482 	if (!matching) {
6483 		return NULL;
6484 	}
6485 
6486 	if (type == gIOPublishNotification) {
6487 		inState = kIOServiceRegisteredState;
6488 	} else if (type == gIOFirstPublishNotification) {
6489 		inState = kIOServiceFirstPublishState;
6490 	} else if (type == gIOMatchedNotification) {
6491 		inState = kIOServiceMatchedState;
6492 	} else if (type == gIOFirstMatchNotification) {
6493 		inState = kIOServiceFirstMatchState;
6494 	} else if ((type == gIOTerminatedNotification) || (type == gIOWillTerminateNotification)) {
6495 		inState = 0;
6496 	} else {
6497 		return NULL;
6498 	}
6499 
6500 	notify = setNotification( type, matching, handler, target, ref, priority );
6501 
6502 	if (inState) {
6503 		// get the current set
6504 		exist = (OSIterator *) copyExistingServices( matching, inState );
6505 	} else {
6506 		exist = NULL;
6507 	}
6508 
6509 	*existing = exist;
6510 
6511 	return notify;
6512 }
6513 
6514 #if !defined(__LP64__)
6515 IONotifier *
installNotification(const OSSymbol * type,OSDictionary * matching,IOServiceNotificationHandler handler,void * target,void * refCon,SInt32 priority,OSIterator ** existing)6516 IOService::installNotification(const OSSymbol * type, OSDictionary * matching,
6517     IOServiceNotificationHandler handler,
6518     void * target, void * refCon,
6519     SInt32 priority, OSIterator ** existing )
6520 {
6521 	IONotifier * result;
6522 	_IOServiceMatchingNotificationHandlerRef ref;
6523 	ref.handler = handler;
6524 	ref.ref     = refCon;
6525 
6526 	result = (_IOServiceNotifier *) installNotification( type, matching,
6527 	    &_IOServiceMatchingNotificationHandler,
6528 	    target, &ref, priority, existing );
6529 	if (result) {
6530 		matching->release();
6531 	}
6532 
6533 	return result;
6534 }
6535 
6536 #endif /* !defined(__LP64__) */
6537 
6538 
6539 IONotifier *
installNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority,OSIterator ** existing)6540 IOService::installNotification(
6541 	const OSSymbol * type, OSDictionary * matching,
6542 	IOServiceMatchingNotificationHandler handler,
6543 	void * target, void * ref,
6544 	SInt32 priority, OSIterator ** existing )
6545 {
6546 	IONotifier * notify;
6547 
6548 	LOCKWRITENOTIFY();
6549 
6550 	notify = doInstallNotification( type, matching, handler, target, ref,
6551 	    priority, existing );
6552 
6553 	// in case handler remove()s
6554 	if (notify) {
6555 		notify->retain();
6556 	}
6557 
6558 	UNLOCKNOTIFY();
6559 
6560 	return notify;
6561 }
6562 
6563 IONotifier *
addNotification(const OSSymbol * type,OSDictionary * matching,IOServiceNotificationHandler handler,void * target,void * refCon,SInt32 priority)6564 IOService::addNotification(
6565 	const OSSymbol * type, OSDictionary * matching,
6566 	IOServiceNotificationHandler handler,
6567 	void * target, void * refCon,
6568 	SInt32 priority )
6569 {
6570 	IONotifier * result;
6571 	_IOServiceMatchingNotificationHandlerRef ref;
6572 
6573 	ref.handler = handler;
6574 	ref.ref     = refCon;
6575 
6576 	result = addMatchingNotification(type, matching, &_IOServiceMatchingNotificationHandler,
6577 	    target, &ref, priority);
6578 
6579 	if (result) {
6580 		matching->release();
6581 	}
6582 
6583 	return result;
6584 }
6585 
6586 IONotifier *
addMatchingNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority)6587 IOService::addMatchingNotification(
6588 	const OSSymbol * type, OSDictionary * matching,
6589 	IOServiceMatchingNotificationHandler handler,
6590 	void * target, void * ref,
6591 	SInt32 priority )
6592 {
6593 	OSIterator *                existing = NULL;
6594 	IONotifier *                ret;
6595 	_IOServiceNotifier *        notify;
6596 	IOService *                 next;
6597 
6598 	ret = notify = (_IOServiceNotifier *) installNotification( type, matching,
6599 	    handler, target, ref, priority, &existing );
6600 	if (!ret) {
6601 		OSSafeReleaseNULL(existing);
6602 		return NULL;
6603 	}
6604 
6605 	// send notifications for existing set
6606 	if (existing) {
6607 		while ((next = (IOService *) existing->getNextObject())) {
6608 			if (0 == (next->__state[0] & kIOServiceInactiveState)) {
6609 				next->invokeNotifier( notify );
6610 			}
6611 		}
6612 		existing->release();
6613 	}
6614 
6615 	LOCKWRITENOTIFY();
6616 	bool removed = (NULL == notify->whence);
6617 	notify->release();
6618 	if (removed) {
6619 		ret = gIOServiceNullNotifier;
6620 	}
6621 	UNLOCKNOTIFY();
6622 
6623 	return ret;
6624 }
6625 
6626 static bool
IOServiceMatchingNotificationHandlerToBlock(void * target __unused,void * refCon,IOService * newService,IONotifier * notifier)6627 IOServiceMatchingNotificationHandlerToBlock( void * target __unused, void * refCon,
6628     IOService * newService,
6629     IONotifier * notifier )
6630 {
6631 	return ((IOServiceMatchingNotificationHandlerBlock) refCon)(newService, notifier);
6632 }
6633 
6634 IONotifier *
addMatchingNotification(const OSSymbol * type,OSDictionary * matching,SInt32 priority,IOServiceMatchingNotificationHandlerBlock handler)6635 IOService::addMatchingNotification(
6636 	const OSSymbol * type, OSDictionary * matching,
6637 	SInt32 priority,
6638 	IOServiceMatchingNotificationHandlerBlock handler)
6639 {
6640 	IONotifier * notify;
6641 
6642 	notify = addMatchingNotification(type, matching,
6643 	    &IOServiceMatchingNotificationHandlerToBlock, NULL, handler, priority);
6644 	return notify;
6645 }
6646 
6647 struct IOUserServerCancellationHandlerArgs {
6648 	IOService ** ref;
6649 	bool canceled;
6650 };
6651 
6652 void
userServerCheckInTokenCancellationHandler(__unused IOUserServerCheckInToken * token,void * ref)6653 IOService::userServerCheckInTokenCancellationHandler(
6654 	__unused IOUserServerCheckInToken *token,
6655 	void *ref)
6656 {
6657 	IOUserServerCancellationHandlerArgs * args = (typeof(args))ref;
6658 	LOCKWRITENOTIFY();
6659 	WAKEUPNOTIFY(args->ref);
6660 	args->canceled = true;
6661 	UNLOCKNOTIFY();
6662 }
6663 
6664 bool
syncNotificationHandler(void *,void * ref,IOService * newService,IONotifier * notifier)6665 IOService::syncNotificationHandler(
6666 	void * /* target */, void * ref,
6667 	IOService * newService,
6668 	IONotifier * notifier )
6669 {
6670 	LOCKWRITENOTIFY();
6671 	if (!*((IOService **) ref)) {
6672 		newService->retain();
6673 		(*(IOService **) ref) = newService;
6674 		WAKEUPNOTIFY(ref);
6675 	}
6676 	UNLOCKNOTIFY();
6677 
6678 	return false;
6679 }
6680 
6681 IOService *
waitForMatchingServiceWithToken(OSDictionary * matching,uint64_t timeout,IOUserServerCheckInToken * checkInToken)6682 IOService::waitForMatchingServiceWithToken( OSDictionary * matching,
6683     uint64_t timeout,
6684     IOUserServerCheckInToken * checkInToken)
6685 {
6686 	IONotifier *        notify = NULL;
6687 	// priority doesn't help us much since we need a thread wakeup
6688 	SInt32              priority = 0;
6689 	IOService *         result;
6690 	IOUserServerCancellationHandlerArgs cancelArgs;
6691 	_IOUserServerCheckInCancellationHandler * cancellationHandler = NULL;
6692 
6693 	if (!matching) {
6694 		return NULL;
6695 	}
6696 
6697 	result = NULL;
6698 	cancelArgs.ref = &result;
6699 	cancelArgs.canceled = false;
6700 
6701 #if DEBUG || DEVELOPMENT
6702 	char                currentName[MAXTHREADNAMESIZE];
6703 	char                newName[MAXTHREADNAMESIZE];
6704 	OSObject          * obj;
6705 	OSString          * str;
6706 	OSDictionary      * dict;
6707 
6708 	currentName[0] = '\0';
6709 	if (thread_has_thread_name(current_thread())) {
6710 		dict = matching;
6711 		obj = matching->getObject(gIOPropertyMatchKey);
6712 		if ((dict = OSDynamicCast(OSDictionary, obj))) {
6713 			OSObject * result __block = NULL;
6714 			dict->iterateObjects(^bool (const OSSymbol * sym, OSObject * value) {
6715 				result = __DECONST(OSObject *, sym);
6716 				return true;
6717 			});
6718 			obj = result;
6719 		}
6720 		if (!obj) {
6721 			obj = matching->getObject(gIOResourceMatchKey);
6722 		}
6723 		if (!obj) {
6724 			obj = matching->getObject(gIONameMatchKey);
6725 		}
6726 		if (!obj) {
6727 			obj = matching->getObject(gIOProviderClassKey);
6728 		}
6729 		if ((str = OSDynamicCast(OSString, obj))) {
6730 			thread_get_thread_name(current_thread(), currentName);
6731 			snprintf(newName, sizeof(newName), "Waiting_'%s'", str->getCStringNoCopy());
6732 			thread_set_thread_name(current_thread(), newName);
6733 		}
6734 	}
6735 #endif /* DEBUG || DEVELOPMENT */
6736 
6737 	if (checkInToken) {
6738 		cancellationHandler = checkInToken->setCancellationHandler(&IOService::userServerCheckInTokenCancellationHandler,
6739 		    &cancelArgs);
6740 	}
6741 
6742 	LOCKWRITENOTIFY();
6743 	do{
6744 		if (cancelArgs.canceled) {
6745 			// token was already canceled, no need to wait or find services
6746 			break;
6747 		}
6748 		result = (IOService *) copyExistingServices( matching,
6749 		    kIOServiceMatchedState, kIONotifyOnce );
6750 		if (result) {
6751 			break;
6752 		}
6753 		notify = IOService::setNotification( gIOMatchedNotification, matching,
6754 		    &IOService::syncNotificationHandler, (void *) NULL,
6755 		    &result, priority );
6756 		if (!notify) {
6757 			break;
6758 		}
6759 		if (UINT64_MAX != timeout) {
6760 			AbsoluteTime deadline;
6761 			nanoseconds_to_absolutetime(timeout, &deadline);
6762 			clock_absolutetime_interval_to_deadline(deadline, &deadline);
6763 			SLEEPNOTIFYTO(&result, deadline);
6764 		} else {
6765 			SLEEPNOTIFY(&result);
6766 		}
6767 	}while (false);
6768 
6769 	UNLOCKNOTIFY();
6770 
6771 	if (checkInToken && cancellationHandler) {
6772 		checkInToken->removeCancellationHandler(cancellationHandler);
6773 	}
6774 
6775 #if DEBUG || DEVELOPMENT
6776 	if (currentName[0]) {
6777 		thread_set_thread_name(current_thread(), currentName);
6778 	}
6779 #endif /* DEBUG || DEVELOPMENT */
6780 
6781 	if (notify) {
6782 		notify->remove(); // dequeues
6783 	}
6784 
6785 	OSSafeReleaseNULL(cancellationHandler);
6786 
6787 	return result;
6788 }
6789 
6790 IOService *
waitForMatchingService(OSDictionary * matching,uint64_t timeout)6791 IOService::waitForMatchingService( OSDictionary * matching,
6792     uint64_t timeout)
6793 {
6794 	return IOService::waitForMatchingServiceWithToken(matching, timeout, NULL);
6795 }
6796 
6797 IOService *
waitForService(OSDictionary * matching,mach_timespec_t * timeout)6798 IOService::waitForService( OSDictionary * matching,
6799     mach_timespec_t * timeout )
6800 {
6801 	IOService * result;
6802 	uint64_t    timeoutNS;
6803 
6804 	if (timeout) {
6805 		timeoutNS = timeout->tv_sec;
6806 		timeoutNS *= kSecondScale;
6807 		timeoutNS += timeout->tv_nsec;
6808 	} else {
6809 		timeoutNS = UINT64_MAX;
6810 	}
6811 
6812 	result = waitForMatchingService(matching, timeoutNS);
6813 
6814 	matching->release();
6815 	if (result) {
6816 		result->release();
6817 	}
6818 
6819 	return result;
6820 }
6821 
6822 __dead2
6823 void
deliverNotification(const OSSymbol * type,IOOptionBits orNewState,IOOptionBits andNewState)6824 IOService::deliverNotification( const OSSymbol * type,
6825     IOOptionBits orNewState, IOOptionBits andNewState )
6826 {
6827 	panic("deliverNotification");
6828 }
6829 
6830 OSArray *
copyNotifiers(const OSSymbol * type,IOOptionBits orNewState,IOOptionBits andNewState)6831 IOService::copyNotifiers(const OSSymbol * type,
6832     IOOptionBits orNewState, IOOptionBits andNewState )
6833 {
6834 	_IOServiceNotifier * notify;
6835 	OSIterator *         iter;
6836 	OSArray *            willSend = NULL;
6837 
6838 	lockForArbitration();
6839 
6840 	if ((0 == (__state[0] & kIOServiceInactiveState))
6841 	    || (type == gIOTerminatedNotification)
6842 	    || (type == gIOWillTerminateNotification)) {
6843 		LOCKREADNOTIFY();
6844 
6845 		iter = OSCollectionIterator::withCollection((OSOrderedSet *)
6846 		    gNotifications->getObject( type ));
6847 
6848 		if (iter) {
6849 			while ((notify = (_IOServiceNotifier *) iter->getNextObject())) {
6850 				if (matchPassive(notify->matching, 0)
6851 				    && (kIOServiceNotifyEnable & notify->state)) {
6852 					if (NULL == willSend) {
6853 						willSend = OSArray::withCapacity(8);
6854 					}
6855 					if (willSend) {
6856 						willSend->setObject( notify );
6857 					}
6858 				}
6859 			}
6860 			iter->release();
6861 		}
6862 		__state[0] = (__state[0] | orNewState) & andNewState;
6863 		UNLOCKNOTIFY();
6864 	}
6865 
6866 	unlockForArbitration();
6867 
6868 	return willSend;
6869 }
6870 
6871 IOOptionBits
getState(void) const6872 IOService::getState( void ) const
6873 {
6874 	return __state[0];
6875 }
6876 
6877 /*
6878  * Helpers to make matching objects for simple cases
6879  */
6880 
6881 OSDictionary *
serviceMatching(const OSString * name,OSDictionary * table)6882 IOService::serviceMatching( const OSString * name,
6883     OSDictionary * table )
6884 {
6885 	const OSString *    str;
6886 
6887 	str = OSSymbol::withString(name);
6888 	if (!str) {
6889 		return NULL;
6890 	}
6891 
6892 	if (!table) {
6893 		table = OSDictionary::withCapacity( 2 );
6894 	}
6895 	if (table) {
6896 		table->setObject(gIOProviderClassKey, (OSObject *)str );
6897 	}
6898 	str->release();
6899 
6900 	return table;
6901 }
6902 
6903 
6904 OSSharedPtr<OSDictionary>
serviceMatching(const OSString * name,OSSharedPtr<OSDictionary> table)6905 IOService::serviceMatching( const OSString * name,
6906     OSSharedPtr<OSDictionary> table)
6907 {
6908 	OSDictionary * result = serviceMatching(name, table.get());
6909 	if (table) {
6910 		return OSSharedPtr<OSDictionary>(result, OSRetain);
6911 	} else {
6912 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
6913 	}
6914 }
6915 
6916 
6917 OSDictionary *
serviceMatching(const char * name,OSDictionary * table)6918 IOService::serviceMatching( const char * name,
6919     OSDictionary * table )
6920 {
6921 	const OSString *    str;
6922 
6923 	str = OSSymbol::withCString( name );
6924 	if (!str) {
6925 		return NULL;
6926 	}
6927 
6928 	table = serviceMatching( str, table );
6929 	str->release();
6930 	return table;
6931 }
6932 
6933 
6934 OSSharedPtr<OSDictionary>
serviceMatching(const char * className,OSSharedPtr<OSDictionary> table)6935 IOService::serviceMatching( const char * className,
6936     OSSharedPtr<OSDictionary> table)
6937 {
6938 	OSDictionary * result = serviceMatching(className, table.get());
6939 	if (table) {
6940 		return OSSharedPtr<OSDictionary>(result, OSRetain);
6941 	} else {
6942 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
6943 	}
6944 }
6945 
6946 
6947 OSDictionary *
nameMatching(const OSString * name,OSDictionary * table)6948 IOService::nameMatching( const OSString * name,
6949     OSDictionary * table )
6950 {
6951 	if (!table) {
6952 		table = OSDictionary::withCapacity( 2 );
6953 	}
6954 	if (table) {
6955 		table->setObject( gIONameMatchKey, (OSObject *)name );
6956 	}
6957 
6958 	return table;
6959 }
6960 
6961 
6962 OSSharedPtr<OSDictionary>
nameMatching(const OSString * name,OSSharedPtr<OSDictionary> table)6963 IOService::nameMatching( const OSString * name,
6964     OSSharedPtr<OSDictionary> table)
6965 {
6966 	OSDictionary * result = nameMatching(name, table.get());
6967 	if (table) {
6968 		return OSSharedPtr<OSDictionary>(result, OSRetain);
6969 	} else {
6970 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
6971 	}
6972 }
6973 
6974 
6975 OSDictionary *
nameMatching(const char * name,OSDictionary * table)6976 IOService::nameMatching( const char * name,
6977     OSDictionary * table )
6978 {
6979 	const OSString *    str;
6980 
6981 	str = OSSymbol::withCString( name );
6982 	if (!str) {
6983 		return NULL;
6984 	}
6985 
6986 	table = nameMatching( str, table );
6987 	str->release();
6988 	return table;
6989 }
6990 
6991 
6992 OSSharedPtr<OSDictionary>
nameMatching(const char * name,OSSharedPtr<OSDictionary> table)6993 IOService::nameMatching( const char * name,
6994     OSSharedPtr<OSDictionary> table)
6995 {
6996 	OSDictionary * result = nameMatching(name, table.get());
6997 	if (table) {
6998 		return OSSharedPtr<OSDictionary>(result, OSRetain);
6999 	} else {
7000 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7001 	}
7002 }
7003 
7004 
7005 OSDictionary *
resourceMatching(const OSString * str,OSDictionary * table)7006 IOService::resourceMatching( const OSString * str,
7007     OSDictionary * table )
7008 {
7009 	table = serviceMatching( gIOResourcesKey, table );
7010 	if (table) {
7011 		table->setObject( gIOResourceMatchKey, (OSObject *) str );
7012 	}
7013 
7014 	return table;
7015 }
7016 
7017 
7018 OSSharedPtr<OSDictionary>
resourceMatching(const OSString * str,OSSharedPtr<OSDictionary> table)7019 IOService::resourceMatching( const OSString * str,
7020     OSSharedPtr<OSDictionary> table)
7021 {
7022 	OSDictionary * result = resourceMatching(str, table.get());
7023 	if (table) {
7024 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7025 	} else {
7026 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7027 	}
7028 }
7029 
7030 
7031 OSDictionary *
resourceMatching(const char * name,OSDictionary * table)7032 IOService::resourceMatching( const char * name,
7033     OSDictionary * table )
7034 {
7035 	const OSSymbol *    str;
7036 
7037 	str = OSSymbol::withCString( name );
7038 	if (!str) {
7039 		return NULL;
7040 	}
7041 
7042 	table = resourceMatching( str, table );
7043 	str->release();
7044 
7045 	return table;
7046 }
7047 
7048 
7049 OSSharedPtr<OSDictionary>
resourceMatching(const char * name,OSSharedPtr<OSDictionary> table)7050 IOService::resourceMatching( const char * name,
7051     OSSharedPtr<OSDictionary> table)
7052 {
7053 	OSDictionary * result = resourceMatching(name, table.get());
7054 	if (table) {
7055 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7056 	} else {
7057 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7058 	}
7059 }
7060 
7061 
7062 OSDictionary *
propertyMatching(const OSSymbol * key,const OSObject * value,OSDictionary * table)7063 IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
7064     OSDictionary * table )
7065 {
7066 	OSDictionary * properties;
7067 
7068 	properties = OSDictionary::withCapacity( 2 );
7069 	if (!properties) {
7070 		return NULL;
7071 	}
7072 	properties->setObject( key, value );
7073 
7074 	if (!table) {
7075 		table = OSDictionary::withCapacity( 2 );
7076 	}
7077 	if (table) {
7078 		table->setObject( gIOPropertyMatchKey, properties );
7079 	}
7080 
7081 	properties->release();
7082 
7083 	return table;
7084 }
7085 
7086 
7087 OSSharedPtr<OSDictionary>
propertyMatching(const OSSymbol * key,const OSObject * value,OSSharedPtr<OSDictionary> table)7088 IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
7089     OSSharedPtr<OSDictionary> table)
7090 {
7091 	OSDictionary * result = propertyMatching(key, value, table.get());
7092 	if (table) {
7093 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7094 	} else {
7095 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7096 	}
7097 }
7098 
7099 
7100 OSDictionary *
registryEntryIDMatching(uint64_t entryID,OSDictionary * table)7101 IOService::registryEntryIDMatching( uint64_t entryID,
7102     OSDictionary * table )
7103 {
7104 	OSNumber *     num;
7105 
7106 	num = OSNumber::withNumber( entryID, 64 );
7107 	if (!num) {
7108 		return NULL;
7109 	}
7110 
7111 	if (!table) {
7112 		table = OSDictionary::withCapacity( 2 );
7113 	}
7114 	if (table) {
7115 		table->setObject( gIORegistryEntryIDKey, num );
7116 	}
7117 
7118 	if (num) {
7119 		num->release();
7120 	}
7121 
7122 	return table;
7123 }
7124 
7125 
7126 OSSharedPtr<OSDictionary>
registryEntryIDMatching(uint64_t entryID,OSSharedPtr<OSDictionary> table)7127 IOService::registryEntryIDMatching( uint64_t entryID,
7128     OSSharedPtr<OSDictionary> table)
7129 {
7130 	OSDictionary * result = registryEntryIDMatching(entryID, table.get());
7131 	if (table) {
7132 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7133 	} else {
7134 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7135 	}
7136 }
7137 
7138 
7139 
7140 /*
7141  * _IOServiceNotifier
7142  */
7143 
7144 // wait for all threads, other than the current one,
7145 //  to exit the handler
7146 
7147 void
wait()7148 _IOServiceNotifier::wait()
7149 {
7150 	_IOServiceNotifierInvocation * next;
7151 	bool doWait;
7152 
7153 	do {
7154 		doWait = false;
7155 		queue_iterate( &handlerInvocations, next,
7156 		    _IOServiceNotifierInvocation *, link) {
7157 			if (next->thread != current_thread()) {
7158 				doWait = true;
7159 				break;
7160 			}
7161 		}
7162 		if (doWait) {
7163 			state |= kIOServiceNotifyWaiter;
7164 			SLEEPNOTIFY(this);
7165 		}
7166 	} while (doWait);
7167 }
7168 
7169 void
free()7170 _IOServiceNotifier::free()
7171 {
7172 	assert( queue_empty( &handlerInvocations ));
7173 
7174 	if (handler == &IOServiceMatchingNotificationHandlerToBlock) {
7175 		Block_release(ref);
7176 	}
7177 
7178 	OSObject::free();
7179 }
7180 
7181 void
remove()7182 _IOServiceNotifier::remove()
7183 {
7184 	LOCKWRITENOTIFY();
7185 
7186 	if (whence) {
7187 		whence->removeObject((OSObject *) this );
7188 		whence = NULL;
7189 	}
7190 	if (matching) {
7191 		matching->release();
7192 		matching = NULL;
7193 	}
7194 
7195 	state &= ~kIOServiceNotifyEnable;
7196 
7197 	wait();
7198 
7199 	UNLOCKNOTIFY();
7200 
7201 	release();
7202 }
7203 
7204 bool
disable()7205 _IOServiceNotifier::disable()
7206 {
7207 	bool        ret;
7208 
7209 	LOCKWRITENOTIFY();
7210 
7211 	ret = (0 != (kIOServiceNotifyEnable & state));
7212 	state &= ~kIOServiceNotifyEnable;
7213 	if (ret) {
7214 		wait();
7215 	}
7216 
7217 	UNLOCKNOTIFY();
7218 
7219 	return ret;
7220 }
7221 
7222 void
enable(bool was)7223 _IOServiceNotifier::enable( bool was )
7224 {
7225 	LOCKWRITENOTIFY();
7226 	if (was) {
7227 		state |= kIOServiceNotifyEnable;
7228 	} else {
7229 		state &= ~kIOServiceNotifyEnable;
7230 	}
7231 	UNLOCKNOTIFY();
7232 }
7233 
7234 
7235 /*
7236  * _IOServiceNullNotifier
7237  */
7238 
7239 void
taggedRetain(const void * tag) const7240 _IOServiceNullNotifier::taggedRetain(const void *tag) const
7241 {
7242 }
7243 void
taggedRelease(const void * tag,const int when) const7244 _IOServiceNullNotifier::taggedRelease(const void *tag, const int when) const
7245 {
7246 }
7247 void
free()7248 _IOServiceNullNotifier::free()
7249 {
7250 }
7251 void
wait()7252 _IOServiceNullNotifier::wait()
7253 {
7254 }
7255 void
remove()7256 _IOServiceNullNotifier::remove()
7257 {
7258 }
7259 void
enable(bool was)7260 _IOServiceNullNotifier::enable(bool was)
7261 {
7262 }
7263 bool
disable()7264 _IOServiceNullNotifier::disable()
7265 {
7266 	return false;
7267 }
7268 
7269 /*
7270  * IOResources
7271  */
7272 
7273 IOService *
resources(void)7274 IOResources::resources( void )
7275 {
7276 	IOResources *       inst;
7277 
7278 	inst = new IOResources;
7279 	if (inst && !inst->init()) {
7280 		inst->release();
7281 		inst = NULL;
7282 	}
7283 
7284 	return inst;
7285 }
7286 
7287 bool
init(OSDictionary * dictionary)7288 IOResources::init( OSDictionary * dictionary )
7289 {
7290 	// Do super init first
7291 	if (!IOService::init()) {
7292 		return false;
7293 	}
7294 
7295 	// Allow PAL layer to publish a value
7296 	const char *property_name;
7297 	int property_value;
7298 
7299 	pal_get_resource_property( &property_name, &property_value );
7300 
7301 	if (property_name) {
7302 		OSNumber *num;
7303 		const OSSymbol *        sym;
7304 
7305 		if ((num = OSNumber::withNumber(property_value, 32)) != NULL) {
7306 			if ((sym = OSSymbol::withCString( property_name)) != NULL) {
7307 				this->setProperty( sym, num );
7308 				sym->release();
7309 			}
7310 			num->release();
7311 		}
7312 	}
7313 
7314 	return true;
7315 }
7316 
7317 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,IOUserClient ** handler)7318 IOResources::newUserClient(task_t owningTask, void * securityID,
7319     UInt32 type, OSDictionary * properties,
7320     IOUserClient ** handler)
7321 {
7322 	return kIOReturnUnsupported;
7323 }
7324 
7325 IOWorkLoop *
getWorkLoop() const7326 IOResources::getWorkLoop() const
7327 {
7328 	// If we are the resource root
7329 	// then use the platform's workloop
7330 	if (this == (IOResources *) gIOResources) {
7331 		return getPlatform()->getWorkLoop();
7332 	} else {
7333 		return IOService::getWorkLoop();
7334 	}
7335 }
7336 
7337 static bool
IOResourcesMatchPropertyTable(IOService * resources,OSDictionary * table)7338 IOResourcesMatchPropertyTable(IOService * resources, OSDictionary * table)
7339 {
7340 	OSObject *          prop;
7341 	bool __block        ok = true;
7342 
7343 	prop = table->getObject( gIOResourceMatchKey );
7344 	if (prop) {
7345 		prop->iterateObjects(^bool (OSObject * obj)
7346 		{
7347 			OSString *
7348 			str = OSDynamicCast(OSString, obj);
7349 			ok = (NULL != resources->getProperty(str));
7350 			return !ok;
7351 		});
7352 	} else if ((prop = table->getObject(gIOResourceMatchedKey))) {
7353 		OSObject * obj;
7354 		OSArray *  keys;
7355 
7356 		obj = resources->copyProperty(gIOResourceMatchedKey);
7357 		keys = OSDynamicCast(OSArray, obj);
7358 		ok = false;
7359 		if (keys) {
7360 			// assuming OSSymbol
7361 			ok = ((-1U) != keys->getNextIndexOfObject(prop, 0));
7362 		}
7363 		OSSafeReleaseNULL(obj);
7364 	}
7365 
7366 	return ok;
7367 }
7368 
7369 bool
matchPropertyTable(OSDictionary * table)7370 IOResources::matchPropertyTable( OSDictionary * table )
7371 {
7372 	return IOResourcesMatchPropertyTable(this, table);
7373 }
7374 
7375 /*
7376  * IOUserResources
7377  */
7378 
7379 IOService *
resources(void)7380 IOUserResources::resources( void )
7381 {
7382 	IOUserResources *       inst;
7383 
7384 	inst = OSTypeAlloc(IOUserResources);
7385 	if (inst && !inst->init()) {
7386 		inst->release();
7387 		inst = NULL;
7388 	}
7389 
7390 	return inst;
7391 }
7392 
7393 bool
init(OSDictionary * dictionary)7394 IOUserResources::init( OSDictionary * dictionary )
7395 {
7396 	// Do super init first
7397 	if (!IOService::init()) {
7398 		return false;
7399 	}
7400 	return true;
7401 }
7402 
7403 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,IOUserClient ** handler)7404 IOUserResources::newUserClient(task_t owningTask, void * securityID,
7405     UInt32 type, OSDictionary * properties,
7406     IOUserClient ** handler)
7407 {
7408 	return kIOReturnUnsupported;
7409 }
7410 
7411 IOWorkLoop *
getWorkLoop() const7412 IOUserResources::getWorkLoop() const
7413 {
7414 	return getPlatform()->getWorkLoop();
7415 }
7416 
7417 bool
matchPropertyTable(OSDictionary * table)7418 IOUserResources::matchPropertyTable( OSDictionary * table )
7419 {
7420 	return IOResourcesMatchPropertyTable(this, table);
7421 }
7422 
7423 IOReturn
powerStateWillChangeTo(IOPMPowerFlags flags,unsigned long state,IOService * service)7424 IOUserResources::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
7425 {
7426 	assert(service == getPMRootDomain());
7427 	if (service != getPMRootDomain()) {
7428 		return kIOReturnSuccess;
7429 	}
7430 	return IOServicePH::rootWillChangeTo(flags, state);
7431 }
7432 
7433 // --
7434 
7435 void
consoleLockTimer(thread_call_param_t p0,thread_call_param_t p1)7436 IOService::consoleLockTimer(thread_call_param_t p0, thread_call_param_t p1)
7437 {
7438 	IOService::updateConsoleUsers(NULL, 0);
7439 }
7440 
7441 void
updateConsoleUsers(OSArray * consoleUsers,IOMessage systemMessage,bool afterUserspaceReboot)7442 IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessage, bool afterUserspaceReboot)
7443 {
7444 	IORegistryEntry * regEntry;
7445 	OSObject *        locked = kOSBooleanFalse;
7446 	uint32_t          idx;
7447 	bool              publish;
7448 	OSDictionary *    user;
7449 	clock_sec_t       now = 0;
7450 	clock_usec_t      microsecs;
7451 
7452 	regEntry = IORegistryEntry::getRegistryRoot();
7453 
7454 	if (!gIOChosenEntry) {
7455 		gIOChosenEntry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
7456 	}
7457 
7458 	IOLockLock(gIOConsoleUsersLock);
7459 
7460 	if (systemMessage) {
7461 		sSystemPower = systemMessage;
7462 #if HIBERNATION
7463 		if (kIOMessageSystemHasPoweredOn == systemMessage) {
7464 			uint32_t lockState = IOHibernateWasScreenLocked();
7465 			switch (lockState) {
7466 			case 0:
7467 				break;
7468 			case kIOScreenLockLocked:
7469 			case kIOScreenLockFileVaultDialog:
7470 				gIOConsoleBooterLockState = kOSBooleanTrue;
7471 				break;
7472 			case kIOScreenLockNoLock:
7473 				gIOConsoleBooterLockState = NULL;
7474 				break;
7475 			case kIOScreenLockUnlocked:
7476 			default:
7477 				gIOConsoleBooterLockState = kOSBooleanFalse;
7478 				break;
7479 			}
7480 		}
7481 #endif /* HIBERNATION */
7482 	}
7483 
7484 	if (consoleUsers) {
7485 		OSNumber * num = NULL;
7486 		bool       loginLocked = true;
7487 
7488 		gIOConsoleLoggedIn = false;
7489 		for (idx = 0;
7490 		    (user = OSDynamicCast(OSDictionary, consoleUsers->getObject(idx)));
7491 		    idx++) {
7492 			gIOConsoleLoggedIn |= ((kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey))
7493 			    && (kOSBooleanTrue == user->getObject(gIOConsoleSessionLoginDoneKey)));
7494 
7495 			loginLocked &= (kOSBooleanTrue == user->getObject(gIOConsoleSessionScreenIsLockedKey));
7496 			if (!num) {
7497 				num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionScreenLockedTimeKey));
7498 			}
7499 		}
7500 #if HIBERNATION
7501 		if (!loginLocked || afterUserspaceReboot) {
7502 			gIOConsoleBooterLockState = NULL;
7503 		}
7504 		IOLog("IOConsoleUsers: time(%d) %ld->%d, lin %d, llk %d, \n",
7505 		    (num != NULL), gIOConsoleLockTime, (num ? num->unsigned32BitValue() : 0),
7506 		    gIOConsoleLoggedIn, loginLocked);
7507 #endif /* HIBERNATION */
7508 		gIOConsoleLockTime = num ? num->unsigned32BitValue() : 0;
7509 	}
7510 
7511 	if (!gIOConsoleLoggedIn
7512 	    || (kIOMessageSystemWillSleep == sSystemPower)
7513 	    || (kIOMessageSystemPagingOff == sSystemPower)) {
7514 		if (afterUserspaceReboot) {
7515 			// set "locked" to false after a user space reboot
7516 			// because the reboot happens directly after a user
7517 			// logs into the machine via fvunlock mode.
7518 			locked = kOSBooleanFalse;
7519 		} else {
7520 			locked = kOSBooleanTrue;
7521 		}
7522 	}
7523 #if HIBERNATION
7524 	else if (gIOConsoleBooterLockState) {
7525 		locked = gIOConsoleBooterLockState;
7526 	}
7527 #endif /* HIBERNATION */
7528 	else if (gIOConsoleLockTime) {
7529 		clock_get_calendar_microtime(&now, &microsecs);
7530 		if (gIOConsoleLockTime > now) {
7531 			AbsoluteTime deadline;
7532 			clock_sec_t interval;
7533 			uint32_t interval32;
7534 
7535 			interval = (gIOConsoleLockTime - now);
7536 			interval32 = (uint32_t) interval;
7537 			if (interval32 != interval) {
7538 				interval32 = UINT_MAX;
7539 			}
7540 			clock_interval_to_deadline(interval32, kSecondScale, &deadline);
7541 			thread_call_enter_delayed(gIOConsoleLockCallout, deadline);
7542 		} else {
7543 			locked = kOSBooleanTrue;
7544 		}
7545 	}
7546 
7547 	publish = (consoleUsers || (locked != regEntry->getProperty(gIOConsoleLockedKey)));
7548 	if (publish) {
7549 		regEntry->setProperty(gIOConsoleLockedKey, locked);
7550 		if (consoleUsers) {
7551 			regEntry->setProperty(gIOConsoleUsersKey, consoleUsers);
7552 		}
7553 		OSIncrementAtomic( &gIOConsoleUsersSeed );
7554 	}
7555 
7556 #if HIBERNATION
7557 	if (gIOChosenEntry) {
7558 		if (locked == kOSBooleanTrue) {
7559 			gIOScreenLockState = kIOScreenLockLocked;
7560 		} else if (gIOConsoleLockTime) {
7561 			gIOScreenLockState = kIOScreenLockUnlocked;
7562 		} else {
7563 			gIOScreenLockState = kIOScreenLockNoLock;
7564 		}
7565 		gIOChosenEntry->setProperty(kIOScreenLockStateKey, &gIOScreenLockState, sizeof(gIOScreenLockState));
7566 
7567 		IOLog("IOConsoleUsers: gIOScreenLockState %d, hs %d, bs %d, now %ld, sm 0x%x\n",
7568 		    gIOScreenLockState, gIOHibernateState, (gIOConsoleBooterLockState != NULL), now, systemMessage);
7569 	}
7570 #endif /* HIBERNATION */
7571 
7572 	IOLockUnlock(gIOConsoleUsersLock);
7573 
7574 	if (publish) {
7575 		publishResource( gIOConsoleUsersSeedKey, gIOConsoleUsersSeedValue );
7576 
7577 		MessageClientsContext context;
7578 
7579 		context.service  = getServiceRoot();
7580 		context.type     = kIOMessageConsoleSecurityChange;
7581 		context.argument = (void *) regEntry;
7582 		context.argSize  = 0;
7583 
7584 		applyToInterestNotifiers(getServiceRoot(), gIOConsoleSecurityInterest,
7585 		    &messageClientsApplier, &context );
7586 	}
7587 }
7588 
7589 IOReturn
setProperties(OSObject * properties)7590 IOResources::setProperties( OSObject * properties )
7591 {
7592 	IOReturn                    err;
7593 	const OSSymbol *            key;
7594 	OSDictionary *              dict;
7595 	OSCollectionIterator *      iter;
7596 
7597 	if (!IOCurrentTaskHasEntitlement(kIOResourcesSetPropertyKey)) {
7598 		err = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
7599 		if (kIOReturnSuccess != err) {
7600 			return err;
7601 		}
7602 	}
7603 
7604 	dict = OSDynamicCast(OSDictionary, properties);
7605 	if (NULL == dict) {
7606 		return kIOReturnBadArgument;
7607 	}
7608 
7609 	iter = OSCollectionIterator::withCollection( dict);
7610 	if (NULL == iter) {
7611 		return kIOReturnBadArgument;
7612 	}
7613 
7614 	while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
7615 		if (gIOConsoleUsersKey == key) {
7616 			do{
7617 				OSArray * consoleUsers;
7618 				consoleUsers = OSDynamicCast(OSArray, dict->getObject(key));
7619 				if (!consoleUsers) {
7620 					continue;
7621 				}
7622 				IOService::updateConsoleUsers(consoleUsers, 0);
7623 			}while (false);
7624 		}
7625 
7626 		publishResource( key, dict->getObject(key));
7627 	}
7628 
7629 	iter->release();
7630 
7631 	return kIOReturnSuccess;
7632 }
7633 
7634 /*
7635  * Helpers for matching dictionaries.
7636  * Keys existing in matching are checked in properties.
7637  * Keys may be a string or OSCollection of IOStrings
7638  */
7639 
7640 bool
compareProperty(OSDictionary * matching,const char * key)7641 IOService::compareProperty( OSDictionary * matching,
7642     const char *   key )
7643 {
7644 	OSObject *  value;
7645 	OSObject *  prop;
7646 	bool        ok;
7647 
7648 	value = matching->getObject( key );
7649 	if (value) {
7650 		prop = copyProperty(key);
7651 		ok = value->isEqualTo(prop);
7652 		if (prop) {
7653 			prop->release();
7654 		}
7655 	} else {
7656 		ok = true;
7657 	}
7658 
7659 	return ok;
7660 }
7661 
7662 
7663 bool
compareProperty(OSDictionary * matching,const OSString * key)7664 IOService::compareProperty( OSDictionary *   matching,
7665     const OSString * key )
7666 {
7667 	OSObject *  value;
7668 	OSObject *  prop;
7669 	bool        ok;
7670 
7671 	value = matching->getObject( key );
7672 	if (value) {
7673 		prop = copyProperty(key);
7674 		ok = value->isEqualTo(prop);
7675 		if (prop) {
7676 			prop->release();
7677 		}
7678 	} else {
7679 		ok = true;
7680 	}
7681 
7682 	return ok;
7683 }
7684 
7685 #ifndef __clang_analyzer__
7686 // Implementation of this function is hidden from the static analyzer.
7687 // The analyzer was worried about this function's confusing contract over
7688 // the 'keys' parameter. The contract is to either release it or not release it
7689 // depending on whether 'matching' is non-null. Such contracts are discouraged
7690 // but changing it now would break compatibility.
7691 bool
compareProperties(OSDictionary * matching,OSCollection * keys)7692 IOService::compareProperties( OSDictionary * matching,
7693     OSCollection * keys )
7694 {
7695 	OSCollectionIterator *      iter;
7696 	const OSString *            key;
7697 	bool                        ok = true;
7698 
7699 	if (!matching || !keys) {
7700 		return false;
7701 	}
7702 
7703 	iter = OSCollectionIterator::withCollection( keys );
7704 
7705 	if (iter) {
7706 		while (ok && (key = OSDynamicCast( OSString, iter->getNextObject()))) {
7707 			ok = compareProperty( matching, key );
7708 		}
7709 
7710 		iter->release();
7711 	}
7712 	keys->release(); // !! consume a ref !!
7713 
7714 	return ok;
7715 }
7716 #endif // __clang_analyzer__
7717 
7718 /* Helper to add a location matching dict to the table */
7719 
7720 OSDictionary *
addLocation(OSDictionary * table)7721 IOService::addLocation( OSDictionary * table )
7722 {
7723 	OSDictionary *      dict;
7724 
7725 	if (!table) {
7726 		return NULL;
7727 	}
7728 
7729 	dict = OSDictionary::withCapacity( 1 );
7730 	if (dict) {
7731 		bool ok = table->setObject( gIOLocationMatchKey, dict );
7732 		dict->release();
7733 		if (!ok) {
7734 			dict = NULL;
7735 		}
7736 	}
7737 
7738 	return dict;
7739 }
7740 
7741 /*
7742  * Go looking for a provider to match a location dict.
7743  */
7744 
7745 IOService *
matchLocation(IOService *)7746 IOService::matchLocation( IOService * /* client */ )
7747 {
7748 	IOService * parent;
7749 
7750 	parent = getProvider();
7751 
7752 	if (parent) {
7753 		parent = parent->matchLocation( this );
7754 	}
7755 
7756 	return parent;
7757 }
7758 
7759 OSDictionary *
_copyPropertiesForMatching(void)7760 IOService::_copyPropertiesForMatching(void)
7761 {
7762 	OSDictionary * matchProps;
7763 
7764 	matchProps = dictionaryWithProperties();
7765 	if (matchProps) {
7766 		// merge will check the OSDynamicCast
7767 		matchProps->merge((const OSDictionary *)matchProps->getObject(gIOUserServicePropertiesKey));
7768 	}
7769 	return matchProps;
7770 }
7771 
7772 bool
matchInternal(OSDictionary * table,uint32_t options,uint32_t * did)7773 IOService::matchInternal(OSDictionary * table, uint32_t options, uint32_t * did)
7774 {
7775 	OSString *          matched;
7776 	OSObject *          obj;
7777 	OSString *          str;
7778 	OSDictionary *      matchProps;
7779 	IORegistryEntry *   entry;
7780 	OSNumber *          num;
7781 	bool                match = true;
7782 	bool                changesOK = (0 != (kIOServiceChangesOK & options));
7783 	uint32_t            count;
7784 	uint32_t            done;
7785 
7786 	do{
7787 		count = table->getCount();
7788 		done = 0;
7789 		matchProps = NULL;
7790 		bool isUser;
7791 
7792 		isUser = (NULL != table->getObject(gIOServiceNotificationUserKey));
7793 		if (isUser) {
7794 			done++;
7795 			match = (0 == (kIOServiceUserInvisibleMatchState & __state[0]));
7796 			if ((!match) || (done == count)) {
7797 				break;
7798 			}
7799 		}
7800 
7801 		if (propertyExists(gIOExclaveAssignedKey)) {
7802 			if (!table->getObject(gIOExclaveProxyKey) && !isUser) {
7803 				match = false;
7804 				break;
7805 			}
7806 		} else if (table->getObject(gIOExclaveProxyKey)) {
7807 			match = false;
7808 			break;
7809 		}
7810 
7811 		if (table->getObject(gIOCompatibilityMatchKey)) {
7812 			done++;
7813 			obj = copyProperty(gIOCompatibilityPropertiesKey);
7814 			matchProps = OSDynamicCast(OSDictionary, obj);
7815 			if (!matchProps) {
7816 				OSSafeReleaseNULL(obj);
7817 			}
7818 		}
7819 
7820 		str = OSDynamicCast(OSString, table->getObject(gIOProviderClassKey));
7821 		if (str) {
7822 			done++;
7823 			if (matchProps && (obj = matchProps->getObject(gIOClassKey))) {
7824 				match = str->isEqualTo(obj);
7825 			} else {
7826 				match = ((kIOServiceClassDone & options) || (NULL != metaCast(str)));
7827 			}
7828 
7829 #if MATCH_DEBUG
7830 			match = (0 != metaCast( str ));
7831 			if ((kIOServiceClassDone & options) && !match) {
7832 				panic("classDone");
7833 			}
7834 #endif
7835 			if ((!match) || (done == count)) {
7836 				break;
7837 			}
7838 		}
7839 
7840 		obj = table->getObject( gIONameMatchKey );
7841 		if (obj) {
7842 			done++;
7843 			match = compareNames( obj, changesOK ? &matched : NULL );
7844 			if (!match) {
7845 				break;
7846 			}
7847 			if (changesOK && matched) {
7848 				// leave a hint as to which name matched
7849 				table->setObject( gIONameMatchedKey, matched );
7850 				matched->release();
7851 			}
7852 			if (done == count) {
7853 				break;
7854 			}
7855 		}
7856 
7857 		str = OSDynamicCast( OSString, table->getObject( gIOLocationMatchKey ));
7858 		if (str) {
7859 			const OSSymbol * sym;
7860 			done++;
7861 			match = false;
7862 			sym = copyLocation();
7863 			if (sym) {
7864 				match = sym->isEqualTo( str );
7865 				sym->release();
7866 			}
7867 			if ((!match) || (done == count)) {
7868 				break;
7869 			}
7870 		}
7871 
7872 		obj = table->getObject( gIOPropertyMatchKey );
7873 		if (obj) {
7874 			OSDictionary * nextDict;
7875 			OSIterator *   iter;
7876 			done++;
7877 			match = false;
7878 			if (!matchProps) {
7879 				matchProps = _copyPropertiesForMatching();
7880 			}
7881 			if (matchProps) {
7882 				nextDict = OSDynamicCast( OSDictionary, obj);
7883 				if (nextDict) {
7884 					iter = NULL;
7885 				} else {
7886 					iter = OSCollectionIterator::withCollection(
7887 						OSDynamicCast(OSCollection, obj));
7888 				}
7889 
7890 				while (nextDict
7891 				    || (iter && (NULL != (nextDict = OSDynamicCast(OSDictionary,
7892 				    iter->getNextObject()))))) {
7893 					match = matchProps->isEqualTo( nextDict, nextDict);
7894 					if (match) {
7895 						break;
7896 					}
7897 					nextDict = NULL;
7898 				}
7899 				if (iter) {
7900 					iter->release();
7901 				}
7902 			}
7903 			if ((!match) || (done == count)) {
7904 				break;
7905 			}
7906 		}
7907 
7908 		obj = table->getObject( gIOPropertyExistsMatchKey );
7909 		if (obj) {
7910 			OSString     * nextKey;
7911 			OSIterator *   iter;
7912 			done++;
7913 			match = false;
7914 			if (!matchProps) {
7915 				matchProps = _copyPropertiesForMatching();
7916 			}
7917 			if (matchProps) {
7918 				nextKey = OSDynamicCast( OSString, obj);
7919 				if (nextKey) {
7920 					iter = NULL;
7921 				} else {
7922 					iter = OSCollectionIterator::withCollection(
7923 						OSDynamicCast(OSCollection, obj));
7924 				}
7925 
7926 				while (nextKey
7927 				    || (iter && (NULL != (nextKey = OSDynamicCast(OSString,
7928 				    iter->getNextObject()))))) {
7929 					match = (NULL != matchProps->getObject(nextKey));
7930 					if (match) {
7931 						break;
7932 					}
7933 					nextKey = NULL;
7934 				}
7935 				if (iter) {
7936 					iter->release();
7937 				}
7938 			}
7939 			if ((!match) || (done == count)) {
7940 				break;
7941 			}
7942 		}
7943 
7944 		str = OSDynamicCast( OSString, table->getObject( gIOPathMatchKey ));
7945 		if (str) {
7946 			done++;
7947 			entry = IORegistryEntry::fromPath( str->getCStringNoCopy());
7948 			match = (this == entry);
7949 			if (entry) {
7950 				entry->release();
7951 			}
7952 			if (!match && matchProps && (obj = matchProps->getObject(gIOPathKey))) {
7953 				match = str->isEqualTo(obj);
7954 			}
7955 			if ((!match) || (done == count)) {
7956 				break;
7957 			}
7958 		}
7959 
7960 		num = OSDynamicCast( OSNumber, table->getObject( gIORegistryEntryIDKey ));
7961 		if (num) {
7962 			done++;
7963 			match = (getRegistryEntryID() == num->unsigned64BitValue());
7964 			if ((!match) || (done == count)) {
7965 				break;
7966 			}
7967 		}
7968 
7969 		num = OSDynamicCast( OSNumber, table->getObject( gIOMatchedServiceCountKey ));
7970 		if (num) {
7971 			OSIterator *        iter;
7972 			IOService *         service = NULL;
7973 			UInt32              serviceCount = 0;
7974 
7975 			done++;
7976 			iter = getClientIterator();
7977 			if (iter) {
7978 				while ((service = (IOService *) iter->getNextObject())) {
7979 					if (kIOServiceInactiveState & service->__state[0]) {
7980 						continue;
7981 					}
7982 					if (NULL == service->getProperty( gIOMatchCategoryKey )) {
7983 						continue;
7984 					}
7985 					++serviceCount;
7986 				}
7987 				iter->release();
7988 			}
7989 			match = (serviceCount == num->unsigned32BitValue());
7990 			if ((!match) || (done == count)) {
7991 				break;
7992 			}
7993 		}
7994 
7995 #define propMatch(key)                                  \
7996 	obj = table->getObject(key);                    \
7997 	if (obj)                                        \
7998 	{                                               \
7999 	    OSObject * prop;                            \
8000 	    done++;                                     \
8001 	    prop = copyProperty(key);                   \
8002 	    match = obj->isEqualTo(prop);               \
8003 	    if (prop) prop->release();                  \
8004 	    if ((!match) || (done == count)) break;     \
8005 	}
8006 		propMatch(gIOBSDNameKey)
8007 		propMatch(gIOBSDMajorKey)
8008 		propMatch(gIOBSDMinorKey)
8009 		propMatch(gIOBSDUnitKey)
8010 #undef propMatch
8011 	}while (false);
8012 
8013 	OSSafeReleaseNULL(matchProps);
8014 
8015 	if (did) {
8016 		*did = done;
8017 	}
8018 	return match;
8019 }
8020 
8021 bool
passiveMatch(OSDictionary * table,bool changesOK)8022 IOService::passiveMatch( OSDictionary * table, bool changesOK )
8023 {
8024 	return matchPassive(table, changesOK ? kIOServiceChangesOK : 0);
8025 }
8026 
8027 bool
matchPassive(OSDictionary * table,uint32_t options)8028 IOService::matchPassive(OSDictionary * table, uint32_t options)
8029 {
8030 	IOService *         where;
8031 	OSDictionary *      nextTable;
8032 	SInt32              score;
8033 	OSNumber *          newPri;
8034 	bool                match = true;
8035 	bool                matchParent = false;
8036 	uint32_t            count;
8037 	uint32_t            done;
8038 
8039 	assert( table );
8040 
8041 #if defined(XNU_TARGET_OS_OSX)
8042 	OSArray* aliasServiceRegIds = NULL;
8043 	IOService* foundAlternateService = NULL;
8044 #endif /* defined(XNU_TARGET_OS_OSX) */
8045 
8046 #if MATCH_DEBUG
8047 	OSDictionary * root = table;
8048 #endif
8049 
8050 	where = this;
8051 	do{
8052 		do{
8053 			count = table->getCount();
8054 			if (!(kIOServiceInternalDone & options)) {
8055 				match = where->matchInternal(table, options, &done);
8056 				// don't call family if we've done all the entries in the table
8057 				if ((!match) || (done == count)) {
8058 					break;
8059 				}
8060 			}
8061 
8062 			// pass in score from property table
8063 			score = IOServiceObjectOrder( table, (void *) gIOProbeScoreKey);
8064 
8065 			// do family specific matching
8066 			match = where->matchPropertyTable( table, &score );
8067 
8068 			if (!match) {
8069 #if IOMATCHDEBUG
8070 				if (kIOLogMatch & getDebugFlags( table )) {
8071 					LOG("%s: family specific matching fails\n", where->getName());
8072 				}
8073 #endif
8074 				break;
8075 			}
8076 
8077 			if (kIOServiceChangesOK & options) {
8078 				// save the score
8079 				newPri = OSNumber::withNumber( score, 32 );
8080 				if (newPri) {
8081 					table->setObject( gIOProbeScoreKey, newPri );
8082 					newPri->release();
8083 				}
8084 			}
8085 
8086 			options = 0;
8087 			matchParent = false;
8088 
8089 			nextTable = OSDynamicCast(OSDictionary,
8090 			    table->getObject( gIOParentMatchKey ));
8091 			if (nextTable) {
8092 				// look for a matching entry anywhere up to root
8093 				match = false;
8094 				matchParent = true;
8095 				table = nextTable;
8096 				break;
8097 			}
8098 
8099 			table = OSDynamicCast(OSDictionary,
8100 			    table->getObject( gIOLocationMatchKey ));
8101 			if (table) {
8102 				// look for a matching entry at matchLocation()
8103 				match = false;
8104 				where = where->getProvider();
8105 				if (where && (where = where->matchLocation(where))) {
8106 					continue;
8107 				}
8108 			}
8109 			break;
8110 		}while (true);
8111 
8112 		if (match == true) {
8113 			break;
8114 		}
8115 
8116 		if (matchParent == true) {
8117 #if defined(XNU_TARGET_OS_OSX)
8118 			// check if service has an alias to search its other "parents" if a parent match isn't found
8119 			OSObject * prop = where->copyProperty(gIOServiceLegacyMatchingRegistryIDKey);
8120 			OSNumber * alternateRegistryID = OSDynamicCast(OSNumber, prop);
8121 			if (alternateRegistryID != NULL) {
8122 				if (aliasServiceRegIds == NULL) {
8123 					aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID));
8124 				}
8125 				aliasServiceRegIds->setObject(alternateRegistryID);
8126 			}
8127 			OSSafeReleaseNULL(prop);
8128 #endif /* defined(XNU_TARGET_OS_OSX) */
8129 		} else {
8130 			break;
8131 		}
8132 
8133 		where = where->getProvider();
8134 #if defined(XNU_TARGET_OS_OSX)
8135 		if (where == NULL) {
8136 			// there were no matching parent services, check to see if there are aliased services that have a matching parent
8137 			if (aliasServiceRegIds != NULL) {
8138 				unsigned int numAliasedServices = aliasServiceRegIds->getCount();
8139 				if (numAliasedServices != 0) {
8140 					OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, aliasServiceRegIds->getObject(numAliasedServices - 1));
8141 					if (alternateRegistryID != NULL) {
8142 						OSDictionary* alternateMatchingDict = IOService::registryEntryIDMatching(alternateRegistryID->unsigned64BitValue());
8143 						aliasServiceRegIds->removeObject(numAliasedServices - 1);
8144 						if (alternateMatchingDict != NULL) {
8145 							OSSafeReleaseNULL(foundAlternateService);
8146 							foundAlternateService = IOService::copyMatchingService(alternateMatchingDict);
8147 							alternateMatchingDict->release();
8148 							if (foundAlternateService != NULL) {
8149 								where = foundAlternateService;
8150 							}
8151 						}
8152 					}
8153 				}
8154 			}
8155 		}
8156 #endif /* defined(XNU_TARGET_OS_OSX) */
8157 	}while (where != NULL);
8158 
8159 #if defined(XNU_TARGET_OS_OSX)
8160 	OSSafeReleaseNULL(foundAlternateService);
8161 	OSSafeReleaseNULL(aliasServiceRegIds);
8162 #endif /* defined(XNU_TARGET_OS_OSX) */
8163 
8164 #if MATCH_DEBUG
8165 	if (where != this) {
8166 		OSSerialize * s = OSSerialize::withCapacity(128);
8167 		root->serialize(s);
8168 		kprintf("parent match 0x%llx, %d,\n%s\n", getRegistryEntryID(), match, s->text());
8169 		s->release();
8170 	}
8171 #endif
8172 
8173 	return match;
8174 }
8175 
8176 
8177 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,IOUserClient ** handler)8178 IOService::newUserClient( task_t owningTask, void * securityID,
8179     UInt32 type, OSDictionary * properties,
8180     IOUserClient ** handler )
8181 {
8182 	const OSSymbol *userClientClass = NULL;
8183 	IOUserClient *client;
8184 	OSObject *prop;
8185 	OSObject *temp;
8186 
8187 	if (reserved && reserved->uvars && reserved->uvars->userServer) {
8188 		return reserved->uvars->userServer->serviceNewUserClient(this, owningTask, securityID, type, properties, handler);
8189 	}
8190 
8191 	if (kIOReturnSuccess == newUserClient( owningTask, securityID, type, handler )) {
8192 		return kIOReturnSuccess;
8193 	}
8194 
8195 	// First try my own properties for a user client class name
8196 	prop = copyProperty(gIOUserClientClassKey);
8197 	if (prop) {
8198 		if (OSDynamicCast(OSSymbol, prop)) {
8199 			userClientClass = (const OSSymbol *) prop;
8200 			prop = NULL;
8201 		} else if (OSDynamicCast(OSString, prop)) {
8202 			userClientClass = OSSymbol::withString((OSString *) prop);
8203 			OSSafeReleaseNULL(prop);
8204 			if (userClientClass) {
8205 				setProperty(gIOUserClientClassKey,
8206 				    (OSObject *) userClientClass);
8207 			}
8208 		} else {
8209 			OSSafeReleaseNULL(prop);
8210 		}
8211 	}
8212 
8213 	// Didn't find one so lets just bomb out now without further ado.
8214 	if (!userClientClass) {
8215 		return kIOReturnUnsupported;
8216 	}
8217 
8218 	// This reference is consumed by the IOServiceOpen call
8219 	temp = OSMetaClass::allocClassWithName(userClientClass);
8220 	OSSafeReleaseNULL(userClientClass);
8221 	if (!temp) {
8222 		return kIOReturnNoMemory;
8223 	}
8224 
8225 	if (OSDynamicCast(IOUserClient, temp)) {
8226 		client = (IOUserClient *) temp;
8227 	} else {
8228 		temp->release();
8229 		return kIOReturnUnsupported;
8230 	}
8231 
8232 	if (!client->initWithTask(owningTask, securityID, type, properties)) {
8233 		client->release();
8234 		return kIOReturnBadArgument;
8235 	}
8236 
8237 	if (!client->attach(this)) {
8238 		client->release();
8239 		return kIOReturnUnsupported;
8240 	}
8241 
8242 	if (!client->start(this)) {
8243 		client->detach(this);
8244 		client->release();
8245 		return kIOReturnUnsupported;
8246 	}
8247 
8248 	*handler = client;
8249 	return kIOReturnSuccess;
8250 }
8251 
8252 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,OSSharedPtr<IOUserClient> & handler)8253 IOService::newUserClient( task_t owningTask, void * securityID,
8254     UInt32 type, OSDictionary * properties,
8255     OSSharedPtr<IOUserClient>& handler )
8256 {
8257 	IOUserClient* handlerRaw = NULL;
8258 	IOReturn result = newUserClient(owningTask, securityID, type, properties, &handlerRaw);
8259 	handler.reset(handlerRaw, OSNoRetain);
8260 	return result;
8261 }
8262 
8263 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,IOUserClient ** handler)8264 IOService::newUserClient( task_t owningTask, void * securityID,
8265     UInt32 type, IOUserClient ** handler )
8266 {
8267 	return kIOReturnUnsupported;
8268 }
8269 
8270 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSSharedPtr<IOUserClient> & handler)8271 IOService::newUserClient( task_t owningTask, void * securityID,
8272     UInt32 type, OSSharedPtr<IOUserClient>& handler )
8273 {
8274 	IOUserClient* handlerRaw = nullptr;
8275 	IOReturn result = IOService::newUserClient(owningTask, securityID, type, &handlerRaw);
8276 	handler.reset(handlerRaw, OSNoRetain);
8277 	return result;
8278 }
8279 
8280 
8281 IOReturn
requestProbe(IOOptionBits options)8282 IOService::requestProbe( IOOptionBits options )
8283 {
8284 	return kIOReturnUnsupported;
8285 }
8286 
8287 bool
hasUserServer() const8288 IOService::hasUserServer() const
8289 {
8290 	return reserved && reserved->uvars && reserved->uvars->userServer;
8291 }
8292 
8293 /*
8294  * Convert an IOReturn to text. Subclasses which add additional
8295  * IOReturn's should override this method and call
8296  * super::stringFromReturn if the desired value is not found.
8297  */
8298 
8299 const char *
stringFromReturn(IOReturn rtn)8300 IOService::stringFromReturn( IOReturn rtn )
8301 {
8302 	static const IONamedValue IOReturn_values[] = {
8303 		{kIOReturnSuccess, "success"                           },
8304 		{kIOReturnError, "general error"                     },
8305 		{kIOReturnNoMemory, "memory allocation error"           },
8306 		{kIOReturnNoResources, "resource shortage"                 },
8307 		{kIOReturnIPCError, "Mach IPC failure"                  },
8308 		{kIOReturnNoDevice, "no such device"                    },
8309 		{kIOReturnNotPrivileged, "privilege violation"               },
8310 		{kIOReturnBadArgument, "invalid argument"                  },
8311 		{kIOReturnLockedRead, "device is read locked"             },
8312 		{kIOReturnLockedWrite, "device is write locked"            },
8313 		{kIOReturnExclusiveAccess, "device is exclusive access"        },
8314 		{kIOReturnBadMessageID, "bad IPC message ID"                },
8315 		{kIOReturnUnsupported, "unsupported function"              },
8316 		{kIOReturnVMError, "virtual memory error"              },
8317 		{kIOReturnInternalError, "internal driver error"             },
8318 		{kIOReturnIOError, "I/O error"                         },
8319 		{kIOReturnCannotLock, "cannot acquire lock"               },
8320 		{kIOReturnNotOpen, "device is not open"                },
8321 		{kIOReturnNotReadable, "device is not readable"            },
8322 		{kIOReturnNotWritable, "device is not writeable"           },
8323 		{kIOReturnNotAligned, "alignment error"                   },
8324 		{kIOReturnBadMedia, "media error"                       },
8325 		{kIOReturnStillOpen, "device is still open"              },
8326 		{kIOReturnRLDError, "rld failure"                       },
8327 		{kIOReturnDMAError, "DMA failure"                       },
8328 		{kIOReturnBusy, "device is busy"                    },
8329 		{kIOReturnTimeout, "I/O timeout"                       },
8330 		{kIOReturnOffline, "device is offline"                 },
8331 		{kIOReturnNotReady, "device is not ready"               },
8332 		{kIOReturnNotAttached, "device/channel is not attached"    },
8333 		{kIOReturnNoChannels, "no DMA channels available"         },
8334 		{kIOReturnNoSpace, "no space for data"                 },
8335 		{kIOReturnPortExists, "device port already exists"        },
8336 		{kIOReturnCannotWire, "cannot wire physical memory"       },
8337 		{kIOReturnNoInterrupt, "no interrupt attached"             },
8338 		{kIOReturnNoFrames, "no DMA frames enqueued"            },
8339 		{kIOReturnMessageTooLarge, "message is too large"              },
8340 		{kIOReturnNotPermitted, "operation is not permitted"        },
8341 		{kIOReturnNoPower, "device is without power"           },
8342 		{kIOReturnNoMedia, "media is not present"              },
8343 		{kIOReturnUnformattedMedia, "media is not formatted"            },
8344 		{kIOReturnUnsupportedMode, "unsupported mode"                  },
8345 		{kIOReturnUnderrun, "data underrun"                     },
8346 		{kIOReturnOverrun, "data overrun"                      },
8347 		{kIOReturnDeviceError, "device error"                      },
8348 		{kIOReturnNoCompletion, "no completion routine"             },
8349 		{kIOReturnAborted, "operation was aborted"             },
8350 		{kIOReturnNoBandwidth, "bus bandwidth would be exceeded"   },
8351 		{kIOReturnNotResponding, "device is not responding"          },
8352 		{kIOReturnInvalid, "unanticipated driver error"        },
8353 		{0, NULL                                }
8354 	};
8355 
8356 	return IOFindNameForValue(rtn, IOReturn_values);
8357 }
8358 
8359 /*
8360  * Convert an IOReturn to an errno.
8361  */
8362 int
errnoFromReturn(IOReturn rtn)8363 IOService::errnoFromReturn( IOReturn rtn )
8364 {
8365 	if (unix_err(err_get_code(rtn)) == rtn) {
8366 		return err_get_code(rtn);
8367 	}
8368 
8369 	switch (rtn) {
8370 	// (obvious match)
8371 	case kIOReturnSuccess:
8372 		return 0;
8373 	case kIOReturnNoMemory:
8374 		return ENOMEM;
8375 	case kIOReturnNoDevice:
8376 		return ENXIO;
8377 	case kIOReturnVMError:
8378 		return EFAULT;
8379 	case kIOReturnNotPermitted:
8380 		return EPERM;
8381 	case kIOReturnNotPrivileged:
8382 		return EACCES;
8383 	case kIOReturnIOError:
8384 		return EIO;
8385 	case kIOReturnNotWritable:
8386 		return EROFS;
8387 	case kIOReturnBadArgument:
8388 		return EINVAL;
8389 	case kIOReturnUnsupported:
8390 		return ENOTSUP;
8391 	case kIOReturnBusy:
8392 		return EBUSY;
8393 	case kIOReturnNoPower:
8394 		return EPWROFF;
8395 	case kIOReturnDeviceError:
8396 		return EDEVERR;
8397 	case kIOReturnTimeout:
8398 		return ETIMEDOUT;
8399 	case kIOReturnMessageTooLarge:
8400 		return EMSGSIZE;
8401 	case kIOReturnNoSpace:
8402 		return ENOSPC;
8403 	case kIOReturnCannotLock:
8404 		return ENOLCK;
8405 
8406 	// (best match)
8407 	case kIOReturnBadMessageID:
8408 	case kIOReturnNoCompletion:
8409 	case kIOReturnNotAligned:
8410 		return EINVAL;
8411 	case kIOReturnNotReady:
8412 		return EBUSY;
8413 	case kIOReturnRLDError:
8414 		return EBADMACHO;
8415 	case kIOReturnPortExists:
8416 	case kIOReturnStillOpen:
8417 		return EEXIST;
8418 	case kIOReturnExclusiveAccess:
8419 	case kIOReturnLockedRead:
8420 	case kIOReturnLockedWrite:
8421 	case kIOReturnNotOpen:
8422 	case kIOReturnNotReadable:
8423 		return EACCES;
8424 	case kIOReturnCannotWire:
8425 	case kIOReturnNoResources:
8426 		return ENOMEM;
8427 	case kIOReturnAborted:
8428 	case kIOReturnOffline:
8429 	case kIOReturnNotResponding:
8430 		return EBUSY;
8431 	case kIOReturnBadMedia:
8432 	case kIOReturnNoMedia:
8433 	case kIOReturnNotAttached:
8434 	case kIOReturnUnformattedMedia:
8435 		return ENXIO; // (media error)
8436 	case kIOReturnDMAError:
8437 	case kIOReturnOverrun:
8438 	case kIOReturnUnderrun:
8439 		return EIO; // (transfer error)
8440 	case kIOReturnNoBandwidth:
8441 	case kIOReturnNoChannels:
8442 	case kIOReturnNoFrames:
8443 	case kIOReturnNoInterrupt:
8444 		return EIO; // (hardware error)
8445 	case kIOReturnError:
8446 	case kIOReturnInternalError:
8447 	case kIOReturnInvalid:
8448 		return EIO; // (generic error)
8449 	case kIOReturnIPCError:
8450 		return EIO; // (ipc error)
8451 	default:
8452 		return EIO; // (all other errors)
8453 	}
8454 }
8455 
8456 IOReturn
message(UInt32 type,IOService * provider,void * argument)8457 IOService::message( UInt32 type, IOService * provider,
8458     void * argument )
8459 {
8460 	/*
8461 	 * Generic entry point for calls from the provider.  A return value of
8462 	 * kIOReturnSuccess indicates that the message was received, and where
8463 	 * applicable, that it was successful.
8464 	 */
8465 
8466 	return kIOReturnUnsupported;
8467 }
8468 
8469 /*
8470  * Device memory
8471  */
8472 
8473 IOItemCount
getDeviceMemoryCount(void)8474 IOService::getDeviceMemoryCount( void )
8475 {
8476 	OSArray *           array;
8477 	IOItemCount         count;
8478 
8479 	array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
8480 	if (array) {
8481 		count = array->getCount();
8482 	} else {
8483 		count = 0;
8484 	}
8485 
8486 	return count;
8487 }
8488 
8489 IODeviceMemory *
getDeviceMemoryWithIndex(unsigned int index)8490 IOService::getDeviceMemoryWithIndex( unsigned int index )
8491 {
8492 	OSArray *           array;
8493 	IODeviceMemory *    range;
8494 
8495 	array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
8496 	if (array) {
8497 		range = (IODeviceMemory *) array->getObject( index );
8498 	} else {
8499 		range = NULL;
8500 	}
8501 
8502 	return range;
8503 }
8504 
8505 IOMemoryMap *
mapDeviceMemoryWithIndex(unsigned int index,IOOptionBits options)8506 IOService::mapDeviceMemoryWithIndex( unsigned int index,
8507     IOOptionBits options )
8508 {
8509 	IODeviceMemory *    range;
8510 	IOMemoryMap *       map;
8511 
8512 	range = getDeviceMemoryWithIndex( index );
8513 	if (range) {
8514 		map = range->map( options );
8515 	} else {
8516 		map = NULL;
8517 	}
8518 
8519 	return map;
8520 }
8521 
8522 OSArray *
getDeviceMemory(void)8523 IOService::getDeviceMemory( void )
8524 {
8525 	return OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
8526 }
8527 
8528 
8529 void
setDeviceMemory(OSArray * array)8530 IOService::setDeviceMemory( OSArray * array )
8531 {
8532 	setProperty( gIODeviceMemoryKey, array);
8533 }
8534 
8535 static void
requireMaxCpuDelay(IOService * service,UInt32 ns,UInt32 delayType)8536 requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType)
8537 {
8538 	static const UInt kNoReplace = -1U; // Must be an illegal index
8539 	UInt replace = kNoReplace;
8540 	bool setCpuDelay = false;
8541 
8542 	IORecursiveLockLock(sCpuDelayLock);
8543 
8544 	UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
8545 	__typed_allocators_ignore_push
8546 	CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
8547 	__typed_allocators_ignore_pop
8548 	IOService * holder = NULL;
8549 
8550 	if (ns) {
8551 		const CpuDelayEntry ne = {service, ns, delayType};
8552 		holder = service;
8553 		// Set maximum delay.
8554 		for (UInt i = 0; i < count; i++) {
8555 			IOService *thisService = entries[i].fService;
8556 			bool sameType = (delayType == entries[i].fDelayType);
8557 			if ((service == thisService) && sameType) {
8558 				replace = i;
8559 			} else if (!thisService) {
8560 				if (kNoReplace == replace) {
8561 					replace = i;
8562 				}
8563 			} else if (sameType) {
8564 				const UInt32 thisMax = entries[i].fMaxDelay;
8565 				if (thisMax < ns) {
8566 					ns = thisMax;
8567 					holder = thisService;
8568 				}
8569 			}
8570 		}
8571 
8572 		setCpuDelay = true;
8573 		if (kNoReplace == replace) {
8574 			__typed_allocators_ignore_push
8575 			sCpuDelayData->appendBytes(&ne, sizeof(ne));
8576 			__typed_allocators_ignore_pop
8577 		} else {
8578 			entries[replace] = ne;
8579 		}
8580 	} else {
8581 		ns = -1U; // Set to max unsigned, i.e. no restriction
8582 
8583 		for (UInt i = 0; i < count; i++) {
8584 			// Clear a maximum delay.
8585 			IOService *thisService = entries[i].fService;
8586 			if (thisService && (delayType == entries[i].fDelayType)) {
8587 				UInt32 thisMax = entries[i].fMaxDelay;
8588 				if (service == thisService) {
8589 					replace = i;
8590 				} else if (thisMax < ns) {
8591 					ns = thisMax;
8592 					holder = thisService;
8593 				}
8594 			}
8595 		}
8596 
8597 		// Check if entry found
8598 		if (kNoReplace != replace) {
8599 			entries[replace].fService = NULL; // Null the entry
8600 			setCpuDelay = true;
8601 		}
8602 	}
8603 
8604 	if (setCpuDelay) {
8605 		if (holder && debug_boot_arg) {
8606 			strlcpy(sCPULatencyHolderName[delayType], holder->getName(), sizeof(sCPULatencyHolderName[delayType]));
8607 		}
8608 
8609 		// Must be safe to call from locked context
8610 		if (delayType == kCpuDelayBusStall) {
8611 #if defined(__x86_64__)
8612 			ml_set_maxbusdelay(ns);
8613 #endif /* defined(__x86_64__) */
8614 		}
8615 #if defined(__x86_64__)
8616 		else if (delayType == kCpuDelayInterrupt) {
8617 			ml_set_maxintdelay(ns);
8618 		}
8619 #endif /* defined(__x86_64__) */
8620 		sCPULatencyHolder[delayType]->setValue(holder ? holder->getRegistryEntryID() : 0);
8621 		sCPULatencySet[delayType]->setValue(ns);
8622 
8623 		OSArray * handlers = sCpuLatencyHandlers[delayType];
8624 		IOService * target;
8625 		if (handlers) {
8626 			for (unsigned int idx = 0;
8627 			    (target = (IOService *) handlers->getObject(idx));
8628 			    idx++) {
8629 				target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
8630 				    (void *) (uintptr_t) ns, holder,
8631 				    NULL, NULL);
8632 			}
8633 		}
8634 	}
8635 
8636 	IORecursiveLockUnlock(sCpuDelayLock);
8637 }
8638 
8639 static IOReturn
setLatencyHandler(UInt32 delayType,IOService * target,bool enable)8640 setLatencyHandler(UInt32 delayType, IOService * target, bool enable)
8641 {
8642 	IOReturn result = kIOReturnNotFound;
8643 	OSArray * array;
8644 	unsigned int idx;
8645 
8646 	IORecursiveLockLock(sCpuDelayLock);
8647 
8648 	do{
8649 		if (enable && !sCpuLatencyHandlers[delayType]) {
8650 			sCpuLatencyHandlers[delayType] = OSArray::withCapacity(4);
8651 		}
8652 		array = sCpuLatencyHandlers[delayType];
8653 		if (!array) {
8654 			break;
8655 		}
8656 		idx = array->getNextIndexOfObject(target, 0);
8657 		if (!enable) {
8658 			if (-1U != idx) {
8659 				array->removeObject(idx);
8660 				result = kIOReturnSuccess;
8661 			}
8662 		} else {
8663 			if (-1U != idx) {
8664 				result = kIOReturnExclusiveAccess;
8665 				break;
8666 			}
8667 			array->setObject(target);
8668 
8669 			UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
8670 			__typed_allocators_ignore_push
8671 			CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
8672 			__typed_allocators_ignore_pop
8673 			UInt32 ns = -1U; // Set to max unsigned, i.e. no restriction
8674 			IOService * holder = NULL;
8675 
8676 			for (UInt i = 0; i < count; i++) {
8677 				if (entries[i].fService
8678 				    && (delayType == entries[i].fDelayType)
8679 				    && (entries[i].fMaxDelay < ns)) {
8680 					ns = entries[i].fMaxDelay;
8681 					holder = entries[i].fService;
8682 				}
8683 			}
8684 			target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
8685 			    (void *) (uintptr_t) ns, holder,
8686 			    NULL, NULL);
8687 			result = kIOReturnSuccess;
8688 		}
8689 	}while (false);
8690 
8691 	IORecursiveLockUnlock(sCpuDelayLock);
8692 
8693 	return result;
8694 }
8695 
8696 IOReturn
requireMaxBusStall(UInt32 ns)8697 IOService::requireMaxBusStall(UInt32 ns)
8698 {
8699 #if !defined(__x86_64__)
8700 	switch (ns) {
8701 	case kIOMaxBusStall40usec:
8702 	case kIOMaxBusStall30usec:
8703 	case kIOMaxBusStall25usec:
8704 	case kIOMaxBusStall20usec:
8705 	case kIOMaxBusStall10usec:
8706 	case kIOMaxBusStall5usec:
8707 	case kIOMaxBusStallNone:
8708 		break;
8709 	default:
8710 		return kIOReturnBadArgument;
8711 	}
8712 #endif /* !defined(__x86_64__) */
8713 	requireMaxCpuDelay(this, ns, kCpuDelayBusStall);
8714 	return kIOReturnSuccess;
8715 }
8716 
8717 IOReturn
requireMaxInterruptDelay(uint32_t ns)8718 IOService::requireMaxInterruptDelay(uint32_t ns)
8719 {
8720 #if defined(__x86_64__)
8721 	requireMaxCpuDelay(this, ns, kCpuDelayInterrupt);
8722 	return kIOReturnSuccess;
8723 #else /* defined(__x86_64__) */
8724 	return kIOReturnUnsupported;
8725 #endif /* defined(__x86_64__) */
8726 }
8727 
8728 /*
8729  * Device interrupts
8730  */
8731 
8732 IOReturn
resolveInterrupt(IOService * nub,int source)8733 IOService::resolveInterrupt(IOService *nub, int source)
8734 {
8735 	IOInterruptController *interruptController;
8736 	OSArray               *array;
8737 	OSData                *data;
8738 	OSSymbol              *interruptControllerName;
8739 	unsigned int           numSources;
8740 	IOInterruptSource     *interruptSources;
8741 	IOInterruptSourcePrivate *interruptSourcesPrivate;
8742 
8743 	// Get the parents list from the nub.
8744 	array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptControllersKey));
8745 	if (array == NULL) {
8746 		return kIOReturnNoResources;
8747 	}
8748 
8749 	// Allocate space for the IOInterruptSources if needed... then return early.
8750 	if (nub->_interruptSources == NULL) {
8751 		numSources = array->getCount();
8752 		interruptSources = IONewZero(IOInterruptSource, numSources);
8753 		interruptSourcesPrivate = IONewZero(IOInterruptSourcePrivate, numSources);
8754 
8755 		if (interruptSources == NULL || interruptSourcesPrivate == NULL) {
8756 			IODelete(interruptSources, IOInterruptSource, numSources);
8757 			IODelete(interruptSourcesPrivate, IOInterruptSourcePrivate, numSources);
8758 			return kIOReturnNoMemory;
8759 		}
8760 
8761 		nub->_numInterruptSources = numSources;
8762 		nub->_interruptSources = interruptSources;
8763 		nub->reserved->interruptSourcesPrivate = interruptSourcesPrivate;
8764 		return kIOReturnSuccess;
8765 	}
8766 
8767 	interruptControllerName = OSDynamicCast(OSSymbol, array->getObject(source));
8768 	if (interruptControllerName == NULL) {
8769 		return kIOReturnNoResources;
8770 	}
8771 
8772 	interruptController = getPlatform()->lookUpInterruptController(interruptControllerName);
8773 	if (interruptController == NULL) {
8774 		return kIOReturnNoResources;
8775 	}
8776 
8777 	// Get the interrupt numbers from the nub.
8778 	array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptSpecifiersKey));
8779 	if (array == NULL) {
8780 		return kIOReturnNoResources;
8781 	}
8782 	data = OSDynamicCast(OSData, array->getObject(source));
8783 	if (data == NULL) {
8784 		return kIOReturnNoResources;
8785 	}
8786 
8787 	// Set the interruptController and interruptSource in the nub's table.
8788 	interruptSources = nub->_interruptSources;
8789 	interruptSources[source].interruptController = interruptController;
8790 	interruptSources[source].vectorData = data;
8791 
8792 	return kIOReturnSuccess;
8793 }
8794 
8795 IOReturn
lookupInterrupt(int source,bool resolve,IOInterruptController ** interruptController)8796 IOService::lookupInterrupt(int source, bool resolve, IOInterruptController **interruptController)
8797 {
8798 	IOReturn ret;
8799 
8800 	/* Make sure the _interruptSources are set */
8801 	if (_interruptSources == NULL) {
8802 		ret = resolveInterrupt(this, source);
8803 		if (ret != kIOReturnSuccess) {
8804 			return ret;
8805 		}
8806 	}
8807 
8808 	/* Make sure the local source number is valid */
8809 	if ((source < 0) || (source >= _numInterruptSources)) {
8810 		return kIOReturnNoInterrupt;
8811 	}
8812 
8813 	/* Look up the contoller for the local source */
8814 	*interruptController = _interruptSources[source].interruptController;
8815 
8816 	if (*interruptController == NULL) {
8817 		if (!resolve) {
8818 			return kIOReturnNoInterrupt;
8819 		}
8820 
8821 		/* Try to resolve the interrupt */
8822 		ret = resolveInterrupt(this, source);
8823 		if (ret != kIOReturnSuccess) {
8824 			return ret;
8825 		}
8826 
8827 		*interruptController = _interruptSources[source].interruptController;
8828 	}
8829 
8830 	return kIOReturnSuccess;
8831 }
8832 
8833 IOReturn
registerInterrupt(int source,OSObject * target,IOInterruptAction handler,void * refCon)8834 IOService::registerInterrupt(int source, OSObject *target,
8835     IOInterruptAction handler,
8836     void *refCon)
8837 {
8838 	IOInterruptController *interruptController;
8839 	IOReturn              ret;
8840 
8841 	ret = lookupInterrupt(source, true, &interruptController);
8842 	if (ret != kIOReturnSuccess) {
8843 		return ret;
8844 	}
8845 
8846 	/* Register the source */
8847 	return interruptController->registerInterrupt(this, source, target,
8848 	           (IOInterruptHandler)handler,
8849 	           refCon);
8850 }
8851 
8852 static void
IOServiceInterruptActionToBlock(OSObject * target,void * refCon,IOService * nub,int source)8853 IOServiceInterruptActionToBlock( OSObject * target, void * refCon,
8854     IOService * nub, int source )
8855 {
8856 	((IOInterruptActionBlock)(refCon))(nub, source);
8857 }
8858 
8859 IOReturn
registerInterruptBlock(int source,OSObject * target,IOInterruptActionBlock handler)8860 IOService::registerInterruptBlock(int source, OSObject *target,
8861     IOInterruptActionBlock handler)
8862 {
8863 	IOReturn ret;
8864 	void   * block;
8865 
8866 	block = Block_copy(handler);
8867 	if (!block) {
8868 		return kIOReturnNoMemory;
8869 	}
8870 
8871 	ret = registerInterrupt(source, target, &IOServiceInterruptActionToBlock, block);
8872 	if (kIOReturnSuccess != ret) {
8873 		Block_release(block);
8874 		return ret;
8875 	}
8876 
8877 	reserved->interruptSourcesPrivate[source].vectorBlock = block;
8878 
8879 	return ret;
8880 }
8881 
8882 IOReturn
unregisterInterrupt(int source)8883 IOService::unregisterInterrupt(int source)
8884 {
8885 	IOReturn              ret;
8886 	IOInterruptController *interruptController;
8887 	IOInterruptSourcePrivate *priv;
8888 	void                  *block;
8889 
8890 	ret = lookupInterrupt(source, false, &interruptController);
8891 	if (ret != kIOReturnSuccess) {
8892 		return ret;
8893 	}
8894 
8895 	/* Unregister the source */
8896 	priv = &reserved->interruptSourcesPrivate[source];
8897 	block = priv->vectorBlock;
8898 	ret = interruptController->unregisterInterrupt(this, source);
8899 	if ((kIOReturnSuccess == ret) && (block = priv->vectorBlock)) {
8900 		priv->vectorBlock = NULL;
8901 		Block_release(block);
8902 	}
8903 
8904 	return ret;
8905 }
8906 
8907 void
unregisterAllInterrupts(void)8908 IOService::unregisterAllInterrupts(void)
8909 {
8910 	for (int source = 0; source < _numInterruptSources; source++) {
8911 		(void) unregisterInterrupt(source);
8912 	}
8913 }
8914 
8915 IOReturn
addInterruptStatistics(IOInterruptAccountingData * statistics,int source)8916 IOService::addInterruptStatistics(IOInterruptAccountingData * statistics, int source)
8917 {
8918 	IOReportLegend * legend = NULL;
8919 	IOInterruptAccountingData * oldValue = NULL;
8920 	IOInterruptAccountingReporter * newArray = NULL;
8921 	char subgroupName[64];
8922 	int newArraySize = 0;
8923 	int i = 0;
8924 
8925 	if (source < 0) {
8926 		return kIOReturnBadArgument;
8927 	}
8928 
8929 	/*
8930 	 * We support statistics on a maximum of 256 interrupts per nub; if a nub
8931 	 * has more than 256 interrupt specifiers associated with it, and tries
8932 	 * to register a high interrupt index with interrupt accounting, panic.
8933 	 * Having more than 256 interrupts associated with a single nub is
8934 	 * probably a sign that something fishy is going on.
8935 	 */
8936 	if (source > IA_INDEX_MAX) {
8937 		panic("addInterruptStatistics called for an excessively large index (%d)", source);
8938 	}
8939 
8940 	/*
8941 	 * TODO: This is ugly (wrapping a lock around an allocation).  I'm only
8942 	 * leaving it as is because the likelihood of contention where we are
8943 	 * actually growing the array is minimal (we would realistically need
8944 	 * to be starting a driver for the first time, with an IOReporting
8945 	 * client already in place).  Nonetheless, cleanup that can be done
8946 	 * to adhere to best practices; it'll make the code more complicated,
8947 	 * unfortunately.
8948 	 */
8949 	IOLockLock(&reserved->interruptStatisticsLock);
8950 
8951 	/*
8952 	 * Lazily allocate the statistics array.
8953 	 */
8954 	if (!reserved->interruptStatisticsArray) {
8955 		reserved->interruptStatisticsArray = IONew(IOInterruptAccountingReporter, 1);
8956 		assert(reserved->interruptStatisticsArray);
8957 		reserved->interruptStatisticsArrayCount = 1;
8958 		bzero(reserved->interruptStatisticsArray, sizeof(*reserved->interruptStatisticsArray));
8959 	}
8960 
8961 	if (source >= reserved->interruptStatisticsArrayCount) {
8962 		/*
8963 		 * We're still within the range of supported indices, but we are out
8964 		 * of space in the current array.  Do a nasty realloc (because
8965 		 * IORealloc isn't a thing) here.  We'll double the size with each
8966 		 * reallocation.
8967 		 *
8968 		 * Yes, the "next power of 2" could be more efficient; but this will
8969 		 * be invoked incredibly rarely.  Who cares.
8970 		 */
8971 		newArraySize = (reserved->interruptStatisticsArrayCount << 1);
8972 
8973 		while (newArraySize <= source) {
8974 			newArraySize = (newArraySize << 1);
8975 		}
8976 		newArray = IONew(IOInterruptAccountingReporter, newArraySize);
8977 
8978 		assert(newArray);
8979 
8980 		/*
8981 		 * TODO: This even zeroes the memory it is about to overwrite.
8982 		 * Shameful; fix it.  Not particularly high impact, however.
8983 		 */
8984 		bzero(newArray, newArraySize * sizeof(*newArray));
8985 		memcpy(newArray, reserved->interruptStatisticsArray, reserved->interruptStatisticsArrayCount * sizeof(*newArray));
8986 		IODelete(reserved->interruptStatisticsArray, IOInterruptAccountingReporter, reserved->interruptStatisticsArrayCount);
8987 		reserved->interruptStatisticsArray = newArray;
8988 		reserved->interruptStatisticsArrayCount = newArraySize;
8989 	}
8990 
8991 	if (!reserved->interruptStatisticsArray[source].reporter) {
8992 		/*
8993 		 * We don't have a reporter associated with this index yet, so we
8994 		 * need to create one.
8995 		 */
8996 		/*
8997 		 * TODO: Some statistics do in fact have common units (time); should this be
8998 		 * split into separate reporters to communicate this?
8999 		 */
9000 		reserved->interruptStatisticsArray[source].reporter = IOSimpleReporter::with(this, kIOReportCategoryPower, kIOReportUnitNone);
9001 
9002 		/*
9003 		 * Each statistic is given an identifier based on the interrupt index (which
9004 		 * should be unique relative to any single nub) and the statistic involved.
9005 		 * We should now have a sane (small and positive) index, so start
9006 		 * constructing the channels for statistics.
9007 		 */
9008 		for (i = 0; i < IA_NUM_INTERRUPT_ACCOUNTING_STATISTICS; i++) {
9009 			/*
9010 			 * TODO: Currently, this does not add channels for disabled statistics.
9011 			 * Will this be confusing for clients?  If so, we should just add the
9012 			 * channels; we can avoid updating the channels even if they exist.
9013 			 */
9014 			if (IA_GET_STATISTIC_ENABLED(i)) {
9015 				reserved->interruptStatisticsArray[source].reporter->addChannel(IA_GET_CHANNEL_ID(source, i), kInterruptAccountingStatisticNameArray[i]);
9016 			}
9017 		}
9018 
9019 		/*
9020 		 * We now need to add the legend for this reporter to the registry.
9021 		 */
9022 		OSObject * prop = copyProperty(kIOReportLegendKey);
9023 		legend = IOReportLegend::with(OSDynamicCast(OSArray, prop));
9024 		OSSafeReleaseNULL(prop);
9025 
9026 		/*
9027 		 * Note that while we compose the subgroup name, we do not need to
9028 		 * manage its lifecycle (the reporter will handle this).
9029 		 */
9030 		snprintf(subgroupName, sizeof(subgroupName), "%s %d", getName(), source);
9031 		subgroupName[sizeof(subgroupName) - 1] = 0;
9032 		legend->addReporterLegend(reserved->interruptStatisticsArray[source].reporter, kInterruptAccountingGroupName, subgroupName);
9033 		setProperty(kIOReportLegendKey, legend->getLegend());
9034 		legend->release();
9035 
9036 		/*
9037 		 * TODO: Is this a good idea?  Probably not; my assumption is it opts
9038 		 * all entities who register interrupts into public disclosure of all
9039 		 * IOReporting channels.  Unfortunately, this appears to be as fine
9040 		 * grain as it gets.
9041 		 */
9042 		setProperty(kIOReportLegendPublicKey, true);
9043 	}
9044 
9045 	/*
9046 	 * Don't stomp existing entries.  If we are about to, panic; this
9047 	 * probably means we failed to tear down our old interrupt source
9048 	 * correctly.
9049 	 */
9050 	oldValue = reserved->interruptStatisticsArray[source].statistics;
9051 
9052 	if (oldValue) {
9053 		panic("addInterruptStatistics call for index %d would have clobbered existing statistics", source);
9054 	}
9055 
9056 	reserved->interruptStatisticsArray[source].statistics = statistics;
9057 
9058 	/*
9059 	 * Inherit the reporter values for each statistic.  The target may
9060 	 * be torn down as part of the runtime of the service (especially
9061 	 * for sleep/wake), so we inherit in order to avoid having values
9062 	 * reset for no apparent reason.  Our statistics are ultimately
9063 	 * tied to the index and the sevice, not to an individual target,
9064 	 * so we should maintain them accordingly.
9065 	 */
9066 	interruptAccountingDataInheritChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
9067 
9068 	IOLockUnlock(&reserved->interruptStatisticsLock);
9069 
9070 	return kIOReturnSuccess;
9071 }
9072 
9073 IOReturn
removeInterruptStatistics(int source)9074 IOService::removeInterruptStatistics(int source)
9075 {
9076 	IOInterruptAccountingData * value = NULL;
9077 
9078 	if (source < 0) {
9079 		return kIOReturnBadArgument;
9080 	}
9081 
9082 	IOLockLock(&reserved->interruptStatisticsLock);
9083 
9084 	/*
9085 	 * We dynamically grow the statistics array, so an excessively
9086 	 * large index value has NEVER been registered.  This either
9087 	 * means our cap on the array size is too small (unlikely), or
9088 	 * that we have been passed a corrupt index (this must be passed
9089 	 * the plain index into the interrupt specifier list).
9090 	 */
9091 	if (source >= reserved->interruptStatisticsArrayCount) {
9092 		panic("removeInterruptStatistics called for index %d, which was never registered", source);
9093 	}
9094 
9095 	assert(reserved->interruptStatisticsArray);
9096 
9097 	/*
9098 	 * If there is no existing entry, we are most likely trying to
9099 	 * free an interrupt owner twice, or we have corrupted the
9100 	 * index value.
9101 	 */
9102 	value = reserved->interruptStatisticsArray[source].statistics;
9103 
9104 	if (!value) {
9105 		panic("removeInterruptStatistics called for empty index %d", source);
9106 	}
9107 
9108 	/*
9109 	 * We update the statistics, so that any delta with the reporter
9110 	 * state is not lost.
9111 	 */
9112 	interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
9113 	reserved->interruptStatisticsArray[source].statistics = NULL;
9114 	IOLockUnlock(&reserved->interruptStatisticsLock);
9115 
9116 	return kIOReturnSuccess;
9117 }
9118 
9119 IOReturn
getInterruptType(int source,int * interruptType)9120 IOService::getInterruptType(int source, int *interruptType)
9121 {
9122 	IOInterruptController *interruptController;
9123 	IOReturn              ret;
9124 
9125 	ret = lookupInterrupt(source, true, &interruptController);
9126 	if (ret != kIOReturnSuccess) {
9127 		return ret;
9128 	}
9129 
9130 	/* Return the type */
9131 	return interruptController->getInterruptType(this, source, interruptType);
9132 }
9133 
9134 IOReturn
enableInterrupt(int source)9135 IOService::enableInterrupt(int source)
9136 {
9137 	IOInterruptController *interruptController;
9138 	IOReturn              ret;
9139 
9140 	ret = lookupInterrupt(source, false, &interruptController);
9141 	if (ret != kIOReturnSuccess) {
9142 		return ret;
9143 	}
9144 
9145 	/* Enable the source */
9146 	return interruptController->enableInterrupt(this, source);
9147 }
9148 
9149 IOReturn
disableInterrupt(int source)9150 IOService::disableInterrupt(int source)
9151 {
9152 	IOInterruptController *interruptController;
9153 	IOReturn              ret;
9154 
9155 	ret = lookupInterrupt(source, false, &interruptController);
9156 	if (ret != kIOReturnSuccess) {
9157 		return ret;
9158 	}
9159 
9160 	/* Disable the source */
9161 	return interruptController->disableInterrupt(this, source);
9162 }
9163 
9164 IOReturn
causeInterrupt(int source)9165 IOService::causeInterrupt(int source)
9166 {
9167 	IOInterruptController *interruptController;
9168 	IOReturn              ret;
9169 
9170 	ret = lookupInterrupt(source, false, &interruptController);
9171 	if (ret != kIOReturnSuccess) {
9172 		return ret;
9173 	}
9174 
9175 	/* Cause an interrupt for the source */
9176 	return interruptController->causeInterrupt(this, source);
9177 }
9178 
9179 IOReturn
configureReport(IOReportChannelList * channelList,IOReportConfigureAction action,void * result,void * destination)9180 IOService::configureReport(IOReportChannelList    *channelList,
9181     IOReportConfigureAction action,
9182     void                   *result,
9183     void                   *destination)
9184 {
9185 	unsigned cnt;
9186 
9187 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9188 		if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
9189 			if (pwrMgt) {
9190 				configurePowerStatesReport(action, result);
9191 			} else {
9192 				return kIOReturnUnsupported;
9193 			}
9194 		} else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
9195 			if (pwrMgt) {
9196 				configureSimplePowerReport(action, result);
9197 			} else {
9198 				return kIOReturnUnsupported;
9199 			}
9200 		}
9201 	}
9202 
9203 	IOLockLock(&reserved->interruptStatisticsLock);
9204 
9205 	/* The array count is signed (because the interrupt indices are signed), hence the cast */
9206 	for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
9207 		if (reserved->interruptStatisticsArray[cnt].reporter) {
9208 			/*
9209 			 * If the reporter is currently associated with the statistics
9210 			 * for an event source, we may need to update the reporter.
9211 			 */
9212 			if (reserved->interruptStatisticsArray[cnt].statistics) {
9213 				interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
9214 			}
9215 
9216 			reserved->interruptStatisticsArray[cnt].reporter->configureReport(channelList, action, result, destination);
9217 		}
9218 	}
9219 
9220 	IOLockUnlock(&reserved->interruptStatisticsLock);
9221 
9222 	if (hasUserServer()) {
9223 		return _ConfigureReport(channelList, action, result, destination);
9224 	} else {
9225 		return kIOReturnSuccess;
9226 	}
9227 }
9228 
9229 IOReturn
updateReport(IOReportChannelList * channelList,IOReportUpdateAction action,void * result,void * destination)9230 IOService::updateReport(IOReportChannelList      *channelList,
9231     IOReportUpdateAction      action,
9232     void                     *result,
9233     void                     *destination)
9234 {
9235 	unsigned cnt;
9236 
9237 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9238 		if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
9239 			if (pwrMgt) {
9240 				updatePowerStatesReport(action, result, destination);
9241 			} else {
9242 				return kIOReturnUnsupported;
9243 			}
9244 		} else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
9245 			if (pwrMgt) {
9246 				updateSimplePowerReport(action, result, destination);
9247 			} else {
9248 				return kIOReturnUnsupported;
9249 			}
9250 		}
9251 	}
9252 
9253 	IOLockLock(&reserved->interruptStatisticsLock);
9254 
9255 	/* The array count is signed (because the interrupt indices are signed), hence the cast */
9256 	for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
9257 		if (reserved->interruptStatisticsArray[cnt].reporter) {
9258 			/*
9259 			 * If the reporter is currently associated with the statistics
9260 			 * for an event source, we need to update the reporter.
9261 			 */
9262 			if (reserved->interruptStatisticsArray[cnt].statistics) {
9263 				interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
9264 			}
9265 
9266 			reserved->interruptStatisticsArray[cnt].reporter->updateReport(channelList, action, result, destination);
9267 		}
9268 	}
9269 
9270 	IOLockUnlock(&reserved->interruptStatisticsLock);
9271 
9272 
9273 	if (hasUserServer()) {
9274 		return _UpdateReport(channelList, action, result, destination);
9275 	} else {
9276 		return kIOReturnSuccess;
9277 	}
9278 }
9279 
9280 uint64_t
getAuthorizationID(void)9281 IOService::getAuthorizationID( void )
9282 {
9283 	return reserved->authorizationID;
9284 }
9285 
9286 IOReturn
setAuthorizationID(uint64_t authorizationID)9287 IOService::setAuthorizationID( uint64_t authorizationID )
9288 {
9289 	OSObject * entitlement;
9290 	IOReturn status;
9291 
9292 	entitlement = IOUserClient::copyClientEntitlement( current_task(), "com.apple.private.iokit.IOServiceSetAuthorizationID" );
9293 
9294 	if (entitlement) {
9295 		if (entitlement == kOSBooleanTrue) {
9296 			reserved->authorizationID = authorizationID;
9297 
9298 			status = kIOReturnSuccess;
9299 		} else {
9300 			status = kIOReturnNotPrivileged;
9301 		}
9302 
9303 		entitlement->release();
9304 	} else {
9305 		status = kIOReturnNotPrivileged;
9306 	}
9307 
9308 	return status;
9309 }
9310 
9311 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9312 
9313 #if __LP64__
9314 OSMetaClassDefineReservedUsedX86(IOService, 0);
9315 OSMetaClassDefineReservedUsedX86(IOService, 1);
9316 OSMetaClassDefineReservedUnused(IOService, 2);
9317 OSMetaClassDefineReservedUnused(IOService, 3);
9318 OSMetaClassDefineReservedUnused(IOService, 4);
9319 OSMetaClassDefineReservedUnused(IOService, 5);
9320 OSMetaClassDefineReservedUnused(IOService, 6);
9321 OSMetaClassDefineReservedUnused(IOService, 7);
9322 #else
9323 OSMetaClassDefineReservedUsedX86(IOService, 0);
9324 OSMetaClassDefineReservedUsedX86(IOService, 1);
9325 OSMetaClassDefineReservedUsedX86(IOService, 2);
9326 OSMetaClassDefineReservedUsedX86(IOService, 3);
9327 OSMetaClassDefineReservedUsedX86(IOService, 4);
9328 OSMetaClassDefineReservedUsedX86(IOService, 5);
9329 OSMetaClassDefineReservedUsedX86(IOService, 6);
9330 OSMetaClassDefineReservedUsedX86(IOService, 7);
9331 #endif
9332 OSMetaClassDefineReservedUnused(IOService, 8);
9333 OSMetaClassDefineReservedUnused(IOService, 9);
9334 OSMetaClassDefineReservedUnused(IOService, 10);
9335 OSMetaClassDefineReservedUnused(IOService, 11);
9336 OSMetaClassDefineReservedUnused(IOService, 12);
9337 OSMetaClassDefineReservedUnused(IOService, 13);
9338 OSMetaClassDefineReservedUnused(IOService, 14);
9339 OSMetaClassDefineReservedUnused(IOService, 15);
9340 OSMetaClassDefineReservedUnused(IOService, 16);
9341 OSMetaClassDefineReservedUnused(IOService, 17);
9342 OSMetaClassDefineReservedUnused(IOService, 18);
9343 OSMetaClassDefineReservedUnused(IOService, 19);
9344 OSMetaClassDefineReservedUnused(IOService, 20);
9345 OSMetaClassDefineReservedUnused(IOService, 21);
9346 OSMetaClassDefineReservedUnused(IOService, 22);
9347 OSMetaClassDefineReservedUnused(IOService, 23);
9348 OSMetaClassDefineReservedUnused(IOService, 24);
9349 OSMetaClassDefineReservedUnused(IOService, 25);
9350 OSMetaClassDefineReservedUnused(IOService, 26);
9351 OSMetaClassDefineReservedUnused(IOService, 27);
9352 OSMetaClassDefineReservedUnused(IOService, 28);
9353 OSMetaClassDefineReservedUnused(IOService, 29);
9354 OSMetaClassDefineReservedUnused(IOService, 30);
9355 OSMetaClassDefineReservedUnused(IOService, 31);
9356 OSMetaClassDefineReservedUnused(IOService, 32);
9357 OSMetaClassDefineReservedUnused(IOService, 33);
9358 OSMetaClassDefineReservedUnused(IOService, 34);
9359 OSMetaClassDefineReservedUnused(IOService, 35);
9360 OSMetaClassDefineReservedUnused(IOService, 36);
9361 OSMetaClassDefineReservedUnused(IOService, 37);
9362 OSMetaClassDefineReservedUnused(IOService, 38);
9363 OSMetaClassDefineReservedUnused(IOService, 39);
9364 OSMetaClassDefineReservedUnused(IOService, 40);
9365 OSMetaClassDefineReservedUnused(IOService, 41);
9366 OSMetaClassDefineReservedUnused(IOService, 42);
9367 OSMetaClassDefineReservedUnused(IOService, 43);
9368 OSMetaClassDefineReservedUnused(IOService, 44);
9369 OSMetaClassDefineReservedUnused(IOService, 45);
9370 OSMetaClassDefineReservedUnused(IOService, 46);
9371 OSMetaClassDefineReservedUnused(IOService, 47);
9372