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