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