xref: /xnu-12377.81.4/iokit/Kernel/IOService.cpp (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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 		if (fSystemState == kIOServiceSystemStateAOT) {
4766 			IOPMNetworkStackWillSleepFromAOT();
4767 		}
4768 
4769 		lock();
4770 		DKLOG("arming ack timer, %u ms\n", dk_power_state_timeout_ms);
4771 		clock_interval_to_deadline(dk_power_state_timeout_ms, kMillisecondScale, &deadline);
4772 		fSystemState       = newState;
4773 		fSystemPowerAckRef = ackRef;
4774 		fSystemPowerAckTo  = ackTo;
4775 		thread_call_enter_delayed(fUserServerAckTimer, deadline);
4776 		unlock();
4777 		matchingEnd(NULL);
4778 
4779 		*pMaxWaitForReply = dk_power_state_timeout_ms * 2 * 1000;
4780 		break;
4781 
4782 	case kIOServiceSystemStateAOT:
4783 	case kIOServiceSystemStateOn:
4784 
4785 		lock();
4786 		fSystemState = newState;
4787 		unlock();
4788 		matchingEnd(NULL);
4789 		*pMaxWaitForReply = 0;
4790 		break;
4791 
4792 	default:
4793 		assert(false);
4794 		break;
4795 	}
4796 }
4797 
4798 IOReturn
systemPowerChange(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgument,vm_size_t argSize)4799 IOServicePH::systemPowerChange(
4800 	void * target,
4801 	void * refCon,
4802 	UInt32 messageType, IOService * service,
4803 	void * messageArgument, vm_size_t argSize)
4804 {
4805 	IOReturn                               ret;
4806 	IOPMSystemCapabilityChangeParameters * params;
4807 
4808 	switch (messageType) {
4809 	case kIOMessageSystemCapabilityChange:
4810 		params = (typeof params)messageArgument;
4811 
4812 		IOLog("IOServicePH::kIOMessageSystemCapabilityChange: %s%s 0x%x->0x%x\n",
4813 		    params->changeFlags & kIOPMSystemCapabilityWillChange ? "will" : "",
4814 		    params->changeFlags & kIOPMSystemCapabilityDidChange ? "did" : "",
4815 		    params->fromCapabilities,
4816 		    params->toCapabilities);
4817 
4818 		if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
4819 		    (params->fromCapabilities & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)) &&
4820 		    ((params->toCapabilities & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)) == 0)) {
4821 			systemPowerChange(kIOServiceSystemStateOffPhase1, service, params->notifyRef, &params->maxWaitForReply);
4822 			ret = kIOReturnSuccess;
4823 		} else if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
4824 		    (0 != ((params->fromCapabilities ^ params->toCapabilities)
4825 		    & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)))) {
4826 			systemPowerChange((params->toCapabilities & kIOPMSystemCapabilityCPU) ? kIOServiceSystemStateOn : kIOServiceSystemStateAOT,
4827 			    service, params->notifyRef, &params->maxWaitForReply);
4828 			ret = kIOReturnSuccess;
4829 		} else {
4830 			params->maxWaitForReply = 0;
4831 			ret                 = kIOReturnSuccess;
4832 		}
4833 		break;
4834 
4835 	default:
4836 		ret = kIOReturnUnsupported;
4837 		break;
4838 	}
4839 
4840 	return ret;
4841 }
4842 
4843 IOReturn
rootWillChangeTo(IOPMPowerFlags flags,unsigned long state)4844 IOServicePH::rootWillChangeTo(IOPMPowerFlags flags, unsigned long state)
4845 {
4846 	IOReturn ret;
4847 	uint32_t maxWaitForReply = kIOPMAckImplied;
4848 
4849 	if (kIOPMSleepCapability & flags) {
4850 		systemPowerChange(kIOServiceSystemStateOffPhase2, gIOUserResources, 0, &maxWaitForReply);
4851 	} else if (kIOPMAOTCapability & flags) {
4852 		systemPowerChange(kIOServiceSystemStateAOT, NULL, 0, &maxWaitForReply);
4853 	} else if (kIOPMPowerOn & flags) {
4854 		systemPowerChange(kIOServiceSystemStateOn, NULL, 0, &maxWaitForReply);
4855 	}
4856 	ret = maxWaitForReply;
4857 	return ret;
4858 }
4859 
4860 bool
IOSystemStateAOT(void)4861 IOSystemStateAOT(void)
4862 {
4863 	return kIOServiceSystemStateAOT == IOServicePH::fSystemState;
4864 }
4865 
4866 bool
checkPMReady(void)4867 IOServicePH::checkPMReady(void)
4868 {
4869 	bool __block ready = true;
4870 
4871 	lock();
4872 	fUserServers->iterateObjects(^bool (OSObject *obj) {
4873 		IOUserServer * us = OSDynamicCast(IOUserServer, obj);
4874 		if (us) {
4875 		        if (!us->checkPMReady()) {
4876 		                ready = false;
4877 		                return true;
4878 			}
4879 		}
4880 		return false;
4881 	});
4882 	unlock();
4883 
4884 	return ready;
4885 }
4886 
4887 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4888 
4889 #if DEBUG || DEVELOPMENT
4890 void
__patchProperties(void)4891 IOService::__patchProperties(void)
4892 {
4893 #if 0
4894 	if (!strcmp("AppleCentauriManager", getName())) {
4895 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4896 	}
4897 	if (!strcmp("CentauriControl", getName())) {
4898 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4899 	}
4900 	if (!strcmp("CentauriAlpha", getName())) {
4901 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4902 	}
4903 	if (!strcmp("CentauriBeta", getName())) {
4904 		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetwork, 64);
4905 	}
4906 #endif
4907 }
4908 #endif /* DEBUG || DEVELOPMENT */
4909 
4910 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4911 
4912 /*
4913  * Start a previously attached & probed instance,
4914  * called on exporting object instance
4915  */
4916 
4917 bool
startCandidate(IOService * service)4918 IOService::startCandidate( IOService * service )
4919 {
4920 	bool                ok;
4921 	OSObject          * obj;
4922 	OSObject          * prop;
4923 	IOUserServer      * userServer;
4924 	bool                ph;
4925 
4926 	userServer = NULL;
4927 	obj = service->copyProperty(gIOUserServerNameKey);
4928 
4929 	if (obj && (this == gIOResources)) {
4930 		ok = false;
4931 	} else {
4932 		ok = service->attach( this );
4933 	}
4934 	if (!ok) {
4935 		OSSafeReleaseNULL(obj);
4936 		return false;
4937 	}
4938 
4939 	if ((this != gIOResources) && (this != gIOUserResources)) {
4940 		// stall for any nub resources
4941 		checkResources();
4942 		// stall for any driver resources
4943 		service->checkResources();
4944 	}
4945 	ph = false;
4946 	{
4947 		OSString       * bundleID;
4948 		OSString       * serverName;
4949 		OSString       * str;
4950 		const OSSymbol * sym;
4951 		OSNumber       * serverTag;
4952 		uint64_t         entryID;
4953 		IOUserServerCheckInToken * token;
4954 		OSData         * serverDUI;
4955 
4956 		if ((serverName = OSDynamicCast(OSString, obj))) {
4957 			obj       = service->copyProperty(gIOModuleIdentifierKey);
4958 			bundleID  = OSDynamicCast(OSString, obj);
4959 			entryID   = service->getRegistryEntryID();
4960 			serverTag = OSNumber::withNumber(entryID, 64);
4961 			token     = NULL;
4962 
4963 			if (kIODKDisableDextLaunch & gIODKDebug) {
4964 				DKLOG(DKS " dext launches are disabled \n", DKN(service));
4965 				service->detach(this);
4966 				OSSafeReleaseNULL(serverName);
4967 				OSSafeReleaseNULL(obj);
4968 				OSSafeReleaseNULL(serverTag);
4969 				return false;
4970 			}
4971 
4972 			if (gIOKitWillTerminate) {
4973 				DKLOG("%s disabled in shutdown\n", serverName->getCStringNoCopy());
4974 				service->detach(this);
4975 				OSSafeReleaseNULL(serverName);
4976 				OSSafeReleaseNULL(obj);
4977 				OSSafeReleaseNULL(serverTag);
4978 				return false;
4979 			}
4980 
4981 			ph = IOServicePH::matchingStart(this);
4982 			if (!ph) {
4983 				DKLOG("%s deferred in sleep\n", serverName->getCStringNoCopy());
4984 				service->setProperty(gIOServiceMatchDeferredKey, kOSBooleanTrue);
4985 				service->detach(this);
4986 				OSSafeReleaseNULL(serverName);
4987 				OSSafeReleaseNULL(obj);
4988 				OSSafeReleaseNULL(serverTag);
4989 				return false;
4990 			}
4991 
4992 			prop = service->copyProperty(gIOUserClassKey);
4993 			str = OSDynamicCast(OSString, prop);
4994 			if (str) {
4995 				service->setName(str);
4996 			}
4997 			OSSafeReleaseNULL(prop);
4998 
4999 			sym = OSSymbol::withString(serverName);
5000 			bool reuse = service->propertyExists(gIOUserServerOneProcessKey);
5001 			bool reuseRequired = false;
5002 			if (propertyExists(gIOUserServerNameKey)) {
5003 				reuseRequired = reuse && service->propertyHasValue(gIOUserServerNameKey, getProperty(gIOUserServerNameKey));
5004 			}
5005 			serverDUI = OSDynamicCast(OSData, service->getProperty(kOSBundleDextUniqueIdentifierKey));
5006 			userServer = IOUserServer::launchUserServer(this, bundleID, sym, serverTag, reuse, &token, serverDUI);
5007 			OSSafeReleaseNULL(sym);
5008 			OSSafeReleaseNULL(serverTag);
5009 			OSSafeReleaseNULL(serverName);
5010 			if (userServer) {
5011 				DKLOG(DKS " using existing server " DKS "\n", DKN(service), DKN(userServer));
5012 			} else if (!reuseRequired && token != NULL) {
5013 				const OSSymbol * tokenServerName = token->copyServerName();
5014 				OSNumber * tokenServerTag = token->copyServerTag();
5015 				assert(tokenServerName && tokenServerTag);
5016 				DKLOG(DKS " waiting for server %s-%llx\n", DKN(service), tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue());
5017 				userServer = __WAITING_FOR_USER_SERVER__(token);
5018 				OSSafeReleaseNULL(tokenServerName);
5019 				OSSafeReleaseNULL(tokenServerTag);
5020 			} else if (reuseRequired) {
5021 				DKLOG(DKS " failed to reuse server\n", DKN(service));
5022 			} else {
5023 				DKLOG(DKS " failed to launch server\n", DKN(service));
5024 			}
5025 
5026 
5027 			if (!userServer) {
5028 				service->detach(this);
5029 				IOServicePH::matchingEnd(this);
5030 				OSSafeReleaseNULL(obj);
5031 
5032 				if (token != NULL) {
5033 					DKLOG(DKS " user server timeout\n", DKN(service));
5034 #if DEVELOPMENT || DEBUG
5035 					driverkit_checkin_timed_out = mach_absolute_time();
5036 #endif
5037 				}
5038 
5039 				OSSafeReleaseNULL(token);
5040 				return false;
5041 			}
5042 
5043 			if (token && !(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
5044 				if (!userServer->serviceMatchesCheckInToken(token)) {
5045 					OSSafeReleaseNULL(token);
5046 					service->detach(this);
5047 					IOServicePH::matchingEnd(this);
5048 					OSSafeReleaseNULL(obj);
5049 					userServer->exit("Check In Token verification failed");
5050 					userServer->release();
5051 					return false;
5052 				}
5053 			}
5054 			OSSafeReleaseNULL(token);
5055 			OSSafeReleaseNULL(obj);
5056 
5057 			if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
5058 				if (!userServer->checkEntitlements(this, service)) {
5059 					service->detach(this);
5060 					IOServicePH::matchingEnd(this);
5061 					userServer->exit("Entitlements check failed");
5062 					userServer->release();
5063 					return false;
5064 				}
5065 			}
5066 #if !XNU_TARGET_OS_OSX && !(DEVELOPMENT || DEBUG)
5067 			// Prevent third party drivers from matching IOUserResources/IOResources, except when signed for development
5068 			if (!userServer->isPlatformDriver() &&
5069 			    userServer->getCSValidationCategory() != CS_VALIDATION_CATEGORY_DEVELOPMENT
5070 			    && (this == gIOUserResources || this == gIOResources)) {
5071 				service->detach(this);
5072 				IOServicePH::matchingEnd(this);
5073 				userServer->exit("Third party driver may only match real hardware");
5074 				userServer->release();
5075 				return false;
5076 			}
5077 #endif /* !XNU_TARGET_OS_OSX && !(DEVELOPMENT || DEBUG) */
5078 
5079 			userServer->serviceAttach(service, this);
5080 		} else {
5081 			OSSafeReleaseNULL(obj);
5082 		}
5083 	}
5084 
5085 	AbsoluteTime startTime;
5086 	AbsoluteTime endTime;
5087 	UInt64       nano;
5088 	bool recordTime = (kIOLogStart & gIOKitDebug) != 0;
5089 
5090 	if (recordTime) {
5091 		clock_get_uptime(&startTime);
5092 	}
5093 
5094 #if DEBUG || DEVELOPMENT
5095 	service->__patchProperties();
5096 #endif /* DEBUG || DEVELOPMENT */
5097 
5098 	ok = service->start(this);
5099 
5100 	if (recordTime) {
5101 		clock_get_uptime(&endTime);
5102 
5103 		if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
5104 			SUB_ABSOLUTETIME(&endTime, &startTime);
5105 			absolutetime_to_nanoseconds(endTime, &nano);
5106 			if (nano > 500000000ULL) {
5107 				IOLog("%s[0x%qx]::start took %ld ms\n", service->getName(), service->getRegistryEntryID(), (long)(UInt32)(nano / 1000000ULL));
5108 			}
5109 		}
5110 	}
5111 	if (userServer) {
5112 		userServer->serviceStarted(service, this, ok);
5113 		userServer->release();
5114 	}
5115 
5116 	if (ok) {
5117 		IOInstallServiceSleepPlatformActions(service);
5118 #if 00
5119 		if (!strcmp("XHC1", getName())) {
5120 			service->setProperty(gIOPrimaryDriverTerminateOptionsKey, kOSBooleanTrue);
5121 		}
5122 #endif
5123 	}
5124 
5125 	if (!ok) {
5126 		service->detach( this );
5127 	}
5128 
5129 	if (ph) {
5130 		IOServicePH::matchingEnd(this);
5131 	}
5132 
5133 	return ok;
5134 }
5135 
5136 void
publishResource(const char * key,OSObject * value)5137 IOService::publishResource( const char * key, OSObject * value )
5138 {
5139 	const OSSymbol *    sym;
5140 
5141 	if ((sym = OSSymbol::withCString( key))) {
5142 		publishResource( sym, value);
5143 		sym->release();
5144 	}
5145 }
5146 
5147 void
publishResource(const OSSymbol * key,OSObject * value)5148 IOService::publishResource( const OSSymbol * key, OSObject * value )
5149 {
5150 	if (NULL == value) {
5151 		value = (OSObject *) gIOServiceKey;
5152 	}
5153 
5154 	gIOResources->setProperty( key, value);
5155 
5156 	if (IORecursiveLockHaveLock( gNotificationLock)) {
5157 		return;
5158 	}
5159 
5160 	gIOResourceGenerationCount++;
5161 	gIOResources->registerService();
5162 }
5163 
5164 void
publishUserResource(const OSSymbol * key,OSObject * value)5165 IOService::publishUserResource( const OSSymbol * key, OSObject * value )
5166 {
5167 	if (NULL == value) {
5168 		value = (OSObject *) gIOServiceKey;
5169 	}
5170 
5171 	gIOUserResources->setProperty( key, value);
5172 
5173 	if (IORecursiveLockHaveLock( gNotificationLock)) {
5174 		return;
5175 	}
5176 
5177 	gIOResourceGenerationCount++;
5178 	gIOUserResources->registerService();
5179 }
5180 
5181 bool
addNeededResource(const char * key)5182 IOService::addNeededResource( const char * key )
5183 {
5184 	OSObject *  resourcesProp;
5185 	OSSet *     set;
5186 	OSString *  newKey;
5187 	bool ret;
5188 
5189 	resourcesProp = copyProperty( gIOResourceMatchKey );
5190 	if (!resourcesProp) {
5191 		return false;
5192 	}
5193 
5194 	newKey = OSString::withCString( key );
5195 	if (!newKey) {
5196 		resourcesProp->release();
5197 		return false;
5198 	}
5199 
5200 	set = OSDynamicCast( OSSet, resourcesProp );
5201 	if (!set) {
5202 		set = OSSet::withCapacity( 1 );
5203 		set->setObject( resourcesProp );
5204 	} else {
5205 		set->retain();
5206 	}
5207 
5208 	set->setObject( newKey );
5209 	newKey->release();
5210 	ret = setProperty( gIOResourceMatchKey, set );
5211 	set->release();
5212 	resourcesProp->release();
5213 
5214 	return ret;
5215 }
5216 
5217 bool
checkResource(OSObject * matching)5218 IOService::checkResource( OSObject * matching )
5219 {
5220 	OSString *          str;
5221 	OSDictionary *      table;
5222 
5223 	if ((str = OSDynamicCast( OSString, matching ))) {
5224 		if (gIOResources->getProperty( str )) {
5225 			return true;
5226 		}
5227 	}
5228 
5229 	if (str) {
5230 		table = resourceMatching( str );
5231 	} else if ((table = OSDynamicCast( OSDictionary, matching ))) {
5232 		table->retain();
5233 	} else {
5234 		IOLog("%s: Can't match using: %s\n", getName(),
5235 		    matching->getMetaClass()->getClassName());
5236 		/* false would stall forever */
5237 		return true;
5238 	}
5239 
5240 	if (gIOKitDebug & kIOLogConfig) {
5241 		LOG("config(%p): stalling %s\n", IOSERVICE_OBFUSCATE(IOThreadSelf()), getName());
5242 	}
5243 
5244 	waitForService( table );
5245 
5246 	if (gIOKitDebug & kIOLogConfig) {
5247 		LOG("config(%p): waking\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
5248 	}
5249 
5250 	return true;
5251 }
5252 
5253 bool
checkResources(void)5254 IOService::checkResources( void )
5255 {
5256 	OSObject *          resourcesProp;
5257 	OSSet *             set;
5258 	OSObject *          obj;
5259 	OSIterator *        iter;
5260 	bool                ok;
5261 
5262 	resourcesProp = copyProperty( gIOResourceMatchKey );
5263 	if (NULL == resourcesProp) {
5264 		return true;
5265 	}
5266 
5267 	if ((set = OSDynamicCast( OSSet, resourcesProp ))) {
5268 		iter = OSCollectionIterator::withCollection( set );
5269 		ok = (NULL != iter);
5270 		while (ok && (obj = iter->getNextObject())) {
5271 			ok = checkResource( obj );
5272 		}
5273 		if (iter) {
5274 			iter->release();
5275 		}
5276 	} else {
5277 		ok = checkResource( resourcesProp );
5278 	}
5279 
5280 	OSSafeReleaseNULL(resourcesProp);
5281 
5282 	return ok;
5283 }
5284 
5285 
5286 void
configThread(const char * name)5287 _IOConfigThread::configThread( const char * name )
5288 {
5289 	_IOConfigThread *   inst;
5290 
5291 	do {
5292 		if (!(inst = new _IOConfigThread)) {
5293 			continue;
5294 		}
5295 		if (!inst->init()) {
5296 			continue;
5297 		}
5298 		thread_t thread;
5299 		if (KERN_SUCCESS != kernel_thread_start(&_IOConfigThread::main, inst, &thread)) {
5300 			continue;
5301 		}
5302 
5303 		char threadName[MAXTHREADNAMESIZE];
5304 		snprintf(threadName, sizeof(threadName), "IOConfigThread_'%s'", name);
5305 		thread_set_thread_name(thread, threadName);
5306 		thread_deallocate(thread);
5307 
5308 		return;
5309 	} while (false);
5310 
5311 	if (inst) {
5312 		inst->release();
5313 	}
5314 
5315 	return;
5316 }
5317 
5318 /*
5319  * To support driver replacement of boot matched drivers later in boot, drivers can
5320  * opt-in to be being terminated if a non-boot driver matches their provider, by
5321  * setting the gIOPrimaryDriverTerminateOptionsKey property. The driver providing the
5322  * root disk media may not be terminated.
5323  * IOMedia objects are hidden from user space until all drivers are available, but any
5324  * associated with the root disk must be published immediately.
5325  */
5326 
5327 struct FindRootMediaContext {
5328 	OSArray   * services;
5329 	IOService * parent;
5330 };
5331 
5332 bool
hasParent(IOService * parent)5333 IOService::hasParent(IOService * parent)
5334 {
5335 	IOService * service;
5336 
5337 	for (service = this;
5338 	    service && (service != parent);
5339 	    service = service->getProvider()) {
5340 	}
5341 
5342 	return service != NULL;
5343 }
5344 
5345 bool
publishHiddenMediaApplier(const OSObject * entry,void * context)5346 IOService::publishHiddenMediaApplier(const OSObject * entry, void * context)
5347 {
5348 	FindRootMediaContext * ctx     = (typeof(ctx))context;
5349 	IOService            * service = (typeof(service))entry;
5350 
5351 	do {
5352 		if (ctx->parent && !service->hasParent(ctx->parent)) {
5353 			break;
5354 		}
5355 		if (ctx->services) {
5356 			ctx->services->setObject(service);
5357 		} else {
5358 			ctx->services  = OSArray::withObjects((const OSObject **) &service, 1);
5359 			assert(ctx->services);
5360 		}
5361 	} while (false);
5362 
5363 	return false;
5364 }
5365 
5366 // publish to user space any hidden IOMedia under the 'parent' object, or all
5367 // if 'parent' is NULL
5368 
5369 void
publishHiddenMedia(IOService * parent)5370 IOService::publishHiddenMedia(IOService * parent)
5371 {
5372 	const OSMetaClass * iomediaClass;
5373 	bool                wasHiding;
5374 
5375 	iomediaClass = OSMetaClass::getMetaClassWithName(gIOMediaKey);
5376 	assert(iomediaClass);
5377 
5378 	LOCKWRITENOTIFY();
5379 	wasHiding = gIOServiceHideIOMedia;
5380 	if (wasHiding && !parent) {
5381 		gIOServiceHideIOMedia = false;
5382 	}
5383 	UNLOCKNOTIFY();
5384 
5385 	FindRootMediaContext ctx = { .services = NULL, .parent = parent };
5386 
5387 	if (wasHiding) {
5388 		iomediaClass->applyToInstances(publishHiddenMediaApplier, &ctx);
5389 	}
5390 	if (ctx.services) {
5391 		unsigned int idx, notiIdx;
5392 		IOService * service;
5393 		OSArray   * notifiers[3] = {};
5394 
5395 		for (idx = 0; (service = (IOService *) ctx.services->getObject(idx)); idx++) {
5396 			service->lockForArbitration(true);
5397 			if (!(kIOServiceUserInvisibleMatchState & service->__state[0])) {
5398 				service->unlockForArbitration();
5399 				continue;
5400 			}
5401 			service->__state[0] &= ~kIOServiceUserInvisibleMatchState;
5402 			service->__state[1] |= kIOServiceUserUnhidden;
5403 			notifiers[0] = service->copyNotifiers(gIOFirstPublishNotification, 0, 0xffffffff);
5404 			if (kIOServiceMatchedState & service->__state[0]) {
5405 				notifiers[1] = service->copyNotifiers(gIOMatchedNotification, 0, 0xffffffff);
5406 			}
5407 			if (kIOServiceFirstMatchState & service->__state[0]) {
5408 				notifiers[2] = service->copyNotifiers(gIOFirstMatchNotification, 0, 0xffffffff);
5409 			}
5410 			service->unlockForArbitration();
5411 			for (notiIdx = 0; notiIdx < 3; notiIdx++) {
5412 				service->invokeNotifiers(&notifiers[notiIdx]);
5413 			}
5414 		}
5415 		OSSafeReleaseNULL(ctx.services);
5416 	}
5417 }
5418 
5419 // Find the block storage driver providing the root disk, or NULL if not booting from
5420 // a block device
5421 
5422 void
setRootMedia(IOService * root)5423 IOService::setRootMedia(IOService * root)
5424 {
5425 	const OSMetaClass * ioblockstoragedriverClass;
5426 	bool unhide;
5427 
5428 	ioblockstoragedriverClass = OSMetaClass::getMetaClassWithName(gIOBlockStorageDriverKey);
5429 	assert(ioblockstoragedriverClass);
5430 
5431 	while (root) {
5432 		if (root->metaCast(ioblockstoragedriverClass)) {
5433 			break;
5434 		}
5435 		root = root->getProvider();
5436 	}
5437 
5438 	LOCKWRITENOTIFY();
5439 	unhide = (kIOServiceRootMediaParentInvalid == gIOServiceRootMediaParent);
5440 	if (unhide) {
5441 		gIOServiceRootMediaParent = root;
5442 	}
5443 	UNLOCKNOTIFY();
5444 
5445 	if (unhide) {
5446 		if (root) {
5447 			root->addPMDriverClass(kIOPMDriverClassStorage);
5448 		}
5449 		publishHiddenMedia(root);
5450 	}
5451 }
5452 
5453 // Check if the driver may be terminated when a later driver could be used instead
5454 
5455 bool
canTerminateForReplacement(IOService * client)5456 IOService::canTerminateForReplacement(IOService * client)
5457 {
5458 	IOService * parent;
5459 
5460 	assert(kIOServiceRootMediaParentInvalid != gIOServiceRootMediaParent);
5461 
5462 	if (!gIOServiceHideIOMedia) {
5463 		return false;
5464 	}
5465 	if (!client->propertyExists(gIOPrimaryDriverTerminateOptionsKey)) {
5466 		return false;
5467 	}
5468 	if (!gIOServiceRootMediaParent) {
5469 		return false;
5470 	}
5471 	parent = gIOServiceRootMediaParent;
5472 	while (parent && (parent != client)) {
5473 		parent = parent->getProvider();
5474 	}
5475 	if (parent) {
5476 		IOLog("Can't replace primary matched driver on root media %s-0x%qx\n",
5477 		    client->getName(), client->getRegistryEntryID());
5478 		return false;
5479 	}
5480 	return true;
5481 }
5482 
5483 void
doServiceMatch(IOOptionBits options)5484 IOService::doServiceMatch( IOOptionBits options )
5485 {
5486 	_IOServiceNotifier * notify;
5487 	OSIterator *        iter;
5488 	OSOrderedSet *      matches;
5489 	OSArray *           resourceKeys = NULL;
5490 	SInt32              catalogGeneration;
5491 	bool                keepGuessing = true;
5492 	bool                reRegistered = true;
5493 	bool                didRegister;
5494 	OSArray *           notifiers[2] = {NULL};
5495 
5496 //    job->nub->deliverNotification( gIOPublishNotification,
5497 //                              kIOServiceRegisteredState, 0xffffffff );
5498 
5499 	while (keepGuessing) {
5500 		matches = gIOCatalogue->findDrivers( this, &catalogGeneration );
5501 		// the matches list should always be created by findDrivers()
5502 		if (matches) {
5503 			lockForArbitration();
5504 			if (0 == (__state[0] & kIOServiceFirstPublishState)) {
5505 				getMetaClass()->addInstance(this);
5506 				notifiers[0] = copyNotifiers(gIOFirstPublishNotification,
5507 				    kIOServiceFirstPublishState, 0xffffffff );
5508 			}
5509 			LOCKREADNOTIFY();
5510 			__state[1] &= ~kIOServiceNeedConfigState;
5511 			__state[1] |= kIOServiceConfigState | kIOServiceConfigRunning;
5512 			didRegister = (0 == (kIOServiceRegisteredState & __state[0]));
5513 			__state[0] |= kIOServiceRegisteredState;
5514 
5515 			if (gIOServiceHideIOMedia
5516 			    && metaCast(gIOMediaKey)
5517 			    && !(kIOServiceUserUnhidden & __state[1])
5518 			    && gIOServiceRootMediaParent
5519 			    && !hasParent(gIOServiceRootMediaParent)
5520 			    && propertyExists(gIOPrimaryDriverTerminateOptionsKey, gIOServicePlane)) {
5521 				__state[0] |= kIOServiceUserInvisibleMatchState;
5522 			}
5523 
5524 			keepGuessing &= (0 == (__state[0] & kIOServiceInactiveState));
5525 			if (reRegistered && keepGuessing) {
5526 				iter = OSCollectionIterator::withCollection((OSOrderedSet *)
5527 				    gNotifications->getObject( gIOPublishNotification ));
5528 				if (iter) {
5529 					while ((notify = (_IOServiceNotifier *)
5530 					    iter->getNextObject())) {
5531 						if (matchPassive(notify->matching, 0)
5532 						    && (kIOServiceNotifyEnable & notify->state)) {
5533 							matches->setObject( notify );
5534 						}
5535 					}
5536 					iter->release();
5537 				}
5538 			}
5539 
5540 			UNLOCKNOTIFY();
5541 			unlockForArbitration();
5542 			invokeNotifiers(&notifiers[0]);
5543 			if (keepGuessing && matches->getCount() && (kIOReturnSuccess == getResources())) {
5544 				if ((this == gIOResources) || (this == gIOUserResources)) {
5545 					if (resourceKeys) {
5546 						resourceKeys->release();
5547 					}
5548 					resourceKeys = copyPropertyKeys();
5549 				}
5550 				probeCandidates( matches );
5551 			} else {
5552 				matches->release();
5553 			}
5554 		}
5555 
5556 		lockForArbitration();
5557 		reRegistered = (0 != (__state[1] & kIOServiceNeedConfigState));
5558 		keepGuessing =
5559 		    (reRegistered || (catalogGeneration !=
5560 		    gIOCatalogue->getGenerationCount()))
5561 		    && (0 == (__state[0] & kIOServiceInactiveState));
5562 
5563 		if (keepGuessing) {
5564 			unlockForArbitration();
5565 		}
5566 	}
5567 
5568 	if ((0 == (__state[0] & kIOServiceInactiveState))
5569 	    && (0 == (__state[1] & kIOServiceModuleStallState))) {
5570 		if (resourceKeys) {
5571 			setProperty(gIOResourceMatchedKey, resourceKeys);
5572 		}
5573 
5574 		notifiers[0] = copyNotifiers(gIOMatchedNotification,
5575 		    kIOServiceMatchedState, 0xffffffff);
5576 		if (0 == (__state[0] & kIOServiceFirstMatchState)) {
5577 			notifiers[1] = copyNotifiers(gIOFirstMatchNotification,
5578 			    kIOServiceFirstMatchState, 0xffffffff);
5579 		}
5580 	}
5581 
5582 	__state[1] &= ~kIOServiceConfigRunning;
5583 	unlockForArbitration();
5584 
5585 	if (resourceKeys) {
5586 		resourceKeys->release();
5587 	}
5588 
5589 	invokeNotifiers(&notifiers[0]);
5590 	invokeNotifiers(&notifiers[1]);
5591 
5592 	lockForArbitration();
5593 	__state[1] &= ~kIOServiceConfigState;
5594 	scheduleTerminatePhase2();
5595 
5596 	_adjustBusy(-1, /*unlock*/ true);
5597 	// does	unlockForArbitration();
5598 }
5599 
5600 UInt32
_adjustBusy(SInt32 delta)5601 IOService::_adjustBusy(SInt32 delta)
5602 {
5603 	return _adjustBusy(delta, false);
5604 }
5605 
5606 UInt32
_adjustBusy(SInt32 delta,bool unlock)5607 IOService::_adjustBusy(SInt32 delta, bool unlock)
5608 {
5609 	IOService * next;
5610 	IOService * nextProvider;
5611 	UInt32      count;
5612 	UInt32      result;
5613 	bool        wasQuiet, nowQuiet, needWake;
5614 
5615 	next = this;
5616 	result = __state[1] & kIOServiceBusyStateMask;
5617 
5618 	if (delta) {
5619 		do {
5620 			if (next != this) {
5621 				next->lockForArbitration();
5622 			}
5623 			count = next->__state[1] & kIOServiceBusyStateMask;
5624 			wasQuiet = (0 == count);
5625 			if (((delta < 0) && wasQuiet) || ((delta > 0) && (kIOServiceBusyMax == count))) {
5626 				OSReportWithBacktrace("%s: bad busy count (%d,%d)\n", next->getName(), (uint32_t)count, (int)delta);
5627 			} else {
5628 				count += delta;
5629 			}
5630 			next->__state[1] = (next->__state[1] & ~kIOServiceBusyStateMask) | count;
5631 			nowQuiet = (0 == count);
5632 			needWake = (0 != (kIOServiceBusyWaiterState & next->__state[1]));
5633 
5634 			if (needWake) {
5635 				next->__state[1] &= ~kIOServiceBusyWaiterState;
5636 				IOLockLock( gIOServiceBusyLock );
5637 				thread_wakeup((event_t) next);
5638 				IOLockUnlock( gIOServiceBusyLock );
5639 			}
5640 			if (wasQuiet || nowQuiet) {
5641 				nextProvider = next->getProvider();
5642 				if (nextProvider) {
5643 					nextProvider->retain();
5644 				}
5645 			}
5646 			if ((next != this) || unlock) {
5647 				next->unlockForArbitration();
5648 			}
5649 
5650 			if ((wasQuiet || nowQuiet)) {
5651 				uint64_t regID = next->getRegistryEntryID();
5652 				IOServiceTrace(
5653 					((wasQuiet /*nowBusy*/) ? IOSERVICE_BUSY : IOSERVICE_NONBUSY),
5654 					(uintptr_t) regID,
5655 					(uintptr_t) (regID >> 32),
5656 					(uintptr_t) next,
5657 					0);
5658 
5659 				if (wasQuiet) {
5660 					next->__timeBusy = mach_absolute_time();
5661 				} else {
5662 					next->__accumBusy += mach_absolute_time() - next->__timeBusy;
5663 					next->__timeBusy = 0;
5664 				}
5665 
5666 				MessageClientsContext context;
5667 
5668 				context.service  = next;
5669 				context.type     = kIOMessageServiceBusyStateChange;
5670 				context.argument = (void *) wasQuiet; /*nowBusy*/
5671 				context.argSize  = 0;
5672 
5673 				applyToInterestNotifiers( next, gIOBusyInterest,
5674 				    &messageClientsApplier, &context );
5675 
5676 #if !NO_KEXTD
5677 				if (nowQuiet && (next == gIOServiceRoot)) {
5678 					if (gIOServiceHideIOMedia) {
5679 						publishHiddenMedia(NULL);
5680 					}
5681 
5682 					OSKext::considerUnloads();
5683 					IOServiceTrace(IOSERVICE_REGISTRY_QUIET, 0, 0, 0, 0);
5684 				}
5685 #endif
5686 			}
5687 
5688 			delta = nowQuiet ? -1 : +1;
5689 			if (next != this) {
5690 				next->release();
5691 			}
5692 			next = nextProvider;
5693 			nextProvider = NULL;
5694 		} while ((wasQuiet || nowQuiet) && next);
5695 	}
5696 
5697 	return result;
5698 }
5699 
5700 void
adjustBusy(SInt32 delta)5701 IOService::adjustBusy( SInt32 delta )
5702 {
5703 	lockForArbitration();
5704 	_adjustBusy( delta );
5705 	unlockForArbitration();
5706 }
5707 
5708 uint64_t
getAccumulatedBusyTime(void)5709 IOService::getAccumulatedBusyTime( void )
5710 {
5711 	uint64_t accumBusy = __accumBusy;
5712 	uint64_t timeBusy = __timeBusy;
5713 	uint64_t nano;
5714 
5715 	do{
5716 		accumBusy = __accumBusy;
5717 		timeBusy  = __timeBusy;
5718 		if (timeBusy) {
5719 			accumBusy += mach_absolute_time() - timeBusy;
5720 		}
5721 	}while (timeBusy != __timeBusy);
5722 
5723 	absolutetime_to_nanoseconds(*(AbsoluteTime *)&accumBusy, &nano);
5724 
5725 	return nano;
5726 }
5727 
5728 UInt32
getBusyState(void)5729 IOService::getBusyState( void )
5730 {
5731 	return __state[1] & kIOServiceBusyStateMask;
5732 }
5733 
5734 IOReturn
waitForState(UInt32 mask,UInt32 value,mach_timespec_t * timeout)5735 IOService::waitForState( UInt32 mask, UInt32 value,
5736     mach_timespec_t * timeout )
5737 {
5738 	panic("waitForState");
5739 	return kIOReturnUnsupported;
5740 }
5741 
5742 IOReturn
waitForState(UInt32 mask,UInt32 value,uint64_t timeout)5743 IOService::waitForState( UInt32 mask, UInt32 value,
5744     uint64_t timeout )
5745 {
5746 	bool            wait, done;
5747 	int             waitResult = THREAD_AWAKENED;
5748 	bool            computeDeadline = true;
5749 	AbsoluteTime    abstime;
5750 
5751 	do {
5752 		lockForArbitration();
5753 		IOLockLock( gIOServiceBusyLock );
5754 		done = (value == (__state[1] & mask));
5755 		wait = (waitResult != THREAD_TIMED_OUT) && !done;
5756 		if (wait) {
5757 			__state[1] |= kIOServiceBusyWaiterState;
5758 			unlockForArbitration();
5759 			if (timeout != UINT64_MAX) {
5760 				if (computeDeadline) {
5761 					AbsoluteTime  nsinterval;
5762 					nanoseconds_to_absolutetime(timeout, &nsinterval );
5763 					clock_absolutetime_interval_to_deadline(nsinterval, &abstime);
5764 					computeDeadline = false;
5765 				}
5766 				assert_wait_deadline((event_t)this, THREAD_UNINT, __OSAbsoluteTime(abstime));
5767 			} else {
5768 				assert_wait((event_t)this, THREAD_UNINT );
5769 			}
5770 		} else {
5771 			unlockForArbitration();
5772 		}
5773 		IOLockUnlock( gIOServiceBusyLock );
5774 		if (wait) {
5775 			waitResult = thread_block(THREAD_CONTINUE_NULL);
5776 		}
5777 	} while (wait);
5778 
5779 	if (done) {
5780 		return kIOReturnSuccess;
5781 	} else {
5782 		return kIOReturnTimeout;
5783 	}
5784 }
5785 
5786 IOReturn
waitQuietWithOptions(uint64_t timeout,IOOptionBits options)5787 IOService::waitQuietWithOptions( uint64_t timeout, IOOptionBits options )
5788 {
5789 	IOReturn ret;
5790 	uint32_t loops, timeoutExtensions;
5791 	char *   busyEntriesString = NULL;
5792 	char *   panicString = NULL;
5793 	size_t   busyEntriesStringLen;
5794 	size_t   panicStringLen;
5795 	uint64_t time;
5796 	uint64_t nano;
5797 	bool     pendingRequests;
5798 	bool     registryRootBusy;
5799 	bool     multipleEntries;
5800 	bool     dopanic = false;
5801 
5802 	enum { kIOServiceBusyTimeoutExtensionsMax = 8 };
5803 #if KASAN
5804 	/*
5805 	 * On kasan kernels, everything takes longer, so double the number of
5806 	 * timeout extensions. This should help with issues like 41259215
5807 	 * where WindowServer was timing out waiting for kextd to get all the
5808 	 * kasan kexts loaded and started.
5809 	 *
5810 	 * On legacy/x86 systems give a bit more time since we may be
5811 	 * booting from a HDD.
5812 	 */
5813 	enum { kTimeoutExtensions = 8 };
5814 #define WITH_IOWAITQUIET_EXTENSIONS 1
5815 #elif defined(__x86_64__)
5816 	enum { kTimeoutExtensions = 4 };
5817 #define WITH_IOWAITQUIET_EXTENSIONS 1
5818 #elif  defined(XNU_TARGET_OS_OSX)
5819 	enum { kTimeoutExtensions = 1 };
5820 #define WITH_IOWAITQUIET_EXTENSIONS 1
5821 #else
5822 	enum { kTimeoutExtensions = 1 };
5823 #define WITH_IOWAITQUIET_EXTENSIONS 0
5824 #endif
5825 
5826 	timeoutExtensions = kTimeoutExtensions;
5827 	time = mach_absolute_time();
5828 	pendingRequests = false;
5829 	for (loops = 0; loops < timeoutExtensions; loops++) {
5830 		ret = waitForState( kIOServiceBusyStateMask, 0, timeout );
5831 
5832 		if (loops && (kIOReturnSuccess == ret)) {
5833 			time = mach_absolute_time() - time;
5834 			absolutetime_to_nanoseconds(*(AbsoluteTime *)&time, &nano);
5835 			IOLog("busy extended ok[%d], (%llds, %llds)\n",
5836 			    loops, timeout / 1000000000ULL, nano / 1000000000ULL);
5837 			break;
5838 		} else if (kIOReturnTimeout != ret) {
5839 			break;
5840 		} else if (timeout < (41ull * NSEC_PER_SEC)) {
5841 			break;
5842 		}
5843 
5844 		{
5845 			IORegistryIterator * iter;
5846 			OSOrderedSet       * set;
5847 			OSOrderedSet       * leaves;
5848 			IOService          * next;
5849 			IOService          * nextParent;
5850 			char               * s;
5851 			size_t               l;
5852 			size_t               busyEntriesStringRemaining;
5853 
5854 			busyEntriesStringLen = 256;
5855 			panicStringLen = 256;
5856 			if (!busyEntriesString) {
5857 				busyEntriesString = IONewZeroData(char, busyEntriesStringLen);
5858 				assert(busyEntriesString != NULL);
5859 			}
5860 			if (!panicString) {
5861 				panicString = IONewZeroData(char, panicStringLen);
5862 				assert(panicString != NULL);
5863 			}
5864 
5865 			set = NULL;
5866 			pendingRequests = OSKext::pendingIOKitDaemonRequests();
5867 			iter = IORegistryIterator::iterateOver(this, gIOServicePlane, kIORegistryIterateRecursively);
5868 			leaves = OSOrderedSet::withCapacity(4);
5869 			if (iter) {
5870 				set = iter->iterateAll();
5871 			}
5872 			if (leaves && set) {
5873 				busyEntriesString[0] = panicString[0] = 0;
5874 				set->setObject(this);
5875 				while ((next = (IOService *) set->getLastObject())) {
5876 					if (next->getBusyState()) {
5877 						if (kIOServiceModuleStallState & next->__state[1]) {
5878 							pendingRequests = true;
5879 						}
5880 #if defined(XNU_TARGET_OS_OSX)
5881 						OSObject * prop;
5882 						if ((prop = next->copyProperty(kIOServiceBusyTimeoutExtensionsKey, gIOServicePlane))) {
5883 							OSNumber * num;
5884 							uint32_t   value;
5885 							if ((num = OSDynamicCast(OSNumber, prop))) {
5886 								value = num->unsigned32BitValue();
5887 								if (value
5888 								    && (value <= kIOServiceBusyTimeoutExtensionsMax)
5889 								    && (value > timeoutExtensions)) {
5890 									timeoutExtensions = value;
5891 								}
5892 							}
5893 							OSSafeReleaseNULL(prop);
5894 						}
5895 #endif /* defined(XNU_TARGET_OS_OSX) */
5896 						leaves->setObject(next);
5897 						nextParent = next;
5898 						while ((nextParent = nextParent->getProvider())) {
5899 							set->removeObject(nextParent);
5900 							leaves->removeObject(nextParent);
5901 						}
5902 					}
5903 					set->removeObject(next);
5904 				}
5905 				registryRootBusy = leaves->getCount() == 1 && leaves->getObject(0) == getServiceRoot();
5906 				multipleEntries = leaves->getCount() > 1;
5907 				s = busyEntriesString;
5908 				busyEntriesStringRemaining = busyEntriesStringLen;
5909 
5910 				if (registryRootBusy) {
5911 					snprintf(s, busyEntriesStringRemaining, "registry root held busy, " kIOKitDaemonName " %s checked in", OSKext::iokitDaemonActive() ? "has" : "has not");
5912 				} else {
5913 					while ((next = (IOService *) leaves->getLastObject())) {
5914 						l = snprintf(s, busyEntriesStringRemaining, "%s'%s' (%x,%x)", ((s == busyEntriesString) ? "" : ", "), next->getName(), (uint32_t)next->__state[0], (uint32_t)next->__state[1]);
5915 						if (l >= busyEntriesStringRemaining) {
5916 							break;
5917 						}
5918 						s += l;
5919 						busyEntriesStringRemaining -= l;
5920 						leaves->removeObject(next);
5921 					}
5922 				}
5923 			}
5924 			OSSafeReleaseNULL(leaves);
5925 			OSSafeReleaseNULL(set);
5926 			OSSafeReleaseNULL(iter);
5927 		}
5928 
5929 		dopanic = (kIOWaitQuietPanics & gIOKitDebug) && (options & kIOWaitQuietPanicOnFailure) && !gIOKitWillTerminate;
5930 #if WITH_IOWAITQUIET_EXTENSIONS
5931 		dopanic = (dopanic && (loops >= (timeoutExtensions - 1)));
5932 #endif
5933 		assert(panicString != NULL);
5934 		if (multipleEntries) {
5935 			snprintf(panicString, panicStringLen,
5936 			    "%s[%d], (%llds): multiple entries holding the registry busy, IOKit termination queue depth %u: %s",
5937 			    pendingRequests ? "IOKit Daemon (" kIOKitDaemonName ") stall" : "busy timeout",
5938 			    loops, timeout / 1000000000ULL,
5939 			    (uint32_t)gIOTerminateWork,
5940 			    busyEntriesString ? busyEntriesString : "");
5941 		} else {
5942 			snprintf(panicString, panicStringLen,
5943 			    "%s[%d], (%llds): %s",
5944 			    pendingRequests ? "IOKit Daemon (" kIOKitDaemonName ") stall" : "busy timeout",
5945 			    loops, timeout / 1000000000ULL,
5946 			    busyEntriesString ? busyEntriesString : "");
5947 		}
5948 
5949 		IOLog("%s\n", panicString);
5950 		if (dopanic) {
5951 			panic("%s", panicString);
5952 		} else if (!loops) {
5953 			getPMRootDomain()->startSpinDump(1);
5954 		}
5955 	}
5956 
5957 	if (busyEntriesString) {
5958 		IODeleteData(busyEntriesString, char, busyEntriesStringLen);
5959 	}
5960 	if (panicString) {
5961 		IODeleteData(panicString, char, panicStringLen);
5962 	}
5963 
5964 	return ret;
5965 }
5966 
5967 IOReturn
waitQuiet(uint64_t timeout)5968 IOService::waitQuiet( uint64_t timeout )
5969 {
5970 	return waitQuietWithOptions(timeout);
5971 }
5972 
5973 IOReturn
waitQuiet(mach_timespec_t * timeout)5974 IOService::waitQuiet( mach_timespec_t * timeout )
5975 {
5976 	uint64_t    timeoutNS;
5977 
5978 	if (timeout) {
5979 		timeoutNS = timeout->tv_sec;
5980 		timeoutNS *= kSecondScale;
5981 		timeoutNS += timeout->tv_nsec;
5982 	} else {
5983 		timeoutNS = UINT64_MAX;
5984 	}
5985 
5986 	return waitQuiet(timeoutNS);
5987 }
5988 
5989 bool
serializeProperties(OSSerialize * s) const5990 IOService::serializeProperties( OSSerialize * s ) const
5991 {
5992 #if 0
5993 	((IOService *)this)->setProperty(((IOService *)this)->__state,
5994 	    sizeof(__state), "__state");
5995 #endif
5996 	return super::serializeProperties(s);
5997 }
5998 
5999 void
resetRematchProperties()6000 IOService::resetRematchProperties()
6001 {
6002 	removeProperty(gIORematchCountKey);
6003 	removeProperty(gIORematchPersonalityKey);
6004 }
6005 
6006 
6007 void
main(void * arg,wait_result_t result)6008 _IOConfigThread::main(void * arg, wait_result_t result)
6009 {
6010 	_IOConfigThread * self = (_IOConfigThread *) arg;
6011 	_IOServiceJob * job;
6012 	IOService   *   nub;
6013 	bool            alive = true;
6014 	kern_return_t   kr;
6015 	thread_precedence_policy_data_t precedence = { -1 };
6016 
6017 	kr = thread_policy_set(current_thread(),
6018 	    THREAD_PRECEDENCE_POLICY,
6019 	    (thread_policy_t) &precedence,
6020 	    THREAD_PRECEDENCE_POLICY_COUNT);
6021 	if (KERN_SUCCESS != kr) {
6022 		IOLog("thread_policy_set(%d)\n", kr);
6023 	}
6024 
6025 	do {
6026 //	randomDelay();
6027 
6028 		semaphore_wait( gJobsSemaphore );
6029 
6030 		IOTakeLock( gJobsLock );
6031 		job = (_IOServiceJob *) gJobs->getFirstObject();
6032 		job->retain();
6033 		gJobs->removeObject(job);
6034 		if (job) {
6035 			gOutstandingJobs--;
6036 //	    gNumConfigThreads--;	// we're out of service
6037 			gNumWaitingThreads--; // we're out of service
6038 		}
6039 		IOUnlock( gJobsLock );
6040 
6041 		if (job) {
6042 			nub = job->nub;
6043 
6044 			if (gIOKitDebug & kIOLogConfig) {
6045 				LOG("config(%p): starting on %s, %d\n",
6046 				    IOSERVICE_OBFUSCATE(IOThreadSelf()), job->nub->getName(), job->type);
6047 			}
6048 
6049 			switch (job->type) {
6050 			case kMatchNubJob:
6051 				nub->doServiceMatch( job->options );
6052 				break;
6053 
6054 			default:
6055 				LOG("config(%p): strange type (%d)\n",
6056 				    IOSERVICE_OBFUSCATE(IOThreadSelf()), job->type );
6057 				break;
6058 			}
6059 
6060 			if (job->options & kIOServiceDextRequirePowerForMatching) {
6061 				gIOPMRootDomain->releaseDriverKitMatchingAssertion();
6062 			}
6063 
6064 			OSSafeReleaseNULL(nub);
6065 			OSSafeReleaseNULL(job);
6066 
6067 			IOTakeLock( gJobsLock );
6068 			alive = (gOutstandingJobs > gNumWaitingThreads);
6069 			if (alive) {
6070 				gNumWaitingThreads++; // back in service
6071 			}
6072 //		gNumConfigThreads++;
6073 			else {
6074 				if (0 == --gNumConfigThreads) {
6075 //                    IOLog("MATCH IDLE\n");
6076 					IOLockWakeup( gJobsLock, (event_t) &gNumConfigThreads, /* one-thread */ false );
6077 				}
6078 			}
6079 			IOUnlock( gJobsLock );
6080 		}
6081 	} while (alive);
6082 
6083 	if (gIOKitDebug & kIOLogConfig) {
6084 		LOG("config(%p): terminating\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
6085 	}
6086 
6087 	self->release();
6088 }
6089 
6090 IOReturn
waitMatchIdle(UInt32 msToWait)6091 IOService::waitMatchIdle( UInt32 msToWait )
6092 {
6093 	bool            wait;
6094 	int             waitResult = THREAD_AWAKENED;
6095 	bool            computeDeadline = true;
6096 	AbsoluteTime    deadline;
6097 
6098 	IOLockLock( gJobsLock );
6099 	do {
6100 		wait = (0 != gNumConfigThreads);
6101 		if (wait) {
6102 			if (msToWait) {
6103 				if (computeDeadline) {
6104 					clock_interval_to_deadline(
6105 						msToWait, kMillisecondScale, &deadline );
6106 					computeDeadline = false;
6107 				}
6108 				waitResult = IOLockSleepDeadline( gJobsLock, &gNumConfigThreads,
6109 				    deadline, THREAD_UNINT );
6110 			} else {
6111 				waitResult = IOLockSleep( gJobsLock, &gNumConfigThreads,
6112 				    THREAD_UNINT );
6113 			}
6114 		}
6115 	} while (wait && (waitResult != THREAD_TIMED_OUT));
6116 	IOLockUnlock( gJobsLock );
6117 
6118 	if (waitResult == THREAD_TIMED_OUT) {
6119 		return kIOReturnTimeout;
6120 	} else {
6121 		return kIOReturnSuccess;
6122 	}
6123 }
6124 
6125 void
cpusRunning(void)6126 IOService::cpusRunning(void)
6127 {
6128 	gCPUsRunning = true;
6129 }
6130 
6131 void
pingConfig(_IOServiceJob * job)6132 _IOServiceJob::pingConfig( _IOServiceJob * job )
6133 {
6134 	int         count;
6135 	bool        create;
6136 	IOService * nub;
6137 
6138 	assert( job );
6139 	nub = job->nub;
6140 
6141 	IOTakeLock( gJobsLock );
6142 
6143 	gOutstandingJobs++;
6144 	if (nub == gIOResources) {
6145 		gJobs->setFirstObject( job );
6146 	} else {
6147 		gJobs->setLastObject( job );
6148 	}
6149 
6150 	count = gNumWaitingThreads;
6151 //    if( gNumConfigThreads) count++;// assume we're called from a config thread
6152 
6153 	create = ((gOutstandingJobs > count)
6154 	    && ((gNumConfigThreads < gMaxConfigThreads)
6155 	    || (nub == gIOResources)
6156 	    || !gCPUsRunning));
6157 	if (create) {
6158 		gNumConfigThreads++;
6159 		gNumWaitingThreads++;
6160 		if (gNumConfigThreads > gHighNumConfigThreads) {
6161 			gHighNumConfigThreads = gNumConfigThreads;
6162 		}
6163 	}
6164 
6165 	IOUnlock( gJobsLock );
6166 
6167 	job->release();
6168 
6169 	if (create) {
6170 		if (gIOKitDebug & kIOLogConfig) {
6171 			LOG("config(%d): creating\n", gNumConfigThreads - 1);
6172 		}
6173 		_IOConfigThread::configThread(nub->getName());
6174 	}
6175 
6176 	semaphore_signal( gJobsSemaphore );
6177 }
6178 
6179 struct IOServiceMatchContext {
6180 	OSDictionary * table;
6181 	OSObject *     result;
6182 	uint32_t       options;
6183 	uint32_t       state;
6184 	uint32_t       count;
6185 	uint32_t       done;
6186 };
6187 
6188 bool
instanceMatch(const OSObject * entry,void * context)6189 IOService::instanceMatch(const OSObject * entry, void * context)
6190 {
6191 	IOServiceMatchContext * ctx = (typeof(ctx))context;
6192 	IOService *    service = (typeof(service))entry;
6193 	OSDictionary * table   = ctx->table;
6194 	uint32_t       options = ctx->options;
6195 	uint32_t       state   = ctx->state;
6196 	uint32_t       done;
6197 	bool           match;
6198 
6199 	done = 0;
6200 	do{
6201 		match = ((state == (state & service->__state[0]))
6202 		    && (0 == (service->__state[0] & kIOServiceInactiveState)));
6203 		if (!match) {
6204 			break;
6205 		}
6206 
6207 		match = service->matchInternal(table, options, &done);
6208 		if (match) {
6209 			ctx->count += table->getCount();
6210 			ctx->done += done;
6211 		}
6212 	}while (false);
6213 	if (!match) {
6214 		return false;
6215 	}
6216 
6217 	if ((kIONotifyOnce & options) && (ctx->done == ctx->count)) {
6218 		service->retain();
6219 		ctx->result = service;
6220 		return true;
6221 	} else if (!ctx->result) {
6222 		ctx->result = OSSet::withObjects((const OSObject **) &service, 1, 1);
6223 	} else {
6224 		((OSSet *)ctx->result)->setObject(service);
6225 	}
6226 	return false;
6227 }
6228 
6229 // internal - call with gNotificationLock
6230 OSObject *
copyExistingServices(OSDictionary * matching,IOOptionBits inState,IOOptionBits options)6231 IOService::copyExistingServices( OSDictionary * matching,
6232     IOOptionBits inState, IOOptionBits options )
6233 {
6234 	OSObject *   current = NULL;
6235 	OSIterator * iter;
6236 	IOService *  service;
6237 	OSObject *   obj;
6238 	OSString *   str;
6239 
6240 	if (!matching) {
6241 		return NULL;
6242 	}
6243 
6244 #if MATCH_DEBUG
6245 	OSSerialize * s = OSSerialize::withCapacity(128);
6246 	matching->serialize(s);
6247 #endif
6248 
6249 	if ((obj = matching->getObject(gIOProviderClassKey))
6250 	    && gIOResourcesKey
6251 	    && gIOResourcesKey->isEqualTo(obj)
6252 	    && (service = gIOResources)) {
6253 		if ((inState == (service->__state[0] & inState))
6254 		    && (0 == (service->__state[0] & kIOServiceInactiveState))
6255 		    && service->matchPassive(matching, options)) {
6256 			if (options & kIONotifyOnce) {
6257 				service->retain();
6258 				current = service;
6259 			} else {
6260 				current = OSSet::withObjects((const OSObject **) &service, 1, 1 );
6261 			}
6262 		}
6263 	} else {
6264 		IOServiceMatchContext ctx;
6265 
6266 		options    |= kIOServiceClassDone;
6267 		ctx.table   = matching;
6268 		ctx.state   = inState;
6269 		ctx.count   = 0;
6270 		ctx.done    = 0;
6271 		ctx.options = options;
6272 		ctx.result  = NULL;
6273 
6274 		if ((str = OSDynamicCast(OSString, obj))) {
6275 			const OSSymbol * sym = OSSymbol::withString(str);
6276 			OSMetaClass::applyToInstancesOfClassName(sym, instanceMatch, &ctx);
6277 			sym->release();
6278 		} else {
6279 			IOService::gMetaClass.applyToInstances(instanceMatch, &ctx);
6280 		}
6281 
6282 		if (((!(options & kIONotifyOnce) || !ctx.result))
6283 		    && matching->getObject(gIOCompatibilityMatchKey)) {
6284 			IOServiceCompatibility::gMetaClass.applyToInstances(instanceMatch, &ctx);
6285 		}
6286 
6287 		current = ctx.result;
6288 		options |= kIOServiceInternalDone;
6289 		if (current && (ctx.done != ctx.count)) {
6290 			OSSet * source = OSDynamicCast(OSSet, current);
6291 			current = NULL;
6292 			while ((service = (IOService *) source->getAnyObject())) {
6293 				if (service->matchPassive(matching, options)) {
6294 					if (options & kIONotifyOnce) {
6295 						service->retain();
6296 						current = service;
6297 						break;
6298 					}
6299 					if (current) {
6300 						((OSSet *)current)->setObject( service );
6301 					} else {
6302 						current = OSSet::withObjects(
6303 							(const OSObject **) &service, 1, 1 );
6304 					}
6305 				}
6306 				source->removeObject(service);
6307 			}
6308 			source->release();
6309 		}
6310 	}
6311 
6312 #if MATCH_DEBUG
6313 	{
6314 		OSObject * _current = 0;
6315 
6316 		iter = IORegistryIterator::iterateOver( gIOServicePlane,
6317 		    kIORegistryIterateRecursively );
6318 		if (iter) {
6319 			do {
6320 				iter->reset();
6321 				while ((service = (IOService *) iter->getNextObject())) {
6322 					if ((inState == (service->__state[0] & inState))
6323 					    && (0 == (service->__state[0] & kIOServiceInactiveState))
6324 					    && service->matchPassive(matching, 0)) {
6325 						if (options & kIONotifyOnce) {
6326 							service->retain();
6327 							_current = service;
6328 							break;
6329 						}
6330 						if (_current) {
6331 							((OSSet *)_current)->setObject( service );
6332 						} else {
6333 							_current = OSSet::withObjects(
6334 								(const OSObject **) &service, 1, 1 );
6335 						}
6336 					}
6337 				}
6338 			} while (!service && !iter->isValid());
6339 			iter->release();
6340 		}
6341 
6342 		if (((current != 0) != (_current != 0))
6343 		    || (current && _current && !current->isEqualTo(_current))) {
6344 			OSSerialize * s1 = OSSerialize::withCapacity(128);
6345 			OSSerialize * s2 = OSSerialize::withCapacity(128);
6346 			current->serialize(s1);
6347 			_current->serialize(s2);
6348 			kprintf("**mismatch** %p %p\n%s\n%s\n%s\n", IOSERVICE_OBFUSCATE(current),
6349 			    IOSERVICE_OBFUSCATE(_current), s->text(), s1->text(), s2->text());
6350 			s1->release();
6351 			s2->release();
6352 		}
6353 
6354 		if (_current) {
6355 			_current->release();
6356 		}
6357 	}
6358 
6359 	s->release();
6360 #endif
6361 
6362 	if (current && (0 == (options & (kIONotifyOnce | kIOServiceExistingSet)))) {
6363 		iter = OSCollectionIterator::withCollection((OSSet *)current );
6364 		current->release();
6365 		current = iter;
6366 	}
6367 
6368 	return current;
6369 }
6370 
6371 // public version
6372 OSIterator *
getMatchingServices(OSDictionary * matching)6373 IOService::getMatchingServices( OSDictionary * matching )
6374 {
6375 	OSIterator *        iter;
6376 
6377 	// is a lock even needed?
6378 	LOCKWRITENOTIFY();
6379 
6380 	iter = (OSIterator *) copyExistingServices( matching,
6381 	    kIOServiceMatchedState );
6382 
6383 	UNLOCKNOTIFY();
6384 
6385 	return iter;
6386 }
6387 
6388 IOService *
copyMatchingService(OSDictionary * matching)6389 IOService::copyMatchingService( OSDictionary * matching )
6390 {
6391 	IOService * service;
6392 
6393 	// is a lock even needed?
6394 	LOCKWRITENOTIFY();
6395 
6396 	service = (IOService *) copyExistingServices( matching,
6397 	    kIOServiceMatchedState, kIONotifyOnce );
6398 
6399 	UNLOCKNOTIFY();
6400 
6401 	return service;
6402 }
6403 
6404 struct _IOServiceMatchingNotificationHandlerRef {
6405 	IOServiceNotificationHandler handler;
6406 	void * ref;
6407 };
6408 
6409 static bool
_IOServiceMatchingNotificationHandler(void * target,void * refCon,IOService * newService,IONotifier * notifier)6410 _IOServiceMatchingNotificationHandler( void * target, void * refCon,
6411     IOService * newService,
6412     IONotifier * notifier )
6413 {
6414 	return (*((_IOServiceNotifier *) notifier)->compatHandler)(target, refCon, newService);
6415 }
6416 
6417 // internal - call with gNotificationLock
6418 IONotifier *
setNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority)6419 IOService::setNotification(
6420 	const OSSymbol * type, OSDictionary * matching,
6421 	IOServiceMatchingNotificationHandler handler, void * target, void * ref,
6422 	SInt32 priority )
6423 {
6424 	_IOServiceNotifier * notify = NULL;
6425 	OSOrderedSet *      set;
6426 
6427 	if (!matching) {
6428 		return NULL;
6429 	}
6430 
6431 	notify = new _IOServiceNotifier;
6432 	if (notify && !notify->init()) {
6433 		notify->release();
6434 		notify = NULL;
6435 	}
6436 
6437 	if (notify) {
6438 		notify->handler = handler;
6439 		notify->target = target;
6440 		notify->type = type;
6441 		notify->matching = matching;
6442 		matching->retain();
6443 		if (handler == &_IOServiceMatchingNotificationHandler) {
6444 			notify->compatHandler = ((_IOServiceMatchingNotificationHandlerRef *)ref)->handler;
6445 			notify->ref = ((_IOServiceMatchingNotificationHandlerRef *)ref)->ref;
6446 		} else if (handler == &IOServiceMatchingNotificationHandlerToBlock) {
6447 			notify->ref = Block_copy(ref);
6448 		} else {
6449 			notify->ref = ref;
6450 		}
6451 		notify->priority = priority;
6452 		notify->state = kIOServiceNotifyEnable;
6453 		queue_init( &notify->handlerInvocations );
6454 
6455 		////// queue
6456 
6457 		if (NULL == (set = (OSOrderedSet *) gNotifications->getObject( type ))) {
6458 			set = OSOrderedSet::withCapacity( 1,
6459 			    IONotifyOrdering, NULL );
6460 			if (set) {
6461 				gNotifications->setObject( type, set );
6462 				set->release();
6463 			}
6464 		}
6465 		notify->whence = set;
6466 		if (set) {
6467 			set->setObject( notify );
6468 		}
6469 	}
6470 
6471 	return notify;
6472 }
6473 
6474 // internal - call with gNotificationLock
6475 IONotifier *
doInstallNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority,OSIterator ** existing)6476 IOService::doInstallNotification(
6477 	const OSSymbol * type, OSDictionary * matching,
6478 	IOServiceMatchingNotificationHandler handler,
6479 	void * target, void * ref,
6480 	SInt32 priority, OSIterator ** existing )
6481 {
6482 	OSIterator *        exist;
6483 	IONotifier *        notify;
6484 	IOOptionBits        inState;
6485 
6486 	if (!matching) {
6487 		return NULL;
6488 	}
6489 
6490 	if (type == gIOPublishNotification) {
6491 		inState = kIOServiceRegisteredState;
6492 	} else if (type == gIOFirstPublishNotification) {
6493 		inState = kIOServiceFirstPublishState;
6494 	} else if (type == gIOMatchedNotification) {
6495 		inState = kIOServiceMatchedState;
6496 	} else if (type == gIOFirstMatchNotification) {
6497 		inState = kIOServiceFirstMatchState;
6498 	} else if ((type == gIOTerminatedNotification) || (type == gIOWillTerminateNotification)) {
6499 		inState = 0;
6500 	} else {
6501 		return NULL;
6502 	}
6503 
6504 	notify = setNotification( type, matching, handler, target, ref, priority );
6505 
6506 	if (inState) {
6507 		// get the current set
6508 		exist = (OSIterator *) copyExistingServices( matching, inState );
6509 	} else {
6510 		exist = NULL;
6511 	}
6512 
6513 	*existing = exist;
6514 
6515 	return notify;
6516 }
6517 
6518 #if !defined(__LP64__)
6519 IONotifier *
installNotification(const OSSymbol * type,OSDictionary * matching,IOServiceNotificationHandler handler,void * target,void * refCon,SInt32 priority,OSIterator ** existing)6520 IOService::installNotification(const OSSymbol * type, OSDictionary * matching,
6521     IOServiceNotificationHandler handler,
6522     void * target, void * refCon,
6523     SInt32 priority, OSIterator ** existing )
6524 {
6525 	IONotifier * result;
6526 	_IOServiceMatchingNotificationHandlerRef ref;
6527 	ref.handler = handler;
6528 	ref.ref     = refCon;
6529 
6530 	result = (_IOServiceNotifier *) installNotification( type, matching,
6531 	    &_IOServiceMatchingNotificationHandler,
6532 	    target, &ref, priority, existing );
6533 	if (result) {
6534 		matching->release();
6535 	}
6536 
6537 	return result;
6538 }
6539 
6540 #endif /* !defined(__LP64__) */
6541 
6542 
6543 IONotifier *
installNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority,OSIterator ** existing)6544 IOService::installNotification(
6545 	const OSSymbol * type, OSDictionary * matching,
6546 	IOServiceMatchingNotificationHandler handler,
6547 	void * target, void * ref,
6548 	SInt32 priority, OSIterator ** existing )
6549 {
6550 	IONotifier * notify;
6551 
6552 	LOCKWRITENOTIFY();
6553 
6554 	notify = doInstallNotification( type, matching, handler, target, ref,
6555 	    priority, existing );
6556 
6557 	// in case handler remove()s
6558 	if (notify) {
6559 		notify->retain();
6560 	}
6561 
6562 	UNLOCKNOTIFY();
6563 
6564 	return notify;
6565 }
6566 
6567 IONotifier *
addNotification(const OSSymbol * type,OSDictionary * matching,IOServiceNotificationHandler handler,void * target,void * refCon,SInt32 priority)6568 IOService::addNotification(
6569 	const OSSymbol * type, OSDictionary * matching,
6570 	IOServiceNotificationHandler handler,
6571 	void * target, void * refCon,
6572 	SInt32 priority )
6573 {
6574 	IONotifier * result;
6575 	_IOServiceMatchingNotificationHandlerRef ref;
6576 
6577 	ref.handler = handler;
6578 	ref.ref     = refCon;
6579 
6580 	result = addMatchingNotification(type, matching, &_IOServiceMatchingNotificationHandler,
6581 	    target, &ref, priority);
6582 
6583 	if (result) {
6584 		matching->release();
6585 	}
6586 
6587 	return result;
6588 }
6589 
6590 IONotifier *
addMatchingNotification(const OSSymbol * type,OSDictionary * matching,IOServiceMatchingNotificationHandler handler,void * target,void * ref,SInt32 priority)6591 IOService::addMatchingNotification(
6592 	const OSSymbol * type, OSDictionary * matching,
6593 	IOServiceMatchingNotificationHandler handler,
6594 	void * target, void * ref,
6595 	SInt32 priority )
6596 {
6597 	OSIterator *                existing = NULL;
6598 	IONotifier *                ret;
6599 	_IOServiceNotifier *        notify;
6600 	IOService *                 next;
6601 
6602 	ret = notify = (_IOServiceNotifier *) installNotification( type, matching,
6603 	    handler, target, ref, priority, &existing );
6604 	if (!ret) {
6605 		OSSafeReleaseNULL(existing);
6606 		return NULL;
6607 	}
6608 
6609 	// send notifications for existing set
6610 	if (existing) {
6611 		while ((next = (IOService *) existing->getNextObject())) {
6612 			if (0 == (next->__state[0] & kIOServiceInactiveState)) {
6613 				next->invokeNotifier( notify );
6614 			}
6615 		}
6616 		existing->release();
6617 	}
6618 
6619 	LOCKWRITENOTIFY();
6620 	bool removed = (NULL == notify->whence);
6621 	notify->release();
6622 	if (removed) {
6623 		ret = gIOServiceNullNotifier;
6624 	}
6625 	UNLOCKNOTIFY();
6626 
6627 	return ret;
6628 }
6629 
6630 static bool
IOServiceMatchingNotificationHandlerToBlock(void * target __unused,void * refCon,IOService * newService,IONotifier * notifier)6631 IOServiceMatchingNotificationHandlerToBlock( void * target __unused, void * refCon,
6632     IOService * newService,
6633     IONotifier * notifier )
6634 {
6635 	return ((IOServiceMatchingNotificationHandlerBlock) refCon)(newService, notifier);
6636 }
6637 
6638 IONotifier *
addMatchingNotification(const OSSymbol * type,OSDictionary * matching,SInt32 priority,IOServiceMatchingNotificationHandlerBlock handler)6639 IOService::addMatchingNotification(
6640 	const OSSymbol * type, OSDictionary * matching,
6641 	SInt32 priority,
6642 	IOServiceMatchingNotificationHandlerBlock handler)
6643 {
6644 	IONotifier * notify;
6645 
6646 	notify = addMatchingNotification(type, matching,
6647 	    &IOServiceMatchingNotificationHandlerToBlock, NULL, handler, priority);
6648 	return notify;
6649 }
6650 
6651 struct IOUserServerCancellationHandlerArgs {
6652 	IOService ** ref;
6653 	bool canceled;
6654 };
6655 
6656 void
userServerCheckInTokenCancellationHandler(__unused IOUserServerCheckInToken * token,void * ref)6657 IOService::userServerCheckInTokenCancellationHandler(
6658 	__unused IOUserServerCheckInToken *token,
6659 	void *ref)
6660 {
6661 	IOUserServerCancellationHandlerArgs * args = (typeof(args))ref;
6662 	LOCKWRITENOTIFY();
6663 	WAKEUPNOTIFY(args->ref);
6664 	args->canceled = true;
6665 	UNLOCKNOTIFY();
6666 }
6667 
6668 bool
syncNotificationHandler(void *,void * ref,IOService * newService,IONotifier * notifier)6669 IOService::syncNotificationHandler(
6670 	void * /* target */, void * ref,
6671 	IOService * newService,
6672 	IONotifier * notifier )
6673 {
6674 	LOCKWRITENOTIFY();
6675 	if (!*((IOService **) ref)) {
6676 		newService->retain();
6677 		(*(IOService **) ref) = newService;
6678 		WAKEUPNOTIFY(ref);
6679 	}
6680 	UNLOCKNOTIFY();
6681 
6682 	return false;
6683 }
6684 
6685 IOService *
waitForMatchingServiceWithToken(OSDictionary * matching,uint64_t timeout,IOUserServerCheckInToken * checkInToken)6686 IOService::waitForMatchingServiceWithToken( OSDictionary * matching,
6687     uint64_t timeout,
6688     IOUserServerCheckInToken * checkInToken)
6689 {
6690 	IONotifier *        notify = NULL;
6691 	// priority doesn't help us much since we need a thread wakeup
6692 	SInt32              priority = 0;
6693 	IOService *         result;
6694 	IOUserServerCancellationHandlerArgs cancelArgs;
6695 	_IOUserServerCheckInCancellationHandler * cancellationHandler = NULL;
6696 
6697 	if (!matching) {
6698 		return NULL;
6699 	}
6700 
6701 	result = NULL;
6702 	cancelArgs.ref = &result;
6703 	cancelArgs.canceled = false;
6704 
6705 #if DEBUG || DEVELOPMENT
6706 	char                currentName[MAXTHREADNAMESIZE];
6707 	char                newName[MAXTHREADNAMESIZE];
6708 	OSObject          * obj;
6709 	OSString          * str;
6710 	OSDictionary      * dict;
6711 
6712 	currentName[0] = '\0';
6713 	if (thread_has_thread_name(current_thread())) {
6714 		dict = matching;
6715 		obj = matching->getObject(gIOPropertyMatchKey);
6716 		if ((dict = OSDynamicCast(OSDictionary, obj))) {
6717 			OSObject * result __block = NULL;
6718 			dict->iterateObjects(^bool (const OSSymbol * sym, OSObject * value) {
6719 				result = __DECONST(OSObject *, sym);
6720 				return true;
6721 			});
6722 			obj = result;
6723 		}
6724 		if (!obj) {
6725 			obj = matching->getObject(gIOResourceMatchKey);
6726 		}
6727 		if (!obj) {
6728 			obj = matching->getObject(gIONameMatchKey);
6729 		}
6730 		if (!obj) {
6731 			obj = matching->getObject(gIOProviderClassKey);
6732 		}
6733 		if ((str = OSDynamicCast(OSString, obj))) {
6734 			thread_get_thread_name(current_thread(), currentName);
6735 			snprintf(newName, sizeof(newName), "Waiting_'%s'", str->getCStringNoCopy());
6736 			thread_set_thread_name(current_thread(), newName);
6737 		}
6738 	}
6739 #endif /* DEBUG || DEVELOPMENT */
6740 
6741 	if (checkInToken) {
6742 		cancellationHandler = checkInToken->setCancellationHandler(&IOService::userServerCheckInTokenCancellationHandler,
6743 		    &cancelArgs);
6744 	}
6745 
6746 	LOCKWRITENOTIFY();
6747 	do{
6748 		if (cancelArgs.canceled) {
6749 			// token was already canceled, no need to wait or find services
6750 			break;
6751 		}
6752 		result = (IOService *) copyExistingServices( matching,
6753 		    kIOServiceMatchedState, kIONotifyOnce );
6754 		if (result) {
6755 			break;
6756 		}
6757 		notify = IOService::setNotification( gIOMatchedNotification, matching,
6758 		    &IOService::syncNotificationHandler, (void *) NULL,
6759 		    &result, priority );
6760 		if (!notify) {
6761 			break;
6762 		}
6763 		if (UINT64_MAX != timeout) {
6764 			AbsoluteTime deadline;
6765 			nanoseconds_to_absolutetime(timeout, &deadline);
6766 			clock_absolutetime_interval_to_deadline(deadline, &deadline);
6767 			SLEEPNOTIFYTO(&result, deadline);
6768 		} else {
6769 			SLEEPNOTIFY(&result);
6770 		}
6771 	}while (false);
6772 
6773 	UNLOCKNOTIFY();
6774 
6775 	if (checkInToken && cancellationHandler) {
6776 		checkInToken->removeCancellationHandler(cancellationHandler);
6777 	}
6778 
6779 #if DEBUG || DEVELOPMENT
6780 	if (currentName[0]) {
6781 		thread_set_thread_name(current_thread(), currentName);
6782 	}
6783 #endif /* DEBUG || DEVELOPMENT */
6784 
6785 	if (notify) {
6786 		notify->remove(); // dequeues
6787 	}
6788 
6789 	OSSafeReleaseNULL(cancellationHandler);
6790 
6791 	return result;
6792 }
6793 
6794 IOService *
waitForMatchingService(OSDictionary * matching,uint64_t timeout)6795 IOService::waitForMatchingService( OSDictionary * matching,
6796     uint64_t timeout)
6797 {
6798 	return IOService::waitForMatchingServiceWithToken(matching, timeout, NULL);
6799 }
6800 
6801 IOService *
waitForService(OSDictionary * matching,mach_timespec_t * timeout)6802 IOService::waitForService( OSDictionary * matching,
6803     mach_timespec_t * timeout )
6804 {
6805 	IOService * result;
6806 	uint64_t    timeoutNS;
6807 
6808 	if (timeout) {
6809 		timeoutNS = timeout->tv_sec;
6810 		timeoutNS *= kSecondScale;
6811 		timeoutNS += timeout->tv_nsec;
6812 	} else {
6813 		timeoutNS = UINT64_MAX;
6814 	}
6815 
6816 	result = waitForMatchingService(matching, timeoutNS);
6817 
6818 	matching->release();
6819 	if (result) {
6820 		result->release();
6821 	}
6822 
6823 	return result;
6824 }
6825 
6826 __dead2
6827 void
deliverNotification(const OSSymbol * type,IOOptionBits orNewState,IOOptionBits andNewState)6828 IOService::deliverNotification( const OSSymbol * type,
6829     IOOptionBits orNewState, IOOptionBits andNewState )
6830 {
6831 	panic("deliverNotification");
6832 }
6833 
6834 OSArray *
copyNotifiers(const OSSymbol * type,IOOptionBits orNewState,IOOptionBits andNewState)6835 IOService::copyNotifiers(const OSSymbol * type,
6836     IOOptionBits orNewState, IOOptionBits andNewState )
6837 {
6838 	_IOServiceNotifier * notify;
6839 	OSIterator *         iter;
6840 	OSArray *            willSend = NULL;
6841 
6842 	lockForArbitration();
6843 
6844 	if ((0 == (__state[0] & kIOServiceInactiveState))
6845 	    || (type == gIOTerminatedNotification)
6846 	    || (type == gIOWillTerminateNotification)) {
6847 		LOCKREADNOTIFY();
6848 
6849 		iter = OSCollectionIterator::withCollection((OSOrderedSet *)
6850 		    gNotifications->getObject( type ));
6851 
6852 		if (iter) {
6853 			while ((notify = (_IOServiceNotifier *) iter->getNextObject())) {
6854 				if (matchPassive(notify->matching, 0)
6855 				    && (kIOServiceNotifyEnable & notify->state)) {
6856 					if (NULL == willSend) {
6857 						willSend = OSArray::withCapacity(8);
6858 					}
6859 					if (willSend) {
6860 						willSend->setObject( notify );
6861 					}
6862 				}
6863 			}
6864 			iter->release();
6865 		}
6866 		__state[0] = (__state[0] | orNewState) & andNewState;
6867 		UNLOCKNOTIFY();
6868 	}
6869 
6870 	unlockForArbitration();
6871 
6872 	return willSend;
6873 }
6874 
6875 IOOptionBits
getState(void) const6876 IOService::getState( void ) const
6877 {
6878 	return __state[0];
6879 }
6880 
6881 /*
6882  * Helpers to make matching objects for simple cases
6883  */
6884 
6885 OSDictionary *
serviceMatching(const OSString * name,OSDictionary * table)6886 IOService::serviceMatching( const OSString * name,
6887     OSDictionary * table )
6888 {
6889 	const OSString *    str;
6890 
6891 	str = OSSymbol::withString(name);
6892 	if (!str) {
6893 		return NULL;
6894 	}
6895 
6896 	if (!table) {
6897 		table = OSDictionary::withCapacity( 2 );
6898 	}
6899 	if (table) {
6900 		table->setObject(gIOProviderClassKey, (OSObject *)str );
6901 	}
6902 	str->release();
6903 
6904 	return table;
6905 }
6906 
6907 
6908 OSSharedPtr<OSDictionary>
serviceMatching(const OSString * name,OSSharedPtr<OSDictionary> table)6909 IOService::serviceMatching( const OSString * name,
6910     OSSharedPtr<OSDictionary> table)
6911 {
6912 	OSDictionary * result = serviceMatching(name, table.get());
6913 	if (table) {
6914 		return OSSharedPtr<OSDictionary>(result, OSRetain);
6915 	} else {
6916 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
6917 	}
6918 }
6919 
6920 
6921 OSDictionary *
serviceMatching(const char * name,OSDictionary * table)6922 IOService::serviceMatching( const char * name,
6923     OSDictionary * table )
6924 {
6925 	const OSString *    str;
6926 
6927 	str = OSSymbol::withCString( name );
6928 	if (!str) {
6929 		return NULL;
6930 	}
6931 
6932 	table = serviceMatching( str, table );
6933 	str->release();
6934 	return table;
6935 }
6936 
6937 
6938 OSSharedPtr<OSDictionary>
serviceMatching(const char * className,OSSharedPtr<OSDictionary> table)6939 IOService::serviceMatching( const char * className,
6940     OSSharedPtr<OSDictionary> table)
6941 {
6942 	OSDictionary * result = serviceMatching(className, table.get());
6943 	if (table) {
6944 		return OSSharedPtr<OSDictionary>(result, OSRetain);
6945 	} else {
6946 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
6947 	}
6948 }
6949 
6950 
6951 OSDictionary *
nameMatching(const OSString * name,OSDictionary * table)6952 IOService::nameMatching( const OSString * name,
6953     OSDictionary * table )
6954 {
6955 	if (!table) {
6956 		table = OSDictionary::withCapacity( 2 );
6957 	}
6958 	if (table) {
6959 		table->setObject( gIONameMatchKey, (OSObject *)name );
6960 	}
6961 
6962 	return table;
6963 }
6964 
6965 
6966 OSSharedPtr<OSDictionary>
nameMatching(const OSString * name,OSSharedPtr<OSDictionary> table)6967 IOService::nameMatching( const OSString * name,
6968     OSSharedPtr<OSDictionary> table)
6969 {
6970 	OSDictionary * result = nameMatching(name, table.get());
6971 	if (table) {
6972 		return OSSharedPtr<OSDictionary>(result, OSRetain);
6973 	} else {
6974 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
6975 	}
6976 }
6977 
6978 
6979 OSDictionary *
nameMatching(const char * name,OSDictionary * table)6980 IOService::nameMatching( const char * name,
6981     OSDictionary * table )
6982 {
6983 	const OSString *    str;
6984 
6985 	str = OSSymbol::withCString( name );
6986 	if (!str) {
6987 		return NULL;
6988 	}
6989 
6990 	table = nameMatching( str, table );
6991 	str->release();
6992 	return table;
6993 }
6994 
6995 
6996 OSSharedPtr<OSDictionary>
nameMatching(const char * name,OSSharedPtr<OSDictionary> table)6997 IOService::nameMatching( const char * name,
6998     OSSharedPtr<OSDictionary> table)
6999 {
7000 	OSDictionary * result = nameMatching(name, table.get());
7001 	if (table) {
7002 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7003 	} else {
7004 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7005 	}
7006 }
7007 
7008 
7009 OSDictionary *
resourceMatching(const OSString * str,OSDictionary * table)7010 IOService::resourceMatching( const OSString * str,
7011     OSDictionary * table )
7012 {
7013 	table = serviceMatching( gIOResourcesKey, table );
7014 	if (table) {
7015 		table->setObject( gIOResourceMatchKey, (OSObject *) str );
7016 	}
7017 
7018 	return table;
7019 }
7020 
7021 
7022 OSSharedPtr<OSDictionary>
resourceMatching(const OSString * str,OSSharedPtr<OSDictionary> table)7023 IOService::resourceMatching( const OSString * str,
7024     OSSharedPtr<OSDictionary> table)
7025 {
7026 	OSDictionary * result = resourceMatching(str, table.get());
7027 	if (table) {
7028 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7029 	} else {
7030 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7031 	}
7032 }
7033 
7034 
7035 OSDictionary *
resourceMatching(const char * name,OSDictionary * table)7036 IOService::resourceMatching( const char * name,
7037     OSDictionary * table )
7038 {
7039 	const OSSymbol *    str;
7040 
7041 	str = OSSymbol::withCString( name );
7042 	if (!str) {
7043 		return NULL;
7044 	}
7045 
7046 	table = resourceMatching( str, table );
7047 	str->release();
7048 
7049 	return table;
7050 }
7051 
7052 
7053 OSSharedPtr<OSDictionary>
resourceMatching(const char * name,OSSharedPtr<OSDictionary> table)7054 IOService::resourceMatching( const char * name,
7055     OSSharedPtr<OSDictionary> table)
7056 {
7057 	OSDictionary * result = resourceMatching(name, table.get());
7058 	if (table) {
7059 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7060 	} else {
7061 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7062 	}
7063 }
7064 
7065 
7066 OSDictionary *
propertyMatching(const OSSymbol * key,const OSObject * value,OSDictionary * table)7067 IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
7068     OSDictionary * table )
7069 {
7070 	OSDictionary * properties;
7071 
7072 	properties = OSDictionary::withCapacity( 2 );
7073 	if (!properties) {
7074 		return NULL;
7075 	}
7076 	properties->setObject( key, value );
7077 
7078 	if (!table) {
7079 		table = OSDictionary::withCapacity( 2 );
7080 	}
7081 	if (table) {
7082 		table->setObject( gIOPropertyMatchKey, properties );
7083 	}
7084 
7085 	properties->release();
7086 
7087 	return table;
7088 }
7089 
7090 
7091 OSSharedPtr<OSDictionary>
propertyMatching(const OSSymbol * key,const OSObject * value,OSSharedPtr<OSDictionary> table)7092 IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
7093     OSSharedPtr<OSDictionary> table)
7094 {
7095 	OSDictionary * result = propertyMatching(key, value, table.get());
7096 	if (table) {
7097 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7098 	} else {
7099 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7100 	}
7101 }
7102 
7103 
7104 OSDictionary *
registryEntryIDMatching(uint64_t entryID,OSDictionary * table)7105 IOService::registryEntryIDMatching( uint64_t entryID,
7106     OSDictionary * table )
7107 {
7108 	OSNumber *     num;
7109 
7110 	num = OSNumber::withNumber( entryID, 64 );
7111 	if (!num) {
7112 		return NULL;
7113 	}
7114 
7115 	if (!table) {
7116 		table = OSDictionary::withCapacity( 2 );
7117 	}
7118 	if (table) {
7119 		table->setObject( gIORegistryEntryIDKey, num );
7120 	}
7121 
7122 	if (num) {
7123 		num->release();
7124 	}
7125 
7126 	return table;
7127 }
7128 
7129 
7130 OSSharedPtr<OSDictionary>
registryEntryIDMatching(uint64_t entryID,OSSharedPtr<OSDictionary> table)7131 IOService::registryEntryIDMatching( uint64_t entryID,
7132     OSSharedPtr<OSDictionary> table)
7133 {
7134 	OSDictionary * result = registryEntryIDMatching(entryID, table.get());
7135 	if (table) {
7136 		return OSSharedPtr<OSDictionary>(result, OSRetain);
7137 	} else {
7138 		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
7139 	}
7140 }
7141 
7142 
7143 
7144 /*
7145  * _IOServiceNotifier
7146  */
7147 
7148 // wait for all threads, other than the current one,
7149 //  to exit the handler
7150 
7151 void
wait()7152 _IOServiceNotifier::wait()
7153 {
7154 	_IOServiceNotifierInvocation * next;
7155 	bool doWait;
7156 
7157 	do {
7158 		doWait = false;
7159 		queue_iterate( &handlerInvocations, next,
7160 		    _IOServiceNotifierInvocation *, link) {
7161 			if (next->thread != current_thread()) {
7162 				doWait = true;
7163 				break;
7164 			}
7165 		}
7166 		if (doWait) {
7167 			state |= kIOServiceNotifyWaiter;
7168 			SLEEPNOTIFY(this);
7169 		}
7170 	} while (doWait);
7171 }
7172 
7173 void
free()7174 _IOServiceNotifier::free()
7175 {
7176 	assert( queue_empty( &handlerInvocations ));
7177 
7178 	if (handler == &IOServiceMatchingNotificationHandlerToBlock) {
7179 		Block_release(ref);
7180 	}
7181 
7182 	OSObject::free();
7183 }
7184 
7185 void
remove()7186 _IOServiceNotifier::remove()
7187 {
7188 	LOCKWRITENOTIFY();
7189 
7190 	if (whence) {
7191 		whence->removeObject((OSObject *) this );
7192 		whence = NULL;
7193 	}
7194 	if (matching) {
7195 		matching->release();
7196 		matching = NULL;
7197 	}
7198 
7199 	state &= ~kIOServiceNotifyEnable;
7200 
7201 	wait();
7202 
7203 	UNLOCKNOTIFY();
7204 
7205 	release();
7206 }
7207 
7208 bool
disable()7209 _IOServiceNotifier::disable()
7210 {
7211 	bool        ret;
7212 
7213 	LOCKWRITENOTIFY();
7214 
7215 	ret = (0 != (kIOServiceNotifyEnable & state));
7216 	state &= ~kIOServiceNotifyEnable;
7217 	if (ret) {
7218 		wait();
7219 	}
7220 
7221 	UNLOCKNOTIFY();
7222 
7223 	return ret;
7224 }
7225 
7226 void
enable(bool was)7227 _IOServiceNotifier::enable( bool was )
7228 {
7229 	LOCKWRITENOTIFY();
7230 	if (was) {
7231 		state |= kIOServiceNotifyEnable;
7232 	} else {
7233 		state &= ~kIOServiceNotifyEnable;
7234 	}
7235 	UNLOCKNOTIFY();
7236 }
7237 
7238 
7239 /*
7240  * _IOServiceNullNotifier
7241  */
7242 
7243 void
taggedRetain(const void * tag) const7244 _IOServiceNullNotifier::taggedRetain(const void *tag) const
7245 {
7246 }
7247 void
taggedRelease(const void * tag,const int when) const7248 _IOServiceNullNotifier::taggedRelease(const void *tag, const int when) const
7249 {
7250 }
7251 void
free()7252 _IOServiceNullNotifier::free()
7253 {
7254 }
7255 void
wait()7256 _IOServiceNullNotifier::wait()
7257 {
7258 }
7259 void
remove()7260 _IOServiceNullNotifier::remove()
7261 {
7262 }
7263 void
enable(bool was)7264 _IOServiceNullNotifier::enable(bool was)
7265 {
7266 }
7267 bool
disable()7268 _IOServiceNullNotifier::disable()
7269 {
7270 	return false;
7271 }
7272 
7273 /*
7274  * IOResources
7275  */
7276 
7277 IOService *
resources(void)7278 IOResources::resources( void )
7279 {
7280 	IOResources *       inst;
7281 
7282 	inst = new IOResources;
7283 	if (inst && !inst->init()) {
7284 		inst->release();
7285 		inst = NULL;
7286 	}
7287 
7288 	return inst;
7289 }
7290 
7291 bool
init(OSDictionary * dictionary)7292 IOResources::init( OSDictionary * dictionary )
7293 {
7294 	// Do super init first
7295 	if (!IOService::init()) {
7296 		return false;
7297 	}
7298 
7299 	// Allow PAL layer to publish a value
7300 	const char *property_name;
7301 	int property_value;
7302 
7303 	pal_get_resource_property( &property_name, &property_value );
7304 
7305 	if (property_name) {
7306 		OSNumber *num;
7307 		const OSSymbol *        sym;
7308 
7309 		if ((num = OSNumber::withNumber(property_value, 32)) != NULL) {
7310 			if ((sym = OSSymbol::withCString( property_name)) != NULL) {
7311 				this->setProperty( sym, num );
7312 				sym->release();
7313 			}
7314 			num->release();
7315 		}
7316 	}
7317 
7318 	return true;
7319 }
7320 
7321 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,IOUserClient ** handler)7322 IOResources::newUserClient(task_t owningTask, void * securityID,
7323     UInt32 type, OSDictionary * properties,
7324     IOUserClient ** handler)
7325 {
7326 	return kIOReturnUnsupported;
7327 }
7328 
7329 IOWorkLoop *
getWorkLoop() const7330 IOResources::getWorkLoop() const
7331 {
7332 	// If we are the resource root
7333 	// then use the platform's workloop
7334 	if (this == (IOResources *) gIOResources) {
7335 		return getPlatform()->getWorkLoop();
7336 	} else {
7337 		return IOService::getWorkLoop();
7338 	}
7339 }
7340 
7341 static bool
IOResourcesMatchPropertyTable(IOService * resources,OSDictionary * table)7342 IOResourcesMatchPropertyTable(IOService * resources, OSDictionary * table)
7343 {
7344 	OSObject *          prop;
7345 	bool __block        ok = true;
7346 
7347 	prop = table->getObject( gIOResourceMatchKey );
7348 	if (prop) {
7349 		prop->iterateObjects(^bool (OSObject * obj)
7350 		{
7351 			OSString *
7352 			str = OSDynamicCast(OSString, obj);
7353 			ok = (NULL != resources->getProperty(str));
7354 			return !ok;
7355 		});
7356 	} else if ((prop = table->getObject(gIOResourceMatchedKey))) {
7357 		OSObject * obj;
7358 		OSArray *  keys;
7359 
7360 		obj = resources->copyProperty(gIOResourceMatchedKey);
7361 		keys = OSDynamicCast(OSArray, obj);
7362 		ok = false;
7363 		if (keys) {
7364 			// assuming OSSymbol
7365 			ok = ((-1U) != keys->getNextIndexOfObject(prop, 0));
7366 		}
7367 		OSSafeReleaseNULL(obj);
7368 	}
7369 
7370 	return ok;
7371 }
7372 
7373 bool
matchPropertyTable(OSDictionary * table)7374 IOResources::matchPropertyTable( OSDictionary * table )
7375 {
7376 	return IOResourcesMatchPropertyTable(this, table);
7377 }
7378 
7379 /*
7380  * IOUserResources
7381  */
7382 
7383 IOService *
resources(void)7384 IOUserResources::resources( void )
7385 {
7386 	IOUserResources *       inst;
7387 
7388 	inst = OSTypeAlloc(IOUserResources);
7389 	if (inst && !inst->init()) {
7390 		inst->release();
7391 		inst = NULL;
7392 	}
7393 
7394 	return inst;
7395 }
7396 
7397 bool
init(OSDictionary * dictionary)7398 IOUserResources::init( OSDictionary * dictionary )
7399 {
7400 	// Do super init first
7401 	if (!IOService::init()) {
7402 		return false;
7403 	}
7404 	return true;
7405 }
7406 
7407 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,IOUserClient ** handler)7408 IOUserResources::newUserClient(task_t owningTask, void * securityID,
7409     UInt32 type, OSDictionary * properties,
7410     IOUserClient ** handler)
7411 {
7412 	return kIOReturnUnsupported;
7413 }
7414 
7415 IOWorkLoop *
getWorkLoop() const7416 IOUserResources::getWorkLoop() const
7417 {
7418 	return getPlatform()->getWorkLoop();
7419 }
7420 
7421 bool
matchPropertyTable(OSDictionary * table)7422 IOUserResources::matchPropertyTable( OSDictionary * table )
7423 {
7424 	return IOResourcesMatchPropertyTable(this, table);
7425 }
7426 
7427 IOReturn
powerStateWillChangeTo(IOPMPowerFlags flags,unsigned long state,IOService * service)7428 IOUserResources::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
7429 {
7430 	assert(service == getPMRootDomain());
7431 	if (service != getPMRootDomain()) {
7432 		return kIOReturnSuccess;
7433 	}
7434 	return IOServicePH::rootWillChangeTo(flags, state);
7435 }
7436 
7437 // --
7438 
7439 void
consoleLockTimer(thread_call_param_t p0,thread_call_param_t p1)7440 IOService::consoleLockTimer(thread_call_param_t p0, thread_call_param_t p1)
7441 {
7442 	IOService::updateConsoleUsers(NULL, 0);
7443 }
7444 
7445 void
updateConsoleUsers(OSArray * consoleUsers,IOMessage systemMessage,bool afterUserspaceReboot)7446 IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessage, bool afterUserspaceReboot)
7447 {
7448 	IORegistryEntry * regEntry;
7449 	OSObject *        locked = kOSBooleanFalse;
7450 	uint32_t          idx;
7451 	bool              publish;
7452 	OSDictionary *    user;
7453 	clock_sec_t       now = 0;
7454 	clock_usec_t      microsecs;
7455 
7456 	regEntry = IORegistryEntry::getRegistryRoot();
7457 
7458 	if (!gIOChosenEntry) {
7459 		gIOChosenEntry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
7460 	}
7461 
7462 	IOLockLock(gIOConsoleUsersLock);
7463 
7464 	if (systemMessage) {
7465 		sSystemPower = systemMessage;
7466 #if HIBERNATION
7467 		if (kIOMessageSystemHasPoweredOn == systemMessage) {
7468 			uint32_t lockState = IOHibernateWasScreenLocked();
7469 			switch (lockState) {
7470 			case 0:
7471 				break;
7472 			case kIOScreenLockLocked:
7473 			case kIOScreenLockFileVaultDialog:
7474 				gIOConsoleBooterLockState = kOSBooleanTrue;
7475 				break;
7476 			case kIOScreenLockNoLock:
7477 				gIOConsoleBooterLockState = NULL;
7478 				break;
7479 			case kIOScreenLockUnlocked:
7480 			default:
7481 				gIOConsoleBooterLockState = kOSBooleanFalse;
7482 				break;
7483 			}
7484 		}
7485 #endif /* HIBERNATION */
7486 	}
7487 
7488 	if (consoleUsers) {
7489 		OSNumber * num = NULL;
7490 		bool       loginLocked = true;
7491 
7492 		gIOConsoleLoggedIn = false;
7493 		for (idx = 0;
7494 		    (user = OSDynamicCast(OSDictionary, consoleUsers->getObject(idx)));
7495 		    idx++) {
7496 			gIOConsoleLoggedIn |= ((kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey))
7497 			    && (kOSBooleanTrue == user->getObject(gIOConsoleSessionLoginDoneKey)));
7498 
7499 			loginLocked &= (kOSBooleanTrue == user->getObject(gIOConsoleSessionScreenIsLockedKey));
7500 			if (!num) {
7501 				num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionScreenLockedTimeKey));
7502 			}
7503 		}
7504 #if HIBERNATION
7505 		if (!loginLocked || afterUserspaceReboot) {
7506 			gIOConsoleBooterLockState = NULL;
7507 		}
7508 		IOLog("IOConsoleUsers: time(%d) %ld->%d, lin %d, llk %d, \n",
7509 		    (num != NULL), gIOConsoleLockTime, (num ? num->unsigned32BitValue() : 0),
7510 		    gIOConsoleLoggedIn, loginLocked);
7511 #endif /* HIBERNATION */
7512 		gIOConsoleLockTime = num ? num->unsigned32BitValue() : 0;
7513 	}
7514 
7515 	if (!gIOConsoleLoggedIn
7516 	    || (kIOMessageSystemWillSleep == sSystemPower)
7517 	    || (kIOMessageSystemPagingOff == sSystemPower)) {
7518 		if (afterUserspaceReboot) {
7519 			// set "locked" to false after a user space reboot
7520 			// because the reboot happens directly after a user
7521 			// logs into the machine via fvunlock mode.
7522 			locked = kOSBooleanFalse;
7523 		} else {
7524 			locked = kOSBooleanTrue;
7525 		}
7526 	}
7527 #if HIBERNATION
7528 	else if (gIOConsoleBooterLockState) {
7529 		locked = gIOConsoleBooterLockState;
7530 	}
7531 #endif /* HIBERNATION */
7532 	else if (gIOConsoleLockTime) {
7533 		clock_get_calendar_microtime(&now, &microsecs);
7534 		if (gIOConsoleLockTime > now) {
7535 			AbsoluteTime deadline;
7536 			clock_sec_t interval;
7537 			uint32_t interval32;
7538 
7539 			interval = (gIOConsoleLockTime - now);
7540 			interval32 = (uint32_t) interval;
7541 			if (interval32 != interval) {
7542 				interval32 = UINT_MAX;
7543 			}
7544 			clock_interval_to_deadline(interval32, kSecondScale, &deadline);
7545 			thread_call_enter_delayed(gIOConsoleLockCallout, deadline);
7546 		} else {
7547 			locked = kOSBooleanTrue;
7548 		}
7549 	}
7550 
7551 	publish = (consoleUsers || (locked != regEntry->getProperty(gIOConsoleLockedKey)));
7552 	if (publish) {
7553 		regEntry->setProperty(gIOConsoleLockedKey, locked);
7554 		if (consoleUsers) {
7555 			regEntry->setProperty(gIOConsoleUsersKey, consoleUsers);
7556 		}
7557 		OSIncrementAtomic( &gIOConsoleUsersSeed );
7558 	}
7559 
7560 #if HIBERNATION
7561 	if (gIOChosenEntry) {
7562 		if (locked == kOSBooleanTrue) {
7563 			gIOScreenLockState = kIOScreenLockLocked;
7564 		} else if (gIOConsoleLockTime) {
7565 			gIOScreenLockState = kIOScreenLockUnlocked;
7566 		} else {
7567 			gIOScreenLockState = kIOScreenLockNoLock;
7568 		}
7569 		gIOChosenEntry->setProperty(kIOScreenLockStateKey, &gIOScreenLockState, sizeof(gIOScreenLockState));
7570 
7571 		IOLog("IOConsoleUsers: gIOScreenLockState %d, hs %d, bs %d, now %ld, sm 0x%x\n",
7572 		    gIOScreenLockState, gIOHibernateState, (gIOConsoleBooterLockState != NULL), now, systemMessage);
7573 	}
7574 #endif /* HIBERNATION */
7575 
7576 	IOLockUnlock(gIOConsoleUsersLock);
7577 
7578 	if (publish) {
7579 		publishResource( gIOConsoleUsersSeedKey, gIOConsoleUsersSeedValue );
7580 
7581 		MessageClientsContext context;
7582 
7583 		context.service  = getServiceRoot();
7584 		context.type     = kIOMessageConsoleSecurityChange;
7585 		context.argument = (void *) regEntry;
7586 		context.argSize  = 0;
7587 
7588 		applyToInterestNotifiers(getServiceRoot(), gIOConsoleSecurityInterest,
7589 		    &messageClientsApplier, &context );
7590 	}
7591 }
7592 
7593 IOReturn
setProperties(OSObject * properties)7594 IOResources::setProperties( OSObject * properties )
7595 {
7596 	IOReturn                    err;
7597 	const OSSymbol *            key;
7598 	OSDictionary *              dict;
7599 	OSCollectionIterator *      iter;
7600 
7601 	if (!IOCurrentTaskHasEntitlement(kIOResourcesSetPropertyKey)) {
7602 		err = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
7603 		if (kIOReturnSuccess != err) {
7604 			return err;
7605 		}
7606 	}
7607 
7608 	dict = OSDynamicCast(OSDictionary, properties);
7609 	if (NULL == dict) {
7610 		return kIOReturnBadArgument;
7611 	}
7612 
7613 	iter = OSCollectionIterator::withCollection( dict);
7614 	if (NULL == iter) {
7615 		return kIOReturnBadArgument;
7616 	}
7617 
7618 	while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
7619 		if (gIOConsoleUsersKey == key) {
7620 			do{
7621 				OSArray * consoleUsers;
7622 				consoleUsers = OSDynamicCast(OSArray, dict->getObject(key));
7623 				if (!consoleUsers) {
7624 					continue;
7625 				}
7626 				IOService::updateConsoleUsers(consoleUsers, 0);
7627 			}while (false);
7628 		}
7629 
7630 		publishResource( key, dict->getObject(key));
7631 	}
7632 
7633 	iter->release();
7634 
7635 	return kIOReturnSuccess;
7636 }
7637 
7638 /*
7639  * Helpers for matching dictionaries.
7640  * Keys existing in matching are checked in properties.
7641  * Keys may be a string or OSCollection of IOStrings
7642  */
7643 
7644 bool
compareProperty(OSDictionary * matching,const char * key)7645 IOService::compareProperty( OSDictionary * matching,
7646     const char *   key )
7647 {
7648 	OSObject *  value;
7649 	OSObject *  prop;
7650 	bool        ok;
7651 
7652 	value = matching->getObject( key );
7653 	if (value) {
7654 		prop = copyProperty(key);
7655 		ok = value->isEqualTo(prop);
7656 		if (prop) {
7657 			prop->release();
7658 		}
7659 	} else {
7660 		ok = true;
7661 	}
7662 
7663 	return ok;
7664 }
7665 
7666 
7667 bool
compareProperty(OSDictionary * matching,const OSString * key)7668 IOService::compareProperty( OSDictionary *   matching,
7669     const OSString * key )
7670 {
7671 	OSObject *  value;
7672 	OSObject *  prop;
7673 	bool        ok;
7674 
7675 	value = matching->getObject( key );
7676 	if (value) {
7677 		prop = copyProperty(key);
7678 		ok = value->isEqualTo(prop);
7679 		if (prop) {
7680 			prop->release();
7681 		}
7682 	} else {
7683 		ok = true;
7684 	}
7685 
7686 	return ok;
7687 }
7688 
7689 #ifndef __clang_analyzer__
7690 // Implementation of this function is hidden from the static analyzer.
7691 // The analyzer was worried about this function's confusing contract over
7692 // the 'keys' parameter. The contract is to either release it or not release it
7693 // depending on whether 'matching' is non-null. Such contracts are discouraged
7694 // but changing it now would break compatibility.
7695 bool
compareProperties(OSDictionary * matching,OSCollection * keys)7696 IOService::compareProperties( OSDictionary * matching,
7697     OSCollection * keys )
7698 {
7699 	OSCollectionIterator *      iter;
7700 	const OSString *            key;
7701 	bool                        ok = true;
7702 
7703 	if (!matching || !keys) {
7704 		return false;
7705 	}
7706 
7707 	iter = OSCollectionIterator::withCollection( keys );
7708 
7709 	if (iter) {
7710 		while (ok && (key = OSDynamicCast( OSString, iter->getNextObject()))) {
7711 			ok = compareProperty( matching, key );
7712 		}
7713 
7714 		iter->release();
7715 	}
7716 	keys->release(); // !! consume a ref !!
7717 
7718 	return ok;
7719 }
7720 #endif // __clang_analyzer__
7721 
7722 /* Helper to add a location matching dict to the table */
7723 
7724 OSDictionary *
addLocation(OSDictionary * table)7725 IOService::addLocation( OSDictionary * table )
7726 {
7727 	OSDictionary *      dict;
7728 
7729 	if (!table) {
7730 		return NULL;
7731 	}
7732 
7733 	dict = OSDictionary::withCapacity( 1 );
7734 	if (dict) {
7735 		bool ok = table->setObject( gIOLocationMatchKey, dict );
7736 		dict->release();
7737 		if (!ok) {
7738 			dict = NULL;
7739 		}
7740 	}
7741 
7742 	return dict;
7743 }
7744 
7745 /*
7746  * Go looking for a provider to match a location dict.
7747  */
7748 
7749 IOService *
matchLocation(IOService *)7750 IOService::matchLocation( IOService * /* client */ )
7751 {
7752 	IOService * parent;
7753 
7754 	parent = getProvider();
7755 
7756 	if (parent) {
7757 		parent = parent->matchLocation( this );
7758 	}
7759 
7760 	return parent;
7761 }
7762 
7763 OSDictionary *
_copyPropertiesForMatching(void)7764 IOService::_copyPropertiesForMatching(void)
7765 {
7766 	OSDictionary * matchProps;
7767 
7768 	matchProps = dictionaryWithProperties();
7769 	if (matchProps) {
7770 		// merge will check the OSDynamicCast
7771 		matchProps->merge((const OSDictionary *)matchProps->getObject(gIOUserServicePropertiesKey));
7772 	}
7773 	return matchProps;
7774 }
7775 
7776 bool
matchInternal(OSDictionary * table,uint32_t options,uint32_t * did)7777 IOService::matchInternal(OSDictionary * table, uint32_t options, uint32_t * did)
7778 {
7779 	OSString *          matched;
7780 	OSObject *          obj;
7781 	OSString *          str;
7782 	OSDictionary *      matchProps;
7783 	IORegistryEntry *   entry;
7784 	OSNumber *          num;
7785 	bool                match = true;
7786 	bool                changesOK = (0 != (kIOServiceChangesOK & options));
7787 	uint32_t            count;
7788 	uint32_t            done;
7789 
7790 	do{
7791 		count = table->getCount();
7792 		done = 0;
7793 		matchProps = NULL;
7794 		bool isUser;
7795 
7796 		isUser = (NULL != table->getObject(gIOServiceNotificationUserKey));
7797 		if (isUser) {
7798 			done++;
7799 			match = (0 == (kIOServiceUserInvisibleMatchState & __state[0]));
7800 			if ((!match) || (done == count)) {
7801 				break;
7802 			}
7803 		}
7804 
7805 		if (propertyExists(gIOExclaveAssignedKey)) {
7806 			if (!table->getObject(gIOExclaveProxyKey) && !isUser) {
7807 				match = false;
7808 				break;
7809 			}
7810 		} else if (table->getObject(gIOExclaveProxyKey)) {
7811 			match = false;
7812 			break;
7813 		}
7814 
7815 		if (table->getObject(gIOCompatibilityMatchKey)) {
7816 			done++;
7817 			obj = copyProperty(gIOCompatibilityPropertiesKey);
7818 			matchProps = OSDynamicCast(OSDictionary, obj);
7819 			if (!matchProps) {
7820 				OSSafeReleaseNULL(obj);
7821 			}
7822 		}
7823 
7824 		str = OSDynamicCast(OSString, table->getObject(gIOProviderClassKey));
7825 		if (str) {
7826 			done++;
7827 			if (matchProps && (obj = matchProps->getObject(gIOClassKey))) {
7828 				match = str->isEqualTo(obj);
7829 			} else {
7830 				match = ((kIOServiceClassDone & options) || (NULL != metaCast(str)));
7831 			}
7832 
7833 #if MATCH_DEBUG
7834 			match = (0 != metaCast( str ));
7835 			if ((kIOServiceClassDone & options) && !match) {
7836 				panic("classDone");
7837 			}
7838 #endif
7839 			if ((!match) || (done == count)) {
7840 				break;
7841 			}
7842 		}
7843 
7844 		obj = table->getObject( gIONameMatchKey );
7845 		if (obj) {
7846 			done++;
7847 			match = compareNames( obj, changesOK ? &matched : NULL );
7848 			if (!match) {
7849 				break;
7850 			}
7851 			if (changesOK && matched) {
7852 				// leave a hint as to which name matched
7853 				table->setObject( gIONameMatchedKey, matched );
7854 				matched->release();
7855 			}
7856 			if (done == count) {
7857 				break;
7858 			}
7859 		}
7860 
7861 		str = OSDynamicCast( OSString, table->getObject( gIOLocationMatchKey ));
7862 		if (str) {
7863 			const OSSymbol * sym;
7864 			done++;
7865 			match = false;
7866 			sym = copyLocation();
7867 			if (sym) {
7868 				match = sym->isEqualTo( str );
7869 				sym->release();
7870 			}
7871 			if ((!match) || (done == count)) {
7872 				break;
7873 			}
7874 		}
7875 
7876 		obj = table->getObject( gIOPropertyMatchKey );
7877 		if (obj) {
7878 			OSDictionary * nextDict;
7879 			OSIterator *   iter;
7880 			done++;
7881 			match = false;
7882 			if (!matchProps) {
7883 				matchProps = _copyPropertiesForMatching();
7884 			}
7885 			if (matchProps) {
7886 				nextDict = OSDynamicCast( OSDictionary, obj);
7887 				if (nextDict) {
7888 					iter = NULL;
7889 				} else {
7890 					iter = OSCollectionIterator::withCollection(
7891 						OSDynamicCast(OSCollection, obj));
7892 				}
7893 
7894 				while (nextDict
7895 				    || (iter && (NULL != (nextDict = OSDynamicCast(OSDictionary,
7896 				    iter->getNextObject()))))) {
7897 					match = matchProps->isEqualTo( nextDict, nextDict);
7898 					if (match) {
7899 						break;
7900 					}
7901 					nextDict = NULL;
7902 				}
7903 				if (iter) {
7904 					iter->release();
7905 				}
7906 			}
7907 			if ((!match) || (done == count)) {
7908 				break;
7909 			}
7910 		}
7911 
7912 		obj = table->getObject( gIOPropertyExistsMatchKey );
7913 		if (obj) {
7914 			OSString     * nextKey;
7915 			OSIterator *   iter;
7916 			done++;
7917 			match = false;
7918 			if (!matchProps) {
7919 				matchProps = _copyPropertiesForMatching();
7920 			}
7921 			if (matchProps) {
7922 				nextKey = OSDynamicCast( OSString, obj);
7923 				if (nextKey) {
7924 					iter = NULL;
7925 				} else {
7926 					iter = OSCollectionIterator::withCollection(
7927 						OSDynamicCast(OSCollection, obj));
7928 				}
7929 
7930 				while (nextKey
7931 				    || (iter && (NULL != (nextKey = OSDynamicCast(OSString,
7932 				    iter->getNextObject()))))) {
7933 					match = (NULL != matchProps->getObject(nextKey));
7934 					if (match) {
7935 						break;
7936 					}
7937 					nextKey = NULL;
7938 				}
7939 				if (iter) {
7940 					iter->release();
7941 				}
7942 			}
7943 			if ((!match) || (done == count)) {
7944 				break;
7945 			}
7946 		}
7947 
7948 		str = OSDynamicCast( OSString, table->getObject( gIOPathMatchKey ));
7949 		if (str) {
7950 			done++;
7951 			entry = IORegistryEntry::fromPath( str->getCStringNoCopy());
7952 			match = (this == entry);
7953 			if (entry) {
7954 				entry->release();
7955 			}
7956 			if (!match && matchProps && (obj = matchProps->getObject(gIOPathKey))) {
7957 				match = str->isEqualTo(obj);
7958 			}
7959 			if ((!match) || (done == count)) {
7960 				break;
7961 			}
7962 		}
7963 
7964 		num = OSDynamicCast( OSNumber, table->getObject( gIORegistryEntryIDKey ));
7965 		if (num) {
7966 			done++;
7967 			match = (getRegistryEntryID() == num->unsigned64BitValue());
7968 			if ((!match) || (done == count)) {
7969 				break;
7970 			}
7971 		}
7972 
7973 		num = OSDynamicCast( OSNumber, table->getObject( gIOMatchedServiceCountKey ));
7974 		if (num) {
7975 			OSIterator *        iter;
7976 			IOService *         service = NULL;
7977 			UInt32              serviceCount = 0;
7978 
7979 			done++;
7980 			iter = getClientIterator();
7981 			if (iter) {
7982 				while ((service = (IOService *) iter->getNextObject())) {
7983 					if (kIOServiceInactiveState & service->__state[0]) {
7984 						continue;
7985 					}
7986 					if (NULL == service->getProperty( gIOMatchCategoryKey )) {
7987 						continue;
7988 					}
7989 					++serviceCount;
7990 				}
7991 				iter->release();
7992 			}
7993 			match = (serviceCount == num->unsigned32BitValue());
7994 			if ((!match) || (done == count)) {
7995 				break;
7996 			}
7997 		}
7998 
7999 #define propMatch(key)                                  \
8000 	obj = table->getObject(key);                    \
8001 	if (obj)                                        \
8002 	{                                               \
8003 	    OSObject * prop;                            \
8004 	    done++;                                     \
8005 	    prop = copyProperty(key);                   \
8006 	    match = obj->isEqualTo(prop);               \
8007 	    if (prop) prop->release();                  \
8008 	    if ((!match) || (done == count)) break;     \
8009 	}
8010 		propMatch(gIOBSDNameKey)
8011 		propMatch(gIOBSDMajorKey)
8012 		propMatch(gIOBSDMinorKey)
8013 		propMatch(gIOBSDUnitKey)
8014 #undef propMatch
8015 	}while (false);
8016 
8017 	OSSafeReleaseNULL(matchProps);
8018 
8019 	if (did) {
8020 		*did = done;
8021 	}
8022 	return match;
8023 }
8024 
8025 bool
passiveMatch(OSDictionary * table,bool changesOK)8026 IOService::passiveMatch( OSDictionary * table, bool changesOK )
8027 {
8028 	return matchPassive(table, changesOK ? kIOServiceChangesOK : 0);
8029 }
8030 
8031 bool
matchPassive(OSDictionary * table,uint32_t options)8032 IOService::matchPassive(OSDictionary * table, uint32_t options)
8033 {
8034 	IOService *         where;
8035 	OSDictionary *      nextTable;
8036 	SInt32              score;
8037 	OSNumber *          newPri;
8038 	bool                match = true;
8039 	bool                matchParent = false;
8040 	uint32_t            count;
8041 	uint32_t            done;
8042 
8043 	assert( table );
8044 
8045 #if defined(XNU_TARGET_OS_OSX)
8046 	OSArray* aliasServiceRegIds = NULL;
8047 	IOService* foundAlternateService = NULL;
8048 #endif /* defined(XNU_TARGET_OS_OSX) */
8049 
8050 #if MATCH_DEBUG
8051 	OSDictionary * root = table;
8052 #endif
8053 
8054 	where = this;
8055 	do{
8056 		do{
8057 			count = table->getCount();
8058 			if (!(kIOServiceInternalDone & options)) {
8059 				match = where->matchInternal(table, options, &done);
8060 				// don't call family if we've done all the entries in the table
8061 				if ((!match) || (done == count)) {
8062 					break;
8063 				}
8064 			}
8065 
8066 			// pass in score from property table
8067 			score = IOServiceObjectOrder( table, (void *) gIOProbeScoreKey);
8068 
8069 			// do family specific matching
8070 			match = where->matchPropertyTable( table, &score );
8071 
8072 			if (!match) {
8073 #if IOMATCHDEBUG
8074 				if (kIOLogMatch & getDebugFlags( table )) {
8075 					LOG("%s: family specific matching fails\n", where->getName());
8076 				}
8077 #endif
8078 				break;
8079 			}
8080 
8081 			if (kIOServiceChangesOK & options) {
8082 				// save the score
8083 				newPri = OSNumber::withNumber( score, 32 );
8084 				if (newPri) {
8085 					table->setObject( gIOProbeScoreKey, newPri );
8086 					newPri->release();
8087 				}
8088 			}
8089 
8090 			options = 0;
8091 			matchParent = false;
8092 
8093 			nextTable = OSDynamicCast(OSDictionary,
8094 			    table->getObject( gIOParentMatchKey ));
8095 			if (nextTable) {
8096 				// look for a matching entry anywhere up to root
8097 				match = false;
8098 				matchParent = true;
8099 				table = nextTable;
8100 				break;
8101 			}
8102 
8103 			table = OSDynamicCast(OSDictionary,
8104 			    table->getObject( gIOLocationMatchKey ));
8105 			if (table) {
8106 				// look for a matching entry at matchLocation()
8107 				match = false;
8108 				where = where->getProvider();
8109 				if (where && (where = where->matchLocation(where))) {
8110 					continue;
8111 				}
8112 			}
8113 			break;
8114 		}while (true);
8115 
8116 		if (match == true) {
8117 			break;
8118 		}
8119 
8120 		if (matchParent == true) {
8121 #if defined(XNU_TARGET_OS_OSX)
8122 			// check if service has an alias to search its other "parents" if a parent match isn't found
8123 			OSObject * prop = where->copyProperty(gIOServiceLegacyMatchingRegistryIDKey);
8124 			OSNumber * alternateRegistryID = OSDynamicCast(OSNumber, prop);
8125 			if (alternateRegistryID != NULL) {
8126 				if (aliasServiceRegIds == NULL) {
8127 					aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID));
8128 				}
8129 				aliasServiceRegIds->setObject(alternateRegistryID);
8130 			}
8131 			OSSafeReleaseNULL(prop);
8132 #endif /* defined(XNU_TARGET_OS_OSX) */
8133 		} else {
8134 			break;
8135 		}
8136 
8137 		where = where->getProvider();
8138 #if defined(XNU_TARGET_OS_OSX)
8139 		if (where == NULL) {
8140 			// there were no matching parent services, check to see if there are aliased services that have a matching parent
8141 			if (aliasServiceRegIds != NULL) {
8142 				unsigned int numAliasedServices = aliasServiceRegIds->getCount();
8143 				if (numAliasedServices != 0) {
8144 					OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, aliasServiceRegIds->getObject(numAliasedServices - 1));
8145 					if (alternateRegistryID != NULL) {
8146 						OSDictionary* alternateMatchingDict = IOService::registryEntryIDMatching(alternateRegistryID->unsigned64BitValue());
8147 						aliasServiceRegIds->removeObject(numAliasedServices - 1);
8148 						if (alternateMatchingDict != NULL) {
8149 							OSSafeReleaseNULL(foundAlternateService);
8150 							foundAlternateService = IOService::copyMatchingService(alternateMatchingDict);
8151 							alternateMatchingDict->release();
8152 							if (foundAlternateService != NULL) {
8153 								where = foundAlternateService;
8154 							}
8155 						}
8156 					}
8157 				}
8158 			}
8159 		}
8160 #endif /* defined(XNU_TARGET_OS_OSX) */
8161 	}while (where != NULL);
8162 
8163 #if defined(XNU_TARGET_OS_OSX)
8164 	OSSafeReleaseNULL(foundAlternateService);
8165 	OSSafeReleaseNULL(aliasServiceRegIds);
8166 #endif /* defined(XNU_TARGET_OS_OSX) */
8167 
8168 #if MATCH_DEBUG
8169 	if (where != this) {
8170 		OSSerialize * s = OSSerialize::withCapacity(128);
8171 		root->serialize(s);
8172 		kprintf("parent match 0x%llx, %d,\n%s\n", getRegistryEntryID(), match, s->text());
8173 		s->release();
8174 	}
8175 #endif
8176 
8177 	return match;
8178 }
8179 
8180 
8181 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,IOUserClient ** handler)8182 IOService::newUserClient( task_t owningTask, void * securityID,
8183     UInt32 type, OSDictionary * properties,
8184     IOUserClient ** handler )
8185 {
8186 	const OSSymbol *userClientClass = NULL;
8187 	IOUserClient *client;
8188 	OSObject *prop;
8189 	OSObject *temp;
8190 
8191 	if (reserved && reserved->uvars && reserved->uvars->userServer) {
8192 		return reserved->uvars->userServer->serviceNewUserClient(this, owningTask, securityID, type, properties, handler);
8193 	}
8194 
8195 	if (kIOReturnSuccess == newUserClient( owningTask, securityID, type, handler )) {
8196 		return kIOReturnSuccess;
8197 	}
8198 
8199 	// First try my own properties for a user client class name
8200 	prop = copyProperty(gIOUserClientClassKey);
8201 	if (prop) {
8202 		if (OSDynamicCast(OSSymbol, prop)) {
8203 			userClientClass = (const OSSymbol *) prop;
8204 			prop = NULL;
8205 		} else if (OSDynamicCast(OSString, prop)) {
8206 			userClientClass = OSSymbol::withString((OSString *) prop);
8207 			OSSafeReleaseNULL(prop);
8208 			if (userClientClass) {
8209 				setProperty(gIOUserClientClassKey,
8210 				    (OSObject *) userClientClass);
8211 			}
8212 		} else {
8213 			OSSafeReleaseNULL(prop);
8214 		}
8215 	}
8216 
8217 	// Didn't find one so lets just bomb out now without further ado.
8218 	if (!userClientClass) {
8219 		return kIOReturnUnsupported;
8220 	}
8221 
8222 	// This reference is consumed by the IOServiceOpen call
8223 	temp = OSMetaClass::allocClassWithName(userClientClass);
8224 	OSSafeReleaseNULL(userClientClass);
8225 	if (!temp) {
8226 		return kIOReturnNoMemory;
8227 	}
8228 
8229 	if (OSDynamicCast(IOUserClient, temp)) {
8230 		client = (IOUserClient *) temp;
8231 	} else {
8232 		temp->release();
8233 		return kIOReturnUnsupported;
8234 	}
8235 
8236 	if (!client->initWithTask(owningTask, securityID, type, properties)) {
8237 		client->release();
8238 		return kIOReturnBadArgument;
8239 	}
8240 
8241 	if (!client->attach(this)) {
8242 		client->release();
8243 		return kIOReturnUnsupported;
8244 	}
8245 
8246 	if (!client->start(this)) {
8247 		client->detach(this);
8248 		client->release();
8249 		return kIOReturnUnsupported;
8250 	}
8251 
8252 	*handler = client;
8253 	return kIOReturnSuccess;
8254 }
8255 
8256 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties,OSSharedPtr<IOUserClient> & handler)8257 IOService::newUserClient( task_t owningTask, void * securityID,
8258     UInt32 type, OSDictionary * properties,
8259     OSSharedPtr<IOUserClient>& handler )
8260 {
8261 	IOUserClient* handlerRaw = NULL;
8262 	IOReturn result = newUserClient(owningTask, securityID, type, properties, &handlerRaw);
8263 	handler.reset(handlerRaw, OSNoRetain);
8264 	return result;
8265 }
8266 
8267 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,IOUserClient ** handler)8268 IOService::newUserClient( task_t owningTask, void * securityID,
8269     UInt32 type, IOUserClient ** handler )
8270 {
8271 	return kIOReturnUnsupported;
8272 }
8273 
8274 IOReturn
newUserClient(task_t owningTask,void * securityID,UInt32 type,OSSharedPtr<IOUserClient> & handler)8275 IOService::newUserClient( task_t owningTask, void * securityID,
8276     UInt32 type, OSSharedPtr<IOUserClient>& handler )
8277 {
8278 	IOUserClient* handlerRaw = nullptr;
8279 	IOReturn result = IOService::newUserClient(owningTask, securityID, type, &handlerRaw);
8280 	handler.reset(handlerRaw, OSNoRetain);
8281 	return result;
8282 }
8283 
8284 
8285 IOReturn
requestProbe(IOOptionBits options)8286 IOService::requestProbe( IOOptionBits options )
8287 {
8288 	return kIOReturnUnsupported;
8289 }
8290 
8291 bool
hasUserServer() const8292 IOService::hasUserServer() const
8293 {
8294 	return reserved && reserved->uvars && reserved->uvars->userServer;
8295 }
8296 
8297 /*
8298  * Convert an IOReturn to text. Subclasses which add additional
8299  * IOReturn's should override this method and call
8300  * super::stringFromReturn if the desired value is not found.
8301  */
8302 
8303 const char *
stringFromReturn(IOReturn rtn)8304 IOService::stringFromReturn( IOReturn rtn )
8305 {
8306 	static const IONamedValue IOReturn_values[] = {
8307 		{kIOReturnSuccess, "success"                           },
8308 		{kIOReturnError, "general error"                     },
8309 		{kIOReturnNoMemory, "memory allocation error"           },
8310 		{kIOReturnNoResources, "resource shortage"                 },
8311 		{kIOReturnIPCError, "Mach IPC failure"                  },
8312 		{kIOReturnNoDevice, "no such device"                    },
8313 		{kIOReturnNotPrivileged, "privilege violation"               },
8314 		{kIOReturnBadArgument, "invalid argument"                  },
8315 		{kIOReturnLockedRead, "device is read locked"             },
8316 		{kIOReturnLockedWrite, "device is write locked"            },
8317 		{kIOReturnExclusiveAccess, "device is exclusive access"        },
8318 		{kIOReturnBadMessageID, "bad IPC message ID"                },
8319 		{kIOReturnUnsupported, "unsupported function"              },
8320 		{kIOReturnVMError, "virtual memory error"              },
8321 		{kIOReturnInternalError, "internal driver error"             },
8322 		{kIOReturnIOError, "I/O error"                         },
8323 		{kIOReturnCannotLock, "cannot acquire lock"               },
8324 		{kIOReturnNotOpen, "device is not open"                },
8325 		{kIOReturnNotReadable, "device is not readable"            },
8326 		{kIOReturnNotWritable, "device is not writeable"           },
8327 		{kIOReturnNotAligned, "alignment error"                   },
8328 		{kIOReturnBadMedia, "media error"                       },
8329 		{kIOReturnStillOpen, "device is still open"              },
8330 		{kIOReturnRLDError, "rld failure"                       },
8331 		{kIOReturnDMAError, "DMA failure"                       },
8332 		{kIOReturnBusy, "device is busy"                    },
8333 		{kIOReturnTimeout, "I/O timeout"                       },
8334 		{kIOReturnOffline, "device is offline"                 },
8335 		{kIOReturnNotReady, "device is not ready"               },
8336 		{kIOReturnNotAttached, "device/channel is not attached"    },
8337 		{kIOReturnNoChannels, "no DMA channels available"         },
8338 		{kIOReturnNoSpace, "no space for data"                 },
8339 		{kIOReturnPortExists, "device port already exists"        },
8340 		{kIOReturnCannotWire, "cannot wire physical memory"       },
8341 		{kIOReturnNoInterrupt, "no interrupt attached"             },
8342 		{kIOReturnNoFrames, "no DMA frames enqueued"            },
8343 		{kIOReturnMessageTooLarge, "message is too large"              },
8344 		{kIOReturnNotPermitted, "operation is not permitted"        },
8345 		{kIOReturnNoPower, "device is without power"           },
8346 		{kIOReturnNoMedia, "media is not present"              },
8347 		{kIOReturnUnformattedMedia, "media is not formatted"            },
8348 		{kIOReturnUnsupportedMode, "unsupported mode"                  },
8349 		{kIOReturnUnderrun, "data underrun"                     },
8350 		{kIOReturnOverrun, "data overrun"                      },
8351 		{kIOReturnDeviceError, "device error"                      },
8352 		{kIOReturnNoCompletion, "no completion routine"             },
8353 		{kIOReturnAborted, "operation was aborted"             },
8354 		{kIOReturnNoBandwidth, "bus bandwidth would be exceeded"   },
8355 		{kIOReturnNotResponding, "device is not responding"          },
8356 		{kIOReturnInvalid, "unanticipated driver error"        },
8357 		{0, NULL                                }
8358 	};
8359 
8360 	return IOFindNameForValue(rtn, IOReturn_values);
8361 }
8362 
8363 /*
8364  * Convert an IOReturn to an errno.
8365  */
8366 int
errnoFromReturn(IOReturn rtn)8367 IOService::errnoFromReturn( IOReturn rtn )
8368 {
8369 	if (unix_err(err_get_code(rtn)) == rtn) {
8370 		return err_get_code(rtn);
8371 	}
8372 
8373 	switch (rtn) {
8374 	// (obvious match)
8375 	case kIOReturnSuccess:
8376 		return 0;
8377 	case kIOReturnNoMemory:
8378 		return ENOMEM;
8379 	case kIOReturnNoDevice:
8380 		return ENXIO;
8381 	case kIOReturnVMError:
8382 		return EFAULT;
8383 	case kIOReturnNotPermitted:
8384 		return EPERM;
8385 	case kIOReturnNotPrivileged:
8386 		return EACCES;
8387 	case kIOReturnIOError:
8388 		return EIO;
8389 	case kIOReturnNotWritable:
8390 		return EROFS;
8391 	case kIOReturnBadArgument:
8392 		return EINVAL;
8393 	case kIOReturnUnsupported:
8394 		return ENOTSUP;
8395 	case kIOReturnBusy:
8396 		return EBUSY;
8397 	case kIOReturnNoPower:
8398 		return EPWROFF;
8399 	case kIOReturnDeviceError:
8400 		return EDEVERR;
8401 	case kIOReturnTimeout:
8402 		return ETIMEDOUT;
8403 	case kIOReturnMessageTooLarge:
8404 		return EMSGSIZE;
8405 	case kIOReturnNoSpace:
8406 		return ENOSPC;
8407 	case kIOReturnCannotLock:
8408 		return ENOLCK;
8409 
8410 	// (best match)
8411 	case kIOReturnBadMessageID:
8412 	case kIOReturnNoCompletion:
8413 	case kIOReturnNotAligned:
8414 		return EINVAL;
8415 	case kIOReturnNotReady:
8416 		return EBUSY;
8417 	case kIOReturnRLDError:
8418 		return EBADMACHO;
8419 	case kIOReturnPortExists:
8420 	case kIOReturnStillOpen:
8421 		return EEXIST;
8422 	case kIOReturnExclusiveAccess:
8423 	case kIOReturnLockedRead:
8424 	case kIOReturnLockedWrite:
8425 	case kIOReturnNotOpen:
8426 	case kIOReturnNotReadable:
8427 		return EACCES;
8428 	case kIOReturnCannotWire:
8429 	case kIOReturnNoResources:
8430 		return ENOMEM;
8431 	case kIOReturnAborted:
8432 	case kIOReturnOffline:
8433 	case kIOReturnNotResponding:
8434 		return EBUSY;
8435 	case kIOReturnBadMedia:
8436 	case kIOReturnNoMedia:
8437 	case kIOReturnNotAttached:
8438 	case kIOReturnUnformattedMedia:
8439 		return ENXIO; // (media error)
8440 	case kIOReturnDMAError:
8441 	case kIOReturnOverrun:
8442 	case kIOReturnUnderrun:
8443 		return EIO; // (transfer error)
8444 	case kIOReturnNoBandwidth:
8445 	case kIOReturnNoChannels:
8446 	case kIOReturnNoFrames:
8447 	case kIOReturnNoInterrupt:
8448 		return EIO; // (hardware error)
8449 	case kIOReturnError:
8450 	case kIOReturnInternalError:
8451 	case kIOReturnInvalid:
8452 		return EIO; // (generic error)
8453 	case kIOReturnIPCError:
8454 		return EIO; // (ipc error)
8455 	default:
8456 		return EIO; // (all other errors)
8457 	}
8458 }
8459 
8460 IOReturn
message(UInt32 type,IOService * provider,void * argument)8461 IOService::message( UInt32 type, IOService * provider,
8462     void * argument )
8463 {
8464 	/*
8465 	 * Generic entry point for calls from the provider.  A return value of
8466 	 * kIOReturnSuccess indicates that the message was received, and where
8467 	 * applicable, that it was successful.
8468 	 */
8469 
8470 	return kIOReturnUnsupported;
8471 }
8472 
8473 /*
8474  * Device memory
8475  */
8476 
8477 IOItemCount
getDeviceMemoryCount(void)8478 IOService::getDeviceMemoryCount( void )
8479 {
8480 	OSArray *           array;
8481 	IOItemCount         count;
8482 
8483 	array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
8484 	if (array) {
8485 		count = array->getCount();
8486 	} else {
8487 		count = 0;
8488 	}
8489 
8490 	return count;
8491 }
8492 
8493 IODeviceMemory *
getDeviceMemoryWithIndex(unsigned int index)8494 IOService::getDeviceMemoryWithIndex( unsigned int index )
8495 {
8496 	OSArray *           array;
8497 	IODeviceMemory *    range;
8498 
8499 	array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
8500 	if (array) {
8501 		range = (IODeviceMemory *) array->getObject( index );
8502 	} else {
8503 		range = NULL;
8504 	}
8505 
8506 	return range;
8507 }
8508 
8509 IOMemoryMap *
mapDeviceMemoryWithIndex(unsigned int index,IOOptionBits options)8510 IOService::mapDeviceMemoryWithIndex( unsigned int index,
8511     IOOptionBits options )
8512 {
8513 	IODeviceMemory *    range;
8514 	IOMemoryMap *       map;
8515 
8516 	range = getDeviceMemoryWithIndex( index );
8517 	if (range) {
8518 		map = range->map( options );
8519 	} else {
8520 		map = NULL;
8521 	}
8522 
8523 	return map;
8524 }
8525 
8526 OSArray *
getDeviceMemory(void)8527 IOService::getDeviceMemory( void )
8528 {
8529 	return OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
8530 }
8531 
8532 
8533 void
setDeviceMemory(OSArray * array)8534 IOService::setDeviceMemory( OSArray * array )
8535 {
8536 	setProperty( gIODeviceMemoryKey, array);
8537 }
8538 
8539 static void
requireMaxCpuDelay(IOService * service,UInt32 ns,UInt32 delayType)8540 requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType)
8541 {
8542 	static const UInt kNoReplace = -1U; // Must be an illegal index
8543 	UInt replace = kNoReplace;
8544 	bool setCpuDelay = false;
8545 
8546 	IORecursiveLockLock(sCpuDelayLock);
8547 
8548 	UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
8549 	__typed_allocators_ignore_push
8550 	CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
8551 	__typed_allocators_ignore_pop
8552 	IOService * holder = NULL;
8553 
8554 	if (ns) {
8555 		const CpuDelayEntry ne = {service, ns, delayType};
8556 		holder = service;
8557 		// Set maximum delay.
8558 		for (UInt i = 0; i < count; i++) {
8559 			IOService *thisService = entries[i].fService;
8560 			bool sameType = (delayType == entries[i].fDelayType);
8561 			if ((service == thisService) && sameType) {
8562 				replace = i;
8563 			} else if (!thisService) {
8564 				if (kNoReplace == replace) {
8565 					replace = i;
8566 				}
8567 			} else if (sameType) {
8568 				const UInt32 thisMax = entries[i].fMaxDelay;
8569 				if (thisMax < ns) {
8570 					ns = thisMax;
8571 					holder = thisService;
8572 				}
8573 			}
8574 		}
8575 
8576 		setCpuDelay = true;
8577 		if (kNoReplace == replace) {
8578 			__typed_allocators_ignore_push
8579 			sCpuDelayData->appendBytes(&ne, sizeof(ne));
8580 			__typed_allocators_ignore_pop
8581 		} else {
8582 			entries[replace] = ne;
8583 		}
8584 	} else {
8585 		ns = -1U; // Set to max unsigned, i.e. no restriction
8586 
8587 		for (UInt i = 0; i < count; i++) {
8588 			// Clear a maximum delay.
8589 			IOService *thisService = entries[i].fService;
8590 			if (thisService && (delayType == entries[i].fDelayType)) {
8591 				UInt32 thisMax = entries[i].fMaxDelay;
8592 				if (service == thisService) {
8593 					replace = i;
8594 				} else if (thisMax < ns) {
8595 					ns = thisMax;
8596 					holder = thisService;
8597 				}
8598 			}
8599 		}
8600 
8601 		// Check if entry found
8602 		if (kNoReplace != replace) {
8603 			entries[replace].fService = NULL; // Null the entry
8604 			setCpuDelay = true;
8605 		}
8606 	}
8607 
8608 	if (setCpuDelay) {
8609 		if (holder && debug_boot_arg) {
8610 			strlcpy(sCPULatencyHolderName[delayType], holder->getName(), sizeof(sCPULatencyHolderName[delayType]));
8611 		}
8612 
8613 		// Must be safe to call from locked context
8614 		if (delayType == kCpuDelayBusStall) {
8615 #if defined(__x86_64__)
8616 			ml_set_maxbusdelay(ns);
8617 #endif /* defined(__x86_64__) */
8618 		}
8619 #if defined(__x86_64__)
8620 		else if (delayType == kCpuDelayInterrupt) {
8621 			ml_set_maxintdelay(ns);
8622 		}
8623 #endif /* defined(__x86_64__) */
8624 		sCPULatencyHolder[delayType]->setValue(holder ? holder->getRegistryEntryID() : 0);
8625 		sCPULatencySet[delayType]->setValue(ns);
8626 
8627 		OSArray * handlers = sCpuLatencyHandlers[delayType];
8628 		IOService * target;
8629 		if (handlers) {
8630 			for (unsigned int idx = 0;
8631 			    (target = (IOService *) handlers->getObject(idx));
8632 			    idx++) {
8633 				target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
8634 				    (void *) (uintptr_t) ns, holder,
8635 				    NULL, NULL);
8636 			}
8637 		}
8638 	}
8639 
8640 	IORecursiveLockUnlock(sCpuDelayLock);
8641 }
8642 
8643 static IOReturn
setLatencyHandler(UInt32 delayType,IOService * target,bool enable)8644 setLatencyHandler(UInt32 delayType, IOService * target, bool enable)
8645 {
8646 	IOReturn result = kIOReturnNotFound;
8647 	OSArray * array;
8648 	unsigned int idx;
8649 
8650 	IORecursiveLockLock(sCpuDelayLock);
8651 
8652 	do{
8653 		if (enable && !sCpuLatencyHandlers[delayType]) {
8654 			sCpuLatencyHandlers[delayType] = OSArray::withCapacity(4);
8655 		}
8656 		array = sCpuLatencyHandlers[delayType];
8657 		if (!array) {
8658 			break;
8659 		}
8660 		idx = array->getNextIndexOfObject(target, 0);
8661 		if (!enable) {
8662 			if (-1U != idx) {
8663 				array->removeObject(idx);
8664 				result = kIOReturnSuccess;
8665 			}
8666 		} else {
8667 			if (-1U != idx) {
8668 				result = kIOReturnExclusiveAccess;
8669 				break;
8670 			}
8671 			array->setObject(target);
8672 
8673 			UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
8674 			__typed_allocators_ignore_push
8675 			CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
8676 			__typed_allocators_ignore_pop
8677 			UInt32 ns = -1U; // Set to max unsigned, i.e. no restriction
8678 			IOService * holder = NULL;
8679 
8680 			for (UInt i = 0; i < count; i++) {
8681 				if (entries[i].fService
8682 				    && (delayType == entries[i].fDelayType)
8683 				    && (entries[i].fMaxDelay < ns)) {
8684 					ns = entries[i].fMaxDelay;
8685 					holder = entries[i].fService;
8686 				}
8687 			}
8688 			target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
8689 			    (void *) (uintptr_t) ns, holder,
8690 			    NULL, NULL);
8691 			result = kIOReturnSuccess;
8692 		}
8693 	}while (false);
8694 
8695 	IORecursiveLockUnlock(sCpuDelayLock);
8696 
8697 	return result;
8698 }
8699 
8700 IOReturn
requireMaxBusStall(UInt32 ns)8701 IOService::requireMaxBusStall(UInt32 ns)
8702 {
8703 #if !defined(__x86_64__)
8704 	switch (ns) {
8705 	case kIOMaxBusStall40usec:
8706 	case kIOMaxBusStall30usec:
8707 	case kIOMaxBusStall25usec:
8708 	case kIOMaxBusStall20usec:
8709 	case kIOMaxBusStall10usec:
8710 	case kIOMaxBusStall5usec:
8711 	case kIOMaxBusStallNone:
8712 		break;
8713 	default:
8714 		return kIOReturnBadArgument;
8715 	}
8716 #endif /* !defined(__x86_64__) */
8717 	requireMaxCpuDelay(this, ns, kCpuDelayBusStall);
8718 	return kIOReturnSuccess;
8719 }
8720 
8721 IOReturn
requireMaxInterruptDelay(uint32_t ns)8722 IOService::requireMaxInterruptDelay(uint32_t ns)
8723 {
8724 #if defined(__x86_64__)
8725 	requireMaxCpuDelay(this, ns, kCpuDelayInterrupt);
8726 	return kIOReturnSuccess;
8727 #else /* defined(__x86_64__) */
8728 	return kIOReturnUnsupported;
8729 #endif /* defined(__x86_64__) */
8730 }
8731 
8732 /*
8733  * Device interrupts
8734  */
8735 
8736 IOReturn
resolveInterrupt(IOService * nub,int source)8737 IOService::resolveInterrupt(IOService *nub, int source)
8738 {
8739 	IOInterruptController *interruptController;
8740 	OSArray               *array;
8741 	OSData                *data;
8742 	OSSymbol              *interruptControllerName;
8743 	unsigned int           numSources;
8744 	IOInterruptSource     *interruptSources;
8745 	IOInterruptSourcePrivate *interruptSourcesPrivate;
8746 
8747 	// Get the parents list from the nub.
8748 	array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptControllersKey));
8749 	if (array == NULL) {
8750 		return kIOReturnNoResources;
8751 	}
8752 
8753 	// Allocate space for the IOInterruptSources if needed... then return early.
8754 	if (nub->_interruptSources == NULL) {
8755 		numSources = array->getCount();
8756 		interruptSources = IONewZero(IOInterruptSource, numSources);
8757 		interruptSourcesPrivate = IONewZero(IOInterruptSourcePrivate, numSources);
8758 
8759 		if (interruptSources == NULL || interruptSourcesPrivate == NULL) {
8760 			IODelete(interruptSources, IOInterruptSource, numSources);
8761 			IODelete(interruptSourcesPrivate, IOInterruptSourcePrivate, numSources);
8762 			return kIOReturnNoMemory;
8763 		}
8764 
8765 		nub->_numInterruptSources = numSources;
8766 		nub->_interruptSources = interruptSources;
8767 		nub->reserved->interruptSourcesPrivate = interruptSourcesPrivate;
8768 		return kIOReturnSuccess;
8769 	}
8770 
8771 	interruptControllerName = OSDynamicCast(OSSymbol, array->getObject(source));
8772 	if (interruptControllerName == NULL) {
8773 		return kIOReturnNoResources;
8774 	}
8775 
8776 	interruptController = getPlatform()->lookUpInterruptController(interruptControllerName);
8777 	if (interruptController == NULL) {
8778 		return kIOReturnNoResources;
8779 	}
8780 
8781 	// Get the interrupt numbers from the nub.
8782 	array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptSpecifiersKey));
8783 	if (array == NULL) {
8784 		return kIOReturnNoResources;
8785 	}
8786 	data = OSDynamicCast(OSData, array->getObject(source));
8787 	if (data == NULL) {
8788 		return kIOReturnNoResources;
8789 	}
8790 
8791 	// Set the interruptController and interruptSource in the nub's table.
8792 	interruptSources = nub->_interruptSources;
8793 	interruptSources[source].interruptController = interruptController;
8794 	interruptSources[source].vectorData = data;
8795 
8796 	return kIOReturnSuccess;
8797 }
8798 
8799 IOReturn
lookupInterrupt(int source,bool resolve,IOInterruptController ** interruptController)8800 IOService::lookupInterrupt(int source, bool resolve, IOInterruptController **interruptController)
8801 {
8802 	IOReturn ret;
8803 
8804 	/* Make sure the _interruptSources are set */
8805 	if (_interruptSources == NULL) {
8806 		ret = resolveInterrupt(this, source);
8807 		if (ret != kIOReturnSuccess) {
8808 			return ret;
8809 		}
8810 	}
8811 
8812 	/* Make sure the local source number is valid */
8813 	if ((source < 0) || (source >= _numInterruptSources)) {
8814 		return kIOReturnNoInterrupt;
8815 	}
8816 
8817 	/* Look up the contoller for the local source */
8818 	*interruptController = _interruptSources[source].interruptController;
8819 
8820 	if (*interruptController == NULL) {
8821 		if (!resolve) {
8822 			return kIOReturnNoInterrupt;
8823 		}
8824 
8825 		/* Try to resolve the interrupt */
8826 		ret = resolveInterrupt(this, source);
8827 		if (ret != kIOReturnSuccess) {
8828 			return ret;
8829 		}
8830 
8831 		*interruptController = _interruptSources[source].interruptController;
8832 	}
8833 
8834 	return kIOReturnSuccess;
8835 }
8836 
8837 IOReturn
registerInterrupt(int source,OSObject * target,IOInterruptAction handler,void * refCon)8838 IOService::registerInterrupt(int source, OSObject *target,
8839     IOInterruptAction handler,
8840     void *refCon)
8841 {
8842 	IOInterruptController *interruptController;
8843 	IOReturn              ret;
8844 
8845 	ret = lookupInterrupt(source, true, &interruptController);
8846 	if (ret != kIOReturnSuccess) {
8847 		return ret;
8848 	}
8849 
8850 	/* Register the source */
8851 	return interruptController->registerInterrupt(this, source, target,
8852 	           (IOInterruptHandler)handler,
8853 	           refCon);
8854 }
8855 
8856 static void
IOServiceInterruptActionToBlock(OSObject * target,void * refCon,IOService * nub,int source)8857 IOServiceInterruptActionToBlock( OSObject * target, void * refCon,
8858     IOService * nub, int source )
8859 {
8860 	((IOInterruptActionBlock)(refCon))(nub, source);
8861 }
8862 
8863 IOReturn
registerInterruptBlock(int source,OSObject * target,IOInterruptActionBlock handler)8864 IOService::registerInterruptBlock(int source, OSObject *target,
8865     IOInterruptActionBlock handler)
8866 {
8867 	IOReturn ret;
8868 	void   * block;
8869 
8870 	block = Block_copy(handler);
8871 	if (!block) {
8872 		return kIOReturnNoMemory;
8873 	}
8874 
8875 	ret = registerInterrupt(source, target, &IOServiceInterruptActionToBlock, block);
8876 	if (kIOReturnSuccess != ret) {
8877 		Block_release(block);
8878 		return ret;
8879 	}
8880 
8881 	reserved->interruptSourcesPrivate[source].vectorBlock = block;
8882 
8883 	return ret;
8884 }
8885 
8886 IOReturn
unregisterInterrupt(int source)8887 IOService::unregisterInterrupt(int source)
8888 {
8889 	IOReturn              ret;
8890 	IOInterruptController *interruptController;
8891 	IOInterruptSourcePrivate *priv;
8892 	void                  *block;
8893 
8894 	ret = lookupInterrupt(source, false, &interruptController);
8895 	if (ret != kIOReturnSuccess) {
8896 		return ret;
8897 	}
8898 
8899 	/* Unregister the source */
8900 	priv = &reserved->interruptSourcesPrivate[source];
8901 	block = priv->vectorBlock;
8902 	ret = interruptController->unregisterInterrupt(this, source);
8903 	if ((kIOReturnSuccess == ret) && (block = priv->vectorBlock)) {
8904 		priv->vectorBlock = NULL;
8905 		Block_release(block);
8906 	}
8907 
8908 	return ret;
8909 }
8910 
8911 void
unregisterAllInterrupts(void)8912 IOService::unregisterAllInterrupts(void)
8913 {
8914 	for (int source = 0; source < _numInterruptSources; source++) {
8915 		(void) unregisterInterrupt(source);
8916 	}
8917 }
8918 
8919 IOReturn
addInterruptStatistics(IOInterruptAccountingData * statistics,int source)8920 IOService::addInterruptStatistics(IOInterruptAccountingData * statistics, int source)
8921 {
8922 	IOReportLegend * legend = NULL;
8923 	IOInterruptAccountingData * oldValue = NULL;
8924 	IOInterruptAccountingReporter * newArray = NULL;
8925 	char subgroupName[64];
8926 	int newArraySize = 0;
8927 	int i = 0;
8928 
8929 	if (source < 0) {
8930 		return kIOReturnBadArgument;
8931 	}
8932 
8933 	/*
8934 	 * We support statistics on a maximum of 256 interrupts per nub; if a nub
8935 	 * has more than 256 interrupt specifiers associated with it, and tries
8936 	 * to register a high interrupt index with interrupt accounting, panic.
8937 	 * Having more than 256 interrupts associated with a single nub is
8938 	 * probably a sign that something fishy is going on.
8939 	 */
8940 	if (source > IA_INDEX_MAX) {
8941 		panic("addInterruptStatistics called for an excessively large index (%d)", source);
8942 	}
8943 
8944 	/*
8945 	 * TODO: This is ugly (wrapping a lock around an allocation).  I'm only
8946 	 * leaving it as is because the likelihood of contention where we are
8947 	 * actually growing the array is minimal (we would realistically need
8948 	 * to be starting a driver for the first time, with an IOReporting
8949 	 * client already in place).  Nonetheless, cleanup that can be done
8950 	 * to adhere to best practices; it'll make the code more complicated,
8951 	 * unfortunately.
8952 	 */
8953 	IOLockLock(&reserved->interruptStatisticsLock);
8954 
8955 	/*
8956 	 * Lazily allocate the statistics array.
8957 	 */
8958 	if (!reserved->interruptStatisticsArray) {
8959 		reserved->interruptStatisticsArray = IONew(IOInterruptAccountingReporter, 1);
8960 		assert(reserved->interruptStatisticsArray);
8961 		reserved->interruptStatisticsArrayCount = 1;
8962 		bzero(reserved->interruptStatisticsArray, sizeof(*reserved->interruptStatisticsArray));
8963 	}
8964 
8965 	if (source >= reserved->interruptStatisticsArrayCount) {
8966 		/*
8967 		 * We're still within the range of supported indices, but we are out
8968 		 * of space in the current array.  Do a nasty realloc (because
8969 		 * IORealloc isn't a thing) here.  We'll double the size with each
8970 		 * reallocation.
8971 		 *
8972 		 * Yes, the "next power of 2" could be more efficient; but this will
8973 		 * be invoked incredibly rarely.  Who cares.
8974 		 */
8975 		newArraySize = (reserved->interruptStatisticsArrayCount << 1);
8976 
8977 		while (newArraySize <= source) {
8978 			newArraySize = (newArraySize << 1);
8979 		}
8980 		newArray = IONew(IOInterruptAccountingReporter, newArraySize);
8981 
8982 		assert(newArray);
8983 
8984 		/*
8985 		 * TODO: This even zeroes the memory it is about to overwrite.
8986 		 * Shameful; fix it.  Not particularly high impact, however.
8987 		 */
8988 		bzero(newArray, newArraySize * sizeof(*newArray));
8989 		memcpy(newArray, reserved->interruptStatisticsArray, reserved->interruptStatisticsArrayCount * sizeof(*newArray));
8990 		IODelete(reserved->interruptStatisticsArray, IOInterruptAccountingReporter, reserved->interruptStatisticsArrayCount);
8991 		reserved->interruptStatisticsArray = newArray;
8992 		reserved->interruptStatisticsArrayCount = newArraySize;
8993 	}
8994 
8995 	if (!reserved->interruptStatisticsArray[source].reporter) {
8996 		/*
8997 		 * We don't have a reporter associated with this index yet, so we
8998 		 * need to create one.
8999 		 */
9000 		/*
9001 		 * TODO: Some statistics do in fact have common units (time); should this be
9002 		 * split into separate reporters to communicate this?
9003 		 */
9004 		reserved->interruptStatisticsArray[source].reporter = IOSimpleReporter::with(this, kIOReportCategoryPower, kIOReportUnitNone);
9005 
9006 		/*
9007 		 * Each statistic is given an identifier based on the interrupt index (which
9008 		 * should be unique relative to any single nub) and the statistic involved.
9009 		 * We should now have a sane (small and positive) index, so start
9010 		 * constructing the channels for statistics.
9011 		 */
9012 		for (i = 0; i < IA_NUM_INTERRUPT_ACCOUNTING_STATISTICS; i++) {
9013 			/*
9014 			 * TODO: Currently, this does not add channels for disabled statistics.
9015 			 * Will this be confusing for clients?  If so, we should just add the
9016 			 * channels; we can avoid updating the channels even if they exist.
9017 			 */
9018 			if (IA_GET_STATISTIC_ENABLED(i)) {
9019 				reserved->interruptStatisticsArray[source].reporter->addChannel(IA_GET_CHANNEL_ID(source, i), kInterruptAccountingStatisticNameArray[i]);
9020 			}
9021 		}
9022 
9023 		/*
9024 		 * We now need to add the legend for this reporter to the registry.
9025 		 */
9026 		OSObject * prop = copyProperty(kIOReportLegendKey);
9027 		legend = IOReportLegend::with(OSDynamicCast(OSArray, prop));
9028 		OSSafeReleaseNULL(prop);
9029 
9030 		/*
9031 		 * Note that while we compose the subgroup name, we do not need to
9032 		 * manage its lifecycle (the reporter will handle this).
9033 		 */
9034 		snprintf(subgroupName, sizeof(subgroupName), "%s %d", getName(), source);
9035 		subgroupName[sizeof(subgroupName) - 1] = 0;
9036 		legend->addReporterLegend(reserved->interruptStatisticsArray[source].reporter, kInterruptAccountingGroupName, subgroupName);
9037 		setProperty(kIOReportLegendKey, legend->getLegend());
9038 		legend->release();
9039 
9040 		/*
9041 		 * TODO: Is this a good idea?  Probably not; my assumption is it opts
9042 		 * all entities who register interrupts into public disclosure of all
9043 		 * IOReporting channels.  Unfortunately, this appears to be as fine
9044 		 * grain as it gets.
9045 		 */
9046 		setProperty(kIOReportLegendPublicKey, true);
9047 	}
9048 
9049 	/*
9050 	 * Don't stomp existing entries.  If we are about to, panic; this
9051 	 * probably means we failed to tear down our old interrupt source
9052 	 * correctly.
9053 	 */
9054 	oldValue = reserved->interruptStatisticsArray[source].statistics;
9055 
9056 	if (oldValue) {
9057 		panic("addInterruptStatistics call for index %d would have clobbered existing statistics", source);
9058 	}
9059 
9060 	reserved->interruptStatisticsArray[source].statistics = statistics;
9061 
9062 	/*
9063 	 * Inherit the reporter values for each statistic.  The target may
9064 	 * be torn down as part of the runtime of the service (especially
9065 	 * for sleep/wake), so we inherit in order to avoid having values
9066 	 * reset for no apparent reason.  Our statistics are ultimately
9067 	 * tied to the index and the sevice, not to an individual target,
9068 	 * so we should maintain them accordingly.
9069 	 */
9070 	interruptAccountingDataInheritChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
9071 
9072 	IOLockUnlock(&reserved->interruptStatisticsLock);
9073 
9074 	return kIOReturnSuccess;
9075 }
9076 
9077 IOReturn
removeInterruptStatistics(int source)9078 IOService::removeInterruptStatistics(int source)
9079 {
9080 	IOInterruptAccountingData * value = NULL;
9081 
9082 	if (source < 0) {
9083 		return kIOReturnBadArgument;
9084 	}
9085 
9086 	IOLockLock(&reserved->interruptStatisticsLock);
9087 
9088 	/*
9089 	 * We dynamically grow the statistics array, so an excessively
9090 	 * large index value has NEVER been registered.  This either
9091 	 * means our cap on the array size is too small (unlikely), or
9092 	 * that we have been passed a corrupt index (this must be passed
9093 	 * the plain index into the interrupt specifier list).
9094 	 */
9095 	if (source >= reserved->interruptStatisticsArrayCount) {
9096 		panic("removeInterruptStatistics called for index %d, which was never registered", source);
9097 	}
9098 
9099 	assert(reserved->interruptStatisticsArray);
9100 
9101 	/*
9102 	 * If there is no existing entry, we are most likely trying to
9103 	 * free an interrupt owner twice, or we have corrupted the
9104 	 * index value.
9105 	 */
9106 	value = reserved->interruptStatisticsArray[source].statistics;
9107 
9108 	if (!value) {
9109 		panic("removeInterruptStatistics called for empty index %d", source);
9110 	}
9111 
9112 	/*
9113 	 * We update the statistics, so that any delta with the reporter
9114 	 * state is not lost.
9115 	 */
9116 	interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
9117 	reserved->interruptStatisticsArray[source].statistics = NULL;
9118 	IOLockUnlock(&reserved->interruptStatisticsLock);
9119 
9120 	return kIOReturnSuccess;
9121 }
9122 
9123 IOReturn
getInterruptType(int source,int * interruptType)9124 IOService::getInterruptType(int source, int *interruptType)
9125 {
9126 	IOInterruptController *interruptController;
9127 	IOReturn              ret;
9128 
9129 	ret = lookupInterrupt(source, true, &interruptController);
9130 	if (ret != kIOReturnSuccess) {
9131 		return ret;
9132 	}
9133 
9134 	/* Return the type */
9135 	return interruptController->getInterruptType(this, source, interruptType);
9136 }
9137 
9138 IOReturn
enableInterrupt(int source)9139 IOService::enableInterrupt(int source)
9140 {
9141 	IOInterruptController *interruptController;
9142 	IOReturn              ret;
9143 
9144 	ret = lookupInterrupt(source, false, &interruptController);
9145 	if (ret != kIOReturnSuccess) {
9146 		return ret;
9147 	}
9148 
9149 	/* Enable the source */
9150 	return interruptController->enableInterrupt(this, source);
9151 }
9152 
9153 IOReturn
disableInterrupt(int source)9154 IOService::disableInterrupt(int source)
9155 {
9156 	IOInterruptController *interruptController;
9157 	IOReturn              ret;
9158 
9159 	ret = lookupInterrupt(source, false, &interruptController);
9160 	if (ret != kIOReturnSuccess) {
9161 		return ret;
9162 	}
9163 
9164 	/* Disable the source */
9165 	return interruptController->disableInterrupt(this, source);
9166 }
9167 
9168 IOReturn
causeInterrupt(int source)9169 IOService::causeInterrupt(int source)
9170 {
9171 	IOInterruptController *interruptController;
9172 	IOReturn              ret;
9173 
9174 	ret = lookupInterrupt(source, false, &interruptController);
9175 	if (ret != kIOReturnSuccess) {
9176 		return ret;
9177 	}
9178 
9179 	/* Cause an interrupt for the source */
9180 	return interruptController->causeInterrupt(this, source);
9181 }
9182 
9183 IOReturn
configureReport(IOReportChannelList * channelList,IOReportConfigureAction action,void * result,void * destination)9184 IOService::configureReport(IOReportChannelList    *channelList,
9185     IOReportConfigureAction action,
9186     void                   *result,
9187     void                   *destination)
9188 {
9189 	unsigned cnt;
9190 
9191 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9192 		if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
9193 			if (pwrMgt) {
9194 				configurePowerStatesReport(action, result);
9195 			} else {
9196 				return kIOReturnUnsupported;
9197 			}
9198 		} else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
9199 			if (pwrMgt) {
9200 				configureSimplePowerReport(action, result);
9201 			} else {
9202 				return kIOReturnUnsupported;
9203 			}
9204 		}
9205 	}
9206 
9207 	IOLockLock(&reserved->interruptStatisticsLock);
9208 
9209 	/* The array count is signed (because the interrupt indices are signed), hence the cast */
9210 	for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
9211 		if (reserved->interruptStatisticsArray[cnt].reporter) {
9212 			/*
9213 			 * If the reporter is currently associated with the statistics
9214 			 * for an event source, we may need to update the reporter.
9215 			 */
9216 			if (reserved->interruptStatisticsArray[cnt].statistics) {
9217 				interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
9218 			}
9219 
9220 			reserved->interruptStatisticsArray[cnt].reporter->configureReport(channelList, action, result, destination);
9221 		}
9222 	}
9223 
9224 	IOLockUnlock(&reserved->interruptStatisticsLock);
9225 
9226 	if (hasUserServer()) {
9227 		return _ConfigureReport(channelList, action, result, destination);
9228 	} else {
9229 		return kIOReturnSuccess;
9230 	}
9231 }
9232 
9233 IOReturn
updateReport(IOReportChannelList * channelList,IOReportUpdateAction action,void * result,void * destination)9234 IOService::updateReport(IOReportChannelList      *channelList,
9235     IOReportUpdateAction      action,
9236     void                     *result,
9237     void                     *destination)
9238 {
9239 	unsigned cnt;
9240 
9241 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9242 		if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
9243 			if (pwrMgt) {
9244 				updatePowerStatesReport(action, result, destination);
9245 			} else {
9246 				return kIOReturnUnsupported;
9247 			}
9248 		} else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
9249 			if (pwrMgt) {
9250 				updateSimplePowerReport(action, result, destination);
9251 			} else {
9252 				return kIOReturnUnsupported;
9253 			}
9254 		}
9255 	}
9256 
9257 	IOLockLock(&reserved->interruptStatisticsLock);
9258 
9259 	/* The array count is signed (because the interrupt indices are signed), hence the cast */
9260 	for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
9261 		if (reserved->interruptStatisticsArray[cnt].reporter) {
9262 			/*
9263 			 * If the reporter is currently associated with the statistics
9264 			 * for an event source, we need to update the reporter.
9265 			 */
9266 			if (reserved->interruptStatisticsArray[cnt].statistics) {
9267 				interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
9268 			}
9269 
9270 			reserved->interruptStatisticsArray[cnt].reporter->updateReport(channelList, action, result, destination);
9271 		}
9272 	}
9273 
9274 	IOLockUnlock(&reserved->interruptStatisticsLock);
9275 
9276 
9277 	if (hasUserServer()) {
9278 		return _UpdateReport(channelList, action, result, destination);
9279 	} else {
9280 		return kIOReturnSuccess;
9281 	}
9282 }
9283 
9284 uint64_t
getAuthorizationID(void)9285 IOService::getAuthorizationID( void )
9286 {
9287 	return reserved->authorizationID;
9288 }
9289 
9290 IOReturn
setAuthorizationID(uint64_t authorizationID)9291 IOService::setAuthorizationID( uint64_t authorizationID )
9292 {
9293 	OSObject * entitlement;
9294 	IOReturn status;
9295 
9296 	entitlement = IOUserClient::copyClientEntitlement( current_task(), "com.apple.private.iokit.IOServiceSetAuthorizationID" );
9297 
9298 	if (entitlement) {
9299 		if (entitlement == kOSBooleanTrue) {
9300 			reserved->authorizationID = authorizationID;
9301 
9302 			status = kIOReturnSuccess;
9303 		} else {
9304 			status = kIOReturnNotPrivileged;
9305 		}
9306 
9307 		entitlement->release();
9308 	} else {
9309 		status = kIOReturnNotPrivileged;
9310 	}
9311 
9312 	return status;
9313 }
9314 
9315 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9316 
9317 #if __LP64__
9318 OSMetaClassDefineReservedUsedX86(IOService, 0);
9319 OSMetaClassDefineReservedUsedX86(IOService, 1);
9320 OSMetaClassDefineReservedUnused(IOService, 2);
9321 OSMetaClassDefineReservedUnused(IOService, 3);
9322 OSMetaClassDefineReservedUnused(IOService, 4);
9323 OSMetaClassDefineReservedUnused(IOService, 5);
9324 OSMetaClassDefineReservedUnused(IOService, 6);
9325 OSMetaClassDefineReservedUnused(IOService, 7);
9326 #else
9327 OSMetaClassDefineReservedUsedX86(IOService, 0);
9328 OSMetaClassDefineReservedUsedX86(IOService, 1);
9329 OSMetaClassDefineReservedUsedX86(IOService, 2);
9330 OSMetaClassDefineReservedUsedX86(IOService, 3);
9331 OSMetaClassDefineReservedUsedX86(IOService, 4);
9332 OSMetaClassDefineReservedUsedX86(IOService, 5);
9333 OSMetaClassDefineReservedUsedX86(IOService, 6);
9334 OSMetaClassDefineReservedUsedX86(IOService, 7);
9335 #endif
9336 OSMetaClassDefineReservedUnused(IOService, 8);
9337 OSMetaClassDefineReservedUnused(IOService, 9);
9338 OSMetaClassDefineReservedUnused(IOService, 10);
9339 OSMetaClassDefineReservedUnused(IOService, 11);
9340 OSMetaClassDefineReservedUnused(IOService, 12);
9341 OSMetaClassDefineReservedUnused(IOService, 13);
9342 OSMetaClassDefineReservedUnused(IOService, 14);
9343 OSMetaClassDefineReservedUnused(IOService, 15);
9344 OSMetaClassDefineReservedUnused(IOService, 16);
9345 OSMetaClassDefineReservedUnused(IOService, 17);
9346 OSMetaClassDefineReservedUnused(IOService, 18);
9347 OSMetaClassDefineReservedUnused(IOService, 19);
9348 OSMetaClassDefineReservedUnused(IOService, 20);
9349 OSMetaClassDefineReservedUnused(IOService, 21);
9350 OSMetaClassDefineReservedUnused(IOService, 22);
9351 OSMetaClassDefineReservedUnused(IOService, 23);
9352 OSMetaClassDefineReservedUnused(IOService, 24);
9353 OSMetaClassDefineReservedUnused(IOService, 25);
9354 OSMetaClassDefineReservedUnused(IOService, 26);
9355 OSMetaClassDefineReservedUnused(IOService, 27);
9356 OSMetaClassDefineReservedUnused(IOService, 28);
9357 OSMetaClassDefineReservedUnused(IOService, 29);
9358 OSMetaClassDefineReservedUnused(IOService, 30);
9359 OSMetaClassDefineReservedUnused(IOService, 31);
9360 OSMetaClassDefineReservedUnused(IOService, 32);
9361 OSMetaClassDefineReservedUnused(IOService, 33);
9362 OSMetaClassDefineReservedUnused(IOService, 34);
9363 OSMetaClassDefineReservedUnused(IOService, 35);
9364 OSMetaClassDefineReservedUnused(IOService, 36);
9365 OSMetaClassDefineReservedUnused(IOService, 37);
9366 OSMetaClassDefineReservedUnused(IOService, 38);
9367 OSMetaClassDefineReservedUnused(IOService, 39);
9368 OSMetaClassDefineReservedUnused(IOService, 40);
9369 OSMetaClassDefineReservedUnused(IOService, 41);
9370 OSMetaClassDefineReservedUnused(IOService, 42);
9371 OSMetaClassDefineReservedUnused(IOService, 43);
9372 OSMetaClassDefineReservedUnused(IOService, 44);
9373 OSMetaClassDefineReservedUnused(IOService, 45);
9374 OSMetaClassDefineReservedUnused(IOService, 46);
9375 OSMetaClassDefineReservedUnused(IOService, 47);
9376