xref: /xnu-11215/iokit/Kernel/IOUserServer.cpp (revision 4f1223e8)
1a5e72196SApple OSS Distributions /*
2e6231be0SApple OSS Distributions  * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
3a5e72196SApple OSS Distributions  *
4a5e72196SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5a5e72196SApple OSS Distributions  *
6a5e72196SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7a5e72196SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8a5e72196SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9a5e72196SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10a5e72196SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11a5e72196SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12a5e72196SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13a5e72196SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14a5e72196SApple OSS Distributions  *
15a5e72196SApple OSS Distributions  * Please obtain a copy of the License at
16a5e72196SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17a5e72196SApple OSS Distributions  *
18a5e72196SApple OSS Distributions  * The Original Code and all software distributed under the License are
19a5e72196SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20a5e72196SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21a5e72196SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22a5e72196SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23a5e72196SApple OSS Distributions  * Please see the License for the specific language governing rights and
24a5e72196SApple OSS Distributions  * limitations under the License.
25a5e72196SApple OSS Distributions  *
26a5e72196SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27a5e72196SApple OSS Distributions  */
28a5e72196SApple OSS Distributions 
29a5e72196SApple OSS Distributions #include <IOKit/IORPC.h>
30a5e72196SApple OSS Distributions #include <IOKit/IOKitServer.h>
31a5e72196SApple OSS Distributions #include <IOKit/IOKitKeysPrivate.h>
32e6231be0SApple OSS Distributions #include <IOKit/IOKernelReportStructs.h>
33a5e72196SApple OSS Distributions #include <IOKit/IOUserClient.h>
34a5e72196SApple OSS Distributions #include <IOKit/IOService.h>
35a5e72196SApple OSS Distributions #include <IOKit/IORegistryEntry.h>
36a5e72196SApple OSS Distributions #include <IOKit/IOCatalogue.h>
37a5e72196SApple OSS Distributions #include <IOKit/IOMemoryDescriptor.h>
38a5e72196SApple OSS Distributions #include <IOKit/IOBufferMemoryDescriptor.h>
39bb611c8fSApple OSS Distributions #include <IOKit/IOSubMemoryDescriptor.h>
40bb611c8fSApple OSS Distributions #include <IOKit/IOMultiMemoryDescriptor.h>
41bb611c8fSApple OSS Distributions #include <IOKit/IOMapper.h>
42a5e72196SApple OSS Distributions #include <IOKit/IOLib.h>
43e6231be0SApple OSS Distributions #include <IOKit/IOHibernatePrivate.h>
44a5e72196SApple OSS Distributions #include <IOKit/IOBSD.h>
45a5e72196SApple OSS Distributions #include <IOKit/system.h>
468d741a5dSApple OSS Distributions #include "IOServicePrivate.h"
47a5e72196SApple OSS Distributions #include <IOKit/IOUserServer.h>
48a5e72196SApple OSS Distributions #include <IOKit/IOInterruptEventSource.h>
49a5e72196SApple OSS Distributions #include <IOKit/IOTimerEventSource.h>
50a5e72196SApple OSS Distributions #include <IOKit/pwr_mgt/RootDomain.h>
5194d3b452SApple OSS Distributions #include <IOKit/pwr_mgt/IOPowerConnection.h>
52e6231be0SApple OSS Distributions #include <libkern/c++/OSAllocation.h>
53a5e72196SApple OSS Distributions #include <libkern/c++/OSKext.h>
54bb611c8fSApple OSS Distributions #include <libkern/c++/OSSharedPtr.h>
55a5e72196SApple OSS Distributions #include <libkern/OSDebug.h>
56a5e72196SApple OSS Distributions #include <libkern/Block.h>
575c2921b0SApple OSS Distributions #include <kern/cs_blobs.h>
585c2921b0SApple OSS Distributions #include <kern/thread_call.h>
595c2921b0SApple OSS Distributions #include <os/atomic_private.h>
60a5e72196SApple OSS Distributions #include <sys/proc.h>
61e6231be0SApple OSS Distributions #include <sys/reboot.h>
625c2921b0SApple OSS Distributions #include <sys/codesign.h>
63a5e72196SApple OSS Distributions #include "IOKitKernelInternal.h"
64a5e72196SApple OSS Distributions 
65bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
66a5e72196SApple OSS Distributions 
67a5e72196SApple OSS Distributions #include <DriverKit/IODispatchQueue.h>
68a5e72196SApple OSS Distributions #include <DriverKit/OSObject.h>
69a5e72196SApple OSS Distributions #include <DriverKit/OSAction.h>
70a5e72196SApple OSS Distributions #include <DriverKit/IODispatchSource.h>
71a5e72196SApple OSS Distributions #include <DriverKit/IOInterruptDispatchSource.h>
72a5e72196SApple OSS Distributions #include <DriverKit/IOService.h>
73a5e72196SApple OSS Distributions #include <DriverKit/IOMemoryDescriptor.h>
74a5e72196SApple OSS Distributions #include <DriverKit/IOBufferMemoryDescriptor.h>
75a5e72196SApple OSS Distributions #include <DriverKit/IOMemoryMap.h>
76a5e72196SApple OSS Distributions #include <DriverKit/IODataQueueDispatchSource.h>
77bb611c8fSApple OSS Distributions #include <DriverKit/IOServiceNotificationDispatchSource.h>
78e6231be0SApple OSS Distributions #include <DriverKit/IOServiceStateNotificationDispatchSource.h>
79e6231be0SApple OSS Distributions #include <DriverKit/IOEventLink.h>
80e6231be0SApple OSS Distributions #include <DriverKit/IOWorkGroup.h>
81a5e72196SApple OSS Distributions #include <DriverKit/IOUserServer.h>
82a5e72196SApple OSS Distributions 
83bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
84a5e72196SApple OSS Distributions 
85a5e72196SApple OSS Distributions #include <System/IODataQueueDispatchSourceShared.h>
86a5e72196SApple OSS Distributions 
87bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
88a5e72196SApple OSS Distributions 
89e6231be0SApple OSS Distributions TUNABLE(SInt64, gIODKDebug, "dk", kIODKEnable);
90e6231be0SApple OSS Distributions 
915c2921b0SApple OSS Distributions #if DEBUG || DEVELOPMENT
925c2921b0SApple OSS Distributions TUNABLE(bool, disable_dext_crash_reboot, "disable_dext_crash_reboot", 0);
935c2921b0SApple OSS Distributions #endif /* DEBUG || DEVELOPMENT */
945c2921b0SApple OSS Distributions 
958d741a5dSApple OSS Distributions extern bool restore_boot;
968d741a5dSApple OSS Distributions 
97e6231be0SApple OSS Distributions static OSString       * gIOSystemStateSleepDescriptionKey;
98e6231be0SApple OSS Distributions static const OSSymbol * gIOSystemStateSleepDescriptionReasonKey;
99e6231be0SApple OSS Distributions static const OSSymbol * gIOSystemStateSleepDescriptionHibernateStateKey;
100e6231be0SApple OSS Distributions 
1015c2921b0SApple OSS Distributions static OSString       * gIOSystemStateWakeDescriptionKey;
1025c2921b0SApple OSS Distributions static const OSSymbol * gIOSystemStateWakeDescriptionWakeReasonKey;
1038d741a5dSApple OSS Distributions static const OSSymbol * gIOSystemStateWakeDescriptionContinuousTimeOffsetKey;
1045c2921b0SApple OSS Distributions 
105e6231be0SApple OSS Distributions static OSString       * gIOSystemStateHaltDescriptionKey;
106e6231be0SApple OSS Distributions static const OSSymbol * gIOSystemStateHaltDescriptionHaltStateKey;
107e6231be0SApple OSS Distributions 
108e6231be0SApple OSS Distributions static OSString       * gIOSystemStatePowerSourceDescriptionKey;
109e6231be0SApple OSS Distributions static const OSSymbol * gIOSystemStatePowerSourceDescriptionACAttachedKey;
110a5e72196SApple OSS Distributions 
1115c2921b0SApple OSS Distributions extern bool gInUserspaceReboot;
1125c2921b0SApple OSS Distributions 
113aca3beaaSApple OSS Distributions extern void iokit_clear_registered_ports(task_t task);
114aca3beaaSApple OSS Distributions 
11594d3b452SApple OSS Distributions static IORPCMessage *
11694d3b452SApple OSS Distributions IORPCMessageFromMachReply(IORPCMessageMach * msg);
11794d3b452SApple OSS Distributions 
118bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
119a5e72196SApple OSS Distributions 
120a5e72196SApple OSS Distributions struct IOPStrings;
121a5e72196SApple OSS Distributions 
122a5e72196SApple OSS Distributions class OSUserMetaClass : public OSObject
123a5e72196SApple OSS Distributions {
124a5e72196SApple OSS Distributions 	OSDeclareDefaultStructors(OSUserMetaClass);
125a5e72196SApple OSS Distributions public:
126a5e72196SApple OSS Distributions 	const OSSymbol    * name;
127a5e72196SApple OSS Distributions 	const OSMetaClass * meta;
128a5e72196SApple OSS Distributions 	OSUserMetaClass   * superMeta;
129a5e72196SApple OSS Distributions 
130a5e72196SApple OSS Distributions 	queue_chain_t       link;
131a5e72196SApple OSS Distributions 
132a5e72196SApple OSS Distributions 	OSClassDescription * description;
133a5e72196SApple OSS Distributions 	IOPStrings * queueNames;
134a5e72196SApple OSS Distributions 	uint32_t     methodCount;
135a5e72196SApple OSS Distributions 	uint64_t   * methods;
136a5e72196SApple OSS Distributions 
137a5e72196SApple OSS Distributions 	virtual void free() override;
138a5e72196SApple OSS Distributions 	virtual kern_return_t Dispatch(const IORPC rpc) APPLE_KEXT_OVERRIDE;
139a5e72196SApple OSS Distributions };
140a5e72196SApple OSS Distributions OSDefineMetaClassAndStructors(OSUserMetaClass, OSObject);
141a5e72196SApple OSS Distributions 
142a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
143a5e72196SApple OSS Distributions 
144a5e72196SApple OSS Distributions class IOUserService : public IOService
145a5e72196SApple OSS Distributions {
146a5e72196SApple OSS Distributions 	friend class IOService;
147a5e72196SApple OSS Distributions 
148a5e72196SApple OSS Distributions 	OSDeclareDefaultStructors(IOUserService)
149a5e72196SApple OSS Distributions 
150a5e72196SApple OSS Distributions 	virtual bool
151a5e72196SApple OSS Distributions 	start(IOService * provider) APPLE_KEXT_OVERRIDE;
152a5e72196SApple OSS Distributions };
153a5e72196SApple OSS Distributions 
154a5e72196SApple OSS Distributions OSDefineMetaClassAndStructors(IOUserService, IOService)
155a5e72196SApple OSS Distributions 
156a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
157a5e72196SApple OSS Distributions 
158a5e72196SApple OSS Distributions class IOUserUserClient : public IOUserClient
159a5e72196SApple OSS Distributions {
160a5e72196SApple OSS Distributions 	OSDeclareDefaultStructors(IOUserUserClient);
161a5e72196SApple OSS Distributions public:
162a5e72196SApple OSS Distributions 	task_t          fTask;
163e6231be0SApple OSS Distributions 	OSDictionary  * fWorkGroups;
164e6231be0SApple OSS Distributions 	OSDictionary  * fEventLinks;
165e6231be0SApple OSS Distributions 	IOLock        * fLock;
166a5e72196SApple OSS Distributions 
167a5e72196SApple OSS Distributions 	IOReturn                   setTask(task_t task);
168e6231be0SApple OSS Distributions 	IOReturn                   eventlinkConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6);
169e6231be0SApple OSS Distributions 	IOReturn                   workgroupConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6);
170e6231be0SApple OSS Distributions 
171e6231be0SApple OSS Distributions 	virtual bool           init( OSDictionary * dictionary ) APPLE_KEXT_OVERRIDE;
172e6231be0SApple OSS Distributions 	virtual void           free() APPLE_KEXT_OVERRIDE;
173a5e72196SApple OSS Distributions 	virtual void           stop(IOService * provider) APPLE_KEXT_OVERRIDE;
174a5e72196SApple OSS Distributions 	virtual IOReturn       clientClose(void) APPLE_KEXT_OVERRIDE;
175a5e72196SApple OSS Distributions 	virtual IOReturn       setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE;
176a5e72196SApple OSS Distributions 	virtual IOReturn       externalMethod(uint32_t selector, IOExternalMethodArguments * args,
177a5e72196SApple OSS Distributions 	    IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) APPLE_KEXT_OVERRIDE;
178a5e72196SApple OSS Distributions 	virtual IOReturn           clientMemoryForType(UInt32 type,
179a5e72196SApple OSS Distributions 	    IOOptionBits * options,
180a5e72196SApple OSS Distributions 	    IOMemoryDescriptor ** memory) APPLE_KEXT_OVERRIDE;
181e6231be0SApple OSS Distributions 	virtual IOExternalTrap * getTargetAndTrapForIndex( IOService **targetP, UInt32 index ) APPLE_KEXT_OVERRIDE;
182a5e72196SApple OSS Distributions };
183a5e72196SApple OSS Distributions 
184bb611c8fSApple OSS Distributions OSDefineMetaClassAndStructors(IOUserServerCheckInToken, OSObject);
185e6231be0SApple OSS Distributions OSDefineMetaClassAndStructors(_IOUserServerCheckInCancellationHandler, OSObject);
186a5e72196SApple OSS Distributions 
187a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
188a5e72196SApple OSS Distributions 
189a5e72196SApple OSS Distributions 
190a5e72196SApple OSS Distributions bool
start(IOService * provider)191a5e72196SApple OSS Distributions IOUserService::start(IOService * provider)
192a5e72196SApple OSS Distributions {
193a5e72196SApple OSS Distributions 	bool     ok = true;
194a5e72196SApple OSS Distributions 	IOReturn ret;
195a5e72196SApple OSS Distributions 
196a5e72196SApple OSS Distributions 	ret = Start(provider);
197a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != ret) {
198a5e72196SApple OSS Distributions 		return false;
199a5e72196SApple OSS Distributions 	}
200a5e72196SApple OSS Distributions 
201a5e72196SApple OSS Distributions 	return ok;
202a5e72196SApple OSS Distributions }
203a5e72196SApple OSS Distributions 
204bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
205a5e72196SApple OSS Distributions 
206a5e72196SApple OSS Distributions #undef super
207a5e72196SApple OSS Distributions 
208bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
209a5e72196SApple OSS Distributions 
210a5e72196SApple OSS Distributions struct IODispatchQueue_IVars {
211a5e72196SApple OSS Distributions 	IOUserServer * userServer;
212a5e72196SApple OSS Distributions 	IODispatchQueue   * queue;
213a5e72196SApple OSS Distributions 	queue_chain_t  link;
214a5e72196SApple OSS Distributions 	uint64_t       tid;
215a5e72196SApple OSS Distributions 
216a5e72196SApple OSS Distributions 	mach_port_t    serverPort;
217a5e72196SApple OSS Distributions };
218a5e72196SApple OSS Distributions 
219a5e72196SApple OSS Distributions struct OSAction_IVars {
220a5e72196SApple OSS Distributions 	OSObject             * target;
221a5e72196SApple OSS Distributions 	uint64_t               targetmsgid;
222a5e72196SApple OSS Distributions 	uint64_t               msgid;
223e6231be0SApple OSS Distributions 	IOUserServer         * userServer;
224a5e72196SApple OSS Distributions 	OSActionAbortedHandler abortedHandler;
225bb611c8fSApple OSS Distributions 	OSString             * typeName;
226e6231be0SApple OSS Distributions 	void                 * reference;
227e6231be0SApple OSS Distributions 	size_t                 referenceSize;
2285c2921b0SApple OSS Distributions 	bool                   aborted;
229e6231be0SApple OSS Distributions };
230e6231be0SApple OSS Distributions 
231e6231be0SApple OSS Distributions struct IOWorkGroup_IVars {
232e6231be0SApple OSS Distributions 	IOUserServer * userServer;
233e6231be0SApple OSS Distributions 	OSString * name;
234e6231be0SApple OSS Distributions 	IOUserUserClient * userClient;
235e6231be0SApple OSS Distributions };
236e6231be0SApple OSS Distributions 
237e6231be0SApple OSS Distributions struct IOEventLink_IVars {
238e6231be0SApple OSS Distributions 	IOUserServer * userServer;
239e6231be0SApple OSS Distributions 	OSString * name;
240e6231be0SApple OSS Distributions 	IOUserUserClient * userClient;
241a5e72196SApple OSS Distributions };
242a5e72196SApple OSS Distributions 
243bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
244a5e72196SApple OSS Distributions 
245a5e72196SApple OSS Distributions kern_return_t
GetRegistryEntryID_Impl(uint64_t * registryEntryID)246bb611c8fSApple OSS Distributions IOService::GetRegistryEntryID_Impl(
247bb611c8fSApple OSS Distributions 	uint64_t * registryEntryID)
248a5e72196SApple OSS Distributions {
249a5e72196SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
250a5e72196SApple OSS Distributions 
251a5e72196SApple OSS Distributions 	*registryEntryID = getRegistryEntryID();
252a5e72196SApple OSS Distributions 
253a5e72196SApple OSS Distributions 	return ret;
254a5e72196SApple OSS Distributions }
255a5e72196SApple OSS Distributions 
256a5e72196SApple OSS Distributions kern_return_t
SetName_Impl(const char * name)257bb611c8fSApple OSS Distributions IOService::SetName_Impl(
258bb611c8fSApple OSS Distributions 	const char * name)
259a5e72196SApple OSS Distributions {
260a5e72196SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
261a5e72196SApple OSS Distributions 
262a5e72196SApple OSS Distributions 	setName(name);
263a5e72196SApple OSS Distributions 
264a5e72196SApple OSS Distributions 	return ret;
265a5e72196SApple OSS Distributions }
266a5e72196SApple OSS Distributions 
267a5e72196SApple OSS Distributions kern_return_t
CopyName_Impl(OSString ** name)268e6231be0SApple OSS Distributions IOService::CopyName_Impl(
269e6231be0SApple OSS Distributions 	OSString ** name)
270e6231be0SApple OSS Distributions {
271e6231be0SApple OSS Distributions 	const OSString * str = copyName();
272e6231be0SApple OSS Distributions 	*name = __DECONST(OSString *, str);
273e6231be0SApple OSS Distributions 	return str ? kIOReturnSuccess : kIOReturnError;
274e6231be0SApple OSS Distributions }
275e6231be0SApple OSS Distributions 
276e6231be0SApple OSS Distributions 
277e6231be0SApple OSS Distributions kern_return_t
Start_Impl(IOService * provider)278bb611c8fSApple OSS Distributions IOService::Start_Impl(
279bb611c8fSApple OSS Distributions 	IOService * provider)
280a5e72196SApple OSS Distributions {
281a5e72196SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
282a5e72196SApple OSS Distributions 	return ret;
283a5e72196SApple OSS Distributions }
284a5e72196SApple OSS Distributions 
285e6231be0SApple OSS Distributions 
286e6231be0SApple OSS Distributions IOReturn
UpdateReport_Impl(OSData * channels,uint32_t action,uint32_t * outElementCount,uint64_t offset,uint64_t capacity,IOMemoryDescriptor * buffer)287e6231be0SApple OSS Distributions IOService::UpdateReport_Impl(OSData *channels, uint32_t action,
288e6231be0SApple OSS Distributions     uint32_t *outElementCount,
289e6231be0SApple OSS Distributions     uint64_t offset, uint64_t capacity,
290e6231be0SApple OSS Distributions     IOMemoryDescriptor *buffer)
291e6231be0SApple OSS Distributions {
292e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
293e6231be0SApple OSS Distributions }
294e6231be0SApple OSS Distributions 
295e6231be0SApple OSS Distributions IOReturn
ConfigureReport_Impl(OSData * channels,uint32_t action,uint32_t * outCount)296e6231be0SApple OSS Distributions IOService::ConfigureReport_Impl(OSData *channels, uint32_t action, uint32_t *outCount)
297e6231be0SApple OSS Distributions {
298e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
299e6231be0SApple OSS Distributions }
300e6231be0SApple OSS Distributions 
301e6231be0SApple OSS Distributions // adapt old signature of configureReport to the iig-friendly signature of ConfigureReport
302e6231be0SApple OSS Distributions IOReturn
_ConfigureReport(IOReportChannelList * channelList,IOReportConfigureAction action,void * result,void * destination)303e6231be0SApple OSS Distributions IOService::_ConfigureReport(IOReportChannelList    *channelList,
304e6231be0SApple OSS Distributions     IOReportConfigureAction action,
305e6231be0SApple OSS Distributions     void                   *result,
306e6231be0SApple OSS Distributions     void                   *destination)
307e6231be0SApple OSS Distributions {
308e6231be0SApple OSS Distributions 	if (action != kIOReportEnable && action != kIOReportGetDimensions && action != kIOReportDisable) {
309e6231be0SApple OSS Distributions 		return kIOReturnUnsupported;
310e6231be0SApple OSS Distributions 	}
311e6231be0SApple OSS Distributions 	static_assert(sizeof(IOReportChannelList) == 8);
312e6231be0SApple OSS Distributions 	static_assert(sizeof(IOReportChannel) == 16);
313e6231be0SApple OSS Distributions 	unsigned int size_of_channels;
314e6231be0SApple OSS Distributions 	bool overflow = os_mul_and_add_overflow(channelList->nchannels, sizeof(IOReportChannel), sizeof(IOReportChannelList), &size_of_channels);
315e6231be0SApple OSS Distributions 	if (overflow) {
316e6231be0SApple OSS Distributions 		return kIOReturnOverrun;
317e6231be0SApple OSS Distributions 	}
318e6231be0SApple OSS Distributions 	OSSharedPtr<OSData> sp_channels(OSData::withBytesNoCopy(channelList, size_of_channels), libkern::no_retain);
319e6231be0SApple OSS Distributions 	if (!sp_channels) {
320e6231be0SApple OSS Distributions 		return kIOReturnNoMemory;
321e6231be0SApple OSS Distributions 	}
322e6231be0SApple OSS Distributions 	int *resultp = (int*) result;
323e6231be0SApple OSS Distributions 	uint32_t count = 0;
324e6231be0SApple OSS Distributions 	IOReturn r = ConfigureReport(sp_channels.get(), action, &count);
325e6231be0SApple OSS Distributions 	int new_result;
326e6231be0SApple OSS Distributions 	overflow = os_add_overflow(*resultp, count, &new_result);
327e6231be0SApple OSS Distributions 	if (overflow) {
328e6231be0SApple OSS Distributions 		return kIOReturnOverrun;
329e6231be0SApple OSS Distributions 	}
330e6231be0SApple OSS Distributions 	*resultp = new_result;
331e6231be0SApple OSS Distributions 	return r;
332e6231be0SApple OSS Distributions }
333e6231be0SApple OSS Distributions 
334e6231be0SApple OSS Distributions // adapt old signature of updateReport to the iig-friendly signature of UpdateReport
335e6231be0SApple OSS Distributions IOReturn
_UpdateReport(IOReportChannelList * channelList,IOReportUpdateAction action,void * result,void * destination)336e6231be0SApple OSS Distributions IOService::_UpdateReport(IOReportChannelList      *channelList,
337e6231be0SApple OSS Distributions     IOReportUpdateAction      action,
338e6231be0SApple OSS Distributions     void                     *result,
339e6231be0SApple OSS Distributions     void                     *destination)
340e6231be0SApple OSS Distributions {
341e6231be0SApple OSS Distributions 	if (action != kIOReportCopyChannelData) {
342e6231be0SApple OSS Distributions 		return kIOReturnUnsupported;
343e6231be0SApple OSS Distributions 	}
344e6231be0SApple OSS Distributions 	unsigned int size_of_channels;
345e6231be0SApple OSS Distributions 	bool overflow = os_mul_and_add_overflow(channelList->nchannels, sizeof(IOReportChannel), sizeof(IOReportChannelList), &size_of_channels);
346e6231be0SApple OSS Distributions 	if (overflow) {
347e6231be0SApple OSS Distributions 		return kIOReturnOverrun;
348e6231be0SApple OSS Distributions 	}
349e6231be0SApple OSS Distributions 	OSSharedPtr<OSData> sp_channels(OSData::withBytesNoCopy(channelList, size_of_channels), libkern::no_retain);
350e6231be0SApple OSS Distributions 	if (!sp_channels) {
351e6231be0SApple OSS Distributions 		return kIOReturnNoMemory;
352e6231be0SApple OSS Distributions 	}
353e6231be0SApple OSS Distributions 	int *resultp = (int*) result;
354e6231be0SApple OSS Distributions 	uint32_t count = 0;
355e6231be0SApple OSS Distributions 	auto buffer = (IOBufferMemoryDescriptor*) destination;
356e6231be0SApple OSS Distributions 	uint64_t length = buffer->getLength();
357e6231be0SApple OSS Distributions 	buffer->setLength(buffer->getCapacity());
358e6231be0SApple OSS Distributions 	IOReturn r = UpdateReport(sp_channels.get(), action, &count, length, buffer->getCapacity() - length, buffer);
359e6231be0SApple OSS Distributions 	int new_result;
360e6231be0SApple OSS Distributions 	overflow = os_add_overflow(*resultp, count, &new_result);
361e6231be0SApple OSS Distributions 	size_t new_length;
362e6231be0SApple OSS Distributions 	overflow = overflow || os_mul_and_add_overflow(count, sizeof(IOReportElement), length, &new_length);
363e6231be0SApple OSS Distributions 	if (overflow || new_length > buffer->getCapacity()) {
364e6231be0SApple OSS Distributions 		buffer->setLength(length);
365e6231be0SApple OSS Distributions 		return kIOReturnOverrun;
366e6231be0SApple OSS Distributions 	}
367e6231be0SApple OSS Distributions 	*resultp = new_result;
368e6231be0SApple OSS Distributions 	buffer->setLength(new_length);
369e6231be0SApple OSS Distributions 	return r;
370e6231be0SApple OSS Distributions }
371e6231be0SApple OSS Distributions 
372e6231be0SApple OSS Distributions 
373e6231be0SApple OSS Distributions IOReturn
SetLegend_Impl(OSArray * legend,bool is_public)374e6231be0SApple OSS Distributions IOService::SetLegend_Impl(OSArray *legend, bool is_public)
375e6231be0SApple OSS Distributions {
376e6231be0SApple OSS Distributions 	bool ok = setProperty(kIOReportLegendKey, legend);
377e6231be0SApple OSS Distributions 	ok = ok && setProperty(kIOReportLegendPublicKey, is_public);
378e6231be0SApple OSS Distributions 	return ok ? kIOReturnSuccess : kIOReturnError;
379e6231be0SApple OSS Distributions }
380e6231be0SApple OSS Distributions 
381e6231be0SApple OSS Distributions 
382a5e72196SApple OSS Distributions kern_return_t
RegisterService_Impl()383bb611c8fSApple OSS Distributions IOService::RegisterService_Impl()
384a5e72196SApple OSS Distributions {
385a5e72196SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
3865c2921b0SApple OSS Distributions 	bool started;
387a5e72196SApple OSS Distributions 
3885c2921b0SApple OSS Distributions 	IOUserServer *us = (typeof(us))thread_iokit_tls_get(0);
3895c2921b0SApple OSS Distributions 	if (reserved != NULL && reserved->uvars != NULL && reserved->uvars->userServer == us) {
3905c2921b0SApple OSS Distributions 		started = reserved->uvars->started;
3915c2921b0SApple OSS Distributions 	} else {
3925c2921b0SApple OSS Distributions 		// assume started
3935c2921b0SApple OSS Distributions 		started = true;
3945c2921b0SApple OSS Distributions 	}
3955c2921b0SApple OSS Distributions 
3965c2921b0SApple OSS Distributions 	if (OSDynamicCast(IOUserServer, this) != NULL || started) {
397e6231be0SApple OSS Distributions 		registerService(kIOServiceAsynchronous);
3985c2921b0SApple OSS Distributions 	} else {
3995c2921b0SApple OSS Distributions 		assert(reserved != NULL && reserved->uvars != NULL);
4005c2921b0SApple OSS Distributions 		reserved->uvars->deferredRegisterService = true;
4015c2921b0SApple OSS Distributions 	}
402a5e72196SApple OSS Distributions 
403a5e72196SApple OSS Distributions 	return ret;
404a5e72196SApple OSS Distributions }
405a5e72196SApple OSS Distributions 
406a5e72196SApple OSS Distributions kern_return_t
CopyDispatchQueue_Impl(const char * name,IODispatchQueue ** queue)407bb611c8fSApple OSS Distributions IOService::CopyDispatchQueue_Impl(
408bb611c8fSApple OSS Distributions 	const char * name,
409bb611c8fSApple OSS Distributions 	IODispatchQueue ** queue)
410a5e72196SApple OSS Distributions {
411a5e72196SApple OSS Distributions 	IODispatchQueue * result;
412a5e72196SApple OSS Distributions 	IOService  * service;
413a5e72196SApple OSS Distributions 	IOReturn     ret;
414a5e72196SApple OSS Distributions 	uint32_t index;
415a5e72196SApple OSS Distributions 
416bb611c8fSApple OSS Distributions 	if (!reserved->uvars) {
417bb611c8fSApple OSS Distributions 		return kIOReturnError;
418bb611c8fSApple OSS Distributions 	}
419bb611c8fSApple OSS Distributions 
4201031c584SApple OSS Distributions 	if (!reserved->uvars->queueArray) {
4211031c584SApple OSS Distributions 		// CopyDispatchQueue should not be called after the service has stopped
4221031c584SApple OSS Distributions 		return kIOReturnError;
4231031c584SApple OSS Distributions 	}
4241031c584SApple OSS Distributions 
425a5e72196SApple OSS Distributions 	ret = kIOReturnNotFound;
426a5e72196SApple OSS Distributions 	index = -1U;
427a5e72196SApple OSS Distributions 	if (!strcmp("Default", name)) {
428a5e72196SApple OSS Distributions 		index = 0;
429a5e72196SApple OSS Distributions 	} else if (reserved->uvars->userMeta
430a5e72196SApple OSS Distributions 	    && reserved->uvars->userMeta->queueNames) {
431a5e72196SApple OSS Distributions 		index = reserved->uvars->userServer->stringArrayIndex(reserved->uvars->userMeta->queueNames, name);
432a5e72196SApple OSS Distributions 		if (index != -1U) {
433a5e72196SApple OSS Distributions 			index++;
434a5e72196SApple OSS Distributions 		}
435a5e72196SApple OSS Distributions 	}
436a5e72196SApple OSS Distributions 	if (index == -1U) {
437a5e72196SApple OSS Distributions 		if ((service = getProvider())) {
438a5e72196SApple OSS Distributions 			ret = service->CopyDispatchQueue(name, queue);
439a5e72196SApple OSS Distributions 		}
440a5e72196SApple OSS Distributions 	} else {
441a5e72196SApple OSS Distributions 		result = reserved->uvars->queueArray[index];
442a5e72196SApple OSS Distributions 		if (result) {
443a5e72196SApple OSS Distributions 			result->retain();
444a5e72196SApple OSS Distributions 			*queue = result;
445a5e72196SApple OSS Distributions 			ret = kIOReturnSuccess;
446a5e72196SApple OSS Distributions 		}
447a5e72196SApple OSS Distributions 	}
448a5e72196SApple OSS Distributions 
449a5e72196SApple OSS Distributions 	return ret;
450a5e72196SApple OSS Distributions }
451a5e72196SApple OSS Distributions 
452a5e72196SApple OSS Distributions kern_return_t
CreateDefaultDispatchQueue_Impl(IODispatchQueue ** queue)453e6231be0SApple OSS Distributions IOService::CreateDefaultDispatchQueue_Impl(
454e6231be0SApple OSS Distributions 	IODispatchQueue ** queue)
455e6231be0SApple OSS Distributions {
456e6231be0SApple OSS Distributions 	return kIOReturnError;
457e6231be0SApple OSS Distributions }
458e6231be0SApple OSS Distributions 
459e6231be0SApple OSS Distributions kern_return_t
CoreAnalyticsSendEvent_Impl(uint64_t options,OSString * eventName,OSDictionary * eventPayload)460e6231be0SApple OSS Distributions IOService::CoreAnalyticsSendEvent_Impl(
461e6231be0SApple OSS Distributions 	uint64_t       options,
462e6231be0SApple OSS Distributions 	OSString     * eventName,
463e6231be0SApple OSS Distributions 	OSDictionary * eventPayload)
464e6231be0SApple OSS Distributions {
465e6231be0SApple OSS Distributions 	kern_return_t ret;
466e6231be0SApple OSS Distributions 
467e6231be0SApple OSS Distributions 	if (NULL == gIOCoreAnalyticsSendEventProc) {
468e6231be0SApple OSS Distributions 		// perhaps save for later?
469e6231be0SApple OSS Distributions 		return kIOReturnNotReady;
470e6231be0SApple OSS Distributions 	}
471e6231be0SApple OSS Distributions 
472e6231be0SApple OSS Distributions 	ret = (*gIOCoreAnalyticsSendEventProc)(options, eventName, eventPayload);
473e6231be0SApple OSS Distributions 
474e6231be0SApple OSS Distributions 	return ret;
475e6231be0SApple OSS Distributions }
476e6231be0SApple OSS Distributions 
477e6231be0SApple OSS Distributions kern_return_t
SetDispatchQueue_Impl(const char * name,IODispatchQueue * queue)478bb611c8fSApple OSS Distributions IOService::SetDispatchQueue_Impl(
479bb611c8fSApple OSS Distributions 	const char * name,
480bb611c8fSApple OSS Distributions 	IODispatchQueue * queue)
481a5e72196SApple OSS Distributions {
482a5e72196SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
483a5e72196SApple OSS Distributions 	uint32_t index;
484a5e72196SApple OSS Distributions 
485bb611c8fSApple OSS Distributions 	if (!reserved->uvars) {
486bb611c8fSApple OSS Distributions 		return kIOReturnError;
487bb611c8fSApple OSS Distributions 	}
488bb611c8fSApple OSS Distributions 
489a5e72196SApple OSS Distributions 	if (kIODKLogSetup & gIODKDebug) {
490a5e72196SApple OSS Distributions 		DKLOG(DKS "::SetDispatchQueue(%s)\n", DKN(this), name);
491a5e72196SApple OSS Distributions 	}
492a5e72196SApple OSS Distributions 	queue->ivars->userServer = reserved->uvars->userServer;
493a5e72196SApple OSS Distributions 	index = -1U;
494a5e72196SApple OSS Distributions 	if (!strcmp("Default", name)) {
495a5e72196SApple OSS Distributions 		index = 0;
496a5e72196SApple OSS Distributions 	} else if (reserved->uvars->userMeta
497a5e72196SApple OSS Distributions 	    && reserved->uvars->userMeta->queueNames) {
498a5e72196SApple OSS Distributions 		index = reserved->uvars->userServer->stringArrayIndex(reserved->uvars->userMeta->queueNames, name);
499a5e72196SApple OSS Distributions 		if (index != -1U) {
500a5e72196SApple OSS Distributions 			index++;
501a5e72196SApple OSS Distributions 		}
502a5e72196SApple OSS Distributions 	}
503a5e72196SApple OSS Distributions 	if (index == -1U) {
504a5e72196SApple OSS Distributions 		ret = kIOReturnBadArgument;
505a5e72196SApple OSS Distributions 	} else {
506a5e72196SApple OSS Distributions 		reserved->uvars->queueArray[index] = queue;
507a5e72196SApple OSS Distributions 		queue->retain();
508a5e72196SApple OSS Distributions 	}
509a5e72196SApple OSS Distributions 
510a5e72196SApple OSS Distributions 	return ret;
511a5e72196SApple OSS Distributions }
512a5e72196SApple OSS Distributions 
513e6231be0SApple OSS Distributions IOService *
GetProvider() const514e6231be0SApple OSS Distributions IOService::GetProvider() const
515e6231be0SApple OSS Distributions {
516e6231be0SApple OSS Distributions 	return getProvider();
517e6231be0SApple OSS Distributions }
518e6231be0SApple OSS Distributions 
519a5e72196SApple OSS Distributions kern_return_t
SetProperties_Impl(OSDictionary * properties)520bb611c8fSApple OSS Distributions IOService::SetProperties_Impl(
521bb611c8fSApple OSS Distributions 	OSDictionary * properties)
522a5e72196SApple OSS Distributions {
523bb611c8fSApple OSS Distributions 	IOUserServer   * us;
524bb611c8fSApple OSS Distributions 	OSDictionary   * dict;
525bb611c8fSApple OSS Distributions 	IOReturn         ret;
526a5e72196SApple OSS Distributions 
527e6231be0SApple OSS Distributions 	us = (typeof(us))thread_iokit_tls_get(0);
528e6231be0SApple OSS Distributions 	dict = OSDynamicCast(OSDictionary, properties);
529e6231be0SApple OSS Distributions 	if (NULL == us) {
530e6231be0SApple OSS Distributions 		if (!dict) {
531e6231be0SApple OSS Distributions 			return kIOReturnBadArgument;
532e6231be0SApple OSS Distributions 		}
533e6231be0SApple OSS Distributions 		bool ok __block = true;
534e6231be0SApple OSS Distributions 		dict->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
535e6231be0SApple OSS Distributions 			ok = setProperty(key, value);
536e6231be0SApple OSS Distributions 			return !ok;
537e6231be0SApple OSS Distributions 		});
538e6231be0SApple OSS Distributions 		ret = ok ? kIOReturnSuccess : kIOReturnNotWritable;
539e6231be0SApple OSS Distributions 		return ret;
540e6231be0SApple OSS Distributions 	}
541e6231be0SApple OSS Distributions 
542a5e72196SApple OSS Distributions 	ret = setProperties(properties);
543a5e72196SApple OSS Distributions 
544bb611c8fSApple OSS Distributions 	if (kIOReturnUnsupported == ret) {
545bb611c8fSApple OSS Distributions 		if (dict && reserved->uvars && (reserved->uvars->userServer == us)) {
546bb611c8fSApple OSS Distributions 			ret = runPropertyActionBlock(^IOReturn (void) {
547bb611c8fSApple OSS Distributions 				OSDictionary   * userProps;
548bb611c8fSApple OSS Distributions 				IOReturn         ret;
549bb611c8fSApple OSS Distributions 
550bb611c8fSApple OSS Distributions 				userProps = OSDynamicCast(OSDictionary, getProperty(gIOUserServicePropertiesKey));
551bb611c8fSApple OSS Distributions 				if (userProps) {
552bb611c8fSApple OSS Distributions 				        userProps = (typeof(userProps))userProps->copyCollection();
553bb611c8fSApple OSS Distributions 				} else {
554bb611c8fSApple OSS Distributions 				        userProps = OSDictionary::withCapacity(4);
555bb611c8fSApple OSS Distributions 				}
556bb611c8fSApple OSS Distributions 				if (!userProps) {
557bb611c8fSApple OSS Distributions 				        ret = kIOReturnNoMemory;
558bb611c8fSApple OSS Distributions 				} else {
559bb611c8fSApple OSS Distributions 				        bool ok = userProps->merge(dict);
560bb611c8fSApple OSS Distributions 				        if (ok) {
561bb611c8fSApple OSS Distributions 				                ok = setProperty(gIOUserServicePropertiesKey, userProps);
562bb611c8fSApple OSS Distributions 					}
563bb611c8fSApple OSS Distributions 				        OSSafeReleaseNULL(userProps);
564bb611c8fSApple OSS Distributions 				        ret = ok ? kIOReturnSuccess : kIOReturnNotWritable;
565bb611c8fSApple OSS Distributions 				}
566bb611c8fSApple OSS Distributions 				return ret;
567bb611c8fSApple OSS Distributions 			});
568bb611c8fSApple OSS Distributions 		}
569bb611c8fSApple OSS Distributions 	}
570bb611c8fSApple OSS Distributions 
571a5e72196SApple OSS Distributions 	return ret;
572a5e72196SApple OSS Distributions }
573a5e72196SApple OSS Distributions 
574a5e72196SApple OSS Distributions kern_return_t
RemoveProperty_Impl(OSString * propertyName)575e6231be0SApple OSS Distributions IOService::RemoveProperty_Impl(OSString * propertyName)
576e6231be0SApple OSS Distributions {
577e6231be0SApple OSS Distributions 	IOUserServer * us  = (IOUserServer *)thread_iokit_tls_get(0);
578e6231be0SApple OSS Distributions 	IOReturn       ret = kIOReturnUnsupported;
579e6231be0SApple OSS Distributions 
580e6231be0SApple OSS Distributions 	if (NULL == propertyName) {
581e6231be0SApple OSS Distributions 		return kIOReturnUnsupported;
582e6231be0SApple OSS Distributions 	}
583e6231be0SApple OSS Distributions 	if (NULL == us) {
584e6231be0SApple OSS Distributions 		removeProperty(propertyName);
585e6231be0SApple OSS Distributions 		return kIOReturnSuccess;
586e6231be0SApple OSS Distributions 	}
587e6231be0SApple OSS Distributions 	if (reserved && reserved->uvars && reserved->uvars->userServer == us) {
588e6231be0SApple OSS Distributions 		ret = runPropertyActionBlock(^IOReturn (void) {
589e6231be0SApple OSS Distributions 			OSDictionary * userProps;
590e6231be0SApple OSS Distributions 			userProps = OSDynamicCast(OSDictionary, getProperty(gIOUserServicePropertiesKey));
591e6231be0SApple OSS Distributions 			if (userProps) {
592e6231be0SApple OSS Distributions 			        userProps = (OSDictionary *)userProps->copyCollection();
593e6231be0SApple OSS Distributions 			        if (!userProps) {
594e6231be0SApple OSS Distributions 			                return kIOReturnNoMemory;
595e6231be0SApple OSS Distributions 				}
596e6231be0SApple OSS Distributions 			        userProps->removeObject(propertyName);
597e6231be0SApple OSS Distributions 			        bool ok = setProperty(gIOUserServicePropertiesKey, userProps);
598e6231be0SApple OSS Distributions 			        OSSafeReleaseNULL(userProps);
599e6231be0SApple OSS Distributions 			        return ok ? kIOReturnSuccess : kIOReturnNotWritable;
600e6231be0SApple OSS Distributions 			} else {
601e6231be0SApple OSS Distributions 			        return kIOReturnNotFound;
602e6231be0SApple OSS Distributions 			}
603e6231be0SApple OSS Distributions 		});
604e6231be0SApple OSS Distributions 	}
605e6231be0SApple OSS Distributions 	return ret;
606e6231be0SApple OSS Distributions }
607e6231be0SApple OSS Distributions 
608e6231be0SApple OSS Distributions kern_return_t
CopyProperties_Local(OSDictionary ** properties)6095c2921b0SApple OSS Distributions IOService::CopyProperties_Local(
610bb611c8fSApple OSS Distributions 	OSDictionary ** properties)
611a5e72196SApple OSS Distributions {
612e6231be0SApple OSS Distributions 	OSDictionary * props;
613e6231be0SApple OSS Distributions 	OSDictionary * userProps;
614e6231be0SApple OSS Distributions 
615e6231be0SApple OSS Distributions 	props = dictionaryWithProperties();
616e6231be0SApple OSS Distributions 	userProps = OSDynamicCast(OSDictionary, props->getObject(gIOUserServicePropertiesKey));
617e6231be0SApple OSS Distributions 	if (userProps) {
618e6231be0SApple OSS Distributions 		props->merge(userProps);
619e6231be0SApple OSS Distributions 		props->removeObject(gIOUserServicePropertiesKey);
620e6231be0SApple OSS Distributions 	}
621e6231be0SApple OSS Distributions 
622e6231be0SApple OSS Distributions 	*properties = props;
623e6231be0SApple OSS Distributions 
624e6231be0SApple OSS Distributions 	return props ? kIOReturnSuccess : kIOReturnNoMemory;
625a5e72196SApple OSS Distributions }
626a5e72196SApple OSS Distributions 
627bb611c8fSApple OSS Distributions kern_return_t
CopyProperties_Impl(OSDictionary ** properties)6285c2921b0SApple OSS Distributions IOService::CopyProperties_Impl(
6295c2921b0SApple OSS Distributions 	OSDictionary ** properties)
6305c2921b0SApple OSS Distributions {
6315c2921b0SApple OSS Distributions 	return CopyProperties_Local(properties);
6325c2921b0SApple OSS Distributions }
6335c2921b0SApple OSS Distributions 
6345c2921b0SApple OSS Distributions kern_return_t
RequireMaxBusStall_Impl(uint64_t u64ns)635bb611c8fSApple OSS Distributions IOService::RequireMaxBusStall_Impl(
636bb611c8fSApple OSS Distributions 	uint64_t u64ns)
637bb611c8fSApple OSS Distributions {
638bb611c8fSApple OSS Distributions 	IOReturn ret;
639bb611c8fSApple OSS Distributions 	UInt32   ns;
640bb611c8fSApple OSS Distributions 
641bb611c8fSApple OSS Distributions 	if (os_convert_overflow(u64ns, &ns)) {
642bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
643bb611c8fSApple OSS Distributions 	}
644bb611c8fSApple OSS Distributions 	ret = requireMaxBusStall(ns);
645bb611c8fSApple OSS Distributions 
646aca3beaaSApple OSS Distributions 	return ret;
647bb611c8fSApple OSS Distributions }
648bb611c8fSApple OSS Distributions 
649e6231be0SApple OSS Distributions #if PRIVATE_WIFI_ONLY
650e6231be0SApple OSS Distributions kern_return_t
UserSetProperties_Impl(OSContainer * properties)651e6231be0SApple OSS Distributions IOService::UserSetProperties_Impl(
652e6231be0SApple OSS Distributions 	OSContainer * properties)
653e6231be0SApple OSS Distributions {
654e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
655e6231be0SApple OSS Distributions }
6565c2921b0SApple OSS Distributions 
6575c2921b0SApple OSS Distributions kern_return_t
SendIOMessageServicePropertyChange_Impl(void)6585c2921b0SApple OSS Distributions IOService::SendIOMessageServicePropertyChange_Impl(void)
6595c2921b0SApple OSS Distributions {
6605c2921b0SApple OSS Distributions 	return messageClients(kIOMessageServicePropertyChange);
6615c2921b0SApple OSS Distributions }
662e6231be0SApple OSS Distributions #endif /* PRIVATE_WIFI_ONLY */
663e6231be0SApple OSS Distributions 
664bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
665a5e72196SApple OSS Distributions 
666a5e72196SApple OSS Distributions kern_return_t
_CopyState_Impl(_IOMDPrivateState * state)667bb611c8fSApple OSS Distributions IOMemoryDescriptor::_CopyState_Impl(
668bb611c8fSApple OSS Distributions 	_IOMDPrivateState * state)
669a5e72196SApple OSS Distributions {
670a5e72196SApple OSS Distributions 	IOReturn ret;
671a5e72196SApple OSS Distributions 
672a5e72196SApple OSS Distributions 	state->length = _length;
673a5e72196SApple OSS Distributions 	state->options = _flags;
674a5e72196SApple OSS Distributions 
675a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
676a5e72196SApple OSS Distributions 
677a5e72196SApple OSS Distributions 	return ret;
678a5e72196SApple OSS Distributions }
679a5e72196SApple OSS Distributions 
680a5e72196SApple OSS Distributions kern_return_t
GetLength(uint64_t * returnLength)681a5e72196SApple OSS Distributions IOMemoryDescriptor::GetLength(uint64_t * returnLength)
682a5e72196SApple OSS Distributions {
683a5e72196SApple OSS Distributions 	*returnLength = getLength();
684a5e72196SApple OSS Distributions 
685a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
686a5e72196SApple OSS Distributions }
687a5e72196SApple OSS Distributions 
688a5e72196SApple OSS Distributions kern_return_t
CreateMapping_Impl(uint64_t options,uint64_t address,uint64_t offset,uint64_t length,uint64_t alignment,IOMemoryMap ** map)689bb611c8fSApple OSS Distributions IOMemoryDescriptor::CreateMapping_Impl(
690bb611c8fSApple OSS Distributions 	uint64_t options,
691bb611c8fSApple OSS Distributions 	uint64_t address,
692bb611c8fSApple OSS Distributions 	uint64_t offset,
693bb611c8fSApple OSS Distributions 	uint64_t length,
694bb611c8fSApple OSS Distributions 	uint64_t alignment,
695bb611c8fSApple OSS Distributions 	IOMemoryMap ** map)
696a5e72196SApple OSS Distributions {
697a5e72196SApple OSS Distributions 	IOReturn          ret;
698a5e72196SApple OSS Distributions 	IOMemoryMap     * resultMap;
699a5e72196SApple OSS Distributions 	IOOptionBits      koptions;
700a5e72196SApple OSS Distributions 	mach_vm_address_t atAddress;
701a5e72196SApple OSS Distributions 
702a5e72196SApple OSS Distributions 	ret       = kIOReturnSuccess;
703a5e72196SApple OSS Distributions 	koptions  = 0;
704a5e72196SApple OSS Distributions 	resultMap = NULL;
705a5e72196SApple OSS Distributions 
706a5e72196SApple OSS Distributions 	if (kIOMemoryMapFixedAddress & options) {
707a5e72196SApple OSS Distributions 		atAddress   = address;
708a5e72196SApple OSS Distributions 		koptions    = 0;
709a5e72196SApple OSS Distributions 	} else {
710e6231be0SApple OSS Distributions 		switch (kIOMemoryMapGuardedMask & options) {
711e6231be0SApple OSS Distributions 		default:
712e6231be0SApple OSS Distributions 		case kIOMemoryMapGuardedDefault:
713e6231be0SApple OSS Distributions 			koptions |= kIOMapGuardedSmall;
714e6231be0SApple OSS Distributions 			break;
715e6231be0SApple OSS Distributions 		case kIOMemoryMapGuardedNone:
716e6231be0SApple OSS Distributions 			break;
717e6231be0SApple OSS Distributions 		case kIOMemoryMapGuardedSmall:
718e6231be0SApple OSS Distributions 			koptions |= kIOMapGuardedSmall;
719e6231be0SApple OSS Distributions 			break;
720e6231be0SApple OSS Distributions 		case kIOMemoryMapGuardedLarge:
721e6231be0SApple OSS Distributions 			koptions |= kIOMapGuardedLarge;
722e6231be0SApple OSS Distributions 			break;
723e6231be0SApple OSS Distributions 		}
724a5e72196SApple OSS Distributions 		atAddress   = 0;
725a5e72196SApple OSS Distributions 		koptions   |= kIOMapAnywhere;
726a5e72196SApple OSS Distributions 	}
727a5e72196SApple OSS Distributions 
728e6231be0SApple OSS Distributions 	if ((kIOMemoryMapReadOnly & options) || (kIODirectionOut == getDirection())) {
729a5e72196SApple OSS Distributions 		if (!reserved || (current_task() != reserved->creator)) {
730a5e72196SApple OSS Distributions 			koptions   |= kIOMapReadOnly;
731a5e72196SApple OSS Distributions 		}
732a5e72196SApple OSS Distributions 	}
733a5e72196SApple OSS Distributions 
734a5e72196SApple OSS Distributions 	switch (0xFF00 & options) {
735a5e72196SApple OSS Distributions 	case kIOMemoryMapCacheModeDefault:
736a5e72196SApple OSS Distributions 		koptions |= kIOMapDefaultCache;
737a5e72196SApple OSS Distributions 		break;
738a5e72196SApple OSS Distributions 	case kIOMemoryMapCacheModeInhibit:
739a5e72196SApple OSS Distributions 		koptions |= kIOMapInhibitCache;
740a5e72196SApple OSS Distributions 		break;
741a5e72196SApple OSS Distributions 	case kIOMemoryMapCacheModeCopyback:
742a5e72196SApple OSS Distributions 		koptions |= kIOMapCopybackCache;
743a5e72196SApple OSS Distributions 		break;
744a5e72196SApple OSS Distributions 	case kIOMemoryMapCacheModeWriteThrough:
745a5e72196SApple OSS Distributions 		koptions |= kIOMapWriteThruCache;
746a5e72196SApple OSS Distributions 		break;
7478d741a5dSApple OSS Distributions 	case kIOMemoryMapCacheModeRealTime:
7488d741a5dSApple OSS Distributions 		koptions |= kIOMapRealTimeCache;
7498d741a5dSApple OSS Distributions 		break;
750a5e72196SApple OSS Distributions 	default:
751a5e72196SApple OSS Distributions 		ret = kIOReturnBadArgument;
752a5e72196SApple OSS Distributions 	}
753a5e72196SApple OSS Distributions 
754a5e72196SApple OSS Distributions 	if (kIOReturnSuccess == ret) {
755a5e72196SApple OSS Distributions 		resultMap = createMappingInTask(current_task(), atAddress, koptions, offset, length);
756a5e72196SApple OSS Distributions 		if (!resultMap) {
757a5e72196SApple OSS Distributions 			ret = kIOReturnError;
758a5e72196SApple OSS Distributions 		}
759a5e72196SApple OSS Distributions 	}
760a5e72196SApple OSS Distributions 
761a5e72196SApple OSS Distributions 	*map = resultMap;
762a5e72196SApple OSS Distributions 
763a5e72196SApple OSS Distributions 	return ret;
764a5e72196SApple OSS Distributions }
765a5e72196SApple OSS Distributions 
766a5e72196SApple OSS Distributions kern_return_t
CreateSubMemoryDescriptor_Impl(uint64_t memoryDescriptorCreateOptions,uint64_t offset,uint64_t length,IOMemoryDescriptor * ofDescriptor,IOMemoryDescriptor ** memory)767bb611c8fSApple OSS Distributions IOMemoryDescriptor::CreateSubMemoryDescriptor_Impl(
768bb611c8fSApple OSS Distributions 	uint64_t memoryDescriptorCreateOptions,
769bb611c8fSApple OSS Distributions 	uint64_t offset,
770bb611c8fSApple OSS Distributions 	uint64_t length,
771bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * ofDescriptor,
772bb611c8fSApple OSS Distributions 	IOMemoryDescriptor ** memory)
773a5e72196SApple OSS Distributions {
774a5e72196SApple OSS Distributions 	IOReturn             ret;
775bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * iomd;
776bb611c8fSApple OSS Distributions 	IOByteCount          mdOffset;
777bb611c8fSApple OSS Distributions 	IOByteCount          mdLength;
778bb611c8fSApple OSS Distributions 	IOByteCount          mdEnd;
779a5e72196SApple OSS Distributions 
780bb611c8fSApple OSS Distributions 	if (!ofDescriptor) {
781bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
782bb611c8fSApple OSS Distributions 	}
783bb611c8fSApple OSS Distributions 	if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) {
784bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
785bb611c8fSApple OSS Distributions 	}
786bb611c8fSApple OSS Distributions 	if (os_convert_overflow(offset, &mdOffset)) {
787bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
788bb611c8fSApple OSS Distributions 	}
789bb611c8fSApple OSS Distributions 	if (os_convert_overflow(length, &mdLength)) {
790bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
791bb611c8fSApple OSS Distributions 	}
792bb611c8fSApple OSS Distributions 	if (os_add_overflow(mdOffset, mdLength, &mdEnd)) {
793bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
794bb611c8fSApple OSS Distributions 	}
795bb611c8fSApple OSS Distributions 	if (mdEnd > ofDescriptor->getLength()) {
796a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
797a5e72196SApple OSS Distributions 	}
798a5e72196SApple OSS Distributions 
799bb611c8fSApple OSS Distributions 	iomd = IOSubMemoryDescriptor::withSubRange(
800bb611c8fSApple OSS Distributions 		ofDescriptor, mdOffset, mdLength, (IOOptionBits) memoryDescriptorCreateOptions);
801a5e72196SApple OSS Distributions 
802bb611c8fSApple OSS Distributions 	if (iomd) {
803a5e72196SApple OSS Distributions 		ret = kIOReturnSuccess;
804bb611c8fSApple OSS Distributions 		*memory = iomd;
805bb611c8fSApple OSS Distributions 	} else {
806bb611c8fSApple OSS Distributions 		ret = kIOReturnNoMemory;
807bb611c8fSApple OSS Distributions 		*memory = NULL;
808bb611c8fSApple OSS Distributions 	}
809bb611c8fSApple OSS Distributions 
810bb611c8fSApple OSS Distributions 	return ret;
811bb611c8fSApple OSS Distributions }
812bb611c8fSApple OSS Distributions 
813bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
814bb611c8fSApple OSS Distributions 
815bb611c8fSApple OSS Distributions kern_return_t
CreateWithMemoryDescriptors_Impl(uint64_t memoryDescriptorCreateOptions,uint32_t withDescriptorsCount,IOMemoryDescriptor ** const withDescriptors,IOMemoryDescriptor ** memory)816bb611c8fSApple OSS Distributions IOMemoryDescriptor::CreateWithMemoryDescriptors_Impl(
817bb611c8fSApple OSS Distributions 	uint64_t memoryDescriptorCreateOptions,
818bb611c8fSApple OSS Distributions 	uint32_t withDescriptorsCount,
819bb611c8fSApple OSS Distributions 	IOMemoryDescriptor ** const withDescriptors,
820bb611c8fSApple OSS Distributions 	IOMemoryDescriptor ** memory)
821bb611c8fSApple OSS Distributions {
822bb611c8fSApple OSS Distributions 	IOReturn             ret;
823bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * iomd;
824bb611c8fSApple OSS Distributions 
825bb611c8fSApple OSS Distributions 	if (!withDescriptors) {
826bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
827bb611c8fSApple OSS Distributions 	}
828bb611c8fSApple OSS Distributions 	if (!withDescriptorsCount) {
829bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
830bb611c8fSApple OSS Distributions 	}
831bb611c8fSApple OSS Distributions 	if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) {
832bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
833bb611c8fSApple OSS Distributions 	}
834bb611c8fSApple OSS Distributions 
835bb611c8fSApple OSS Distributions 	for (unsigned int idx = 0; idx < withDescriptorsCount; idx++) {
836bb611c8fSApple OSS Distributions 		if (NULL == withDescriptors[idx]) {
837bb611c8fSApple OSS Distributions 			return kIOReturnBadArgument;
838bb611c8fSApple OSS Distributions 		}
839bb611c8fSApple OSS Distributions 	}
840bb611c8fSApple OSS Distributions 
841bb611c8fSApple OSS Distributions 	iomd = IOMultiMemoryDescriptor::withDescriptors(withDescriptors, withDescriptorsCount,
842bb611c8fSApple OSS Distributions 	    (IODirection) memoryDescriptorCreateOptions, false);
843bb611c8fSApple OSS Distributions 
844bb611c8fSApple OSS Distributions 	if (iomd) {
845bb611c8fSApple OSS Distributions 		ret = kIOReturnSuccess;
846bb611c8fSApple OSS Distributions 		*memory = iomd;
847bb611c8fSApple OSS Distributions 	} else {
848bb611c8fSApple OSS Distributions 		ret = kIOReturnNoMemory;
849bb611c8fSApple OSS Distributions 		*memory = NULL;
850bb611c8fSApple OSS Distributions 	}
851a5e72196SApple OSS Distributions 
852a5e72196SApple OSS Distributions 	return ret;
853a5e72196SApple OSS Distributions }
854a5e72196SApple OSS Distributions 
855a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
856a5e72196SApple OSS Distributions 
857a5e72196SApple OSS Distributions kern_return_t
CreateMemoryDescriptorFromClient_Impl(uint64_t memoryDescriptorCreateOptions,uint32_t segmentsCount,const IOAddressSegment segments[32],IOMemoryDescriptor ** memory)858bb611c8fSApple OSS Distributions IOUserClient::CreateMemoryDescriptorFromClient_Impl(
859bb611c8fSApple OSS Distributions 	uint64_t memoryDescriptorCreateOptions,
860bb611c8fSApple OSS Distributions 	uint32_t segmentsCount,
861bb611c8fSApple OSS Distributions 	const IOAddressSegment segments[32],
862bb611c8fSApple OSS Distributions 	IOMemoryDescriptor ** memory)
863bb611c8fSApple OSS Distributions {
864bb611c8fSApple OSS Distributions 	IOReturn             ret;
865bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * iomd;
866bb611c8fSApple OSS Distributions 	IOOptionBits         mdOptions;
867bb611c8fSApple OSS Distributions 	IOUserUserClient   * me;
868bb611c8fSApple OSS Distributions 	IOAddressRange     * ranges;
869bb611c8fSApple OSS Distributions 
870bb611c8fSApple OSS Distributions 	me = OSDynamicCast(IOUserUserClient, this);
871bb611c8fSApple OSS Distributions 	if (!me) {
872bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
873bb611c8fSApple OSS Distributions 	}
874e6231be0SApple OSS Distributions 	if (!me->fTask) {
875e6231be0SApple OSS Distributions 		return kIOReturnNotReady;
876e6231be0SApple OSS Distributions 	}
877bb611c8fSApple OSS Distributions 
8785c2921b0SApple OSS Distributions 	mdOptions = kIOMemoryThreadSafe;
879bb611c8fSApple OSS Distributions 	if (kIOMemoryDirectionOut & memoryDescriptorCreateOptions) {
880bb611c8fSApple OSS Distributions 		mdOptions |= kIODirectionOut;
881bb611c8fSApple OSS Distributions 	}
882bb611c8fSApple OSS Distributions 	if (kIOMemoryDirectionIn & memoryDescriptorCreateOptions) {
883bb611c8fSApple OSS Distributions 		mdOptions |= kIODirectionIn;
884bb611c8fSApple OSS Distributions 	}
885bb611c8fSApple OSS Distributions 	if (!(kIOMemoryDisableCopyOnWrite & memoryDescriptorCreateOptions)) {
886bb611c8fSApple OSS Distributions 		mdOptions |= kIOMemoryMapCopyOnWrite;
887bb611c8fSApple OSS Distributions 	}
888bb611c8fSApple OSS Distributions 
889bb611c8fSApple OSS Distributions 	static_assert(sizeof(IOAddressRange) == sizeof(IOAddressSegment));
890bb611c8fSApple OSS Distributions 	ranges = __DECONST(IOAddressRange *, &segments[0]);
891bb611c8fSApple OSS Distributions 
892bb611c8fSApple OSS Distributions 	iomd = IOMemoryDescriptor::withAddressRanges(
893bb611c8fSApple OSS Distributions 		ranges, segmentsCount,
894bb611c8fSApple OSS Distributions 		mdOptions, me->fTask);
895bb611c8fSApple OSS Distributions 
896bb611c8fSApple OSS Distributions 	if (iomd) {
897bb611c8fSApple OSS Distributions 		ret = kIOReturnSuccess;
898bb611c8fSApple OSS Distributions 		*memory = iomd;
899bb611c8fSApple OSS Distributions 	} else {
900bb611c8fSApple OSS Distributions 		ret = kIOReturnNoMemory;
901bb611c8fSApple OSS Distributions 		*memory = NULL;
902bb611c8fSApple OSS Distributions 	}
903bb611c8fSApple OSS Distributions 
904bb611c8fSApple OSS Distributions 	return ret;
905bb611c8fSApple OSS Distributions }
906bb611c8fSApple OSS Distributions 
907bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
908bb611c8fSApple OSS Distributions 
909bb611c8fSApple OSS Distributions kern_return_t
_CopyState_Impl(_IOMemoryMapPrivateState * state)910bb611c8fSApple OSS Distributions IOMemoryMap::_CopyState_Impl(
911bb611c8fSApple OSS Distributions 	_IOMemoryMapPrivateState * state)
912a5e72196SApple OSS Distributions {
913a5e72196SApple OSS Distributions 	IOReturn ret;
914a5e72196SApple OSS Distributions 
915a5e72196SApple OSS Distributions 	state->offset  = fOffset;
916a5e72196SApple OSS Distributions 	state->length  = getLength();
917a5e72196SApple OSS Distributions 	state->address = getAddress();
918a5e72196SApple OSS Distributions 	state->options = getMapOptions();
919a5e72196SApple OSS Distributions 
920a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
921a5e72196SApple OSS Distributions 
922a5e72196SApple OSS Distributions 	return ret;
923a5e72196SApple OSS Distributions }
924a5e72196SApple OSS Distributions 
925bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
926a5e72196SApple OSS Distributions 
927a5e72196SApple OSS Distributions kern_return_t
Create_Impl(uint64_t options,uint64_t capacity,uint64_t alignment,IOBufferMemoryDescriptor ** memory)928bb611c8fSApple OSS Distributions IOBufferMemoryDescriptor::Create_Impl(
929bb611c8fSApple OSS Distributions 	uint64_t options,
930bb611c8fSApple OSS Distributions 	uint64_t capacity,
931bb611c8fSApple OSS Distributions 	uint64_t alignment,
932bb611c8fSApple OSS Distributions 	IOBufferMemoryDescriptor ** memory)
933a5e72196SApple OSS Distributions {
934a5e72196SApple OSS Distributions 	IOReturn ret;
935bb611c8fSApple OSS Distributions 	IOOptionBits                 bmdOptions;
936a5e72196SApple OSS Distributions 	IOBufferMemoryDescriptor   * bmd;
937a5e72196SApple OSS Distributions 	IOMemoryDescriptorReserved * reserved;
938a5e72196SApple OSS Distributions 
939a5e72196SApple OSS Distributions 	if (options & ~((uint64_t) kIOMemoryDirectionOutIn)) {
940a5e72196SApple OSS Distributions 		// no other options currently defined
941a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
942a5e72196SApple OSS Distributions 	}
9435c2921b0SApple OSS Distributions 	bmdOptions = (options & kIOMemoryDirectionOutIn) | kIOMemoryKernelUserShared | kIOMemoryThreadSafe;
944a5e72196SApple OSS Distributions 	bmd = IOBufferMemoryDescriptor::inTaskWithOptions(
945bb611c8fSApple OSS Distributions 		kernel_task, bmdOptions, capacity, alignment);
946a5e72196SApple OSS Distributions 
947a5e72196SApple OSS Distributions 	*memory = bmd;
948a5e72196SApple OSS Distributions 
949a5e72196SApple OSS Distributions 	if (!bmd) {
950a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
951a5e72196SApple OSS Distributions 	}
952a5e72196SApple OSS Distributions 
953a5e72196SApple OSS Distributions 	reserved = bmd->getKernelReserved();
954a5e72196SApple OSS Distributions 	reserved->creator = current_task();
955a5e72196SApple OSS Distributions 	task_reference(reserved->creator);
956a5e72196SApple OSS Distributions 
957a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
958a5e72196SApple OSS Distributions 
959a5e72196SApple OSS Distributions 	return ret;
960a5e72196SApple OSS Distributions }
961a5e72196SApple OSS Distributions 
962a5e72196SApple OSS Distributions kern_return_t
SetLength_Impl(uint64_t length)963bb611c8fSApple OSS Distributions IOBufferMemoryDescriptor::SetLength_Impl(
964bb611c8fSApple OSS Distributions 	uint64_t length)
965a5e72196SApple OSS Distributions {
966a5e72196SApple OSS Distributions 	setLength(length);
967a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
968a5e72196SApple OSS Distributions }
969a5e72196SApple OSS Distributions 
970bb611c8fSApple OSS Distributions 
971bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
972a5e72196SApple OSS Distributions 
973a5e72196SApple OSS Distributions kern_return_t
Create_Impl(IOService * device,uint64_t options,const IODMACommandSpecification * specification,IODMACommand ** command)974bb611c8fSApple OSS Distributions IODMACommand::Create_Impl(
975bb611c8fSApple OSS Distributions 	IOService * device,
976bb611c8fSApple OSS Distributions 	uint64_t options,
977bb611c8fSApple OSS Distributions 	const IODMACommandSpecification * specification,
978bb611c8fSApple OSS Distributions 	IODMACommand ** command)
979a5e72196SApple OSS Distributions {
980bb611c8fSApple OSS Distributions 	IOReturn ret;
981bb611c8fSApple OSS Distributions 	IODMACommand   * dma;
982bb611c8fSApple OSS Distributions 	IODMACommand::SegmentOptions segmentOptions;
983bb611c8fSApple OSS Distributions 	IOMapper             * mapper;
984bb611c8fSApple OSS Distributions 
985bb611c8fSApple OSS Distributions 	if (options & ~((uint64_t) kIODMACommandCreateNoOptions)) {
986bb611c8fSApple OSS Distributions 		// no other options currently defined
987bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
988bb611c8fSApple OSS Distributions 	}
989bb611c8fSApple OSS Distributions 
990bb611c8fSApple OSS Distributions 	if (os_convert_overflow(specification->maxAddressBits, &segmentOptions.fNumAddressBits)) {
991bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
992bb611c8fSApple OSS Distributions 	}
993bb611c8fSApple OSS Distributions 	segmentOptions.fMaxSegmentSize            = 0;
994bb611c8fSApple OSS Distributions 	segmentOptions.fMaxTransferSize           = 0;
995bb611c8fSApple OSS Distributions 	segmentOptions.fAlignment                 = 1;
996bb611c8fSApple OSS Distributions 	segmentOptions.fAlignmentLength           = 1;
997bb611c8fSApple OSS Distributions 	segmentOptions.fAlignmentInternalSegments = 1;
998bb611c8fSApple OSS Distributions 	segmentOptions.fStructSize                = sizeof(segmentOptions);
999bb611c8fSApple OSS Distributions 
1000bb611c8fSApple OSS Distributions 	mapper = IOMapper::copyMapperForDevice(device);
1001bb611c8fSApple OSS Distributions 
1002bb611c8fSApple OSS Distributions 	dma = IODMACommand::withSpecification(
1003bb611c8fSApple OSS Distributions 		kIODMACommandOutputHost64,
1004bb611c8fSApple OSS Distributions 		&segmentOptions,
10055c2921b0SApple OSS Distributions 		kIODMAMapOptionDextOwner |
1006bb611c8fSApple OSS Distributions 		kIODMAMapOptionMapped,
1007bb611c8fSApple OSS Distributions 		mapper,
1008bb611c8fSApple OSS Distributions 		NULL);
1009bb611c8fSApple OSS Distributions 
1010bb611c8fSApple OSS Distributions 	OSSafeReleaseNULL(mapper);
1011bb611c8fSApple OSS Distributions 	*command = dma;
1012bb611c8fSApple OSS Distributions 
1013bb611c8fSApple OSS Distributions 	if (!dma) {
1014bb611c8fSApple OSS Distributions 		return kIOReturnNoMemory;
1015bb611c8fSApple OSS Distributions 	}
1016bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
1017bb611c8fSApple OSS Distributions 
1018a5e72196SApple OSS Distributions 	return ret;
1019a5e72196SApple OSS Distributions }
1020a5e72196SApple OSS Distributions 
1021aca3beaaSApple OSS Distributions #define fInternalState reserved
1022aca3beaaSApple OSS Distributions 
1023a5e72196SApple OSS Distributions kern_return_t
PrepareForDMA_Impl(uint64_t options,IOMemoryDescriptor * memory,uint64_t offset,uint64_t length,uint64_t * flags,uint32_t * segmentsCount,IOAddressSegment * segments)1024bb611c8fSApple OSS Distributions IODMACommand::PrepareForDMA_Impl(
1025bb611c8fSApple OSS Distributions 	uint64_t options,
1026bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * memory,
1027bb611c8fSApple OSS Distributions 	uint64_t offset,
1028bb611c8fSApple OSS Distributions 	uint64_t length,
1029bb611c8fSApple OSS Distributions 	uint64_t * flags,
1030bb611c8fSApple OSS Distributions 	uint32_t * segmentsCount,
1031bb611c8fSApple OSS Distributions 	IOAddressSegment * segments)
1032a5e72196SApple OSS Distributions {
1033bb611c8fSApple OSS Distributions 	IOReturn ret;
1034bb611c8fSApple OSS Distributions 	uint64_t lflags, mdFlags;
1035bb611c8fSApple OSS Distributions 	UInt32   numSegments;
1036bb611c8fSApple OSS Distributions 	UInt64   genOffset;
1037a5e72196SApple OSS Distributions 
1038bb611c8fSApple OSS Distributions 	if (options & ~((uint64_t) kIODMACommandPrepareForDMANoOptions)) {
1039bb611c8fSApple OSS Distributions 		// no other options currently defined
1040a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
1041a5e72196SApple OSS Distributions 	}
1042bb611c8fSApple OSS Distributions 
1043aca3beaaSApple OSS Distributions 	if (memory == NULL) {
1044aca3beaaSApple OSS Distributions 		return kIOReturnBadArgument;
1045aca3beaaSApple OSS Distributions 	}
1046aca3beaaSApple OSS Distributions 
1047aca3beaaSApple OSS Distributions 	assert(fInternalState->fDextLock);
1048aca3beaaSApple OSS Distributions 	IOLockLock(fInternalState->fDextLock);
1049aca3beaaSApple OSS Distributions 
1050bb611c8fSApple OSS Distributions 	// uses IOMD direction
1051bb611c8fSApple OSS Distributions 	ret = memory->prepare();
1052bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess != ret) {
1053aca3beaaSApple OSS Distributions 		goto exit;
1054bb611c8fSApple OSS Distributions 	}
1055bb611c8fSApple OSS Distributions 
1056bb611c8fSApple OSS Distributions 	ret = setMemoryDescriptor(memory, false);
1057bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess != ret) {
1058bb611c8fSApple OSS Distributions 		memory->complete();
1059aca3beaaSApple OSS Distributions 		goto exit;
1060bb611c8fSApple OSS Distributions 	}
1061bb611c8fSApple OSS Distributions 
1062bb611c8fSApple OSS Distributions 	ret = prepare(offset, length);
1063bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess != ret) {
1064bb611c8fSApple OSS Distributions 		clearMemoryDescriptor(false);
1065bb611c8fSApple OSS Distributions 		memory->complete();
1066aca3beaaSApple OSS Distributions 		goto exit;
1067bb611c8fSApple OSS Distributions 	}
1068bb611c8fSApple OSS Distributions 
1069bb611c8fSApple OSS Distributions 	static_assert(sizeof(IODMACommand::Segment64) == sizeof(IOAddressSegment));
1070bb611c8fSApple OSS Distributions 
1071bb611c8fSApple OSS Distributions 	numSegments = *segmentsCount;
1072e6231be0SApple OSS Distributions 	genOffset   = 0;
1073bb611c8fSApple OSS Distributions 	ret = genIOVMSegments(&genOffset, segments, &numSegments);
1074bb611c8fSApple OSS Distributions 
1075aca3beaaSApple OSS Distributions 	if (kIOReturnSuccess != ret) {
1076aca3beaaSApple OSS Distributions 		clearMemoryDescriptor(true);
1077aca3beaaSApple OSS Distributions 		memory->complete();
1078aca3beaaSApple OSS Distributions 		goto exit;
1079aca3beaaSApple OSS Distributions 	}
1080aca3beaaSApple OSS Distributions 
1081bb611c8fSApple OSS Distributions 	mdFlags = fMemory->getFlags();
1082bb611c8fSApple OSS Distributions 	lflags  = 0;
1083bb611c8fSApple OSS Distributions 	if (kIODirectionOut & mdFlags) {
1084bb611c8fSApple OSS Distributions 		lflags |= kIOMemoryDirectionOut;
1085bb611c8fSApple OSS Distributions 	}
1086bb611c8fSApple OSS Distributions 	if (kIODirectionIn & mdFlags) {
1087bb611c8fSApple OSS Distributions 		lflags |= kIOMemoryDirectionIn;
1088bb611c8fSApple OSS Distributions 	}
1089bb611c8fSApple OSS Distributions 	*flags = lflags;
1090bb611c8fSApple OSS Distributions 	*segmentsCount = numSegments;
1091aca3beaaSApple OSS Distributions 
1092aca3beaaSApple OSS Distributions exit:
1093aca3beaaSApple OSS Distributions 	IOLockUnlock(fInternalState->fDextLock);
1094bb611c8fSApple OSS Distributions 
1095bb611c8fSApple OSS Distributions 	return ret;
1096bb611c8fSApple OSS Distributions }
1097bb611c8fSApple OSS Distributions 
1098bb611c8fSApple OSS Distributions kern_return_t
CompleteDMA_Impl(uint64_t options)1099bb611c8fSApple OSS Distributions IODMACommand::CompleteDMA_Impl(
1100bb611c8fSApple OSS Distributions 	uint64_t options)
1101bb611c8fSApple OSS Distributions {
1102bb611c8fSApple OSS Distributions 	IOReturn ret, completeRet;
1103bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * md;
1104bb611c8fSApple OSS Distributions 
1105bb611c8fSApple OSS Distributions 	if (options & ~((uint64_t) kIODMACommandCompleteDMANoOptions)) {
1106bb611c8fSApple OSS Distributions 		// no other options currently defined
1107bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
1108bb611c8fSApple OSS Distributions 	}
1109aca3beaaSApple OSS Distributions 
1110aca3beaaSApple OSS Distributions 	assert(fInternalState->fDextLock);
1111aca3beaaSApple OSS Distributions 	IOLockLock(fInternalState->fDextLock);
1112aca3beaaSApple OSS Distributions 
1113aca3beaaSApple OSS Distributions 	if (!fInternalState->fPrepared) {
1114aca3beaaSApple OSS Distributions 		ret = kIOReturnNotReady;
1115aca3beaaSApple OSS Distributions 		goto exit;
1116bb611c8fSApple OSS Distributions 	}
1117bb611c8fSApple OSS Distributions 
1118bb611c8fSApple OSS Distributions 	md = __DECONST(IOMemoryDescriptor *, fMemory);
1119bb611c8fSApple OSS Distributions 	if (md) {
1120bb611c8fSApple OSS Distributions 		md->retain();
1121bb611c8fSApple OSS Distributions 	}
1122bb611c8fSApple OSS Distributions 
1123bb611c8fSApple OSS Distributions 	ret = clearMemoryDescriptor(true);
1124bb611c8fSApple OSS Distributions 
1125bb611c8fSApple OSS Distributions 	if (md) {
1126bb611c8fSApple OSS Distributions 		completeRet = md->complete();
1127bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(md);
1128bb611c8fSApple OSS Distributions 		if (kIOReturnSuccess == ret) {
1129bb611c8fSApple OSS Distributions 			ret = completeRet;
1130bb611c8fSApple OSS Distributions 		}
1131bb611c8fSApple OSS Distributions 	}
1132aca3beaaSApple OSS Distributions exit:
1133aca3beaaSApple OSS Distributions 	IOLockUnlock(fInternalState->fDextLock);
1134bb611c8fSApple OSS Distributions 
1135bb611c8fSApple OSS Distributions 	return ret;
1136bb611c8fSApple OSS Distributions }
1137bb611c8fSApple OSS Distributions 
1138bb611c8fSApple OSS Distributions kern_return_t
GetPreparation_Impl(uint64_t * offset,uint64_t * length,IOMemoryDescriptor ** memory)1139bb611c8fSApple OSS Distributions IODMACommand::GetPreparation_Impl(
1140bb611c8fSApple OSS Distributions 	uint64_t * offset,
1141bb611c8fSApple OSS Distributions 	uint64_t * length,
1142bb611c8fSApple OSS Distributions 	IOMemoryDescriptor ** memory)
1143bb611c8fSApple OSS Distributions {
1144bb611c8fSApple OSS Distributions 	IOReturn ret;
1145bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * md;
1146bb611c8fSApple OSS Distributions 
1147bb611c8fSApple OSS Distributions 	if (!fActive) {
1148bb611c8fSApple OSS Distributions 		return kIOReturnNotReady;
1149bb611c8fSApple OSS Distributions 	}
1150bb611c8fSApple OSS Distributions 
1151bb611c8fSApple OSS Distributions 	ret = getPreparedOffsetAndLength(offset, length);
1152bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess != ret) {
1153bb611c8fSApple OSS Distributions 		return ret;
1154bb611c8fSApple OSS Distributions 	}
1155bb611c8fSApple OSS Distributions 
1156bb611c8fSApple OSS Distributions 	if (memory) {
1157bb611c8fSApple OSS Distributions 		md = __DECONST(IOMemoryDescriptor *, fMemory);
1158bb611c8fSApple OSS Distributions 		*memory = md;
1159bb611c8fSApple OSS Distributions 		if (!md) {
1160bb611c8fSApple OSS Distributions 			ret = kIOReturnNotReady;
1161bb611c8fSApple OSS Distributions 		} else {
1162bb611c8fSApple OSS Distributions 			md->retain();
1163bb611c8fSApple OSS Distributions 		}
1164bb611c8fSApple OSS Distributions 	}
1165bb611c8fSApple OSS Distributions 	return ret;
1166bb611c8fSApple OSS Distributions }
1167bb611c8fSApple OSS Distributions 
1168bb611c8fSApple OSS Distributions kern_return_t
PerformOperation_Impl(uint64_t options,uint64_t dmaOffset,uint64_t length,uint64_t dataOffset,IOMemoryDescriptor * data)1169bb611c8fSApple OSS Distributions IODMACommand::PerformOperation_Impl(
1170bb611c8fSApple OSS Distributions 	uint64_t options,
1171bb611c8fSApple OSS Distributions 	uint64_t dmaOffset,
1172bb611c8fSApple OSS Distributions 	uint64_t length,
1173bb611c8fSApple OSS Distributions 	uint64_t dataOffset,
1174bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * data)
1175bb611c8fSApple OSS Distributions {
1176bb611c8fSApple OSS Distributions 	IOReturn ret;
1177e6231be0SApple OSS Distributions 	OSDataAllocation<uint8_t> buffer;
1178bb611c8fSApple OSS Distributions 	UInt64 copiedDMA;
1179bb611c8fSApple OSS Distributions 	IOByteCount mdOffset, mdLength, copied;
1180bb611c8fSApple OSS Distributions 
1181bb611c8fSApple OSS Distributions 	if (options & ~((uint64_t)
1182bb611c8fSApple OSS Distributions 	    (kIODMACommandPerformOperationOptionRead
1183bb611c8fSApple OSS Distributions 	    | kIODMACommandPerformOperationOptionWrite
1184bb611c8fSApple OSS Distributions 	    | kIODMACommandPerformOperationOptionZero))) {
1185bb611c8fSApple OSS Distributions 		// no other options currently defined
1186bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
1187bb611c8fSApple OSS Distributions 	}
1188bb611c8fSApple OSS Distributions 
1189bb611c8fSApple OSS Distributions 	if (!fActive) {
1190bb611c8fSApple OSS Distributions 		return kIOReturnNotReady;
1191bb611c8fSApple OSS Distributions 	}
1192bb611c8fSApple OSS Distributions 	if (os_convert_overflow(dataOffset, &mdOffset)) {
1193bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
1194bb611c8fSApple OSS Distributions 	}
1195bb611c8fSApple OSS Distributions 	if (os_convert_overflow(length, &mdLength)) {
1196bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
1197bb611c8fSApple OSS Distributions 	}
1198bb611c8fSApple OSS Distributions 	if (length > fMemory->getLength()) {
1199bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
1200bb611c8fSApple OSS Distributions 	}
1201e6231be0SApple OSS Distributions 	buffer = OSDataAllocation<uint8_t>(length, OSAllocateMemory);
1202e6231be0SApple OSS Distributions 	if (!buffer) {
1203a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
1204a5e72196SApple OSS Distributions 	}
1205bb611c8fSApple OSS Distributions 
1206bb611c8fSApple OSS Distributions 	switch (options) {
1207bb611c8fSApple OSS Distributions 	case kIODMACommandPerformOperationOptionZero:
1208e6231be0SApple OSS Distributions 		bzero(buffer.data(), length);
1209e6231be0SApple OSS Distributions 		copiedDMA = writeBytes(dmaOffset, buffer.data(), length);
1210bb611c8fSApple OSS Distributions 		if (copiedDMA != length) {
1211bb611c8fSApple OSS Distributions 			ret = kIOReturnUnderrun;
1212bb611c8fSApple OSS Distributions 			break;
1213bb611c8fSApple OSS Distributions 		}
1214bb611c8fSApple OSS Distributions 		ret = kIOReturnSuccess;
1215bb611c8fSApple OSS Distributions 		break;
1216bb611c8fSApple OSS Distributions 
1217bb611c8fSApple OSS Distributions 	case kIODMACommandPerformOperationOptionRead:
1218bb611c8fSApple OSS Distributions 	case kIODMACommandPerformOperationOptionWrite:
1219bb611c8fSApple OSS Distributions 
1220bb611c8fSApple OSS Distributions 		if (!data) {
1221bb611c8fSApple OSS Distributions 			ret = kIOReturnBadArgument;
1222bb611c8fSApple OSS Distributions 			break;
1223bb611c8fSApple OSS Distributions 		}
1224bb611c8fSApple OSS Distributions 		if (length > data->getLength()) {
1225bb611c8fSApple OSS Distributions 			ret = kIOReturnBadArgument;
1226bb611c8fSApple OSS Distributions 			break;
1227bb611c8fSApple OSS Distributions 		}
1228bb611c8fSApple OSS Distributions 		if (kIODMACommandPerformOperationOptionWrite == options) {
1229e6231be0SApple OSS Distributions 			copied = data->readBytes(mdOffset, buffer.data(), mdLength);
1230bb611c8fSApple OSS Distributions 			if (copied != mdLength) {
1231bb611c8fSApple OSS Distributions 				ret = kIOReturnUnderrun;
1232bb611c8fSApple OSS Distributions 				break;
1233bb611c8fSApple OSS Distributions 			}
1234e6231be0SApple OSS Distributions 			copiedDMA = writeBytes(dmaOffset, buffer.data(), length);
1235bb611c8fSApple OSS Distributions 			if (copiedDMA != length) {
1236bb611c8fSApple OSS Distributions 				ret = kIOReturnUnderrun;
1237bb611c8fSApple OSS Distributions 				break;
1238bb611c8fSApple OSS Distributions 			}
1239bb611c8fSApple OSS Distributions 		} else {       /* kIODMACommandPerformOperationOptionRead */
1240e6231be0SApple OSS Distributions 			copiedDMA = readBytes(dmaOffset, buffer.data(), length);
1241bb611c8fSApple OSS Distributions 			if (copiedDMA != length) {
1242bb611c8fSApple OSS Distributions 				ret = kIOReturnUnderrun;
1243bb611c8fSApple OSS Distributions 				break;
1244bb611c8fSApple OSS Distributions 			}
1245e6231be0SApple OSS Distributions 			copied = data->writeBytes(mdOffset, buffer.data(), mdLength);
1246bb611c8fSApple OSS Distributions 			if (copied != mdLength) {
1247bb611c8fSApple OSS Distributions 				ret = kIOReturnUnderrun;
1248bb611c8fSApple OSS Distributions 				break;
1249bb611c8fSApple OSS Distributions 			}
1250bb611c8fSApple OSS Distributions 		}
1251bb611c8fSApple OSS Distributions 		ret = kIOReturnSuccess;
1252bb611c8fSApple OSS Distributions 		break;
1253bb611c8fSApple OSS Distributions 	default:
1254bb611c8fSApple OSS Distributions 		ret = kIOReturnBadArgument;
1255bb611c8fSApple OSS Distributions 		break;
1256bb611c8fSApple OSS Distributions 	}
1257bb611c8fSApple OSS Distributions 
1258bb611c8fSApple OSS Distributions 	return ret;
1259bb611c8fSApple OSS Distributions }
1260bb611c8fSApple OSS Distributions 
1261bb611c8fSApple OSS Distributions 
1262bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1263bb611c8fSApple OSS Distributions 
1264bb611c8fSApple OSS Distributions static kern_return_t
OSActionCreateWithTypeNameInternal(OSObject * target,uint64_t targetmsgid,uint64_t msgid,size_t referenceSize,OSString * typeName,bool fromKernel,OSAction ** action)1265bb611c8fSApple OSS Distributions OSActionCreateWithTypeNameInternal(OSObject * target, uint64_t targetmsgid, uint64_t msgid, size_t referenceSize, OSString * typeName, bool fromKernel, OSAction ** action)
1266bb611c8fSApple OSS Distributions {
1267bb611c8fSApple OSS Distributions 	OSAction * inst = NULL;
1268e6231be0SApple OSS Distributions 	void * reference = NULL; // must release
1269bb611c8fSApple OSS Distributions 	const OSSymbol *sym = NULL; // must release
1270bb611c8fSApple OSS Distributions 	OSObject *obj = NULL; // must release
1271bb611c8fSApple OSS Distributions 	const OSMetaClass *actionMetaClass = NULL; // do not release
1272bb611c8fSApple OSS Distributions 	kern_return_t ret;
1273bb611c8fSApple OSS Distributions 
1274bb611c8fSApple OSS Distributions 	if (fromKernel && typeName) {
1275bb611c8fSApple OSS Distributions 		/* The action is being constructed in the kernel with a type name */
1276bb611c8fSApple OSS Distributions 		sym = OSSymbol::withString(typeName);
1277bb611c8fSApple OSS Distributions 		actionMetaClass = OSMetaClass::getMetaClassWithName(sym);
1278bb611c8fSApple OSS Distributions 		if (actionMetaClass && actionMetaClass->getSuperClass() == OSTypeID(OSAction)) {
1279bb611c8fSApple OSS Distributions 			obj = actionMetaClass->alloc();
1280bb611c8fSApple OSS Distributions 			if (!obj) {
1281bb611c8fSApple OSS Distributions 				ret = kIOReturnNoMemory;
1282bb611c8fSApple OSS Distributions 				goto finish;
1283bb611c8fSApple OSS Distributions 			}
1284bb611c8fSApple OSS Distributions 			inst = OSDynamicCast(OSAction, obj);
1285bb611c8fSApple OSS Distributions 			obj = NULL; // prevent release
1286bb611c8fSApple OSS Distributions 			assert(inst); // obj is a subclass of OSAction so the dynamic cast should always work
1287bb611c8fSApple OSS Distributions 		} else {
1288bb611c8fSApple OSS Distributions 			DKLOG("Attempted to create action object with type \"%s\" which does not inherit from OSAction\n", typeName->getCStringNoCopy());
1289bb611c8fSApple OSS Distributions 			ret = kIOReturnBadArgument;
1290bb611c8fSApple OSS Distributions 			goto finish;
1291bb611c8fSApple OSS Distributions 		}
1292bb611c8fSApple OSS Distributions 	} else {
1293bb611c8fSApple OSS Distributions 		inst = OSTypeAlloc(OSAction);
1294bb611c8fSApple OSS Distributions 		if (!inst) {
1295bb611c8fSApple OSS Distributions 			ret = kIOReturnNoMemory;
1296bb611c8fSApple OSS Distributions 			goto finish;
1297bb611c8fSApple OSS Distributions 		}
1298bb611c8fSApple OSS Distributions 	}
1299bb611c8fSApple OSS Distributions 
1300e6231be0SApple OSS Distributions 	if (referenceSize != 0) {
1301e6231be0SApple OSS Distributions 		reference = IONewZeroData(uint8_t, referenceSize);
1302e6231be0SApple OSS Distributions 		if (reference == NULL) {
1303e6231be0SApple OSS Distributions 			ret = kIOReturnNoMemory;
1304e6231be0SApple OSS Distributions 			goto finish;
1305e6231be0SApple OSS Distributions 		}
1306e6231be0SApple OSS Distributions 	}
1307e6231be0SApple OSS Distributions 
1308e6231be0SApple OSS Distributions 	inst->ivars = IONewZero(OSAction_IVars, 1);
1309a5e72196SApple OSS Distributions 	if (!inst->ivars) {
1310bb611c8fSApple OSS Distributions 		ret = kIOReturnNoMemory;
1311bb611c8fSApple OSS Distributions 		goto finish;
1312a5e72196SApple OSS Distributions 	}
1313e6231be0SApple OSS Distributions 	if (target) {
1314a5e72196SApple OSS Distributions 		target->retain();
1315e6231be0SApple OSS Distributions 		if (!fromKernel && !OSDynamicCast(IOService, target)) {
1316e6231be0SApple OSS Distributions 			IOUserServer * us;
1317e6231be0SApple OSS Distributions 			us = (typeof(us))thread_iokit_tls_get(0);
1318e6231be0SApple OSS Distributions 			inst->ivars->userServer = OSDynamicCast(IOUserServer, us);
1319e6231be0SApple OSS Distributions 			assert(inst->ivars->userServer);
1320e6231be0SApple OSS Distributions 			inst->ivars->userServer->retain();
1321e6231be0SApple OSS Distributions 		}
1322e6231be0SApple OSS Distributions 	}
1323a5e72196SApple OSS Distributions 	inst->ivars->target        = target;
1324a5e72196SApple OSS Distributions 	inst->ivars->targetmsgid   = targetmsgid;
1325a5e72196SApple OSS Distributions 	inst->ivars->msgid         = msgid;
1326e6231be0SApple OSS Distributions 
1327e6231be0SApple OSS Distributions 	inst->ivars->reference     = reference;
1328a5e72196SApple OSS Distributions 	inst->ivars->referenceSize = referenceSize;
1329e6231be0SApple OSS Distributions 	reference = NULL; // prevent release
1330e6231be0SApple OSS Distributions 
1331bb611c8fSApple OSS Distributions 	if (typeName) {
1332bb611c8fSApple OSS Distributions 		typeName->retain();
1333bb611c8fSApple OSS Distributions 	}
1334bb611c8fSApple OSS Distributions 	inst->ivars->typeName      = typeName;
1335a5e72196SApple OSS Distributions 
1336a5e72196SApple OSS Distributions 	*action = inst;
1337bb611c8fSApple OSS Distributions 	inst = NULL; // prevent release
1338bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
1339a5e72196SApple OSS Distributions 
1340bb611c8fSApple OSS Distributions finish:
1341bb611c8fSApple OSS Distributions 	OSSafeReleaseNULL(obj);
1342bb611c8fSApple OSS Distributions 	OSSafeReleaseNULL(sym);
1343bb611c8fSApple OSS Distributions 	OSSafeReleaseNULL(inst);
1344e6231be0SApple OSS Distributions 	if (reference) {
1345e6231be0SApple OSS Distributions 		IODeleteData(reference, uint8_t, referenceSize);
1346e6231be0SApple OSS Distributions 	}
1347bb611c8fSApple OSS Distributions 
1348bb611c8fSApple OSS Distributions 	return ret;
1349bb611c8fSApple OSS Distributions }
1350bb611c8fSApple OSS Distributions 
1351bb611c8fSApple OSS Distributions kern_return_t
Create(OSAction_Create_Args)1352bb611c8fSApple OSS Distributions OSAction::Create(OSAction_Create_Args)
1353bb611c8fSApple OSS Distributions {
1354bb611c8fSApple OSS Distributions 	return OSAction::CreateWithTypeName(target, targetmsgid, msgid, referenceSize, NULL, action);
1355bb611c8fSApple OSS Distributions }
1356bb611c8fSApple OSS Distributions 
1357bb611c8fSApple OSS Distributions kern_return_t
CreateWithTypeName(OSAction_CreateWithTypeName_Args)1358bb611c8fSApple OSS Distributions OSAction::CreateWithTypeName(OSAction_CreateWithTypeName_Args)
1359bb611c8fSApple OSS Distributions {
1360bb611c8fSApple OSS Distributions 	return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, true, action);
1361bb611c8fSApple OSS Distributions }
1362bb611c8fSApple OSS Distributions 
1363bb611c8fSApple OSS Distributions kern_return_t
Create_Impl(OSObject * target,uint64_t targetmsgid,uint64_t msgid,size_t referenceSize,OSAction ** action)1364bb611c8fSApple OSS Distributions OSAction::Create_Impl(
1365bb611c8fSApple OSS Distributions 	OSObject * target,
1366bb611c8fSApple OSS Distributions 	uint64_t targetmsgid,
1367bb611c8fSApple OSS Distributions 	uint64_t msgid,
1368bb611c8fSApple OSS Distributions 	size_t referenceSize,
1369bb611c8fSApple OSS Distributions 	OSAction ** action)
1370bb611c8fSApple OSS Distributions {
1371bb611c8fSApple OSS Distributions 	return OSAction::CreateWithTypeName_Impl(target, targetmsgid, msgid, referenceSize, NULL, action);
1372bb611c8fSApple OSS Distributions }
1373bb611c8fSApple OSS Distributions 
1374bb611c8fSApple OSS Distributions kern_return_t
CreateWithTypeName_Impl(OSObject * target,uint64_t targetmsgid,uint64_t msgid,size_t referenceSize,OSString * typeName,OSAction ** action)1375bb611c8fSApple OSS Distributions OSAction::CreateWithTypeName_Impl(
1376bb611c8fSApple OSS Distributions 	OSObject * target,
1377bb611c8fSApple OSS Distributions 	uint64_t targetmsgid,
1378bb611c8fSApple OSS Distributions 	uint64_t msgid,
1379bb611c8fSApple OSS Distributions 	size_t referenceSize,
1380bb611c8fSApple OSS Distributions 	OSString * typeName,
1381bb611c8fSApple OSS Distributions 	OSAction ** action)
1382bb611c8fSApple OSS Distributions {
1383bb611c8fSApple OSS Distributions 	return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, false, action);
1384a5e72196SApple OSS Distributions }
1385a5e72196SApple OSS Distributions 
1386a5e72196SApple OSS Distributions void
free()1387a5e72196SApple OSS Distributions OSAction::free()
1388a5e72196SApple OSS Distributions {
1389a5e72196SApple OSS Distributions 	if (ivars) {
1390a5e72196SApple OSS Distributions 		if (ivars->abortedHandler) {
1391a5e72196SApple OSS Distributions 			Block_release(ivars->abortedHandler);
1392a5e72196SApple OSS Distributions 			ivars->abortedHandler = NULL;
1393a5e72196SApple OSS Distributions 		}
1394a5e72196SApple OSS Distributions 		OSSafeReleaseNULL(ivars->target);
1395bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(ivars->typeName);
1396e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(ivars->userServer);
1397e6231be0SApple OSS Distributions 		if (ivars->reference) {
1398e6231be0SApple OSS Distributions 			assert(ivars->referenceSize > 0);
1399e6231be0SApple OSS Distributions 			IODeleteData(ivars->reference, uint8_t, ivars->referenceSize);
1400e6231be0SApple OSS Distributions 		}
1401e6231be0SApple OSS Distributions 		IOSafeDeleteNULL(ivars, OSAction_IVars, 1);
1402a5e72196SApple OSS Distributions 	}
1403a5e72196SApple OSS Distributions 	return super::free();
1404a5e72196SApple OSS Distributions }
1405a5e72196SApple OSS Distributions 
1406a5e72196SApple OSS Distributions void *
GetReference()1407a5e72196SApple OSS Distributions OSAction::GetReference()
1408a5e72196SApple OSS Distributions {
1409e6231be0SApple OSS Distributions 	assert(ivars && ivars->referenceSize && ivars->reference);
1410e6231be0SApple OSS Distributions 	return ivars->reference;
1411a5e72196SApple OSS Distributions }
1412a5e72196SApple OSS Distributions 
1413a5e72196SApple OSS Distributions kern_return_t
SetAbortedHandler(OSActionAbortedHandler handler)1414a5e72196SApple OSS Distributions OSAction::SetAbortedHandler(OSActionAbortedHandler handler)
1415a5e72196SApple OSS Distributions {
1416a5e72196SApple OSS Distributions 	ivars->abortedHandler = Block_copy(handler);
1417a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
1418a5e72196SApple OSS Distributions }
1419a5e72196SApple OSS Distributions 
1420a5e72196SApple OSS Distributions void
Aborted_Impl(void)1421a5e72196SApple OSS Distributions OSAction::Aborted_Impl(void)
1422a5e72196SApple OSS Distributions {
14235c2921b0SApple OSS Distributions 	if (!os_atomic_cmpxchg(&ivars->aborted, false, true, relaxed)) {
14245c2921b0SApple OSS Distributions 		// already aborted
14255c2921b0SApple OSS Distributions 		return;
14265c2921b0SApple OSS Distributions 	}
1427a5e72196SApple OSS Distributions 	if (ivars->abortedHandler) {
1428a5e72196SApple OSS Distributions 		ivars->abortedHandler();
1429a5e72196SApple OSS Distributions 	}
1430a5e72196SApple OSS Distributions }
1431a5e72196SApple OSS Distributions 
1432bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1433a5e72196SApple OSS Distributions 
1434a5e72196SApple OSS Distributions struct IODispatchSource_IVars {
1435a5e72196SApple OSS Distributions 	queue_chain_t           link;
1436a5e72196SApple OSS Distributions 	IODispatchSource      * source;
1437a5e72196SApple OSS Distributions 	IOUserServer          * server;
1438a5e72196SApple OSS Distributions 	IODispatchQueue_IVars * queue;
1439a5e72196SApple OSS Distributions 	bool                    enabled;
1440a5e72196SApple OSS Distributions };
1441a5e72196SApple OSS Distributions 
1442a5e72196SApple OSS Distributions bool
init()1443a5e72196SApple OSS Distributions IODispatchSource::init()
1444a5e72196SApple OSS Distributions {
1445a5e72196SApple OSS Distributions 	if (!super::init()) {
1446a5e72196SApple OSS Distributions 		return false;
1447a5e72196SApple OSS Distributions 	}
1448a5e72196SApple OSS Distributions 
1449e6231be0SApple OSS Distributions 	ivars = IOMallocType(IODispatchSource_IVars);
1450a5e72196SApple OSS Distributions 
1451a5e72196SApple OSS Distributions 	ivars->source = this;
1452a5e72196SApple OSS Distributions 
1453a5e72196SApple OSS Distributions 	return true;
1454a5e72196SApple OSS Distributions }
1455a5e72196SApple OSS Distributions 
1456a5e72196SApple OSS Distributions void
free()1457a5e72196SApple OSS Distributions IODispatchSource::free()
1458a5e72196SApple OSS Distributions {
1459e6231be0SApple OSS Distributions 	IOFreeType(ivars, IODispatchSource_IVars);
1460a5e72196SApple OSS Distributions 	super::free();
1461a5e72196SApple OSS Distributions }
1462a5e72196SApple OSS Distributions 
1463bb611c8fSApple OSS Distributions kern_return_t
SetEnable_Impl(bool enable)1464bb611c8fSApple OSS Distributions IODispatchSource::SetEnable_Impl(
1465bb611c8fSApple OSS Distributions 	bool enable)
1466bb611c8fSApple OSS Distributions {
1467bb611c8fSApple OSS Distributions 	return SetEnableWithCompletion(enable, NULL);
1468bb611c8fSApple OSS Distributions }
1469bb611c8fSApple OSS Distributions 
1470bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1471a5e72196SApple OSS Distributions 
1472a5e72196SApple OSS Distributions struct IOInterruptDispatchSource_IVars {
1473a5e72196SApple OSS Distributions 	IOService    * provider;
1474a5e72196SApple OSS Distributions 	uint32_t       intIndex;
1475e6231be0SApple OSS Distributions 	uint32_t       flags;
1476bb611c8fSApple OSS Distributions 	int            interruptType;
1477a5e72196SApple OSS Distributions 	IOSimpleLock * lock;
1478a5e72196SApple OSS Distributions 	thread_t       waiter;
1479a5e72196SApple OSS Distributions 	uint64_t       count;
1480a5e72196SApple OSS Distributions 	uint64_t       time;
1481a5e72196SApple OSS Distributions 	OSAction     * action;
1482a5e72196SApple OSS Distributions 	bool           enable;
14835c2921b0SApple OSS Distributions 	bool           canceled;
1484a5e72196SApple OSS Distributions };
1485a5e72196SApple OSS Distributions 
1486a5e72196SApple OSS Distributions static void
IOInterruptDispatchSourceInterrupt(OSObject * target,void * refCon,IOService * nub,int source)1487a5e72196SApple OSS Distributions IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon,
1488a5e72196SApple OSS Distributions     IOService * nub, int source )
1489a5e72196SApple OSS Distributions {
1490a5e72196SApple OSS Distributions 	IOInterruptDispatchSource_IVars * ivars = (typeof(ivars))refCon;
1491a5e72196SApple OSS Distributions 	IOInterruptState is;
1492a5e72196SApple OSS Distributions 
1493a5e72196SApple OSS Distributions 	is = IOSimpleLockLockDisableInterrupt(ivars->lock);
1494a5e72196SApple OSS Distributions 	ivars->count++;
1495e6231be0SApple OSS Distributions 	ivars->time = (kIOInterruptSourceContinuousTime & ivars->flags)
1496e6231be0SApple OSS Distributions 	    ? mach_continuous_time() : mach_absolute_time();
1497a5e72196SApple OSS Distributions 	if (ivars->waiter) {
1498a5e72196SApple OSS Distributions 		thread_wakeup_thread((event_t) ivars, ivars->waiter);
1499a5e72196SApple OSS Distributions 		ivars->waiter = NULL;
1500a5e72196SApple OSS Distributions 	}
1501bb611c8fSApple OSS Distributions 	if (kIOInterruptTypeLevel & ivars->interruptType) {
1502bb611c8fSApple OSS Distributions 		ivars->provider->disableInterrupt(ivars->intIndex);
1503bb611c8fSApple OSS Distributions 	}
1504a5e72196SApple OSS Distributions 	IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
1505a5e72196SApple OSS Distributions }
1506a5e72196SApple OSS Distributions 
1507a5e72196SApple OSS Distributions kern_return_t
Create_Impl(IOService * provider,uint32_t indexAndFlags,IODispatchQueue * queue,IOInterruptDispatchSource ** source)1508bb611c8fSApple OSS Distributions IOInterruptDispatchSource::Create_Impl(
1509bb611c8fSApple OSS Distributions 	IOService * provider,
1510e6231be0SApple OSS Distributions 	uint32_t indexAndFlags,
1511bb611c8fSApple OSS Distributions 	IODispatchQueue * queue,
1512bb611c8fSApple OSS Distributions 	IOInterruptDispatchSource ** source)
1513a5e72196SApple OSS Distributions {
1514a5e72196SApple OSS Distributions 	IOReturn ret;
1515a5e72196SApple OSS Distributions 	IOInterruptDispatchSource * inst;
1516e6231be0SApple OSS Distributions 	uint32_t index;
1517e6231be0SApple OSS Distributions 	uint32_t flags;
1518e6231be0SApple OSS Distributions 
1519e6231be0SApple OSS Distributions 	index = indexAndFlags & kIOInterruptSourceIndexMask;
1520e6231be0SApple OSS Distributions 	flags = indexAndFlags & ~kIOInterruptSourceIndexMask;
1521a5e72196SApple OSS Distributions 
1522a5e72196SApple OSS Distributions 	inst = OSTypeAlloc(IOInterruptDispatchSource);
1523a5e72196SApple OSS Distributions 	if (!inst->init()) {
1524a5e72196SApple OSS Distributions 		inst->free();
1525a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
1526a5e72196SApple OSS Distributions 	}
1527a5e72196SApple OSS Distributions 
1528a5e72196SApple OSS Distributions 	inst->ivars->lock = IOSimpleLockAlloc();
1529a5e72196SApple OSS Distributions 
1530bb611c8fSApple OSS Distributions 	ret = provider->getInterruptType(index, &inst->ivars->interruptType);
1531bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess != ret) {
1532bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(inst);
1533bb611c8fSApple OSS Distributions 		return ret;
1534bb611c8fSApple OSS Distributions 	}
1535a5e72196SApple OSS Distributions 	ret = provider->registerInterrupt(index, inst, IOInterruptDispatchSourceInterrupt, inst->ivars);
1536a5e72196SApple OSS Distributions 	if (kIOReturnSuccess == ret) {
1537a5e72196SApple OSS Distributions 		inst->ivars->intIndex = index;
1538e6231be0SApple OSS Distributions 		inst->ivars->flags    = flags;
1539a5e72196SApple OSS Distributions 		inst->ivars->provider = provider;
1540bb611c8fSApple OSS Distributions 		inst->ivars->provider->retain();
1541a5e72196SApple OSS Distributions 		*source = inst;
1542a5e72196SApple OSS Distributions 	}
1543a5e72196SApple OSS Distributions 	return ret;
1544a5e72196SApple OSS Distributions }
1545a5e72196SApple OSS Distributions 
1546bb611c8fSApple OSS Distributions kern_return_t
GetInterruptType_Impl(IOService * provider,uint32_t index,uint64_t * interruptType)1547bb611c8fSApple OSS Distributions IOInterruptDispatchSource::GetInterruptType_Impl(
1548bb611c8fSApple OSS Distributions 	IOService * provider,
1549bb611c8fSApple OSS Distributions 	uint32_t index,
1550bb611c8fSApple OSS Distributions 	uint64_t * interruptType)
1551bb611c8fSApple OSS Distributions {
1552bb611c8fSApple OSS Distributions 	IOReturn ret;
1553bb611c8fSApple OSS Distributions 	int      type;
1554bb611c8fSApple OSS Distributions 
1555bb611c8fSApple OSS Distributions 	*interruptType = 0;
1556bb611c8fSApple OSS Distributions 	ret = provider->getInterruptType(index, &type);
1557bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess == ret) {
1558bb611c8fSApple OSS Distributions 		*interruptType = type;
1559bb611c8fSApple OSS Distributions 	}
1560bb611c8fSApple OSS Distributions 
1561bb611c8fSApple OSS Distributions 	return ret;
1562bb611c8fSApple OSS Distributions }
1563bb611c8fSApple OSS Distributions 
1564a5e72196SApple OSS Distributions bool
init()1565a5e72196SApple OSS Distributions IOInterruptDispatchSource::init()
1566a5e72196SApple OSS Distributions {
1567a5e72196SApple OSS Distributions 	if (!super::init()) {
1568a5e72196SApple OSS Distributions 		return false;
1569a5e72196SApple OSS Distributions 	}
1570e6231be0SApple OSS Distributions 	ivars = IOMallocType(IOInterruptDispatchSource_IVars);
1571a5e72196SApple OSS Distributions 
1572a5e72196SApple OSS Distributions 	return true;
1573a5e72196SApple OSS Distributions }
1574a5e72196SApple OSS Distributions 
1575a5e72196SApple OSS Distributions void
free()1576a5e72196SApple OSS Distributions IOInterruptDispatchSource::free()
1577a5e72196SApple OSS Distributions {
1578a5e72196SApple OSS Distributions 	if (ivars && ivars->provider) {
15798d741a5dSApple OSS Distributions 		(void) ivars->provider->unregisterInterrupt(ivars->intIndex);
1580bb611c8fSApple OSS Distributions 		ivars->provider->release();
1581bb611c8fSApple OSS Distributions 	}
1582bb611c8fSApple OSS Distributions 
1583bb611c8fSApple OSS Distributions 	if (ivars && ivars->lock) {
1584bb611c8fSApple OSS Distributions 		IOSimpleLockFree(ivars->lock);
1585a5e72196SApple OSS Distributions 	}
1586a5e72196SApple OSS Distributions 
1587e6231be0SApple OSS Distributions 	IOFreeType(ivars, IOInterruptDispatchSource_IVars);
1588a5e72196SApple OSS Distributions 
1589a5e72196SApple OSS Distributions 	super::free();
1590a5e72196SApple OSS Distributions }
1591a5e72196SApple OSS Distributions 
1592a5e72196SApple OSS Distributions kern_return_t
SetHandler_Impl(OSAction * action)1593bb611c8fSApple OSS Distributions IOInterruptDispatchSource::SetHandler_Impl(
1594bb611c8fSApple OSS Distributions 	OSAction * action)
1595a5e72196SApple OSS Distributions {
1596a5e72196SApple OSS Distributions 	IOReturn ret;
1597a5e72196SApple OSS Distributions 	OSAction * oldAction;
1598a5e72196SApple OSS Distributions 
1599a5e72196SApple OSS Distributions 	oldAction = (typeof(oldAction))ivars->action;
1600a5e72196SApple OSS Distributions 	if (oldAction && OSCompareAndSwapPtr(oldAction, NULL, &ivars->action)) {
1601a5e72196SApple OSS Distributions 		oldAction->release();
1602a5e72196SApple OSS Distributions 	}
1603a5e72196SApple OSS Distributions 	action->retain();
1604a5e72196SApple OSS Distributions 	ivars->action = action;
1605a5e72196SApple OSS Distributions 
1606a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
1607a5e72196SApple OSS Distributions 
1608a5e72196SApple OSS Distributions 	return ret;
1609a5e72196SApple OSS Distributions }
1610a5e72196SApple OSS Distributions 
1611a5e72196SApple OSS Distributions kern_return_t
SetEnableWithCompletion_Impl(bool enable,IODispatchSourceCancelHandler handler)1612bb611c8fSApple OSS Distributions IOInterruptDispatchSource::SetEnableWithCompletion_Impl(
1613bb611c8fSApple OSS Distributions 	bool enable,
1614bb611c8fSApple OSS Distributions 	IODispatchSourceCancelHandler handler)
1615a5e72196SApple OSS Distributions {
1616a5e72196SApple OSS Distributions 	IOReturn ret;
1617a5e72196SApple OSS Distributions 	IOInterruptState is;
1618a5e72196SApple OSS Distributions 
1619a5e72196SApple OSS Distributions 	if (enable == ivars->enable) {
1620a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
1621a5e72196SApple OSS Distributions 	}
1622a5e72196SApple OSS Distributions 
1623*4f1223e8SApple OSS Distributions 	if (ivars->canceled) {
1624*4f1223e8SApple OSS Distributions 		return kIOReturnUnsupported;
1625*4f1223e8SApple OSS Distributions 	}
1626*4f1223e8SApple OSS Distributions 	assert(ivars->provider != NULL);
1627*4f1223e8SApple OSS Distributions 
1628a5e72196SApple OSS Distributions 	if (enable) {
1629a5e72196SApple OSS Distributions 		is = IOSimpleLockLockDisableInterrupt(ivars->lock);
1630a5e72196SApple OSS Distributions 		ivars->enable = enable;
1631a5e72196SApple OSS Distributions 		IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
1632a5e72196SApple OSS Distributions 		ret = ivars->provider->enableInterrupt(ivars->intIndex);
1633a5e72196SApple OSS Distributions 	} else {
1634a5e72196SApple OSS Distributions 		ret = ivars->provider->disableInterrupt(ivars->intIndex);
1635a5e72196SApple OSS Distributions 		is = IOSimpleLockLockDisableInterrupt(ivars->lock);
1636a5e72196SApple OSS Distributions 		ivars->enable = enable;
1637a5e72196SApple OSS Distributions 		IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
1638a5e72196SApple OSS Distributions 	}
1639a5e72196SApple OSS Distributions 
1640a5e72196SApple OSS Distributions 	return ret;
1641a5e72196SApple OSS Distributions }
1642a5e72196SApple OSS Distributions 
1643a5e72196SApple OSS Distributions kern_return_t
Cancel_Impl(IODispatchSourceCancelHandler handler)1644bb611c8fSApple OSS Distributions IOInterruptDispatchSource::Cancel_Impl(
1645bb611c8fSApple OSS Distributions 	IODispatchSourceCancelHandler handler)
1646a5e72196SApple OSS Distributions {
16475c2921b0SApple OSS Distributions 	IOInterruptState is;
16488d741a5dSApple OSS Distributions 	IOService * provider;
16495c2921b0SApple OSS Distributions 
16505c2921b0SApple OSS Distributions 	is = IOSimpleLockLockDisableInterrupt(ivars->lock);
16515c2921b0SApple OSS Distributions 	ivars->canceled = true;
16525c2921b0SApple OSS Distributions 	if (ivars->waiter) {
16535c2921b0SApple OSS Distributions 		thread_wakeup_thread((event_t) ivars, ivars->waiter);
16545c2921b0SApple OSS Distributions 		ivars->waiter = NULL;
16555c2921b0SApple OSS Distributions 	}
16568d741a5dSApple OSS Distributions 	provider = ivars->provider;
16578d741a5dSApple OSS Distributions 	if (provider) {
16588d741a5dSApple OSS Distributions 		ivars->provider = NULL;
16598d741a5dSApple OSS Distributions 	}
16605c2921b0SApple OSS Distributions 	IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
16615c2921b0SApple OSS Distributions 
16628d741a5dSApple OSS Distributions 	if (provider) {
16638d741a5dSApple OSS Distributions 		(void) provider->unregisterInterrupt(ivars->intIndex);
16648d741a5dSApple OSS Distributions 		provider->release();
16658d741a5dSApple OSS Distributions 	}
16668d741a5dSApple OSS Distributions 
16675c2921b0SApple OSS Distributions 	return kIOReturnSuccess;
1668a5e72196SApple OSS Distributions }
1669a5e72196SApple OSS Distributions 
1670a5e72196SApple OSS Distributions kern_return_t
CheckForWork_Impl(const IORPC rpc,bool synchronous)1671bb611c8fSApple OSS Distributions IOInterruptDispatchSource::CheckForWork_Impl(
1672bb611c8fSApple OSS Distributions 	const IORPC rpc,
1673bb611c8fSApple OSS Distributions 	bool synchronous)
1674a5e72196SApple OSS Distributions {
1675a5e72196SApple OSS Distributions 	IOReturn         ret = kIOReturnNotReady;
1676a5e72196SApple OSS Distributions 	IOInterruptState is;
1677bb611c8fSApple OSS Distributions 	bool             willWait;
16785c2921b0SApple OSS Distributions 	bool             canceled;
1679a5e72196SApple OSS Distributions 	wait_result_t    waitResult;
1680a5e72196SApple OSS Distributions 	uint64_t         icount;
1681a5e72196SApple OSS Distributions 	uint64_t         itime;
1682a5e72196SApple OSS Distributions 	thread_t         self;
1683a5e72196SApple OSS Distributions 
1684a5e72196SApple OSS Distributions 	self = current_thread();
1685a5e72196SApple OSS Distributions 	icount = 0;
1686a5e72196SApple OSS Distributions 	do {
16875c2921b0SApple OSS Distributions 		willWait = false;
1688a5e72196SApple OSS Distributions 		is = IOSimpleLockLockDisableInterrupt(ivars->lock);
16895c2921b0SApple OSS Distributions 		canceled = ivars->canceled;
16905c2921b0SApple OSS Distributions 		if (!canceled) {
1691a5e72196SApple OSS Distributions 			if ((icount = ivars->count)) {
1692a5e72196SApple OSS Distributions 				itime = ivars->time;
1693a5e72196SApple OSS Distributions 				ivars->count = 0;
1694a5e72196SApple OSS Distributions 				waitResult = THREAD_AWAKENED;
1695a5e72196SApple OSS Distributions 			} else if (synchronous) {
1696a5e72196SApple OSS Distributions 				assert(NULL == ivars->waiter);
1697a5e72196SApple OSS Distributions 				ivars->waiter = self;
1698a5e72196SApple OSS Distributions 				waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
1699a5e72196SApple OSS Distributions 			}
1700bb611c8fSApple OSS Distributions 			willWait = (synchronous && (waitResult == THREAD_WAITING));
1701bb611c8fSApple OSS Distributions 			if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
1702a5e72196SApple OSS Distributions 				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
1703e7776783SApple OSS Distributions 				ivars->provider->enableInterrupt(ivars->intIndex);
1704e7776783SApple OSS Distributions 			} else {
1705e7776783SApple OSS Distributions 				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
1706e7776783SApple OSS Distributions 			}
17075c2921b0SApple OSS Distributions 		} else {
17085c2921b0SApple OSS Distributions 			IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
17095c2921b0SApple OSS Distributions 		}
1710bb611c8fSApple OSS Distributions 		if (willWait) {
1711a5e72196SApple OSS Distributions 			waitResult = thread_block(THREAD_CONTINUE_NULL);
1712a5e72196SApple OSS Distributions 			if (THREAD_INTERRUPTED == waitResult) {
1713bb611c8fSApple OSS Distributions 				is = IOSimpleLockLockDisableInterrupt(ivars->lock);
1714bb611c8fSApple OSS Distributions 				ivars->waiter = NULL;
1715bb611c8fSApple OSS Distributions 				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
17165c2921b0SApple OSS Distributions 				canceled = true;
1717a5e72196SApple OSS Distributions 				break;
1718a5e72196SApple OSS Distributions 			}
1719a5e72196SApple OSS Distributions 		}
17205c2921b0SApple OSS Distributions 	} while (synchronous && !icount && !canceled);
1721a5e72196SApple OSS Distributions 
1722a5e72196SApple OSS Distributions 	if (icount && ivars->action) {
1723a5e72196SApple OSS Distributions 		ret = InterruptOccurred(rpc, ivars->action, icount, itime);
1724a5e72196SApple OSS Distributions 	}
1725a5e72196SApple OSS Distributions 
1726a5e72196SApple OSS Distributions 	return ret;
1727a5e72196SApple OSS Distributions }
1728a5e72196SApple OSS Distributions 
1729a5e72196SApple OSS Distributions void
InterruptOccurred_Impl(OSAction * action,uint64_t count,uint64_t time)1730bb611c8fSApple OSS Distributions IOInterruptDispatchSource::InterruptOccurred_Impl(
1731bb611c8fSApple OSS Distributions 	OSAction * action,
1732bb611c8fSApple OSS Distributions 	uint64_t count,
1733bb611c8fSApple OSS Distributions 	uint64_t time)
1734a5e72196SApple OSS Distributions {
1735a5e72196SApple OSS Distributions }
1736a5e72196SApple OSS Distributions 
17375c2921b0SApple OSS Distributions kern_return_t
GetLastInterrupt_Impl(uint64_t * pCount,uint64_t * pTime)17385c2921b0SApple OSS Distributions IOInterruptDispatchSource::GetLastInterrupt_Impl(
17395c2921b0SApple OSS Distributions 	uint64_t  * pCount,
17405c2921b0SApple OSS Distributions 	uint64_t  * pTime)
17415c2921b0SApple OSS Distributions {
17425c2921b0SApple OSS Distributions 	IOInterruptState is;
17435c2921b0SApple OSS Distributions 	uint64_t count, time;
17445c2921b0SApple OSS Distributions 
17455c2921b0SApple OSS Distributions 	is = IOSimpleLockLockDisableInterrupt(ivars->lock);
17465c2921b0SApple OSS Distributions 	count = ivars->count;
17475c2921b0SApple OSS Distributions 	time  = ivars->time;
17485c2921b0SApple OSS Distributions 	IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
17495c2921b0SApple OSS Distributions 
17505c2921b0SApple OSS Distributions 	if (pCount) {
17515c2921b0SApple OSS Distributions 		*pCount = count;
17525c2921b0SApple OSS Distributions 	}
17535c2921b0SApple OSS Distributions 	if (pTime) {
17545c2921b0SApple OSS Distributions 		*pTime = time;
17555c2921b0SApple OSS Distributions 	}
17565c2921b0SApple OSS Distributions 	return kIOReturnSuccess;
17575c2921b0SApple OSS Distributions }
17585c2921b0SApple OSS Distributions 
1759bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1760bb611c8fSApple OSS Distributions 
1761bb611c8fSApple OSS Distributions enum {
1762bb611c8fSApple OSS Distributions 	kIOServiceNotificationTypeCount = kIOServiceNotificationTypeLast + 1,
1763bb611c8fSApple OSS Distributions };
1764bb611c8fSApple OSS Distributions 
1765bb611c8fSApple OSS Distributions struct IOServiceNotificationDispatchSource_IVars {
1766bb611c8fSApple OSS Distributions 	OSObject     * serverName;
1767bb611c8fSApple OSS Distributions 	OSAction     * action;
1768bb611c8fSApple OSS Distributions 	IOLock       * lock;
1769bb611c8fSApple OSS Distributions 	IONotifier   * notifier;
1770bb611c8fSApple OSS Distributions 	OSDictionary * interestNotifiers;
17715c2921b0SApple OSS Distributions 	OSBoundedArray<OSArray *, kIOServiceNotificationTypeCount> pending;
1772bb611c8fSApple OSS Distributions 	bool           enable;
1773bb611c8fSApple OSS Distributions };
1774bb611c8fSApple OSS Distributions 
1775bb611c8fSApple OSS Distributions kern_return_t
Create_Impl(OSDictionary * matching,uint64_t options,IODispatchQueue * queue,IOServiceNotificationDispatchSource ** notification)1776bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::Create_Impl(
1777bb611c8fSApple OSS Distributions 	OSDictionary * matching,
1778bb611c8fSApple OSS Distributions 	uint64_t options,
1779bb611c8fSApple OSS Distributions 	IODispatchQueue * queue,
1780bb611c8fSApple OSS Distributions 	IOServiceNotificationDispatchSource ** notification)
1781bb611c8fSApple OSS Distributions {
1782bb611c8fSApple OSS Distributions 	IOUserServer * us;
1783bb611c8fSApple OSS Distributions 	IOReturn       ret;
1784bb611c8fSApple OSS Distributions 	IOServiceNotificationDispatchSource * inst;
1785bb611c8fSApple OSS Distributions 
1786bb611c8fSApple OSS Distributions 	inst = OSTypeAlloc(IOServiceNotificationDispatchSource);
1787bb611c8fSApple OSS Distributions 	if (!inst->init()) {
1788bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(inst);
1789bb611c8fSApple OSS Distributions 		return kIOReturnNoMemory;
1790bb611c8fSApple OSS Distributions 	}
1791bb611c8fSApple OSS Distributions 
1792bb611c8fSApple OSS Distributions 	us = (typeof(us))thread_iokit_tls_get(0);
1793bb611c8fSApple OSS Distributions 	assert(OSDynamicCast(IOUserServer, us));
1794bb611c8fSApple OSS Distributions 	if (!us) {
1795bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(inst);
1796bb611c8fSApple OSS Distributions 		return kIOReturnError;
1797bb611c8fSApple OSS Distributions 	}
1798bb611c8fSApple OSS Distributions 	inst->ivars->serverName = us->copyProperty(gIOUserServerNameKey);
1799bb611c8fSApple OSS Distributions 	if (!inst->ivars->serverName) {
1800bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(inst);
1801bb611c8fSApple OSS Distributions 		return kIOReturnNoMemory;
1802bb611c8fSApple OSS Distributions 	}
1803bb611c8fSApple OSS Distributions 
1804bb611c8fSApple OSS Distributions 	inst->ivars->lock    = IOLockAlloc();
1805bb611c8fSApple OSS Distributions 	if (!inst->ivars->lock) {
1806bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(inst);
1807bb611c8fSApple OSS Distributions 		return kIOReturnNoMemory;
1808bb611c8fSApple OSS Distributions 	}
1809bb611c8fSApple OSS Distributions 	for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
1810bb611c8fSApple OSS Distributions 		inst->ivars->pending[idx] = OSArray::withCapacity(4);
1811bb611c8fSApple OSS Distributions 		if (!inst->ivars->pending[idx]) {
1812bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(inst);
1813bb611c8fSApple OSS Distributions 			return kIOReturnNoMemory;
1814bb611c8fSApple OSS Distributions 		}
1815bb611c8fSApple OSS Distributions 	}
1816bb611c8fSApple OSS Distributions 	inst->ivars->interestNotifiers = OSDictionary::withCapacity(4);
1817bb611c8fSApple OSS Distributions 	if (!inst->ivars->interestNotifiers) {
1818bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(inst);
1819bb611c8fSApple OSS Distributions 		return kIOReturnNoMemory;
1820bb611c8fSApple OSS Distributions 	}
1821bb611c8fSApple OSS Distributions 
1822bb611c8fSApple OSS Distributions 	inst->ivars->notifier = IOService::addMatchingNotification(gIOMatchedNotification, matching, 0 /*priority*/,
1823bb611c8fSApple OSS Distributions 	    ^bool (IOService * newService, IONotifier * notifier) {
1824bb611c8fSApple OSS Distributions 		bool         notifyReady = false;
1825bb611c8fSApple OSS Distributions 		IONotifier * interest;
1826bb611c8fSApple OSS Distributions 		OSObject   * serverName;
1827bb611c8fSApple OSS Distributions 		bool         okToUse;
1828bb611c8fSApple OSS Distributions 
1829bb611c8fSApple OSS Distributions 		serverName = newService->copyProperty(gIOUserServerNameKey);
1830bb611c8fSApple OSS Distributions 		okToUse = (serverName && inst->ivars->serverName->isEqualTo(serverName));
1831bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(serverName);
1832bb611c8fSApple OSS Distributions 		if (!okToUse) {
18331031c584SApple OSS Distributions 		        OSObject * prop;
18341031c584SApple OSS Distributions 		        OSObject * str;
18351031c584SApple OSS Distributions 
18361031c584SApple OSS Distributions 		        if (!newService->reserved->uvars || !newService->reserved->uvars->userServer) {
1837bb611c8fSApple OSS Distributions 		                return false;
1838bb611c8fSApple OSS Distributions 			}
18391031c584SApple OSS Distributions 		        str = OSString::withCStringNoCopy(kIODriverKitAllowsPublishEntitlementsKey);
18401031c584SApple OSS Distributions 		        if (!str) {
18411031c584SApple OSS Distributions 		                return false;
18421031c584SApple OSS Distributions 			}
18431031c584SApple OSS Distributions 		        okToUse = newService->reserved->uvars->userServer->checkEntitlements(str, NULL, NULL);
18441031c584SApple OSS Distributions 		        if (!okToUse) {
18458d741a5dSApple OSS Distributions 		                if (kIODKLogSetup & gIODKDebug) {
18461031c584SApple OSS Distributions 		                        DKLOG(DKS ": publisher entitlements check failed\n", DKN(newService));
18478d741a5dSApple OSS Distributions 				}
18481031c584SApple OSS Distributions 		                return false;
18491031c584SApple OSS Distributions 			}
18501031c584SApple OSS Distributions 		        prop = newService->copyProperty(kIODriverKitPublishEntitlementsKey);
18511031c584SApple OSS Distributions 		        if (!prop) {
18521031c584SApple OSS Distributions 		                return false;
18531031c584SApple OSS Distributions 			}
18541031c584SApple OSS Distributions 		        okToUse = us->checkEntitlements(prop, NULL, NULL);
18551031c584SApple OSS Distributions 		        if (!okToUse) {
18568d741a5dSApple OSS Distributions 		                if (kIODKLogSetup & gIODKDebug) {
18571031c584SApple OSS Distributions 		                        DKLOG(DKS ": subscriber entitlements check failed\n", DKN(newService));
18588d741a5dSApple OSS Distributions 				}
18591031c584SApple OSS Distributions 		                return false;
18601031c584SApple OSS Distributions 			}
18611031c584SApple OSS Distributions 		}
1862bb611c8fSApple OSS Distributions 
1863bb611c8fSApple OSS Distributions 		IOLockLock(inst->ivars->lock);
1864bb611c8fSApple OSS Distributions 		notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeMatched]->getCount());
1865bb611c8fSApple OSS Distributions 		inst->ivars->pending[kIOServiceNotificationTypeMatched]->setObject(newService);
1866bb611c8fSApple OSS Distributions 		IOLockUnlock(inst->ivars->lock);
1867bb611c8fSApple OSS Distributions 
1868bb611c8fSApple OSS Distributions 		interest = newService->registerInterest(gIOGeneralInterest,
1869bb611c8fSApple OSS Distributions 		^IOReturn (uint32_t messageType, IOService * provider,
1870bb611c8fSApple OSS Distributions 		void * messageArgument, size_t argSize) {
1871bb611c8fSApple OSS Distributions 			IONotifier * interest;
1872bb611c8fSApple OSS Distributions 			bool         notifyReady = false;
1873bb611c8fSApple OSS Distributions 
1874bb611c8fSApple OSS Distributions 			switch (messageType) {
1875bb611c8fSApple OSS Distributions 			case kIOMessageServiceIsTerminated:
1876bb611c8fSApple OSS Distributions 				IOLockLock(inst->ivars->lock);
1877bb611c8fSApple OSS Distributions 				notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount());
1878bb611c8fSApple OSS Distributions 				inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider);
18795c2921b0SApple OSS Distributions 				if (inst->ivars->interestNotifiers != NULL) {
1880bb611c8fSApple OSS Distributions 				        interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService);
1881bb611c8fSApple OSS Distributions 				        assert(interest);
1882bb611c8fSApple OSS Distributions 				        interest->remove();
1883bb611c8fSApple OSS Distributions 				        inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService);
18845c2921b0SApple OSS Distributions 				}
1885bb611c8fSApple OSS Distributions 				IOLockUnlock(inst->ivars->lock);
1886bb611c8fSApple OSS Distributions 				break;
1887bb611c8fSApple OSS Distributions 			default:
1888bb611c8fSApple OSS Distributions 				break;
1889bb611c8fSApple OSS Distributions 			}
1890bb611c8fSApple OSS Distributions 			if (notifyReady && inst->ivars->action) {
1891bb611c8fSApple OSS Distributions 			        inst->ServiceNotificationReady(inst->ivars->action);
1892bb611c8fSApple OSS Distributions 			}
1893bb611c8fSApple OSS Distributions 			return kIOReturnSuccess;
1894bb611c8fSApple OSS Distributions 		});
1895bb611c8fSApple OSS Distributions 		if (interest) {
1896bb611c8fSApple OSS Distributions 		        IOLockLock(inst->ivars->lock);
1897bb611c8fSApple OSS Distributions 		        inst->ivars->interestNotifiers->setObject((const OSSymbol *) newService, interest);
1898bb611c8fSApple OSS Distributions 		        IOLockUnlock(inst->ivars->lock);
1899bb611c8fSApple OSS Distributions 		}
1900bb611c8fSApple OSS Distributions 		if (notifyReady) {
1901bb611c8fSApple OSS Distributions 		        if (inst->ivars->action) {
1902bb611c8fSApple OSS Distributions 		                inst->ServiceNotificationReady(inst->ivars->action);
1903bb611c8fSApple OSS Distributions 			}
1904bb611c8fSApple OSS Distributions 		}
1905bb611c8fSApple OSS Distributions 		return false;
1906bb611c8fSApple OSS Distributions 	});
1907bb611c8fSApple OSS Distributions 
1908bb611c8fSApple OSS Distributions 	if (!inst->ivars->notifier) {
1909bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(inst);
1910bb611c8fSApple OSS Distributions 		ret = kIOReturnError;
1911bb611c8fSApple OSS Distributions 	}
1912bb611c8fSApple OSS Distributions 
1913bb611c8fSApple OSS Distributions 	*notification = inst;
1914bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
1915bb611c8fSApple OSS Distributions 
1916bb611c8fSApple OSS Distributions 	return ret;
1917bb611c8fSApple OSS Distributions }
1918bb611c8fSApple OSS Distributions 
1919bb611c8fSApple OSS Distributions kern_return_t
CopyNextNotification_Impl(uint64_t * type,IOService ** service,uint64_t * options)1920bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::CopyNextNotification_Impl(
1921bb611c8fSApple OSS Distributions 	uint64_t * type,
1922bb611c8fSApple OSS Distributions 	IOService ** service,
1923bb611c8fSApple OSS Distributions 	uint64_t * options)
1924bb611c8fSApple OSS Distributions {
1925bb611c8fSApple OSS Distributions 	IOService * next;
1926bb611c8fSApple OSS Distributions 	uint32_t    idx;
1927bb611c8fSApple OSS Distributions 
1928bb611c8fSApple OSS Distributions 	IOLockLock(ivars->lock);
1929bb611c8fSApple OSS Distributions 	for (idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
1930bb611c8fSApple OSS Distributions 		next = (IOService *) ivars->pending[idx]->getObject(0);
1931bb611c8fSApple OSS Distributions 		if (next) {
1932bb611c8fSApple OSS Distributions 			next->retain();
1933bb611c8fSApple OSS Distributions 			ivars->pending[idx]->removeObject(0);
1934bb611c8fSApple OSS Distributions 			break;
1935bb611c8fSApple OSS Distributions 		}
1936bb611c8fSApple OSS Distributions 	}
1937bb611c8fSApple OSS Distributions 	IOLockUnlock(ivars->lock);
1938bb611c8fSApple OSS Distributions 
1939bb611c8fSApple OSS Distributions 	if (idx == kIOServiceNotificationTypeCount) {
1940bb611c8fSApple OSS Distributions 		idx = kIOServiceNotificationTypeNone;
1941bb611c8fSApple OSS Distributions 	}
1942bb611c8fSApple OSS Distributions 	*type    = idx;
1943bb611c8fSApple OSS Distributions 	*service = next;
1944bb611c8fSApple OSS Distributions 	*options = 0;
1945bb611c8fSApple OSS Distributions 
1946bb611c8fSApple OSS Distributions 	return kIOReturnSuccess;
1947bb611c8fSApple OSS Distributions }
1948bb611c8fSApple OSS Distributions 
1949bb611c8fSApple OSS Distributions bool
init()1950bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::init()
1951bb611c8fSApple OSS Distributions {
1952bb611c8fSApple OSS Distributions 	if (!super::init()) {
1953bb611c8fSApple OSS Distributions 		return false;
1954bb611c8fSApple OSS Distributions 	}
1955e6231be0SApple OSS Distributions 	ivars = IOMallocType(IOServiceNotificationDispatchSource_IVars);
1956bb611c8fSApple OSS Distributions 
1957bb611c8fSApple OSS Distributions 	return true;
1958bb611c8fSApple OSS Distributions }
1959bb611c8fSApple OSS Distributions 
1960bb611c8fSApple OSS Distributions void
free()1961bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::free()
1962bb611c8fSApple OSS Distributions {
1963bb611c8fSApple OSS Distributions 	if (ivars) {
19645c2921b0SApple OSS Distributions 		if (ivars->notifier) {
19655c2921b0SApple OSS Distributions 			ivars->notifier->remove();
19665c2921b0SApple OSS Distributions 			ivars->notifier = NULL;
19675c2921b0SApple OSS Distributions 		}
1968bb611c8fSApple OSS Distributions 		if (ivars->interestNotifiers) {
19695c2921b0SApple OSS Distributions 			OSDictionary * savedInterestNotifiers = NULL;
19705c2921b0SApple OSS Distributions 
19715c2921b0SApple OSS Distributions 			// the lock is always initialized first, so it should exist
19725c2921b0SApple OSS Distributions 			assert(ivars->lock);
19735c2921b0SApple OSS Distributions 
19745c2921b0SApple OSS Distributions 			// Prevent additional changes to interestNotifiers
19755c2921b0SApple OSS Distributions 			IOLockLock(ivars->lock);
19765c2921b0SApple OSS Distributions 			savedInterestNotifiers = ivars->interestNotifiers;
19775c2921b0SApple OSS Distributions 			ivars->interestNotifiers = NULL;
19785c2921b0SApple OSS Distributions 			IOLockUnlock(ivars->lock);
19795c2921b0SApple OSS Distributions 
19805c2921b0SApple OSS Distributions 			// Remove all interest notifiers
19815c2921b0SApple OSS Distributions 			savedInterestNotifiers->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
1982bb611c8fSApple OSS Distributions 				IONotifier * interest = (typeof(interest))object;
1983bb611c8fSApple OSS Distributions 				interest->remove();
1984bb611c8fSApple OSS Distributions 				return false;
1985bb611c8fSApple OSS Distributions 			});
19865c2921b0SApple OSS Distributions 			OSSafeReleaseNULL(savedInterestNotifiers);
1987bb611c8fSApple OSS Distributions 		}
1988bb611c8fSApple OSS Distributions 		for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
1989bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(ivars->pending[idx]);
1990bb611c8fSApple OSS Distributions 		}
1991bb611c8fSApple OSS Distributions 		if (ivars->lock) {
1992bb611c8fSApple OSS Distributions 			IOLockFree(ivars->lock);
1993bb611c8fSApple OSS Distributions 			ivars->lock = NULL;
1994bb611c8fSApple OSS Distributions 		}
19955c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(ivars->serverName);
1996e6231be0SApple OSS Distributions 		IOFreeType(ivars, IOServiceNotificationDispatchSource_IVars);
1997bb611c8fSApple OSS Distributions 	}
1998bb611c8fSApple OSS Distributions 
1999bb611c8fSApple OSS Distributions 	super::free();
2000bb611c8fSApple OSS Distributions }
2001bb611c8fSApple OSS Distributions 
2002bb611c8fSApple OSS Distributions kern_return_t
SetHandler_Impl(OSAction * action)2003bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::SetHandler_Impl(
2004bb611c8fSApple OSS Distributions 	OSAction * action)
2005bb611c8fSApple OSS Distributions {
2006bb611c8fSApple OSS Distributions 	IOReturn ret;
2007bb611c8fSApple OSS Distributions 	bool     notifyReady;
2008bb611c8fSApple OSS Distributions 
2009bb611c8fSApple OSS Distributions 	notifyReady = false;
2010bb611c8fSApple OSS Distributions 
2011bb611c8fSApple OSS Distributions 	IOLockLock(ivars->lock);
2012bb611c8fSApple OSS Distributions 	OSSafeReleaseNULL(ivars->action);
2013bb611c8fSApple OSS Distributions 	action->retain();
2014bb611c8fSApple OSS Distributions 	ivars->action = action;
2015bb611c8fSApple OSS Distributions 	if (action) {
2016bb611c8fSApple OSS Distributions 		for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
2017bb611c8fSApple OSS Distributions 			notifyReady = (ivars->pending[idx]->getCount());
2018bb611c8fSApple OSS Distributions 			if (notifyReady) {
2019bb611c8fSApple OSS Distributions 				break;
2020bb611c8fSApple OSS Distributions 			}
2021bb611c8fSApple OSS Distributions 		}
2022bb611c8fSApple OSS Distributions 	}
2023bb611c8fSApple OSS Distributions 	IOLockUnlock(ivars->lock);
2024bb611c8fSApple OSS Distributions 
2025bb611c8fSApple OSS Distributions 	if (notifyReady) {
2026bb611c8fSApple OSS Distributions 		ServiceNotificationReady(action);
2027bb611c8fSApple OSS Distributions 	}
2028bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
2029bb611c8fSApple OSS Distributions 
2030bb611c8fSApple OSS Distributions 	return ret;
2031bb611c8fSApple OSS Distributions }
2032bb611c8fSApple OSS Distributions 
2033bb611c8fSApple OSS Distributions kern_return_t
SetEnableWithCompletion_Impl(bool enable,IODispatchSourceCancelHandler handler)2034bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::SetEnableWithCompletion_Impl(
2035bb611c8fSApple OSS Distributions 	bool enable,
2036bb611c8fSApple OSS Distributions 	IODispatchSourceCancelHandler handler)
2037bb611c8fSApple OSS Distributions {
2038bb611c8fSApple OSS Distributions 	if (enable == ivars->enable) {
2039bb611c8fSApple OSS Distributions 		return kIOReturnSuccess;
2040bb611c8fSApple OSS Distributions 	}
2041bb611c8fSApple OSS Distributions 
2042bb611c8fSApple OSS Distributions 	IOLockLock(ivars->lock);
2043bb611c8fSApple OSS Distributions 	ivars->enable = enable;
2044bb611c8fSApple OSS Distributions 	IOLockUnlock(ivars->lock);
2045bb611c8fSApple OSS Distributions 
2046bb611c8fSApple OSS Distributions 	return kIOReturnSuccess;
2047bb611c8fSApple OSS Distributions }
2048bb611c8fSApple OSS Distributions 
2049bb611c8fSApple OSS Distributions kern_return_t
Cancel_Impl(IODispatchSourceCancelHandler handler)2050bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::Cancel_Impl(
2051bb611c8fSApple OSS Distributions 	IODispatchSourceCancelHandler handler)
2052bb611c8fSApple OSS Distributions {
2053bb611c8fSApple OSS Distributions 	return kIOReturnUnsupported;
2054bb611c8fSApple OSS Distributions }
2055bb611c8fSApple OSS Distributions 
2056bb611c8fSApple OSS Distributions kern_return_t
CheckForWork_Impl(const IORPC rpc,bool synchronous)2057bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::CheckForWork_Impl(
2058bb611c8fSApple OSS Distributions 	const IORPC rpc,
2059bb611c8fSApple OSS Distributions 	bool synchronous)
2060bb611c8fSApple OSS Distributions {
2061bb611c8fSApple OSS Distributions 	return kIOReturnNotReady;
2062bb611c8fSApple OSS Distributions }
2063bb611c8fSApple OSS Distributions 
2064bb611c8fSApple OSS Distributions kern_return_t
DeliverNotifications(IOServiceNotificationBlock block)2065bb611c8fSApple OSS Distributions IOServiceNotificationDispatchSource::DeliverNotifications(IOServiceNotificationBlock block)
2066bb611c8fSApple OSS Distributions {
2067bb611c8fSApple OSS Distributions 	return kIOReturnUnsupported;
2068bb611c8fSApple OSS Distributions }
2069bb611c8fSApple OSS Distributions 
2070e6231be0SApple OSS Distributions 
2071e6231be0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2072e6231be0SApple OSS Distributions 
2073e6231be0SApple OSS Distributions OSDictionary *
CreatePropertyMatchingDictionary(const char * key,OSObjectPtr value,OSDictionary * matching)2074e6231be0SApple OSS Distributions IOService::CreatePropertyMatchingDictionary(const char * key, OSObjectPtr value, OSDictionary * matching)
2075e6231be0SApple OSS Distributions {
2076e6231be0SApple OSS Distributions 	OSDictionary   * result;
2077e6231be0SApple OSS Distributions 	const OSSymbol * keySym;
2078e6231be0SApple OSS Distributions 
2079e6231be0SApple OSS Distributions 	keySym = OSSymbol::withCString(key);
2080e6231be0SApple OSS Distributions 	result = propertyMatching(keySym, (const OSObject *) value, matching);
2081e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(keySym);
2082e6231be0SApple OSS Distributions 
2083e6231be0SApple OSS Distributions 	return result;
2084e6231be0SApple OSS Distributions }
2085e6231be0SApple OSS Distributions 
2086e6231be0SApple OSS Distributions OSDictionary *
CreatePropertyMatchingDictionary(const char * key,const char * stringValue,OSDictionary * matching)2087e6231be0SApple OSS Distributions IOService::CreatePropertyMatchingDictionary(const char * key, const char * stringValue, OSDictionary * matching)
2088e6231be0SApple OSS Distributions {
2089e6231be0SApple OSS Distributions 	OSDictionary * result;
2090e6231be0SApple OSS Distributions 	OSString     * value;
2091e6231be0SApple OSS Distributions 
2092e6231be0SApple OSS Distributions 	value = OSString::withCString(stringValue);
2093e6231be0SApple OSS Distributions 	result = CreatePropertyMatchingDictionary(key, value, matching);
2094e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(value);
2095e6231be0SApple OSS Distributions 
2096e6231be0SApple OSS Distributions 	return result;
2097e6231be0SApple OSS Distributions }
2098e6231be0SApple OSS Distributions 
2099e6231be0SApple OSS Distributions OSDictionary *
CreateKernelClassMatchingDictionary(OSString * className,OSDictionary * matching)2100e6231be0SApple OSS Distributions IOService::CreateKernelClassMatchingDictionary(OSString * className, OSDictionary * matching)
2101e6231be0SApple OSS Distributions {
2102e6231be0SApple OSS Distributions 	if (!className) {
2103e6231be0SApple OSS Distributions 		return NULL;
2104e6231be0SApple OSS Distributions 	}
2105e6231be0SApple OSS Distributions 	if (!matching) {
2106e6231be0SApple OSS Distributions 		matching = OSDictionary::withCapacity(2);
2107e6231be0SApple OSS Distributions 		if (!matching) {
2108e6231be0SApple OSS Distributions 			return NULL;
2109e6231be0SApple OSS Distributions 		}
2110e6231be0SApple OSS Distributions 	}
2111e6231be0SApple OSS Distributions 	matching->setObject(kIOProviderClassKey, className);
2112e6231be0SApple OSS Distributions 
2113e6231be0SApple OSS Distributions 	return matching;
2114e6231be0SApple OSS Distributions }
2115e6231be0SApple OSS Distributions 
2116e6231be0SApple OSS Distributions OSDictionary *
CreateKernelClassMatchingDictionary(const char * className,OSDictionary * matching)2117e6231be0SApple OSS Distributions IOService::CreateKernelClassMatchingDictionary(const char * className, OSDictionary * matching)
2118e6231be0SApple OSS Distributions {
2119e6231be0SApple OSS Distributions 	OSDictionary * result;
2120e6231be0SApple OSS Distributions 	OSString     * string;
2121e6231be0SApple OSS Distributions 
2122e6231be0SApple OSS Distributions 	string = OSString::withCString(className);
2123e6231be0SApple OSS Distributions 	result = CreateKernelClassMatchingDictionary(string, matching);
2124e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(string);
2125e6231be0SApple OSS Distributions 
2126e6231be0SApple OSS Distributions 	return result;
2127e6231be0SApple OSS Distributions }
2128e6231be0SApple OSS Distributions 
2129e6231be0SApple OSS Distributions OSDictionary *
CreateUserClassMatchingDictionary(OSString * className,OSDictionary * matching)2130e6231be0SApple OSS Distributions IOService::CreateUserClassMatchingDictionary(OSString * className, OSDictionary * matching)
2131e6231be0SApple OSS Distributions {
2132e6231be0SApple OSS Distributions 	return CreatePropertyMatchingDictionary(kIOUserClassKey, className, matching);
2133e6231be0SApple OSS Distributions }
2134e6231be0SApple OSS Distributions 
2135e6231be0SApple OSS Distributions OSDictionary *
CreateUserClassMatchingDictionary(const char * className,OSDictionary * matching)2136e6231be0SApple OSS Distributions IOService::CreateUserClassMatchingDictionary(const char * className, OSDictionary * matching)
2137e6231be0SApple OSS Distributions {
2138e6231be0SApple OSS Distributions 	return CreatePropertyMatchingDictionary(kIOUserClassKey, className, matching);
2139e6231be0SApple OSS Distributions }
2140e6231be0SApple OSS Distributions 
2141e6231be0SApple OSS Distributions OSDictionary *
CreateNameMatchingDictionary(OSString * serviceName,OSDictionary * matching)2142e6231be0SApple OSS Distributions IOService::CreateNameMatchingDictionary(OSString * serviceName, OSDictionary * matching)
2143e6231be0SApple OSS Distributions {
2144e6231be0SApple OSS Distributions 	if (!serviceName) {
2145e6231be0SApple OSS Distributions 		return NULL;
2146e6231be0SApple OSS Distributions 	}
2147e6231be0SApple OSS Distributions 	if (!matching) {
2148e6231be0SApple OSS Distributions 		matching = OSDictionary::withCapacity(2);
2149e6231be0SApple OSS Distributions 		if (!matching) {
2150e6231be0SApple OSS Distributions 			return NULL;
2151e6231be0SApple OSS Distributions 		}
2152e6231be0SApple OSS Distributions 	}
2153e6231be0SApple OSS Distributions 	matching->setObject(kIONameMatchKey, serviceName);
2154e6231be0SApple OSS Distributions 
2155e6231be0SApple OSS Distributions 	return matching;
2156e6231be0SApple OSS Distributions }
2157e6231be0SApple OSS Distributions 
2158e6231be0SApple OSS Distributions OSDictionary *
CreateNameMatchingDictionary(const char * serviceName,OSDictionary * matching)2159e6231be0SApple OSS Distributions IOService::CreateNameMatchingDictionary(const char * serviceName, OSDictionary * matching)
2160e6231be0SApple OSS Distributions {
2161e6231be0SApple OSS Distributions 	OSDictionary * result;
2162e6231be0SApple OSS Distributions 	OSString     * string;
2163e6231be0SApple OSS Distributions 
2164e6231be0SApple OSS Distributions 	string = OSString::withCString(serviceName);
2165e6231be0SApple OSS Distributions 	result = CreateNameMatchingDictionary(string, matching);
2166e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(string);
2167e6231be0SApple OSS Distributions 
2168e6231be0SApple OSS Distributions 	return result;
2169e6231be0SApple OSS Distributions }
2170e6231be0SApple OSS Distributions 
2171e6231be0SApple OSS Distributions 
2172e6231be0SApple OSS Distributions 
2173bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2174a5e72196SApple OSS Distributions 
2175a5e72196SApple OSS Distributions kern_return_t
waitInterruptTrap(void * p1,void * p2,void * p3,void * p4,void * p5,void * p6)2176a5e72196SApple OSS Distributions IOUserServer::waitInterruptTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
2177a5e72196SApple OSS Distributions {
2178a5e72196SApple OSS Distributions 	IOReturn         ret = kIOReturnBadArgument;
2179a5e72196SApple OSS Distributions 	IOInterruptState is;
2180a5e72196SApple OSS Distributions 	IOInterruptDispatchSource * interrupt;
2181a5e72196SApple OSS Distributions 	IOInterruptDispatchSource_IVars * ivars;
2182a5e72196SApple OSS Distributions 	IOInterruptDispatchSourcePayload payload;
2183a5e72196SApple OSS Distributions 
2184bb611c8fSApple OSS Distributions 	bool             willWait;
21855c2921b0SApple OSS Distributions 	bool             canceled;
2186a5e72196SApple OSS Distributions 	wait_result_t    waitResult;
2187a5e72196SApple OSS Distributions 	thread_t         self;
2188a5e72196SApple OSS Distributions 
2189a5e72196SApple OSS Distributions 	OSObject * object;
2190a5e72196SApple OSS Distributions 
2191a5e72196SApple OSS Distributions 	object = iokit_lookup_object_with_port_name((mach_port_name_t)(uintptr_t)p1, IKOT_UEXT_OBJECT, current_task());
2192a5e72196SApple OSS Distributions 
2193a5e72196SApple OSS Distributions 	if (!object) {
2194a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2195a5e72196SApple OSS Distributions 	}
2196a5e72196SApple OSS Distributions 	if (!(interrupt = OSDynamicCast(IOInterruptDispatchSource, object))) {
2197a5e72196SApple OSS Distributions 		ret = kIOReturnBadArgument;
2198a5e72196SApple OSS Distributions 	} else {
2199a5e72196SApple OSS Distributions 		self = current_thread();
2200a5e72196SApple OSS Distributions 		ivars = interrupt->ivars;
2201a5e72196SApple OSS Distributions 		payload.count = 0;
2202a5e72196SApple OSS Distributions 		do {
22035c2921b0SApple OSS Distributions 			willWait = false;
2204a5e72196SApple OSS Distributions 			is = IOSimpleLockLockDisableInterrupt(ivars->lock);
22055c2921b0SApple OSS Distributions 			canceled = ivars->canceled;
22065c2921b0SApple OSS Distributions 			if (!canceled) {
2207a5e72196SApple OSS Distributions 				if ((payload.count = ivars->count)) {
2208a5e72196SApple OSS Distributions 					payload.time = ivars->time;
2209a5e72196SApple OSS Distributions 					ivars->count = 0;
2210a5e72196SApple OSS Distributions 					waitResult = THREAD_AWAKENED;
2211a5e72196SApple OSS Distributions 				} else {
2212a5e72196SApple OSS Distributions 					assert(NULL == ivars->waiter);
2213a5e72196SApple OSS Distributions 					ivars->waiter = self;
2214a5e72196SApple OSS Distributions 					waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
2215a5e72196SApple OSS Distributions 				}
2216bb611c8fSApple OSS Distributions 				willWait = (waitResult == THREAD_WAITING);
2217bb611c8fSApple OSS Distributions 				if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
2218a5e72196SApple OSS Distributions 					IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
2219e7776783SApple OSS Distributions 					ivars->provider->enableInterrupt(ivars->intIndex);
2220e7776783SApple OSS Distributions 				} else {
2221e7776783SApple OSS Distributions 					IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
2222e7776783SApple OSS Distributions 				}
22235c2921b0SApple OSS Distributions 			} else {
22245c2921b0SApple OSS Distributions 				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
22255c2921b0SApple OSS Distributions 			}
2226bb611c8fSApple OSS Distributions 			if (willWait) {
2227a5e72196SApple OSS Distributions 				waitResult = thread_block(THREAD_CONTINUE_NULL);
2228a5e72196SApple OSS Distributions 				if (THREAD_INTERRUPTED == waitResult) {
2229bb611c8fSApple OSS Distributions 					is = IOSimpleLockLockDisableInterrupt(ivars->lock);
2230bb611c8fSApple OSS Distributions 					ivars->waiter = NULL;
2231bb611c8fSApple OSS Distributions 					IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
22325c2921b0SApple OSS Distributions 					canceled = true;
2233a5e72196SApple OSS Distributions 					break;
2234a5e72196SApple OSS Distributions 				}
2235a5e72196SApple OSS Distributions 			}
22365c2921b0SApple OSS Distributions 		} while (!payload.count && !canceled);
2237a5e72196SApple OSS Distributions 		ret = (payload.count ? kIOReturnSuccess : kIOReturnAborted);
2238a5e72196SApple OSS Distributions 	}
2239a5e72196SApple OSS Distributions 
2240a5e72196SApple OSS Distributions 	if (kIOReturnSuccess == ret) {
2241a5e72196SApple OSS Distributions 		int copyerr = copyout(&payload, (user_addr_t) p2, sizeof(payload));
2242a5e72196SApple OSS Distributions 		if (copyerr) {
2243a5e72196SApple OSS Distributions 			ret = kIOReturnVMError;
2244a5e72196SApple OSS Distributions 		}
2245a5e72196SApple OSS Distributions 	}
2246a5e72196SApple OSS Distributions 
2247a5e72196SApple OSS Distributions 	object->release();
2248a5e72196SApple OSS Distributions 
2249a5e72196SApple OSS Distributions 	return ret;
2250a5e72196SApple OSS Distributions }
2251a5e72196SApple OSS Distributions 
2252bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2253a5e72196SApple OSS Distributions 
2254a5e72196SApple OSS Distributions kern_return_t
Create_Impl(const char * name,uint64_t tag,uint64_t options,OSString * bundleID,IOUserServer ** server)2255bb611c8fSApple OSS Distributions IOUserServer::Create_Impl(
2256bb611c8fSApple OSS Distributions 	const char * name,
2257bb611c8fSApple OSS Distributions 	uint64_t tag,
2258bb611c8fSApple OSS Distributions 	uint64_t options,
2259e6231be0SApple OSS Distributions 	OSString * bundleID,
2260bb611c8fSApple OSS Distributions 	IOUserServer ** server)
2261a5e72196SApple OSS Distributions {
2262a5e72196SApple OSS Distributions 	IOReturn          ret;
2263a5e72196SApple OSS Distributions 	IOUserServer    * us;
2264a5e72196SApple OSS Distributions 	const OSSymbol  * sym;
2265a5e72196SApple OSS Distributions 	OSNumber        * serverTag;
2266a5e72196SApple OSS Distributions 	io_name_t         rname;
2267e6231be0SApple OSS Distributions 	OSKext          * kext;
2268a5e72196SApple OSS Distributions 
2269a5e72196SApple OSS Distributions 	us = (typeof(us))thread_iokit_tls_get(0);
2270a5e72196SApple OSS Distributions 	assert(OSDynamicCast(IOUserServer, us));
2271a5e72196SApple OSS Distributions 	if (kIODKLogSetup & gIODKDebug) {
2272a5e72196SApple OSS Distributions 		DKLOG(DKS "::Create(" DKS ") %p\n", DKN(us), name, tag, us);
2273a5e72196SApple OSS Distributions 	}
2274a5e72196SApple OSS Distributions 	if (!us) {
2275a5e72196SApple OSS Distributions 		return kIOReturnError;
2276a5e72196SApple OSS Distributions 	}
2277a5e72196SApple OSS Distributions 
2278e6231be0SApple OSS Distributions 	if (bundleID) {
2279e6231be0SApple OSS Distributions 		kext = OSKext::lookupKextWithIdentifier(bundleID->getCStringNoCopy());
2280e6231be0SApple OSS Distributions 		if (kext) {
2281e6231be0SApple OSS Distributions 			us->setTaskLoadTag(kext);
2282e6231be0SApple OSS Distributions 			us->setDriverKitUUID(kext);
22835c2921b0SApple OSS Distributions 			us->setDriverKitStatistics(kext);
2284e6231be0SApple OSS Distributions 			OSKext::OSKextLogDriverKitInfoLoad(kext);
2285e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(kext);
2286e6231be0SApple OSS Distributions 		} else {
2287e6231be0SApple OSS Distributions 			DKLOG(DKS "::Create(" DKS "): could not find OSKext for %s\n", DKN(us), name, tag, bundleID->getCStringNoCopy());
2288e6231be0SApple OSS Distributions 		}
2289e6231be0SApple OSS Distributions 
2290e6231be0SApple OSS Distributions 		us->fAllocationName = kern_allocation_name_allocate(bundleID->getCStringNoCopy(), 0);
2291e6231be0SApple OSS Distributions 		assert(us->fAllocationName);
2292e6231be0SApple OSS Distributions 	}
2293e6231be0SApple OSS Distributions 
2294a5e72196SApple OSS Distributions 	sym       = OSSymbol::withCString(name);
2295a5e72196SApple OSS Distributions 	serverTag = OSNumber::withNumber(tag, 64);
2296a5e72196SApple OSS Distributions 
2297a5e72196SApple OSS Distributions 	us->setProperty(gIOUserServerNameKey, (OSObject *) sym);
2298a5e72196SApple OSS Distributions 	us->setProperty(gIOUserServerTagKey, serverTag);
2299a5e72196SApple OSS Distributions 
2300a5e72196SApple OSS Distributions 	serverTag->release();
2301a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(sym);
2302a5e72196SApple OSS Distributions 
2303a5e72196SApple OSS Distributions 	snprintf(rname, sizeof(rname), "IOUserServer(%s-0x%qx)", name, tag);
2304a5e72196SApple OSS Distributions 	us->setName(rname);
2305a5e72196SApple OSS Distributions 
2306a5e72196SApple OSS Distributions 	us->retain();
2307a5e72196SApple OSS Distributions 	*server = us;
2308a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
2309a5e72196SApple OSS Distributions 
2310a5e72196SApple OSS Distributions 	return ret;
2311a5e72196SApple OSS Distributions }
2312a5e72196SApple OSS Distributions 
2313a5e72196SApple OSS Distributions kern_return_t
RegisterService_Impl()2314e6231be0SApple OSS Distributions IOUserServer::RegisterService_Impl()
2315e6231be0SApple OSS Distributions {
2316e6231be0SApple OSS Distributions 	kern_return_t ret = IOService::RegisterService_Impl();
2317e6231be0SApple OSS Distributions 
2318e6231be0SApple OSS Distributions 	return ret;
2319e6231be0SApple OSS Distributions }
2320e6231be0SApple OSS Distributions 
2321e6231be0SApple OSS Distributions kern_return_t
Exit_Impl(const char * reason)2322bb611c8fSApple OSS Distributions IOUserServer::Exit_Impl(
2323bb611c8fSApple OSS Distributions 	const char * reason)
2324a5e72196SApple OSS Distributions {
2325a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2326a5e72196SApple OSS Distributions }
2327a5e72196SApple OSS Distributions 
2328a5e72196SApple OSS Distributions kern_return_t
LoadModule_Impl(const char * path)2329bb611c8fSApple OSS Distributions IOUserServer::LoadModule_Impl(
2330bb611c8fSApple OSS Distributions 	const char * path)
2331a5e72196SApple OSS Distributions {
2332a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2333a5e72196SApple OSS Distributions }
2334a5e72196SApple OSS Distributions 
2335a5e72196SApple OSS Distributions 
2336bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2337a5e72196SApple OSS Distributions 
2338a5e72196SApple OSS Distributions kern_return_t
Create_Impl(const char * name,uint64_t options,uint64_t priority,IODispatchQueue ** queue)2339bb611c8fSApple OSS Distributions IODispatchQueue::Create_Impl(
2340bb611c8fSApple OSS Distributions 	const char * name,
2341bb611c8fSApple OSS Distributions 	uint64_t options,
2342bb611c8fSApple OSS Distributions 	uint64_t priority,
2343bb611c8fSApple OSS Distributions 	IODispatchQueue ** queue)
2344a5e72196SApple OSS Distributions {
2345a5e72196SApple OSS Distributions 	IODispatchQueue * result;
2346a5e72196SApple OSS Distributions 	IOUserServer    * us;
2347a5e72196SApple OSS Distributions 
2348a5e72196SApple OSS Distributions 	result = OSTypeAlloc(IODispatchQueue);
2349a5e72196SApple OSS Distributions 	if (!result) {
2350a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
2351a5e72196SApple OSS Distributions 	}
2352a5e72196SApple OSS Distributions 	if (!result->init()) {
2353e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(result);
2354a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
2355a5e72196SApple OSS Distributions 	}
2356a5e72196SApple OSS Distributions 
2357a5e72196SApple OSS Distributions 	*queue = result;
2358a5e72196SApple OSS Distributions 
2359a5e72196SApple OSS Distributions 	if (!strcmp("Root", name)) {
2360a5e72196SApple OSS Distributions 		us = (typeof(us))thread_iokit_tls_get(0);
2361a5e72196SApple OSS Distributions 		assert(OSDynamicCast(IOUserServer, us));
2362a5e72196SApple OSS Distributions 		us->setRootQueue(result);
2363a5e72196SApple OSS Distributions 	}
2364a5e72196SApple OSS Distributions 
2365a5e72196SApple OSS Distributions 	if (kIODKLogSetup & gIODKDebug) {
2366a5e72196SApple OSS Distributions 		DKLOG("IODispatchQueue::Create %s %p\n", name, result);
2367a5e72196SApple OSS Distributions 	}
2368a5e72196SApple OSS Distributions 
2369a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2370a5e72196SApple OSS Distributions }
2371a5e72196SApple OSS Distributions 
2372a5e72196SApple OSS Distributions kern_return_t
SetPort_Impl(mach_port_t port)2373bb611c8fSApple OSS Distributions IODispatchQueue::SetPort_Impl(
2374bb611c8fSApple OSS Distributions 	mach_port_t port)
2375a5e72196SApple OSS Distributions {
2376bb611c8fSApple OSS Distributions 	if (MACH_PORT_NULL != ivars->serverPort) {
2377bb611c8fSApple OSS Distributions 		return kIOReturnNotReady;
2378bb611c8fSApple OSS Distributions 	}
23798d741a5dSApple OSS Distributions 	ivars->serverPort = ipc_port_copy_send_mqueue(port);
23808d741a5dSApple OSS Distributions 	if (ivars->serverPort == MACH_PORT_NULL) {
23818d741a5dSApple OSS Distributions 		return kIOReturnBadArgument;
23828d741a5dSApple OSS Distributions 	}
2383a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2384a5e72196SApple OSS Distributions }
2385a5e72196SApple OSS Distributions 
2386a5e72196SApple OSS Distributions bool
init()2387a5e72196SApple OSS Distributions IODispatchQueue::init()
2388a5e72196SApple OSS Distributions {
2389e6231be0SApple OSS Distributions 	ivars = IOMallocType(IODispatchQueue_IVars);
2390a5e72196SApple OSS Distributions 	ivars->queue = this;
2391a5e72196SApple OSS Distributions 
2392a5e72196SApple OSS Distributions 	return true;
2393a5e72196SApple OSS Distributions }
2394a5e72196SApple OSS Distributions 
2395a5e72196SApple OSS Distributions void
free()2396a5e72196SApple OSS Distributions IODispatchQueue::free()
2397a5e72196SApple OSS Distributions {
2398bb611c8fSApple OSS Distributions 	if (ivars && ivars->serverPort) {
2399bb611c8fSApple OSS Distributions 		ipc_port_release_send(ivars->serverPort);
2400bb611c8fSApple OSS Distributions 		ivars->serverPort = MACH_PORT_NULL;
2401bb611c8fSApple OSS Distributions 	}
2402e6231be0SApple OSS Distributions 	IOFreeType(ivars, IODispatchQueue_IVars);
2403a5e72196SApple OSS Distributions 	super::free();
2404a5e72196SApple OSS Distributions }
2405a5e72196SApple OSS Distributions 
2406a5e72196SApple OSS Distributions bool
OnQueue()2407a5e72196SApple OSS Distributions IODispatchQueue::OnQueue()
2408a5e72196SApple OSS Distributions {
2409a5e72196SApple OSS Distributions 	return false;
2410a5e72196SApple OSS Distributions }
2411a5e72196SApple OSS Distributions 
2412a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2413a5e72196SApple OSS Distributions 
2414a5e72196SApple OSS Distributions 
2415a5e72196SApple OSS Distributions kern_return_t
Dispatch(IORPC rpc)2416a5e72196SApple OSS Distributions OSMetaClassBase::Dispatch(IORPC rpc)
2417a5e72196SApple OSS Distributions {
2418a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2419a5e72196SApple OSS Distributions }
2420a5e72196SApple OSS Distributions 
2421a5e72196SApple OSS Distributions kern_return_t
Invoke(IORPC rpc)2422a5e72196SApple OSS Distributions OSMetaClassBase::Invoke(IORPC rpc)
2423a5e72196SApple OSS Distributions {
2424a5e72196SApple OSS Distributions 	IOReturn          ret = kIOReturnUnsupported;
2425a5e72196SApple OSS Distributions 	OSMetaClassBase * object;
2426a5e72196SApple OSS Distributions 	OSAction        * action;
2427a5e72196SApple OSS Distributions 	IOService       * service;
2428a5e72196SApple OSS Distributions 	IOUserServer    * us;
2429a5e72196SApple OSS Distributions 	IORPCMessage    * message;
2430a5e72196SApple OSS Distributions 
2431a5e72196SApple OSS Distributions 	assert(rpc.sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
243294d3b452SApple OSS Distributions 	message = rpc.kernelContent;
2433a5e72196SApple OSS Distributions 	if (!message) {
2434a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
2435a5e72196SApple OSS Distributions 	}
2436a5e72196SApple OSS Distributions 	message->flags |= kIORPCMessageKernel;
2437a5e72196SApple OSS Distributions 
2438a5e72196SApple OSS Distributions 	us = NULL;
2439a5e72196SApple OSS Distributions 	if (!(kIORPCMessageLocalHost & message->flags)) {
2440a5e72196SApple OSS Distributions 		us = OSDynamicCast(IOUserServer, this);
2441a5e72196SApple OSS Distributions 		if (!us) {
2442e6231be0SApple OSS Distributions 			IOEventLink * eventLink = NULL;
2443e6231be0SApple OSS Distributions 			IOWorkGroup * workgroup = NULL;
2444e6231be0SApple OSS Distributions 
2445a5e72196SApple OSS Distributions 			if ((action = OSDynamicCast(OSAction, this))) {
2446a5e72196SApple OSS Distributions 				object = IOUserServer::target(action, message);
2447a5e72196SApple OSS Distributions 			} else {
2448a5e72196SApple OSS Distributions 				object = this;
2449a5e72196SApple OSS Distributions 			}
2450a5e72196SApple OSS Distributions 			if ((service = OSDynamicCast(IOService, object))
2451a5e72196SApple OSS Distributions 			    && service->reserved->uvars) {
2452a5e72196SApple OSS Distributions 				// xxx other classes
2453a5e72196SApple OSS Distributions 				us = service->reserved->uvars->userServer;
2454e6231be0SApple OSS Distributions 			} else if (action) {
2455e6231be0SApple OSS Distributions 				us = action->ivars->userServer;
2456e6231be0SApple OSS Distributions 			} else if ((eventLink = OSDynamicCast(IOEventLink, object))) {
2457e6231be0SApple OSS Distributions 				us = eventLink->ivars->userServer;
2458e6231be0SApple OSS Distributions 			} else if ((workgroup = OSDynamicCast(IOWorkGroup, object))) {
2459e6231be0SApple OSS Distributions 				us = workgroup->ivars->userServer;
2460a5e72196SApple OSS Distributions 			}
2461a5e72196SApple OSS Distributions 		}
2462a5e72196SApple OSS Distributions 	}
2463a5e72196SApple OSS Distributions 	if (us) {
2464a5e72196SApple OSS Distributions 		message->flags |= kIORPCMessageRemote;
2465a5e72196SApple OSS Distributions 		ret = us->rpc(rpc);
2466a5e72196SApple OSS Distributions 		if (kIOReturnSuccess != ret) {
2467a5e72196SApple OSS Distributions 			if (kIODKLogIPC & gIODKDebug) {
2468a5e72196SApple OSS Distributions 				DKLOG("OSMetaClassBase::Invoke user 0x%x\n", ret);
2469a5e72196SApple OSS Distributions 			}
2470a5e72196SApple OSS Distributions 		}
2471a5e72196SApple OSS Distributions 	} else {
2472a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
2473a5e72196SApple OSS Distributions 			DKLOG("OSMetaClassBase::Invoke kernel %s 0x%qx\n", getMetaClass()->getClassName(), message->msgid);
2474a5e72196SApple OSS Distributions 		}
2475e6231be0SApple OSS Distributions 		void * prior = thread_iokit_tls_get(0);
2476e6231be0SApple OSS Distributions 		thread_iokit_tls_set(0, NULL);
2477a5e72196SApple OSS Distributions 		ret = Dispatch(rpc);
2478e6231be0SApple OSS Distributions 		thread_iokit_tls_set(0, prior);
2479a5e72196SApple OSS Distributions 	}
2480a5e72196SApple OSS Distributions 
2481a5e72196SApple OSS Distributions 	return ret;
2482a5e72196SApple OSS Distributions }
2483a5e72196SApple OSS Distributions 
2484a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2485a5e72196SApple OSS Distributions 
2486a5e72196SApple OSS Distributions struct IOPStrings {
2487a5e72196SApple OSS Distributions 	uint32_t     dataSize;
2488a5e72196SApple OSS Distributions 	uint32_t     count;
2489a5e72196SApple OSS Distributions 	const char   strings[0];
2490a5e72196SApple OSS Distributions };
2491a5e72196SApple OSS Distributions 
2492a5e72196SApple OSS Distributions kern_return_t
Dispatch(IORPC rpc)2493a5e72196SApple OSS Distributions OSUserMetaClass::Dispatch(IORPC rpc)
2494a5e72196SApple OSS Distributions {
2495bb611c8fSApple OSS Distributions 	if (meta) {
2496a5e72196SApple OSS Distributions 		return const_cast<OSMetaClass *>(meta)->Dispatch(rpc);
2497bb611c8fSApple OSS Distributions 	} else {
2498bb611c8fSApple OSS Distributions 		return kIOReturnUnsupported;
2499bb611c8fSApple OSS Distributions 	}
2500a5e72196SApple OSS Distributions }
2501a5e72196SApple OSS Distributions 
2502a5e72196SApple OSS Distributions void
free()2503a5e72196SApple OSS Distributions OSUserMetaClass::free()
2504a5e72196SApple OSS Distributions {
2505a5e72196SApple OSS Distributions 	if (queueNames) {
2506e6231be0SApple OSS Distributions 		IOFreeData(queueNames, sizeof(IOPStrings) + queueNames->dataSize * sizeof(char));
2507a5e72196SApple OSS Distributions 		queueNames = NULL;
2508a5e72196SApple OSS Distributions 	}
2509a5e72196SApple OSS Distributions 	if (description) {
2510e6231be0SApple OSS Distributions 		IOFreeData(description, description->descriptionSize);
2511a5e72196SApple OSS Distributions 		description = NULL;
2512a5e72196SApple OSS Distributions 	}
2513e6231be0SApple OSS Distributions 	IODeleteData(methods, uint64_t, 2 * methodCount);
2514a5e72196SApple OSS Distributions 	if (meta) {
2515a5e72196SApple OSS Distributions 		meta->releaseMetaClass();
2516a5e72196SApple OSS Distributions 	}
2517a5e72196SApple OSS Distributions 	if (name) {
2518a5e72196SApple OSS Distributions 		name->release();
2519a5e72196SApple OSS Distributions 	}
2520a5e72196SApple OSS Distributions 	OSObject::free();
2521a5e72196SApple OSS Distributions }
2522a5e72196SApple OSS Distributions 
2523a5e72196SApple OSS Distributions /*
2524a5e72196SApple OSS Distributions  * Sets the loadTag of the associated OSKext
2525a5e72196SApple OSS Distributions  * in the dext task.
2526a5e72196SApple OSS Distributions  * NOTE: different instances of the same OSKext
2527a5e72196SApple OSS Distributions  * (so same BounleID but different tasks)
2528a5e72196SApple OSS Distributions  * will have the same loadTag.
2529a5e72196SApple OSS Distributions  */
2530a5e72196SApple OSS Distributions void
setTaskLoadTag(OSKext * kext)2531a5e72196SApple OSS Distributions IOUserServer::setTaskLoadTag(OSKext *kext)
2532a5e72196SApple OSS Distributions {
2533a5e72196SApple OSS Distributions 	task_t owningTask;
2534a5e72196SApple OSS Distributions 	uint32_t loadTag, prev_taskloadTag;
2535a5e72196SApple OSS Distributions 
2536a5e72196SApple OSS Distributions 	owningTask = this->fOwningTask;
2537a5e72196SApple OSS Distributions 	if (!owningTask) {
2538a5e72196SApple OSS Distributions 		printf("%s: fOwningTask not found\n", __FUNCTION__);
2539a5e72196SApple OSS Distributions 		return;
2540a5e72196SApple OSS Distributions 	}
2541a5e72196SApple OSS Distributions 
2542a5e72196SApple OSS Distributions 	loadTag = kext->getLoadTag();
2543a5e72196SApple OSS Distributions 	prev_taskloadTag = set_task_loadTag(owningTask, loadTag);
2544a5e72196SApple OSS Distributions 	if (prev_taskloadTag) {
2545a5e72196SApple OSS Distributions 		printf("%s: found the task loadTag already set to %u (set to %u)\n",
2546a5e72196SApple OSS Distributions 		    __FUNCTION__, prev_taskloadTag, loadTag);
2547a5e72196SApple OSS Distributions 	}
2548a5e72196SApple OSS Distributions }
2549a5e72196SApple OSS Distributions 
2550a5e72196SApple OSS Distributions /*
2551a5e72196SApple OSS Distributions  * Sets the OSKext uuid as the uuid of the userspace
2552a5e72196SApple OSS Distributions  * dext executable.
2553a5e72196SApple OSS Distributions  */
2554a5e72196SApple OSS Distributions void
setDriverKitUUID(OSKext * kext)2555a5e72196SApple OSS Distributions IOUserServer::setDriverKitUUID(OSKext *kext)
2556a5e72196SApple OSS Distributions {
2557a5e72196SApple OSS Distributions 	task_t task;
2558a5e72196SApple OSS Distributions 	proc_t p;
2559a5e72196SApple OSS Distributions 	uuid_t p_uuid, k_uuid;
2560a5e72196SApple OSS Distributions 	OSData *k_data_uuid;
2561a5e72196SApple OSS Distributions 	OSData *new_uuid;
2562a5e72196SApple OSS Distributions 	uuid_string_t       uuid_string = "";
2563a5e72196SApple OSS Distributions 
2564a5e72196SApple OSS Distributions 	task = this->fOwningTask;
2565a5e72196SApple OSS Distributions 	if (!task) {
2566a5e72196SApple OSS Distributions 		printf("%s: fOwningTask not found\n", __FUNCTION__);
2567a5e72196SApple OSS Distributions 		return;
2568a5e72196SApple OSS Distributions 	}
2569a5e72196SApple OSS Distributions 
2570a5e72196SApple OSS Distributions 	p = (proc_t)(get_bsdtask_info(task));
2571a5e72196SApple OSS Distributions 	if (!p) {
2572a5e72196SApple OSS Distributions 		printf("%s: proc not found\n", __FUNCTION__);
2573a5e72196SApple OSS Distributions 		return;
2574a5e72196SApple OSS Distributions 	}
2575a5e72196SApple OSS Distributions 	proc_getexecutableuuid(p, p_uuid, sizeof(p_uuid));
2576a5e72196SApple OSS Distributions 
2577a5e72196SApple OSS Distributions 	k_data_uuid = kext->copyUUID();
2578a5e72196SApple OSS Distributions 	if (k_data_uuid) {
2579a5e72196SApple OSS Distributions 		memcpy(&k_uuid, k_data_uuid->getBytesNoCopy(), sizeof(k_uuid));
2580a5e72196SApple OSS Distributions 		OSSafeReleaseNULL(k_data_uuid);
2581a5e72196SApple OSS Distributions 		if (uuid_compare(k_uuid, p_uuid) != 0) {
2582a5e72196SApple OSS Distributions 			printf("%s: uuid not matching\n", __FUNCTION__);
2583a5e72196SApple OSS Distributions 		}
2584a5e72196SApple OSS Distributions 		return;
2585a5e72196SApple OSS Distributions 	}
2586a5e72196SApple OSS Distributions 
2587a5e72196SApple OSS Distributions 	uuid_unparse(p_uuid, uuid_string);
2588e7776783SApple OSS Distributions 	new_uuid = OSData::withValue(p_uuid);
2589a5e72196SApple OSS Distributions 	kext->setDriverKitUUID(new_uuid);
2590a5e72196SApple OSS Distributions }
2591a5e72196SApple OSS Distributions 
2592bb611c8fSApple OSS Distributions void
setDriverKitStatistics(OSKext * kext)25935c2921b0SApple OSS Distributions IOUserServer::setDriverKitStatistics(OSKext *kext)
25945c2921b0SApple OSS Distributions {
25955c2921b0SApple OSS Distributions 	OSDextStatistics * statistics = kext->copyDextStatistics();
25965c2921b0SApple OSS Distributions 	if (statistics == NULL) {
25975c2921b0SApple OSS Distributions 		panic("Kext %s was not a DriverKit OSKext", kext->getIdentifierCString());
25985c2921b0SApple OSS Distributions 	}
25995c2921b0SApple OSS Distributions 	fStatistics = statistics;
26005c2921b0SApple OSS Distributions }
26015c2921b0SApple OSS Distributions 
26028d741a5dSApple OSS Distributions IOReturn
setCheckInToken(IOUserServerCheckInToken * token)2603bb611c8fSApple OSS Distributions IOUserServer::setCheckInToken(IOUserServerCheckInToken *token)
2604a5e72196SApple OSS Distributions {
26058d741a5dSApple OSS Distributions 	IOReturn ret = kIOReturnError;
2606bb611c8fSApple OSS Distributions 	if (token != NULL && fCheckInToken == NULL) {
2607bb611c8fSApple OSS Distributions 		token->retain();
2608bb611c8fSApple OSS Distributions 		fCheckInToken = token;
26098d741a5dSApple OSS Distributions 		ret = fCheckInToken->complete();
2610aca3beaaSApple OSS Distributions 		iokit_clear_registered_ports(fOwningTask);
2611a5e72196SApple OSS Distributions 	} else {
2612bb611c8fSApple OSS Distributions 		printf("%s: failed to set check in token. token=%p, fCheckInToken=%p\n", __FUNCTION__, token, fCheckInToken);
2613a5e72196SApple OSS Distributions 	}
26148d741a5dSApple OSS Distributions 	return ret;
2615a5e72196SApple OSS Distributions }
2616a5e72196SApple OSS Distributions 
2617bb611c8fSApple OSS Distributions bool
serviceMatchesCheckInToken(IOUserServerCheckInToken * token)2618bb611c8fSApple OSS Distributions IOUserServer::serviceMatchesCheckInToken(IOUserServerCheckInToken *token)
2619bb611c8fSApple OSS Distributions {
2620bb611c8fSApple OSS Distributions 	if (token != NULL) {
2621e6231be0SApple OSS Distributions 		bool result = token == fCheckInToken;
2622e6231be0SApple OSS Distributions 		return result;
2623bb611c8fSApple OSS Distributions 	} else {
2624bb611c8fSApple OSS Distributions 		printf("%s: null check in token\n", __FUNCTION__);
2625bb611c8fSApple OSS Distributions 		return false;
2626bb611c8fSApple OSS Distributions 	}
2627a5e72196SApple OSS Distributions }
2628a5e72196SApple OSS Distributions 
2629e6231be0SApple OSS Distributions // entitlements - dict of entitlements to check
2630e6231be0SApple OSS Distributions // prop - string - if present return true
2631e6231be0SApple OSS Distributions //      - array of strings - if any present return true
2632e6231be0SApple OSS Distributions //      - array of arrays of strings - in each leaf array all must be present
2633e6231be0SApple OSS Distributions //                                   - if any top level array succeeds return true
2634e6231be0SApple OSS Distributions // consumes one reference of prop
2635a5e72196SApple OSS Distributions bool
checkEntitlements(OSDictionary * entitlements,OSObject * prop,IOService * provider,IOService * dext)2636a5e72196SApple OSS Distributions IOUserServer::checkEntitlements(
2637a5e72196SApple OSS Distributions 	OSDictionary * entitlements, OSObject * prop,
2638a5e72196SApple OSS Distributions 	IOService * provider, IOService * dext)
2639a5e72196SApple OSS Distributions {
2640a5e72196SApple OSS Distributions 	OSDictionary * matching;
2641a5e72196SApple OSS Distributions 
2642a5e72196SApple OSS Distributions 	if (!prop) {
2643a5e72196SApple OSS Distributions 		return true;
2644a5e72196SApple OSS Distributions 	}
2645a5e72196SApple OSS Distributions 	if (!entitlements) {
2646e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(prop);
2647a5e72196SApple OSS Distributions 		return false;
2648a5e72196SApple OSS Distributions 	}
2649a5e72196SApple OSS Distributions 
2650a5e72196SApple OSS Distributions 	matching = NULL;
2651a5e72196SApple OSS Distributions 	if (dext) {
2652a5e72196SApple OSS Distributions 		matching = dext->dictionaryWithProperties();
2653a5e72196SApple OSS Distributions 		if (!matching) {
2654e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(prop);
2655a5e72196SApple OSS Distributions 			return false;
2656a5e72196SApple OSS Distributions 		}
2657a5e72196SApple OSS Distributions 	}
2658a5e72196SApple OSS Distributions 
26591031c584SApple OSS Distributions 	bool allPresent __block = false;
2660a5e72196SApple OSS Distributions 	prop->iterateObjects(^bool (OSObject * object) {
2661a5e72196SApple OSS Distributions 		allPresent = false;
2662a5e72196SApple OSS Distributions 		object->iterateObjects(^bool (OSObject * object) {
2663a5e72196SApple OSS Distributions 			OSString * string;
2664a5e72196SApple OSS Distributions 			OSObject * value;
2665a5e72196SApple OSS Distributions 			string = OSDynamicCast(OSString, object);
2666a5e72196SApple OSS Distributions 			value = entitlements->getObject(string);
2667a5e72196SApple OSS Distributions 			if (matching && value) {
2668a5e72196SApple OSS Distributions 			        matching->setObject(string, value);
2669a5e72196SApple OSS Distributions 			}
2670a5e72196SApple OSS Distributions 			allPresent = (NULL != value);
2671e6231be0SApple OSS Distributions 			// early terminate if not found
2672a5e72196SApple OSS Distributions 			return !allPresent;
2673a5e72196SApple OSS Distributions 		});
2674e6231be0SApple OSS Distributions 		// early terminate if found
2675a5e72196SApple OSS Distributions 		return allPresent;
2676a5e72196SApple OSS Distributions 	});
2677a5e72196SApple OSS Distributions 
2678a5e72196SApple OSS Distributions 	if (allPresent && matching && provider) {
2679a5e72196SApple OSS Distributions 		allPresent = provider->matchPropertyTable(matching);
2680a5e72196SApple OSS Distributions 	}
2681a5e72196SApple OSS Distributions 
2682a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(matching);
2683a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(prop);
2684a5e72196SApple OSS Distributions 
2685a5e72196SApple OSS Distributions 	return allPresent;
2686a5e72196SApple OSS Distributions }
2687a5e72196SApple OSS Distributions 
2688a5e72196SApple OSS Distributions bool
checkEntitlements(OSObject * prop,IOService * provider,IOService * dext)26891031c584SApple OSS Distributions IOUserServer::checkEntitlements(OSObject * prop, IOService * provider, IOService * dext)
26901031c584SApple OSS Distributions {
26911031c584SApple OSS Distributions 	return checkEntitlements(fEntitlements, prop, provider, dext);
26921031c584SApple OSS Distributions }
26931031c584SApple OSS Distributions 
26941031c584SApple OSS Distributions bool
checkEntitlements(IOService * provider,IOService * dext)2695a5e72196SApple OSS Distributions IOUserServer::checkEntitlements(IOService * provider, IOService * dext)
2696a5e72196SApple OSS Distributions {
2697a5e72196SApple OSS Distributions 	OSObject     * prop;
2698a5e72196SApple OSS Distributions 	bool           ok;
2699a5e72196SApple OSS Distributions 
2700a5e72196SApple OSS Distributions 	if (!fOwningTask) {
2701a5e72196SApple OSS Distributions 		return false;
2702a5e72196SApple OSS Distributions 	}
2703a5e72196SApple OSS Distributions 
2704a5e72196SApple OSS Distributions 	prop = provider->copyProperty(gIOServiceDEXTEntitlementsKey);
2705a5e72196SApple OSS Distributions 	ok = checkEntitlements(fEntitlements, prop, provider, dext);
2706a5e72196SApple OSS Distributions 	if (!ok) {
2707a5e72196SApple OSS Distributions 		DKLOG(DKS ": provider entitlements check failed\n", DKN(dext));
2708a5e72196SApple OSS Distributions 	}
2709a5e72196SApple OSS Distributions 	if (ok) {
2710a5e72196SApple OSS Distributions 		prop = dext->copyProperty(gIOServiceDEXTEntitlementsKey);
2711a5e72196SApple OSS Distributions 		ok = checkEntitlements(fEntitlements, prop, NULL, NULL);
2712a5e72196SApple OSS Distributions 		if (!ok) {
2713a5e72196SApple OSS Distributions 			DKLOG(DKS ": family entitlements check failed\n", DKN(dext));
2714a5e72196SApple OSS Distributions 		}
2715a5e72196SApple OSS Distributions 	}
2716a5e72196SApple OSS Distributions 
2717a5e72196SApple OSS Distributions 	return ok;
2718a5e72196SApple OSS Distributions }
2719a5e72196SApple OSS Distributions 
2720a5e72196SApple OSS Distributions IOReturn
exit(const char * reason)2721a5e72196SApple OSS Distributions IOUserServer::exit(const char * reason)
2722a5e72196SApple OSS Distributions {
2723a5e72196SApple OSS Distributions 	DKLOG("%s::exit(%s)\n", getName(), reason);
2724a5e72196SApple OSS Distributions 	Exit(reason);
2725a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2726a5e72196SApple OSS Distributions }
2727a5e72196SApple OSS Distributions 
27285c2921b0SApple OSS Distributions IOReturn
kill(const char * reason)27295c2921b0SApple OSS Distributions IOUserServer::kill(const char * reason)
27305c2921b0SApple OSS Distributions {
27315c2921b0SApple OSS Distributions 	IOReturn ret = kIOReturnError;
27325c2921b0SApple OSS Distributions 	if (fOwningTask != NULL) {
27335c2921b0SApple OSS Distributions 		DKLOG("%s::kill(%s)\n", getName(), reason);
27345c2921b0SApple OSS Distributions 		task_bsdtask_kill(fOwningTask);
27355c2921b0SApple OSS Distributions 		ret = kIOReturnSuccess;
27365c2921b0SApple OSS Distributions 	}
27375c2921b0SApple OSS Distributions 	return ret;
27385c2921b0SApple OSS Distributions }
27395c2921b0SApple OSS Distributions 
2740a5e72196SApple OSS Distributions OSObjectUserVars *
varsForObject(OSObject * obj)2741a5e72196SApple OSS Distributions IOUserServer::varsForObject(OSObject * obj)
2742a5e72196SApple OSS Distributions {
2743a5e72196SApple OSS Distributions 	IOService * service;
2744a5e72196SApple OSS Distributions 
2745a5e72196SApple OSS Distributions 	if ((service = OSDynamicCast(IOService, obj))) {
2746a5e72196SApple OSS Distributions 		return service->reserved->uvars;
2747a5e72196SApple OSS Distributions 	}
2748a5e72196SApple OSS Distributions 
2749a5e72196SApple OSS Distributions 	return NULL;
2750a5e72196SApple OSS Distributions }
2751a5e72196SApple OSS Distributions 
2752a5e72196SApple OSS Distributions IOPStrings *
copyInStringArray(const char * string,uint32_t userSize)2753a5e72196SApple OSS Distributions IOUserServer::copyInStringArray(const char * string, uint32_t userSize)
2754a5e72196SApple OSS Distributions {
2755a5e72196SApple OSS Distributions 	IOPStrings * array;
2756a5e72196SApple OSS Distributions 	vm_size_t    alloc;
2757a5e72196SApple OSS Distributions 	size_t       len;
2758a5e72196SApple OSS Distributions 	const char * end;
27595c2921b0SApple OSS Distributions 	OSBoundedPtr<const char> cstr;
2760a5e72196SApple OSS Distributions 
2761a5e72196SApple OSS Distributions 	if (userSize <= 1) {
2762a5e72196SApple OSS Distributions 		return NULL;
2763a5e72196SApple OSS Distributions 	}
2764a5e72196SApple OSS Distributions 
2765a5e72196SApple OSS Distributions 	if (os_add_overflow(sizeof(IOPStrings), userSize, &alloc)) {
2766a5e72196SApple OSS Distributions 		assert(false);
2767a5e72196SApple OSS Distributions 		return NULL;
2768a5e72196SApple OSS Distributions 	}
2769a5e72196SApple OSS Distributions 	if (alloc > 16384) {
2770a5e72196SApple OSS Distributions 		assert(false);
2771a5e72196SApple OSS Distributions 		return NULL;
2772a5e72196SApple OSS Distributions 	}
2773e6231be0SApple OSS Distributions 	array = (typeof(array))IOMallocData(alloc);
2774a5e72196SApple OSS Distributions 	if (!array) {
2775a5e72196SApple OSS Distributions 		return NULL;
2776a5e72196SApple OSS Distributions 	}
2777a5e72196SApple OSS Distributions 	array->dataSize = userSize;
2778a5e72196SApple OSS Distributions 	bcopy(string, (void *) &array->strings[0], userSize);
2779a5e72196SApple OSS Distributions 
2780a5e72196SApple OSS Distributions 	array->count = 0;
2781a5e72196SApple OSS Distributions 	end =  &array->strings[array->dataSize];
27825c2921b0SApple OSS Distributions 	cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end);
2783bb611c8fSApple OSS Distributions 	while ((len = (unsigned char)cstr[0])) {
2784a5e72196SApple OSS Distributions 		cstr++;
2785a5e72196SApple OSS Distributions 		if ((cstr + len) >= end) {
2786a5e72196SApple OSS Distributions 			break;
2787a5e72196SApple OSS Distributions 		}
2788a5e72196SApple OSS Distributions 		cstr += len;
2789a5e72196SApple OSS Distributions 		array->count++;
2790a5e72196SApple OSS Distributions 	}
2791a5e72196SApple OSS Distributions 	if (len) {
2792e6231be0SApple OSS Distributions 		IOFreeData(array, alloc);
2793a5e72196SApple OSS Distributions 		array = NULL;
2794a5e72196SApple OSS Distributions 	}
2795a5e72196SApple OSS Distributions 
2796a5e72196SApple OSS Distributions 	return array;
2797a5e72196SApple OSS Distributions }
2798a5e72196SApple OSS Distributions 
2799a5e72196SApple OSS Distributions uint32_t
stringArrayIndex(IOPStrings * array,const char * look)2800a5e72196SApple OSS Distributions IOUserServer::stringArrayIndex(IOPStrings * array, const char * look)
2801a5e72196SApple OSS Distributions {
2802a5e72196SApple OSS Distributions 	uint32_t     idx;
2803a5e72196SApple OSS Distributions 	size_t       len, llen;
28045c2921b0SApple OSS Distributions 	OSBoundedPtr<const char> cstr;
2805a5e72196SApple OSS Distributions 	const char * end;
2806a5e72196SApple OSS Distributions 
2807a5e72196SApple OSS Distributions 	idx  = 0;
2808a5e72196SApple OSS Distributions 	end  =  &array->strings[array->dataSize];
28095c2921b0SApple OSS Distributions 	cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end);
28105c2921b0SApple OSS Distributions 
2811a5e72196SApple OSS Distributions 	llen = strlen(look);
2812bb611c8fSApple OSS Distributions 	while ((len = (unsigned char)cstr[0])) {
2813a5e72196SApple OSS Distributions 		cstr++;
2814a5e72196SApple OSS Distributions 		if ((cstr + len) >= end) {
2815a5e72196SApple OSS Distributions 			break;
2816a5e72196SApple OSS Distributions 		}
28175c2921b0SApple OSS Distributions 		if ((len == llen) && !strncmp(cstr.discard_bounds(), look, len)) {
2818a5e72196SApple OSS Distributions 			return idx;
2819a5e72196SApple OSS Distributions 		}
2820a5e72196SApple OSS Distributions 		cstr += len;
2821a5e72196SApple OSS Distributions 		idx++;
2822a5e72196SApple OSS Distributions 	}
2823a5e72196SApple OSS Distributions 
2824a5e72196SApple OSS Distributions 	return -1U;
2825a5e72196SApple OSS Distributions }
2826a5e72196SApple OSS Distributions #define kIODispatchQueueStopped ((IODispatchQueue *) -1L)
2827a5e72196SApple OSS Distributions 
2828a5e72196SApple OSS Distributions IODispatchQueue *
queueForObject(OSObject * obj,uint64_t msgid)2829a5e72196SApple OSS Distributions IOUserServer::queueForObject(OSObject * obj, uint64_t msgid)
2830a5e72196SApple OSS Distributions {
2831a5e72196SApple OSS Distributions 	IODispatchQueue  * queue;
2832a5e72196SApple OSS Distributions 	OSObjectUserVars * uvars;
2833a5e72196SApple OSS Distributions 	uint64_t           option;
2834a5e72196SApple OSS Distributions 
2835a5e72196SApple OSS Distributions 	uvars = varsForObject(obj);
2836a5e72196SApple OSS Distributions 	if (!uvars) {
2837a5e72196SApple OSS Distributions 		return NULL;
2838a5e72196SApple OSS Distributions 	}
2839a5e72196SApple OSS Distributions 	if (!uvars->queueArray) {
2840a5e72196SApple OSS Distributions 		if (uvars->stopped) {
2841a5e72196SApple OSS Distributions 			return kIODispatchQueueStopped;
2842a5e72196SApple OSS Distributions 		}
2843a5e72196SApple OSS Distributions 		return NULL;
2844a5e72196SApple OSS Distributions 	}
2845a5e72196SApple OSS Distributions 	queue = uvars->queueArray[0];
2846a5e72196SApple OSS Distributions 
2847a5e72196SApple OSS Distributions 	if (uvars->userMeta
2848a5e72196SApple OSS Distributions 	    && uvars->userMeta->methods) {
2849a5e72196SApple OSS Distributions 		uint32_t idx, baseIdx;
2850a5e72196SApple OSS Distributions 		uint32_t lim;
2851a5e72196SApple OSS Distributions 		// bsearch
2852a5e72196SApple OSS Distributions 		for (baseIdx = 0, lim = uvars->userMeta->methodCount; lim; lim >>= 1) {
2853a5e72196SApple OSS Distributions 			idx = baseIdx + (lim >> 1);
2854a5e72196SApple OSS Distributions 			if (msgid == uvars->userMeta->methods[idx]) {
2855a5e72196SApple OSS Distributions 				option = uvars->userMeta->methods[uvars->userMeta->methodCount + idx];
2856a5e72196SApple OSS Distributions 				option &= 0xFF;
2857a5e72196SApple OSS Distributions 				if (option < uvars->userMeta->queueNames->count) {
2858a5e72196SApple OSS Distributions 					queue = uvars->queueArray[option + 1];
2859a5e72196SApple OSS Distributions 				}
2860a5e72196SApple OSS Distributions 				break;
2861a5e72196SApple OSS Distributions 			} else if (msgid > uvars->userMeta->methods[idx]) {
2862a5e72196SApple OSS Distributions 				// move right
2863a5e72196SApple OSS Distributions 				baseIdx += (lim >> 1) + 1;
2864a5e72196SApple OSS Distributions 				lim--;
2865a5e72196SApple OSS Distributions 			}
2866a5e72196SApple OSS Distributions 			// else move left
2867a5e72196SApple OSS Distributions 		}
2868a5e72196SApple OSS Distributions 	}
2869a5e72196SApple OSS Distributions 	return queue;
2870a5e72196SApple OSS Distributions }
2871a5e72196SApple OSS Distributions 
2872a5e72196SApple OSS Distributions IOReturn
objectInstantiate(OSObject * obj,IORPC rpc,IORPCMessage * message)2873a5e72196SApple OSS Distributions IOUserServer::objectInstantiate(OSObject * obj, IORPC rpc, IORPCMessage * message)
2874a5e72196SApple OSS Distributions {
2875a5e72196SApple OSS Distributions 	IOReturn         ret;
2876a5e72196SApple OSS Distributions 	OSString       * str;
2877a5e72196SApple OSS Distributions 	OSObject       * prop;
2878a5e72196SApple OSS Distributions 	IOService      * service;
2879a5e72196SApple OSS Distributions 
2880a5e72196SApple OSS Distributions 	OSAction       * action;
2881a5e72196SApple OSS Distributions 	OSObject       * target;
2882a5e72196SApple OSS Distributions 	uint32_t         queueCount, queueAlloc;
2883a5e72196SApple OSS Distributions 	const char     * resultClassName;
2884a5e72196SApple OSS Distributions 	uint64_t         resultFlags;
2885a5e72196SApple OSS Distributions 
2886bb611c8fSApple OSS Distributions 	mach_msg_size_t    replySize;
2887a5e72196SApple OSS Distributions 	uint32_t           methodCount;
2888a5e72196SApple OSS Distributions 	const uint64_t   * methods;
2889a5e72196SApple OSS Distributions 	IODispatchQueue  * queue;
2890a5e72196SApple OSS Distributions 	OSUserMetaClass  * userMeta;
2891a5e72196SApple OSS Distributions 	OSObjectUserVars * uvars;
2892a5e72196SApple OSS Distributions 	uint32_t           idx;
2893a5e72196SApple OSS Distributions 	ipc_port_t         sendPort;
28948d741a5dSApple OSS Distributions 	bool               serviceInactive;
2895a5e72196SApple OSS Distributions 
2896a5e72196SApple OSS Distributions 	OSObject_Instantiate_Rpl_Content * reply;
28975c2921b0SApple OSS Distributions 	IODispatchQueue ** unboundedQueueArray = NULL;
2898a5e72196SApple OSS Distributions 	queueCount      = 0;
2899a5e72196SApple OSS Distributions 	methodCount     = 0;
2900a5e72196SApple OSS Distributions 	methods         = NULL;
2901a5e72196SApple OSS Distributions 	str             = NULL;
2902a5e72196SApple OSS Distributions 	prop            = NULL;
2903a5e72196SApple OSS Distributions 	userMeta        = NULL;
2904a5e72196SApple OSS Distributions 	resultClassName = NULL;
2905a5e72196SApple OSS Distributions 	resultFlags     = 0;
2906a5e72196SApple OSS Distributions 	ret = kIOReturnUnsupportedMode;
2907a5e72196SApple OSS Distributions 
2908a5e72196SApple OSS Distributions 	service = OSDynamicCast(IOService, obj);
2909bb611c8fSApple OSS Distributions 	action = OSDynamicCast(OSAction, obj);
2910a5e72196SApple OSS Distributions 	if (!service) {
2911a5e72196SApple OSS Distributions 		// xxx other classes hosted
2912a5e72196SApple OSS Distributions 		resultFlags |= kOSObjectRPCKernel;
2913a5e72196SApple OSS Distributions 		resultFlags |= kOSObjectRPCRemote;
2914a5e72196SApple OSS Distributions 	} else {
29158d741a5dSApple OSS Distributions 		serviceInactive = false;
29168d741a5dSApple OSS Distributions 		if (service->lockForArbitration()) {
29178d741a5dSApple OSS Distributions 			if (service->isInactive() && (service->__state[1] & kIOServiceStartState) == 0) {
29188d741a5dSApple OSS Distributions 				serviceInactive = true;
29198d741a5dSApple OSS Distributions 			}
29208d741a5dSApple OSS Distributions 			service->unlockForArbitration();
29218d741a5dSApple OSS Distributions 		}
29228d741a5dSApple OSS Distributions 		if (serviceInactive) {
2923a5e72196SApple OSS Distributions 			DKLOG(DKS "::instantiate inactive\n", DKN(service));
2924a5e72196SApple OSS Distributions 			return kIOReturnOffline;
2925a5e72196SApple OSS Distributions 		}
2926a5e72196SApple OSS Distributions 		prop = service->copyProperty(gIOUserClassKey);
2927a5e72196SApple OSS Distributions 		str = OSDynamicCast(OSString, prop);
2928a5e72196SApple OSS Distributions 		if (!service->reserved->uvars) {
2929a5e72196SApple OSS Distributions 			resultFlags |= kOSObjectRPCRemote;
2930a5e72196SApple OSS Distributions 			resultFlags |= kOSObjectRPCKernel;
2931a5e72196SApple OSS Distributions 		} else if (this != service->reserved->uvars->userServer) {
2932a5e72196SApple OSS Distributions 			// remote, use base class
2933a5e72196SApple OSS Distributions 			resultFlags |= kOSObjectRPCRemote;
2934a5e72196SApple OSS Distributions 		}
2935a5e72196SApple OSS Distributions 		if (service->reserved->uvars && service->reserved->uvars->userServer) {
2936e6231be0SApple OSS Distributions 			if (!str) {
2937e6231be0SApple OSS Distributions 				DKLOG("no IOUserClass defined for " DKS "\n", DKN(service));
2938e6231be0SApple OSS Distributions 				OSSafeReleaseNULL(prop);
2939e6231be0SApple OSS Distributions 				return kIOReturnError;
2940e6231be0SApple OSS Distributions 			}
2941bb611c8fSApple OSS Distributions 			IOLockLock(service->reserved->uvars->userServer->fLock);
2942a5e72196SApple OSS Distributions 			userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str);
2943bb611c8fSApple OSS Distributions 			IOLockUnlock(service->reserved->uvars->userServer->fLock);
2944a5e72196SApple OSS Distributions 		}
2945a5e72196SApple OSS Distributions 	}
2946a5e72196SApple OSS Distributions 	if (!str && !userMeta) {
2947a5e72196SApple OSS Distributions 		const OSMetaClass * meta;
2948a5e72196SApple OSS Distributions 		meta = obj->getMetaClass();
2949bb611c8fSApple OSS Distributions 		IOLockLock(fLock);
2950bb611c8fSApple OSS Distributions 		if (action) {
2951bb611c8fSApple OSS Distributions 			str = action->ivars->typeName;
2952bb611c8fSApple OSS Distributions 			if (str) {
2953bb611c8fSApple OSS Distributions 				userMeta = (typeof(userMeta))fClasses->getObject(str);
2954bb611c8fSApple OSS Distributions 			}
2955bb611c8fSApple OSS Distributions 		}
2956a5e72196SApple OSS Distributions 		while (meta && !userMeta) {
2957a5e72196SApple OSS Distributions 			str = (OSString *) meta->getClassNameSymbol();
2958a5e72196SApple OSS Distributions 			userMeta = (typeof(userMeta))fClasses->getObject(str);
2959a5e72196SApple OSS Distributions 			if (!userMeta) {
2960a5e72196SApple OSS Distributions 				meta = meta->getSuperClass();
2961a5e72196SApple OSS Distributions 			}
2962a5e72196SApple OSS Distributions 		}
2963bb611c8fSApple OSS Distributions 		IOLockUnlock(fLock);
2964a5e72196SApple OSS Distributions 	}
2965a5e72196SApple OSS Distributions 	if (str) {
2966a5e72196SApple OSS Distributions 		if (!userMeta) {
2967bb611c8fSApple OSS Distributions 			IOLockLock(fLock);
2968a5e72196SApple OSS Distributions 			userMeta = (typeof(userMeta))fClasses->getObject(str);
2969bb611c8fSApple OSS Distributions 			IOLockUnlock(fLock);
2970a5e72196SApple OSS Distributions 		}
2971a5e72196SApple OSS Distributions 		if (kIODKLogSetup & gIODKDebug) {
2972a5e72196SApple OSS Distributions 			DKLOG("userMeta %s %p\n", str->getCStringNoCopy(), userMeta);
2973a5e72196SApple OSS Distributions 		}
2974a5e72196SApple OSS Distributions 		if (userMeta) {
2975a5e72196SApple OSS Distributions 			if (kOSObjectRPCRemote & resultFlags) {
2976bb611c8fSApple OSS Distributions 				if (!action) {
2977bb611c8fSApple OSS Distributions 					/* Special case: For OSAction subclasses, do not use the superclass */
2978a5e72196SApple OSS Distributions 					while (userMeta && !(kOSClassCanRemote & userMeta->description->flags)) {
2979a5e72196SApple OSS Distributions 						userMeta = userMeta->superMeta;
2980a5e72196SApple OSS Distributions 					}
2981bb611c8fSApple OSS Distributions 				}
2982a5e72196SApple OSS Distributions 				if (userMeta) {
2983a5e72196SApple OSS Distributions 					resultClassName = userMeta->description->name;
2984a5e72196SApple OSS Distributions 					ret = kIOReturnSuccess;
2985a5e72196SApple OSS Distributions 				}
2986a5e72196SApple OSS Distributions 			} else {
2987a5e72196SApple OSS Distributions 				service->reserved->uvars->userMeta = userMeta;
2988a5e72196SApple OSS Distributions 				queueAlloc = 1;
2989a5e72196SApple OSS Distributions 				if (userMeta->queueNames) {
2990a5e72196SApple OSS Distributions 					queueAlloc += userMeta->queueNames->count;
2991a5e72196SApple OSS Distributions 				}
29925c2921b0SApple OSS Distributions 				unboundedQueueArray = IONewZero(IODispatchQueue *, queueAlloc);
2993a5e72196SApple OSS Distributions 				service->reserved->uvars->queueArray =
29945c2921b0SApple OSS Distributions 				    OSBoundedArrayRef<IODispatchQueue *>(unboundedQueueArray, queueAlloc);
2995a5e72196SApple OSS Distributions 				resultClassName = str->getCStringNoCopy();
2996a5e72196SApple OSS Distributions 				ret = kIOReturnSuccess;
2997a5e72196SApple OSS Distributions 			}
2998bb611c8fSApple OSS Distributions 		} else if (kIODKLogSetup & gIODKDebug) {
2999bb611c8fSApple OSS Distributions 			DKLOG("userMeta %s was not found in fClasses\n", str->getCStringNoCopy());
3000bb611c8fSApple OSS Distributions 			IOLockLock(fLock);
3001bb611c8fSApple OSS Distributions 			fClasses->iterateObjects(^bool (const OSSymbol * key, OSObject * val) {
3002bb611c8fSApple OSS Distributions 				DKLOG(" fClasses[\"%s\"] => %p\n", key->getCStringNoCopy(), val);
3003bb611c8fSApple OSS Distributions 				return false;
3004bb611c8fSApple OSS Distributions 			});
3005bb611c8fSApple OSS Distributions 			IOLockUnlock(fLock);
3006a5e72196SApple OSS Distributions 		}
3007a5e72196SApple OSS Distributions 	}
3008a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(prop);
3009a5e72196SApple OSS Distributions 
3010a5e72196SApple OSS Distributions 	IORPCMessageMach * machReply = rpc.reply;
3011a5e72196SApple OSS Distributions 	replySize = sizeof(OSObject_Instantiate_Rpl);
3012a5e72196SApple OSS Distributions 
3013a5e72196SApple OSS Distributions 	if ((kIOReturnSuccess == ret) && (kOSObjectRPCRemote & resultFlags)) {
3014a5e72196SApple OSS Distributions 		target = obj;
3015bb611c8fSApple OSS Distributions 		if (action) {
3016a5e72196SApple OSS Distributions 			if (action->ivars->referenceSize) {
3017a5e72196SApple OSS Distributions 				resultFlags |= kOSObjectRPCKernel;
3018a5e72196SApple OSS Distributions 			} else {
3019a5e72196SApple OSS Distributions 				resultFlags &= ~kOSObjectRPCKernel;
3020e6231be0SApple OSS Distributions 				if (action->ivars->target) {
3021a5e72196SApple OSS Distributions 					target = action->ivars->target;
3022a5e72196SApple OSS Distributions 					queueCount = 1;
3023a5e72196SApple OSS Distributions 					queue = queueForObject(target, action->ivars->targetmsgid);
3024e6231be0SApple OSS Distributions 					if (!queue && action->ivars->userServer) {
3025e6231be0SApple OSS Distributions 						queue = action->ivars->userServer->fRootQueue;
3026e6231be0SApple OSS Distributions 					}
3027a5e72196SApple OSS Distributions 					idx = 0;
3028a5e72196SApple OSS Distributions 					sendPort = NULL;
3029a5e72196SApple OSS Distributions 					if (queue && (kIODispatchQueueStopped != queue)) {
30305c2921b0SApple OSS Distributions 						sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort);
3031a5e72196SApple OSS Distributions 					}
3032a5e72196SApple OSS Distributions 					replySize = sizeof(OSObject_Instantiate_Rpl)
3033a5e72196SApple OSS Distributions 					    + queueCount * sizeof(machReply->objects[0])
3034a5e72196SApple OSS Distributions 					    + 2 * methodCount * sizeof(reply->methods[0]);
3035a5e72196SApple OSS Distributions 					if (replySize > rpc.replySize) {
3036a5e72196SApple OSS Distributions 						assert(false);
3037a5e72196SApple OSS Distributions 						return kIOReturnIPCError;
3038a5e72196SApple OSS Distributions 					}
3039a5e72196SApple OSS Distributions 					machReply->objects[idx].type        = MACH_MSG_PORT_DESCRIPTOR;
3040a5e72196SApple OSS Distributions 					machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND;
3041a5e72196SApple OSS Distributions 					machReply->objects[idx].name        = sendPort;
3042a5e72196SApple OSS Distributions 					machReply->objects[idx].pad2        = 0;
3043a5e72196SApple OSS Distributions 					machReply->objects[idx].pad_end     = 0;
3044a5e72196SApple OSS Distributions 				}
3045e6231be0SApple OSS Distributions 			}
3046a5e72196SApple OSS Distributions 		} else {
3047a5e72196SApple OSS Distributions 			uvars = varsForObject(target);
3048a5e72196SApple OSS Distributions 			if (uvars && uvars->userMeta) {
3049a5e72196SApple OSS Distributions 				queueCount = 1;
3050a5e72196SApple OSS Distributions 				if (uvars->userMeta->queueNames) {
3051a5e72196SApple OSS Distributions 					queueCount += uvars->userMeta->queueNames->count;
3052a5e72196SApple OSS Distributions 				}
3053a5e72196SApple OSS Distributions 				methods = &uvars->userMeta->methods[0];
3054a5e72196SApple OSS Distributions 				methodCount = uvars->userMeta->methodCount;
3055a5e72196SApple OSS Distributions 				replySize = sizeof(OSObject_Instantiate_Rpl)
3056a5e72196SApple OSS Distributions 				    + queueCount * sizeof(machReply->objects[0])
3057a5e72196SApple OSS Distributions 				    + 2 * methodCount * sizeof(reply->methods[0]);
3058a5e72196SApple OSS Distributions 				if (replySize > rpc.replySize) {
3059a5e72196SApple OSS Distributions 					assert(false);
3060a5e72196SApple OSS Distributions 					return kIOReturnIPCError;
3061a5e72196SApple OSS Distributions 				}
3062a5e72196SApple OSS Distributions 				for (idx = 0; idx < queueCount; idx++) {
3063a5e72196SApple OSS Distributions 					queue = uvars->queueArray[idx];
3064a5e72196SApple OSS Distributions 					sendPort = NULL;
3065a5e72196SApple OSS Distributions 					if (queue) {
30665c2921b0SApple OSS Distributions 						sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort);
3067a5e72196SApple OSS Distributions 					}
3068a5e72196SApple OSS Distributions 					machReply->objects[idx].type        = MACH_MSG_PORT_DESCRIPTOR;
3069a5e72196SApple OSS Distributions 					machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND;
3070a5e72196SApple OSS Distributions 					machReply->objects[idx].name        = sendPort;
3071a5e72196SApple OSS Distributions 					machReply->objects[idx].pad2        = 0;
3072a5e72196SApple OSS Distributions 					machReply->objects[idx].pad_end     = 0;
3073a5e72196SApple OSS Distributions 				}
3074a5e72196SApple OSS Distributions 			}
3075a5e72196SApple OSS Distributions 		}
3076a5e72196SApple OSS Distributions 	}
3077a5e72196SApple OSS Distributions 
3078a5e72196SApple OSS Distributions 	if (kIODKLogIPC & gIODKDebug) {
3079bb611c8fSApple OSS Distributions 		DKLOG("instantiate object %s with user class %s\n", obj->getMetaClass()->getClassName(), str ? str->getCStringNoCopy() : "(null)");
3080a5e72196SApple OSS Distributions 	}
3081a5e72196SApple OSS Distributions 
3082a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != ret) {
3083a5e72196SApple OSS Distributions 		DKLOG("%s: no user class found\n", str ? str->getCStringNoCopy() : obj->getMetaClass()->getClassName());
3084a5e72196SApple OSS Distributions 		resultClassName = "unknown";
3085a5e72196SApple OSS Distributions 	}
3086a5e72196SApple OSS Distributions 
3087a5e72196SApple OSS Distributions 	machReply->msgh.msgh_id                    = kIORPCVersionCurrentReply;
3088a5e72196SApple OSS Distributions 	machReply->msgh.msgh_size                  = replySize;
3089a5e72196SApple OSS Distributions 	machReply->msgh_body.msgh_descriptor_count = queueCount;
3090a5e72196SApple OSS Distributions 
309194d3b452SApple OSS Distributions 	reply = (typeof(reply))IORPCMessageFromMachReply(machReply);
3092a5e72196SApple OSS Distributions 	if (!reply) {
3093a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
3094a5e72196SApple OSS Distributions 	}
3095a5e72196SApple OSS Distributions 	if (methodCount) {
3096a5e72196SApple OSS Distributions 		bcopy(methods, &reply->methods[0], methodCount * 2 * sizeof(reply->methods[0]));
3097a5e72196SApple OSS Distributions 	}
3098a5e72196SApple OSS Distributions 	reply->__hdr.msgid       = OSObject_Instantiate_ID;
3099a5e72196SApple OSS Distributions 	reply->__hdr.flags       = kIORPCMessageOneway;
3100a5e72196SApple OSS Distributions 	reply->__hdr.objectRefs  = 0;
3101a5e72196SApple OSS Distributions 	reply->__pad             = 0;
3102a5e72196SApple OSS Distributions 	reply->flags             = resultFlags;
3103a5e72196SApple OSS Distributions 	strlcpy(reply->classname, resultClassName, sizeof(reply->classname));
3104a5e72196SApple OSS Distributions 	reply->__result          = ret;
3105a5e72196SApple OSS Distributions 
3106a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
3107a5e72196SApple OSS Distributions 
3108a5e72196SApple OSS Distributions 	return ret;
3109a5e72196SApple OSS Distributions }
3110a5e72196SApple OSS Distributions 
3111bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3112a5e72196SApple OSS Distributions 
3113a5e72196SApple OSS Distributions IOReturn
kernelDispatch(OSObject * obj,IORPC rpc)3114a5e72196SApple OSS Distributions IOUserServer::kernelDispatch(OSObject * obj, IORPC rpc)
3115a5e72196SApple OSS Distributions {
3116a5e72196SApple OSS Distributions 	IOReturn       ret;
3117a5e72196SApple OSS Distributions 	IORPCMessage * message;
3118a5e72196SApple OSS Distributions 
311994d3b452SApple OSS Distributions 	message = rpc.kernelContent;
3120a5e72196SApple OSS Distributions 	if (!message) {
3121a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
3122a5e72196SApple OSS Distributions 	}
3123a5e72196SApple OSS Distributions 
3124a5e72196SApple OSS Distributions 	if (OSObject_Instantiate_ID == message->msgid) {
3125a5e72196SApple OSS Distributions 		ret = objectInstantiate(obj, rpc, message);
3126a5e72196SApple OSS Distributions 		if (kIOReturnSuccess != ret) {
3127a5e72196SApple OSS Distributions 			DKLOG("%s: instantiate failed 0x%x\n", obj->getMetaClass()->getClassName(), ret);
3128a5e72196SApple OSS Distributions 		}
3129a5e72196SApple OSS Distributions 	} else {
3130a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3131a5e72196SApple OSS Distributions 			DKLOG("%s::Dispatch kernel 0x%qx\n", obj->getMetaClass()->getClassName(), message->msgid);
3132a5e72196SApple OSS Distributions 		}
3133a5e72196SApple OSS Distributions 		ret = obj->Dispatch(rpc);
3134a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3135a5e72196SApple OSS Distributions 			DKLOG("%s::Dispatch kernel 0x%qx result 0x%x\n", obj->getMetaClass()->getClassName(), message->msgid, ret);
3136a5e72196SApple OSS Distributions 		}
3137a5e72196SApple OSS Distributions 	}
3138a5e72196SApple OSS Distributions 
3139a5e72196SApple OSS Distributions 	return ret;
3140a5e72196SApple OSS Distributions }
3141a5e72196SApple OSS Distributions 
3142a5e72196SApple OSS Distributions 
3143bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3144a5e72196SApple OSS Distributions 
3145a5e72196SApple OSS Distributions OSObject *
target(OSAction * action,IORPCMessage * message)3146a5e72196SApple OSS Distributions IOUserServer::target(OSAction * action, IORPCMessage * message)
3147a5e72196SApple OSS Distributions {
3148a5e72196SApple OSS Distributions 	OSObject * object;
3149a5e72196SApple OSS Distributions 
3150a5e72196SApple OSS Distributions 	if (message->msgid != action->ivars->msgid) {
3151a5e72196SApple OSS Distributions 		return action;
3152a5e72196SApple OSS Distributions 	}
3153a5e72196SApple OSS Distributions 	object = action->ivars->target;
3154e6231be0SApple OSS Distributions 	if (!object) {
3155e6231be0SApple OSS Distributions 		return action;
3156e6231be0SApple OSS Distributions 	}
3157a5e72196SApple OSS Distributions 	message->msgid      = action->ivars->targetmsgid;
3158a5e72196SApple OSS Distributions 	message->objects[0] = (OSObjectRef) object;
3159a5e72196SApple OSS Distributions 	if (kIORPCMessageRemote & message->flags) {
3160a5e72196SApple OSS Distributions 		object->retain();
3161bb611c8fSApple OSS Distributions #ifndef __clang_analyzer__
3162bb611c8fSApple OSS Distributions 		// Hide the release of 'action' from the clang static analyzer to suppress
3163bb611c8fSApple OSS Distributions 		// an overrelease diagnostic. The analyzer doesn't have a way to express the
3164bb611c8fSApple OSS Distributions 		// non-standard contract of this method, which is that it releases 'action' when
3165bb611c8fSApple OSS Distributions 		// the message flags have kIORPCMessageRemote set.
3166a5e72196SApple OSS Distributions 		action->release();
3167bb611c8fSApple OSS Distributions #endif
3168a5e72196SApple OSS Distributions 	}
3169a5e72196SApple OSS Distributions 	if (kIODKLogIPC & gIODKDebug) {
3170a5e72196SApple OSS Distributions 		DKLOG("TARGET %s msg 0x%qx from 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid, action->ivars->msgid);
3171a5e72196SApple OSS Distributions 	}
3172a5e72196SApple OSS Distributions 
3173a5e72196SApple OSS Distributions 	return object;
3174a5e72196SApple OSS Distributions }
3175a5e72196SApple OSS Distributions 
3176bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3177a5e72196SApple OSS Distributions 
3178a5e72196SApple OSS Distributions kern_return_t
uext_server(ipc_port_t receiver,ipc_kmsg_t requestkmsg,ipc_kmsg_t * pReply)3179e6231be0SApple OSS Distributions uext_server(ipc_port_t receiver, ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply)
3180a5e72196SApple OSS Distributions {
3181a5e72196SApple OSS Distributions 	kern_return_t      ret;
3182a5e72196SApple OSS Distributions 	OSObject         * object;
3183a5e72196SApple OSS Distributions 	IOUserServer     * server;
3184a5e72196SApple OSS Distributions 
3185e6231be0SApple OSS Distributions 	object = IOUserServer::copyObjectForSendRight(receiver, IKOT_UEXT_OBJECT);
3186a5e72196SApple OSS Distributions 	server = OSDynamicCast(IOUserServer, object);
3187a5e72196SApple OSS Distributions 	if (!server) {
3188a5e72196SApple OSS Distributions 		OSSafeReleaseNULL(object);
3189a5e72196SApple OSS Distributions 		return KERN_INVALID_NAME;
3190a5e72196SApple OSS Distributions 	}
319194d3b452SApple OSS Distributions 
319294d3b452SApple OSS Distributions 	IORPCMessage * message = (typeof(message))ikm_udata_from_header(requestkmsg);
319394d3b452SApple OSS Distributions 
319494d3b452SApple OSS Distributions 	ret = server->server(requestkmsg, message, pReply);
3195a5e72196SApple OSS Distributions 	object->release();
3196a5e72196SApple OSS Distributions 
3197a5e72196SApple OSS Distributions 	return ret;
3198a5e72196SApple OSS Distributions }
3199a5e72196SApple OSS Distributions 
3200e6231be0SApple OSS Distributions /*
3201e6231be0SApple OSS Distributions  * Chosen to hit kalloc zones (as opposed to the VM).
3202e6231be0SApple OSS Distributions  * doesn't include the trailer size which ipc_kmsg_alloc() will add
3203e6231be0SApple OSS Distributions  */
3204a5e72196SApple OSS Distributions #define MAX_UEXT_REPLY_SIZE     0x17c0
3205e6231be0SApple OSS Distributions static_assert(MAX_UEXT_REPLY_SIZE + MAX_TRAILER_SIZE <= KALLOC_SAFE_ALLOC_SIZE);
3206a5e72196SApple OSS Distributions 
3207a5e72196SApple OSS Distributions kern_return_t
server(ipc_kmsg_t requestkmsg,IORPCMessage * message,ipc_kmsg_t * pReply)320894d3b452SApple OSS Distributions IOUserServer::server(ipc_kmsg_t requestkmsg, IORPCMessage * message, ipc_kmsg_t * pReply)
3209a5e72196SApple OSS Distributions {
3210a5e72196SApple OSS Distributions 	kern_return_t      ret;
3211a5e72196SApple OSS Distributions 	mach_msg_size_t    replyAlloc;
3212a5e72196SApple OSS Distributions 	ipc_kmsg_t         replykmsg;
3213a5e72196SApple OSS Distributions 	IORPCMessageMach * msgin;
3214a5e72196SApple OSS Distributions 	IORPCMessageMach * msgout;
3215a5e72196SApple OSS Distributions 	IORPCMessage     * reply;
3216a5e72196SApple OSS Distributions 	uint32_t           replySize;
3217a5e72196SApple OSS Distributions 	OSObject         * object;
3218a5e72196SApple OSS Distributions 	OSAction         * action;
3219a5e72196SApple OSS Distributions 	bool               oneway;
3220a5e72196SApple OSS Distributions 	uint64_t           msgid;
3221a5e72196SApple OSS Distributions 
32225c2921b0SApple OSS Distributions 	msgin   = (typeof(msgin))ikm_header(requestkmsg);
3223a5e72196SApple OSS Distributions 	replyAlloc = 0;
3224a5e72196SApple OSS Distributions 	msgout = NULL;
3225a5e72196SApple OSS Distributions 	replykmsg = NULL;
3226a5e72196SApple OSS Distributions 
3227a5e72196SApple OSS Distributions 	if (msgin->msgh.msgh_size < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) {
3228a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3229a5e72196SApple OSS Distributions 			DKLOG("UEXT notify %o\n", msgin->msgh.msgh_id);
3230a5e72196SApple OSS Distributions 		}
3231a5e72196SApple OSS Distributions 		return KERN_NOT_SUPPORTED;
3232a5e72196SApple OSS Distributions 	}
3233a5e72196SApple OSS Distributions 
3234a5e72196SApple OSS Distributions 	if (!(MACH_MSGH_BITS_COMPLEX & msgin->msgh.msgh_bits)) {
3235a5e72196SApple OSS Distributions 		msgin->msgh_body.msgh_descriptor_count = 0;
3236a5e72196SApple OSS Distributions 	}
3237a5e72196SApple OSS Distributions 	if (!message) {
3238a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
3239a5e72196SApple OSS Distributions 	}
3240bb611c8fSApple OSS Distributions 	if (message->objectRefs == 0) {
3241bb611c8fSApple OSS Distributions 		return kIOReturnIPCError;
3242bb611c8fSApple OSS Distributions 	}
3243a5e72196SApple OSS Distributions 	ret = copyInObjects(msgin, message, msgin->msgh.msgh_size, true, false);
3244a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != ret) {
3245a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3246a5e72196SApple OSS Distributions 			DKLOG("UEXT copyin(0x%x) %x\n", ret, msgin->msgh.msgh_id);
3247a5e72196SApple OSS Distributions 		}
32488d741a5dSApple OSS Distributions 		// release objects and ports
32498d741a5dSApple OSS Distributions 		consumeObjects(msgin, message, msgin->msgh.msgh_size);
32508d741a5dSApple OSS Distributions 		copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true);
3251a5e72196SApple OSS Distributions 		return KERN_NOT_SUPPORTED;
3252a5e72196SApple OSS Distributions 	}
3253a5e72196SApple OSS Distributions 
3254a5e72196SApple OSS Distributions 	if (msgin->msgh_body.msgh_descriptor_count < 1) {
3255a5e72196SApple OSS Distributions 		return KERN_NOT_SUPPORTED;
3256a5e72196SApple OSS Distributions 	}
3257a5e72196SApple OSS Distributions 	object = (OSObject *) message->objects[0];
3258a5e72196SApple OSS Distributions 	msgid = message->msgid;
3259a5e72196SApple OSS Distributions 	message->flags &= ~kIORPCMessageKernel;
3260a5e72196SApple OSS Distributions 	message->flags |= kIORPCMessageRemote;
3261a5e72196SApple OSS Distributions 
3262a5e72196SApple OSS Distributions 	if ((action = OSDynamicCast(OSAction, object))) {
3263a5e72196SApple OSS Distributions 		object = target(action, message);
3264a5e72196SApple OSS Distributions 		msgid  = message->msgid;
3265a5e72196SApple OSS Distributions 	}
3266a5e72196SApple OSS Distributions 
3267a5e72196SApple OSS Distributions 	oneway = (0 != (kIORPCMessageOneway & message->flags));
3268a5e72196SApple OSS Distributions 	assert(oneway || (MACH_PORT_NULL != msgin->msgh.msgh_local_port));
3269a5e72196SApple OSS Distributions 
3270a5e72196SApple OSS Distributions 	replyAlloc = oneway ? 0 : MAX_UEXT_REPLY_SIZE;
327194d3b452SApple OSS Distributions 
327294d3b452SApple OSS Distributions 
327394d3b452SApple OSS Distributions 
327494d3b452SApple OSS Distributions 
3275a5e72196SApple OSS Distributions 	if (replyAlloc) {
3276a5e72196SApple OSS Distributions 		/*
3277e6231be0SApple OSS Distributions 		 * Same as:
327894d3b452SApple OSS Distributions 		 *    ipc_kmsg_alloc(MAX_UEXT_REPLY_SIZE_MACH, MAX_UEXT_REPLY_SIZE_MESSAGE,
3279aca3beaaSApple OSS Distributions 		 *        IPC_KMSG_ALLOC_KERNEL | IPC_KMSG_ALLOC_ZERO | IPC_KMSG_ALLOC_LINEAR |
3280e6231be0SApple OSS Distributions 		 *        IPC_KMSG_ALLOC_NOFAIL);
3281a5e72196SApple OSS Distributions 		 */
328294d3b452SApple OSS Distributions 		replykmsg = ipc_kmsg_alloc_uext_reply(MAX_UEXT_REPLY_SIZE);
3283aca3beaaSApple OSS Distributions 		msgout = (typeof(msgout))ikm_header(replykmsg);
3284a5e72196SApple OSS Distributions 	}
3285a5e72196SApple OSS Distributions 
328694d3b452SApple OSS Distributions 	IORPC rpc = { .message = msgin, .reply = msgout, .sendSize = msgin->msgh.msgh_size, .replySize = replyAlloc, .kernelContent = message };
3287a5e72196SApple OSS Distributions 
3288a5e72196SApple OSS Distributions 	if (object) {
3289e6231be0SApple OSS Distributions 		kern_allocation_name_t prior;
3290e6231be0SApple OSS Distributions 		bool                   setAllocationName;
3291e6231be0SApple OSS Distributions 
3292e6231be0SApple OSS Distributions 		setAllocationName = (NULL != fAllocationName);
3293e6231be0SApple OSS Distributions 		if (setAllocationName) {
3294e6231be0SApple OSS Distributions 			prior = thread_set_allocation_name(fAllocationName);
3295e6231be0SApple OSS Distributions 		}
3296a5e72196SApple OSS Distributions 		thread_iokit_tls_set(0, this);
3297a5e72196SApple OSS Distributions 		ret = kernelDispatch(object, rpc);
3298a5e72196SApple OSS Distributions 		thread_iokit_tls_set(0, NULL);
3299e6231be0SApple OSS Distributions 		if (setAllocationName) {
3300e6231be0SApple OSS Distributions 			thread_set_allocation_name(prior);
3301e6231be0SApple OSS Distributions 		}
3302a5e72196SApple OSS Distributions 	} else {
3303a5e72196SApple OSS Distributions 		ret = kIOReturnBadArgument;
3304a5e72196SApple OSS Distributions 	}
3305a5e72196SApple OSS Distributions 
3306a5e72196SApple OSS Distributions 	// release objects
33078d741a5dSApple OSS Distributions 	consumeObjects(msgin, message, msgin->msgh.msgh_size);
3308a5e72196SApple OSS Distributions 
3309a5e72196SApple OSS Distributions 	// release ports
3310a5e72196SApple OSS Distributions 	copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true);
3311a5e72196SApple OSS Distributions 
3312a5e72196SApple OSS Distributions 	if (!oneway) {
3313a5e72196SApple OSS Distributions 		if (kIOReturnSuccess == ret) {
3314a5e72196SApple OSS Distributions 			replySize = msgout->msgh.msgh_size;
331594d3b452SApple OSS Distributions 			reply = IORPCMessageFromMachReply(msgout);
3316a5e72196SApple OSS Distributions 			if (!reply) {
3317a5e72196SApple OSS Distributions 				ret = kIOReturnIPCError;
3318a5e72196SApple OSS Distributions 			} else {
3319a5e72196SApple OSS Distributions 				ret = copyOutObjects(msgout, reply, replySize, (kIORPCVersionCurrentReply == msgout->msgh.msgh_id) /* =>!InvokeReply */);
3320a5e72196SApple OSS Distributions 			}
3321a5e72196SApple OSS Distributions 		}
3322a5e72196SApple OSS Distributions 		if (kIOReturnSuccess != ret) {
3323a5e72196SApple OSS Distributions 			IORPCMessageErrorReturnContent * errorMsg;
3324a5e72196SApple OSS Distributions 
3325a5e72196SApple OSS Distributions 			msgout->msgh_body.msgh_descriptor_count = 0;
3326a5e72196SApple OSS Distributions 			msgout->msgh.msgh_id                    = kIORPCVersionCurrentReply;
332794d3b452SApple OSS Distributions 			errorMsg = (typeof(errorMsg))IORPCMessageFromMachReply(msgout);
3328a5e72196SApple OSS Distributions 			errorMsg->hdr.msgid      = message->msgid;
3329a5e72196SApple OSS Distributions 			errorMsg->hdr.flags      = kIORPCMessageOneway | kIORPCMessageError;
3330a5e72196SApple OSS Distributions 			errorMsg->hdr.objectRefs = 0;
3331a5e72196SApple OSS Distributions 			errorMsg->result         = ret;
3332a5e72196SApple OSS Distributions 			errorMsg->pad            = 0;
3333a5e72196SApple OSS Distributions 			replySize                = sizeof(IORPCMessageErrorReturn);
3334a5e72196SApple OSS Distributions 		}
3335a5e72196SApple OSS Distributions 
3336a5e72196SApple OSS Distributions 		msgout->msgh.msgh_bits = MACH_MSGH_BITS_COMPLEX |
3337a5e72196SApple OSS Distributions 		    MACH_MSGH_BITS_SET(MACH_MSGH_BITS_LOCAL(msgin->msgh.msgh_bits) /*remote*/, 0 /*local*/, 0, 0);
3338a5e72196SApple OSS Distributions 
3339a5e72196SApple OSS Distributions 		msgout->msgh.msgh_remote_port  = msgin->msgh.msgh_local_port;
3340a5e72196SApple OSS Distributions 		msgout->msgh.msgh_local_port   = MACH_PORT_NULL;
3341a5e72196SApple OSS Distributions 		msgout->msgh.msgh_voucher_port = (mach_port_name_t) 0;
3342a5e72196SApple OSS Distributions 		msgout->msgh.msgh_reserved     = 0;
3343a5e72196SApple OSS Distributions 		msgout->msgh.msgh_size         = replySize;
3344a5e72196SApple OSS Distributions 	}
3345a5e72196SApple OSS Distributions 
3346a5e72196SApple OSS Distributions 	*pReply = replykmsg;
3347e6231be0SApple OSS Distributions 	return KERN_SUCCESS;
3348a5e72196SApple OSS Distributions }
3349a5e72196SApple OSS Distributions 
3350bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3351a5e72196SApple OSS Distributions 
33528d741a5dSApple OSS Distributions static inline uint32_t
MAX_OBJECT_COUNT(IORPCMessageMach * mach,size_t size,IORPCMessage * message __unused)33538d741a5dSApple OSS Distributions MAX_OBJECT_COUNT(IORPCMessageMach *mach, size_t size, IORPCMessage *message __unused)
33548d741a5dSApple OSS Distributions {
33558d741a5dSApple OSS Distributions 	assert(mach->msgh.msgh_size == size);
33568d741a5dSApple OSS Distributions 	size_t used_size;
33578d741a5dSApple OSS Distributions 	size_t remaining_size;
33588d741a5dSApple OSS Distributions 	if (os_mul_and_add_overflow(
33598d741a5dSApple OSS Distributions 		    mach->msgh_body.msgh_descriptor_count,
33608d741a5dSApple OSS Distributions 		    sizeof(mach_msg_port_descriptor_t),
33618d741a5dSApple OSS Distributions 		    sizeof(mach->msgh) + sizeof(mach->msgh_body) + offsetof(IORPCMessage, objects[0]),
33628d741a5dSApple OSS Distributions 		    &used_size)) {
33638d741a5dSApple OSS Distributions 		return 0;
33648d741a5dSApple OSS Distributions 	}
33658d741a5dSApple OSS Distributions 	if (os_sub_overflow(size, used_size, &remaining_size)) {
33668d741a5dSApple OSS Distributions 		return 0;
33678d741a5dSApple OSS Distributions 	}
33688d741a5dSApple OSS Distributions 	return (uint32_t)(remaining_size / sizeof(OSObjectRef));
33698d741a5dSApple OSS Distributions }
3370a5e72196SApple OSS Distributions 
33715c2921b0SApple OSS Distributions #pragma pack(push, 4)
33725c2921b0SApple OSS Distributions struct UEXTTrapReply {
33735c2921b0SApple OSS Distributions 	uint64_t replySize;
33745c2921b0SApple OSS Distributions 	IORPCMessage replyMessage;
33755c2921b0SApple OSS Distributions };
33765c2921b0SApple OSS Distributions #pragma pack(pop)
33775c2921b0SApple OSS Distributions 
3378a5e72196SApple OSS Distributions kern_return_t
IOUserServerUEXTTrap(OSObject * object,void * p1,void * p2,void * p3,void * p4,void * p5,void * p6)3379a5e72196SApple OSS Distributions IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
3380a5e72196SApple OSS Distributions {
3381a5e72196SApple OSS Distributions 	const user_addr_t msg              = (uintptr_t) p1;
3382a5e72196SApple OSS Distributions 	size_t            inSize           = (uintptr_t) p2;
3383a5e72196SApple OSS Distributions 	user_addr_t       out              = (uintptr_t) p3;
3384a5e72196SApple OSS Distributions 	size_t            outSize          = (uintptr_t) p4;
3385bb611c8fSApple OSS Distributions 	mach_port_name_t  objectName1      = (mach_port_name_t)(uintptr_t) p5;
3386a5e72196SApple OSS Distributions 	size_t            totalSize;
3387a5e72196SApple OSS Distributions 	OSObject        * objectArg1;
3388a5e72196SApple OSS Distributions 
3389a5e72196SApple OSS Distributions 	IORPCMessageMach *  mach;
3390a5e72196SApple OSS Distributions 	mach_msg_port_descriptor_t * descs;
3391a5e72196SApple OSS Distributions 
3392a5e72196SApple OSS Distributions #pragma pack(4)
3393a5e72196SApple OSS Distributions 	struct {
3394a5e72196SApple OSS Distributions 		uint32_t                   pad;
3395a5e72196SApple OSS Distributions 		IORPCMessageMach           mach;
3396a5e72196SApple OSS Distributions 		mach_msg_port_descriptor_t objects[2];
3397a5e72196SApple OSS Distributions 		IOTrapMessageBuffer        buffer;
3398a5e72196SApple OSS Distributions 	} buffer;
3399a5e72196SApple OSS Distributions #pragma pack()
3400a5e72196SApple OSS Distributions 
3401a5e72196SApple OSS Distributions 	IOReturn           ret;
3402a5e72196SApple OSS Distributions 	OSAction         * action;
3403a5e72196SApple OSS Distributions 	int                copyerr;
3404a5e72196SApple OSS Distributions 	IORPCMessage     * message;
3405a5e72196SApple OSS Distributions 	IORPCMessage     * reply;
3406a5e72196SApple OSS Distributions 	IORPC              rpc;
3407a5e72196SApple OSS Distributions 	uint64_t           refs;
3408a5e72196SApple OSS Distributions 	uint32_t           maxObjectCount;
3409a5e72196SApple OSS Distributions 	size_t             copySize;
34105c2921b0SApple OSS Distributions 	UEXTTrapReply    * replyHdr;
3411a5e72196SApple OSS Distributions 	uintptr_t          p;
3412a5e72196SApple OSS Distributions 
3413a5e72196SApple OSS Distributions 	bzero(&buffer, sizeof(buffer));
3414a5e72196SApple OSS Distributions 
3415a5e72196SApple OSS Distributions 	p = (typeof(p)) & buffer.buffer[0];
3416a5e72196SApple OSS Distributions 	if (os_add_overflow(inSize, outSize, &totalSize)) {
3417a5e72196SApple OSS Distributions 		return kIOReturnMessageTooLarge;
3418a5e72196SApple OSS Distributions 	}
3419a5e72196SApple OSS Distributions 	if (totalSize > sizeof(buffer.buffer)) {
3420a5e72196SApple OSS Distributions 		return kIOReturnMessageTooLarge;
3421a5e72196SApple OSS Distributions 	}
3422a5e72196SApple OSS Distributions 	if (inSize < sizeof(IORPCMessage)) {
3423a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
3424a5e72196SApple OSS Distributions 	}
3425a5e72196SApple OSS Distributions 	copyerr = copyin(msg, &buffer.buffer[0], inSize);
3426a5e72196SApple OSS Distributions 	if (copyerr) {
3427a5e72196SApple OSS Distributions 		return kIOReturnVMError;
3428a5e72196SApple OSS Distributions 	}
3429a5e72196SApple OSS Distributions 
3430a5e72196SApple OSS Distributions 	message = (typeof(message))p;
3431a5e72196SApple OSS Distributions 	refs    = message->objectRefs;
3432a5e72196SApple OSS Distributions 	if ((refs > 2) || !refs) {
3433a5e72196SApple OSS Distributions 		return kIOReturnUnsupported;
3434a5e72196SApple OSS Distributions 	}
3435a5e72196SApple OSS Distributions 	if (!(kIORPCMessageSimpleReply & message->flags)) {
3436a5e72196SApple OSS Distributions 		return kIOReturnUnsupported;
3437a5e72196SApple OSS Distributions 	}
34385c2921b0SApple OSS Distributions 	message->flags &= ~(kIORPCMessageKernel | kIORPCMessageRemote);
3439a5e72196SApple OSS Distributions 
3440a5e72196SApple OSS Distributions 	descs = (typeof(descs))(p - refs * sizeof(*descs));
3441a5e72196SApple OSS Distributions 	mach  = (typeof(mach))(p - refs * sizeof(*descs) - sizeof(*mach));
3442a5e72196SApple OSS Distributions 
3443a5e72196SApple OSS Distributions 	mach->msgh.msgh_id   = kIORPCVersionCurrent;
3444bb611c8fSApple OSS Distributions 	mach->msgh.msgh_size = (mach_msg_size_t) (sizeof(IORPCMessageMach) + refs * sizeof(*descs) + inSize); // totalSize was checked
3445bb611c8fSApple OSS Distributions 	mach->msgh_body.msgh_descriptor_count = ((mach_msg_size_t) refs);
3446a5e72196SApple OSS Distributions 
3447a5e72196SApple OSS Distributions 	rpc.message   = mach;
3448a5e72196SApple OSS Distributions 	rpc.sendSize  = mach->msgh.msgh_size;
3449a5e72196SApple OSS Distributions 	rpc.reply     = (IORPCMessageMach *) (p + inSize);
3450bb611c8fSApple OSS Distributions 	rpc.replySize = ((uint32_t) (sizeof(buffer.buffer) - inSize));    // inSize was checked
345194d3b452SApple OSS Distributions 	rpc.kernelContent = message;
3452a5e72196SApple OSS Distributions 
3453a5e72196SApple OSS Distributions 	message->objects[0] = 0;
3454a5e72196SApple OSS Distributions 	if ((action = OSDynamicCast(OSAction, object))) {
3455a5e72196SApple OSS Distributions 		maxObjectCount = MAX_OBJECT_COUNT(rpc.message, rpc.sendSize, message);
3456a5e72196SApple OSS Distributions 		if (refs > maxObjectCount) {
3457a5e72196SApple OSS Distributions 			return kIOReturnBadArgument;
3458a5e72196SApple OSS Distributions 		}
34595c2921b0SApple OSS Distributions 		if (refs < 2) {
34605c2921b0SApple OSS Distributions 			DKLOG("invalid refs count %qd in message id 0x%qx\n", refs, message->msgid);
34615c2921b0SApple OSS Distributions 			return kIOReturnBadArgument;
34625c2921b0SApple OSS Distributions 		}
3463a5e72196SApple OSS Distributions 		object = IOUserServer::target(action, message);
3464a5e72196SApple OSS Distributions 		message->objects[1] = (OSObjectRef) action;
3465a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3466a5e72196SApple OSS Distributions 			DKLOG("%s::Dispatch(trap) kernel 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid);
3467a5e72196SApple OSS Distributions 		}
3468a5e72196SApple OSS Distributions 		ret = object->Dispatch(rpc);
3469a5e72196SApple OSS Distributions 	} else {
3470a5e72196SApple OSS Distributions 		objectArg1 = NULL;
3471a5e72196SApple OSS Distributions 		if (refs > 1) {
3472bb611c8fSApple OSS Distributions 			if (objectName1) {
3473a5e72196SApple OSS Distributions 				objectArg1 = iokit_lookup_uext_ref_current_task(objectName1);
3474a5e72196SApple OSS Distributions 				if (!objectArg1) {
3475a5e72196SApple OSS Distributions 					return kIOReturnIPCError;
3476a5e72196SApple OSS Distributions 				}
3477bb611c8fSApple OSS Distributions 			}
3478a5e72196SApple OSS Distributions 			message->objects[1] = (OSObjectRef) objectArg1;
3479a5e72196SApple OSS Distributions 		}
3480a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3481a5e72196SApple OSS Distributions 			DKLOG("%s::Dispatch(trap) kernel 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid);
3482a5e72196SApple OSS Distributions 		}
3483a5e72196SApple OSS Distributions 		ret = object->Dispatch(rpc);
3484a5e72196SApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3485a5e72196SApple OSS Distributions 			DKLOG("%s::Dispatch(trap) kernel 0x%qx 0x%x\n", object->getMetaClass()->getClassName(), message->msgid, ret);
3486a5e72196SApple OSS Distributions 		}
3487a5e72196SApple OSS Distributions 		OSSafeReleaseNULL(objectArg1);
3488a5e72196SApple OSS Distributions 
3489a5e72196SApple OSS Distributions 		if (kIOReturnSuccess == ret) {
3490a5e72196SApple OSS Distributions 			if (rpc.reply->msgh_body.msgh_descriptor_count) {
3491a5e72196SApple OSS Distributions 				return kIOReturnIPCError;
3492a5e72196SApple OSS Distributions 			}
349394d3b452SApple OSS Distributions 			reply = IORPCMessageFromMachReply(rpc.reply);
3494a5e72196SApple OSS Distributions 			if (!reply) {
3495a5e72196SApple OSS Distributions 				return kIOReturnIPCError;
3496a5e72196SApple OSS Distributions 			}
3497a5e72196SApple OSS Distributions 			copySize = rpc.reply->msgh.msgh_size - (((uintptr_t) reply) - ((uintptr_t) rpc.reply)) + sizeof(uint64_t);
3498a5e72196SApple OSS Distributions 			if (copySize > outSize) {
3499a5e72196SApple OSS Distributions 				return kIOReturnIPCError;
3500a5e72196SApple OSS Distributions 			}
35015c2921b0SApple OSS Distributions 			replyHdr = (UEXTTrapReply *) ((uintptr_t)reply - sizeof(uint64_t));
35025c2921b0SApple OSS Distributions 			replyHdr->replySize = copySize;
3503a5e72196SApple OSS Distributions 			copyerr = copyout(replyHdr, out, copySize);
3504a5e72196SApple OSS Distributions 			if (copyerr) {
3505a5e72196SApple OSS Distributions 				return kIOReturnVMError;
3506a5e72196SApple OSS Distributions 			}
3507a5e72196SApple OSS Distributions 		}
3508a5e72196SApple OSS Distributions 	}
3509a5e72196SApple OSS Distributions 
3510a5e72196SApple OSS Distributions 	return ret;
3511a5e72196SApple OSS Distributions }
3512a5e72196SApple OSS Distributions 
3513bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3514a5e72196SApple OSS Distributions 
3515a5e72196SApple OSS Distributions IOReturn
rpc(IORPC rpc)3516a5e72196SApple OSS Distributions IOUserServer::rpc(IORPC rpc)
3517a5e72196SApple OSS Distributions {
3518a5e72196SApple OSS Distributions 	if (isInactive() && !fRootQueue) {
3519a5e72196SApple OSS Distributions 		return kIOReturnOffline;
3520a5e72196SApple OSS Distributions 	}
3521a5e72196SApple OSS Distributions 
3522a5e72196SApple OSS Distributions 	IOReturn           ret;
3523a5e72196SApple OSS Distributions 	IORPCMessage     * message;
3524a5e72196SApple OSS Distributions 	IORPCMessageMach * mach;
3525a5e72196SApple OSS Distributions 	mach_msg_id_t      machid;
3526a5e72196SApple OSS Distributions 	uint32_t           sendSize, replySize;
3527a5e72196SApple OSS Distributions 	bool               oneway;
3528a5e72196SApple OSS Distributions 	uint64_t           msgid;
3529a5e72196SApple OSS Distributions 	IODispatchQueue  * queue;
3530a5e72196SApple OSS Distributions 	IOService        * service;
3531a5e72196SApple OSS Distributions 	ipc_port_t         port;
3532a5e72196SApple OSS Distributions 	ipc_port_t         sendPort;
3533a5e72196SApple OSS Distributions 
3534a5e72196SApple OSS Distributions 	queue    = NULL;
3535a5e72196SApple OSS Distributions 	port     = NULL;
3536a5e72196SApple OSS Distributions 	sendPort = NULL;
3537a5e72196SApple OSS Distributions 
3538a5e72196SApple OSS Distributions 	mach      = rpc.message;
3539a5e72196SApple OSS Distributions 	sendSize  = rpc.sendSize;
3540a5e72196SApple OSS Distributions 	replySize = rpc.replySize;
3541a5e72196SApple OSS Distributions 
3542a5e72196SApple OSS Distributions 	assert(sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
3543a5e72196SApple OSS Distributions 
354494d3b452SApple OSS Distributions 	message = rpc.kernelContent;
3545a5e72196SApple OSS Distributions 	if (!message) {
3546bb611c8fSApple OSS Distributions 		return kIOReturnIPCError;
3547a5e72196SApple OSS Distributions 	}
3548a5e72196SApple OSS Distributions 	msgid   = message->msgid;
3549a5e72196SApple OSS Distributions 	machid  = (msgid >> 32);
3550a5e72196SApple OSS Distributions 
3551a5e72196SApple OSS Distributions 	if (mach->msgh_body.msgh_descriptor_count < 1) {
3552a5e72196SApple OSS Distributions 		return kIOReturnNoMedia;
3553a5e72196SApple OSS Distributions 	}
3554a5e72196SApple OSS Distributions 
3555a5e72196SApple OSS Distributions 	IOLockLock(gIOUserServerLock);
3556a5e72196SApple OSS Distributions 	if ((service = OSDynamicCast(IOService, (OSObject *) message->objects[0]))) {
3557a5e72196SApple OSS Distributions 		queue = queueForObject(service, msgid);
3558a5e72196SApple OSS Distributions 	}
3559a5e72196SApple OSS Distributions 	if (!queue) {
3560a5e72196SApple OSS Distributions 		queue = fRootQueue;
3561a5e72196SApple OSS Distributions 	}
3562a5e72196SApple OSS Distributions 	if (queue && (kIODispatchQueueStopped != queue)) {
3563a5e72196SApple OSS Distributions 		port = queue->ivars->serverPort;
3564a5e72196SApple OSS Distributions 	}
3565a5e72196SApple OSS Distributions 	if (port) {
35665c2921b0SApple OSS Distributions 		sendPort = ipc_port_copy_send_mqueue(port);
3567a5e72196SApple OSS Distributions 	}
3568a5e72196SApple OSS Distributions 	IOLockUnlock(gIOUserServerLock);
3569a5e72196SApple OSS Distributions 	if (!sendPort) {
3570a5e72196SApple OSS Distributions 		return kIOReturnNotReady;
3571a5e72196SApple OSS Distributions 	}
3572a5e72196SApple OSS Distributions 
3573a5e72196SApple OSS Distributions 	oneway = (0 != (kIORPCMessageOneway & message->flags));
3574a5e72196SApple OSS Distributions 
3575a5e72196SApple OSS Distributions 	ret = copyOutObjects(mach, message, sendSize, false);
3576a5e72196SApple OSS Distributions 
3577a5e72196SApple OSS Distributions 	mach->msgh.msgh_bits = MACH_MSGH_BITS_COMPLEX |
3578bb611c8fSApple OSS Distributions 	    MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, (oneway ? 0 : MACH_MSG_TYPE_MAKE_SEND_ONCE));
3579a5e72196SApple OSS Distributions 	mach->msgh.msgh_remote_port  = sendPort;
3580a5e72196SApple OSS Distributions 	mach->msgh.msgh_local_port   = (oneway ? MACH_PORT_NULL : mig_get_reply_port());
3581a5e72196SApple OSS Distributions 	mach->msgh.msgh_id           = kIORPCVersionCurrent;
3582a5e72196SApple OSS Distributions 	mach->msgh.msgh_reserved     = 0;
3583a5e72196SApple OSS Distributions 
3584bb611c8fSApple OSS Distributions 	boolean_t message_moved;
3585bb611c8fSApple OSS Distributions 
3586a5e72196SApple OSS Distributions 	if (oneway) {
3587bb611c8fSApple OSS Distributions 		ret = kernel_mach_msg_send(&mach->msgh, sendSize,
35888d741a5dSApple OSS Distributions 		    MACH_SEND_KERNEL_DEFAULT, 0, &message_moved);
3589a5e72196SApple OSS Distributions 	} else {
3590a5e72196SApple OSS Distributions 		assert(replySize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
3591bb611c8fSApple OSS Distributions 		ret = kernel_mach_msg_rpc(&mach->msgh, sendSize, replySize, FALSE, &message_moved);
3592bb611c8fSApple OSS Distributions 	}
3593bb611c8fSApple OSS Distributions 
3594bb611c8fSApple OSS Distributions 	ipc_port_release_send(sendPort);
3595bb611c8fSApple OSS Distributions 
3596bb611c8fSApple OSS Distributions 	if (MACH_MSG_SUCCESS != ret) {
3597bb611c8fSApple OSS Distributions 		if (kIODKLogIPC & gIODKDebug) {
3598bb611c8fSApple OSS Distributions 			DKLOG("mach_msg() failed 0x%x\n", ret);
3599bb611c8fSApple OSS Distributions 		}
3600bb611c8fSApple OSS Distributions 		if (!message_moved) {
3601bb611c8fSApple OSS Distributions 			// release ports
3602bb611c8fSApple OSS Distributions 			copyInObjects(mach, message, sendSize, false, true);
3603bb611c8fSApple OSS Distributions 		}
3604bb611c8fSApple OSS Distributions 	}
3605bb611c8fSApple OSS Distributions 
3606bb611c8fSApple OSS Distributions 	if ((KERN_SUCCESS == ret) && !oneway) {
3607a5e72196SApple OSS Distributions 		if (kIORPCVersionCurrentReply != mach->msgh.msgh_id) {
3608a5e72196SApple OSS Distributions 			ret = (MACH_NOTIFY_SEND_ONCE == mach->msgh.msgh_id) ? MIG_SERVER_DIED : MIG_REPLY_MISMATCH;
3609a5e72196SApple OSS Distributions 		} else if ((replySize = mach->msgh.msgh_size) < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) {
3610a5e72196SApple OSS Distributions //				printf("BAD REPLY SIZE\n");
3611a5e72196SApple OSS Distributions 			ret = MIG_BAD_ARGUMENTS;
3612a5e72196SApple OSS Distributions 		} else {
3613a5e72196SApple OSS Distributions 			if (!(MACH_MSGH_BITS_COMPLEX & mach->msgh.msgh_bits)) {
3614a5e72196SApple OSS Distributions 				mach->msgh_body.msgh_descriptor_count = 0;
3615a5e72196SApple OSS Distributions 			}
361694d3b452SApple OSS Distributions 			message = IORPCMessageFromMachReply(mach);
3617a5e72196SApple OSS Distributions 			if (!message) {
3618a5e72196SApple OSS Distributions 				ret = kIOReturnIPCError;
3619a5e72196SApple OSS Distributions 			} else if (message->msgid != msgid) {
3620a5e72196SApple OSS Distributions //					printf("BAD REPLY ID\n");
3621a5e72196SApple OSS Distributions 				ret = MIG_BAD_ARGUMENTS;
3622a5e72196SApple OSS Distributions 			} else {
3623a5e72196SApple OSS Distributions 				bool isError = (0 != (kIORPCMessageError & message->flags));
3624a5e72196SApple OSS Distributions 				ret = copyInObjects(mach, message, replySize, !isError, true);
3625a5e72196SApple OSS Distributions 				if (kIOReturnSuccess != ret) {
3626a5e72196SApple OSS Distributions 					if (kIODKLogIPC & gIODKDebug) {
3627a5e72196SApple OSS Distributions 						DKLOG("rpc copyin(0x%x) %x\n", ret, mach->msgh.msgh_id);
3628a5e72196SApple OSS Distributions 					}
36298d741a5dSApple OSS Distributions 					if (!isError) {
36308d741a5dSApple OSS Distributions 						consumeObjects(mach, message, replySize);
36318d741a5dSApple OSS Distributions 						copyInObjects(mach, message, replySize, false, true);
36328d741a5dSApple OSS Distributions 					}
3633a5e72196SApple OSS Distributions 					return KERN_NOT_SUPPORTED;
3634a5e72196SApple OSS Distributions 				}
3635a5e72196SApple OSS Distributions 				if (isError) {
3636a5e72196SApple OSS Distributions 					IORPCMessageErrorReturnContent * errorMsg = (typeof(errorMsg))message;
3637a5e72196SApple OSS Distributions 					ret = errorMsg->result;
3638a5e72196SApple OSS Distributions 				}
3639a5e72196SApple OSS Distributions 			}
3640a5e72196SApple OSS Distributions 		}
3641a5e72196SApple OSS Distributions 	}
3642a5e72196SApple OSS Distributions 
3643a5e72196SApple OSS Distributions 	return ret;
3644a5e72196SApple OSS Distributions }
3645a5e72196SApple OSS Distributions 
3646a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3647a5e72196SApple OSS Distributions 
364894d3b452SApple OSS Distributions static IORPCMessage *
IORPCMessageFromMachReply(IORPCMessageMach * msg)364994d3b452SApple OSS Distributions IORPCMessageFromMachReply(IORPCMessageMach * msg)
3650a5e72196SApple OSS Distributions {
3651a5e72196SApple OSS Distributions 	mach_msg_size_t              idx, count;
3652a5e72196SApple OSS Distributions 	mach_msg_port_descriptor_t * desc;
3653a5e72196SApple OSS Distributions 	mach_msg_port_descriptor_t * maxDesc;
3654a5e72196SApple OSS Distributions 	size_t                       size, msgsize;
3655a5e72196SApple OSS Distributions 	bool                         upgrade;
365694d3b452SApple OSS Distributions 	bool                         reply = true;
3657a5e72196SApple OSS Distributions 
3658a5e72196SApple OSS Distributions 	msgsize = msg->msgh.msgh_size;
3659a5e72196SApple OSS Distributions 	count   = msg->msgh_body.msgh_descriptor_count;
3660a5e72196SApple OSS Distributions 	desc    = &msg->objects[0];
3661a5e72196SApple OSS Distributions 	maxDesc = (typeof(maxDesc))(((uintptr_t) msg) + msgsize);
3662a5e72196SApple OSS Distributions 	upgrade = (msg->msgh.msgh_id != (reply ? kIORPCVersionCurrentReply : kIORPCVersionCurrent));
3663a5e72196SApple OSS Distributions 
3664a5e72196SApple OSS Distributions 	if (upgrade) {
3665a5e72196SApple OSS Distributions 		OSReportWithBacktrace("obsolete message");
3666a5e72196SApple OSS Distributions 		return NULL;
3667a5e72196SApple OSS Distributions 	}
3668a5e72196SApple OSS Distributions 
3669a5e72196SApple OSS Distributions 	for (idx = 0; idx < count; idx++) {
3670a5e72196SApple OSS Distributions 		if (desc >= maxDesc) {
3671a5e72196SApple OSS Distributions 			return NULL;
3672a5e72196SApple OSS Distributions 		}
3673a5e72196SApple OSS Distributions 		switch (desc->type) {
3674a5e72196SApple OSS Distributions 		case MACH_MSG_PORT_DESCRIPTOR:
3675a5e72196SApple OSS Distributions 			size = sizeof(mach_msg_port_descriptor_t);
3676a5e72196SApple OSS Distributions 			break;
3677a5e72196SApple OSS Distributions 		case MACH_MSG_OOL_DESCRIPTOR:
3678a5e72196SApple OSS Distributions 			size = sizeof(mach_msg_ool_descriptor_t);
3679a5e72196SApple OSS Distributions 			break;
3680a5e72196SApple OSS Distributions 		default:
3681a5e72196SApple OSS Distributions 			return NULL;
3682a5e72196SApple OSS Distributions 		}
3683a5e72196SApple OSS Distributions 		desc = (typeof(desc))(((uintptr_t) desc) + size);
3684a5e72196SApple OSS Distributions 	}
3685a5e72196SApple OSS Distributions 	return (IORPCMessage *)(uintptr_t) desc;
3686a5e72196SApple OSS Distributions }
3687a5e72196SApple OSS Distributions 
3688a5e72196SApple OSS Distributions ipc_port_t
copySendRightForObject(OSObject * object,ipc_kobject_type_t type)3689a5e72196SApple OSS Distributions IOUserServer::copySendRightForObject(OSObject * object, ipc_kobject_type_t type)
3690a5e72196SApple OSS Distributions {
3691a5e72196SApple OSS Distributions 	ipc_port_t port;
3692a5e72196SApple OSS Distributions 	ipc_port_t sendPort = NULL;
36931031c584SApple OSS Distributions 	ipc_kobject_t kobj;
3694a5e72196SApple OSS Distributions 
36951031c584SApple OSS Distributions 	port = iokit_port_for_object(object, type, &kobj);
3696a5e72196SApple OSS Distributions 	if (port) {
36971031c584SApple OSS Distributions 		sendPort = ipc_kobject_make_send(port, kobj, type);
3698a5e72196SApple OSS Distributions 		iokit_release_port(port);
3699a5e72196SApple OSS Distributions 	}
3700a5e72196SApple OSS Distributions 
3701a5e72196SApple OSS Distributions 	return sendPort;
3702a5e72196SApple OSS Distributions }
3703a5e72196SApple OSS Distributions 
3704a5e72196SApple OSS Distributions OSObject *
copyObjectForSendRight(ipc_port_t port,ipc_kobject_type_t type)3705a5e72196SApple OSS Distributions IOUserServer::copyObjectForSendRight(ipc_port_t port, ipc_kobject_type_t type)
3706a5e72196SApple OSS Distributions {
3707a5e72196SApple OSS Distributions 	OSObject * object;
3708a5e72196SApple OSS Distributions 	object = iokit_lookup_io_object(port, type);
3709a5e72196SApple OSS Distributions 	return object;
3710a5e72196SApple OSS Distributions }
3711a5e72196SApple OSS Distributions 
3712a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3713a5e72196SApple OSS Distributions 
3714a5e72196SApple OSS Distributions // Create a vm_map_copy_t or kalloc'ed data for memory
3715a5e72196SApple OSS Distributions // to be copied out. ipc will free after the copyout.
3716a5e72196SApple OSS Distributions 
3717a5e72196SApple OSS Distributions static kern_return_t
copyoutkdata(const void * data,vm_size_t len,void ** buf)3718a5e72196SApple OSS Distributions copyoutkdata(const void * data, vm_size_t len, void ** buf)
3719a5e72196SApple OSS Distributions {
3720a5e72196SApple OSS Distributions 	kern_return_t       err;
3721a5e72196SApple OSS Distributions 	vm_map_copy_t       copy;
3722a5e72196SApple OSS Distributions 
3723a5e72196SApple OSS Distributions 	err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
3724a5e72196SApple OSS Distributions 	    false /* src_destroy */, &copy);
3725a5e72196SApple OSS Distributions 
3726a5e72196SApple OSS Distributions 	assert( err == KERN_SUCCESS );
3727a5e72196SApple OSS Distributions 	if (err == KERN_SUCCESS) {
3728a5e72196SApple OSS Distributions 		*buf = (char *) copy;
3729a5e72196SApple OSS Distributions 	}
3730a5e72196SApple OSS Distributions 
3731a5e72196SApple OSS Distributions 	return err;
3732a5e72196SApple OSS Distributions }
3733a5e72196SApple OSS Distributions 
3734a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3735a5e72196SApple OSS Distributions 
3736a5e72196SApple OSS Distributions IOReturn
copyOutObjects(IORPCMessageMach * mach,IORPCMessage * message,size_t size,bool consume)3737a5e72196SApple OSS Distributions IOUserServer::copyOutObjects(IORPCMessageMach * mach, IORPCMessage * message,
3738a5e72196SApple OSS Distributions     size_t size, bool consume)
3739a5e72196SApple OSS Distributions {
3740a5e72196SApple OSS Distributions 	uint64_t           refs;
3741a5e72196SApple OSS Distributions 	uint32_t           idx, maxObjectCount;
3742a5e72196SApple OSS Distributions 	ipc_port_t         port;
3743a5e72196SApple OSS Distributions 	OSObject         * object;
3744a5e72196SApple OSS Distributions 	size_t             descsize;
3745a5e72196SApple OSS Distributions 	mach_msg_port_descriptor_t * desc;
3746a5e72196SApple OSS Distributions 	mach_msg_ool_descriptor_t  * ool;
3747a5e72196SApple OSS Distributions 	vm_map_copy_t                copy;
3748a5e72196SApple OSS Distributions 	void                       * address;
3749a5e72196SApple OSS Distributions 	mach_msg_size_t              length;
3750a5e72196SApple OSS Distributions 	kern_return_t                kr;
3751a5e72196SApple OSS Distributions 	OSSerialize                * s;
3752a5e72196SApple OSS Distributions 
3753a5e72196SApple OSS Distributions 	refs           = message->objectRefs;
3754a5e72196SApple OSS Distributions 	maxObjectCount = MAX_OBJECT_COUNT(mach, size, message);
3755a5e72196SApple OSS Distributions //	assert(refs <= mach->msgh_body.msgh_descriptor_count);
3756a5e72196SApple OSS Distributions //	assert(refs <= maxObjectCount);
3757a5e72196SApple OSS Distributions 	if (refs > mach->msgh_body.msgh_descriptor_count) {
3758a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3759a5e72196SApple OSS Distributions 	}
3760a5e72196SApple OSS Distributions 	if (refs > maxObjectCount) {
3761a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3762a5e72196SApple OSS Distributions 	}
3763a5e72196SApple OSS Distributions 
3764a5e72196SApple OSS Distributions 	desc = &mach->objects[0];
3765a5e72196SApple OSS Distributions 	for (idx = 0; idx < refs; idx++) {
3766a5e72196SApple OSS Distributions 		object = (OSObject *) message->objects[idx];
3767a5e72196SApple OSS Distributions 
3768a5e72196SApple OSS Distributions 		switch (desc->type) {
3769a5e72196SApple OSS Distributions 		case MACH_MSG_PORT_DESCRIPTOR:
3770a5e72196SApple OSS Distributions 			descsize = sizeof(mach_msg_port_descriptor_t);
3771a5e72196SApple OSS Distributions 			port = NULL;
3772a5e72196SApple OSS Distributions 			if (object) {
37735c2921b0SApple OSS Distributions #if DEVELOPMENT || DEBUG
37745c2921b0SApple OSS Distributions 				if (kIODKLogIPC & gIODKDebug) {
37755c2921b0SApple OSS Distributions 					IOMemoryDescriptor * iomd = OSDynamicCast(IOMemoryDescriptor, object);
37765c2921b0SApple OSS Distributions 					if (iomd != NULL && (iomd->getFlags() & kIOMemoryThreadSafe) == 0) {
37775c2921b0SApple OSS Distributions 						OSReportWithBacktrace("IOMemoryDescriptor %p was created without kIOMemoryThreadSafe flag", iomd);
37785c2921b0SApple OSS Distributions 					}
37795c2921b0SApple OSS Distributions 				}
37805c2921b0SApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
37815c2921b0SApple OSS Distributions 
3782a5e72196SApple OSS Distributions 				port = copySendRightForObject(object, IKOT_UEXT_OBJECT);
3783a5e72196SApple OSS Distributions 				if (!port) {
3784a5e72196SApple OSS Distributions 					break;
3785a5e72196SApple OSS Distributions 				}
3786a5e72196SApple OSS Distributions 				if (consume) {
3787a5e72196SApple OSS Distributions 					object->release();
3788a5e72196SApple OSS Distributions 				}
3789a5e72196SApple OSS Distributions 				message->objects[idx] = 0;
3790a5e72196SApple OSS Distributions 			}
3791a5e72196SApple OSS Distributions //		    desc->type        = MACH_MSG_PORT_DESCRIPTOR;
3792a5e72196SApple OSS Distributions 			desc->disposition = MACH_MSG_TYPE_MOVE_SEND;
3793a5e72196SApple OSS Distributions 			desc->name        = port;
3794a5e72196SApple OSS Distributions 			desc->pad2        = 0;
3795a5e72196SApple OSS Distributions 			desc->pad_end     = 0;
3796a5e72196SApple OSS Distributions 			break;
3797a5e72196SApple OSS Distributions 
3798a5e72196SApple OSS Distributions 		case MACH_MSG_OOL_DESCRIPTOR:
3799a5e72196SApple OSS Distributions 			descsize = sizeof(mach_msg_ool_descriptor_t);
3800a5e72196SApple OSS Distributions 
3801a5e72196SApple OSS Distributions 			length = 0;
3802a5e72196SApple OSS Distributions 			address = NULL;
3803a5e72196SApple OSS Distributions 			if (object) {
3804a5e72196SApple OSS Distributions 				s = OSSerialize::binaryWithCapacity(4096);
3805a5e72196SApple OSS Distributions 				assert(s);
3806a5e72196SApple OSS Distributions 				if (!s) {
3807a5e72196SApple OSS Distributions 					break;
3808a5e72196SApple OSS Distributions 				}
3809a5e72196SApple OSS Distributions 				s->setIndexed(true);
3810a5e72196SApple OSS Distributions 				if (!object->serialize(s)) {
3811a5e72196SApple OSS Distributions 					assert(false);
3812a5e72196SApple OSS Distributions 					descsize = -1UL;
3813a5e72196SApple OSS Distributions 					s->release();
3814a5e72196SApple OSS Distributions 					break;
3815a5e72196SApple OSS Distributions 				}
3816a5e72196SApple OSS Distributions 				length = s->getLength();
3817a5e72196SApple OSS Distributions 				kr = copyoutkdata(s->text(), length, &address);
3818a5e72196SApple OSS Distributions 				s->release();
3819a5e72196SApple OSS Distributions 				if (KERN_SUCCESS != kr) {
3820a5e72196SApple OSS Distributions 					descsize = -1UL;
3821a5e72196SApple OSS Distributions 					address = NULL;
3822a5e72196SApple OSS Distributions 					length = 0;
3823a5e72196SApple OSS Distributions 				}
3824a5e72196SApple OSS Distributions 				if (consume) {
3825a5e72196SApple OSS Distributions 					object->release();
3826a5e72196SApple OSS Distributions 				}
3827a5e72196SApple OSS Distributions 				message->objects[idx] = 0;
3828a5e72196SApple OSS Distributions 			}
3829a5e72196SApple OSS Distributions 			ool = (typeof(ool))desc;
3830a5e72196SApple OSS Distributions //		    ool->type        = MACH_MSG_OOL_DESCRIPTOR;
3831a5e72196SApple OSS Distributions 			ool->deallocate  = false;
3832a5e72196SApple OSS Distributions 			ool->copy        = MACH_MSG_PHYSICAL_COPY;
3833a5e72196SApple OSS Distributions 			ool->size        = length;
3834a5e72196SApple OSS Distributions 			ool->address     = address;
3835a5e72196SApple OSS Distributions 			break;
3836a5e72196SApple OSS Distributions 
3837a5e72196SApple OSS Distributions 		default:
3838a5e72196SApple OSS Distributions 			descsize = -1UL;
3839a5e72196SApple OSS Distributions 			break;
3840a5e72196SApple OSS Distributions 		}
3841a5e72196SApple OSS Distributions 		if (-1UL == descsize) {
3842a5e72196SApple OSS Distributions 			break;
3843a5e72196SApple OSS Distributions 		}
3844a5e72196SApple OSS Distributions 		desc = (typeof(desc))(((uintptr_t) desc) + descsize);
3845a5e72196SApple OSS Distributions 	}
3846a5e72196SApple OSS Distributions 
3847a5e72196SApple OSS Distributions 	if (idx >= refs) {
3848a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
3849a5e72196SApple OSS Distributions 	}
3850a5e72196SApple OSS Distributions 
3851a5e72196SApple OSS Distributions 	desc = &mach->objects[0];
3852a5e72196SApple OSS Distributions 	while (idx--) {
3853a5e72196SApple OSS Distributions 		switch (desc->type) {
3854a5e72196SApple OSS Distributions 		case MACH_MSG_PORT_DESCRIPTOR:
3855a5e72196SApple OSS Distributions 			descsize = sizeof(mach_msg_port_descriptor_t);
3856a5e72196SApple OSS Distributions 			port = desc->name;
3857a5e72196SApple OSS Distributions 			if (port) {
3858a5e72196SApple OSS Distributions 				ipc_port_release_send(port);
3859a5e72196SApple OSS Distributions 			}
3860a5e72196SApple OSS Distributions 			break;
3861a5e72196SApple OSS Distributions 
3862a5e72196SApple OSS Distributions 		case MACH_MSG_OOL_DESCRIPTOR:
3863a5e72196SApple OSS Distributions 			descsize = sizeof(mach_msg_ool_descriptor_t);
3864a5e72196SApple OSS Distributions 			ool = (typeof(ool))desc;
3865a5e72196SApple OSS Distributions 			copy = (vm_map_copy_t) ool->address;
3866a5e72196SApple OSS Distributions 			if (copy) {
3867a5e72196SApple OSS Distributions 				vm_map_copy_discard(copy);
3868a5e72196SApple OSS Distributions 			}
3869a5e72196SApple OSS Distributions 			break;
3870a5e72196SApple OSS Distributions 
3871a5e72196SApple OSS Distributions 		default:
3872a5e72196SApple OSS Distributions 			descsize = -1UL;
3873a5e72196SApple OSS Distributions 			break;
3874a5e72196SApple OSS Distributions 		}
3875a5e72196SApple OSS Distributions 		if (-1UL == descsize) {
3876a5e72196SApple OSS Distributions 			break;
3877a5e72196SApple OSS Distributions 		}
3878a5e72196SApple OSS Distributions 		desc = (typeof(desc))(((uintptr_t) desc) + descsize);
3879a5e72196SApple OSS Distributions 	}
3880a5e72196SApple OSS Distributions 
3881a5e72196SApple OSS Distributions 	return kIOReturnBadArgument;
3882a5e72196SApple OSS Distributions }
3883a5e72196SApple OSS Distributions 
3884a5e72196SApple OSS Distributions IOReturn
copyInObjects(IORPCMessageMach * mach,IORPCMessage * message,size_t size,bool copyObjects,bool consumePorts)3885a5e72196SApple OSS Distributions IOUserServer::copyInObjects(IORPCMessageMach * mach, IORPCMessage * message,
3886a5e72196SApple OSS Distributions     size_t size, bool copyObjects, bool consumePorts)
3887a5e72196SApple OSS Distributions {
3888a5e72196SApple OSS Distributions 	uint64_t           refs;
3889a5e72196SApple OSS Distributions 	uint32_t           idx, maxObjectCount;
3890a5e72196SApple OSS Distributions 	ipc_port_t         port;
3891a5e72196SApple OSS Distributions 	OSObject         * object;
3892a5e72196SApple OSS Distributions 	size_t                       descsize;
3893a5e72196SApple OSS Distributions 	mach_msg_port_descriptor_t * desc;
3894a5e72196SApple OSS Distributions 	mach_msg_ool_descriptor_t  * ool;
3895a5e72196SApple OSS Distributions 	vm_map_address_t             copyoutdata;
3896a5e72196SApple OSS Distributions 	kern_return_t                kr;
3897a5e72196SApple OSS Distributions 
3898a5e72196SApple OSS Distributions 	refs           = message->objectRefs;
3899a5e72196SApple OSS Distributions 	maxObjectCount = MAX_OBJECT_COUNT(mach, size, message);
3900a5e72196SApple OSS Distributions //	assert(refs <= mach->msgh_body.msgh_descriptor_count);
3901a5e72196SApple OSS Distributions //	assert(refs <= maxObjectCount);
3902a5e72196SApple OSS Distributions 	if (refs > mach->msgh_body.msgh_descriptor_count) {
3903a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3904a5e72196SApple OSS Distributions 	}
3905a5e72196SApple OSS Distributions 	if (refs > maxObjectCount) {
3906a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3907a5e72196SApple OSS Distributions 	}
3908a5e72196SApple OSS Distributions 
3909a5e72196SApple OSS Distributions 	for (idx = 0; idx < refs; idx++) {
39108d741a5dSApple OSS Distributions 		message->objects[idx] = (OSObjectRef) NULL;
39118d741a5dSApple OSS Distributions 	}
39128d741a5dSApple OSS Distributions 
39138d741a5dSApple OSS Distributions 	desc = &mach->objects[0];
39148d741a5dSApple OSS Distributions 	for (idx = 0; idx < mach->msgh_body.msgh_descriptor_count; idx++) {
39158d741a5dSApple OSS Distributions 		bool isObjectPort = idx < refs;
39168d741a5dSApple OSS Distributions 
3917a5e72196SApple OSS Distributions 		switch (desc->type) {
3918a5e72196SApple OSS Distributions 		case MACH_MSG_PORT_DESCRIPTOR:
3919a5e72196SApple OSS Distributions 			descsize = sizeof(mach_msg_port_descriptor_t);
3920a5e72196SApple OSS Distributions 
3921a5e72196SApple OSS Distributions 			object = NULL;
3922a5e72196SApple OSS Distributions 			port = desc->name;
3923a5e72196SApple OSS Distributions 			if (port) {
39248d741a5dSApple OSS Distributions 				if (isObjectPort && copyObjects) {
3925a5e72196SApple OSS Distributions 					object = copyObjectForSendRight(port, IKOT_UEXT_OBJECT);
3926a5e72196SApple OSS Distributions 					if (!object) {
3927a5e72196SApple OSS Distributions 						descsize = -1UL;
3928a5e72196SApple OSS Distributions 						break;
3929a5e72196SApple OSS Distributions 					}
3930a5e72196SApple OSS Distributions 				}
3931a5e72196SApple OSS Distributions 				if (consumePorts) {
3932a5e72196SApple OSS Distributions 					ipc_port_release_send(port);
39338d741a5dSApple OSS Distributions 					desc->name = MACH_PORT_NULL;
3934a5e72196SApple OSS Distributions 				}
3935a5e72196SApple OSS Distributions 			}
3936a5e72196SApple OSS Distributions 			break;
3937a5e72196SApple OSS Distributions 
3938a5e72196SApple OSS Distributions 		case MACH_MSG_OOL_DESCRIPTOR:
3939a5e72196SApple OSS Distributions 			descsize = sizeof(mach_msg_ool_descriptor_t);
3940a5e72196SApple OSS Distributions 			ool = (typeof(ool))desc;
3941a5e72196SApple OSS Distributions 
3942a5e72196SApple OSS Distributions 			object = NULL;
39438d741a5dSApple OSS Distributions 			if (isObjectPort && copyObjects && ool->size && ool->address) {
3944a5e72196SApple OSS Distributions 				kr = vm_map_copyout(kernel_map, &copyoutdata, (vm_map_copy_t) ool->address);
3945a5e72196SApple OSS Distributions 				if (KERN_SUCCESS == kr) {
3946a5e72196SApple OSS Distributions 					object = OSUnserializeXML((const char *) copyoutdata, ool->size);
3947e6231be0SApple OSS Distributions 					kr = vm_deallocate(kernel_map, copyoutdata, ool->size);
3948e6231be0SApple OSS Distributions 					assert(KERN_SUCCESS == kr);
3949a5e72196SApple OSS Distributions 					// vm_map_copyout() has consumed the vm_map_copy_t in the message
3950a5e72196SApple OSS Distributions 					ool->size = 0;
3951a5e72196SApple OSS Distributions 					ool->address = NULL;
3952a5e72196SApple OSS Distributions 				}
3953a5e72196SApple OSS Distributions 				if (!object) {
3954a5e72196SApple OSS Distributions 					descsize = -1UL;
3955a5e72196SApple OSS Distributions 					break;
3956a5e72196SApple OSS Distributions 				}
3957a5e72196SApple OSS Distributions 			}
3958a5e72196SApple OSS Distributions 			break;
3959a5e72196SApple OSS Distributions 
3960a5e72196SApple OSS Distributions 		default:
3961a5e72196SApple OSS Distributions 			descsize = -1UL;
3962a5e72196SApple OSS Distributions 			break;
3963a5e72196SApple OSS Distributions 		}
3964a5e72196SApple OSS Distributions 		if (-1UL == descsize) {
3965a5e72196SApple OSS Distributions 			break;
3966a5e72196SApple OSS Distributions 		}
39678d741a5dSApple OSS Distributions 		if (isObjectPort && copyObjects) {
3968a5e72196SApple OSS Distributions 			message->objects[idx] = (OSObjectRef) object;
3969a5e72196SApple OSS Distributions 		}
3970a5e72196SApple OSS Distributions 		desc = (typeof(desc))(((uintptr_t) desc) + descsize);
3971a5e72196SApple OSS Distributions 	}
3972a5e72196SApple OSS Distributions 
3973a5e72196SApple OSS Distributions 	if (idx >= refs) {
3974a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
3975a5e72196SApple OSS Distributions 	}
3976a5e72196SApple OSS Distributions 
3977a5e72196SApple OSS Distributions 	while (idx--) {
3978a5e72196SApple OSS Distributions 		object = (OSObject *) message->objects[idx];
3979e7776783SApple OSS Distributions 		OSSafeReleaseNULL(object);
3980a5e72196SApple OSS Distributions 		message->objects[idx] = 0;
3981a5e72196SApple OSS Distributions 	}
3982a5e72196SApple OSS Distributions 
3983a5e72196SApple OSS Distributions 	return kIOReturnBadArgument;
3984a5e72196SApple OSS Distributions }
3985a5e72196SApple OSS Distributions 
3986a5e72196SApple OSS Distributions IOReturn
consumeObjects(IORPCMessageMach * mach,IORPCMessage * message,size_t messageSize)39878d741a5dSApple OSS Distributions IOUserServer::consumeObjects(IORPCMessageMach *mach, IORPCMessage * message, size_t messageSize)
3988a5e72196SApple OSS Distributions {
3989a5e72196SApple OSS Distributions 	uint64_t    refs, idx;
3990a5e72196SApple OSS Distributions 	OSObject  * object;
3991a5e72196SApple OSS Distributions 
3992a5e72196SApple OSS Distributions 	refs   = message->objectRefs;
39938d741a5dSApple OSS Distributions 	uint32_t maxObjectCount = MAX_OBJECT_COUNT(mach, messageSize, message);
39948d741a5dSApple OSS Distributions 	if (refs > mach->msgh_body.msgh_descriptor_count) {
39958d741a5dSApple OSS Distributions 		return kIOReturnBadArgument;
39968d741a5dSApple OSS Distributions 	}
39978d741a5dSApple OSS Distributions 	if (refs > maxObjectCount) {
39988d741a5dSApple OSS Distributions 		return kIOReturnBadArgument;
39998d741a5dSApple OSS Distributions 	}
40008d741a5dSApple OSS Distributions 
4001a5e72196SApple OSS Distributions 	for (idx = 0; idx < refs; idx++) {
4002a5e72196SApple OSS Distributions 		object = (OSObject *) message->objects[idx];
4003a5e72196SApple OSS Distributions 		if (object) {
4004a5e72196SApple OSS Distributions 			object->release();
4005a5e72196SApple OSS Distributions 			message->objects[idx] = 0;
4006a5e72196SApple OSS Distributions 		}
4007a5e72196SApple OSS Distributions 	}
4008a5e72196SApple OSS Distributions 
4009a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4010a5e72196SApple OSS Distributions }
4011a5e72196SApple OSS Distributions 
4012a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4013a5e72196SApple OSS Distributions 
4014*4f1223e8SApple OSS Distributions static kern_return_t
4015*4f1223e8SApple OSS Distributions acknowledgeSetPowerState(IOService * service);
4016*4f1223e8SApple OSS Distributions 
4017a5e72196SApple OSS Distributions bool
finalize(IOOptionBits options)4018a5e72196SApple OSS Distributions IOUserServer::finalize(IOOptionBits options)
4019a5e72196SApple OSS Distributions {
4020a5e72196SApple OSS Distributions 	OSArray   * services;
4021a5e72196SApple OSS Distributions 
4022a5e72196SApple OSS Distributions 	if (kIODKLogSetup & gIODKDebug) {
4023a5e72196SApple OSS Distributions 		DKLOG("%s::finalize(%p)\n", getName(), this);
4024a5e72196SApple OSS Distributions 	}
4025a5e72196SApple OSS Distributions 
4026a5e72196SApple OSS Distributions 	IOLockLock(gIOUserServerLock);
4027a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(fRootQueue);
4028a5e72196SApple OSS Distributions 	IOLockUnlock(gIOUserServerLock);
4029a5e72196SApple OSS Distributions 
4030a5e72196SApple OSS Distributions 	services = NULL;
4031a5e72196SApple OSS Distributions 	IOLockLock(fLock);
4032a5e72196SApple OSS Distributions 	if (fServices) {
4033a5e72196SApple OSS Distributions 		services = OSArray::withArray(fServices);
4034a5e72196SApple OSS Distributions 	}
4035a5e72196SApple OSS Distributions 	IOLockUnlock(fLock);
4036a5e72196SApple OSS Distributions 
40375c2921b0SApple OSS Distributions 	IOOptionBits terminateFlags = kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch;
40385c2921b0SApple OSS Distributions 	if (fCheckInToken) {
40395c2921b0SApple OSS Distributions 		bool can_rematch = fCheckInToken->dextTerminate();
40405c2921b0SApple OSS Distributions 		if (can_rematch) {
40415c2921b0SApple OSS Distributions 			terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
40425c2921b0SApple OSS Distributions 		} else {
40435c2921b0SApple OSS Distributions 			DKLOG("%s::finalize(%p) dext was replaced, do not rematch current dext\n", getName(), this);
40445c2921b0SApple OSS Distributions 		}
40455c2921b0SApple OSS Distributions 	} else {
40465c2921b0SApple OSS Distributions 		terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
40475c2921b0SApple OSS Distributions 		DKLOG("%s::finalize(%p) could not find fCheckInToken\n", getName(), this);
40485c2921b0SApple OSS Distributions 	}
40495c2921b0SApple OSS Distributions 
4050a5e72196SApple OSS Distributions 	if (services) {
4051a5e72196SApple OSS Distributions 		services->iterateObjects(^bool (OSObject * obj) {
4052e6231be0SApple OSS Distributions 			int         service __unused;       // hide outer defn
4053e6231be0SApple OSS Distributions 			IOService * nextService;
4054a5e72196SApple OSS Distributions 			IOService * provider;
4055a5e72196SApple OSS Distributions 			bool        started = false;
4056a5e72196SApple OSS Distributions 
4057e6231be0SApple OSS Distributions 			nextService = (IOService *) obj;
4058a5e72196SApple OSS Distributions 			if (kIODKLogSetup & gIODKDebug) {
4059e6231be0SApple OSS Distributions 			        DKLOG("%s::terminate(" DKS ")\n", getName(), DKN(nextService));
4060a5e72196SApple OSS Distributions 			}
4061e6231be0SApple OSS Distributions 			if (nextService->reserved->uvars) {
40625c2921b0SApple OSS Distributions 			        IOUserClient * nextUserClient = OSDynamicCast(IOUserClient, nextService);
40635c2921b0SApple OSS Distributions 			        provider = nextService->getProvider();
40645c2921b0SApple OSS Distributions 			        if (nextUserClient) {
40655c2921b0SApple OSS Distributions 			                nextUserClient->setTerminateDefer(provider, false);
40665c2921b0SApple OSS Distributions 				}
4067*4f1223e8SApple OSS Distributions 			        (void)::acknowledgeSetPowerState(nextService);
4068e6231be0SApple OSS Distributions 			        started = nextService->reserved->uvars->started;
4069e6231be0SApple OSS Distributions 			        nextService->reserved->uvars->serverDied = true;
40705c2921b0SApple OSS Distributions 
4071e6231be0SApple OSS Distributions 			        serviceDidStop(nextService, provider);
40725c2921b0SApple OSS Distributions 			        if (provider != NULL && (terminateFlags & kIOServiceTerminateWithRematchCurrentDext) == 0) {
40735c2921b0SApple OSS Distributions 			                provider->resetRematchProperties();
40745c2921b0SApple OSS Distributions 				}
40755c2921b0SApple OSS Distributions 			        if (started) {
40765c2921b0SApple OSS Distributions 			                nextService->terminate(terminateFlags);
4077a5e72196SApple OSS Distributions 				}
4078a5e72196SApple OSS Distributions 			}
4079a5e72196SApple OSS Distributions 			if (!started) {
4080e6231be0SApple OSS Distributions 			        DKLOG("%s::terminate(" DKS ") server exit before start()\n", getName(), DKN(nextService));
4081e6231be0SApple OSS Distributions 			        serviceStop(nextService, NULL);
4082a5e72196SApple OSS Distributions 			}
4083a5e72196SApple OSS Distributions 			return false;
4084a5e72196SApple OSS Distributions 		});
4085a5e72196SApple OSS Distributions 		services->release();
4086a5e72196SApple OSS Distributions 	}
4087a5e72196SApple OSS Distributions 
4088a5e72196SApple OSS Distributions 	return IOUserClient::finalize(options);
4089a5e72196SApple OSS Distributions }
4090a5e72196SApple OSS Distributions 
4091a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4092a5e72196SApple OSS Distributions 
4093a5e72196SApple OSS Distributions #undef super
40945c2921b0SApple OSS Distributions #define super IOUserClient2022
4095a5e72196SApple OSS Distributions 
OSDefineMetaClassAndStructors(IOUserServer,IOUserClient2022)40965c2921b0SApple OSS Distributions OSDefineMetaClassAndStructors(IOUserServer, IOUserClient2022)
4097a5e72196SApple OSS Distributions 
4098a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4099a5e72196SApple OSS Distributions 
4100a5e72196SApple OSS Distributions IOUserClient * IOUserServer::withTask(task_t owningTask)
4101a5e72196SApple OSS Distributions {
4102a5e72196SApple OSS Distributions 	IOUserServer * inst;
4103a5e72196SApple OSS Distributions 
4104e6231be0SApple OSS Distributions 	assert(owningTask == current_task());
4105e6231be0SApple OSS Distributions 	if (!task_is_driver(owningTask)) {
4106e6231be0SApple OSS Distributions 		DKLOG("IOUserServer may only be created with driver tasks\n");
4107e6231be0SApple OSS Distributions 		return NULL;
4108e6231be0SApple OSS Distributions 	}
4109e6231be0SApple OSS Distributions 
4110a5e72196SApple OSS Distributions 	inst = new IOUserServer;
4111a5e72196SApple OSS Distributions 	if (inst && !inst->init()) {
4112a5e72196SApple OSS Distributions 		inst->release();
4113a5e72196SApple OSS Distributions 		inst = NULL;
4114a5e72196SApple OSS Distributions 		return inst;
4115a5e72196SApple OSS Distributions 	}
4116e7776783SApple OSS Distributions 	OS_ANALYZER_SUPPRESS("82033761") inst->PMinit();
4117a5e72196SApple OSS Distributions 
4118a5e72196SApple OSS Distributions 	inst->fOwningTask = current_task();
41195c2921b0SApple OSS Distributions 	task_reference(inst->fOwningTask);
41205c2921b0SApple OSS Distributions 
4121a5e72196SApple OSS Distributions 	inst->fEntitlements = IOUserClient::copyClientEntitlements(inst->fOwningTask);
4122a5e72196SApple OSS Distributions 
4123a5e72196SApple OSS Distributions 	if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
4124a5e72196SApple OSS Distributions 		proc_t p;
4125a5e72196SApple OSS Distributions 		pid_t  pid;
4126e7776783SApple OSS Distributions 		const char * name;
4127a5e72196SApple OSS Distributions 		p = (proc_t)get_bsdtask_info(inst->fOwningTask);
4128a5e72196SApple OSS Distributions 		if (p) {
4129e7776783SApple OSS Distributions 			name = proc_best_name(p);
4130a5e72196SApple OSS Distributions 			pid = proc_pid(p);
4131e7776783SApple OSS Distributions 		} else {
4132e7776783SApple OSS Distributions 			name = "unknown";
4133e7776783SApple OSS Distributions 			pid = 0;
4134a5e72196SApple OSS Distributions 		}
4135e7776783SApple OSS Distributions 
4136e7776783SApple OSS Distributions 		if (inst->fEntitlements == NULL) {
4137e7776783SApple OSS Distributions #if DEVELOPMENT || DEBUG
4138e7776783SApple OSS Distributions 			panic("entitlements are missing for %s[%d]\n", name, pid);
4139e7776783SApple OSS Distributions #else
4140e7776783SApple OSS Distributions 			DKLOG("entitlements are missing for %s[%d]\n", name, pid);
4141e7776783SApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
4142e7776783SApple OSS Distributions 		}
4143e7776783SApple OSS Distributions 
41445c2921b0SApple OSS Distributions 
41455c2921b0SApple OSS Distributions 		const char * dextTeamID = csproc_get_teamid(p);
41465c2921b0SApple OSS Distributions 		if (dextTeamID != NULL) {
41475c2921b0SApple OSS Distributions 			inst->fTeamIdentifier = OSString::withCString(dextTeamID);
41485c2921b0SApple OSS Distributions 			DKLOG("%s[%d] has team identifier %s\n", name, pid, dextTeamID);
41495c2921b0SApple OSS Distributions 		}
41505c2921b0SApple OSS Distributions 
4151e7776783SApple OSS Distributions 		if (!IOCurrentTaskHasEntitlement(gIODriverKitEntitlementKey->getCStringNoCopy())) {
4152e7776783SApple OSS Distributions 			IOLog(kIODriverKitEntitlementKey " entitlement check failed for %s[%d]\n", name, pid);
4153a5e72196SApple OSS Distributions 			inst->release();
4154a5e72196SApple OSS Distributions 			inst = NULL;
4155a5e72196SApple OSS Distributions 			return inst;
4156a5e72196SApple OSS Distributions 		}
4157a5e72196SApple OSS Distributions 	}
4158a5e72196SApple OSS Distributions 
4159bb611c8fSApple OSS Distributions 	/* Mark the current task's space as eligible for uext object ports */
4160bb611c8fSApple OSS Distributions 	iokit_label_dext_task(inst->fOwningTask);
4161bb611c8fSApple OSS Distributions 
4162a5e72196SApple OSS Distributions 	inst->fLock     = IOLockAlloc();
4163a5e72196SApple OSS Distributions 	inst->fServices = OSArray::withCapacity(4);
4164a5e72196SApple OSS Distributions 	inst->fClasses  = OSDictionary::withCapacity(16);
4165a5e72196SApple OSS Distributions 	inst->fClasses->setOptions(OSCollection::kSort, OSCollection::kSort);
41665c2921b0SApple OSS Distributions 	inst->fPlatformDriver = task_get_platform_binary(inst->fOwningTask);
41675c2921b0SApple OSS Distributions 	if (csproc_get_validation_category(current_proc(), &inst->fCSValidationCategory) != KERN_SUCCESS) {
41685c2921b0SApple OSS Distributions 		inst->fCSValidationCategory = CS_VALIDATION_CATEGORY_INVALID;
41695c2921b0SApple OSS Distributions 	}
4170*4f1223e8SApple OSS Distributions 	inst->fWorkLoop = IOWorkLoop::workLoop();
41715c2921b0SApple OSS Distributions 
41725c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
41735c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue);
41745c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey, kOSBooleanTrue);
41755c2921b0SApple OSS Distributions 	//requirement for gIODriverKitEntitlementKey is enforced elsewhere conditionally
41765c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientEntitlementsKey, kOSBooleanFalse);
4177a5e72196SApple OSS Distributions 
4178a5e72196SApple OSS Distributions 	return inst;
4179a5e72196SApple OSS Distributions }
4180a5e72196SApple OSS Distributions 
41815c2921b0SApple OSS Distributions static bool gIOUserServerLeakObjects = false;
41825c2921b0SApple OSS Distributions 
41835c2921b0SApple OSS Distributions bool
shouldLeakObjects()41845c2921b0SApple OSS Distributions IOUserServer::shouldLeakObjects()
41855c2921b0SApple OSS Distributions {
41865c2921b0SApple OSS Distributions 	return gIOUserServerLeakObjects;
41875c2921b0SApple OSS Distributions }
41885c2921b0SApple OSS Distributions 
41895c2921b0SApple OSS Distributions void
beginLeakingObjects()41905c2921b0SApple OSS Distributions IOUserServer::beginLeakingObjects()
41915c2921b0SApple OSS Distributions {
41925c2921b0SApple OSS Distributions 	gIOUserServerLeakObjects = true;
41935c2921b0SApple OSS Distributions }
41945c2921b0SApple OSS Distributions 
41955c2921b0SApple OSS Distributions bool
isPlatformDriver()41965c2921b0SApple OSS Distributions IOUserServer::isPlatformDriver()
41975c2921b0SApple OSS Distributions {
41985c2921b0SApple OSS Distributions 	return fPlatformDriver;
41995c2921b0SApple OSS Distributions }
42005c2921b0SApple OSS Distributions 
42015c2921b0SApple OSS Distributions int
getCSValidationCategory()42025c2921b0SApple OSS Distributions IOUserServer::getCSValidationCategory()
42035c2921b0SApple OSS Distributions {
42045c2921b0SApple OSS Distributions 	return fCSValidationCategory;
42055c2921b0SApple OSS Distributions }
42065c2921b0SApple OSS Distributions 
42075c2921b0SApple OSS Distributions 
42085c2921b0SApple OSS Distributions struct IOUserServerRecordExitReasonContext {
42095c2921b0SApple OSS Distributions 	task_t task;
42105c2921b0SApple OSS Distributions 	os_reason_t reason;
42115c2921b0SApple OSS Distributions };
42125c2921b0SApple OSS Distributions 
42135c2921b0SApple OSS Distributions static bool
IOUserServerRecordExitReasonMatch(const OSObject * obj,void * context)42145c2921b0SApple OSS Distributions IOUserServerRecordExitReasonMatch(const OSObject *obj, void * context)
42155c2921b0SApple OSS Distributions {
42165c2921b0SApple OSS Distributions 	IOUserServerRecordExitReasonContext * ctx = (IOUserServerRecordExitReasonContext *)context;
42175c2921b0SApple OSS Distributions 	IOUserServer * us = OSDynamicCast(IOUserServer, obj);
42185c2921b0SApple OSS Distributions 	if (us == NULL) {
42195c2921b0SApple OSS Distributions 		return false;
42205c2921b0SApple OSS Distributions 	}
42215c2921b0SApple OSS Distributions 
42225c2921b0SApple OSS Distributions 	if (us->fOwningTask == ctx->task) {
42235c2921b0SApple OSS Distributions 		assert(us->fTaskCrashReason == OS_REASON_NULL);
42245c2921b0SApple OSS Distributions 		assert(ctx->reason != OS_REASON_NULL);
42255c2921b0SApple OSS Distributions 		os_reason_ref(ctx->reason);
42265c2921b0SApple OSS Distributions 		us->fTaskCrashReason = ctx->reason;
42275c2921b0SApple OSS Distributions 		return true;
42285c2921b0SApple OSS Distributions 	}
42295c2921b0SApple OSS Distributions 
42305c2921b0SApple OSS Distributions 	return false;
42315c2921b0SApple OSS Distributions }
42325c2921b0SApple OSS Distributions 
42335c2921b0SApple OSS Distributions extern "C" void
IOUserServerRecordExitReason(task_t task,os_reason_t reason)42345c2921b0SApple OSS Distributions IOUserServerRecordExitReason(task_t task, os_reason_t reason)
42355c2921b0SApple OSS Distributions {
42365c2921b0SApple OSS Distributions 	IOUserServerRecordExitReasonContext ctx { task, reason };
42375c2921b0SApple OSS Distributions 	IOUserServer::gMetaClass.applyToInstances(IOUserServerRecordExitReasonMatch, &ctx);
42385c2921b0SApple OSS Distributions }
42395c2921b0SApple OSS Distributions 
4240a5e72196SApple OSS Distributions IOReturn
clientClose(void)4241a5e72196SApple OSS Distributions IOUserServer::clientClose(void)
4242a5e72196SApple OSS Distributions {
4243e6231be0SApple OSS Distributions 	OSArray   * services;
42445c2921b0SApple OSS Distributions 	bool __block unexpectedExit = false;
4245e6231be0SApple OSS Distributions 
4246e6231be0SApple OSS Distributions 	if (kIODKLogSetup & gIODKDebug) {
4247e6231be0SApple OSS Distributions 		DKLOG("%s::clientClose(%p)\n", getName(), this);
4248e6231be0SApple OSS Distributions 	}
4249e6231be0SApple OSS Distributions 	services = NULL;
4250e6231be0SApple OSS Distributions 	IOLockLock(fLock);
4251e6231be0SApple OSS Distributions 	if (fServices) {
4252e6231be0SApple OSS Distributions 		services = OSArray::withArray(fServices);
4253e6231be0SApple OSS Distributions 	}
4254e6231be0SApple OSS Distributions 	IOLockUnlock(fLock);
4255e6231be0SApple OSS Distributions 
4256e6231be0SApple OSS Distributions 	// if this was a an expected exit, termination and stop should have detached at this
4257e6231be0SApple OSS Distributions 	// point, so send any provider still attached and not owned by this user server
4258e6231be0SApple OSS Distributions 	// the ClientCrashed() notification
4259e6231be0SApple OSS Distributions 	if (services) {
4260e6231be0SApple OSS Distributions 		services->iterateObjects(^bool (OSObject * obj) {
4261e6231be0SApple OSS Distributions 			int         service __unused;       // hide outer defn
4262e6231be0SApple OSS Distributions 			IOService * nextService;
4263e6231be0SApple OSS Distributions 			IOService * provider;
4264e6231be0SApple OSS Distributions 
4265e6231be0SApple OSS Distributions 			nextService = (IOService *) obj;
4266e6231be0SApple OSS Distributions 			if (nextService->isInactive()) {
4267e6231be0SApple OSS Distributions 			        return false;
4268e6231be0SApple OSS Distributions 			}
42695c2921b0SApple OSS Distributions 			if (nextService->reserved && nextService->reserved->uvars && nextService->reserved->uvars->started) {
42705c2921b0SApple OSS Distributions 			        unexpectedExit = true;
42715c2921b0SApple OSS Distributions 			}
4272e6231be0SApple OSS Distributions 			provider = nextService->getProvider();
4273e6231be0SApple OSS Distributions 			if (provider
4274e6231be0SApple OSS Distributions 			&& (!provider->reserved->uvars || (provider->reserved->uvars->userServer != this))) {
4275e6231be0SApple OSS Distributions 			        if (kIODKLogSetup & gIODKDebug) {
4276e6231be0SApple OSS Distributions 			                DKLOG(DKS "::ClientCrashed(" DKS ")\n", DKN(provider), DKN(nextService));
4277e6231be0SApple OSS Distributions 				}
42788d741a5dSApple OSS Distributions 			        if (unexpectedExit) {
42798d741a5dSApple OSS Distributions 			                provider->unregisterAllInterrupts();
42808d741a5dSApple OSS Distributions 				}
4281e6231be0SApple OSS Distributions 			        provider->ClientCrashed(nextService, 0);
4282e6231be0SApple OSS Distributions 			}
4283e6231be0SApple OSS Distributions 			return false;
4284e6231be0SApple OSS Distributions 		});
4285e6231be0SApple OSS Distributions 		services->release();
4286e6231be0SApple OSS Distributions 	}
4287e6231be0SApple OSS Distributions 
42885c2921b0SApple OSS Distributions 	if (unexpectedExit &&
42895c2921b0SApple OSS Distributions 	    !gInUserspaceReboot &&
429094d3b452SApple OSS Distributions 	    (fTaskCrashReason != OS_REASON_NULL && fTaskCrashReason->osr_namespace != OS_REASON_JETSAM && fTaskCrashReason->osr_namespace != OS_REASON_RUNNINGBOARD) &&
42915c2921b0SApple OSS Distributions 	    fStatistics != NULL) {
42925c2921b0SApple OSS Distributions 		OSDextCrashPolicy policy = fStatistics->recordCrash();
42931031c584SApple OSS Distributions 		bool allowPanic;
42945c2921b0SApple OSS Distributions #if DEVELOPMENT || DEBUG
42958d741a5dSApple OSS Distributions 		allowPanic = !restore_boot && fPlatformDriver && fEntitlements->getObject(gIODriverKitTestDriverEntitlementKey) != kOSBooleanTrue && !disable_dext_crash_reboot;
42965c2921b0SApple OSS Distributions #else
42978d741a5dSApple OSS Distributions 		allowPanic = !restore_boot && fPlatformDriver;
42985c2921b0SApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
42995c2921b0SApple OSS Distributions 
43001031c584SApple OSS Distributions 		if (policy == kOSDextCrashPolicyReboot && allowPanic) {
43011031c584SApple OSS Distributions 			panic("Driver %s has crashed too many times\n", getName());
43025c2921b0SApple OSS Distributions 		}
43035c2921b0SApple OSS Distributions 	}
43045c2921b0SApple OSS Distributions 
4305a5e72196SApple OSS Distributions 	terminate();
4306a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4307a5e72196SApple OSS Distributions }
4308a5e72196SApple OSS Distributions 
4309a5e72196SApple OSS Distributions IOReturn
setProperties(OSObject * properties)4310a5e72196SApple OSS Distributions IOUserServer::setProperties(OSObject * properties)
4311a5e72196SApple OSS Distributions {
4312a5e72196SApple OSS Distributions 	IOReturn kr = kIOReturnUnsupported;
4313a5e72196SApple OSS Distributions 	return kr;
4314a5e72196SApple OSS Distributions }
4315a5e72196SApple OSS Distributions 
4316a5e72196SApple OSS Distributions void
stop(IOService * provider)4317a5e72196SApple OSS Distributions IOUserServer::stop(IOService * provider)
4318a5e72196SApple OSS Distributions {
43195c2921b0SApple OSS Distributions 	if (fOwningTask) {
43205c2921b0SApple OSS Distributions 		task_deallocate(fOwningTask);
4321a5e72196SApple OSS Distributions 		fOwningTask = TASK_NULL;
43225c2921b0SApple OSS Distributions 	}
4323a5e72196SApple OSS Distributions 
4324a5e72196SApple OSS Distributions 	PMstop();
4325a5e72196SApple OSS Distributions 
4326a5e72196SApple OSS Distributions 	IOServicePH::serverRemove(this);
4327a5e72196SApple OSS Distributions 
4328a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(fRootQueue);
4329a5e72196SApple OSS Distributions 
4330a5e72196SApple OSS Distributions 	if (fInterruptLock) {
4331a5e72196SApple OSS Distributions 		IOSimpleLockFree(fInterruptLock);
4332a5e72196SApple OSS Distributions 	}
4333a5e72196SApple OSS Distributions }
4334a5e72196SApple OSS Distributions 
4335*4f1223e8SApple OSS Distributions IOWorkLoop *
getWorkLoop() const4336*4f1223e8SApple OSS Distributions IOUserServer::getWorkLoop() const
4337*4f1223e8SApple OSS Distributions {
4338*4f1223e8SApple OSS Distributions 	return fWorkLoop;
4339*4f1223e8SApple OSS Distributions }
4340*4f1223e8SApple OSS Distributions 
4341a5e72196SApple OSS Distributions void
free()4342a5e72196SApple OSS Distributions IOUserServer::free()
4343a5e72196SApple OSS Distributions {
4344a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(fEntitlements);
4345a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(fClasses);
43465c2921b0SApple OSS Distributions 	if (fOwningTask) {
43475c2921b0SApple OSS Distributions 		task_deallocate(fOwningTask);
43485c2921b0SApple OSS Distributions 		fOwningTask = TASK_NULL;
43495c2921b0SApple OSS Distributions 	}
4350a5e72196SApple OSS Distributions 	if (fLock) {
4351a5e72196SApple OSS Distributions 		IOLockFree(fLock);
4352a5e72196SApple OSS Distributions 	}
4353a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(fServices);
4354bb611c8fSApple OSS Distributions 	OSSafeReleaseNULL(fCheckInToken);
43555c2921b0SApple OSS Distributions 	OSSafeReleaseNULL(fStatistics);
43565c2921b0SApple OSS Distributions 	OSSafeReleaseNULL(fTeamIdentifier);
4357e6231be0SApple OSS Distributions 	if (fAllocationName) {
4358e6231be0SApple OSS Distributions 		kern_allocation_name_release(fAllocationName);
4359e6231be0SApple OSS Distributions 		fAllocationName = NULL;
4360e6231be0SApple OSS Distributions 	}
43615c2921b0SApple OSS Distributions 	if (fTaskCrashReason != OS_REASON_NULL) {
43625c2921b0SApple OSS Distributions 		os_reason_free(fTaskCrashReason);
43635c2921b0SApple OSS Distributions 	}
4364*4f1223e8SApple OSS Distributions 	OSSafeReleaseNULL(fWorkLoop);
4365a5e72196SApple OSS Distributions 	IOUserClient::free();
4366a5e72196SApple OSS Distributions }
4367a5e72196SApple OSS Distributions 
4368a5e72196SApple OSS Distributions IOReturn
registerClass(OSClassDescription * desc,uint32_t size,OSUserMetaClass ** pCls)4369a5e72196SApple OSS Distributions IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSUserMetaClass ** pCls)
4370a5e72196SApple OSS Distributions {
4371a5e72196SApple OSS Distributions 	OSUserMetaClass * cls;
4372a5e72196SApple OSS Distributions 	const OSSymbol  * sym;
4373a5e72196SApple OSS Distributions 	uint64_t        * methodOptions;
4374a5e72196SApple OSS Distributions 	const char      * queueNames;
4375a5e72196SApple OSS Distributions 	uint32_t          methodOptionsEnd, queueNamesEnd;
4376a5e72196SApple OSS Distributions 	IOReturn          ret = kIOReturnSuccess;
4377a5e72196SApple OSS Distributions 
4378a5e72196SApple OSS Distributions 	if (size < sizeof(OSClassDescription)) {
4379a5e72196SApple OSS Distributions 		assert(false);
4380a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4381a5e72196SApple OSS Distributions 	}
4382a5e72196SApple OSS Distributions 
4383a5e72196SApple OSS Distributions 	if (kIODKLogSetup & gIODKDebug) {
4384a5e72196SApple OSS Distributions 		DKLOG("%s::registerClass %s, %d, %d\n", getName(), desc->name, desc->queueNamesSize, desc->methodNamesSize);
4385a5e72196SApple OSS Distributions 	}
4386a5e72196SApple OSS Distributions 
4387a5e72196SApple OSS Distributions 	if (desc->descriptionSize != size) {
4388a5e72196SApple OSS Distributions 		assert(false);
4389a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4390a5e72196SApple OSS Distributions 	}
4391a5e72196SApple OSS Distributions 	if (os_add_overflow(desc->queueNamesOffset, desc->queueNamesSize, &queueNamesEnd)) {
4392a5e72196SApple OSS Distributions 		assert(false);
4393a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4394a5e72196SApple OSS Distributions 	}
4395a5e72196SApple OSS Distributions 	if (queueNamesEnd > size) {
4396a5e72196SApple OSS Distributions 		assert(false);
4397a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4398a5e72196SApple OSS Distributions 	}
4399a5e72196SApple OSS Distributions 	if (os_add_overflow(desc->methodOptionsOffset, desc->methodOptionsSize, &methodOptionsEnd)) {
4400a5e72196SApple OSS Distributions 		assert(false);
4401a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4402a5e72196SApple OSS Distributions 	}
4403a5e72196SApple OSS Distributions 	if (methodOptionsEnd > size) {
4404a5e72196SApple OSS Distributions 		assert(false);
4405a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4406a5e72196SApple OSS Distributions 	}
4407a5e72196SApple OSS Distributions 	// overlaps?
4408a5e72196SApple OSS Distributions 	if ((desc->queueNamesOffset >= desc->methodOptionsOffset) && (desc->queueNamesOffset < methodOptionsEnd)) {
4409a5e72196SApple OSS Distributions 		assert(false);
4410a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4411a5e72196SApple OSS Distributions 	}
4412a5e72196SApple OSS Distributions 	if ((queueNamesEnd >= desc->methodOptionsOffset) && (queueNamesEnd < methodOptionsEnd)) {
4413a5e72196SApple OSS Distributions 		assert(false);
4414a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4415a5e72196SApple OSS Distributions 	}
4416a5e72196SApple OSS Distributions 
4417a5e72196SApple OSS Distributions 	if (desc->methodOptionsSize & ((2 * sizeof(uint64_t)) - 1)) {
4418a5e72196SApple OSS Distributions 		assert(false);
4419a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4420a5e72196SApple OSS Distributions 	}
4421a5e72196SApple OSS Distributions 	if (sizeof(desc->name) == strnlen(desc->name, sizeof(desc->name))) {
4422a5e72196SApple OSS Distributions 		assert(false);
4423a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4424a5e72196SApple OSS Distributions 	}
4425a5e72196SApple OSS Distributions 	if (sizeof(desc->superName) == strnlen(desc->superName, sizeof(desc->superName))) {
4426a5e72196SApple OSS Distributions 		assert(false);
4427a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4428a5e72196SApple OSS Distributions 	}
4429a5e72196SApple OSS Distributions 
4430a5e72196SApple OSS Distributions 	cls = OSTypeAlloc(OSUserMetaClass);
4431a5e72196SApple OSS Distributions 	assert(cls);
4432a5e72196SApple OSS Distributions 	if (!cls) {
4433a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
4434a5e72196SApple OSS Distributions 	}
4435a5e72196SApple OSS Distributions 
4436e6231be0SApple OSS Distributions 	cls->description = (typeof(cls->description))IOMallocData(size);
4437a5e72196SApple OSS Distributions 	assert(cls->description);
4438a5e72196SApple OSS Distributions 	if (!cls->description) {
4439a5e72196SApple OSS Distributions 		assert(false);
4440a5e72196SApple OSS Distributions 		cls->release();
4441a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
4442a5e72196SApple OSS Distributions 	}
4443a5e72196SApple OSS Distributions 	bcopy(desc, cls->description, size);
4444a5e72196SApple OSS Distributions 
4445a5e72196SApple OSS Distributions 	cls->methodCount = desc->methodOptionsSize / (2 * sizeof(uint64_t));
4446e6231be0SApple OSS Distributions 	cls->methods = IONewData(uint64_t, 2 * cls->methodCount);
4447a5e72196SApple OSS Distributions 	if (!cls->methods) {
4448a5e72196SApple OSS Distributions 		assert(false);
4449a5e72196SApple OSS Distributions 		cls->release();
4450a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
4451a5e72196SApple OSS Distributions 	}
4452a5e72196SApple OSS Distributions 
4453a5e72196SApple OSS Distributions 	methodOptions = (typeof(methodOptions))(((uintptr_t) desc) + desc->methodOptionsOffset);
4454a5e72196SApple OSS Distributions 	bcopy(methodOptions, cls->methods, 2 * cls->methodCount * sizeof(uint64_t));
4455a5e72196SApple OSS Distributions 
4456a5e72196SApple OSS Distributions 	queueNames = (typeof(queueNames))(((uintptr_t) desc) + desc->queueNamesOffset);
4457a5e72196SApple OSS Distributions 	cls->queueNames = copyInStringArray(queueNames, desc->queueNamesSize);
4458a5e72196SApple OSS Distributions 
4459a5e72196SApple OSS Distributions 	sym = OSSymbol::withCString(desc->name);
4460a5e72196SApple OSS Distributions 	assert(sym);
4461a5e72196SApple OSS Distributions 	if (!sym) {
4462a5e72196SApple OSS Distributions 		assert(false);
4463a5e72196SApple OSS Distributions 		cls->release();
4464a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
4465a5e72196SApple OSS Distributions 	}
4466a5e72196SApple OSS Distributions 
4467a5e72196SApple OSS Distributions 	cls->name = sym;
4468a5e72196SApple OSS Distributions 	cls->meta = OSMetaClass::copyMetaClassWithName(sym);
4469bb611c8fSApple OSS Distributions 	IOLockLock(fLock);
4470a5e72196SApple OSS Distributions 	cls->superMeta = OSDynamicCast(OSUserMetaClass, fClasses->getObject(desc->superName));
4471bb611c8fSApple OSS Distributions 	if (fClasses->getObject(sym) != NULL) {
4472bb611c8fSApple OSS Distributions 		/* class with this name exists */
4473bb611c8fSApple OSS Distributions 		ret = kIOReturnBadArgument;
4474bb611c8fSApple OSS Distributions 	} else {
4475bb611c8fSApple OSS Distributions 		if (fClasses->setObject(sym, cls)) {
4476a5e72196SApple OSS Distributions 			*pCls = cls;
4477bb611c8fSApple OSS Distributions 		} else {
4478bb611c8fSApple OSS Distributions 			/* could not add class to fClasses */
4479bb611c8fSApple OSS Distributions 			ret = kIOReturnNoMemory;
4480bb611c8fSApple OSS Distributions 		}
4481bb611c8fSApple OSS Distributions 	}
4482bb611c8fSApple OSS Distributions 	IOLockUnlock(fLock);
4483bb611c8fSApple OSS Distributions 	cls->release();
4484a5e72196SApple OSS Distributions 	return ret;
4485a5e72196SApple OSS Distributions }
4486a5e72196SApple OSS Distributions 
4487a5e72196SApple OSS Distributions IOReturn
registerClass(OSClassDescription * desc,uint32_t size,OSSharedPtr<OSUserMetaClass> & pCls)4488bb611c8fSApple OSS Distributions IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSSharedPtr<OSUserMetaClass>& pCls)
4489bb611c8fSApple OSS Distributions {
4490bb611c8fSApple OSS Distributions 	OSUserMetaClass* pClsRaw = NULL;
4491bb611c8fSApple OSS Distributions 	IOReturn result = registerClass(desc, size, &pClsRaw);
4492bb611c8fSApple OSS Distributions 	if (result == kIOReturnSuccess) {
4493bb611c8fSApple OSS Distributions 		pCls.reset(pClsRaw, OSRetain);
4494bb611c8fSApple OSS Distributions 	}
4495bb611c8fSApple OSS Distributions 	return result;
4496bb611c8fSApple OSS Distributions }
4497bb611c8fSApple OSS Distributions 
4498bb611c8fSApple OSS Distributions IOReturn
setRootQueue(IODispatchQueue * queue)4499a5e72196SApple OSS Distributions IOUserServer::setRootQueue(IODispatchQueue * queue)
4500a5e72196SApple OSS Distributions {
4501a5e72196SApple OSS Distributions 	assert(!fRootQueue);
4502a5e72196SApple OSS Distributions 	if (fRootQueue) {
4503a5e72196SApple OSS Distributions 		return kIOReturnStillOpen;
4504a5e72196SApple OSS Distributions 	}
4505a5e72196SApple OSS Distributions 	queue->retain();
4506a5e72196SApple OSS Distributions 	fRootQueue = queue;
4507a5e72196SApple OSS Distributions 
4508a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4509a5e72196SApple OSS Distributions }
4510a5e72196SApple OSS Distributions 
45115c2921b0SApple OSS Distributions 
4512a5e72196SApple OSS Distributions IOReturn
externalMethod(uint32_t selector,IOExternalMethodArgumentsOpaque * args)45135c2921b0SApple OSS Distributions IOUserServer::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args)
45145c2921b0SApple OSS Distributions {
45155c2921b0SApple OSS Distributions 	static const IOExternalMethodDispatch2022 dispatchArray[] = {
45165c2921b0SApple OSS Distributions 		[kIOUserServerMethodRegisterClass] = {
45175c2921b0SApple OSS Distributions 			.function                 = &IOUserServer::externalMethodRegisterClass,
45185c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
45195c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
45205c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 2,
45215c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
45225c2921b0SApple OSS Distributions 			.allowAsync               = false,
45235c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
45245c2921b0SApple OSS Distributions 		},
45255c2921b0SApple OSS Distributions 		[kIOUserServerMethodStart] = {
45265c2921b0SApple OSS Distributions 			.function                 = &IOUserServer::externalMethodStart,
45275c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 1,
45285c2921b0SApple OSS Distributions 			.checkStructureInputSize  = 0,
45295c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 1,
45305c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
45315c2921b0SApple OSS Distributions 			.allowAsync               = false,
45325c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
45335c2921b0SApple OSS Distributions 		},
45345c2921b0SApple OSS Distributions 	};
45355c2921b0SApple OSS Distributions 
45365c2921b0SApple OSS Distributions 	return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL);
45375c2921b0SApple OSS Distributions }
45385c2921b0SApple OSS Distributions 
45395c2921b0SApple OSS Distributions IOReturn
externalMethodRegisterClass(OSObject * target,void * reference,IOExternalMethodArguments * args)45405c2921b0SApple OSS Distributions IOUserServer::externalMethodRegisterClass(OSObject * target, void * reference, IOExternalMethodArguments * args)
4541a5e72196SApple OSS Distributions {
4542a5e72196SApple OSS Distributions 	IOReturn ret = kIOReturnBadArgument;
4543a5e72196SApple OSS Distributions 	mach_port_name_t portname;
4544a5e72196SApple OSS Distributions 
45455c2921b0SApple OSS Distributions 	IOUserServer * me = (typeof(me))target;
45465c2921b0SApple OSS Distributions 
4547a5e72196SApple OSS Distributions 	OSUserMetaClass * cls;
4548a5e72196SApple OSS Distributions 	if (!args->structureInputSize) {
4549a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4550a5e72196SApple OSS Distributions 	}
45515c2921b0SApple OSS Distributions 
45525c2921b0SApple OSS Distributions 	ret = me->registerClass((OSClassDescription *) args->structureInput, args->structureInputSize, &cls);
4553a5e72196SApple OSS Distributions 	if (kIOReturnSuccess == ret) {
45545c2921b0SApple OSS Distributions 		portname = iokit_make_send_right(me->fOwningTask, cls, IKOT_UEXT_OBJECT);
4555a5e72196SApple OSS Distributions 		assert(portname);
4556a5e72196SApple OSS Distributions 		args->scalarOutput[0] = portname;
4557a5e72196SApple OSS Distributions 		args->scalarOutput[1] = kOSObjectRPCRemote;
4558a5e72196SApple OSS Distributions 	}
45595c2921b0SApple OSS Distributions 
45605c2921b0SApple OSS Distributions 	return ret;
4561a5e72196SApple OSS Distributions }
45625c2921b0SApple OSS Distributions 
45635c2921b0SApple OSS Distributions IOReturn
externalMethodStart(OSObject * target,void * reference,IOExternalMethodArguments * args)45645c2921b0SApple OSS Distributions IOUserServer::externalMethodStart(OSObject * target, void * reference, IOExternalMethodArguments * args)
4565a5e72196SApple OSS Distributions {
45668d741a5dSApple OSS Distributions 	mach_port_name_t portname = 0;
45678d741a5dSApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
45685c2921b0SApple OSS Distributions 
45695c2921b0SApple OSS Distributions 	IOUserServer * me = (typeof(me))target;
45705c2921b0SApple OSS Distributions 
4571bb611c8fSApple OSS Distributions 	if (!(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
4572bb611c8fSApple OSS Distributions 		mach_port_name_t checkInPortName = ((typeof(checkInPortName))args->scalarInput[0]);
45735c2921b0SApple OSS Distributions 		OSObject * obj = iokit_lookup_object_with_port_name(checkInPortName, IKOT_IOKIT_IDENT, me->fOwningTask);
4574bb611c8fSApple OSS Distributions 		IOUserServerCheckInToken * retrievedToken = OSDynamicCast(IOUserServerCheckInToken, obj);
4575bb611c8fSApple OSS Distributions 		if (retrievedToken != NULL) {
45768d741a5dSApple OSS Distributions 			ret = me->setCheckInToken(retrievedToken);
4577bb611c8fSApple OSS Distributions 		} else {
45788d741a5dSApple OSS Distributions 			ret = kIOReturnBadArgument;
4579bb611c8fSApple OSS Distributions 		}
4580bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(obj);
4581bb611c8fSApple OSS Distributions 	}
45828d741a5dSApple OSS Distributions 	if (ret == kIOReturnSuccess) {
45835c2921b0SApple OSS Distributions 		portname = iokit_make_send_right(me->fOwningTask, me, IKOT_UEXT_OBJECT);
4584a5e72196SApple OSS Distributions 		assert(portname);
45858d741a5dSApple OSS Distributions 	}
4586a5e72196SApple OSS Distributions 	args->scalarOutput[0] = portname;
45878d741a5dSApple OSS Distributions 	return ret;
4588a5e72196SApple OSS Distributions }
4589a5e72196SApple OSS Distributions IOExternalTrap *
getTargetAndTrapForIndex(IOService ** targetP,UInt32 index)4590a5e72196SApple OSS Distributions IOUserServer::getTargetAndTrapForIndex( IOService **targetP, UInt32 index )
4591a5e72196SApple OSS Distributions {
45925c2921b0SApple OSS Distributions 	static const OSBoundedArray<IOExternalTrap, 1> trapTemplate = {{
4593a5e72196SApple OSS Distributions 									       { NULL, (IOTrap) & IOUserServer::waitInterruptTrap},
45945c2921b0SApple OSS Distributions 								       }};
45955c2921b0SApple OSS Distributions 	if (index >= trapTemplate.size()) {
4596a5e72196SApple OSS Distributions 		return NULL;
4597a5e72196SApple OSS Distributions 	}
4598a5e72196SApple OSS Distributions 	*targetP = this;
4599a5e72196SApple OSS Distributions 	return (IOExternalTrap *)&trapTemplate[index];
4600a5e72196SApple OSS Distributions }
4601a5e72196SApple OSS Distributions 
4602a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4603a5e72196SApple OSS Distributions 
4604a5e72196SApple OSS Distributions IOReturn
serviceAttach(IOService * service,IOService * provider)4605a5e72196SApple OSS Distributions IOUserServer::serviceAttach(IOService * service, IOService * provider)
4606a5e72196SApple OSS Distributions {
4607a5e72196SApple OSS Distributions 	IOReturn           ret;
4608a5e72196SApple OSS Distributions 	OSObjectUserVars * vars;
4609a5e72196SApple OSS Distributions 	OSObject         * prop;
4610a5e72196SApple OSS Distributions 	OSString         * str;
4611bb611c8fSApple OSS Distributions 	OSSymbol const*   bundleID;
4612a5e72196SApple OSS Distributions 	char               execPath[1024];
4613a5e72196SApple OSS Distributions 
4614e6231be0SApple OSS Distributions 	vars = IOMallocType(OSObjectUserVars);
4615a5e72196SApple OSS Distributions 	service->reserved->uvars = vars;
4616a5e72196SApple OSS Distributions 
4617a5e72196SApple OSS Distributions 	vars->userServer = this;
4618a5e72196SApple OSS Distributions 	vars->userServer->retain();
4619e6231be0SApple OSS Distributions 	vars->uvarsLock = IOLockAlloc();
4620a5e72196SApple OSS Distributions 	IOLockLock(fLock);
4621a5e72196SApple OSS Distributions 	if (-1U == fServices->getNextIndexOfObject(service, 0)) {
4622a5e72196SApple OSS Distributions 		fServices->setObject(service);
4623e6231be0SApple OSS Distributions 
4624e6231be0SApple OSS Distributions 		// Add to IOAssociatedServices
4625e6231be0SApple OSS Distributions 		OSObject * serviceArrayObj = copyProperty(gIOAssociatedServicesKey);
4626e6231be0SApple OSS Distributions 		OSArray * serviceArray = OSDynamicCast(OSArray, serviceArrayObj);
4627e6231be0SApple OSS Distributions 		if (!serviceArray) {
4628e6231be0SApple OSS Distributions 			serviceArray = OSArray::withCapacity(0);
4629e6231be0SApple OSS Distributions 		} else {
4630e6231be0SApple OSS Distributions 			serviceArray = OSDynamicCast(OSArray, serviceArray->copyCollection());
4631e6231be0SApple OSS Distributions 			assert(serviceArray != NULL);
4632e6231be0SApple OSS Distributions 		}
4633e6231be0SApple OSS Distributions 
4634e6231be0SApple OSS Distributions 		OSNumber * registryEntryNumber = OSNumber::withNumber(service->getRegistryEntryID(), 64);
4635e6231be0SApple OSS Distributions 		serviceArray->setObject(registryEntryNumber);
4636e6231be0SApple OSS Distributions 		setProperty(gIOAssociatedServicesKey, serviceArray);
4637e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(registryEntryNumber);
4638e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(serviceArray);
4639e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(serviceArrayObj);
46405c2921b0SApple OSS Distributions 
46415c2921b0SApple OSS Distributions 		// populate kIOUserClassesKey
46425c2921b0SApple OSS Distributions 
46435c2921b0SApple OSS Distributions 		OSUserMetaClass * userMeta;
46445c2921b0SApple OSS Distributions 		OSArray         * classesArray;
46455c2921b0SApple OSS Distributions 		const OSString  * str2;
46465c2921b0SApple OSS Distributions 
46475c2921b0SApple OSS Distributions 		classesArray = OSArray::withCapacity(4);
46485c2921b0SApple OSS Distributions 		prop = service->copyProperty(gIOUserClassKey);
46495c2921b0SApple OSS Distributions 		str2 = OSDynamicCast(OSString, prop);
46505c2921b0SApple OSS Distributions 		userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str2);
46515c2921b0SApple OSS Distributions 		while (str2 && userMeta) {
46525c2921b0SApple OSS Distributions 			classesArray->setObject(str2);
46535c2921b0SApple OSS Distributions 			userMeta = userMeta->superMeta;
46545c2921b0SApple OSS Distributions 			if (userMeta) {
46555c2921b0SApple OSS Distributions 				str2 = userMeta->name;
46565c2921b0SApple OSS Distributions 			}
46575c2921b0SApple OSS Distributions 		}
46585c2921b0SApple OSS Distributions 		service->setProperty(gIOUserClassesKey, classesArray);
46595c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(classesArray);
46605c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(prop);
4661a5e72196SApple OSS Distributions 	}
4662a5e72196SApple OSS Distributions 	IOLockUnlock(fLock);
4663a5e72196SApple OSS Distributions 
4664a5e72196SApple OSS Distributions 	prop = service->copyProperty(gIOUserClassKey);
4665a5e72196SApple OSS Distributions 	str = OSDynamicCast(OSString, prop);
4666a5e72196SApple OSS Distributions 	if (str) {
4667a5e72196SApple OSS Distributions 		service->setName(str);
4668a5e72196SApple OSS Distributions 	}
4669a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(prop);
4670a5e72196SApple OSS Distributions 
4671a5e72196SApple OSS Distributions 	prop = service->copyProperty(gIOModuleIdentifierKey);
4672a5e72196SApple OSS Distributions 	bundleID = OSDynamicCast(OSSymbol, prop);
4673a5e72196SApple OSS Distributions 	if (bundleID) {
4674a5e72196SApple OSS Distributions 		execPath[0] = 0;
4675a5e72196SApple OSS Distributions 		bool ok = OSKext::copyUserExecutablePath(bundleID, execPath, sizeof(execPath));
4676a5e72196SApple OSS Distributions 		if (ok) {
4677a5e72196SApple OSS Distributions 			ret = LoadModule(execPath);
4678a5e72196SApple OSS Distributions 			if (kIODKLogSetup & gIODKDebug) {
4679a5e72196SApple OSS Distributions 				DKLOG("%s::LoadModule 0x%x %s\n", getName(), ret, execPath);
4680a5e72196SApple OSS Distributions 			}
4681a5e72196SApple OSS Distributions 		}
4682a5e72196SApple OSS Distributions 	}
4683a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(prop);
4684a5e72196SApple OSS Distributions 
4685a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
4686a5e72196SApple OSS Distributions 
4687a5e72196SApple OSS Distributions 	return ret;
4688a5e72196SApple OSS Distributions }
4689a5e72196SApple OSS Distributions 
4690a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4691a5e72196SApple OSS Distributions 
4692a5e72196SApple OSS Distributions IOReturn
serviceNewUserClient(IOService * service,task_t owningTask,void * securityID,uint32_t type,OSDictionary * properties,IOUserClient ** handler)4693a5e72196SApple OSS Distributions IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID,
4694a5e72196SApple OSS Distributions     uint32_t type, OSDictionary * properties, IOUserClient ** handler)
4695a5e72196SApple OSS Distributions {
4696a5e72196SApple OSS Distributions 	IOReturn           ret;
4697a5e72196SApple OSS Distributions 	IOUserClient     * uc;
4698a5e72196SApple OSS Distributions 	IOUserUserClient * userUC;
4699a5e72196SApple OSS Distributions 	OSDictionary     * entitlements;
4700a5e72196SApple OSS Distributions 	OSObject         * prop;
4701a5e72196SApple OSS Distributions 	OSObject         * bundleID;
47025c2921b0SApple OSS Distributions 	bool               ok = false;
4703a5e72196SApple OSS Distributions 
4704e6231be0SApple OSS Distributions 	entitlements = IOUserClient::copyClientEntitlements(owningTask);
4705e6231be0SApple OSS Distributions 	if (!entitlements) {
4706e6231be0SApple OSS Distributions 		entitlements = OSDictionary::withCapacity(8);
4707e6231be0SApple OSS Distributions 	}
47085c2921b0SApple OSS Distributions 	if (entitlements) {
47095c2921b0SApple OSS Distributions 		if (kIOReturnSuccess == clientHasPrivilege((void *) owningTask, kIOClientPrivilegeAdministrator)) {
4710e6231be0SApple OSS Distributions 			entitlements->setObject(kIODriverKitUserClientEntitlementAdministratorKey, kOSBooleanTrue);
4711e6231be0SApple OSS Distributions 		}
47125c2921b0SApple OSS Distributions 		OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
47135c2921b0SApple OSS Distributions 		if (creatorName) {
47145c2921b0SApple OSS Distributions 			entitlements->setObject(kIOUserClientCreatorKey, creatorName);
47155c2921b0SApple OSS Distributions 			OSSafeReleaseNULL(creatorName);
47165c2921b0SApple OSS Distributions 		}
47175c2921b0SApple OSS Distributions 	}
4718e6231be0SApple OSS Distributions 
4719a5e72196SApple OSS Distributions 	*handler = NULL;
4720e6231be0SApple OSS Distributions 	ret = service->_NewUserClient(type, entitlements, &uc);
4721a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != ret) {
4722e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(entitlements);
4723a5e72196SApple OSS Distributions 		return ret;
4724a5e72196SApple OSS Distributions 	}
4725a5e72196SApple OSS Distributions 	userUC = OSDynamicCast(IOUserUserClient, uc);
4726a5e72196SApple OSS Distributions 	if (!userUC) {
4727*4f1223e8SApple OSS Distributions 		if (uc) {
4728e7776783SApple OSS Distributions 			uc->terminate(kIOServiceTerminateNeedWillTerminate);
47295c2921b0SApple OSS Distributions 			uc->setTerminateDefer(service, false);
4730a5e72196SApple OSS Distributions 			OSSafeReleaseNULL(uc);
4731*4f1223e8SApple OSS Distributions 		}
4732e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(entitlements);
4733a5e72196SApple OSS Distributions 		return kIOReturnUnsupported;
4734a5e72196SApple OSS Distributions 	}
4735a5e72196SApple OSS Distributions 	userUC->setTask(owningTask);
4736a5e72196SApple OSS Distributions 
4737a5e72196SApple OSS Distributions 	if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
47385c2921b0SApple OSS Distributions 		do {
47395c2921b0SApple OSS Distributions 			bool checkiOS3pEntitlements;
47405c2921b0SApple OSS Distributions 
47415c2921b0SApple OSS Distributions 			// check if client has com.apple.private.driverkit.driver-access and the required entitlements match the driver's entitlements
4742e6231be0SApple OSS Distributions 			if (entitlements && (prop = entitlements->getObject(gIODriverKitRequiredEntitlementsKey))) {
4743e6231be0SApple OSS Distributions 				prop->retain();
4744e6231be0SApple OSS Distributions 				ok = checkEntitlements(fEntitlements, prop, NULL, NULL);
47455c2921b0SApple OSS Distributions 				if (ok) {
47465c2921b0SApple OSS Distributions 					break;
47475c2921b0SApple OSS Distributions 				} else {
47485c2921b0SApple OSS Distributions 					DKLOG(DKS ":UC failed required entitlement check\n", DKN(userUC));
47495c2921b0SApple OSS Distributions 				}
47505c2921b0SApple OSS Distributions 			}
47515c2921b0SApple OSS Distributions 
47525c2921b0SApple OSS Distributions #if XNU_TARGET_OS_IOS
47535c2921b0SApple OSS Distributions 			checkiOS3pEntitlements = !fPlatformDriver;
47545c2921b0SApple OSS Distributions 			if (checkiOS3pEntitlements && fTeamIdentifier == NULL) {
47555c2921b0SApple OSS Distributions 				DKLOG("warning: " DKS " does not have a team identifier\n", DKN(this));
47565c2921b0SApple OSS Distributions 			}
47575c2921b0SApple OSS Distributions #else
47585c2921b0SApple OSS Distributions 			checkiOS3pEntitlements = false;
47595c2921b0SApple OSS Distributions #endif
47605c2921b0SApple OSS Distributions 			if (checkiOS3pEntitlements) {
47615c2921b0SApple OSS Distributions 				// App must have com.apple.developer.driverkit.communicates-with-drivers
47625c2921b0SApple OSS Distributions 				ok = entitlements && entitlements->getObject(gIODriverKitUserClientEntitlementCommunicatesWithDriversKey) == kOSBooleanTrue;
47635c2921b0SApple OSS Distributions 				if (ok) {
47645c2921b0SApple OSS Distributions 					// check team ID
47655c2921b0SApple OSS Distributions 					const char * clientTeamID = csproc_get_teamid(current_proc());
47665c2921b0SApple OSS Distributions 					bool sameTeam = fTeamIdentifier != NULL && clientTeamID != NULL && strncmp(fTeamIdentifier->getCStringNoCopy(), clientTeamID, CS_MAX_TEAMID_LEN) == 0;
47675c2921b0SApple OSS Distributions 
47685c2921b0SApple OSS Distributions 					if (sameTeam) {
4769e6231be0SApple OSS Distributions 						ok = true;
47705c2921b0SApple OSS Distributions 					} else {
47715c2921b0SApple OSS Distributions 						// different team IDs, dext must have com.apple.developer.driverkit.allow-third-party-userclients
47725c2921b0SApple OSS Distributions 						ok = fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey) == kOSBooleanTrue;
47735c2921b0SApple OSS Distributions 					}
47745c2921b0SApple OSS Distributions 					if (!ok) {
47755c2921b0SApple OSS Distributions 						DKLOG(DKS ":UC failed team ID check. client team=%s, driver team=%s\n", DKN(userUC), clientTeamID ? clientTeamID : "(null)", fTeamIdentifier ? fTeamIdentifier->getCStringNoCopy() : "(null)");
4776e6231be0SApple OSS Distributions 					}
4777e6231be0SApple OSS Distributions 				} else {
47785c2921b0SApple OSS Distributions 					DKLOG(DKS ":UC entitlement check failed, app does not have %s entitlement\n", DKN(userUC), gIODriverKitUserClientEntitlementCommunicatesWithDriversKey->getCStringNoCopy());
47795c2921b0SApple OSS Distributions 				}
47805c2921b0SApple OSS Distributions 
47815c2921b0SApple OSS Distributions 				// When checking iOS 3rd party entitlements, do not fall through to other entitlement checks
47825c2921b0SApple OSS Distributions 				break;
47835c2921b0SApple OSS Distributions 			}
47845c2921b0SApple OSS Distributions 
47855c2921b0SApple OSS Distributions 			// first party dexts and third party macOS dexts
47865c2921b0SApple OSS Distributions 
47875c2921b0SApple OSS Distributions 			// check if driver has com.apple.developer.driverkit.allow-any-userclient-access
4788bb611c8fSApple OSS Distributions 			if (fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowAnyKey)) {
4789bb611c8fSApple OSS Distributions 				ok = true;
47905c2921b0SApple OSS Distributions 				break;
47915c2921b0SApple OSS Distributions 			}
47925c2921b0SApple OSS Distributions 
47935c2921b0SApple OSS Distributions 			// check if client has com.apple.developer.driverkit.userclient-access and its value matches the bundle ID of the service
4794a5e72196SApple OSS Distributions 			bundleID = service->copyProperty(gIOModuleIdentifierKey);
4795a5e72196SApple OSS Distributions 			ok = (entitlements
4796a5e72196SApple OSS Distributions 			    && bundleID
4797a5e72196SApple OSS Distributions 			    && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey)));
4798a5e72196SApple OSS Distributions 			if (ok) {
4799a5e72196SApple OSS Distributions 				bool found __block = false;
4800a5e72196SApple OSS Distributions 				ok = prop->iterateObjects(^bool (OSObject * object) {
4801a5e72196SApple OSS Distributions 					found = object->isEqualTo(bundleID);
4802a5e72196SApple OSS Distributions 					return found;
4803a5e72196SApple OSS Distributions 				});
4804a5e72196SApple OSS Distributions 				ok = found;
48055c2921b0SApple OSS Distributions 			} else {
48065c2921b0SApple OSS Distributions 				OSString * bundleIDStr = OSDynamicCast(OSString, bundleID);
48075c2921b0SApple OSS Distributions 				DKLOG(DKS ":UC failed userclient-access check, needed bundle ID %s\n", DKN(userUC), bundleIDStr ? bundleIDStr->getCStringNoCopy() : "(null)");
4808a5e72196SApple OSS Distributions 			}
4809e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(bundleID);
48105c2921b0SApple OSS Distributions 		} while (false);
48115c2921b0SApple OSS Distributions 
4812a5e72196SApple OSS Distributions 		if (ok) {
4813a5e72196SApple OSS Distributions 			prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey);
4814a5e72196SApple OSS Distributions 			ok = checkEntitlements(entitlements, prop, NULL, NULL);
4815a5e72196SApple OSS Distributions 		}
4816e6231be0SApple OSS Distributions 
4817a5e72196SApple OSS Distributions 		if (!ok) {
4818a5e72196SApple OSS Distributions 			DKLOG(DKS ":UC entitlements check failed\n", DKN(userUC));
4819e7776783SApple OSS Distributions 			uc->terminate(kIOServiceTerminateNeedWillTerminate);
48205c2921b0SApple OSS Distributions 			uc->setTerminateDefer(service, false);
4821a5e72196SApple OSS Distributions 			OSSafeReleaseNULL(uc);
4822e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(entitlements);
4823a5e72196SApple OSS Distributions 			return kIOReturnNotPermitted;
4824a5e72196SApple OSS Distributions 		}
4825a5e72196SApple OSS Distributions 	}
4826a5e72196SApple OSS Distributions 
4827e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(entitlements);
4828a5e72196SApple OSS Distributions 	*handler = userUC;
4829a5e72196SApple OSS Distributions 
4830a5e72196SApple OSS Distributions 	return ret;
4831a5e72196SApple OSS Distributions }
4832a5e72196SApple OSS Distributions 
4833bb611c8fSApple OSS Distributions IOReturn
serviceNewUserClient(IOService * service,task_t owningTask,void * securityID,uint32_t type,OSDictionary * properties,OSSharedPtr<IOUserClient> & handler)4834bb611c8fSApple OSS Distributions IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID,
4835bb611c8fSApple OSS Distributions     uint32_t type, OSDictionary * properties, OSSharedPtr<IOUserClient>& handler)
4836bb611c8fSApple OSS Distributions {
4837bb611c8fSApple OSS Distributions 	IOUserClient* handlerRaw = NULL;
4838bb611c8fSApple OSS Distributions 	IOReturn result = serviceNewUserClient(service, owningTask, securityID, type, properties, &handlerRaw);
4839bb611c8fSApple OSS Distributions 	handler.reset(handlerRaw, OSNoRetain);
4840bb611c8fSApple OSS Distributions 	return result;
4841bb611c8fSApple OSS Distributions }
4842bb611c8fSApple OSS Distributions 
4843a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4844a5e72196SApple OSS Distributions 
4845a5e72196SApple OSS Distributions static IOPMPowerState
4846a5e72196SApple OSS Distributions     sPowerStates[] = {
4847a5e72196SApple OSS Distributions 	{   .version                = kIOPMPowerStateVersion1,
4848a5e72196SApple OSS Distributions 	    .capabilityFlags        = 0,
4849a5e72196SApple OSS Distributions 	    .outputPowerCharacter   = 0,
4850a5e72196SApple OSS Distributions 	    .inputPowerRequirement  = 0},
4851a5e72196SApple OSS Distributions 	{   .version                = kIOPMPowerStateVersion1,
4852a5e72196SApple OSS Distributions 	    .capabilityFlags        = kIOPMLowPower,
4853a5e72196SApple OSS Distributions 	    .outputPowerCharacter   = kIOPMLowPower,
4854a5e72196SApple OSS Distributions 	    .inputPowerRequirement  = kIOPMLowPower},
4855a5e72196SApple OSS Distributions 	{   .version                = kIOPMPowerStateVersion1,
4856a5e72196SApple OSS Distributions 	    .capabilityFlags        = kIOPMPowerOn,
4857a5e72196SApple OSS Distributions 	    .outputPowerCharacter   = kIOPMPowerOn,
4858a5e72196SApple OSS Distributions 	    .inputPowerRequirement  = kIOPMPowerOn},
4859a5e72196SApple OSS Distributions };
4860a5e72196SApple OSS Distributions 
48615c2921b0SApple OSS Distributions enum {
48625c2921b0SApple OSS Distributions 	kUserServerMaxPowerState    = 2
48635c2921b0SApple OSS Distributions };
48645c2921b0SApple OSS Distributions 
48655c2921b0SApple OSS Distributions IOReturn
serviceJoinPMTree(IOService * service)48665c2921b0SApple OSS Distributions IOUserServer::serviceJoinPMTree(IOService * service)
48675c2921b0SApple OSS Distributions {
48685c2921b0SApple OSS Distributions 	IOReturn    ret;
48695c2921b0SApple OSS Distributions 	IOService * pmProvider;
48705c2921b0SApple OSS Distributions 	bool        joinTree;
48715c2921b0SApple OSS Distributions 
48725c2921b0SApple OSS Distributions 	if (service->reserved->uvars->userServerPM) {
48735c2921b0SApple OSS Distributions 		return kIOReturnSuccess;
48745c2921b0SApple OSS Distributions 	}
48755c2921b0SApple OSS Distributions 
48765c2921b0SApple OSS Distributions 	if (!fRootNotifier) {
48775c2921b0SApple OSS Distributions 		ret = registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
48785c2921b0SApple OSS Distributions 		assert(kIOReturnSuccess == ret);
48795c2921b0SApple OSS Distributions 		IOServicePH::serverAdd(this);
48805c2921b0SApple OSS Distributions 		fRootNotifier = true;
48815c2921b0SApple OSS Distributions 	}
48825c2921b0SApple OSS Distributions 
48835c2921b0SApple OSS Distributions 	joinTree = false;
48845c2921b0SApple OSS Distributions 	if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) {
48855c2921b0SApple OSS Distributions 		kern_return_t  kr;
48865c2921b0SApple OSS Distributions 		OSDictionary * props;
48875c2921b0SApple OSS Distributions 		kr = service->CopyProperties_Local(&props);
48885c2921b0SApple OSS Distributions 		if (kIOReturnSuccess == kr) {
48895c2921b0SApple OSS Distributions 			if (props->getObject(kIOPMResetPowerStateOnWakeKey) == kOSBooleanTrue) {
48905c2921b0SApple OSS Distributions 				service->setProperty(kIOPMResetPowerStateOnWakeKey, kOSBooleanTrue);
48915c2921b0SApple OSS Distributions 			}
48925c2921b0SApple OSS Distributions 			OSSafeReleaseNULL(props);
48935c2921b0SApple OSS Distributions 		}
48945c2921b0SApple OSS Distributions 		service->PMinit();
48955c2921b0SApple OSS Distributions 		ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
48965c2921b0SApple OSS Distributions 		assert(kIOReturnSuccess == ret);
48975c2921b0SApple OSS Distributions 		joinTree = true;
48985c2921b0SApple OSS Distributions 	}
48995c2921b0SApple OSS Distributions 
49005c2921b0SApple OSS Distributions 	pmProvider = service;
49015c2921b0SApple OSS Distributions 	while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) {
49025c2921b0SApple OSS Distributions 		pmProvider = pmProvider->getProvider();
49035c2921b0SApple OSS Distributions 	}
49045c2921b0SApple OSS Distributions 	if (!pmProvider) {
49055c2921b0SApple OSS Distributions 		pmProvider = getPMRootDomain();
49065c2921b0SApple OSS Distributions 	}
49075c2921b0SApple OSS Distributions 	if (pmProvider) {
49085c2921b0SApple OSS Distributions 		IOService * entry;
49095c2921b0SApple OSS Distributions 		OSObject  * prop;
49105c2921b0SApple OSS Distributions 		OSObject  * nextProp;
49115c2921b0SApple OSS Distributions 		OSString  * str;
49125c2921b0SApple OSS Distributions 
49135c2921b0SApple OSS Distributions 		entry = pmProvider;
49145c2921b0SApple OSS Distributions 		prop  = NULL;
49155c2921b0SApple OSS Distributions 		do {
49165c2921b0SApple OSS Distributions 			nextProp = entry->copyProperty("non-removable");
49175c2921b0SApple OSS Distributions 			if (nextProp) {
49185c2921b0SApple OSS Distributions 				OSSafeReleaseNULL(prop);
49195c2921b0SApple OSS Distributions 				prop = nextProp;
49205c2921b0SApple OSS Distributions 			}
49215c2921b0SApple OSS Distributions 			entry = entry->getProvider();
49225c2921b0SApple OSS Distributions 		} while (entry);
49235c2921b0SApple OSS Distributions 		if (prop) {
49245c2921b0SApple OSS Distributions 			str = OSDynamicCast(OSString, prop);
49255c2921b0SApple OSS Distributions 			if (str && str->isEqualTo("yes")) {
49265c2921b0SApple OSS Distributions 				pmProvider = NULL;
49275c2921b0SApple OSS Distributions 			}
49285c2921b0SApple OSS Distributions 			prop->release();
49295c2921b0SApple OSS Distributions 		}
49305c2921b0SApple OSS Distributions 	}
49315c2921b0SApple OSS Distributions 
49325c2921b0SApple OSS Distributions 	if (!(kIODKDisablePM & gIODKDebug) && pmProvider) {
49335c2921b0SApple OSS Distributions 		IOLockLock(fLock);
49345c2921b0SApple OSS Distributions 		service->reserved->uvars->powerState = true;
49355c2921b0SApple OSS Distributions 		IOLockUnlock(fLock);
49365c2921b0SApple OSS Distributions 
49375c2921b0SApple OSS Distributions 		if (joinTree) {
49385c2921b0SApple OSS Distributions 			pmProvider->joinPMtree(service);
49395c2921b0SApple OSS Distributions 			service->reserved->uvars->userServerPM = true;
49405c2921b0SApple OSS Distributions 			service->reserved->uvars->resetPowerOnWake = service->propertyExists(kIOPMResetPowerStateOnWakeKey);
49415c2921b0SApple OSS Distributions 		}
49425c2921b0SApple OSS Distributions 	}
49435c2921b0SApple OSS Distributions 
49445c2921b0SApple OSS Distributions 	service->registerInterestedDriver(this);
49455c2921b0SApple OSS Distributions 	return kIOReturnSuccess;
49465c2921b0SApple OSS Distributions }
49475c2921b0SApple OSS Distributions 
4948a5e72196SApple OSS Distributions IOReturn
setPowerState(unsigned long state,IOService * service)4949a5e72196SApple OSS Distributions IOUserServer::setPowerState(unsigned long state, IOService * service)
4950a5e72196SApple OSS Distributions {
4951a5e72196SApple OSS Distributions 	if (kIODKLogPM & gIODKDebug) {
4952a5e72196SApple OSS Distributions 		DKLOG(DKS "::setPowerState(%ld) %d\n", DKN(service), state, fSystemPowerAck);
4953a5e72196SApple OSS Distributions 	}
4954a5e72196SApple OSS Distributions 	return kIOPMAckImplied;
4955a5e72196SApple OSS Distributions }
4956a5e72196SApple OSS Distributions 
49575c2921b0SApple OSS Distributions 
4958a5e72196SApple OSS Distributions IOReturn
serviceSetPowerState(IOService * controllingDriver,IOService * service,IOPMPowerFlags flags,unsigned long state)4959bb611c8fSApple OSS Distributions IOUserServer::serviceSetPowerState(IOService * controllingDriver, IOService * service, IOPMPowerFlags flags, unsigned long state)
4960a5e72196SApple OSS Distributions {
4961a5e72196SApple OSS Distributions 	IOReturn ret;
4962e6231be0SApple OSS Distributions 	bool sendIt = false;
4963a5e72196SApple OSS Distributions 
4964e6231be0SApple OSS Distributions 	IOLockLock(fLock);
4965a5e72196SApple OSS Distributions 	if (service->reserved->uvars) {
496694d3b452SApple OSS Distributions 		if (!fSystemOff && !(kIODKDisablePM & gIODKDebug)) {
49675c2921b0SApple OSS Distributions 			OSDictionary * wakeDescription;
49685c2921b0SApple OSS Distributions 			OSObject     * prop;
49695c2921b0SApple OSS Distributions 			char           wakeReasonString[128];
49705c2921b0SApple OSS Distributions 
49715c2921b0SApple OSS Distributions 			wakeDescription = OSDictionary::withCapacity(4);
49725c2921b0SApple OSS Distributions 			if (wakeDescription) {
49735c2921b0SApple OSS Distributions 				wakeReasonString[0] = 0;
49745c2921b0SApple OSS Distributions 				getPMRootDomain()->copyWakeReasonString(wakeReasonString, sizeof(wakeReasonString));
49755c2921b0SApple OSS Distributions 
49765c2921b0SApple OSS Distributions 				if (wakeReasonString[0]) {
49775c2921b0SApple OSS Distributions 					prop = OSString::withCString(&wakeReasonString[0]);
49785c2921b0SApple OSS Distributions 					wakeDescription->setObject(gIOSystemStateWakeDescriptionWakeReasonKey, prop);
49795c2921b0SApple OSS Distributions 					OSSafeReleaseNULL(prop);
49805c2921b0SApple OSS Distributions 				}
49818d741a5dSApple OSS Distributions #if defined(__arm__) || defined(__arm64__)
49828d741a5dSApple OSS Distributions 				prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
49838d741a5dSApple OSS Distributions 				wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
49848d741a5dSApple OSS Distributions 				OSSafeReleaseNULL(prop);
49858d741a5dSApple OSS Distributions #endif /* defined(__arm__) || defined(__arm64__) */
49865c2921b0SApple OSS Distributions 				getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateWakeDescriptionKey, wakeDescription);
49875c2921b0SApple OSS Distributions 				OSSafeReleaseNULL(wakeDescription);
49885c2921b0SApple OSS Distributions 			}
49895c2921b0SApple OSS Distributions 
4990a5e72196SApple OSS Distributions 			service->reserved->uvars->willPower = true;
4991bb611c8fSApple OSS Distributions 			service->reserved->uvars->willPowerState = state;
4992bb611c8fSApple OSS Distributions 			service->reserved->uvars->controllingDriver = controllingDriver;
4993e6231be0SApple OSS Distributions 			sendIt = true;
4994e6231be0SApple OSS Distributions 		} else {
4995e6231be0SApple OSS Distributions 			service->reserved->uvars->willPower = false;
4996e6231be0SApple OSS Distributions 		}
4997e6231be0SApple OSS Distributions 	}
4998e6231be0SApple OSS Distributions 	IOLockUnlock(fLock);
4999e6231be0SApple OSS Distributions 
5000e6231be0SApple OSS Distributions 	if (sendIt) {
5001a5e72196SApple OSS Distributions 		if (kIODKLogPM & gIODKDebug) {
5002e6231be0SApple OSS Distributions 			DKLOG(DKS "::serviceSetPowerState(%ld) %d\n", DKN(service), state, fSystemPowerAck);
5003a5e72196SApple OSS Distributions 		}
5004bb611c8fSApple OSS Distributions 		ret = service->SetPowerState((uint32_t) flags);
5005a5e72196SApple OSS Distributions 		if (kIOReturnSuccess == ret) {
5006a5e72196SApple OSS Distributions 			return 20 * 1000 * 1000;
5007e6231be0SApple OSS Distributions 		} else {
5008e6231be0SApple OSS Distributions 			IOLockLock(fLock);
5009a5e72196SApple OSS Distributions 			service->reserved->uvars->willPower = false;
5010e6231be0SApple OSS Distributions 			IOLockUnlock(fLock);
5011e6231be0SApple OSS Distributions 		}
5012a5e72196SApple OSS Distributions 	}
5013a5e72196SApple OSS Distributions 
5014a5e72196SApple OSS Distributions 	return kIOPMAckImplied;
5015a5e72196SApple OSS Distributions }
5016a5e72196SApple OSS Distributions 
5017a5e72196SApple OSS Distributions IOReturn
powerStateWillChangeTo(IOPMPowerFlags flags,unsigned long state,IOService * service)5018bb611c8fSApple OSS Distributions IOUserServer::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
5019bb611c8fSApple OSS Distributions {
5020bb611c8fSApple OSS Distributions 	return kIOPMAckImplied;
5021bb611c8fSApple OSS Distributions }
5022bb611c8fSApple OSS Distributions 
5023bb611c8fSApple OSS Distributions IOReturn
powerStateDidChangeTo(IOPMPowerFlags flags,unsigned long state,IOService * service)5024a5e72196SApple OSS Distributions IOUserServer::powerStateDidChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
5025a5e72196SApple OSS Distributions {
5026a5e72196SApple OSS Distributions 	unsigned int idx;
5027a5e72196SApple OSS Distributions 	bool         pmAck;
5028a5e72196SApple OSS Distributions 
5029a5e72196SApple OSS Distributions 	pmAck = false;
5030a5e72196SApple OSS Distributions 	IOLockLock(fLock);
5031a5e72196SApple OSS Distributions 	idx = fServices->getNextIndexOfObject(service, 0);
5032a5e72196SApple OSS Distributions 	if (-1U == idx) {
5033a5e72196SApple OSS Distributions 		IOLockUnlock(fLock);
5034a5e72196SApple OSS Distributions 		return kIOPMAckImplied;
5035a5e72196SApple OSS Distributions 	}
5036a5e72196SApple OSS Distributions 
5037e6231be0SApple OSS Distributions 	service->reserved->uvars->powerState = (0 != state);
50385c2921b0SApple OSS Distributions 	bool allPowerStates __block = service->reserved->uvars->powerState;
50395c2921b0SApple OSS Distributions 	if (!allPowerStates) {
5040e6231be0SApple OSS Distributions 		// any service on?
5041e6231be0SApple OSS Distributions 		fServices->iterateObjects(^bool (OSObject * obj) {
5042e6231be0SApple OSS Distributions 			int         service __unused;       // hide outer defn
5043e6231be0SApple OSS Distributions 			IOService * nextService;
5044e6231be0SApple OSS Distributions 			nextService = (IOService *) obj;
5045e6231be0SApple OSS Distributions 			allPowerStates = nextService->reserved->uvars->powerState;
5046e6231be0SApple OSS Distributions 			// early terminate if true
5047e6231be0SApple OSS Distributions 			return allPowerStates;
5048e6231be0SApple OSS Distributions 		});
5049a5e72196SApple OSS Distributions 	}
5050a5e72196SApple OSS Distributions 	if (kIODKLogPM & gIODKDebug) {
5051e6231be0SApple OSS Distributions 		DKLOG(DKS "::powerStateDidChangeTo(%ld) %d, %d\n", DKN(service), state, allPowerStates, fSystemPowerAck);
5052a5e72196SApple OSS Distributions 	}
5053e6231be0SApple OSS Distributions 	if (!allPowerStates && (pmAck = fSystemPowerAck)) {
5054a5e72196SApple OSS Distributions 		fSystemPowerAck = false;
5055a5e72196SApple OSS Distributions 		fSystemOff      = true;
5056a5e72196SApple OSS Distributions 	}
5057a5e72196SApple OSS Distributions 	IOLockUnlock(fLock);
5058a5e72196SApple OSS Distributions 
5059a5e72196SApple OSS Distributions 	if (pmAck) {
5060a5e72196SApple OSS Distributions 		IOServicePH::serverAck(this);
5061a5e72196SApple OSS Distributions 	}
5062a5e72196SApple OSS Distributions 
5063a5e72196SApple OSS Distributions 	return kIOPMAckImplied;
5064a5e72196SApple OSS Distributions }
5065a5e72196SApple OSS Distributions 
506694d3b452SApple OSS Distributions bool
checkPMReady()506794d3b452SApple OSS Distributions IOUserServer::checkPMReady()
506894d3b452SApple OSS Distributions {
506994d3b452SApple OSS Distributions 	bool __block ready = true;
507094d3b452SApple OSS Distributions 
507194d3b452SApple OSS Distributions 	IOLockLock(fLock);
507294d3b452SApple OSS Distributions 	// Check if any services have not completely joined the PM tree (i.e.
507394d3b452SApple OSS Distributions 	// addPowerChild has not compeleted).
507494d3b452SApple OSS Distributions 	fServices->iterateObjects(^bool (OSObject * obj) {
507594d3b452SApple OSS Distributions 		IOPowerConnection *conn;
507694d3b452SApple OSS Distributions 		IOService *service = (IOService *) obj;
507794d3b452SApple OSS Distributions 		IORegistryEntry *parent = service->getParentEntry(gIOPowerPlane);
507894d3b452SApple OSS Distributions 		if ((conn = OSDynamicCast(IOPowerConnection, parent))) {
507994d3b452SApple OSS Distributions 		        if (!conn->getReadyFlag()) {
508094d3b452SApple OSS Distributions 		                ready = false;
508194d3b452SApple OSS Distributions 		                return true;
508294d3b452SApple OSS Distributions 			}
508394d3b452SApple OSS Distributions 		}
508494d3b452SApple OSS Distributions 		return false;
508594d3b452SApple OSS Distributions 	});
508694d3b452SApple OSS Distributions 	IOLockUnlock(fLock);
508794d3b452SApple OSS Distributions 
508894d3b452SApple OSS Distributions 	return ready;
508994d3b452SApple OSS Distributions }
509094d3b452SApple OSS Distributions 
5091a5e72196SApple OSS Distributions kern_return_t
JoinPMTree_Impl(void)50925c2921b0SApple OSS Distributions IOService::JoinPMTree_Impl(void)
50935c2921b0SApple OSS Distributions {
50945c2921b0SApple OSS Distributions 	if (!reserved->uvars || !reserved->uvars->userServer) {
50955c2921b0SApple OSS Distributions 		return kIOReturnNotReady;
50965c2921b0SApple OSS Distributions 	}
50975c2921b0SApple OSS Distributions 	return reserved->uvars->userServer->serviceJoinPMTree(this);
50985c2921b0SApple OSS Distributions }
50995c2921b0SApple OSS Distributions 
5100*4f1223e8SApple OSS Distributions static kern_return_t
acknowledgeSetPowerState(IOService * service)5101*4f1223e8SApple OSS Distributions acknowledgeSetPowerState(IOService * service)
5102*4f1223e8SApple OSS Distributions {
5103*4f1223e8SApple OSS Distributions 	if (service->reserved->uvars
5104*4f1223e8SApple OSS Distributions 	    && service->reserved->uvars->userServer
5105*4f1223e8SApple OSS Distributions 	    && service->reserved->uvars->willPower) {
5106*4f1223e8SApple OSS Distributions 		IOReturn ret;
5107*4f1223e8SApple OSS Distributions 		service->reserved->uvars->willPower = false;
5108*4f1223e8SApple OSS Distributions 		ret = service->reserved->uvars->controllingDriver->setPowerState(service->reserved->uvars->willPowerState, service);
5109*4f1223e8SApple OSS Distributions 		if (kIOPMAckImplied == ret) {
5110*4f1223e8SApple OSS Distributions 			service->acknowledgeSetPowerState();
5111*4f1223e8SApple OSS Distributions 		}
5112*4f1223e8SApple OSS Distributions 		return kIOReturnSuccess;
5113*4f1223e8SApple OSS Distributions 	}
5114*4f1223e8SApple OSS Distributions 	return kIOReturnNotReady;
5115*4f1223e8SApple OSS Distributions }
5116*4f1223e8SApple OSS Distributions 
51175c2921b0SApple OSS Distributions kern_return_t
SetPowerState_Impl(uint32_t powerFlags)5118bb611c8fSApple OSS Distributions IOService::SetPowerState_Impl(
5119bb611c8fSApple OSS Distributions 	uint32_t powerFlags)
5120a5e72196SApple OSS Distributions {
5121a5e72196SApple OSS Distributions 	if (kIODKLogPM & gIODKDebug) {
5122a5e72196SApple OSS Distributions 		DKLOG(DKS "::SetPowerState(%d), %d\n", DKN(this), powerFlags, reserved->uvars->willPower);
5123a5e72196SApple OSS Distributions 	}
5124*4f1223e8SApple OSS Distributions 	return ::acknowledgeSetPowerState(this);
5125a5e72196SApple OSS Distributions }
5126a5e72196SApple OSS Distributions 
5127a5e72196SApple OSS Distributions kern_return_t
ChangePowerState_Impl(uint32_t powerFlags)5128bb611c8fSApple OSS Distributions IOService::ChangePowerState_Impl(
5129bb611c8fSApple OSS Distributions 	uint32_t powerFlags)
5130a5e72196SApple OSS Distributions {
5131a5e72196SApple OSS Distributions 	switch (powerFlags) {
5132a5e72196SApple OSS Distributions 	case kIOServicePowerCapabilityOff:
5133a5e72196SApple OSS Distributions 		changePowerStateToPriv(0);
5134a5e72196SApple OSS Distributions 		break;
5135a5e72196SApple OSS Distributions 	case kIOServicePowerCapabilityLow:
5136a5e72196SApple OSS Distributions 		changePowerStateToPriv(1);
5137a5e72196SApple OSS Distributions 		break;
5138a5e72196SApple OSS Distributions 	case kIOServicePowerCapabilityOn:
5139a5e72196SApple OSS Distributions 		changePowerStateToPriv(2);
5140a5e72196SApple OSS Distributions 		break;
5141a5e72196SApple OSS Distributions 	default:
5142a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
5143a5e72196SApple OSS Distributions 	}
5144a5e72196SApple OSS Distributions 
5145a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
5146a5e72196SApple OSS Distributions }
5147a5e72196SApple OSS Distributions 
5148a5e72196SApple OSS Distributions kern_return_t
SetPowerOverride_Impl(bool enable)5149*4f1223e8SApple OSS Distributions IOService::SetPowerOverride_Impl(
5150*4f1223e8SApple OSS Distributions 	bool enable)
5151*4f1223e8SApple OSS Distributions {
5152*4f1223e8SApple OSS Distributions 	kern_return_t ret;
5153*4f1223e8SApple OSS Distributions 
5154*4f1223e8SApple OSS Distributions 	if (enable) {
5155*4f1223e8SApple OSS Distributions 		ret = powerOverrideOnPriv();
5156*4f1223e8SApple OSS Distributions 	} else {
5157*4f1223e8SApple OSS Distributions 		ret = powerOverrideOffPriv();
5158*4f1223e8SApple OSS Distributions 	}
5159*4f1223e8SApple OSS Distributions 
5160*4f1223e8SApple OSS Distributions 	return ret == IOPMNoErr ? kIOReturnSuccess : kIOReturnError;
5161*4f1223e8SApple OSS Distributions }
5162*4f1223e8SApple OSS Distributions 
5163*4f1223e8SApple OSS Distributions kern_return_t
_ClaimSystemWakeEvent_Impl(IOService * device,uint64_t flags,const char * reason,OSContainer * details)5164e6231be0SApple OSS Distributions IOService::_ClaimSystemWakeEvent_Impl(
5165e6231be0SApple OSS Distributions 	IOService          * device,
5166e6231be0SApple OSS Distributions 	uint64_t             flags,
5167e6231be0SApple OSS Distributions 	const char         * reason,
5168e6231be0SApple OSS Distributions 	OSContainer        * details)
5169e6231be0SApple OSS Distributions {
5170e6231be0SApple OSS Distributions 	IOPMrootDomain * rootDomain;
5171e6231be0SApple OSS Distributions 	IOOptionBits     pmFlags;
5172e6231be0SApple OSS Distributions 
5173e6231be0SApple OSS Distributions 	rootDomain = getPMRootDomain();
5174e6231be0SApple OSS Distributions 	if (!rootDomain) {
5175e6231be0SApple OSS Distributions 		return kIOReturnNotReady;
5176e6231be0SApple OSS Distributions 	}
5177e6231be0SApple OSS Distributions 	if (os_convert_overflow(flags, &pmFlags)) {
5178e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
5179e6231be0SApple OSS Distributions 	}
5180e6231be0SApple OSS Distributions 	rootDomain->claimSystemWakeEvent(device, pmFlags, reason, details);
5181e6231be0SApple OSS Distributions 
5182e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
5183e6231be0SApple OSS Distributions }
5184e6231be0SApple OSS Distributions 
5185e6231be0SApple OSS Distributions kern_return_t
Create_Impl(IOService * provider,const char * propertiesKey,IOService ** result)5186bb611c8fSApple OSS Distributions IOService::Create_Impl(
5187bb611c8fSApple OSS Distributions 	IOService * provider,
5188bb611c8fSApple OSS Distributions 	const char * propertiesKey,
5189bb611c8fSApple OSS Distributions 	IOService ** result)
5190a5e72196SApple OSS Distributions {
5191a5e72196SApple OSS Distributions 	OSObject       * inst;
5192a5e72196SApple OSS Distributions 	IOService      * service;
5193a5e72196SApple OSS Distributions 	OSString       * str;
5194a5e72196SApple OSS Distributions 	const OSSymbol * sym;
51955c2921b0SApple OSS Distributions 	OSObject       * prop = NULL;
51965c2921b0SApple OSS Distributions 	OSObject       * moduleIdentifier = NULL;
51975c2921b0SApple OSS Distributions 	OSObject       * userServerName = NULL;
51985c2921b0SApple OSS Distributions 	OSDictionary   * properties = NULL;
51995c2921b0SApple OSS Distributions 	OSDictionary   * copyProperties = NULL;
5200a5e72196SApple OSS Distributions 	kern_return_t    ret;
5201a5e72196SApple OSS Distributions 
5202a5e72196SApple OSS Distributions 	if (provider != this) {
5203a5e72196SApple OSS Distributions 		return kIOReturnUnsupported;
5204a5e72196SApple OSS Distributions 	}
5205a5e72196SApple OSS Distributions 
5206a5e72196SApple OSS Distributions 	ret = kIOReturnUnsupported;
5207a5e72196SApple OSS Distributions 	inst = NULL;
5208a5e72196SApple OSS Distributions 	service = NULL;
5209a5e72196SApple OSS Distributions 
5210a5e72196SApple OSS Distributions 	prop = copyProperty(propertiesKey);
5211a5e72196SApple OSS Distributions 	properties = OSDynamicCast(OSDictionary, prop);
52125c2921b0SApple OSS Distributions 	if (!properties) {
52135c2921b0SApple OSS Distributions 		ret = kIOReturnBadArgument;
52145c2921b0SApple OSS Distributions 		goto finish;
52155c2921b0SApple OSS Distributions 	}
52165c2921b0SApple OSS Distributions 	copyProperties = OSDynamicCast(OSDictionary, properties->copyCollection());
52175c2921b0SApple OSS Distributions 	if (!copyProperties) {
52185c2921b0SApple OSS Distributions 		ret = kIOReturnNoMemory;
52195c2921b0SApple OSS Distributions 		goto finish;
52205c2921b0SApple OSS Distributions 	}
52215c2921b0SApple OSS Distributions 	moduleIdentifier = copyProperty(gIOModuleIdentifierKey);
52225c2921b0SApple OSS Distributions 	if (moduleIdentifier) {
52235c2921b0SApple OSS Distributions 		copyProperties->setObject(gIOModuleIdentifierKey, moduleIdentifier);
52245c2921b0SApple OSS Distributions 	}
52255c2921b0SApple OSS Distributions 	userServerName = reserved->uvars->userServer->copyProperty(gIOUserServerNameKey);
52265c2921b0SApple OSS Distributions 	if (userServerName) {
52275c2921b0SApple OSS Distributions 		copyProperties->setObject(gIOUserServerNameKey, userServerName);
52285c2921b0SApple OSS Distributions 	}
52295c2921b0SApple OSS Distributions 
52305c2921b0SApple OSS Distributions 	str = OSDynamicCast(OSString, copyProperties->getObject(gIOClassKey));
52315c2921b0SApple OSS Distributions 	if (!str) {
52325c2921b0SApple OSS Distributions 		ret = kIOReturnBadArgument;
52335c2921b0SApple OSS Distributions 		goto finish;
52345c2921b0SApple OSS Distributions 	}
5235a5e72196SApple OSS Distributions 	sym = OSSymbol::withString(str);
5236a5e72196SApple OSS Distributions 	if (sym) {
5237a5e72196SApple OSS Distributions 		inst = OSMetaClass::allocClassWithName(sym);
5238a5e72196SApple OSS Distributions 		service = OSDynamicCast(IOService, inst);
52395c2921b0SApple OSS Distributions 		if (service && service->init(copyProperties) && service->attach(this)) {
5240a5e72196SApple OSS Distributions 			reserved->uvars->userServer->serviceAttach(service, this);
5241bb611c8fSApple OSS Distributions 			service->reserved->uvars->started = true;
5242a5e72196SApple OSS Distributions 			ret = kIOReturnSuccess;
5243a5e72196SApple OSS Distributions 			*result = service;
5244a5e72196SApple OSS Distributions 		}
5245a5e72196SApple OSS Distributions 		OSSafeReleaseNULL(sym);
5246a5e72196SApple OSS Distributions 	}
5247a5e72196SApple OSS Distributions 
52485c2921b0SApple OSS Distributions finish:
5249a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(prop);
52505c2921b0SApple OSS Distributions 	OSSafeReleaseNULL(copyProperties);
52515c2921b0SApple OSS Distributions 	OSSafeReleaseNULL(moduleIdentifier);
52525c2921b0SApple OSS Distributions 	OSSafeReleaseNULL(userServerName);
5253a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != ret) {
5254a5e72196SApple OSS Distributions 		OSSafeReleaseNULL(inst);
5255a5e72196SApple OSS Distributions 	}
5256a5e72196SApple OSS Distributions 
5257a5e72196SApple OSS Distributions 	return ret;
5258a5e72196SApple OSS Distributions }
5259a5e72196SApple OSS Distributions 
5260a5e72196SApple OSS Distributions kern_return_t
Terminate_Impl(uint64_t options)5261bb611c8fSApple OSS Distributions IOService::Terminate_Impl(
5262bb611c8fSApple OSS Distributions 	uint64_t options)
5263bb611c8fSApple OSS Distributions {
5264bb611c8fSApple OSS Distributions 	IOUserServer * us;
5265bb611c8fSApple OSS Distributions 
5266bb611c8fSApple OSS Distributions 	if (options) {
5267bb611c8fSApple OSS Distributions 		return kIOReturnUnsupported;
5268bb611c8fSApple OSS Distributions 	}
5269bb611c8fSApple OSS Distributions 
5270bb611c8fSApple OSS Distributions 	us = (typeof(us))thread_iokit_tls_get(0);
52715c2921b0SApple OSS Distributions 	if (us && (!reserved->uvars
52725c2921b0SApple OSS Distributions 	    || (reserved->uvars->userServer != us))) {
5273bb611c8fSApple OSS Distributions 		return kIOReturnNotPermitted;
5274bb611c8fSApple OSS Distributions 	}
5275bb611c8fSApple OSS Distributions 	terminate(kIOServiceTerminateNeedWillTerminate);
5276bb611c8fSApple OSS Distributions 
5277bb611c8fSApple OSS Distributions 	return kIOReturnSuccess;
5278bb611c8fSApple OSS Distributions }
5279bb611c8fSApple OSS Distributions 
5280bb611c8fSApple OSS Distributions kern_return_t
NewUserClient_Impl(uint32_t type,IOUserClient ** userClient)5281bb611c8fSApple OSS Distributions IOService::NewUserClient_Impl(
5282bb611c8fSApple OSS Distributions 	uint32_t type,
5283bb611c8fSApple OSS Distributions 	IOUserClient ** userClient)
5284a5e72196SApple OSS Distributions {
5285a5e72196SApple OSS Distributions 	return kIOReturnError;
5286a5e72196SApple OSS Distributions }
5287a5e72196SApple OSS Distributions 
5288a5e72196SApple OSS Distributions kern_return_t
_NewUserClient_Impl(uint32_t type,OSDictionary * entitlements,IOUserClient ** userClient)5289e6231be0SApple OSS Distributions IOService::_NewUserClient_Impl(
5290e6231be0SApple OSS Distributions 	uint32_t type,
5291e6231be0SApple OSS Distributions 	OSDictionary * entitlements,
5292e6231be0SApple OSS Distributions 	IOUserClient ** userClient)
5293e6231be0SApple OSS Distributions {
5294e6231be0SApple OSS Distributions 	return kIOReturnError;
5295e6231be0SApple OSS Distributions }
5296e6231be0SApple OSS Distributions 
5297e6231be0SApple OSS Distributions kern_return_t
SearchProperty_Impl(const char * name,const char * plane,uint64_t options,OSContainer ** property)5298bb611c8fSApple OSS Distributions IOService::SearchProperty_Impl(
5299bb611c8fSApple OSS Distributions 	const char * name,
5300bb611c8fSApple OSS Distributions 	const char * plane,
5301bb611c8fSApple OSS Distributions 	uint64_t options,
5302bb611c8fSApple OSS Distributions 	OSContainer ** property)
5303a5e72196SApple OSS Distributions {
5304e6231be0SApple OSS Distributions 	OSObject   * object __block;
5305e6231be0SApple OSS Distributions 	IOService  * provider;
5306bb611c8fSApple OSS Distributions 	IOOptionBits regOptions;
5307a5e72196SApple OSS Distributions 
5308a5e72196SApple OSS Distributions 	if (kIOServiceSearchPropertyParents & options) {
5309bb611c8fSApple OSS Distributions 		regOptions = kIORegistryIterateParents | kIORegistryIterateRecursively;
5310a5e72196SApple OSS Distributions 	} else {
5311bb611c8fSApple OSS Distributions 		regOptions = 0;
5312a5e72196SApple OSS Distributions 	}
5313a5e72196SApple OSS Distributions 
5314bb611c8fSApple OSS Distributions 	object = copyProperty(name, IORegistryEntry::getPlane(plane), regOptions);
5315e6231be0SApple OSS Distributions 
5316e6231be0SApple OSS Distributions 	if (NULL == object) {
5317e6231be0SApple OSS Distributions 		for (provider = this; provider; provider = provider->getProvider()) {
5318e6231be0SApple OSS Distributions 			provider->runPropertyActionBlock(^IOReturn (void) {
5319e6231be0SApple OSS Distributions 				OSDictionary * userProps;
5320e6231be0SApple OSS Distributions 				object = provider->getProperty(name);
5321e6231be0SApple OSS Distributions 				if (!object
5322e6231be0SApple OSS Distributions 				&& (userProps = OSDynamicCast(OSDictionary, provider->getProperty(gIOUserServicePropertiesKey)))) {
5323e6231be0SApple OSS Distributions 				        object = userProps->getObject(name);
5324e6231be0SApple OSS Distributions 				}
5325e6231be0SApple OSS Distributions 				if (object) {
5326e6231be0SApple OSS Distributions 				        object->retain();
5327e6231be0SApple OSS Distributions 				}
5328e6231be0SApple OSS Distributions 				return kIOReturnSuccess;
5329e6231be0SApple OSS Distributions 			});
5330e6231be0SApple OSS Distributions 			if (object || !(kIORegistryIterateParents & options)) {
5331e6231be0SApple OSS Distributions 				break;
5332e6231be0SApple OSS Distributions 			}
5333e6231be0SApple OSS Distributions 		}
5334e6231be0SApple OSS Distributions 	}
5335e6231be0SApple OSS Distributions 
5336a5e72196SApple OSS Distributions 	*property = object;
5337a5e72196SApple OSS Distributions 
5338a5e72196SApple OSS Distributions 	return object ? kIOReturnSuccess : kIOReturnNotFound;
5339a5e72196SApple OSS Distributions }
5340a5e72196SApple OSS Distributions 
5341bb611c8fSApple OSS Distributions kern_return_t
StringFromReturn_Impl(IOReturn retval,OSString ** str)5342e6231be0SApple OSS Distributions IOService::StringFromReturn_Impl(
5343e6231be0SApple OSS Distributions 	IOReturn retval,
5344e6231be0SApple OSS Distributions 	OSString ** str)
5345e6231be0SApple OSS Distributions {
5346e6231be0SApple OSS Distributions 	OSString *obj = OSString::withCString(stringFromReturn(retval));
5347e6231be0SApple OSS Distributions 	*str = obj;
5348e6231be0SApple OSS Distributions 	return obj ? kIOReturnSuccess : kIOReturnError;
5349e6231be0SApple OSS Distributions }
5350e6231be0SApple OSS Distributions 
53515c2921b0SApple OSS Distributions #if PRIVATE_WIFI_ONLY
53525c2921b0SApple OSS Distributions const char *
StringFromReturn(IOReturn retval)53535c2921b0SApple OSS Distributions IOService::StringFromReturn(
53545c2921b0SApple OSS Distributions 	IOReturn retval)
53555c2921b0SApple OSS Distributions {
53565c2921b0SApple OSS Distributions 	return stringFromReturn(retval);
53575c2921b0SApple OSS Distributions }
53585c2921b0SApple OSS Distributions #endif /* PRIVATE_WIFI_ONLY */
53595c2921b0SApple OSS Distributions 
5360e6231be0SApple OSS Distributions kern_return_t
CopyProviderProperties_Impl(OSArray * propertyKeys,OSArray ** properties)5361bb611c8fSApple OSS Distributions IOService::CopyProviderProperties_Impl(
5362bb611c8fSApple OSS Distributions 	OSArray * propertyKeys,
5363bb611c8fSApple OSS Distributions 	OSArray ** properties)
5364bb611c8fSApple OSS Distributions {
5365bb611c8fSApple OSS Distributions 	IOReturn    ret;
5366bb611c8fSApple OSS Distributions 	OSArray   * result;
5367bb611c8fSApple OSS Distributions 	IOService * provider;
5368bb611c8fSApple OSS Distributions 
5369bb611c8fSApple OSS Distributions 	result = OSArray::withCapacity(8);
5370bb611c8fSApple OSS Distributions 	if (!result) {
5371bb611c8fSApple OSS Distributions 		return kIOReturnNoMemory;
5372bb611c8fSApple OSS Distributions 	}
5373bb611c8fSApple OSS Distributions 
5374bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
5375bb611c8fSApple OSS Distributions 	for (provider = this; provider; provider = provider->getProvider()) {
5376bb611c8fSApple OSS Distributions 		OSObject     * obj;
5377bb611c8fSApple OSS Distributions 		OSDictionary * props;
5378bb611c8fSApple OSS Distributions 
5379bb611c8fSApple OSS Distributions 		obj = provider->copyProperty(gIOSupportedPropertiesKey);
5380bb611c8fSApple OSS Distributions 		props = OSDynamicCast(OSDictionary, obj);
5381bb611c8fSApple OSS Distributions 		if (!props) {
5382bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(obj);
5383bb611c8fSApple OSS Distributions 			props = provider->dictionaryWithProperties();
5384bb611c8fSApple OSS Distributions 		}
5385bb611c8fSApple OSS Distributions 		if (!props) {
5386bb611c8fSApple OSS Distributions 			ret = kIOReturnNoMemory;
5387bb611c8fSApple OSS Distributions 			break;
5388bb611c8fSApple OSS Distributions 		}
5389e6231be0SApple OSS Distributions 
5390bb611c8fSApple OSS Distributions 		bool __block addClass = true;
5391bb611c8fSApple OSS Distributions 		if (propertyKeys) {
5392bb611c8fSApple OSS Distributions 			OSDictionary * retProps;
5393bb611c8fSApple OSS Distributions 			retProps = OSDictionary::withCapacity(4);
5394bb611c8fSApple OSS Distributions 			addClass = false;
5395bb611c8fSApple OSS Distributions 			if (!retProps) {
5396bb611c8fSApple OSS Distributions 				ret = kIOReturnNoMemory;
5397e6231be0SApple OSS Distributions 				OSSafeReleaseNULL(props);
5398bb611c8fSApple OSS Distributions 				break;
5399bb611c8fSApple OSS Distributions 			}
5400bb611c8fSApple OSS Distributions 			propertyKeys->iterateObjects(^bool (OSObject * _key) {
5401bb611c8fSApple OSS Distributions 				OSString * key = OSDynamicCast(OSString, _key);
5402bb611c8fSApple OSS Distributions 				if (gIOClassKey->isEqualTo(key)) {
5403bb611c8fSApple OSS Distributions 				        addClass = true;
5404bb611c8fSApple OSS Distributions 				        return false;
5405bb611c8fSApple OSS Distributions 				}
5406bb611c8fSApple OSS Distributions 				retProps->setObject(key, props->getObject(key));
5407bb611c8fSApple OSS Distributions 				return false;
5408bb611c8fSApple OSS Distributions 			});
5409bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(props);
5410bb611c8fSApple OSS Distributions 			props = retProps;
5411bb611c8fSApple OSS Distributions 		}
5412bb611c8fSApple OSS Distributions 		if (addClass) {
5413bb611c8fSApple OSS Distributions 			OSArray * classes = OSArray::withCapacity(8);
5414bb611c8fSApple OSS Distributions 			if (!classes) {
5415e6231be0SApple OSS Distributions 				OSSafeReleaseNULL(props);
5416bb611c8fSApple OSS Distributions 				ret = kIOReturnNoMemory;
5417bb611c8fSApple OSS Distributions 				break;
5418bb611c8fSApple OSS Distributions 			}
5419bb611c8fSApple OSS Distributions 			for (const OSMetaClass * meta = provider->getMetaClass(); meta; meta = meta->getSuperClass()) {
5420bb611c8fSApple OSS Distributions 				classes->setObject(meta->getClassNameSymbol());
5421bb611c8fSApple OSS Distributions 			}
5422bb611c8fSApple OSS Distributions 			props->setObject(gIOClassKey, classes);
5423bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(classes);
5424bb611c8fSApple OSS Distributions 		}
5425bb611c8fSApple OSS Distributions 		bool ok = result->setObject(props);
5426bb611c8fSApple OSS Distributions 		props->release();
5427bb611c8fSApple OSS Distributions 		if (!ok) {
5428bb611c8fSApple OSS Distributions 			ret = kIOReturnNoMemory;
5429bb611c8fSApple OSS Distributions 			break;
5430bb611c8fSApple OSS Distributions 		}
5431bb611c8fSApple OSS Distributions 	}
5432bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess != ret) {
5433bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(result);
5434bb611c8fSApple OSS Distributions 	}
5435bb611c8fSApple OSS Distributions 	*properties = result;
5436bb611c8fSApple OSS Distributions 	return ret;
5437bb611c8fSApple OSS Distributions }
5438bb611c8fSApple OSS Distributions 
5439e6231be0SApple OSS Distributions IOReturn
AdjustBusy_Impl(int32_t delta)5440e6231be0SApple OSS Distributions IOService::AdjustBusy_Impl(int32_t delta)
5441e6231be0SApple OSS Distributions {
5442e6231be0SApple OSS Distributions 	adjustBusy(delta);
5443e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
5444e6231be0SApple OSS Distributions }
5445e6231be0SApple OSS Distributions 
5446e6231be0SApple OSS Distributions IOReturn
GetBusyState_Impl(uint32_t * busyState)5447e6231be0SApple OSS Distributions IOService::GetBusyState_Impl(uint32_t *busyState)
5448e6231be0SApple OSS Distributions {
5449e6231be0SApple OSS Distributions 	*busyState = getBusyState();
5450e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
5451e6231be0SApple OSS Distributions }
5452e6231be0SApple OSS Distributions 
5453a5e72196SApple OSS Distributions void
systemPower(bool powerOff,bool hibernate)54548d741a5dSApple OSS Distributions IOUserServer::systemPower(bool powerOff, bool hibernate)
5455a5e72196SApple OSS Distributions {
5456a5e72196SApple OSS Distributions 	OSArray * services;
5457e6231be0SApple OSS Distributions 	{
5458e6231be0SApple OSS Distributions 		OSDictionary * sleepDescription;
5459e6231be0SApple OSS Distributions 		OSObject     * prop;
5460a5e72196SApple OSS Distributions 
5461e6231be0SApple OSS Distributions 		sleepDescription = OSDictionary::withCapacity(4);
5462e6231be0SApple OSS Distributions 		if (sleepDescription) {
5463e6231be0SApple OSS Distributions 			prop = getPMRootDomain()->copyProperty(kRootDomainSleepReasonKey);
5464e6231be0SApple OSS Distributions 			if (prop) {
5465e6231be0SApple OSS Distributions 				sleepDescription->setObject(gIOSystemStateSleepDescriptionReasonKey, prop);
5466e6231be0SApple OSS Distributions 				OSSafeReleaseNULL(prop);
5467e6231be0SApple OSS Distributions 			}
5468e6231be0SApple OSS Distributions 			prop = getPMRootDomain()->copyProperty(kIOHibernateStateKey);
5469e6231be0SApple OSS Distributions 			if (prop) {
5470e6231be0SApple OSS Distributions 				sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, prop);
5471e6231be0SApple OSS Distributions 				OSSafeReleaseNULL(prop);
5472e6231be0SApple OSS Distributions 			}
54738d741a5dSApple OSS Distributions 			if (hibernate) {
54748d741a5dSApple OSS Distributions 				uint32_t correctHibernateState = kIOSystemStateSleepDescriptionHibernateStateHibernating;
54758d741a5dSApple OSS Distributions 				OSData *correctHibernateStateData = OSData::withValue(correctHibernateState);
54768d741a5dSApple OSS Distributions 				assert(correctHibernateStateData != NULL);
54778d741a5dSApple OSS Distributions 				sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, correctHibernateStateData);
54788d741a5dSApple OSS Distributions 				OSSafeReleaseNULL(correctHibernateStateData);
54798d741a5dSApple OSS Distributions 			}
5480e6231be0SApple OSS Distributions 			getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateSleepDescriptionKey, sleepDescription);
5481e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(sleepDescription);
5482e6231be0SApple OSS Distributions 		}
5483a5e72196SApple OSS Distributions 	}
5484a5e72196SApple OSS Distributions 
5485a5e72196SApple OSS Distributions 	IOLockLock(fLock);
54865c2921b0SApple OSS Distributions 
5487a5e72196SApple OSS Distributions 	services = OSArray::withArray(fServices);
5488a5e72196SApple OSS Distributions 
5489e6231be0SApple OSS Distributions 	bool allPowerStates __block = 0;
5490e6231be0SApple OSS Distributions 	// any service on?
5491e6231be0SApple OSS Distributions 	fServices->iterateObjects(^bool (OSObject * obj) {
5492e6231be0SApple OSS Distributions 		int         service __unused;       // hide outer defn
5493e6231be0SApple OSS Distributions 		IOService * nextService;
5494e6231be0SApple OSS Distributions 		nextService = (IOService *) obj;
5495e6231be0SApple OSS Distributions 		allPowerStates = nextService->reserved->uvars->powerState;
5496e6231be0SApple OSS Distributions 		// early terminate if true
5497e6231be0SApple OSS Distributions 		return allPowerStates;
5498e6231be0SApple OSS Distributions 	});
5499e6231be0SApple OSS Distributions 
5500e6231be0SApple OSS Distributions 	if (kIODKLogPM & gIODKDebug) {
5501e6231be0SApple OSS Distributions 		DKLOG("%s::powerOff(%d) %d\n", getName(), powerOff, allPowerStates);
5502e6231be0SApple OSS Distributions 	}
5503e6231be0SApple OSS Distributions 
5504a5e72196SApple OSS Distributions 	if (powerOff) {
5505e6231be0SApple OSS Distributions 		fSystemPowerAck = allPowerStates;
5506a5e72196SApple OSS Distributions 		if (!fSystemPowerAck) {
5507a5e72196SApple OSS Distributions 			fSystemOff = true;
5508a5e72196SApple OSS Distributions 		}
5509a5e72196SApple OSS Distributions 		IOLockUnlock(fLock);
5510a5e72196SApple OSS Distributions 
5511a5e72196SApple OSS Distributions 		if (!fSystemPowerAck) {
5512a5e72196SApple OSS Distributions 			IOServicePH::serverAck(this);
5513a5e72196SApple OSS Distributions 		} else {
5514a5e72196SApple OSS Distributions 			if (services) {
5515a5e72196SApple OSS Distributions 				services->iterateObjects(^bool (OSObject * obj) {
5516e6231be0SApple OSS Distributions 					int         service __unused;       // hide outer defn
5517e6231be0SApple OSS Distributions 					IOService * nextService;
5518e6231be0SApple OSS Distributions 					nextService = (IOService *) obj;
5519a5e72196SApple OSS Distributions 					if (kIODKLogPM & gIODKDebug) {
5520e6231be0SApple OSS Distributions 					        DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(nextService), 0);
5521a5e72196SApple OSS Distributions 					}
55225c2921b0SApple OSS Distributions 					nextService->reserved->uvars->powerOverride = nextService->reserved->uvars->userServerPM ? kUserServerMaxPowerState : nextService->getPowerState();
5523e6231be0SApple OSS Distributions 					nextService->changePowerStateWithOverrideTo(0, 0);
5524a5e72196SApple OSS Distributions 					return false;
5525a5e72196SApple OSS Distributions 				});
5526a5e72196SApple OSS Distributions 			}
5527a5e72196SApple OSS Distributions 		}
5528a5e72196SApple OSS Distributions 	} else {
5529a5e72196SApple OSS Distributions 		fSystemOff = false;
5530a5e72196SApple OSS Distributions 		IOLockUnlock(fLock);
5531a5e72196SApple OSS Distributions 		if (services) {
5532a5e72196SApple OSS Distributions 			services->iterateObjects(^bool (OSObject * obj) {
5533e6231be0SApple OSS Distributions 				int         service __unused;       // hide outer defn
5534e6231be0SApple OSS Distributions 				IOService * nextService;
5535e6231be0SApple OSS Distributions 				nextService = (IOService *) obj;
5536e6231be0SApple OSS Distributions 				if (-1U != nextService->reserved->uvars->powerOverride) {
5537a5e72196SApple OSS Distributions 				        if (kIODKLogPM & gIODKDebug) {
55385c2921b0SApple OSS Distributions 				                DKLOG("%schangePowerStateWithOverrideTo(" DKS ", %d)\n", nextService->reserved->uvars->resetPowerOnWake ? "!" : "", DKN(nextService), nextService->reserved->uvars->powerOverride);
5539a5e72196SApple OSS Distributions 					}
55405c2921b0SApple OSS Distributions 				        if (!nextService->reserved->uvars->resetPowerOnWake) {
5541e6231be0SApple OSS Distributions 				                nextService->changePowerStateWithOverrideTo(nextService->reserved->uvars->powerOverride, 0);
55425c2921b0SApple OSS Distributions 					}
5543e6231be0SApple OSS Distributions 				        nextService->reserved->uvars->powerOverride = -1U;
5544a5e72196SApple OSS Distributions 				}
5545a5e72196SApple OSS Distributions 				return false;
5546a5e72196SApple OSS Distributions 			});
5547a5e72196SApple OSS Distributions 		}
5548a5e72196SApple OSS Distributions 	}
5549a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(services);
5550a5e72196SApple OSS Distributions }
5551a5e72196SApple OSS Distributions 
5552a5e72196SApple OSS Distributions 
5553e6231be0SApple OSS Distributions void
systemHalt(int howto)5554e6231be0SApple OSS Distributions IOUserServer::systemHalt(int howto)
5555e6231be0SApple OSS Distributions {
5556e6231be0SApple OSS Distributions 	OSArray * services;
5557e6231be0SApple OSS Distributions 
5558e6231be0SApple OSS Distributions 	if (true || (kIODKLogPM & gIODKDebug)) {
5559e6231be0SApple OSS Distributions 		DKLOG("%s::systemHalt()\n", getName());
5560e6231be0SApple OSS Distributions 	}
5561e6231be0SApple OSS Distributions 
5562e6231be0SApple OSS Distributions 	{
5563e6231be0SApple OSS Distributions 		OSDictionary * haltDescription;
5564e6231be0SApple OSS Distributions 		OSNumber     * state;
5565e6231be0SApple OSS Distributions 		uint64_t       haltStateFlags;
5566e6231be0SApple OSS Distributions 
5567e6231be0SApple OSS Distributions 		haltDescription = OSDictionary::withCapacity(4);
5568e6231be0SApple OSS Distributions 		if (haltDescription) {
5569e6231be0SApple OSS Distributions 			haltStateFlags = 0;
5570e6231be0SApple OSS Distributions 			if (RB_HALT & howto) {
5571e6231be0SApple OSS Distributions 				haltStateFlags |= kIOServiceHaltStatePowerOff;
5572e6231be0SApple OSS Distributions 			} else {
5573e6231be0SApple OSS Distributions 				haltStateFlags |= kIOServiceHaltStateRestart;
5574e6231be0SApple OSS Distributions 			}
5575e6231be0SApple OSS Distributions 			state = OSNumber::withNumber(haltStateFlags, 64);
5576e6231be0SApple OSS Distributions 			haltDescription->setObject(gIOSystemStateHaltDescriptionHaltStateKey, state);
5577e6231be0SApple OSS Distributions 			getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateHaltDescriptionKey, haltDescription);
5578e6231be0SApple OSS Distributions 
5579e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(state);
5580e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(haltDescription);
5581e6231be0SApple OSS Distributions 		}
5582e6231be0SApple OSS Distributions 	}
5583e6231be0SApple OSS Distributions 
5584e6231be0SApple OSS Distributions 	IOLockLock(fLock);
5585e6231be0SApple OSS Distributions 	services = OSArray::withArray(fServices);
5586e6231be0SApple OSS Distributions 	IOLockUnlock(fLock);
5587e6231be0SApple OSS Distributions 
5588e6231be0SApple OSS Distributions 	if (services) {
5589e6231be0SApple OSS Distributions 		services->iterateObjects(^bool (OSObject * obj) {
5590e6231be0SApple OSS Distributions 			int         service __unused;       // hide outer defn
5591e6231be0SApple OSS Distributions 			IOService  * nextService;
5592e6231be0SApple OSS Distributions 			IOService  * provider;
5593e6231be0SApple OSS Distributions 			IOOptionBits terminateOptions;
5594e6231be0SApple OSS Distributions 			bool         root;
5595e6231be0SApple OSS Distributions 
5596e6231be0SApple OSS Distributions 			nextService = (IOService *) obj;
5597e6231be0SApple OSS Distributions 			provider = nextService->getProvider();
5598e6231be0SApple OSS Distributions 			if (!provider) {
5599e6231be0SApple OSS Distributions 			        DKLOG("stale service " DKS " found, skipping termination\n", DKN(nextService));
5600e6231be0SApple OSS Distributions 			        return false;
5601e6231be0SApple OSS Distributions 			}
5602e6231be0SApple OSS Distributions 			root = (NULL == provider->getProperty(gIOUserServerNameKey, gIOServicePlane));
5603e6231be0SApple OSS Distributions 			if (true || (kIODKLogPM & gIODKDebug)) {
5604e6231be0SApple OSS Distributions 			        DKLOG("%d: terminate(" DKS ")\n", root, DKN(nextService));
5605e6231be0SApple OSS Distributions 			}
5606e6231be0SApple OSS Distributions 			if (!root) {
5607e6231be0SApple OSS Distributions 			        return false;
5608e6231be0SApple OSS Distributions 			}
5609e6231be0SApple OSS Distributions 			terminateOptions = kIOServiceRequired | kIOServiceTerminateNeedWillTerminate;
5610e6231be0SApple OSS Distributions 			if (!nextService->terminate(terminateOptions)) {
5611e6231be0SApple OSS Distributions 			        IOLog("failed to terminate service %s-0x%llx\n", nextService->getName(), nextService->getRegistryEntryID());
5612e6231be0SApple OSS Distributions 			}
5613e6231be0SApple OSS Distributions 			return false;
5614e6231be0SApple OSS Distributions 		});
5615e6231be0SApple OSS Distributions 	}
5616e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(services);
5617e6231be0SApple OSS Distributions }
5618e6231be0SApple OSS Distributions 
5619e6231be0SApple OSS Distributions void
powerSourceChanged(bool acAttached)5620e6231be0SApple OSS Distributions IOUserServer::powerSourceChanged(bool acAttached)
5621e6231be0SApple OSS Distributions {
5622e6231be0SApple OSS Distributions 	OSDictionary * powerSourceDescription;
5623e6231be0SApple OSS Distributions 
5624e6231be0SApple OSS Distributions 	powerSourceDescription = OSDictionary::withCapacity(4);
5625e6231be0SApple OSS Distributions 	if (!powerSourceDescription) {
5626e6231be0SApple OSS Distributions 		return;
5627e6231be0SApple OSS Distributions 	}
5628e6231be0SApple OSS Distributions 	powerSourceDescription->setObject(gIOSystemStatePowerSourceDescriptionACAttachedKey, acAttached ? kOSBooleanTrue : kOSBooleanFalse);
5629e6231be0SApple OSS Distributions 	getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStatePowerSourceDescriptionKey, powerSourceDescription);
5630e6231be0SApple OSS Distributions 
5631e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(powerSourceDescription);
5632e6231be0SApple OSS Distributions }
5633a5e72196SApple OSS Distributions 
5634a5e72196SApple OSS Distributions IOReturn
serviceStarted(IOService * service,IOService * provider,bool result)5635a5e72196SApple OSS Distributions IOUserServer::serviceStarted(IOService * service, IOService * provider, bool result)
5636a5e72196SApple OSS Distributions {
5637a5e72196SApple OSS Distributions 	IOReturn    ret;
5638a5e72196SApple OSS Distributions 
5639a5e72196SApple OSS Distributions 	DKLOG(DKS "::start(" DKS ") %s\n", DKN(service), DKN(provider), result ? "ok" : "fail");
5640a5e72196SApple OSS Distributions 
5641a5e72196SApple OSS Distributions 	if (!result) {
5642a5e72196SApple OSS Distributions 		ret = kIOReturnSuccess;
5643a5e72196SApple OSS Distributions 		return ret;
5644a5e72196SApple OSS Distributions 	}
5645a5e72196SApple OSS Distributions 
56465c2921b0SApple OSS Distributions 	ret = serviceJoinPMTree(service);
5647a5e72196SApple OSS Distributions 
5648a5e72196SApple OSS Distributions 	service->reserved->uvars->started = true;
5649a5e72196SApple OSS Distributions 
56505c2921b0SApple OSS Distributions 	if (service->reserved->uvars->deferredRegisterService) {
56511031c584SApple OSS Distributions 		service->registerService(kIOServiceAsynchronous | kIOServiceDextRequirePowerForMatching);
56525c2921b0SApple OSS Distributions 		service->reserved->uvars->deferredRegisterService = false;
56535c2921b0SApple OSS Distributions 	}
56545c2921b0SApple OSS Distributions 
5655a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
5656a5e72196SApple OSS Distributions }
5657a5e72196SApple OSS Distributions 
5658a5e72196SApple OSS Distributions 
5659a5e72196SApple OSS Distributions IOReturn
serviceOpen(IOService * provider,IOService * client)5660a5e72196SApple OSS Distributions IOUserServer::serviceOpen(IOService * provider, IOService * client)
5661a5e72196SApple OSS Distributions {
5662a5e72196SApple OSS Distributions 	OSObjectUserVars * uvars;
56635c2921b0SApple OSS Distributions 	IOReturn ret;
5664a5e72196SApple OSS Distributions 
5665e6231be0SApple OSS Distributions 	IOLockLock(client->reserved->uvars->uvarsLock);
5666a5e72196SApple OSS Distributions 	uvars = client->reserved->uvars;
56675c2921b0SApple OSS Distributions 	if (uvars->willTerminate || uvars->stopped) {
56685c2921b0SApple OSS Distributions 		DKLOG(DKS "- " DKS " blocked attempt to open " DKS "\n", DKN(this), DKN(client), DKN(provider));
56695c2921b0SApple OSS Distributions 		ret = kIOReturnBadArgument;
56705c2921b0SApple OSS Distributions 	} else {
5671a5e72196SApple OSS Distributions 		if (!uvars->openProviders) {
5672a5e72196SApple OSS Distributions 			uvars->openProviders = OSArray::withObjects((const OSObject **) &provider, 1);
5673e6231be0SApple OSS Distributions 		} else if (-1U == uvars->openProviders->getNextIndexOfObject(provider, 0)) {
5674a5e72196SApple OSS Distributions 			uvars->openProviders->setObject(provider);
5675a5e72196SApple OSS Distributions 		}
56765c2921b0SApple OSS Distributions 		ret = kIOReturnSuccess;
56775c2921b0SApple OSS Distributions 	}
56785c2921b0SApple OSS Distributions 
5679e6231be0SApple OSS Distributions 	IOLockUnlock(client->reserved->uvars->uvarsLock);
5680a5e72196SApple OSS Distributions 
56815c2921b0SApple OSS Distributions 	return ret;
5682a5e72196SApple OSS Distributions }
5683a5e72196SApple OSS Distributions 
5684a5e72196SApple OSS Distributions IOReturn
serviceClose(IOService * provider,IOService * client)5685a5e72196SApple OSS Distributions IOUserServer::serviceClose(IOService * provider, IOService * client)
5686a5e72196SApple OSS Distributions {
5687a5e72196SApple OSS Distributions 	OSObjectUserVars * uvars;
5688a5e72196SApple OSS Distributions 	unsigned int       idx;
5689e6231be0SApple OSS Distributions 	IOReturn           ret;
5690a5e72196SApple OSS Distributions 
5691e6231be0SApple OSS Distributions 	IOLockLock(client->reserved->uvars->uvarsLock);
5692a5e72196SApple OSS Distributions 	uvars = client->reserved->uvars;
5693a5e72196SApple OSS Distributions 	if (!uvars->openProviders) {
5694e6231be0SApple OSS Distributions 		ret = kIOReturnNotOpen;
5695e6231be0SApple OSS Distributions 		goto finish;
5696a5e72196SApple OSS Distributions 	}
5697e6231be0SApple OSS Distributions 	idx = uvars->openProviders->getNextIndexOfObject(provider, 0);
5698a5e72196SApple OSS Distributions 	if (-1U == idx) {
5699e6231be0SApple OSS Distributions 		ret = kIOReturnNotOpen;
5700e6231be0SApple OSS Distributions 		goto finish;
5701a5e72196SApple OSS Distributions 	}
5702a5e72196SApple OSS Distributions 	uvars->openProviders->removeObject(idx);
5703e6231be0SApple OSS Distributions 	if (!uvars->openProviders->getCount()) {
5704e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(uvars->openProviders);
5705e6231be0SApple OSS Distributions 	}
5706a5e72196SApple OSS Distributions 
5707e6231be0SApple OSS Distributions 	ret = kIOReturnSuccess;
5708e6231be0SApple OSS Distributions 
5709e6231be0SApple OSS Distributions finish:
5710e6231be0SApple OSS Distributions 	IOLockUnlock(client->reserved->uvars->uvarsLock);
5711e6231be0SApple OSS Distributions 
5712e6231be0SApple OSS Distributions 	return ret;
5713a5e72196SApple OSS Distributions }
5714a5e72196SApple OSS Distributions 
5715a5e72196SApple OSS Distributions 
5716a5e72196SApple OSS Distributions IOReturn
serviceStop(IOService * service,IOService *)5717a5e72196SApple OSS Distributions IOUserServer::serviceStop(IOService * service, IOService *)
5718a5e72196SApple OSS Distributions {
5719a5e72196SApple OSS Distributions 	IOReturn           ret;
57208d741a5dSApple OSS Distributions 	uint32_t           idx;
5721e6231be0SApple OSS Distributions 	bool               pmAck;
5722a5e72196SApple OSS Distributions 	OSObjectUserVars * uvars;
5723e6231be0SApple OSS Distributions 	pmAck = false;
5724a5e72196SApple OSS Distributions 	IOLockLock(fLock);
5725a5e72196SApple OSS Distributions 	idx = fServices->getNextIndexOfObject(service, 0);
5726a5e72196SApple OSS Distributions 	if (-1U != idx) {
5727a5e72196SApple OSS Distributions 		fServices->removeObject(idx);
5728e6231be0SApple OSS Distributions 
5729e6231be0SApple OSS Distributions 		// Remove the service from IOAssociatedServices
5730e6231be0SApple OSS Distributions 		OSObject * serviceArrayObj = copyProperty(gIOAssociatedServicesKey);
5731e6231be0SApple OSS Distributions 		OSArray * serviceArray = OSDynamicCast(OSArray, serviceArrayObj);
5732e6231be0SApple OSS Distributions 		assert(serviceArray != NULL);
5733e6231be0SApple OSS Distributions 
5734e6231be0SApple OSS Distributions 		serviceArray = OSDynamicCast(OSArray, serviceArray->copyCollection());
5735e6231be0SApple OSS Distributions 		assert(serviceArray != NULL);
5736e6231be0SApple OSS Distributions 
5737e6231be0SApple OSS Distributions 		// Index should be the same as it was in fServices
5738e6231be0SApple OSS Distributions 		OSNumber * __assert_only registryEntryID = OSDynamicCast(OSNumber, serviceArray->getObject(idx));
5739e6231be0SApple OSS Distributions 		assert(registryEntryID);
5740e6231be0SApple OSS Distributions 
5741e6231be0SApple OSS Distributions 		// ensure it is the right service
5742e6231be0SApple OSS Distributions 		assert(registryEntryID->unsigned64BitValue() == service->getRegistryEntryID());
5743e6231be0SApple OSS Distributions 		serviceArray->removeObject(idx);
5744e6231be0SApple OSS Distributions 
5745e6231be0SApple OSS Distributions 		setProperty(gIOAssociatedServicesKey, serviceArray);
5746e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(serviceArray);
5747e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(serviceArrayObj);
5748e6231be0SApple OSS Distributions 
5749a5e72196SApple OSS Distributions 		uvars = service->reserved->uvars;
5750a5e72196SApple OSS Distributions 		uvars->stopped = true;
5751e6231be0SApple OSS Distributions 		uvars->powerState = 0;
5752e6231be0SApple OSS Distributions 
5753e6231be0SApple OSS Distributions 		bool allPowerStates __block = 0;
5754e6231be0SApple OSS Distributions 		// any service on?
5755e6231be0SApple OSS Distributions 		fServices->iterateObjects(^bool (OSObject * obj) {
5756e6231be0SApple OSS Distributions 			int         service __unused;       // hide outer defn
5757e6231be0SApple OSS Distributions 			IOService * nextService;
5758e6231be0SApple OSS Distributions 			nextService = (IOService *) obj;
5759e6231be0SApple OSS Distributions 			allPowerStates = nextService->reserved->uvars->powerState;
5760e6231be0SApple OSS Distributions 			// early terminate if true
5761e6231be0SApple OSS Distributions 			return allPowerStates;
5762e6231be0SApple OSS Distributions 		});
5763e6231be0SApple OSS Distributions 
5764e6231be0SApple OSS Distributions 		if (!allPowerStates && (pmAck = fSystemPowerAck)) {
5765e6231be0SApple OSS Distributions 			fSystemPowerAck = false;
5766e6231be0SApple OSS Distributions 			fSystemOff      = true;
5767e6231be0SApple OSS Distributions 		}
5768a5e72196SApple OSS Distributions 	}
5769a5e72196SApple OSS Distributions 	IOLockUnlock(fLock);
5770e6231be0SApple OSS Distributions 	if (pmAck) {
5771e6231be0SApple OSS Distributions 		IOServicePH::serverAck(this);
5772e6231be0SApple OSS Distributions 	}
5773a5e72196SApple OSS Distributions 
5774a5e72196SApple OSS Distributions 	if (-1U == idx) {
5775a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
5776a5e72196SApple OSS Distributions 	}
5777a5e72196SApple OSS Distributions 
5778a5e72196SApple OSS Distributions 	(void) service->deRegisterInterestedDriver(this);
5779a5e72196SApple OSS Distributions 	if (uvars->userServerPM) {
5780a5e72196SApple OSS Distributions 		service->PMstop();
5781*4f1223e8SApple OSS Distributions 		service->acknowledgeSetPowerState();
5782a5e72196SApple OSS Distributions 	}
5783a5e72196SApple OSS Distributions 
5784a5e72196SApple OSS Distributions 	ret = kIOReturnSuccess;
5785a5e72196SApple OSS Distributions 	return ret;
5786a5e72196SApple OSS Distributions }
5787a5e72196SApple OSS Distributions 
5788a5e72196SApple OSS Distributions void
serviceFree(IOService * service)5789a5e72196SApple OSS Distributions IOUserServer::serviceFree(IOService * service)
5790a5e72196SApple OSS Distributions {
5791a5e72196SApple OSS Distributions 	OSObjectUserVars * uvars;
57928d741a5dSApple OSS Distributions 	uint32_t idx, queueAlloc;
57938d741a5dSApple OSS Distributions 	IODispatchQueue ** unboundedQueueArray = NULL;
5794a5e72196SApple OSS Distributions 
5795a5e72196SApple OSS Distributions 	uvars = service->reserved->uvars;
5796a5e72196SApple OSS Distributions 	if (!uvars) {
5797a5e72196SApple OSS Distributions 		return;
5798a5e72196SApple OSS Distributions 	}
57998d741a5dSApple OSS Distributions 	if (uvars->queueArray && uvars->userMeta) {
58008d741a5dSApple OSS Distributions 		queueAlloc = 1;
58018d741a5dSApple OSS Distributions 		if (uvars->userMeta->queueNames) {
58028d741a5dSApple OSS Distributions 			queueAlloc += uvars->userMeta->queueNames->count;
58038d741a5dSApple OSS Distributions 		}
58048d741a5dSApple OSS Distributions 		for (idx = 0; idx < queueAlloc; idx++) {
58058d741a5dSApple OSS Distributions 			OSSafeReleaseNULL(uvars->queueArray[idx]);
58068d741a5dSApple OSS Distributions 		}
58078d741a5dSApple OSS Distributions 		unboundedQueueArray = uvars->queueArray.data();
58088d741a5dSApple OSS Distributions 		IOSafeDeleteNULL(unboundedQueueArray, IODispatchQueue *, queueAlloc);
58098d741a5dSApple OSS Distributions 		uvars->queueArray = OSBoundedArrayRef<IODispatchQueue *>();
58108d741a5dSApple OSS Distributions 	}
5811a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(uvars->userServer);
5812e6231be0SApple OSS Distributions 	IOLockFree(uvars->uvarsLock);
5813e6231be0SApple OSS Distributions 	IOFreeType(service->reserved->uvars, OSObjectUserVars);
5814a5e72196SApple OSS Distributions }
5815a5e72196SApple OSS Distributions 
5816a5e72196SApple OSS Distributions void
serviceWillTerminate(IOService * client,IOService * provider,IOOptionBits options)5817a5e72196SApple OSS Distributions IOUserServer::serviceWillTerminate(IOService * client, IOService * provider, IOOptionBits options)
5818a5e72196SApple OSS Distributions {
5819a5e72196SApple OSS Distributions 	IOReturn ret;
5820a5e72196SApple OSS Distributions 	bool     willTerminate;
5821a5e72196SApple OSS Distributions 
5822a5e72196SApple OSS Distributions 	willTerminate = false;
5823e6231be0SApple OSS Distributions 	IOLockLock(client->reserved->uvars->uvarsLock);
5824a5e72196SApple OSS Distributions 	if (!client->reserved->uvars->serverDied
5825a5e72196SApple OSS Distributions 	    && !client->reserved->uvars->willTerminate) {
5826a5e72196SApple OSS Distributions 		client->reserved->uvars->willTerminate = true;
5827a5e72196SApple OSS Distributions 		willTerminate = true;
5828a5e72196SApple OSS Distributions 	}
5829e6231be0SApple OSS Distributions 	IOLockUnlock(client->reserved->uvars->uvarsLock);
5830a5e72196SApple OSS Distributions 
5831a5e72196SApple OSS Distributions 	if (willTerminate) {
5832e6231be0SApple OSS Distributions 		if (provider->isInactive() || IOServicePH::serverSlept()) {
5833bb611c8fSApple OSS Distributions 			client->Stop_async(provider);
5834bb611c8fSApple OSS Distributions 			ret = kIOReturnOffline;
5835bb611c8fSApple OSS Distributions 		} else {
5836a5e72196SApple OSS Distributions 			ret = client->Stop(provider);
5837bb611c8fSApple OSS Distributions 		}
5838a5e72196SApple OSS Distributions 		if (kIOReturnSuccess != ret) {
5839bb611c8fSApple OSS Distributions 			IOUserServer::serviceDidStop(client, provider);
5840bb611c8fSApple OSS Distributions 			ret = kIOReturnSuccess;
5841a5e72196SApple OSS Distributions 		}
5842a5e72196SApple OSS Distributions 	}
5843a5e72196SApple OSS Distributions }
5844a5e72196SApple OSS Distributions 
5845a5e72196SApple OSS Distributions void
serviceDidTerminate(IOService * client,IOService * provider,IOOptionBits options,bool * defer)5846a5e72196SApple OSS Distributions IOUserServer::serviceDidTerminate(IOService * client, IOService * provider, IOOptionBits options, bool * defer)
5847a5e72196SApple OSS Distributions {
5848e6231be0SApple OSS Distributions 	IOLockLock(client->reserved->uvars->uvarsLock);
5849a5e72196SApple OSS Distributions 	client->reserved->uvars->didTerminate = true;
5850a5e72196SApple OSS Distributions 	if (!client->reserved->uvars->serverDied
5851a5e72196SApple OSS Distributions 	    && !client->reserved->uvars->stopped) {
5852a5e72196SApple OSS Distributions 		*defer = true;
5853a5e72196SApple OSS Distributions 	}
5854e6231be0SApple OSS Distributions 	IOLockUnlock(client->reserved->uvars->uvarsLock);
5855a5e72196SApple OSS Distributions }
5856a5e72196SApple OSS Distributions 
5857a5e72196SApple OSS Distributions void
serviceDidStop(IOService * client,IOService * provider)5858a5e72196SApple OSS Distributions IOUserServer::serviceDidStop(IOService * client, IOService * provider)
5859a5e72196SApple OSS Distributions {
5860a5e72196SApple OSS Distributions 	bool complete;
5861a5e72196SApple OSS Distributions 	OSArray * closeArray;
5862a5e72196SApple OSS Distributions 
5863a5e72196SApple OSS Distributions 	complete = false;
5864a5e72196SApple OSS Distributions 	closeArray = NULL;
5865a5e72196SApple OSS Distributions 
5866e6231be0SApple OSS Distributions 	IOLockLock(client->reserved->uvars->uvarsLock);
5867a5e72196SApple OSS Distributions 	if (client->reserved->uvars
5868a5e72196SApple OSS Distributions 	    && client->reserved->uvars->willTerminate
5869a5e72196SApple OSS Distributions 	    && !client->reserved->uvars->stopped) {
5870a5e72196SApple OSS Distributions 		client->reserved->uvars->stopped = true;
5871a5e72196SApple OSS Distributions 		complete = client->reserved->uvars->didTerminate;
5872a5e72196SApple OSS Distributions 	}
5873a5e72196SApple OSS Distributions 
5874a5e72196SApple OSS Distributions 	if (client->reserved->uvars) {
5875a5e72196SApple OSS Distributions 		closeArray = client->reserved->uvars->openProviders;
5876a5e72196SApple OSS Distributions 		client->reserved->uvars->openProviders = NULL;
5877a5e72196SApple OSS Distributions 	}
5878e6231be0SApple OSS Distributions 	IOLockUnlock(client->reserved->uvars->uvarsLock);
5879e6231be0SApple OSS Distributions 
5880a5e72196SApple OSS Distributions 	if (closeArray) {
5881a5e72196SApple OSS Distributions 		closeArray->iterateObjects(^bool (OSObject * obj) {
5882a5e72196SApple OSS Distributions 			IOService * toClose;
5883a5e72196SApple OSS Distributions 			toClose = OSDynamicCast(IOService, obj);
5884a5e72196SApple OSS Distributions 			if (toClose) {
5885a5e72196SApple OSS Distributions 			        DKLOG(DKS ":force close (" DKS ")\n", DKN(client), DKN(toClose));
5886a5e72196SApple OSS Distributions 			        toClose->close(client);
5887a5e72196SApple OSS Distributions 			}
5888a5e72196SApple OSS Distributions 			return false;
5889a5e72196SApple OSS Distributions 		});
5890a5e72196SApple OSS Distributions 		closeArray->release();
5891a5e72196SApple OSS Distributions 	}
5892e6231be0SApple OSS Distributions 
5893a5e72196SApple OSS Distributions 	if (complete) {
5894a5e72196SApple OSS Distributions 		bool defer = false;
5895a5e72196SApple OSS Distributions 		client->didTerminate(provider, 0, &defer);
5896a5e72196SApple OSS Distributions 	}
5897a5e72196SApple OSS Distributions }
5898a5e72196SApple OSS Distributions 
5899a5e72196SApple OSS Distributions kern_return_t
ClientCrashed_Impl(IOService * client,uint64_t options)5900e6231be0SApple OSS Distributions IOService::ClientCrashed_Impl(
5901e6231be0SApple OSS Distributions 	IOService * client,
5902e6231be0SApple OSS Distributions 	uint64_t    options)
5903e6231be0SApple OSS Distributions {
5904e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
5905e6231be0SApple OSS Distributions }
5906e6231be0SApple OSS Distributions 
5907e6231be0SApple OSS Distributions kern_return_t
Stop_Impl(IOService * provider)5908bb611c8fSApple OSS Distributions IOService::Stop_Impl(
5909bb611c8fSApple OSS Distributions 	IOService * provider)
5910a5e72196SApple OSS Distributions {
5911a5e72196SApple OSS Distributions 	IOUserServer::serviceDidStop(this, provider);
5912a5e72196SApple OSS Distributions 
5913a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
5914a5e72196SApple OSS Distributions }
5915a5e72196SApple OSS Distributions 
5916bb611c8fSApple OSS Distributions void
Stop_async_Impl(IOService * provider)5917bb611c8fSApple OSS Distributions IOService::Stop_async_Impl(
5918bb611c8fSApple OSS Distributions 	IOService * provider)
5919a5e72196SApple OSS Distributions {
5920a5e72196SApple OSS Distributions }
5921a5e72196SApple OSS Distributions 
5922a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5923a5e72196SApple OSS Distributions 
5924a5e72196SApple OSS Distributions #undef super
5925a5e72196SApple OSS Distributions #define super IOUserClient
5926a5e72196SApple OSS Distributions 
OSDefineMetaClassAndStructors(IOUserUserClient,IOUserClient)5927a5e72196SApple OSS Distributions OSDefineMetaClassAndStructors(IOUserUserClient, IOUserClient)
5928a5e72196SApple OSS Distributions 
5929a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5930a5e72196SApple OSS Distributions 
5931e6231be0SApple OSS Distributions bool
5932e6231be0SApple OSS Distributions IOUserUserClient::init(OSDictionary * properties)
5933e6231be0SApple OSS Distributions {
5934e6231be0SApple OSS Distributions 	if (!super::init(properties)) {
5935e6231be0SApple OSS Distributions 		return false;
5936e6231be0SApple OSS Distributions 	}
5937e6231be0SApple OSS Distributions 
5938e6231be0SApple OSS Distributions 	fWorkGroups = OSDictionary::withCapacity(0);
5939e6231be0SApple OSS Distributions 	if (fWorkGroups == NULL) {
5940e6231be0SApple OSS Distributions 		return false;
5941e6231be0SApple OSS Distributions 	}
5942e6231be0SApple OSS Distributions 
5943e6231be0SApple OSS Distributions 	fEventLinks = OSDictionary::withCapacity(0);
5944e6231be0SApple OSS Distributions 	if (fEventLinks == NULL) {
5945e6231be0SApple OSS Distributions 		return false;
5946e6231be0SApple OSS Distributions 	}
5947e6231be0SApple OSS Distributions 
5948e6231be0SApple OSS Distributions 	fLock = IOLockAlloc();
5949e6231be0SApple OSS Distributions 
5950e6231be0SApple OSS Distributions 	return true;
5951e6231be0SApple OSS Distributions }
5952e6231be0SApple OSS Distributions 
5953e6231be0SApple OSS Distributions void
free()5954e6231be0SApple OSS Distributions IOUserUserClient::free()
5955e6231be0SApple OSS Distributions {
5956e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(fWorkGroups);
5957e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(fEventLinks);
5958e6231be0SApple OSS Distributions 	if (fLock) {
5959e6231be0SApple OSS Distributions 		IOLockFree(fLock);
5960e6231be0SApple OSS Distributions 	}
5961e6231be0SApple OSS Distributions 
5962e6231be0SApple OSS Distributions 	super::free();
5963e6231be0SApple OSS Distributions }
5964e6231be0SApple OSS Distributions 
5965a5e72196SApple OSS Distributions IOReturn
setTask(task_t task)5966a5e72196SApple OSS Distributions IOUserUserClient::setTask(task_t task)
5967a5e72196SApple OSS Distributions {
5968a5e72196SApple OSS Distributions 	task_reference(task);
5969a5e72196SApple OSS Distributions 	fTask = task;
5970a5e72196SApple OSS Distributions 
5971a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
5972a5e72196SApple OSS Distributions }
5973a5e72196SApple OSS Distributions 
5974a5e72196SApple OSS Distributions void
stop(IOService * provider)5975a5e72196SApple OSS Distributions IOUserUserClient::stop(IOService * provider)
5976a5e72196SApple OSS Distributions {
5977a5e72196SApple OSS Distributions 	if (fTask) {
5978a5e72196SApple OSS Distributions 		task_deallocate(fTask);
5979a5e72196SApple OSS Distributions 		fTask = NULL;
5980a5e72196SApple OSS Distributions 	}
5981a5e72196SApple OSS Distributions 	super::stop(provider);
5982a5e72196SApple OSS Distributions }
5983a5e72196SApple OSS Distributions 
5984a5e72196SApple OSS Distributions IOReturn
clientClose(void)5985a5e72196SApple OSS Distributions IOUserUserClient::clientClose(void)
5986a5e72196SApple OSS Distributions {
5987bb611c8fSApple OSS Distributions 	terminate(kIOServiceTerminateNeedWillTerminate);
5988a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
5989a5e72196SApple OSS Distributions }
5990a5e72196SApple OSS Distributions 
5991a5e72196SApple OSS Distributions IOReturn
setProperties(OSObject * properties)5992a5e72196SApple OSS Distributions IOUserUserClient::setProperties(OSObject * properties)
5993a5e72196SApple OSS Distributions {
5994a5e72196SApple OSS Distributions 	IOReturn ret = kIOReturnUnsupported;
5995a5e72196SApple OSS Distributions 	return ret;
5996a5e72196SApple OSS Distributions }
5997a5e72196SApple OSS Distributions 
5998e6231be0SApple OSS Distributions // p1 - name of object
5999e6231be0SApple OSS Distributions // p2 - length of object name
6000e6231be0SApple OSS Distributions // p3 - mach port name
6001e6231be0SApple OSS Distributions 
6002e6231be0SApple OSS Distributions kern_return_t
eventlinkConfigurationTrap(void * p1,void * p2,void * p3,void * p4,void * p5,void * p6)6003e6231be0SApple OSS Distributions IOUserUserClient::eventlinkConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
6004e6231be0SApple OSS Distributions {
6005e6231be0SApple OSS Distributions 	user_addr_t userObjectName = (user_addr_t)p1;
6006e6231be0SApple OSS Distributions 	mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
6007e6231be0SApple OSS Distributions 	mach_port_t port = MACH_PORT_NULL;
6008e6231be0SApple OSS Distributions 	ipc_kobject_type_t portType;
6009e6231be0SApple OSS Distributions 	char eventlinkName[kIOEventLinkMaxNameLength + 1] = {0};
6010e6231be0SApple OSS Distributions 	size_t eventLinkNameLen;
6011e6231be0SApple OSS Distributions 	OSString * eventlinkNameStr = NULL; // must release
6012e6231be0SApple OSS Distributions 	IOEventLink * eventLink = NULL; // do not release
6013e6231be0SApple OSS Distributions 	kern_return_t ret;
6014e6231be0SApple OSS Distributions 
6015e6231be0SApple OSS Distributions 	ret = copyinstr(userObjectName, &eventlinkName[0], sizeof(eventlinkName), &eventLinkNameLen);
6016e6231be0SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
6017e6231be0SApple OSS Distributions 		goto finish;
6018e6231be0SApple OSS Distributions 	}
6019e6231be0SApple OSS Distributions 
6020e6231be0SApple OSS Distributions 	// ensure string length matches trap argument
6021e6231be0SApple OSS Distributions 	if (eventLinkNameLen != (size_t)p2 + 1) {
6022e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
6023e6231be0SApple OSS Distributions 		goto finish;
6024e6231be0SApple OSS Distributions 	}
6025e6231be0SApple OSS Distributions 
6026e6231be0SApple OSS Distributions 	eventlinkNameStr = OSString::withCStringNoCopy(eventlinkName);
6027e6231be0SApple OSS Distributions 	if (eventlinkNameStr == NULL) {
6028e6231be0SApple OSS Distributions 		ret = kIOReturnNoMemory;
6029e6231be0SApple OSS Distributions 		goto finish;
6030e6231be0SApple OSS Distributions 	}
6031e6231be0SApple OSS Distributions 
6032e6231be0SApple OSS Distributions 	IOLockLock(fLock);
6033e6231be0SApple OSS Distributions 	eventLink = OSDynamicCast(IOEventLink, fEventLinks->getObject(eventlinkNameStr));
6034e7776783SApple OSS Distributions 	if (eventLink) {
6035e7776783SApple OSS Distributions 		eventLink->retain();
6036e7776783SApple OSS Distributions 	}
6037e6231be0SApple OSS Distributions 	IOLockUnlock(fLock);
6038e6231be0SApple OSS Distributions 
6039e6231be0SApple OSS Distributions 	if (eventLink == NULL) {
6040e6231be0SApple OSS Distributions 		ret = kIOReturnNotFound;
6041e6231be0SApple OSS Distributions 		goto finish;
6042e6231be0SApple OSS Distributions 	}
6043e6231be0SApple OSS Distributions 
6044e6231be0SApple OSS Distributions 	port = iokit_lookup_raw_current_task(portName, &portType);
6045e6231be0SApple OSS Distributions 
6046e6231be0SApple OSS Distributions 	if (port == NULL) {
6047e6231be0SApple OSS Distributions 		ret = kIOReturnNotFound;
6048e6231be0SApple OSS Distributions 		goto finish;
6049e6231be0SApple OSS Distributions 	}
6050e6231be0SApple OSS Distributions 
6051e6231be0SApple OSS Distributions 	if (portType != IKOT_EVENTLINK) {
6052e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
6053e6231be0SApple OSS Distributions 		goto finish;
6054e6231be0SApple OSS Distributions 	}
6055e6231be0SApple OSS Distributions 
6056e6231be0SApple OSS Distributions 	ret = eventLink->SetEventlinkPort(port);
6057e6231be0SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
6058e6231be0SApple OSS Distributions 		if (kIODKLogSetup & gIODKDebug) {
6059e6231be0SApple OSS Distributions 			DKLOG(DKS " %s SetEventlinkPort() returned %x\n", DKN(this), eventlinkNameStr->getCStringNoCopy(), ret);
6060e6231be0SApple OSS Distributions 		}
6061e6231be0SApple OSS Distributions 		goto finish;
6062e6231be0SApple OSS Distributions 	}
6063e6231be0SApple OSS Distributions 
6064e6231be0SApple OSS Distributions finish:
6065e6231be0SApple OSS Distributions 	if (port != NULL) {
6066e6231be0SApple OSS Distributions 		iokit_release_port_send(port);
6067e6231be0SApple OSS Distributions 	}
6068e6231be0SApple OSS Distributions 
6069e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(eventlinkNameStr);
6070e7776783SApple OSS Distributions 	OSSafeReleaseNULL(eventLink);
6071e6231be0SApple OSS Distributions 
6072e6231be0SApple OSS Distributions 	return ret;
6073e6231be0SApple OSS Distributions }
6074e6231be0SApple OSS Distributions 
6075e6231be0SApple OSS Distributions kern_return_t
workgroupConfigurationTrap(void * p1,void * p2,void * p3,void * p4,void * p5,void * p6)6076e6231be0SApple OSS Distributions IOUserUserClient::workgroupConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
6077e6231be0SApple OSS Distributions {
6078e6231be0SApple OSS Distributions 	user_addr_t userObjectName = (user_addr_t)p1;
6079e6231be0SApple OSS Distributions 	mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
6080e6231be0SApple OSS Distributions 	mach_port_t port = MACH_PORT_NULL;
6081e6231be0SApple OSS Distributions 	ipc_kobject_type_t portType;
6082e6231be0SApple OSS Distributions 	char workgroupName[kIOWorkGroupMaxNameLength + 1] = {0};
6083e6231be0SApple OSS Distributions 	size_t workgroupNameLen;
6084e6231be0SApple OSS Distributions 	OSString * workgroupNameStr = NULL; // must release
6085e6231be0SApple OSS Distributions 	IOWorkGroup * workgroup = NULL; // do not release
6086e6231be0SApple OSS Distributions 	kern_return_t ret;
6087e6231be0SApple OSS Distributions 
6088e6231be0SApple OSS Distributions 	ret = copyinstr(userObjectName, &workgroupName[0], sizeof(workgroupName), &workgroupNameLen);
6089e6231be0SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
6090e6231be0SApple OSS Distributions 		goto finish;
6091e6231be0SApple OSS Distributions 	}
6092e6231be0SApple OSS Distributions 
6093e6231be0SApple OSS Distributions 	// ensure string length matches trap argument
6094e6231be0SApple OSS Distributions 	if (workgroupNameLen != (size_t)p2 + 1) {
6095e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
6096e6231be0SApple OSS Distributions 		goto finish;
6097e6231be0SApple OSS Distributions 	}
6098e6231be0SApple OSS Distributions 
6099e6231be0SApple OSS Distributions 	workgroupNameStr = OSString::withCStringNoCopy(workgroupName);
6100e6231be0SApple OSS Distributions 	if (workgroupNameStr == NULL) {
6101e6231be0SApple OSS Distributions 		ret = kIOReturnNoMemory;
6102e6231be0SApple OSS Distributions 		goto finish;
6103e6231be0SApple OSS Distributions 	}
6104e6231be0SApple OSS Distributions 
6105e6231be0SApple OSS Distributions 	IOLockLock(fLock);
6106e6231be0SApple OSS Distributions 	workgroup = OSDynamicCast(IOWorkGroup, fWorkGroups->getObject(workgroupNameStr));
6107e7776783SApple OSS Distributions 	if (workgroup) {
6108e7776783SApple OSS Distributions 		workgroup->retain();
6109e7776783SApple OSS Distributions 	}
6110e6231be0SApple OSS Distributions 	IOLockUnlock(fLock);
6111e6231be0SApple OSS Distributions 
6112e6231be0SApple OSS Distributions 	if (workgroup == NULL) {
6113e6231be0SApple OSS Distributions 		ret = kIOReturnNotFound;
6114e6231be0SApple OSS Distributions 		goto finish;
6115e6231be0SApple OSS Distributions 	}
6116e6231be0SApple OSS Distributions 
6117e6231be0SApple OSS Distributions 	port = iokit_lookup_raw_current_task(portName, &portType);
6118e6231be0SApple OSS Distributions 
6119e6231be0SApple OSS Distributions 	if (port == NULL) {
6120e6231be0SApple OSS Distributions 		ret = kIOReturnNotFound;
6121e6231be0SApple OSS Distributions 		goto finish;
6122e6231be0SApple OSS Distributions 	}
6123e6231be0SApple OSS Distributions 
6124e6231be0SApple OSS Distributions 	if (portType != IKOT_WORK_INTERVAL) {
6125e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
6126e6231be0SApple OSS Distributions 		goto finish;
6127e6231be0SApple OSS Distributions 	}
6128e6231be0SApple OSS Distributions 
6129e6231be0SApple OSS Distributions 	ret = workgroup->SetWorkGroupPort(port);
6130e6231be0SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
6131e6231be0SApple OSS Distributions 		if (kIODKLogSetup & gIODKDebug) {
6132e6231be0SApple OSS Distributions 			DKLOG(DKS " %s SetWorkGroupPort() returned %x\n", DKN(this), workgroupNameStr->getCStringNoCopy(), ret);
6133e6231be0SApple OSS Distributions 		}
6134e6231be0SApple OSS Distributions 		goto finish;
6135e6231be0SApple OSS Distributions 	}
6136e6231be0SApple OSS Distributions 
6137e6231be0SApple OSS Distributions finish:
6138e6231be0SApple OSS Distributions 
6139e6231be0SApple OSS Distributions 	if (port != NULL) {
6140e6231be0SApple OSS Distributions 		iokit_release_port_send(port);
6141e6231be0SApple OSS Distributions 	}
6142e6231be0SApple OSS Distributions 
6143e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(workgroupNameStr);
6144e7776783SApple OSS Distributions 	OSSafeReleaseNULL(workgroup);
6145e6231be0SApple OSS Distributions 
6146e6231be0SApple OSS Distributions 	return ret;
6147e6231be0SApple OSS Distributions }
6148e6231be0SApple OSS Distributions 
6149e6231be0SApple OSS Distributions IOExternalTrap *
getTargetAndTrapForIndex(IOService ** targetP,UInt32 index)6150e6231be0SApple OSS Distributions IOUserUserClient::getTargetAndTrapForIndex( IOService **targetP, UInt32 index )
6151e6231be0SApple OSS Distributions {
61525c2921b0SApple OSS Distributions 	static const OSBoundedArray<IOExternalTrap, 2> trapTemplate = {{
6153e6231be0SApple OSS Distributions 									       { NULL, (IOTrap) & IOUserUserClient::eventlinkConfigurationTrap},
6154e6231be0SApple OSS Distributions 									       { NULL, (IOTrap) & IOUserUserClient::workgroupConfigurationTrap},
61555c2921b0SApple OSS Distributions 								       }};
61565c2921b0SApple OSS Distributions 	if (index >= trapTemplate.size()) {
6157e6231be0SApple OSS Distributions 		return NULL;
6158e6231be0SApple OSS Distributions 	}
6159e6231be0SApple OSS Distributions 	*targetP = this;
6160e6231be0SApple OSS Distributions 	return (IOExternalTrap *)&trapTemplate[index];
6161e6231be0SApple OSS Distributions }
6162e6231be0SApple OSS Distributions 
6163e6231be0SApple OSS Distributions kern_return_t
CopyClientEntitlements_Impl(OSDictionary ** entitlements)6164e6231be0SApple OSS Distributions IOUserClient::CopyClientEntitlements_Impl(OSDictionary ** entitlements)
6165e6231be0SApple OSS Distributions {
6166e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
6167e6231be0SApple OSS Distributions };
6168e6231be0SApple OSS Distributions 
6169a5e72196SApple OSS Distributions struct IOUserUserClientActionRef {
6170a5e72196SApple OSS Distributions 	OSAsyncReference64 asyncRef;
6171a5e72196SApple OSS Distributions };
6172a5e72196SApple OSS Distributions 
6173a5e72196SApple OSS Distributions void
KernelCompletion_Impl(OSAction * action,IOReturn status,const unsigned long long * asyncData,uint32_t asyncDataCount)6174bb611c8fSApple OSS Distributions IOUserClient::KernelCompletion_Impl(
6175bb611c8fSApple OSS Distributions 	OSAction * action,
6176bb611c8fSApple OSS Distributions 	IOReturn status,
6177bb611c8fSApple OSS Distributions 	const unsigned long long * asyncData,
6178bb611c8fSApple OSS Distributions 	uint32_t asyncDataCount)
6179a5e72196SApple OSS Distributions {
6180a5e72196SApple OSS Distributions 	IOUserUserClientActionRef * ref;
6181a5e72196SApple OSS Distributions 
6182a5e72196SApple OSS Distributions 	ref = (typeof(ref))action->GetReference();
6183a5e72196SApple OSS Distributions 
6184a5e72196SApple OSS Distributions 	IOUserClient::sendAsyncResult64(ref->asyncRef, status, (io_user_reference_t *) asyncData, asyncDataCount);
6185a5e72196SApple OSS Distributions }
6186a5e72196SApple OSS Distributions 
6187a5e72196SApple OSS Distributions kern_return_t
_ExternalMethod_Impl(uint64_t selector,const unsigned long long * scalarInput,uint32_t scalarInputCount,OSData * structureInput,IOMemoryDescriptor * structureInputDescriptor,unsigned long long * scalarOutput,uint32_t * scalarOutputCount,uint64_t structureOutputMaximumSize,OSData ** structureOutput,IOMemoryDescriptor * structureOutputDescriptor,OSAction * completion)6188bb611c8fSApple OSS Distributions IOUserClient::_ExternalMethod_Impl(
6189bb611c8fSApple OSS Distributions 	uint64_t selector,
6190bb611c8fSApple OSS Distributions 	const unsigned long long * scalarInput,
6191bb611c8fSApple OSS Distributions 	uint32_t scalarInputCount,
6192bb611c8fSApple OSS Distributions 	OSData * structureInput,
6193bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * structureInputDescriptor,
6194bb611c8fSApple OSS Distributions 	unsigned long long * scalarOutput,
6195bb611c8fSApple OSS Distributions 	uint32_t * scalarOutputCount,
6196bb611c8fSApple OSS Distributions 	uint64_t structureOutputMaximumSize,
6197bb611c8fSApple OSS Distributions 	OSData ** structureOutput,
6198bb611c8fSApple OSS Distributions 	IOMemoryDescriptor * structureOutputDescriptor,
6199bb611c8fSApple OSS Distributions 	OSAction * completion)
6200a5e72196SApple OSS Distributions {
6201a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
6202a5e72196SApple OSS Distributions }
6203a5e72196SApple OSS Distributions 
6204a5e72196SApple OSS Distributions IOReturn
clientMemoryForType(UInt32 type,IOOptionBits * koptions,IOMemoryDescriptor ** kmemory)6205a5e72196SApple OSS Distributions IOUserUserClient::clientMemoryForType(UInt32 type,
6206a5e72196SApple OSS Distributions     IOOptionBits * koptions,
6207a5e72196SApple OSS Distributions     IOMemoryDescriptor ** kmemory)
6208a5e72196SApple OSS Distributions {
6209a5e72196SApple OSS Distributions 	IOReturn             kr;
6210a5e72196SApple OSS Distributions 	uint64_t             options;
6211a5e72196SApple OSS Distributions 	IOMemoryDescriptor * memory;
6212a5e72196SApple OSS Distributions 
6213a5e72196SApple OSS Distributions 	kr = CopyClientMemoryForType(type, &options, &memory);
6214a5e72196SApple OSS Distributions 
6215a5e72196SApple OSS Distributions 	*koptions = 0;
6216a5e72196SApple OSS Distributions 	*kmemory  = NULL;
6217a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != kr) {
6218a5e72196SApple OSS Distributions 		return kr;
6219a5e72196SApple OSS Distributions 	}
6220a5e72196SApple OSS Distributions 
6221a5e72196SApple OSS Distributions 	if (kIOUserClientMemoryReadOnly & options) {
6222a5e72196SApple OSS Distributions 		*koptions |= kIOMapReadOnly;
6223a5e72196SApple OSS Distributions 	}
6224a5e72196SApple OSS Distributions 	*kmemory = memory;
6225a5e72196SApple OSS Distributions 
6226a5e72196SApple OSS Distributions 	return kr;
6227a5e72196SApple OSS Distributions }
6228a5e72196SApple OSS Distributions 
6229a5e72196SApple OSS Distributions IOReturn
externalMethod(uint32_t selector,IOExternalMethodArguments * args,IOExternalMethodDispatch * dispatch,OSObject * target,void * reference)6230a5e72196SApple OSS Distributions IOUserUserClient::externalMethod(uint32_t selector, IOExternalMethodArguments * args,
6231a5e72196SApple OSS Distributions     IOExternalMethodDispatch * dispatch, OSObject * target, void * reference)
6232a5e72196SApple OSS Distributions {
6233a5e72196SApple OSS Distributions 	IOReturn   kr;
6234a5e72196SApple OSS Distributions 	OSData   * structureInput;
6235a5e72196SApple OSS Distributions 	OSData   * structureOutput;
6236a5e72196SApple OSS Distributions 	size_t     copylen;
6237a5e72196SApple OSS Distributions 	uint64_t   structureOutputSize;
6238a5e72196SApple OSS Distributions 	OSAction                  * action;
6239a5e72196SApple OSS Distributions 	IOUserUserClientActionRef * ref;
6240e7776783SApple OSS Distributions 	mach_port_t wake_port = MACH_PORT_NULL;
6241a5e72196SApple OSS Distributions 
6242a5e72196SApple OSS Distributions 	kr             = kIOReturnUnsupported;
6243a5e72196SApple OSS Distributions 	structureInput = NULL;
6244a5e72196SApple OSS Distributions 	action         = NULL;
6245bb611c8fSApple OSS Distributions 	ref            = NULL;
6246a5e72196SApple OSS Distributions 
6247a5e72196SApple OSS Distributions 	if (args->structureInputSize) {
6248a5e72196SApple OSS Distributions 		structureInput = OSData::withBytesNoCopy((void *) args->structureInput, args->structureInputSize);
6249a5e72196SApple OSS Distributions 	}
6250a5e72196SApple OSS Distributions 
6251a5e72196SApple OSS Distributions 	if (MACH_PORT_NULL != args->asyncWakePort) {
6252e6231be0SApple OSS Distributions 		// this retain is for the OSAction to release
62535c2921b0SApple OSS Distributions 		wake_port = ipc_port_make_send_mqueue(args->asyncWakePort);
6254a5e72196SApple OSS Distributions 		kr = CreateActionKernelCompletion(sizeof(IOUserUserClientActionRef), &action);
6255a5e72196SApple OSS Distributions 		assert(KERN_SUCCESS == kr);
6256a5e72196SApple OSS Distributions 		ref = (typeof(ref))action->GetReference();
6257a5e72196SApple OSS Distributions 		bcopy(args->asyncReference, &ref->asyncRef[0], args->asyncReferenceCount * sizeof(ref->asyncRef[0]));
6258bb611c8fSApple OSS Distributions 		kr = action->SetAbortedHandler(^(void) {
6259bb611c8fSApple OSS Distributions 			IOUserUserClientActionRef * ref;
6260bb611c8fSApple OSS Distributions 			IOReturn ret;
6261bb611c8fSApple OSS Distributions 
6262bb611c8fSApple OSS Distributions 			ref = (typeof(ref))action->GetReference();
6263bb611c8fSApple OSS Distributions 			ret = releaseAsyncReference64(ref->asyncRef);
6264bb611c8fSApple OSS Distributions 			assert(kIOReturnSuccess == ret);
6265bb611c8fSApple OSS Distributions 			bzero(&ref->asyncRef[0], sizeof(ref->asyncRef));
6266bb611c8fSApple OSS Distributions 		});
6267bb611c8fSApple OSS Distributions 		assert(KERN_SUCCESS == kr);
6268a5e72196SApple OSS Distributions 	}
6269a5e72196SApple OSS Distributions 
6270a5e72196SApple OSS Distributions 	if (args->structureVariableOutputData) {
6271a5e72196SApple OSS Distributions 		structureOutputSize = kIOUserClientVariableStructureSize;
6272a5e72196SApple OSS Distributions 	} else if (args->structureOutputDescriptor) {
6273a5e72196SApple OSS Distributions 		structureOutputSize = args->structureOutputDescriptor->getLength();
6274a5e72196SApple OSS Distributions 	} else {
6275a5e72196SApple OSS Distributions 		structureOutputSize = args->structureOutputSize;
6276a5e72196SApple OSS Distributions 	}
6277a5e72196SApple OSS Distributions 
6278a5e72196SApple OSS Distributions 	kr = _ExternalMethod(selector, &args->scalarInput[0], args->scalarInputCount,
6279a5e72196SApple OSS Distributions 	    structureInput, args->structureInputDescriptor,
6280a5e72196SApple OSS Distributions 	    args->scalarOutput, &args->scalarOutputCount,
6281a5e72196SApple OSS Distributions 	    structureOutputSize, &structureOutput, args->structureOutputDescriptor,
6282a5e72196SApple OSS Distributions 	    action);
6283a5e72196SApple OSS Distributions 
6284a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(structureInput);
6285a5e72196SApple OSS Distributions 	OSSafeReleaseNULL(action);
6286a5e72196SApple OSS Distributions 
62875c2921b0SApple OSS Distributions 	if (kr == kIOReturnSuccess && structureOutput) {
6288a5e72196SApple OSS Distributions 		if (args->structureVariableOutputData) {
6289a5e72196SApple OSS Distributions 			*args->structureVariableOutputData = structureOutput;
6290a5e72196SApple OSS Distributions 		} else {
6291a5e72196SApple OSS Distributions 			copylen = structureOutput->getLength();
6292a5e72196SApple OSS Distributions 			if (copylen > args->structureOutputSize) {
6293a5e72196SApple OSS Distributions 				kr = kIOReturnBadArgument;
6294a5e72196SApple OSS Distributions 			} else {
6295a5e72196SApple OSS Distributions 				bcopy((const void *) structureOutput->getBytesNoCopy(), args->structureOutput, copylen);
6296e6231be0SApple OSS Distributions 				args->structureOutputSize = (uint32_t) copylen;
6297a5e72196SApple OSS Distributions 			}
6298a5e72196SApple OSS Distributions 			OSSafeReleaseNULL(structureOutput);
6299a5e72196SApple OSS Distributions 		}
6300a5e72196SApple OSS Distributions 	}
6301a5e72196SApple OSS Distributions 
63025c2921b0SApple OSS Distributions 	if (kIOReturnSuccess != kr) {
63035c2921b0SApple OSS Distributions 		// mig will destroy any async port
63045c2921b0SApple OSS Distributions 		return kr;
63055c2921b0SApple OSS Distributions 	}
63065c2921b0SApple OSS Distributions 
63075c2921b0SApple OSS Distributions 	// We must never return error after this point in order to preserve MIG ownership semantics
63085c2921b0SApple OSS Distributions 	assert(kr == kIOReturnSuccess);
63095c2921b0SApple OSS Distributions 	if (MACH_PORT_NULL != wake_port) {
63105c2921b0SApple OSS Distributions 		// this release is for the mig created send right
63115c2921b0SApple OSS Distributions 		iokit_release_port_send(wake_port);
63125c2921b0SApple OSS Distributions 	}
63135c2921b0SApple OSS Distributions 
6314a5e72196SApple OSS Distributions 	return kr;
6315a5e72196SApple OSS Distributions }
6316a5e72196SApple OSS Distributions 
6317a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6318bb611c8fSApple OSS Distributions 
6319e6231be0SApple OSS Distributions extern IORecursiveLock               * gDriverKitLaunchLock;
6320e6231be0SApple OSS Distributions extern OSSet                         * gDriverKitLaunches;
6321e6231be0SApple OSS Distributions 
6322e6231be0SApple OSS Distributions _IOUserServerCheckInCancellationHandler *
setCancellationHandler(IOUserServerCheckInCancellationHandler handler,void * handlerArgs)6323e6231be0SApple OSS Distributions IOUserServerCheckInToken::setCancellationHandler(IOUserServerCheckInCancellationHandler handler,
6324bb611c8fSApple OSS Distributions     void* handlerArgs)
6325bb611c8fSApple OSS Distributions {
6326e6231be0SApple OSS Distributions 	_IOUserServerCheckInCancellationHandler * handlerObj = _IOUserServerCheckInCancellationHandler::withHandler(handler, handlerArgs);
6327e6231be0SApple OSS Distributions 	if (!handlerObj) {
6328e6231be0SApple OSS Distributions 		goto finish;
6329e6231be0SApple OSS Distributions 	}
6330e6231be0SApple OSS Distributions 
6331e7776783SApple OSS Distributions 	IORecursiveLockLock(gDriverKitLaunchLock);
6332e7776783SApple OSS Distributions 
6333e6231be0SApple OSS Distributions 	if (fState == kIOUserServerCheckInCanceled) {
6334e6231be0SApple OSS Distributions 		// Send cancel notification if we set the handler after this was canceled
6335e7776783SApple OSS Distributions 		handlerObj->call(this);
6336e6231be0SApple OSS Distributions 	} else if (fState == kIOUserServerCheckInPending) {
6337e6231be0SApple OSS Distributions 		fHandlers->setObject(handlerObj);
6338e6231be0SApple OSS Distributions 	}
6339e6231be0SApple OSS Distributions 
6340e7776783SApple OSS Distributions 	IORecursiveLockUnlock(gDriverKitLaunchLock);
6341e6231be0SApple OSS Distributions 
6342e6231be0SApple OSS Distributions finish:
6343e6231be0SApple OSS Distributions 	return handlerObj;
6344bb611c8fSApple OSS Distributions }
6345bb611c8fSApple OSS Distributions 
6346bb611c8fSApple OSS Distributions void
removeCancellationHandler(_IOUserServerCheckInCancellationHandler * handler)6347e6231be0SApple OSS Distributions IOUserServerCheckInToken::removeCancellationHandler(_IOUserServerCheckInCancellationHandler * handler)
6348bb611c8fSApple OSS Distributions {
6349e6231be0SApple OSS Distributions 	IORecursiveLockLock(gDriverKitLaunchLock);
6350e6231be0SApple OSS Distributions 
6351e7776783SApple OSS Distributions 	fHandlers->removeObject(handler);
6352e7776783SApple OSS Distributions 
6353e7776783SApple OSS Distributions 	IORecursiveLockUnlock(gDriverKitLaunchLock);
6354e6231be0SApple OSS Distributions }
6355e6231be0SApple OSS Distributions 
6356e6231be0SApple OSS Distributions void
cancel()6357e6231be0SApple OSS Distributions IOUserServerCheckInToken::cancel()
6358e6231be0SApple OSS Distributions {
6359e7776783SApple OSS Distributions 	IORecursiveLockLock(gDriverKitLaunchLock);
6360e6231be0SApple OSS Distributions 
6361e7776783SApple OSS Distributions 	if (fState == kIOUserServerCheckInPending) {
6362e7776783SApple OSS Distributions 		fState = kIOUserServerCheckInCanceled;
6363e7776783SApple OSS Distributions 		if (gDriverKitLaunches != NULL) {
6364e7776783SApple OSS Distributions 			// Remove pending launch from list, if we have not shut down yet.
6365e7776783SApple OSS Distributions 			gDriverKitLaunches->removeObject(this);
6366e7776783SApple OSS Distributions 		}
6367e7776783SApple OSS Distributions 
6368e6231be0SApple OSS Distributions 		fHandlers->iterateObjects(^bool (OSObject * obj){
6369e6231be0SApple OSS Distributions 			_IOUserServerCheckInCancellationHandler * handlerObj = OSDynamicCast(_IOUserServerCheckInCancellationHandler, obj);
6370e6231be0SApple OSS Distributions 			if (handlerObj) {
6371e6231be0SApple OSS Distributions 			        handlerObj->call(this);
6372e6231be0SApple OSS Distributions 			}
6373e6231be0SApple OSS Distributions 			return false;
6374e6231be0SApple OSS Distributions 		});
6375e6231be0SApple OSS Distributions 		fHandlers->flushCollection();
6376bb611c8fSApple OSS Distributions 	}
6377e7776783SApple OSS Distributions 
6378e7776783SApple OSS Distributions 	IORecursiveLockUnlock(gDriverKitLaunchLock);
6379bb611c8fSApple OSS Distributions }
6380bb611c8fSApple OSS Distributions 
63818d741a5dSApple OSS Distributions IOReturn
complete()6382e6231be0SApple OSS Distributions IOUserServerCheckInToken::complete()
6383bb611c8fSApple OSS Distributions {
63848d741a5dSApple OSS Distributions 	IOReturn ret;
6385e7776783SApple OSS Distributions 	IORecursiveLockLock(gDriverKitLaunchLock);
6386e7776783SApple OSS Distributions 
63878d741a5dSApple OSS Distributions 	if (fState == kIOUserServerCheckInCanceled) {
63888d741a5dSApple OSS Distributions 		ret = kIOReturnError;
63898d741a5dSApple OSS Distributions 	} else {
63908d741a5dSApple OSS Distributions 		ret = kIOReturnSuccess;
63918d741a5dSApple OSS Distributions 	}
63928d741a5dSApple OSS Distributions 
6393e7776783SApple OSS Distributions 	if (fState == kIOUserServerCheckInPending && --fPendingCount == 0) {
6394e7776783SApple OSS Distributions 		fState = kIOUserServerCheckInComplete;
6395e7776783SApple OSS Distributions 		if (gDriverKitLaunches != NULL) {
6396e7776783SApple OSS Distributions 			// Remove pending launch from list, if we have not shut down yet.
6397e7776783SApple OSS Distributions 			gDriverKitLaunches->removeObject(this);
6398e7776783SApple OSS Distributions 		}
6399e7776783SApple OSS Distributions 
6400e6231be0SApple OSS Distributions 		// No need to hold on to the cancellation handlers
6401e6231be0SApple OSS Distributions 		fHandlers->flushCollection();
6402e6231be0SApple OSS Distributions 	}
6403e7776783SApple OSS Distributions 
6404e7776783SApple OSS Distributions 	IORecursiveLockUnlock(gDriverKitLaunchLock);
64058d741a5dSApple OSS Distributions 	return ret;
6406bb611c8fSApple OSS Distributions }
6407bb611c8fSApple OSS Distributions 
6408e6231be0SApple OSS Distributions bool
init(const OSSymbol * serverName,OSNumber * serverTag,OSKext * driverKext,OSData * serverDUI)64095c2921b0SApple OSS Distributions IOUserServerCheckInToken::init(const OSSymbol * serverName, OSNumber * serverTag, OSKext *driverKext, OSData *serverDUI)
6410bb611c8fSApple OSS Distributions {
6411e6231be0SApple OSS Distributions 	if (!OSObject::init()) {
6412e6231be0SApple OSS Distributions 		return false;
6413bb611c8fSApple OSS Distributions 	}
6414e6231be0SApple OSS Distributions 
6415e6231be0SApple OSS Distributions 	if (!serverName) {
6416e6231be0SApple OSS Distributions 		return false;
6417e6231be0SApple OSS Distributions 	}
6418e6231be0SApple OSS Distributions 	fServerName = serverName;
6419e6231be0SApple OSS Distributions 	fServerName->retain();
6420e6231be0SApple OSS Distributions 
6421e6231be0SApple OSS Distributions 	if (!serverTag) {
6422e6231be0SApple OSS Distributions 		return false;
6423e6231be0SApple OSS Distributions 	}
6424e6231be0SApple OSS Distributions 	fServerTag = serverTag;
6425e6231be0SApple OSS Distributions 	fServerTag->retain();
6426e6231be0SApple OSS Distributions 
6427e6231be0SApple OSS Distributions 	fHandlers = OSSet::withCapacity(0);
6428e6231be0SApple OSS Distributions 	if (!fHandlers) {
6429e6231be0SApple OSS Distributions 		return false;
6430e6231be0SApple OSS Distributions 	}
6431e6231be0SApple OSS Distributions 
6432e6231be0SApple OSS Distributions 	fState = kIOUserServerCheckInPending;
6433e7776783SApple OSS Distributions 	fPendingCount = 1;
6434e6231be0SApple OSS Distributions 
64355c2921b0SApple OSS Distributions 	fKextBundleID = NULL;
64365c2921b0SApple OSS Distributions 	fNeedDextDec = false;
64375c2921b0SApple OSS Distributions 
6438aca3beaaSApple OSS Distributions 	fExecutableName = NULL;
6439aca3beaaSApple OSS Distributions 
64405c2921b0SApple OSS Distributions 	if (driverKext) {
6441aca3beaaSApple OSS Distributions 		fExecutableName = OSDynamicCast(OSSymbol, driverKext->getBundleExecutable());
6442aca3beaaSApple OSS Distributions 
6443aca3beaaSApple OSS Distributions 		if (fExecutableName) {
6444aca3beaaSApple OSS Distributions 			fExecutableName->retain();
6445aca3beaaSApple OSS Distributions 		}
6446aca3beaaSApple OSS Distributions 
64475c2921b0SApple OSS Distributions 		/*
64485c2921b0SApple OSS Distributions 		 * We need to keep track of how many dexts we have started.
64495c2921b0SApple OSS Distributions 		 * For every new dext we are going to create a new token, and
64505c2921b0SApple OSS Distributions 		 * we consider the token creation as the initial step to
64515c2921b0SApple OSS Distributions 		 * create a dext as it is the data structure that will back up
64525c2921b0SApple OSS Distributions 		 * the userspace dance to start a dext.
64535c2921b0SApple OSS Distributions 		 * We later have to decrement only once per token.
64545c2921b0SApple OSS Distributions 		 * If no error occurs we consider the finalize() call on IOUserServer
64555c2921b0SApple OSS Distributions 		 * as the moment in which we do not consider the dext "alive" anymore;
64565c2921b0SApple OSS Distributions 		 * however in case of errors we will still need to decrement the count
64575c2921b0SApple OSS Distributions 		 * otherwise upgrades of the dext will never make progress.
64585c2921b0SApple OSS Distributions 		 */
64595c2921b0SApple OSS Distributions 		if (OSKext::incrementDextLaunchCount(driverKext, serverDUI)) {
64605c2921b0SApple OSS Distributions 			/*
64615c2921b0SApple OSS Distributions 			 * If fKext holds a pointer,
64625c2921b0SApple OSS Distributions 			 * it is the indication that a decrements needs
64635c2921b0SApple OSS Distributions 			 * to be called.
64645c2921b0SApple OSS Distributions 			 */
64655c2921b0SApple OSS Distributions 			fNeedDextDec = true;
64665c2921b0SApple OSS Distributions 			fKextBundleID = OSDynamicCast(OSString, driverKext->getIdentifier());
64675c2921b0SApple OSS Distributions 			fKextBundleID->retain();
64685c2921b0SApple OSS Distributions 		} else {
64695c2921b0SApple OSS Distributions 			return false;
64705c2921b0SApple OSS Distributions 		}
64715c2921b0SApple OSS Distributions 	}
64725c2921b0SApple OSS Distributions 
6473e6231be0SApple OSS Distributions 	return true;
6474e6231be0SApple OSS Distributions }
6475e6231be0SApple OSS Distributions 
64765c2921b0SApple OSS Distributions /*
64775c2921b0SApple OSS Distributions  * Returns if the dext can be re-used
64785c2921b0SApple OSS Distributions  * for matching.
64795c2921b0SApple OSS Distributions  */
64805c2921b0SApple OSS Distributions bool
dextTerminate(void)64815c2921b0SApple OSS Distributions IOUserServerCheckInToken::dextTerminate(void)
64825c2921b0SApple OSS Distributions {
64835c2921b0SApple OSS Distributions 	bool ret = true;
64845c2921b0SApple OSS Distributions 
64855c2921b0SApple OSS Distributions 	if (fNeedDextDec == true) {
64865c2921b0SApple OSS Distributions 		/*
64875c2921b0SApple OSS Distributions 		 * We can decrement DextLaunchCount only
64885c2921b0SApple OSS Distributions 		 * once per token.
64895c2921b0SApple OSS Distributions 		 */
64905c2921b0SApple OSS Distributions 		ret = !(OSKext::decrementDextLaunchCount(fKextBundleID));
64915c2921b0SApple OSS Distributions 		fNeedDextDec = false;
64925c2921b0SApple OSS Distributions 	}
64935c2921b0SApple OSS Distributions 
64945c2921b0SApple OSS Distributions 	return ret;
64955c2921b0SApple OSS Distributions }
64965c2921b0SApple OSS Distributions 
6497e6231be0SApple OSS Distributions void
free()6498e6231be0SApple OSS Distributions IOUserServerCheckInToken::free()
6499e6231be0SApple OSS Distributions {
6500e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(fServerName);
6501e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(fServerTag);
6502aca3beaaSApple OSS Distributions 	OSSafeReleaseNULL(fExecutableName);
6503e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(fHandlers);
65045c2921b0SApple OSS Distributions 	if (fKextBundleID != NULL) {
65055c2921b0SApple OSS Distributions 		dextTerminate();
65065c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(fKextBundleID);
65075c2921b0SApple OSS Distributions 	}
6508e6231be0SApple OSS Distributions 
6509e6231be0SApple OSS Distributions 	OSObject::free();
6510e6231be0SApple OSS Distributions }
6511e6231be0SApple OSS Distributions 
6512e6231be0SApple OSS Distributions const OSSymbol *
copyServerName() const6513e6231be0SApple OSS Distributions IOUserServerCheckInToken::copyServerName() const
6514e6231be0SApple OSS Distributions {
6515e6231be0SApple OSS Distributions 	fServerName->retain();
6516e6231be0SApple OSS Distributions 	return fServerName;
6517e6231be0SApple OSS Distributions }
6518e6231be0SApple OSS Distributions 
6519e6231be0SApple OSS Distributions OSNumber *
copyServerTag() const6520e6231be0SApple OSS Distributions IOUserServerCheckInToken::copyServerTag() const
6521e6231be0SApple OSS Distributions {
6522e6231be0SApple OSS Distributions 	fServerTag->retain();
6523e6231be0SApple OSS Distributions 	return fServerTag;
6524e6231be0SApple OSS Distributions }
6525e6231be0SApple OSS Distributions 
6526e6231be0SApple OSS Distributions IOUserServer *
launchUserServer(OSString * bundleID,const OSSymbol * serverName,OSNumber * serverTag,bool reuseIfExists,IOUserServerCheckInToken ** resultToken,OSData * serverDUI)65275c2921b0SApple OSS Distributions IOUserServer::launchUserServer(OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, IOUserServerCheckInToken ** resultToken, OSData *serverDUI)
6528e6231be0SApple OSS Distributions {
6529e6231be0SApple OSS Distributions 	IOUserServer *me = NULL;
6530e6231be0SApple OSS Distributions 	IOUserServerCheckInToken * token = NULL;
6531e6231be0SApple OSS Distributions 	OSDictionary * matching = NULL;  // must release
65325c2921b0SApple OSS Distributions 	OSKext * driverKext = NULL; // must release
65335c2921b0SApple OSS Distributions 	OSDextStatistics * driverStatistics = NULL; // must release
65345c2921b0SApple OSS Distributions 	bool reslide = false;
65355c2921b0SApple OSS Distributions 
65365c2921b0SApple OSS Distributions 	/* TODO: Check we are looking for same dextID
65375c2921b0SApple OSS Distributions 	 * and if it is not the same
65385c2921b0SApple OSS Distributions 	 * restart the matching process.
65395c2921b0SApple OSS Distributions 	 */
65405c2921b0SApple OSS Distributions 	driverKext = OSKext::lookupDextWithIdentifier(bundleID, serverDUI);
65415c2921b0SApple OSS Distributions 	if (driverKext != NULL) {
65425c2921b0SApple OSS Distributions 		driverStatistics = driverKext->copyDextStatistics();
65435c2921b0SApple OSS Distributions 		if (driverStatistics == NULL) {
65445c2921b0SApple OSS Distributions 			panic("Kext %s was not a DriverKit OSKext", bundleID->getCStringNoCopy());
65455c2921b0SApple OSS Distributions 		}
65465c2921b0SApple OSS Distributions 		IOLog("Driver %s has crashed %zu time(s)\n", bundleID->getCStringNoCopy(), driverStatistics->getCrashCount());
65475c2921b0SApple OSS Distributions 		reslide = driverStatistics->getCrashCount() > 0;
65485c2921b0SApple OSS Distributions 	} else {
65495c2921b0SApple OSS Distributions 		DKLOG("Could not find OSKext for %s\n", bundleID->getCStringNoCopy());
65505c2921b0SApple OSS Distributions 		*resultToken = NULL;
65515c2921b0SApple OSS Distributions 		return NULL;
65525c2921b0SApple OSS Distributions 	}
6553e6231be0SApple OSS Distributions 
6554e6231be0SApple OSS Distributions 	IORecursiveLockLock(gDriverKitLaunchLock);
6555e6231be0SApple OSS Distributions 
6556e6231be0SApple OSS Distributions 	if (gDriverKitLaunches == NULL) {
6557e6231be0SApple OSS Distributions 		// About to shut down, don't launch anything
6558e6231be0SApple OSS Distributions 		goto finish;
6559e6231be0SApple OSS Distributions 	}
6560e6231be0SApple OSS Distributions 
6561e6231be0SApple OSS Distributions 	if (reuseIfExists) {
6562e6231be0SApple OSS Distributions 		const char * serverNameCStr;
6563e6231be0SApple OSS Distributions 		const char * bundleIDCStr;
6564e6231be0SApple OSS Distributions 		const char * endOrgCStr;
6565e6231be0SApple OSS Distributions 
6566e6231be0SApple OSS Distributions 		serverNameCStr = serverName->getCStringNoCopy();
6567e6231be0SApple OSS Distributions 		bundleIDCStr = bundleID->getCStringNoCopy();
6568e6231be0SApple OSS Distributions 		(endOrgCStr = strchr(bundleIDCStr, '.')) && (endOrgCStr = strchr(endOrgCStr + 1, '.'));
6569e6231be0SApple OSS Distributions 		reuseIfExists = endOrgCStr && (0 == strncmp(bundleIDCStr, serverNameCStr, endOrgCStr + 1 - bundleIDCStr));
6570e6231be0SApple OSS Distributions 		if (!reuseIfExists) {
6571e6231be0SApple OSS Distributions 			IOLog(kIOUserServerNameKey " \"%s\" not correct organization for bundleID \"%s\"\n", serverNameCStr, bundleIDCStr);
6572e6231be0SApple OSS Distributions 		}
6573e6231be0SApple OSS Distributions 	}
6574e6231be0SApple OSS Distributions 
6575e6231be0SApple OSS Distributions 	// Find existing server
6576e6231be0SApple OSS Distributions 	if (reuseIfExists) {
6577e6231be0SApple OSS Distributions 		token = IOUserServerCheckInToken::findExistingToken(serverName);
6578e6231be0SApple OSS Distributions 		if (token) {
6579e6231be0SApple OSS Distributions 			// Launch in progress, return token
6580e6231be0SApple OSS Distributions 			goto finish;
6581e6231be0SApple OSS Distributions 		} else {
6582e6231be0SApple OSS Distributions 			// Check if launch completed
6583e6231be0SApple OSS Distributions 			matching = IOService::serviceMatching(gIOUserServerClassKey);
6584e6231be0SApple OSS Distributions 			if (!matching) {
6585e6231be0SApple OSS Distributions 				goto finish;
6586e6231be0SApple OSS Distributions 			}
6587e6231be0SApple OSS Distributions 			IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
6588e6231be0SApple OSS Distributions 			IOService * service = IOService::copyMatchingService(matching);
6589e6231be0SApple OSS Distributions 			IOUserServer * userServer = OSDynamicCast(IOUserServer, service);
6590e6231be0SApple OSS Distributions 			if (userServer) {
6591e6231be0SApple OSS Distributions 				// found existing user server
6592e6231be0SApple OSS Distributions 				me = userServer;
6593e6231be0SApple OSS Distributions 				goto finish;
6594e6231be0SApple OSS Distributions 			} else {
6595e6231be0SApple OSS Distributions 				OSSafeReleaseNULL(service);
6596e6231be0SApple OSS Distributions 			}
6597e6231be0SApple OSS Distributions 		}
6598e6231be0SApple OSS Distributions 	}
6599e6231be0SApple OSS Distributions 
6600e6231be0SApple OSS Distributions 	// No existing server, request launch
6601e6231be0SApple OSS Distributions 	token = new IOUserServerCheckInToken;
6602e6231be0SApple OSS Distributions 	if (!token) {
6603e6231be0SApple OSS Distributions 		goto finish;
6604e6231be0SApple OSS Distributions 	}
66055c2921b0SApple OSS Distributions 
66065c2921b0SApple OSS Distributions 	/*
66075c2921b0SApple OSS Distributions 	 * TODO: If the init fails because the personalities are not up to date
66085c2921b0SApple OSS Distributions 	 * restart the whole matching process.
66095c2921b0SApple OSS Distributions 	 */
66105c2921b0SApple OSS Distributions 	if (token && !token->init(serverName, serverTag, driverKext, serverDUI)) {
66115c2921b0SApple OSS Distributions 		IOLog("Could not initialize token\n");
6612e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(token);
6613e6231be0SApple OSS Distributions 		goto finish;
6614e6231be0SApple OSS Distributions 	}
6615e6231be0SApple OSS Distributions 
66165c2921b0SApple OSS Distributions 	/*
66175c2921b0SApple OSS Distributions 	 * If the launch fails at any point terminate() will
66185c2921b0SApple OSS Distributions 	 * be called on this IOUserServer.
66195c2921b0SApple OSS Distributions 	 */
6620e6231be0SApple OSS Distributions 	gDriverKitLaunches->setObject(token);
66215c2921b0SApple OSS Distributions 	OSKext::requestDaemonLaunch(bundleID, (OSString *)serverName, serverTag, reslide ? kOSBooleanTrue : kOSBooleanFalse, token, serverDUI);
6622e6231be0SApple OSS Distributions 
6623e6231be0SApple OSS Distributions finish:
6624e6231be0SApple OSS Distributions 	IORecursiveLockUnlock(gDriverKitLaunchLock);
6625e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(matching);
66265c2921b0SApple OSS Distributions 	OSSafeReleaseNULL(driverStatistics);
66275c2921b0SApple OSS Distributions 	OSSafeReleaseNULL(driverKext);
6628e6231be0SApple OSS Distributions 
6629e6231be0SApple OSS Distributions 	if (resultToken) {
6630e6231be0SApple OSS Distributions 		*resultToken = token;
6631e6231be0SApple OSS Distributions 	} else {
6632e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(token);
6633e6231be0SApple OSS Distributions 	}
6634e6231be0SApple OSS Distributions 
6635bb611c8fSApple OSS Distributions 	return me;
6636bb611c8fSApple OSS Distributions }
6637bb611c8fSApple OSS Distributions 
6638e7776783SApple OSS Distributions /*
6639e7776783SApple OSS Distributions  * IOUserServerCheckInTokens are used to track dext launches. They have three possible states:
6640e7776783SApple OSS Distributions  *
6641e7776783SApple OSS Distributions  * - Pending: A dext launch is pending
6642e7776783SApple OSS Distributions  * - Canceled: Dext launch failed
6643e7776783SApple OSS Distributions  * - Complete: Dext launch is complete
6644e7776783SApple OSS Distributions  *
6645e7776783SApple OSS Distributions  * A token can be shared among multiple IOServices that are waiting for dexts if the IOUserServerName
6646e7776783SApple OSS Distributions  * is the same. This allows dexts to be reused and host multiple services. All pending tokens are stored
6647e7776783SApple OSS Distributions  * in gDriverKitLaunches and we check here before creating a new token when launching a dext.
6648e7776783SApple OSS Distributions  *
6649e7776783SApple OSS Distributions  * A token starts in the pending state with a pending count of 1. When we reuse a token, we increase the
6650e7776783SApple OSS Distributions  * pending count of the token.
6651e7776783SApple OSS Distributions  *
6652e7776783SApple OSS Distributions  * The token is sent to userspace as a mach port through kernelmanagerd/driverkitd to the dext. The dext then
6653e7776783SApple OSS Distributions  * uses that token to check in to the kernel. If any part of the dext launch failed (dext crashed, kmd crashed, etc.)
6654e7776783SApple OSS Distributions  * we get a no-senders notification for the token in the kernel and the token goes into the Canceled state.
6655e7776783SApple OSS Distributions  *
6656e7776783SApple OSS Distributions  * Once the dext checks in to the kernel, we decrement the pending count for the token. When the pending count reaches
6657e7776783SApple OSS Distributions  * 0, the token goes into the Complete state. So if the token is in the Complete state, there are no kernel matching threads
6658e7776783SApple OSS Distributions  * waiting on the dext to check in.
6659e7776783SApple OSS Distributions  */
6660e7776783SApple OSS Distributions 
6661e6231be0SApple OSS Distributions IOUserServerCheckInToken *
findExistingToken(const OSSymbol * serverName)6662e6231be0SApple OSS Distributions IOUserServerCheckInToken::findExistingToken(const OSSymbol * serverName)
6663e6231be0SApple OSS Distributions {
6664e6231be0SApple OSS Distributions 	IOUserServerCheckInToken * __block result = NULL;
6665e6231be0SApple OSS Distributions 
6666e6231be0SApple OSS Distributions 	IORecursiveLockLock(gDriverKitLaunchLock);
6667e6231be0SApple OSS Distributions 	if (gDriverKitLaunches == NULL) {
6668e6231be0SApple OSS Distributions 		goto finish;
6669e6231be0SApple OSS Distributions 	}
6670e6231be0SApple OSS Distributions 
6671e6231be0SApple OSS Distributions 	gDriverKitLaunches->iterateObjects(^(OSObject * obj) {
6672e6231be0SApple OSS Distributions 		IOUserServerCheckInToken * token = OSDynamicCast(IOUserServerCheckInToken, obj);
6673e6231be0SApple OSS Distributions 		if (token) {
6674e6231be0SApple OSS Distributions 		        // Check if server name matches
6675e6231be0SApple OSS Distributions 		        const OSSymbol * tokenServerName = token->fServerName;
6676e6231be0SApple OSS Distributions 		        if (tokenServerName->isEqualTo(serverName)) {
6677e7776783SApple OSS Distributions 		                assert(token->fState == kIOUserServerCheckInPending);
6678e7776783SApple OSS Distributions 		                token->fPendingCount++;
6679e6231be0SApple OSS Distributions 		                result = token;
6680e6231be0SApple OSS Distributions 		                result->retain();
6681e6231be0SApple OSS Distributions 			}
6682e6231be0SApple OSS Distributions 		}
6683e6231be0SApple OSS Distributions 		return result != NULL;
6684e6231be0SApple OSS Distributions 	});
6685e6231be0SApple OSS Distributions 
6686e6231be0SApple OSS Distributions finish:
6687e6231be0SApple OSS Distributions 	IORecursiveLockUnlock(gDriverKitLaunchLock);
6688e6231be0SApple OSS Distributions 	return result;
6689e6231be0SApple OSS Distributions }
6690e6231be0SApple OSS Distributions 
6691e6231be0SApple OSS Distributions void
cancelAll()6692e6231be0SApple OSS Distributions IOUserServerCheckInToken::cancelAll()
6693e6231be0SApple OSS Distributions {
6694e6231be0SApple OSS Distributions 	OSSet * tokensToCancel;
6695e6231be0SApple OSS Distributions 
6696e6231be0SApple OSS Distributions 	IORecursiveLockLock(gDriverKitLaunchLock);
6697e6231be0SApple OSS Distributions 	tokensToCancel = gDriverKitLaunches;
6698e6231be0SApple OSS Distributions 	gDriverKitLaunches = NULL;
6699e7776783SApple OSS Distributions 
6700e6231be0SApple OSS Distributions 
6701e6231be0SApple OSS Distributions 	tokensToCancel->iterateObjects(^(OSObject *obj) {
6702e6231be0SApple OSS Distributions 		IOUserServerCheckInToken * token = OSDynamicCast(IOUserServerCheckInToken, obj);
6703e6231be0SApple OSS Distributions 		if (token) {
6704e6231be0SApple OSS Distributions 		        token->cancel();
6705e6231be0SApple OSS Distributions 		}
6706e6231be0SApple OSS Distributions 		return false;
6707e6231be0SApple OSS Distributions 	});
6708e6231be0SApple OSS Distributions 
6709e7776783SApple OSS Distributions 	IORecursiveLockUnlock(gDriverKitLaunchLock);
6710e7776783SApple OSS Distributions 
6711e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(tokensToCancel);
6712e6231be0SApple OSS Distributions }
6713e6231be0SApple OSS Distributions 
6714e6231be0SApple OSS Distributions void
call(IOUserServerCheckInToken * token)6715e6231be0SApple OSS Distributions _IOUserServerCheckInCancellationHandler::call(IOUserServerCheckInToken * token)
6716e6231be0SApple OSS Distributions {
6717e6231be0SApple OSS Distributions 	fHandler(token, fHandlerArgs);
6718e6231be0SApple OSS Distributions }
6719e6231be0SApple OSS Distributions 
6720e6231be0SApple OSS Distributions _IOUserServerCheckInCancellationHandler *
withHandler(IOUserServerCheckInCancellationHandler handler,void * args)6721e6231be0SApple OSS Distributions _IOUserServerCheckInCancellationHandler::withHandler(IOUserServerCheckInCancellationHandler handler, void * args)
6722e6231be0SApple OSS Distributions {
6723e6231be0SApple OSS Distributions 	_IOUserServerCheckInCancellationHandler * handlerObj = NULL;
6724e6231be0SApple OSS Distributions 	if (!handler) {
6725e6231be0SApple OSS Distributions 		goto finish;
6726e6231be0SApple OSS Distributions 	}
6727e6231be0SApple OSS Distributions 
6728e6231be0SApple OSS Distributions 	handlerObj = new _IOUserServerCheckInCancellationHandler;
6729e6231be0SApple OSS Distributions 	if (!handlerObj) {
6730e6231be0SApple OSS Distributions 		goto finish;
6731e6231be0SApple OSS Distributions 	}
6732e6231be0SApple OSS Distributions 
6733e6231be0SApple OSS Distributions 	handlerObj->fHandler = handler;
6734e6231be0SApple OSS Distributions 	handlerObj->fHandlerArgs = args;
6735e6231be0SApple OSS Distributions 
6736e6231be0SApple OSS Distributions finish:
6737e6231be0SApple OSS Distributions 	return handlerObj;
6738e6231be0SApple OSS Distributions }
6739e6231be0SApple OSS Distributions 
6740bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6741e6231be0SApple OSS Distributions 
6742e6231be0SApple OSS Distributions struct IOServiceStateNotificationDispatchSource_IVars {
6743e6231be0SApple OSS Distributions 	IOLock                       * fLock;
6744e6231be0SApple OSS Distributions 	IOService                    * fStateNotification;
6745e6231be0SApple OSS Distributions 	IOStateNotificationListenerRef fListener;
6746e6231be0SApple OSS Distributions 	OSAction                     * fAction;
6747e6231be0SApple OSS Distributions 	bool                           fEnable;
6748e6231be0SApple OSS Distributions 	bool                           fArmed;
6749e6231be0SApple OSS Distributions };
6750e6231be0SApple OSS Distributions 
6751e6231be0SApple OSS Distributions kern_return_t
Create_Impl(IOService * service,OSArray * items,IODispatchQueue * queue,IOServiceStateNotificationDispatchSource ** outSource)6752e6231be0SApple OSS Distributions IOServiceStateNotificationDispatchSource::Create_Impl(IOService * service, OSArray * items,
6753e6231be0SApple OSS Distributions     IODispatchQueue * queue, IOServiceStateNotificationDispatchSource ** outSource)
6754e6231be0SApple OSS Distributions {
6755e6231be0SApple OSS Distributions 	kern_return_t kr;
6756e6231be0SApple OSS Distributions 	IOServiceStateNotificationDispatchSource * source;
6757e6231be0SApple OSS Distributions 
6758e6231be0SApple OSS Distributions 	source = OSTypeAlloc(IOServiceStateNotificationDispatchSource);
6759e6231be0SApple OSS Distributions 	source->init();
6760e6231be0SApple OSS Distributions 
6761e6231be0SApple OSS Distributions 	source->ivars->fStateNotification = service;
6762e6231be0SApple OSS Distributions 	kr = service->stateNotificationListenerAdd(items, &source->ivars->fListener, ^kern_return_t () {
6763e6231be0SApple OSS Distributions 		OSAction * action;
6764e6231be0SApple OSS Distributions 
6765e6231be0SApple OSS Distributions 		action = NULL;
6766e6231be0SApple OSS Distributions 		IOLockLock(source->ivars->fLock);
6767e6231be0SApple OSS Distributions 		if (source->ivars->fArmed && source->ivars->fAction) {
6768e6231be0SApple OSS Distributions 		        source->ivars->fArmed = false;
6769e6231be0SApple OSS Distributions 		        action = source->ivars->fAction;
6770e6231be0SApple OSS Distributions 		        action->retain();
6771e6231be0SApple OSS Distributions 		}
6772e6231be0SApple OSS Distributions 		IOLockUnlock(source->ivars->fLock);
6773e6231be0SApple OSS Distributions 		if (action) {
6774e6231be0SApple OSS Distributions 		        source->StateNotificationReady(action);
6775e6231be0SApple OSS Distributions 		        OSSafeReleaseNULL(action);
6776e6231be0SApple OSS Distributions 		}
6777e6231be0SApple OSS Distributions 		return kIOReturnSuccess;
6778e6231be0SApple OSS Distributions 	});
6779e6231be0SApple OSS Distributions 
6780e6231be0SApple OSS Distributions 	if (kIOReturnSuccess != kr) {
6781e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(source);
6782e6231be0SApple OSS Distributions 	}
6783e6231be0SApple OSS Distributions 	*outSource = source;
6784e6231be0SApple OSS Distributions 
6785e6231be0SApple OSS Distributions 	return kr;
6786e6231be0SApple OSS Distributions }
6787e6231be0SApple OSS Distributions 
6788e6231be0SApple OSS Distributions 
6789e6231be0SApple OSS Distributions bool
init()6790e6231be0SApple OSS Distributions IOServiceStateNotificationDispatchSource::init()
6791e6231be0SApple OSS Distributions {
6792e6231be0SApple OSS Distributions 	if (!IODispatchSource::init()) {
6793e6231be0SApple OSS Distributions 		return false;
6794e6231be0SApple OSS Distributions 	}
6795e6231be0SApple OSS Distributions 	ivars = IOMallocType(IOServiceStateNotificationDispatchSource_IVars);
6796e6231be0SApple OSS Distributions 	if (!ivars) {
6797e6231be0SApple OSS Distributions 		return false;
6798e6231be0SApple OSS Distributions 	}
6799e6231be0SApple OSS Distributions 	ivars->fLock = IOLockAlloc();
6800e6231be0SApple OSS Distributions 	if (!ivars->fLock) {
6801e6231be0SApple OSS Distributions 		return false;
6802e6231be0SApple OSS Distributions 	}
6803e6231be0SApple OSS Distributions 	ivars->fArmed = true;
6804e6231be0SApple OSS Distributions 
6805e6231be0SApple OSS Distributions 	return true;
6806e6231be0SApple OSS Distributions }
6807e6231be0SApple OSS Distributions 
6808e6231be0SApple OSS Distributions void
free()6809e6231be0SApple OSS Distributions IOServiceStateNotificationDispatchSource::free()
6810e6231be0SApple OSS Distributions {
6811e6231be0SApple OSS Distributions 	if (ivars) {
6812e6231be0SApple OSS Distributions 		if (ivars->fListener) {
6813e6231be0SApple OSS Distributions 			ivars->fStateNotification->stateNotificationListenerRemove(ivars->fListener);
6814e6231be0SApple OSS Distributions 		}
6815e6231be0SApple OSS Distributions 		if (ivars->fLock) {
6816e6231be0SApple OSS Distributions 			IOLockFree(ivars->fLock);
6817e6231be0SApple OSS Distributions 		}
6818e6231be0SApple OSS Distributions 		IOFreeType(ivars, IOServiceStateNotificationDispatchSource_IVars);
6819e6231be0SApple OSS Distributions 	}
6820e6231be0SApple OSS Distributions 	IODispatchSource::free();
6821e6231be0SApple OSS Distributions }
6822e6231be0SApple OSS Distributions 
6823e6231be0SApple OSS Distributions kern_return_t
SetHandler_Impl(OSAction * action)6824e6231be0SApple OSS Distributions IOServiceStateNotificationDispatchSource::SetHandler_Impl(OSAction * action)
6825e6231be0SApple OSS Distributions {
6826e6231be0SApple OSS Distributions 	IOReturn ret;
6827e6231be0SApple OSS Distributions 	bool     notifyReady;
6828e6231be0SApple OSS Distributions 
6829e6231be0SApple OSS Distributions 	notifyReady = false;
6830e6231be0SApple OSS Distributions 
6831e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
6832e6231be0SApple OSS Distributions 	action->retain();
6833e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(ivars->fAction);
6834e6231be0SApple OSS Distributions 	ivars->fAction = action;
6835e6231be0SApple OSS Distributions 	if (action) {
6836e6231be0SApple OSS Distributions 		notifyReady = true;
6837e6231be0SApple OSS Distributions 	}
6838e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
6839e6231be0SApple OSS Distributions 
6840e6231be0SApple OSS Distributions 	if (notifyReady) {
6841e6231be0SApple OSS Distributions 		StateNotificationReady(action);
6842e6231be0SApple OSS Distributions 	}
6843e6231be0SApple OSS Distributions 	ret = kIOReturnSuccess;
6844e6231be0SApple OSS Distributions 
6845e6231be0SApple OSS Distributions 	return ret;
6846e6231be0SApple OSS Distributions }
6847e6231be0SApple OSS Distributions 
6848e6231be0SApple OSS Distributions kern_return_t
SetEnableWithCompletion_Impl(bool enable,IODispatchSourceCancelHandler handler)6849e6231be0SApple OSS Distributions IOServiceStateNotificationDispatchSource::SetEnableWithCompletion_Impl(
6850e6231be0SApple OSS Distributions 	bool enable,
6851e6231be0SApple OSS Distributions 	IODispatchSourceCancelHandler handler)
6852e6231be0SApple OSS Distributions {
6853e6231be0SApple OSS Distributions 	if (enable == ivars->fEnable) {
6854e6231be0SApple OSS Distributions 		return kIOReturnSuccess;
6855e6231be0SApple OSS Distributions 	}
6856e6231be0SApple OSS Distributions 
6857e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
6858e6231be0SApple OSS Distributions 	ivars->fEnable = enable;
6859e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
6860e6231be0SApple OSS Distributions 
6861e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
6862e6231be0SApple OSS Distributions }
6863e6231be0SApple OSS Distributions 
6864e6231be0SApple OSS Distributions kern_return_t
Cancel_Impl(IODispatchSourceCancelHandler handler)6865e6231be0SApple OSS Distributions IOServiceStateNotificationDispatchSource::Cancel_Impl(
6866e6231be0SApple OSS Distributions 	IODispatchSourceCancelHandler handler)
6867e6231be0SApple OSS Distributions {
6868e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
6869e6231be0SApple OSS Distributions }
6870e6231be0SApple OSS Distributions 
6871e6231be0SApple OSS Distributions kern_return_t
StateNotificationBegin_Impl(void)6872e6231be0SApple OSS Distributions IOServiceStateNotificationDispatchSource::StateNotificationBegin_Impl(void)
6873e6231be0SApple OSS Distributions {
6874e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
6875e6231be0SApple OSS Distributions 	ivars->fArmed = true;
6876e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
6877e6231be0SApple OSS Distributions 
6878e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
6879e6231be0SApple OSS Distributions }
6880e6231be0SApple OSS Distributions 
6881e6231be0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6882e6231be0SApple OSS Distributions 
6883e6231be0SApple OSS Distributions #include <IOKit/IOServiceStateNotificationEventSource.h>
6884e6231be0SApple OSS Distributions 
6885e6231be0SApple OSS Distributions OSDefineMetaClassAndStructors(IOServiceStateNotificationEventSource, IOEventSource)
6886e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 0);
6887e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 1);
6888e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 2);
6889e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 3);
6890e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 4);
6891e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 5);
6892e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 6);
6893e6231be0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 7);
6894e6231be0SApple OSS Distributions 
6895e6231be0SApple OSS Distributions OSPtr<IOServiceStateNotificationEventSource>
serviceStateNotificationEventSource(IOService * service,OSArray * items,ActionBlock inAction)6896e6231be0SApple OSS Distributions IOServiceStateNotificationEventSource::serviceStateNotificationEventSource(IOService *service,
6897e6231be0SApple OSS Distributions     OSArray * items,
6898e6231be0SApple OSS Distributions     ActionBlock inAction)
6899e6231be0SApple OSS Distributions {
6900e6231be0SApple OSS Distributions 	kern_return_t kr;
6901e6231be0SApple OSS Distributions 	IOServiceStateNotificationEventSource * source;
6902e6231be0SApple OSS Distributions 
6903e6231be0SApple OSS Distributions 	source = OSTypeAlloc(IOServiceStateNotificationEventSource);
6904e6231be0SApple OSS Distributions 	if (source && !source->init(service, NULL)) {
6905e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(source);
6906e6231be0SApple OSS Distributions 	}
6907e6231be0SApple OSS Distributions 
6908e6231be0SApple OSS Distributions 	if (!source) {
6909e6231be0SApple OSS Distributions 		return nullptr;
6910e6231be0SApple OSS Distributions 	}
6911e6231be0SApple OSS Distributions 
6912e6231be0SApple OSS Distributions 	source->fStateNotification = service;
6913e6231be0SApple OSS Distributions 	kr = service->stateNotificationListenerAdd(items, &source->fListener, ^kern_return_t () {
6914e6231be0SApple OSS Distributions 		if (!source->workLoop) {
6915e6231be0SApple OSS Distributions 		        return kIOReturnSuccess;
6916e6231be0SApple OSS Distributions 		}
6917e6231be0SApple OSS Distributions 		source->workLoop->runActionBlock(^IOReturn (void) {
6918e6231be0SApple OSS Distributions 			source->fArmed = true;
6919e6231be0SApple OSS Distributions 			return kIOReturnSuccess;
6920e6231be0SApple OSS Distributions 		});
6921e6231be0SApple OSS Distributions 		source->signalWorkAvailable();
6922e6231be0SApple OSS Distributions 		return kIOReturnSuccess;
6923e6231be0SApple OSS Distributions 	});
6924e6231be0SApple OSS Distributions 
6925e6231be0SApple OSS Distributions 	if (kIOReturnSuccess != kr) {
6926e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(source);
6927e6231be0SApple OSS Distributions 	}
6928e6231be0SApple OSS Distributions 
6929e6231be0SApple OSS Distributions 	if (source) {
6930e6231be0SApple OSS Distributions 		source->setActionBlock((IOEventSource::ActionBlock) inAction);
6931e6231be0SApple OSS Distributions 	}
6932e6231be0SApple OSS Distributions 
6933e6231be0SApple OSS Distributions 	return source;
6934e6231be0SApple OSS Distributions }
6935e6231be0SApple OSS Distributions 
6936e6231be0SApple OSS Distributions void
free()6937e6231be0SApple OSS Distributions IOServiceStateNotificationEventSource::free()
6938e6231be0SApple OSS Distributions {
6939e6231be0SApple OSS Distributions 	if (fListener) {
6940e6231be0SApple OSS Distributions 		fStateNotification->stateNotificationListenerRemove(fListener);
6941e6231be0SApple OSS Distributions 	}
6942e6231be0SApple OSS Distributions 	IOEventSource::free();
6943e6231be0SApple OSS Distributions }
6944e6231be0SApple OSS Distributions 
6945e6231be0SApple OSS Distributions void
enable()6946e6231be0SApple OSS Distributions IOServiceStateNotificationEventSource::enable()
6947e6231be0SApple OSS Distributions {
6948e6231be0SApple OSS Distributions 	fEnable = true;
6949e6231be0SApple OSS Distributions }
6950e6231be0SApple OSS Distributions 
6951e6231be0SApple OSS Distributions void
disable()6952e6231be0SApple OSS Distributions IOServiceStateNotificationEventSource::disable()
6953e6231be0SApple OSS Distributions {
6954e6231be0SApple OSS Distributions 	fEnable = false;
6955e6231be0SApple OSS Distributions }
6956e6231be0SApple OSS Distributions 
6957e6231be0SApple OSS Distributions void
setWorkLoop(IOWorkLoop * inWorkLoop)6958e6231be0SApple OSS Distributions IOServiceStateNotificationEventSource::setWorkLoop(IOWorkLoop *inWorkLoop)
6959e6231be0SApple OSS Distributions {
6960e6231be0SApple OSS Distributions 	IOEventSource::setWorkLoop(inWorkLoop);
6961e6231be0SApple OSS Distributions }
6962e6231be0SApple OSS Distributions 
6963e6231be0SApple OSS Distributions bool
checkForWork()6964e6231be0SApple OSS Distributions IOServiceStateNotificationEventSource::checkForWork()
6965e6231be0SApple OSS Distributions {
6966e6231be0SApple OSS Distributions 	ActionBlock intActionBlock = (ActionBlock) actionBlock;
6967e6231be0SApple OSS Distributions 
6968e6231be0SApple OSS Distributions 	if (fArmed) {
6969e6231be0SApple OSS Distributions 		fArmed = false;
6970e6231be0SApple OSS Distributions 		(intActionBlock)();
6971e6231be0SApple OSS Distributions 	}
6972e6231be0SApple OSS Distributions 
6973e6231be0SApple OSS Distributions 	return false;
6974e6231be0SApple OSS Distributions }
6975e6231be0SApple OSS Distributions 
6976e6231be0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6977e6231be0SApple OSS Distributions 
6978e6231be0SApple OSS Distributions OSDefineMetaClassAndStructors(IOSystemStateNotification, IOService);
6979e6231be0SApple OSS Distributions 
6980e6231be0SApple OSS Distributions class IOStateNotificationItem : public OSObject
6981e6231be0SApple OSS Distributions {
6982e6231be0SApple OSS Distributions 	OSDeclareDefaultStructors(IOStateNotificationItem);
6983e6231be0SApple OSS Distributions 
6984e6231be0SApple OSS Distributions public:
6985e6231be0SApple OSS Distributions 	virtual bool init() override;
6986e6231be0SApple OSS Distributions 
6987e6231be0SApple OSS Distributions 	OSDictionary * fSchema;
6988e6231be0SApple OSS Distributions 	OSDictionary * fValue;
6989e6231be0SApple OSS Distributions 	OSSet        * fListeners;
6990e6231be0SApple OSS Distributions };
6991e6231be0SApple OSS Distributions OSDefineMetaClassAndStructors(IOStateNotificationItem, OSObject);
6992e6231be0SApple OSS Distributions 
6993e6231be0SApple OSS Distributions 
6994e6231be0SApple OSS Distributions class IOStateNotificationListener : public OSObject
6995e6231be0SApple OSS Distributions {
6996e6231be0SApple OSS Distributions 	OSDeclareDefaultStructors(IOStateNotificationListener);
6997e6231be0SApple OSS Distributions 
6998e6231be0SApple OSS Distributions public:
6999e6231be0SApple OSS Distributions 	virtual bool init() override;
7000e6231be0SApple OSS Distributions 	virtual void free() override;
7001e6231be0SApple OSS Distributions 
7002e6231be0SApple OSS Distributions 	IOStateNotificationHandler fHandler;
7003e6231be0SApple OSS Distributions };
7004e6231be0SApple OSS Distributions OSDefineMetaClassAndStructors(IOStateNotificationListener, OSObject);
7005e6231be0SApple OSS Distributions 
7006e6231be0SApple OSS Distributions 
7007e6231be0SApple OSS Distributions bool
init()7008e6231be0SApple OSS Distributions IOStateNotificationItem::init()
7009e6231be0SApple OSS Distributions {
7010e6231be0SApple OSS Distributions 	return OSObject::init();
7011e6231be0SApple OSS Distributions }
7012e6231be0SApple OSS Distributions 
7013e6231be0SApple OSS Distributions bool
init()7014e6231be0SApple OSS Distributions IOStateNotificationListener::init()
7015e6231be0SApple OSS Distributions {
7016e6231be0SApple OSS Distributions 	return OSObject::init();
7017e6231be0SApple OSS Distributions }
7018e6231be0SApple OSS Distributions 
7019e6231be0SApple OSS Distributions void
free()7020e6231be0SApple OSS Distributions IOStateNotificationListener::free()
7021e6231be0SApple OSS Distributions {
7022e6231be0SApple OSS Distributions 	if (fHandler) {
7023e6231be0SApple OSS Distributions 		Block_release(fHandler);
7024e6231be0SApple OSS Distributions 	}
7025e6231be0SApple OSS Distributions 	OSObject::free();
7026e6231be0SApple OSS Distributions }
7027e6231be0SApple OSS Distributions 
7028e6231be0SApple OSS Distributions 
7029e6231be0SApple OSS Distributions struct IOServiceStateChangeVars {
7030e6231be0SApple OSS Distributions 	IOLock       * fLock;
7031e6231be0SApple OSS Distributions 	OSDictionary * fItems;
7032e6231be0SApple OSS Distributions };
7033e6231be0SApple OSS Distributions 
7034e6231be0SApple OSS Distributions IOService *
initialize(void)7035e6231be0SApple OSS Distributions IOSystemStateNotification::initialize(void)
7036e6231be0SApple OSS Distributions {
7037e6231be0SApple OSS Distributions 	IOSystemStateNotification * me;
7038e6231be0SApple OSS Distributions 	IOServiceStateChangeVars  * vars;
7039e6231be0SApple OSS Distributions 
7040e6231be0SApple OSS Distributions 	me = OSTypeAlloc(IOSystemStateNotification);
7041e6231be0SApple OSS Distributions 	me->init();
7042e6231be0SApple OSS Distributions 	vars = IOMallocType(IOServiceStateChangeVars);
7043e6231be0SApple OSS Distributions 	me->reserved->svars = vars;
7044e6231be0SApple OSS Distributions 	vars->fLock  = IOLockAlloc();
7045e6231be0SApple OSS Distributions 	vars->fItems = OSDictionary::withCapacity(16);
7046e6231be0SApple OSS Distributions 	{
7047e6231be0SApple OSS Distributions 		kern_return_t ret;
7048e6231be0SApple OSS Distributions 
7049e6231be0SApple OSS Distributions 		gIOSystemStateSleepDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionKey);
7050e6231be0SApple OSS Distributions 		gIOSystemStateSleepDescriptionHibernateStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionHibernateStateKey);
7051e6231be0SApple OSS Distributions 		gIOSystemStateSleepDescriptionReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionReasonKey);
7052e6231be0SApple OSS Distributions 
7053e6231be0SApple OSS Distributions 		ret = me->StateNotificationItemCreate(gIOSystemStateSleepDescriptionKey, NULL);
7054e6231be0SApple OSS Distributions 		assert(kIOReturnSuccess == ret);
7055e6231be0SApple OSS Distributions 
70565c2921b0SApple OSS Distributions 		gIOSystemStateWakeDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionKey);
70575c2921b0SApple OSS Distributions 		gIOSystemStateWakeDescriptionWakeReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionWakeReasonKey);
70588d741a5dSApple OSS Distributions 		gIOSystemStateWakeDescriptionContinuousTimeOffsetKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionContinuousTimeOffsetKey);
70595c2921b0SApple OSS Distributions 
70605c2921b0SApple OSS Distributions 		ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, NULL);
70615c2921b0SApple OSS Distributions 		assert(kIOReturnSuccess == ret);
70625c2921b0SApple OSS Distributions 
7063e6231be0SApple OSS Distributions 		gIOSystemStateHaltDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionKey);
7064e6231be0SApple OSS Distributions 		gIOSystemStateHaltDescriptionHaltStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionHaltStateKey);
7065e6231be0SApple OSS Distributions 
7066e6231be0SApple OSS Distributions 		ret = me->StateNotificationItemCreate(gIOSystemStateHaltDescriptionKey, NULL);
7067e6231be0SApple OSS Distributions 		assert(kIOReturnSuccess == ret);
7068e6231be0SApple OSS Distributions 
7069e6231be0SApple OSS Distributions 		gIOSystemStatePowerSourceDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStatePowerSourceDescriptionKey);
7070e6231be0SApple OSS Distributions 		gIOSystemStatePowerSourceDescriptionACAttachedKey = OSSymbol::withCStringNoCopy(kIOSystemStatePowerSourceDescriptionACAttachedKey);
7071e6231be0SApple OSS Distributions 
7072e6231be0SApple OSS Distributions 		ret = me->StateNotificationItemCreate(gIOSystemStatePowerSourceDescriptionKey, NULL);
7073e6231be0SApple OSS Distributions 		assert(kIOReturnSuccess == ret);
7074e6231be0SApple OSS Distributions 	}
7075e6231be0SApple OSS Distributions 
7076e6231be0SApple OSS Distributions 	return me;
7077e6231be0SApple OSS Distributions }
7078e6231be0SApple OSS Distributions 
7079e6231be0SApple OSS Distributions bool
serializeProperties(OSSerialize * s) const7080e6231be0SApple OSS Distributions IOSystemStateNotification::serializeProperties(OSSerialize * s) const
7081e6231be0SApple OSS Distributions {
7082e6231be0SApple OSS Distributions 	IOServiceStateChangeVars * ivars = reserved->svars;
7083e6231be0SApple OSS Distributions 
7084e6231be0SApple OSS Distributions 	bool ok;
7085e6231be0SApple OSS Distributions 	OSDictionary * result;
7086e6231be0SApple OSS Distributions 
7087e6231be0SApple OSS Distributions 	result = OSDictionary::withCapacity(16);
7088e6231be0SApple OSS Distributions 
7089e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
7090e6231be0SApple OSS Distributions 	ivars->fItems->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
7091e6231be0SApple OSS Distributions 		IOStateNotificationItem * item;
7092e6231be0SApple OSS Distributions 
7093e6231be0SApple OSS Distributions 		item = (typeof(item))object;
7094e6231be0SApple OSS Distributions 		if (!item->fValue) {
7095e6231be0SApple OSS Distributions 		        return false;
7096e6231be0SApple OSS Distributions 		}
7097e6231be0SApple OSS Distributions 		result->setObject(key, item->fValue);
7098e6231be0SApple OSS Distributions 		return false;
7099e6231be0SApple OSS Distributions 	});
7100e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
7101e6231be0SApple OSS Distributions 
7102e6231be0SApple OSS Distributions 	ok = result->serialize(s);
7103e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(result);
7104e6231be0SApple OSS Distributions 
7105e6231be0SApple OSS Distributions 	return ok;
7106e6231be0SApple OSS Distributions }
7107e6231be0SApple OSS Distributions 
7108e6231be0SApple OSS Distributions kern_return_t
setProperties(OSObject * properties)7109e6231be0SApple OSS Distributions IOSystemStateNotification::setProperties(OSObject * properties)
7110e6231be0SApple OSS Distributions {
7111e6231be0SApple OSS Distributions 	kern_return_t  kr;
7112e6231be0SApple OSS Distributions 	OSDictionary * dict;
7113e6231be0SApple OSS Distributions 	OSDictionary * schema;
7114e6231be0SApple OSS Distributions 	OSDictionary * value;
7115e6231be0SApple OSS Distributions 	OSString     * itemName;
7116e6231be0SApple OSS Distributions 
7117e6231be0SApple OSS Distributions 	dict = OSDynamicCast(OSDictionary, properties);
7118e6231be0SApple OSS Distributions 	if (!dict) {
7119e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
7120e6231be0SApple OSS Distributions 	}
7121e6231be0SApple OSS Distributions 
71225c2921b0SApple OSS Distributions 	if (!IOCurrentTaskHasEntitlement(kIOSystemStateEntitlement)) {
71235c2921b0SApple OSS Distributions 		return kIOReturnNotPermitted;
71245c2921b0SApple OSS Distributions 	}
71255c2921b0SApple OSS Distributions 
7126e6231be0SApple OSS Distributions 	if ((schema = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemCreateKey)))) {
7127e6231be0SApple OSS Distributions 		itemName = OSDynamicCast(OSString, schema->getObject(kIOStateNotificationNameKey));
7128e6231be0SApple OSS Distributions 		kr = StateNotificationItemCreate(itemName, schema);
7129e6231be0SApple OSS Distributions 	} else if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemSetKey)))) {
7130e6231be0SApple OSS Distributions 		itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey));
7131e6231be0SApple OSS Distributions 		itemName->retain();
7132e6231be0SApple OSS Distributions 		value->removeObject(kIOStateNotificationNameKey);
7133e6231be0SApple OSS Distributions 		kr = StateNotificationItemSet(itemName, value);
7134e6231be0SApple OSS Distributions 		itemName->release();
7135e6231be0SApple OSS Distributions 	} else {
7136e6231be0SApple OSS Distributions 		kr = kIOReturnError;
7137e6231be0SApple OSS Distributions 	}
7138e6231be0SApple OSS Distributions 
7139e6231be0SApple OSS Distributions 	return kr;
7140e6231be0SApple OSS Distributions }
7141e6231be0SApple OSS Distributions 
7142e6231be0SApple OSS Distributions kern_return_t
CopySystemStateNotificationService_Impl(IOService ** outService)7143e6231be0SApple OSS Distributions IOService::CopySystemStateNotificationService_Impl(IOService ** outService)
7144e6231be0SApple OSS Distributions {
7145e6231be0SApple OSS Distributions 	IOService * service;
7146e6231be0SApple OSS Distributions 
7147e6231be0SApple OSS Distributions 	service = getSystemStateNotificationService();
7148e6231be0SApple OSS Distributions 	service->retain();
7149e6231be0SApple OSS Distributions 	*outService = service;
7150e6231be0SApple OSS Distributions 
7151e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
7152e6231be0SApple OSS Distributions }
7153e6231be0SApple OSS Distributions 
7154e6231be0SApple OSS Distributions IOStateNotificationItem *
stateNotificationItemCopy(OSString * itemName,OSDictionary * schema)7155e6231be0SApple OSS Distributions IOService::stateNotificationItemCopy(OSString * itemName, OSDictionary * schema)
7156e6231be0SApple OSS Distributions {
7157e6231be0SApple OSS Distributions 	IOServiceStateChangeVars * ivars = reserved->svars;
7158e6231be0SApple OSS Distributions 
7159e6231be0SApple OSS Distributions 	const OSSymbol          * name;
7160e6231be0SApple OSS Distributions 	IOStateNotificationItem * item;
7161e6231be0SApple OSS Distributions 
7162e6231be0SApple OSS Distributions 	name = OSSymbol::withString(itemName);
7163e6231be0SApple OSS Distributions 
7164e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
7165e6231be0SApple OSS Distributions 	if ((item = (typeof(item))ivars->fItems->getObject(name))) {
7166e6231be0SApple OSS Distributions 		item->retain();
7167e6231be0SApple OSS Distributions 	} else {
7168e6231be0SApple OSS Distributions 		item = OSTypeAlloc(IOStateNotificationItem);
7169e6231be0SApple OSS Distributions 		item->init();
7170e6231be0SApple OSS Distributions 		item->fListeners = OSSet::withCapacity(16);
7171e6231be0SApple OSS Distributions 
7172e6231be0SApple OSS Distributions 		if (schema) {
7173e6231be0SApple OSS Distributions 			schema->retain();
7174e6231be0SApple OSS Distributions 		} else {
7175e6231be0SApple OSS Distributions 			schema = OSDictionary::withCapacity(8);
7176e6231be0SApple OSS Distributions 		}
7177e6231be0SApple OSS Distributions 		schema->setObject(kIOStateNotificationNameKey, name);
7178e6231be0SApple OSS Distributions 		item->fSchema = schema;
7179e6231be0SApple OSS Distributions 		ivars->fItems->setObject(name, item);
7180e6231be0SApple OSS Distributions 	}
7181e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
7182e6231be0SApple OSS Distributions 
7183e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(name);
7184e6231be0SApple OSS Distributions 
7185e6231be0SApple OSS Distributions 	return item;
7186e6231be0SApple OSS Distributions }
7187e6231be0SApple OSS Distributions 
7188e6231be0SApple OSS Distributions kern_return_t
StateNotificationItemCreate_Impl(OSString * itemName,OSDictionary * schema)7189e6231be0SApple OSS Distributions IOService::StateNotificationItemCreate_Impl(OSString * itemName, OSDictionary * schema)
7190e6231be0SApple OSS Distributions {
7191e6231be0SApple OSS Distributions 	IOStateNotificationItem * item;
7192e6231be0SApple OSS Distributions 
7193e6231be0SApple OSS Distributions 	item = stateNotificationItemCopy(itemName, schema);
7194e6231be0SApple OSS Distributions 	if (!item) {
7195e6231be0SApple OSS Distributions 		return kIOReturnNoMemory;
7196e6231be0SApple OSS Distributions 	}
7197e6231be0SApple OSS Distributions 	item->release();
7198e6231be0SApple OSS Distributions 
7199e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
7200e6231be0SApple OSS Distributions }
7201e6231be0SApple OSS Distributions 
7202e6231be0SApple OSS Distributions kern_return_t
StateNotificationItemSet_Impl(OSString * itemName,OSDictionary * value)7203e6231be0SApple OSS Distributions IOService::StateNotificationItemSet_Impl(OSString * itemName, OSDictionary * value)
7204e6231be0SApple OSS Distributions {
7205e6231be0SApple OSS Distributions 	IOServiceStateChangeVars * ivars = reserved->svars;
7206e6231be0SApple OSS Distributions 
7207e6231be0SApple OSS Distributions 	OSSet                   * listeners;
7208e6231be0SApple OSS Distributions 	IOStateNotificationItem * item;
7209e6231be0SApple OSS Distributions 
7210e6231be0SApple OSS Distributions 	value->retain();
7211e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
7212e6231be0SApple OSS Distributions 	item = (typeof(item))ivars->fItems->getObject(itemName);
7213e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(item->fValue);
7214e6231be0SApple OSS Distributions 	item->fValue = value;
7215e6231be0SApple OSS Distributions 	listeners = NULL;
7216e6231be0SApple OSS Distributions 	if (item->fListeners->getCount()) {
7217e6231be0SApple OSS Distributions 		listeners = OSSet::withSet(item->fListeners);
7218e6231be0SApple OSS Distributions 	}
7219e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
7220e6231be0SApple OSS Distributions 
7221e6231be0SApple OSS Distributions 	if (listeners) {
7222e6231be0SApple OSS Distributions 		listeners->iterateObjects(^bool (OSObject * object) {
7223e6231be0SApple OSS Distributions 			IOStateNotificationListener * listener;
7224e6231be0SApple OSS Distributions 
7225e6231be0SApple OSS Distributions 			listener = (typeof(listener))object;
7226e6231be0SApple OSS Distributions 			listener->fHandler();
7227e6231be0SApple OSS Distributions 			return false;
7228e6231be0SApple OSS Distributions 		});
7229e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(listeners);
7230e6231be0SApple OSS Distributions 	}
7231e6231be0SApple OSS Distributions 
7232e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
7233e6231be0SApple OSS Distributions }
7234e6231be0SApple OSS Distributions 
7235e6231be0SApple OSS Distributions kern_return_t
StateNotificationItemCopy_Impl(OSString * itemName,OSDictionary ** outValue)7236e6231be0SApple OSS Distributions IOService::StateNotificationItemCopy_Impl(OSString * itemName, OSDictionary ** outValue)
7237e6231be0SApple OSS Distributions {
7238e6231be0SApple OSS Distributions 	IOServiceStateChangeVars * ivars = reserved->svars;
7239e6231be0SApple OSS Distributions 
7240e6231be0SApple OSS Distributions 	kern_return_t              ret;
7241e6231be0SApple OSS Distributions 	IOStateNotificationItem  * item;
7242e6231be0SApple OSS Distributions 	OSDictionary             * value;
7243e6231be0SApple OSS Distributions 
7244e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
7245e6231be0SApple OSS Distributions 	item = (typeof(item))ivars->fItems->getObject(itemName);
7246e6231be0SApple OSS Distributions 	if (item) {
7247e6231be0SApple OSS Distributions 		value = item->fValue;
7248e6231be0SApple OSS Distributions 	} else {
7249e6231be0SApple OSS Distributions 		value = NULL;
7250e6231be0SApple OSS Distributions 	}
7251e6231be0SApple OSS Distributions 	if (!value) {
7252e6231be0SApple OSS Distributions 		ret = kIOReturnNotFound;
7253e6231be0SApple OSS Distributions 	} else {
7254e6231be0SApple OSS Distributions 		value->retain();
7255e6231be0SApple OSS Distributions 		ret = kIOReturnSuccess;
7256e6231be0SApple OSS Distributions 	}
7257e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
7258e6231be0SApple OSS Distributions 
7259e6231be0SApple OSS Distributions 	*outValue = value;
7260e6231be0SApple OSS Distributions 
7261e6231be0SApple OSS Distributions 	return ret;
7262e6231be0SApple OSS Distributions }
7263e6231be0SApple OSS Distributions 
7264e6231be0SApple OSS Distributions kern_return_t
stateNotificationListenerAdd(OSArray * items,IOStateNotificationListenerRef * outRef,IOStateNotificationHandler handler)7265e6231be0SApple OSS Distributions IOService::stateNotificationListenerAdd(OSArray * items,
7266e6231be0SApple OSS Distributions     IOStateNotificationListenerRef * outRef,
7267e6231be0SApple OSS Distributions     IOStateNotificationHandler handler)
7268e6231be0SApple OSS Distributions {
7269e6231be0SApple OSS Distributions 	IOServiceStateChangeVars * ivars = reserved->svars;
7270e6231be0SApple OSS Distributions 
7271e6231be0SApple OSS Distributions 	kern_return_t                 kr __block;
7272e6231be0SApple OSS Distributions 	IOStateNotificationListener * listener;
7273e6231be0SApple OSS Distributions 
7274e6231be0SApple OSS Distributions 	listener = OSTypeAlloc(IOStateNotificationListener);
7275e6231be0SApple OSS Distributions 	listener->init();
7276e6231be0SApple OSS Distributions 	listener->fHandler = Block_copy(handler);
7277e6231be0SApple OSS Distributions 
7278e6231be0SApple OSS Distributions 	kr = kIOReturnSuccess;
7279e6231be0SApple OSS Distributions 	items->iterateObjects(^bool (OSObject * object) {
7280e6231be0SApple OSS Distributions 		OSString                * itemName;
7281e6231be0SApple OSS Distributions 		IOStateNotificationItem * item;
7282e6231be0SApple OSS Distributions 
7283e6231be0SApple OSS Distributions 		itemName = OSDynamicCast(OSString, object);
7284e6231be0SApple OSS Distributions 		if (!itemName) {
7285e6231be0SApple OSS Distributions 		        kr = kIOReturnBadArgument;
7286e6231be0SApple OSS Distributions 		        return true;
7287e6231be0SApple OSS Distributions 		}
7288e6231be0SApple OSS Distributions 		item = stateNotificationItemCopy(itemName, NULL);
7289e6231be0SApple OSS Distributions 		if (!item) {
7290e6231be0SApple OSS Distributions 		        kr = kIOReturnNoMemory;
7291e6231be0SApple OSS Distributions 		        return true;
7292e6231be0SApple OSS Distributions 		}
7293e6231be0SApple OSS Distributions 		IOLockLock(ivars->fLock);
7294e6231be0SApple OSS Distributions 		item->fListeners->setObject(listener);
7295e6231be0SApple OSS Distributions 		IOLockUnlock(ivars->fLock);
7296e6231be0SApple OSS Distributions 		item->release();
7297e6231be0SApple OSS Distributions 		return false;
7298e6231be0SApple OSS Distributions 	});
7299e6231be0SApple OSS Distributions 
7300e6231be0SApple OSS Distributions 	if (kIOReturnSuccess != kr) {
7301e6231be0SApple OSS Distributions 		stateNotificationListenerRemove(listener);
7302e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(listener);
7303e6231be0SApple OSS Distributions 	}
7304e6231be0SApple OSS Distributions 	*outRef = listener;
7305e6231be0SApple OSS Distributions 
7306e6231be0SApple OSS Distributions 	return kr;
7307e6231be0SApple OSS Distributions }
7308e6231be0SApple OSS Distributions 
7309e6231be0SApple OSS Distributions 
7310e6231be0SApple OSS Distributions kern_return_t
stateNotificationListenerRemove(IOStateNotificationListenerRef ref)7311e6231be0SApple OSS Distributions IOService::stateNotificationListenerRemove(IOStateNotificationListenerRef ref)
7312e6231be0SApple OSS Distributions {
7313e6231be0SApple OSS Distributions 	IOServiceStateChangeVars * ivars = reserved->svars;
7314e6231be0SApple OSS Distributions 
7315e6231be0SApple OSS Distributions 	IOStateNotificationListener * listener;
7316e6231be0SApple OSS Distributions 	kern_return_t                 kr;
7317e6231be0SApple OSS Distributions 
7318e6231be0SApple OSS Distributions 	kr = kIOReturnSuccess;
7319e6231be0SApple OSS Distributions 	listener = (typeof(listener))ref;
7320e6231be0SApple OSS Distributions 
7321e6231be0SApple OSS Distributions 	IOLockLock(ivars->fLock);
7322e6231be0SApple OSS Distributions 	ivars->fItems->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
7323e6231be0SApple OSS Distributions 		IOStateNotificationItem * item;
7324e6231be0SApple OSS Distributions 
7325e6231be0SApple OSS Distributions 		item = (typeof(item))object;
7326e6231be0SApple OSS Distributions 		item->fListeners->removeObject(listener);
7327e6231be0SApple OSS Distributions 		return false;
7328e6231be0SApple OSS Distributions 	});
7329e6231be0SApple OSS Distributions 	IOLockUnlock(ivars->fLock);
7330e6231be0SApple OSS Distributions 
7331e6231be0SApple OSS Distributions 	return kr;
7332e6231be0SApple OSS Distributions }
7333e6231be0SApple OSS Distributions 
7334e6231be0SApple OSS Distributions 
7335e6231be0SApple OSS Distributions 
7336e6231be0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7337e6231be0SApple OSS Distributions 
7338e6231be0SApple OSS Distributions kern_return_t
Create_Impl(OSString * name,IOUserClient * userClient,IOWorkGroup ** workgroup)7339e6231be0SApple OSS Distributions IOWorkGroup::Create_Impl(OSString * name, IOUserClient * userClient, IOWorkGroup ** workgroup)
7340e6231be0SApple OSS Distributions {
7341e6231be0SApple OSS Distributions 	IOWorkGroup * inst = NULL;
7342e6231be0SApple OSS Distributions 	IOUserUserClient * uc = NULL;
7343e6231be0SApple OSS Distributions 	kern_return_t ret = kIOReturnError;
7344e6231be0SApple OSS Distributions 	IOUserServer * us;
7345e6231be0SApple OSS Distributions 
7346e6231be0SApple OSS Distributions 	if (name == NULL) {
7347e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7348e6231be0SApple OSS Distributions 		goto finish;
7349e6231be0SApple OSS Distributions 	}
7350e6231be0SApple OSS Distributions 
7351e6231be0SApple OSS Distributions 	if (name->getLength() > kIOWorkGroupMaxNameLength) {
7352e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7353e6231be0SApple OSS Distributions 		goto finish;
7354e6231be0SApple OSS Distributions 	}
7355e6231be0SApple OSS Distributions 
7356e6231be0SApple OSS Distributions 	uc = OSDynamicCast(IOUserUserClient, userClient);
7357e6231be0SApple OSS Distributions 	if (uc == NULL) {
7358e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7359e6231be0SApple OSS Distributions 		goto finish;
7360e6231be0SApple OSS Distributions 	}
7361e6231be0SApple OSS Distributions 
7362e6231be0SApple OSS Distributions 	inst = OSTypeAlloc(IOWorkGroup);
7363e6231be0SApple OSS Distributions 	if (!inst->init()) {
7364e6231be0SApple OSS Distributions 		inst->free();
7365e6231be0SApple OSS Distributions 		inst = NULL;
7366e6231be0SApple OSS Distributions 		ret = kIOReturnNoMemory;
7367e6231be0SApple OSS Distributions 		goto finish;
7368e6231be0SApple OSS Distributions 	}
7369e6231be0SApple OSS Distributions 
7370e6231be0SApple OSS Distributions 	us = (typeof(us))thread_iokit_tls_get(0);
7371e6231be0SApple OSS Distributions 	inst->ivars->userServer = OSDynamicCast(IOUserServer, us);
7372e6231be0SApple OSS Distributions 
7373e6231be0SApple OSS Distributions 	if (inst->ivars->userServer == NULL) {
7374e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7375e6231be0SApple OSS Distributions 		goto finish;
7376e6231be0SApple OSS Distributions 	}
7377e6231be0SApple OSS Distributions 	inst->ivars->userServer->retain();
7378e6231be0SApple OSS Distributions 
7379e6231be0SApple OSS Distributions 	inst->ivars->name = name;
7380e6231be0SApple OSS Distributions 	inst->ivars->name->retain();
7381e6231be0SApple OSS Distributions 
7382e6231be0SApple OSS Distributions 	inst->ivars->userClient = uc; // no retain
7383e6231be0SApple OSS Distributions 
7384e6231be0SApple OSS Distributions 	IOLockLock(uc->fLock);
7385e6231be0SApple OSS Distributions 	uc->fWorkGroups->setObject(name, inst);
7386e6231be0SApple OSS Distributions 	IOLockUnlock(uc->fLock);
7387e6231be0SApple OSS Distributions 	ret = kIOReturnSuccess;
7388e6231be0SApple OSS Distributions 
7389e6231be0SApple OSS Distributions finish:
7390e6231be0SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
7391e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(inst);
7392e6231be0SApple OSS Distributions 	} else {
7393e6231be0SApple OSS Distributions 		*workgroup = inst;
7394e6231be0SApple OSS Distributions 	}
7395e6231be0SApple OSS Distributions 
7396e6231be0SApple OSS Distributions 	return ret;
7397e6231be0SApple OSS Distributions }
7398e6231be0SApple OSS Distributions 
7399e6231be0SApple OSS Distributions kern_return_t
InvalidateKernel_Impl(IOUserClient * client)7400e6231be0SApple OSS Distributions IOWorkGroup::InvalidateKernel_Impl(IOUserClient * client)
7401e6231be0SApple OSS Distributions {
7402e6231be0SApple OSS Distributions 	IOUserUserClient * uc = OSDynamicCast(IOUserUserClient, client);
7403e6231be0SApple OSS Distributions 
7404e6231be0SApple OSS Distributions 	if (uc == NULL) {
7405e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
7406e6231be0SApple OSS Distributions 	}
7407e6231be0SApple OSS Distributions 
7408e6231be0SApple OSS Distributions 	if (uc != ivars->userClient) {
7409e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
7410e6231be0SApple OSS Distributions 	}
7411e6231be0SApple OSS Distributions 
7412e6231be0SApple OSS Distributions 	IOLockLock(uc->fLock);
7413e6231be0SApple OSS Distributions 	uc->fWorkGroups->removeObject(ivars->name);
7414e6231be0SApple OSS Distributions 	IOLockUnlock(uc->fLock);
7415e6231be0SApple OSS Distributions 
7416e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
7417e6231be0SApple OSS Distributions }
7418e6231be0SApple OSS Distributions 
7419e6231be0SApple OSS Distributions kern_return_t
SetWorkGroupPort_Impl(mach_port_t port)7420e6231be0SApple OSS Distributions IOWorkGroup::SetWorkGroupPort_Impl(mach_port_t port)
7421e6231be0SApple OSS Distributions {
7422e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
7423e6231be0SApple OSS Distributions }
7424e6231be0SApple OSS Distributions 
7425e6231be0SApple OSS Distributions bool
init()7426e6231be0SApple OSS Distributions IOWorkGroup::init()
7427e6231be0SApple OSS Distributions {
7428e6231be0SApple OSS Distributions 	if (!OSObject::init()) {
7429e6231be0SApple OSS Distributions 		return false;
7430e6231be0SApple OSS Distributions 	}
7431e6231be0SApple OSS Distributions 	ivars = IOMallocType(IOWorkGroup_IVars);
7432e6231be0SApple OSS Distributions 
7433e6231be0SApple OSS Distributions 	return true;
7434e6231be0SApple OSS Distributions }
7435e6231be0SApple OSS Distributions 
7436e6231be0SApple OSS Distributions void
free()7437e6231be0SApple OSS Distributions IOWorkGroup::free()
7438e6231be0SApple OSS Distributions {
7439e6231be0SApple OSS Distributions 	if (ivars) {
7440e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(ivars->userServer);
7441e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(ivars->name);
7442e6231be0SApple OSS Distributions 		IOFreeType(ivars, IOWorkGroup_IVars);
7443e6231be0SApple OSS Distributions 	}
7444e6231be0SApple OSS Distributions 
7445e6231be0SApple OSS Distributions 	OSObject::free();
7446e6231be0SApple OSS Distributions }
7447e6231be0SApple OSS Distributions 
7448e6231be0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7449e6231be0SApple OSS Distributions 
7450e6231be0SApple OSS Distributions kern_return_t
Create_Impl(OSString * name,IOUserClient * userClient,IOEventLink ** eventlink)7451e6231be0SApple OSS Distributions IOEventLink::Create_Impl(OSString * name, IOUserClient * userClient, IOEventLink ** eventlink)
7452e6231be0SApple OSS Distributions {
7453e6231be0SApple OSS Distributions 	IOEventLink * inst = NULL;
7454e6231be0SApple OSS Distributions 	IOUserUserClient * uc = NULL;
7455e6231be0SApple OSS Distributions 	IOUserServer * us;
7456e6231be0SApple OSS Distributions 	kern_return_t ret = kIOReturnError;
7457e6231be0SApple OSS Distributions 
7458e6231be0SApple OSS Distributions 	if (name == NULL) {
7459e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7460e6231be0SApple OSS Distributions 		goto finish;
7461e6231be0SApple OSS Distributions 	}
7462e6231be0SApple OSS Distributions 
7463e6231be0SApple OSS Distributions 	if (name->getLength() > kIOEventLinkMaxNameLength) {
7464e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7465e6231be0SApple OSS Distributions 		goto finish;
7466e6231be0SApple OSS Distributions 	}
7467e6231be0SApple OSS Distributions 
7468e6231be0SApple OSS Distributions 	uc = OSDynamicCast(IOUserUserClient, userClient);
7469e6231be0SApple OSS Distributions 	if (uc == NULL) {
7470e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7471e6231be0SApple OSS Distributions 		goto finish;
7472e6231be0SApple OSS Distributions 	}
7473e6231be0SApple OSS Distributions 
7474e6231be0SApple OSS Distributions 	inst = OSTypeAlloc(IOEventLink);
7475e6231be0SApple OSS Distributions 	if (!inst->init()) {
7476e6231be0SApple OSS Distributions 		inst->free();
7477e6231be0SApple OSS Distributions 		inst = NULL;
7478e6231be0SApple OSS Distributions 		ret = kIOReturnNoMemory;
7479e6231be0SApple OSS Distributions 		goto finish;
7480e6231be0SApple OSS Distributions 	}
7481e6231be0SApple OSS Distributions 
7482e6231be0SApple OSS Distributions 	us = (typeof(us))thread_iokit_tls_get(0);
7483e6231be0SApple OSS Distributions 	inst->ivars->userServer = OSDynamicCast(IOUserServer, us);
7484e6231be0SApple OSS Distributions 
7485e6231be0SApple OSS Distributions 	if (inst->ivars->userServer == NULL) {
7486e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
7487e6231be0SApple OSS Distributions 		goto finish;
7488e6231be0SApple OSS Distributions 	}
7489e6231be0SApple OSS Distributions 	inst->ivars->userServer->retain();
7490e6231be0SApple OSS Distributions 
7491e6231be0SApple OSS Distributions 	inst->ivars->name = name;
7492e6231be0SApple OSS Distributions 	inst->ivars->name->retain();
7493e6231be0SApple OSS Distributions 
7494e6231be0SApple OSS Distributions 	inst->ivars->userClient = uc; // no retain
7495e6231be0SApple OSS Distributions 
7496e6231be0SApple OSS Distributions 	IOLockLock(uc->fLock);
7497e6231be0SApple OSS Distributions 	uc->fEventLinks->setObject(name, inst);
7498e6231be0SApple OSS Distributions 	IOLockUnlock(uc->fLock);
7499e6231be0SApple OSS Distributions 
7500e6231be0SApple OSS Distributions 	ret = kIOReturnSuccess;
7501e6231be0SApple OSS Distributions 
7502e6231be0SApple OSS Distributions finish:
7503e6231be0SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
7504e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(inst);
7505e6231be0SApple OSS Distributions 	} else {
7506e6231be0SApple OSS Distributions 		*eventlink = inst;
7507e6231be0SApple OSS Distributions 	}
7508e6231be0SApple OSS Distributions 
7509e6231be0SApple OSS Distributions 	return ret;
7510e6231be0SApple OSS Distributions }
7511e6231be0SApple OSS Distributions 
7512e6231be0SApple OSS Distributions kern_return_t
InvalidateKernel_Impl(IOUserClient * client)7513e6231be0SApple OSS Distributions IOEventLink::InvalidateKernel_Impl(IOUserClient * client)
7514e6231be0SApple OSS Distributions {
7515e6231be0SApple OSS Distributions 	IOUserUserClient * uc = OSDynamicCast(IOUserUserClient, client);
7516e6231be0SApple OSS Distributions 
7517e6231be0SApple OSS Distributions 	if (uc == NULL) {
7518e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
7519e6231be0SApple OSS Distributions 	}
7520e6231be0SApple OSS Distributions 
7521e6231be0SApple OSS Distributions 	if (uc != ivars->userClient) {
7522e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
7523e6231be0SApple OSS Distributions 	}
7524e6231be0SApple OSS Distributions 
7525e6231be0SApple OSS Distributions 	IOLockLock(uc->fLock);
7526e6231be0SApple OSS Distributions 	uc->fEventLinks->removeObject(ivars->name);
7527e6231be0SApple OSS Distributions 	IOLockUnlock(uc->fLock);
7528e6231be0SApple OSS Distributions 
7529e6231be0SApple OSS Distributions 	return kIOReturnSuccess;
7530e6231be0SApple OSS Distributions }
7531e6231be0SApple OSS Distributions 
7532e6231be0SApple OSS Distributions bool
init()7533e6231be0SApple OSS Distributions IOEventLink::init()
7534e6231be0SApple OSS Distributions {
7535e6231be0SApple OSS Distributions 	if (!OSObject::init()) {
7536e6231be0SApple OSS Distributions 		return false;
7537e6231be0SApple OSS Distributions 	}
7538e6231be0SApple OSS Distributions 	ivars = IOMallocType(IOEventLink_IVars);
7539e6231be0SApple OSS Distributions 
7540e6231be0SApple OSS Distributions 	return true;
7541e6231be0SApple OSS Distributions }
7542e6231be0SApple OSS Distributions 
7543e6231be0SApple OSS Distributions void
free()7544e6231be0SApple OSS Distributions IOEventLink::free()
7545e6231be0SApple OSS Distributions {
7546e6231be0SApple OSS Distributions 	if (ivars) {
7547e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(ivars->userServer);
7548e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(ivars->name);
7549e6231be0SApple OSS Distributions 		IOFreeType(ivars, IOEventLink_IVars);
7550e6231be0SApple OSS Distributions 	}
7551e6231be0SApple OSS Distributions 
7552e6231be0SApple OSS Distributions 	OSObject::free();
7553e6231be0SApple OSS Distributions }
7554e6231be0SApple OSS Distributions 
7555e6231be0SApple OSS Distributions kern_return_t
SetEventlinkPort_Impl(mach_port_t port __unused)7556e6231be0SApple OSS Distributions IOEventLink::SetEventlinkPort_Impl(mach_port_t port __unused)
7557e6231be0SApple OSS Distributions {
7558e6231be0SApple OSS Distributions 	return kIOReturnUnsupported;
7559e6231be0SApple OSS Distributions }
7560