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 */, ©);
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, ©outdata, (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