xref: /xnu-11215/iokit/Kernel/IOUserClient.cpp (revision 8d741a5d)
1c1dac77fSApple OSS Distributions /*
2a5e72196SApple OSS Distributions  * Copyright (c) 1998-2019 Apple Inc. All rights reserved.
3c1dac77fSApple OSS Distributions  *
4e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5c1dac77fSApple OSS Distributions  *
6e13b1fa5SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14c1dac77fSApple OSS Distributions  *
15e13b1fa5SApple OSS Distributions  * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions  *
18e13b1fa5SApple OSS Distributions  * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20c1dac77fSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21c1dac77fSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions  * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions  * limitations under the License.
25c1dac77fSApple OSS Distributions  *
26e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27c1dac77fSApple OSS Distributions  */
28368ad365SApple OSS Distributions 
293ca3bd55SApple OSS Distributions #include <libkern/c++/OSKext.h>
30bb611c8fSApple OSS Distributions #include <libkern/c++/OSSharedPtr.h>
31c1dac77fSApple OSS Distributions #include <IOKit/IOKitServer.h>
32e13b1fa5SApple OSS Distributions #include <IOKit/IOKitKeysPrivate.h>
33c1dac77fSApple OSS Distributions #include <IOKit/IOUserClient.h>
34c1dac77fSApple OSS Distributions #include <IOKit/IOService.h>
35c1dac77fSApple OSS Distributions #include <IOKit/IORegistryEntry.h>
36c1dac77fSApple OSS Distributions #include <IOKit/IOCatalogue.h>
37c1dac77fSApple OSS Distributions #include <IOKit/IOMemoryDescriptor.h>
383ca3bd55SApple OSS Distributions #include <IOKit/IOBufferMemoryDescriptor.h>
39c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h>
4076e12aa3SApple OSS Distributions #include <IOKit/IOBSD.h>
41855239e5SApple OSS Distributions #include <IOKit/IOStatisticsPrivate.h>
42855239e5SApple OSS Distributions #include <IOKit/IOTimeStamp.h>
43cc9a6355SApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h>
44a5e72196SApple OSS Distributions #include <IOKit/IOUserServer.h>
45186b8fceSApple OSS Distributions #include <IOKit/system.h>
463ca3bd55SApple OSS Distributions #include <libkern/OSDebug.h>
47a5e72196SApple OSS Distributions #include <DriverKit/OSAction.h>
48e13b1fa5SApple OSS Distributions #include <sys/proc.h>
49855239e5SApple OSS Distributions #include <sys/kauth.h>
50a3bb9fccSApple OSS Distributions #include <sys/codesign.h>
51aca3beaaSApple OSS Distributions #include <sys/code_signing.h>
52*8d741a5dSApple OSS Distributions #include <vm/vm_kern_xnu.h>
53855239e5SApple OSS Distributions 
5488cc0b97SApple OSS Distributions #include <mach/sdt.h>
55a5e72196SApple OSS Distributions #include <os/hash.h>
5688cc0b97SApple OSS Distributions 
57e6231be0SApple OSS Distributions #include <libkern/amfi/amfi.h>
58e6231be0SApple OSS Distributions 
59855239e5SApple OSS Distributions #if CONFIG_MACF
60855239e5SApple OSS Distributions 
61855239e5SApple OSS Distributions extern "C" {
62855239e5SApple OSS Distributions #include <security/mac_framework.h>
63855239e5SApple OSS Distributions };
64855239e5SApple OSS Distributions #include <sys/kauth.h>
65855239e5SApple OSS Distributions 
66855239e5SApple OSS Distributions #define IOMACF_LOG 0
67855239e5SApple OSS Distributions 
68855239e5SApple OSS Distributions #endif /* CONFIG_MACF */
69c1dac77fSApple OSS Distributions 
70c1dac77fSApple OSS Distributions #include <IOKit/assert.h>
71c1dac77fSApple OSS Distributions 
72368ad365SApple OSS Distributions #include "IOServicePrivate.h"
73e13b1fa5SApple OSS Distributions #include "IOKitKernelInternal.h"
74e13b1fa5SApple OSS Distributions 
75e13b1fa5SApple OSS Distributions #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
76e13b1fa5SApple OSS Distributions #define SCALAR32(x) ((uint32_t )x)
77186b8fceSApple OSS Distributions #define ARG32(x)    ((void *)(uintptr_t)SCALAR32(x))
783ca3bd55SApple OSS Distributions #define REF64(x)    ((io_user_reference_t)((UInt64)(x)))
79e13b1fa5SApple OSS Distributions #define REF32(x)    ((int)(x))
80e13b1fa5SApple OSS Distributions 
81a5e72196SApple OSS Distributions enum{
82e13b1fa5SApple OSS Distributions 	kIOUCAsync0Flags          = 3ULL,
8388cc0b97SApple OSS Distributions 	kIOUCAsync64Flag          = 1ULL,
8488cc0b97SApple OSS Distributions 	kIOUCAsyncErrorLoggedFlag = 2ULL
85e13b1fa5SApple OSS Distributions };
86368ad365SApple OSS Distributions 
87855239e5SApple OSS Distributions #if IOKITSTATS
88855239e5SApple OSS Distributions 
89855239e5SApple OSS Distributions #define IOStatisticsRegisterCounter() \
90855239e5SApple OSS Distributions do { \
91855239e5SApple OSS Distributions 	reserved->counter = IOStatistics::registerUserClient(this); \
92855239e5SApple OSS Distributions } while (0)
93855239e5SApple OSS Distributions 
94855239e5SApple OSS Distributions #define IOStatisticsUnregisterCounter() \
95855239e5SApple OSS Distributions do { \
96855239e5SApple OSS Distributions 	if (reserved) \
97855239e5SApple OSS Distributions 	        IOStatistics::unregisterUserClient(reserved->counter); \
98855239e5SApple OSS Distributions } while (0)
99855239e5SApple OSS Distributions 
100855239e5SApple OSS Distributions #define IOStatisticsClientCall() \
101855239e5SApple OSS Distributions do { \
102855239e5SApple OSS Distributions 	IOStatistics::countUserClientCall(client); \
103855239e5SApple OSS Distributions } while (0)
104855239e5SApple OSS Distributions 
105855239e5SApple OSS Distributions #else
106855239e5SApple OSS Distributions 
107855239e5SApple OSS Distributions #define IOStatisticsRegisterCounter()
108855239e5SApple OSS Distributions #define IOStatisticsUnregisterCounter()
109855239e5SApple OSS Distributions #define IOStatisticsClientCall()
110855239e5SApple OSS Distributions 
111855239e5SApple OSS Distributions #endif /* IOKITSTATS */
112855239e5SApple OSS Distributions 
11388cc0b97SApple OSS Distributions #if DEVELOPMENT || DEBUG
11488cc0b97SApple OSS Distributions 
11588cc0b97SApple OSS Distributions #define FAKE_STACK_FRAME(a)                                             \
11688cc0b97SApple OSS Distributions 	const void ** __frameptr;                                       \
11788cc0b97SApple OSS Distributions 	const void  * __retaddr;                                        \
11888cc0b97SApple OSS Distributions 	__frameptr = (typeof(__frameptr)) __builtin_frame_address(0);   \
11988cc0b97SApple OSS Distributions 	__retaddr = __frameptr[1];                                      \
12088cc0b97SApple OSS Distributions 	__frameptr[1] = (a);
12188cc0b97SApple OSS Distributions 
12288cc0b97SApple OSS Distributions #define FAKE_STACK_FRAME_END()                                          \
12388cc0b97SApple OSS Distributions 	__frameptr[1] = __retaddr;
12488cc0b97SApple OSS Distributions 
12588cc0b97SApple OSS Distributions #else /* DEVELOPMENT || DEBUG */
12688cc0b97SApple OSS Distributions 
12788cc0b97SApple OSS Distributions #define FAKE_STACK_FRAME(a)
12888cc0b97SApple OSS Distributions #define FAKE_STACK_FRAME_END()
12988cc0b97SApple OSS Distributions 
13088cc0b97SApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
13188cc0b97SApple OSS Distributions 
132a5e72196SApple OSS Distributions #define ASYNC_REF_COUNT         (sizeof(io_async_ref_t) / sizeof(natural_t))
133a5e72196SApple OSS Distributions #define ASYNC_REF64_COUNT       (sizeof(io_async_ref64_t) / sizeof(io_user_reference_t))
134a5e72196SApple OSS Distributions 
135c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
136c1dac77fSApple OSS Distributions 
137c1dac77fSApple OSS Distributions extern "C" {
13814e3d835SApple OSS Distributions #include <mach/mach_traps.h>
139*8d741a5dSApple OSS Distributions #include <vm/vm_map_xnu.h>
140c1dac77fSApple OSS Distributions } /* extern "C" */
141c1dac77fSApple OSS Distributions 
142a5e72196SApple OSS Distributions struct IOMachPortHashList;
143a5e72196SApple OSS Distributions 
144a5e72196SApple OSS Distributions static_assert(IKOT_MAX_TYPE <= 255);
145a5e72196SApple OSS Distributions 
146c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
147c1dac77fSApple OSS Distributions 
148c1dac77fSApple OSS Distributions // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
149c1dac77fSApple OSS Distributions class IOMachPort : public OSObject
150c1dac77fSApple OSS Distributions {
151a5e72196SApple OSS Distributions 	OSDeclareDefaultStructors(IOMachPort);
152c1dac77fSApple OSS Distributions public:
1531031c584SApple OSS Distributions 	mach_port_mscount_t mscount;
1541031c584SApple OSS Distributions 	IOLock      lock;
155a5e72196SApple OSS Distributions 	SLIST_ENTRY(IOMachPort) link;
156c1dac77fSApple OSS Distributions 	ipc_port_t  port;
1571031c584SApple OSS Distributions 	OSObject*   XNU_PTRAUTH_SIGNED_PTR("IOMachPort.object") object;
158c1dac77fSApple OSS Distributions 
159a5e72196SApple OSS Distributions 	static IOMachPort* withObjectAndType(OSObject *obj, ipc_kobject_type_t type);
160a5e72196SApple OSS Distributions 
161a5e72196SApple OSS Distributions 	static IOMachPortHashList* bucketForObject(OSObject *obj,
162c1dac77fSApple OSS Distributions 	    ipc_kobject_type_t type);
163a5e72196SApple OSS Distributions 
164e6231be0SApple OSS Distributions 	static LIBKERN_RETURNS_NOT_RETAINED IOMachPort* portForObjectInBucket(IOMachPortHashList *bucket, OSObject *obj, ipc_kobject_type_t type);
165a5e72196SApple OSS Distributions 
166fad439e7SApple OSS Distributions 	static bool noMoreSendersForObject( OSObject * obj,
167fad439e7SApple OSS Distributions 	    ipc_kobject_type_t type, mach_port_mscount_t * mscount );
168c1dac77fSApple OSS Distributions 	static void releasePortForObject( OSObject * obj,
169c1dac77fSApple OSS Distributions 	    ipc_kobject_type_t type );
170368ad365SApple OSS Distributions 
171c1dac77fSApple OSS Distributions 	static mach_port_name_t makeSendRightForTask( task_t task,
172c1dac77fSApple OSS Distributions 	    io_object_t obj, ipc_kobject_type_t type );
173c1dac77fSApple OSS Distributions 
1740f3703acSApple OSS Distributions 	virtual void free() APPLE_KEXT_OVERRIDE;
175c1dac77fSApple OSS Distributions };
176c1dac77fSApple OSS Distributions 
177c1dac77fSApple OSS Distributions #define super OSObject
178bb611c8fSApple OSS Distributions OSDefineMetaClassAndStructorsWithZone(IOMachPort, OSObject, ZC_ZFREE_CLEARMEM)
179c1dac77fSApple OSS Distributions 
180c1dac77fSApple OSS Distributions static IOLock *         gIOObjectPortLock;
181a5e72196SApple OSS Distributions IOLock *                gIOUserServerLock;
182c1dac77fSApple OSS Distributions 
183bb611c8fSApple OSS Distributions SECURITY_READ_ONLY_LATE(const struct io_filter_callbacks *) gIOUCFilterCallbacks;
184bb611c8fSApple OSS Distributions 
185c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
186c1dac77fSApple OSS Distributions 
187a5e72196SApple OSS Distributions SLIST_HEAD(IOMachPortHashList, IOMachPort);
188c1dac77fSApple OSS Distributions 
189bb611c8fSApple OSS Distributions #if defined(XNU_TARGET_OS_OSX)
190a5e72196SApple OSS Distributions #define PORT_HASH_SIZE 4096
191bb611c8fSApple OSS Distributions #else /* defined(!XNU_TARGET_OS_OSX) */
192bb611c8fSApple OSS Distributions #define PORT_HASH_SIZE 256
193bb611c8fSApple OSS Distributions #endif /* !defined(!XNU_TARGET_OS_OSX) */
194a5e72196SApple OSS Distributions 
195bb611c8fSApple OSS Distributions IOMachPortHashList gIOMachPortHash[PORT_HASH_SIZE];
196a5e72196SApple OSS Distributions 
197a5e72196SApple OSS Distributions void
IOMachPortInitialize(void)198a5e72196SApple OSS Distributions IOMachPortInitialize(void)
199c1dac77fSApple OSS Distributions {
200a5e72196SApple OSS Distributions 	for (size_t i = 0; i < PORT_HASH_SIZE; i++) {
201bb611c8fSApple OSS Distributions 		SLIST_INIT(&gIOMachPortHash[i]);
202a5e72196SApple OSS Distributions 	}
203a5e72196SApple OSS Distributions }
204c1dac77fSApple OSS Distributions 
205a5e72196SApple OSS Distributions IOMachPortHashList*
bucketForObject(OSObject * obj,ipc_kobject_type_t type)206a5e72196SApple OSS Distributions IOMachPort::bucketForObject(OSObject *obj, ipc_kobject_type_t type )
207cc9a6355SApple OSS Distributions {
208bb611c8fSApple OSS Distributions 	return &gIOMachPortHash[os_hash_kernel_pointer(obj) % PORT_HASH_SIZE];
209cc9a6355SApple OSS Distributions }
210c1dac77fSApple OSS Distributions 
211a5e72196SApple OSS Distributions IOMachPort*
portForObjectInBucket(IOMachPortHashList * bucket,OSObject * obj,ipc_kobject_type_t type)212a5e72196SApple OSS Distributions IOMachPort::portForObjectInBucket(IOMachPortHashList *bucket, OSObject *obj, ipc_kobject_type_t type)
213c1dac77fSApple OSS Distributions {
214a5e72196SApple OSS Distributions 	IOMachPort *machPort;
215c1dac77fSApple OSS Distributions 
216a5e72196SApple OSS Distributions 	SLIST_FOREACH(machPort, bucket, link) {
2171031c584SApple OSS Distributions 		if (machPort->object == obj && iokit_port_type(machPort->port) == type) {
218a5e72196SApple OSS Distributions 			return machPort;
219a5e72196SApple OSS Distributions 		}
220a5e72196SApple OSS Distributions 	}
221a5e72196SApple OSS Distributions 	return NULL;
222fad439e7SApple OSS Distributions }
223c1dac77fSApple OSS Distributions 
224a5e72196SApple OSS Distributions IOMachPort*
withObjectAndType(OSObject * obj,ipc_kobject_type_t type)225a5e72196SApple OSS Distributions IOMachPort::withObjectAndType(OSObject *obj, ipc_kobject_type_t type)
226a5e72196SApple OSS Distributions {
227a5e72196SApple OSS Distributions 	IOMachPort *machPort = NULL;
228a5e72196SApple OSS Distributions 
229a5e72196SApple OSS Distributions 	machPort = new IOMachPort;
230a5e72196SApple OSS Distributions 	if (__improbable(machPort && !machPort->init())) {
231e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(machPort);
232a5e72196SApple OSS Distributions 		return NULL;
233c1dac77fSApple OSS Distributions 	}
234c1dac77fSApple OSS Distributions 
235a5e72196SApple OSS Distributions 	machPort->object = obj;
2361031c584SApple OSS Distributions 	machPort->port = iokit_alloc_object_port(machPort, type);
2371031c584SApple OSS Distributions 	IOLockInlineInit(&machPort->lock);
238c1dac77fSApple OSS Distributions 
239a5e72196SApple OSS Distributions 	obj->taggedRetain(OSTypeID(OSCollection));
240a5e72196SApple OSS Distributions 	machPort->mscount++;
241a5e72196SApple OSS Distributions 
242a5e72196SApple OSS Distributions 	return machPort;
243c1dac77fSApple OSS Distributions }
244c1dac77fSApple OSS Distributions 
245a5e72196SApple OSS Distributions bool
noMoreSendersForObject(OSObject * obj,ipc_kobject_type_t type,mach_port_mscount_t * mscount)246a5e72196SApple OSS Distributions IOMachPort::noMoreSendersForObject( OSObject * obj,
247fad439e7SApple OSS Distributions     ipc_kobject_type_t type, mach_port_mscount_t * mscount )
248fad439e7SApple OSS Distributions {
249a5e72196SApple OSS Distributions 	IOMachPort *machPort = NULL;
25088cc0b97SApple OSS Distributions 	IOUserClient *uc;
251a5e72196SApple OSS Distributions 	OSAction *action;
252fad439e7SApple OSS Distributions 	bool destroyed = true;
253fad439e7SApple OSS Distributions 
254a5e72196SApple OSS Distributions 	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, type);
255fad439e7SApple OSS Distributions 
256fad439e7SApple OSS Distributions 	obj->retain();
257fad439e7SApple OSS Distributions 
258a5e72196SApple OSS Distributions 	lck_mtx_lock(gIOObjectPortLock);
259a5e72196SApple OSS Distributions 
260a5e72196SApple OSS Distributions 	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
261a5e72196SApple OSS Distributions 
262fad439e7SApple OSS Distributions 	if (machPort) {
2633ca3bd55SApple OSS Distributions 		destroyed = (machPort->mscount <= *mscount);
264a5e72196SApple OSS Distributions 		if (!destroyed) {
265a5e72196SApple OSS Distributions 			*mscount = machPort->mscount;
266a5e72196SApple OSS Distributions 			lck_mtx_unlock(gIOObjectPortLock);
267a5e72196SApple OSS Distributions 		} else {
268a5e72196SApple OSS Distributions 			if ((IKOT_IOKIT_CONNECT == type) && (uc = OSDynamicCast(IOUserClient, obj))) {
26988cc0b97SApple OSS Distributions 				uc->noMoreSenders();
27088cc0b97SApple OSS Distributions 			}
271a5e72196SApple OSS Distributions 			SLIST_REMOVE(bucket, machPort, IOMachPort, link);
272a5e72196SApple OSS Distributions 
2731031c584SApple OSS Distributions 			IOLockLock(&machPort->lock);
2741031c584SApple OSS Distributions 			iokit_remove_object_port(machPort->port, type);
2751031c584SApple OSS Distributions 			machPort->object = NULL;
2761031c584SApple OSS Distributions 			IOLockUnlock(&machPort->lock);
2771031c584SApple OSS Distributions 
278a5e72196SApple OSS Distributions 			lck_mtx_unlock(gIOObjectPortLock);
279a5e72196SApple OSS Distributions 
280e6231be0SApple OSS Distributions 			OS_ANALYZER_SUPPRESS("77508635") OSSafeReleaseNULL(machPort);
281e6231be0SApple OSS Distributions 
282a5e72196SApple OSS Distributions 			obj->taggedRelease(OSTypeID(OSCollection));
28388cc0b97SApple OSS Distributions 		}
284a5e72196SApple OSS Distributions 	} else {
285a5e72196SApple OSS Distributions 		lck_mtx_unlock(gIOObjectPortLock);
286fad439e7SApple OSS Distributions 	}
287a5e72196SApple OSS Distributions 
288a5e72196SApple OSS Distributions 	if ((IKOT_UEXT_OBJECT == type) && (action = OSDynamicCast(OSAction, obj))) {
289a5e72196SApple OSS Distributions 		action->Aborted();
290a5e72196SApple OSS Distributions 	}
291a5e72196SApple OSS Distributions 
2925c2921b0SApple OSS Distributions 	if (IKOT_UEXT_OBJECT == type && IOUserServer::shouldLeakObjects()) {
2935c2921b0SApple OSS Distributions 		// Leak object
2945c2921b0SApple OSS Distributions 		obj->retain();
2955c2921b0SApple OSS Distributions 	}
2965c2921b0SApple OSS Distributions 
297fad439e7SApple OSS Distributions 	obj->release();
298a5e72196SApple OSS Distributions 
299a5e72196SApple OSS Distributions 	return destroyed;
300fad439e7SApple OSS Distributions }
301fad439e7SApple OSS Distributions 
302a5e72196SApple OSS Distributions void
releasePortForObject(OSObject * obj,ipc_kobject_type_t type)303a5e72196SApple OSS Distributions IOMachPort::releasePortForObject( OSObject * obj,
304c1dac77fSApple OSS Distributions     ipc_kobject_type_t type )
305c1dac77fSApple OSS Distributions {
306368ad365SApple OSS Distributions 	IOMachPort *machPort;
3071031c584SApple OSS Distributions 	IOService  *service;
308a5e72196SApple OSS Distributions 	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, type);
309c1dac77fSApple OSS Distributions 
31088cc0b97SApple OSS Distributions 	assert(IKOT_IOKIT_CONNECT != type);
31188cc0b97SApple OSS Distributions 
312a5e72196SApple OSS Distributions 	lck_mtx_lock(gIOObjectPortLock);
313c1dac77fSApple OSS Distributions 
314a5e72196SApple OSS Distributions 	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
315a5e72196SApple OSS Distributions 
3161031c584SApple OSS Distributions 	if (machPort
3171031c584SApple OSS Distributions 	    && (type == IKOT_IOKIT_OBJECT)
3181031c584SApple OSS Distributions 	    && (service = OSDynamicCast(IOService, obj))
3191031c584SApple OSS Distributions 	    && !service->machPortHoldDestroy()) {
320c1dac77fSApple OSS Distributions 		obj->retain();
321a5e72196SApple OSS Distributions 		SLIST_REMOVE(bucket, machPort, IOMachPort, link);
322a5e72196SApple OSS Distributions 
3231031c584SApple OSS Distributions 		IOLockLock(&machPort->lock);
3241031c584SApple OSS Distributions 		iokit_remove_object_port(machPort->port, type);
3251031c584SApple OSS Distributions 		machPort->object = NULL;
3261031c584SApple OSS Distributions 		IOLockUnlock(&machPort->lock);
3271031c584SApple OSS Distributions 
328a5e72196SApple OSS Distributions 		lck_mtx_unlock(gIOObjectPortLock);
329a5e72196SApple OSS Distributions 
330e6231be0SApple OSS Distributions 		OS_ANALYZER_SUPPRESS("77508635") OSSafeReleaseNULL(machPort);
331e6231be0SApple OSS Distributions 
332a5e72196SApple OSS Distributions 		obj->taggedRelease(OSTypeID(OSCollection));
333c1dac77fSApple OSS Distributions 		obj->release();
334a5e72196SApple OSS Distributions 	} else {
335a5e72196SApple OSS Distributions 		lck_mtx_unlock(gIOObjectPortLock);
336a5e72196SApple OSS Distributions 	}
337c1dac77fSApple OSS Distributions }
338c1dac77fSApple OSS Distributions 
339a5e72196SApple OSS Distributions void
destroyUserReferences(OSObject * obj)340a5e72196SApple OSS Distributions IOUserClient::destroyUserReferences( OSObject * obj )
341a5e72196SApple OSS Distributions {
342a5e72196SApple OSS Distributions 	IOMachPort *machPort;
3431031c584SApple OSS Distributions 	bool        destroyPort;
344a5e72196SApple OSS Distributions 
345c1dac77fSApple OSS Distributions 	IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
346368ad365SApple OSS Distributions 
347368ad365SApple OSS Distributions 	// panther, 3160200
348368ad365SApple OSS Distributions 	// IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
349368ad365SApple OSS Distributions 
350368ad365SApple OSS Distributions 	obj->retain();
351a5e72196SApple OSS Distributions 	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, IKOT_IOKIT_CONNECT);
352a5e72196SApple OSS Distributions 	IOMachPortHashList *mappingBucket = NULL;
353368ad365SApple OSS Distributions 
354a5e72196SApple OSS Distributions 	lck_mtx_lock(gIOObjectPortLock);
355a5e72196SApple OSS Distributions 
356a5e72196SApple OSS Distributions 	IOUserClient * uc = OSDynamicCast(IOUserClient, obj);
357a5e72196SApple OSS Distributions 	if (uc && uc->mappings) {
358a5e72196SApple OSS Distributions 		mappingBucket = IOMachPort::bucketForObject(uc->mappings, IKOT_IOKIT_CONNECT);
359a5e72196SApple OSS Distributions 	}
360a5e72196SApple OSS Distributions 
361a5e72196SApple OSS Distributions 	machPort = IOMachPort::portForObjectInBucket(bucket, obj, IKOT_IOKIT_CONNECT);
362a5e72196SApple OSS Distributions 
363a5e72196SApple OSS Distributions 	if (machPort == NULL) {
364a5e72196SApple OSS Distributions 		lck_mtx_unlock(gIOObjectPortLock);
365a5e72196SApple OSS Distributions 		goto end;
366a5e72196SApple OSS Distributions 	}
367a5e72196SApple OSS Distributions 
368a5e72196SApple OSS Distributions 	SLIST_REMOVE(bucket, machPort, IOMachPort, link);
369a5e72196SApple OSS Distributions 	obj->taggedRelease(OSTypeID(OSCollection));
370a5e72196SApple OSS Distributions 
3711031c584SApple OSS Distributions 	destroyPort = true;
372a5e72196SApple OSS Distributions 	if (uc) {
37388cc0b97SApple OSS Distributions 		uc->noMoreSenders();
374a5e72196SApple OSS Distributions 		if (uc->mappings) {
375a5e72196SApple OSS Distributions 			uc->mappings->taggedRetain(OSTypeID(OSCollection));
376a5e72196SApple OSS Distributions 			SLIST_INSERT_HEAD(mappingBucket, machPort, link);
3771031c584SApple OSS Distributions 
3781031c584SApple OSS Distributions 			IOLockLock(&machPort->lock);
3791031c584SApple OSS Distributions 			machPort->object = uc->mappings;
3801031c584SApple OSS Distributions 			IOLockUnlock(&machPort->lock);
381a5e72196SApple OSS Distributions 
382a5e72196SApple OSS Distributions 			lck_mtx_unlock(gIOObjectPortLock);
383368ad365SApple OSS Distributions 
384e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(uc->mappings);
3851031c584SApple OSS Distributions 			destroyPort = false;
386368ad365SApple OSS Distributions 		}
387c1dac77fSApple OSS Distributions 	}
388c1dac77fSApple OSS Distributions 
3891031c584SApple OSS Distributions 	if (destroyPort) {
3901031c584SApple OSS Distributions 		IOLockLock(&machPort->lock);
3911031c584SApple OSS Distributions 		iokit_remove_object_port(machPort->port, IKOT_IOKIT_CONNECT);
3921031c584SApple OSS Distributions 		machPort->object = NULL;
3931031c584SApple OSS Distributions 		IOLockUnlock(&machPort->lock);
3941031c584SApple OSS Distributions 
3951031c584SApple OSS Distributions 		lck_mtx_unlock(gIOObjectPortLock);
3961031c584SApple OSS Distributions 		OS_ANALYZER_SUPPRESS("77508635") OSSafeReleaseNULL(machPort);
3971031c584SApple OSS Distributions 	}
398a5e72196SApple OSS Distributions 
399a5e72196SApple OSS Distributions end:
400e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(obj);
401a5e72196SApple OSS Distributions }
402a5e72196SApple OSS Distributions 
403a5e72196SApple OSS Distributions mach_port_name_t
makeSendRightForTask(task_t task,io_object_t obj,ipc_kobject_type_t type)404a5e72196SApple OSS Distributions IOMachPort::makeSendRightForTask( task_t task,
405c1dac77fSApple OSS Distributions     io_object_t obj, ipc_kobject_type_t type )
406c1dac77fSApple OSS Distributions {
407a5e72196SApple OSS Distributions 	return iokit_make_send_right( task, obj, type );
408c1dac77fSApple OSS Distributions }
409c1dac77fSApple OSS Distributions 
410a5e72196SApple OSS Distributions void
free(void)411a5e72196SApple OSS Distributions IOMachPort::free( void )
412c1dac77fSApple OSS Distributions {
413a5e72196SApple OSS Distributions 	if (port) {
4141031c584SApple OSS Distributions 		iokit_destroy_object_port(port, iokit_port_type(port));
415a5e72196SApple OSS Distributions 	}
4161031c584SApple OSS Distributions 	IOLockInlineDestroy(&lock);
417c1dac77fSApple OSS Distributions 	super::free();
418c1dac77fSApple OSS Distributions }
419c1dac77fSApple OSS Distributions 
420c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
421c1dac77fSApple OSS Distributions 
422bb611c8fSApple OSS Distributions static bool
IOTaskRegistryCompatibility(task_t task)423bb611c8fSApple OSS Distributions IOTaskRegistryCompatibility(task_t task)
424bb611c8fSApple OSS Distributions {
425bb611c8fSApple OSS Distributions 	return false;
426bb611c8fSApple OSS Distributions }
427bb611c8fSApple OSS Distributions 
428bb611c8fSApple OSS Distributions static void
IOTaskRegistryCompatibilityMatching(task_t task,OSDictionary * matching)429bb611c8fSApple OSS Distributions IOTaskRegistryCompatibilityMatching(task_t task, OSDictionary * matching)
430bb611c8fSApple OSS Distributions {
431e6231be0SApple OSS Distributions 	matching->setObject(gIOServiceNotificationUserKey, kOSBooleanTrue);
432bb611c8fSApple OSS Distributions 	if (!IOTaskRegistryCompatibility(task)) {
433bb611c8fSApple OSS Distributions 		return;
434bb611c8fSApple OSS Distributions 	}
435bb611c8fSApple OSS Distributions 	matching->setObject(gIOCompatibilityMatchKey, kOSBooleanTrue);
436bb611c8fSApple OSS Distributions }
437bb611c8fSApple OSS Distributions 
438bb611c8fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
439bb611c8fSApple OSS Distributions 
OSDefineMetaClassAndStructors(IOUserIterator,OSIterator)4408dd02465SApple OSS Distributions OSDefineMetaClassAndStructors( IOUserIterator, OSIterator )
4418dd02465SApple OSS Distributions 
4428dd02465SApple OSS Distributions IOUserIterator *
4438dd02465SApple OSS Distributions IOUserIterator::withIterator(OSIterator * iter)
4448dd02465SApple OSS Distributions {
4458dd02465SApple OSS Distributions 	IOUserIterator * me;
4468dd02465SApple OSS Distributions 
447a5e72196SApple OSS Distributions 	if (!iter) {
448a5e72196SApple OSS Distributions 		return NULL;
449a5e72196SApple OSS Distributions 	}
4508dd02465SApple OSS Distributions 
4518dd02465SApple OSS Distributions 	me = new IOUserIterator;
452a5e72196SApple OSS Distributions 	if (me && !me->init()) {
4538dd02465SApple OSS Distributions 		me->release();
454a5e72196SApple OSS Distributions 		me = NULL;
4558dd02465SApple OSS Distributions 	}
456a5e72196SApple OSS Distributions 	if (!me) {
457e6231be0SApple OSS Distributions 		iter->release();
458a5e72196SApple OSS Distributions 		return me;
459a5e72196SApple OSS Distributions 	}
4608dd02465SApple OSS Distributions 	me->userIteratorObject = iter;
4618dd02465SApple OSS Distributions 
462a5e72196SApple OSS Distributions 	return me;
4638dd02465SApple OSS Distributions }
4648dd02465SApple OSS Distributions 
4658dd02465SApple OSS Distributions bool
init(void)4668dd02465SApple OSS Distributions IOUserIterator::init( void )
4678dd02465SApple OSS Distributions {
468a5e72196SApple OSS Distributions 	if (!OSObject::init()) {
469a5e72196SApple OSS Distributions 		return false;
470a5e72196SApple OSS Distributions 	}
4718dd02465SApple OSS Distributions 
472aca3beaaSApple OSS Distributions 	IOLockInlineInit(&lock);
473a5e72196SApple OSS Distributions 	return true;
4748dd02465SApple OSS Distributions }
4758dd02465SApple OSS Distributions 
4768dd02465SApple OSS Distributions void
free()4778dd02465SApple OSS Distributions IOUserIterator::free()
4788dd02465SApple OSS Distributions {
479a5e72196SApple OSS Distributions 	if (userIteratorObject) {
480a5e72196SApple OSS Distributions 		userIteratorObject->release();
481a5e72196SApple OSS Distributions 	}
482aca3beaaSApple OSS Distributions 	IOLockInlineDestroy(&lock);
4838dd02465SApple OSS Distributions 	OSObject::free();
4848dd02465SApple OSS Distributions }
4858dd02465SApple OSS Distributions 
4868dd02465SApple OSS Distributions void
reset()4878dd02465SApple OSS Distributions IOUserIterator::reset()
4888dd02465SApple OSS Distributions {
489aca3beaaSApple OSS Distributions 	IOLockLock(&lock);
4908dd02465SApple OSS Distributions 	assert(OSDynamicCast(OSIterator, userIteratorObject));
4918dd02465SApple OSS Distributions 	((OSIterator *)userIteratorObject)->reset();
492aca3beaaSApple OSS Distributions 	IOLockUnlock(&lock);
4938dd02465SApple OSS Distributions }
4948dd02465SApple OSS Distributions 
4958dd02465SApple OSS Distributions bool
isValid()4968dd02465SApple OSS Distributions IOUserIterator::isValid()
4978dd02465SApple OSS Distributions {
4988dd02465SApple OSS Distributions 	bool ret;
4998dd02465SApple OSS Distributions 
500aca3beaaSApple OSS Distributions 	IOLockLock(&lock);
5018dd02465SApple OSS Distributions 	assert(OSDynamicCast(OSIterator, userIteratorObject));
5028dd02465SApple OSS Distributions 	ret = ((OSIterator *)userIteratorObject)->isValid();
503aca3beaaSApple OSS Distributions 	IOLockUnlock(&lock);
5048dd02465SApple OSS Distributions 
505a5e72196SApple OSS Distributions 	return ret;
5068dd02465SApple OSS Distributions }
5078dd02465SApple OSS Distributions 
5088dd02465SApple OSS Distributions OSObject *
getNextObject()5098dd02465SApple OSS Distributions IOUserIterator::getNextObject()
5108dd02465SApple OSS Distributions {
511cc9a6355SApple OSS Distributions 	assert(false);
512a5e72196SApple OSS Distributions 	return NULL;
513cc9a6355SApple OSS Distributions }
514cc9a6355SApple OSS Distributions 
515cc9a6355SApple OSS Distributions OSObject *
copyNextObject()516cc9a6355SApple OSS Distributions IOUserIterator::copyNextObject()
517cc9a6355SApple OSS Distributions {
518cc9a6355SApple OSS Distributions 	OSObject * ret = NULL;
5198dd02465SApple OSS Distributions 
520aca3beaaSApple OSS Distributions 	IOLockLock(&lock);
521cc9a6355SApple OSS Distributions 	if (userIteratorObject) {
5228dd02465SApple OSS Distributions 		ret = ((OSIterator *)userIteratorObject)->getNextObject();
523a5e72196SApple OSS Distributions 		if (ret) {
524a5e72196SApple OSS Distributions 			ret->retain();
525a5e72196SApple OSS Distributions 		}
526cc9a6355SApple OSS Distributions 	}
527aca3beaaSApple OSS Distributions 	IOLockUnlock(&lock);
5288dd02465SApple OSS Distributions 
529a5e72196SApple OSS Distributions 	return ret;
5308dd02465SApple OSS Distributions }
5318dd02465SApple OSS Distributions 
5328dd02465SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
533c1dac77fSApple OSS Distributions extern "C" {
534c1dac77fSApple OSS Distributions // functions called from osfmk/device/iokit_rpc.c
535c1dac77fSApple OSS Distributions 
536c1dac77fSApple OSS Distributions void
iokit_port_object_description(io_object_t obj,kobject_description_t desc)537bb611c8fSApple OSS Distributions iokit_port_object_description(io_object_t obj, kobject_description_t desc)
538bb611c8fSApple OSS Distributions {
539bb611c8fSApple OSS Distributions 	IORegistryEntry    * regEntry;
540bb611c8fSApple OSS Distributions 	IOUserNotification * __unused noti;
541bb611c8fSApple OSS Distributions 	_IOServiceNotifier * __unused serviceNoti;
542bb611c8fSApple OSS Distributions 	OSSerialize        * __unused s;
543e6231be0SApple OSS Distributions 	OSDictionary       * __unused matching = NULL;
544bb611c8fSApple OSS Distributions 
545bb611c8fSApple OSS Distributions 	if ((regEntry = OSDynamicCast(IORegistryEntry, obj))) {
546bb611c8fSApple OSS Distributions 		snprintf(desc, KOBJECT_DESCRIPTION_LENGTH, "%s(0x%qx)", obj->getMetaClass()->getClassName(), regEntry->getRegistryEntryID());
547bb611c8fSApple OSS Distributions #if DEVELOPMENT || DEBUG
548e6231be0SApple OSS Distributions 	} else if ((noti = OSDynamicCast(IOUserNotification, obj))) {
549e6231be0SApple OSS Distributions 		// serviceNoti->matching may become NULL if the port gets a no-senders notification, so we have to lock gIOObjectPortLock
550e6231be0SApple OSS Distributions 		IOLockLock(gIOObjectPortLock);
551e6231be0SApple OSS Distributions 		serviceNoti = OSDynamicCast(_IOServiceNotifier, noti->userIteratorObject);
552e6231be0SApple OSS Distributions 		if (serviceNoti && (matching = serviceNoti->matching)) {
553e6231be0SApple OSS Distributions 			matching->retain();
554e6231be0SApple OSS Distributions 		}
555e6231be0SApple OSS Distributions 		IOLockUnlock(gIOObjectPortLock);
556e6231be0SApple OSS Distributions 
557e6231be0SApple OSS Distributions 		if (matching) {
558bb611c8fSApple OSS Distributions 			s = OSSerialize::withCapacity((unsigned int) page_size);
559e6231be0SApple OSS Distributions 			if (s && matching->serialize(s)) {
560bb611c8fSApple OSS Distributions 				snprintf(desc, KOBJECT_DESCRIPTION_LENGTH, "%s(%s)", obj->getMetaClass()->getClassName(), s->text());
561bb611c8fSApple OSS Distributions 			}
562bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(s);
563e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(matching);
564e6231be0SApple OSS Distributions 		}
565bb611c8fSApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
566bb611c8fSApple OSS Distributions 	} else {
567bb611c8fSApple OSS Distributions 		snprintf(desc, KOBJECT_DESCRIPTION_LENGTH, "%s", obj->getMetaClass()->getClassName());
568bb611c8fSApple OSS Distributions 	}
569bb611c8fSApple OSS Distributions }
570bb611c8fSApple OSS Distributions 
571bb611c8fSApple OSS Distributions // FIXME: Implementation of these functions are hidden from the static analyzer.
572bb611c8fSApple OSS Distributions // As for now, the analyzer doesn't consistently support wrapper functions
573bb611c8fSApple OSS Distributions // for retain and release.
574bb611c8fSApple OSS Distributions #ifndef __clang_analyzer__
575bb611c8fSApple OSS Distributions void
iokit_add_reference(io_object_t obj,natural_t type)576bb611c8fSApple OSS Distributions iokit_add_reference( io_object_t obj, natural_t type )
577c1dac77fSApple OSS Distributions {
578a5e72196SApple OSS Distributions 	if (!obj) {
579a5e72196SApple OSS Distributions 		return;
580a5e72196SApple OSS Distributions 	}
581c1dac77fSApple OSS Distributions 	obj->retain();
582c1dac77fSApple OSS Distributions }
583c1dac77fSApple OSS Distributions 
584c1dac77fSApple OSS Distributions void
iokit_remove_reference(io_object_t obj)585c1dac77fSApple OSS Distributions iokit_remove_reference( io_object_t obj )
586c1dac77fSApple OSS Distributions {
587a5e72196SApple OSS Distributions 	if (obj) {
588c1dac77fSApple OSS Distributions 		obj->release();
589c1dac77fSApple OSS Distributions 	}
590a5e72196SApple OSS Distributions }
591bb611c8fSApple OSS Distributions #endif // __clang_analyzer__
592c1dac77fSApple OSS Distributions 
59388cc0b97SApple OSS Distributions void
iokit_remove_connect_reference(LIBKERN_CONSUMED io_object_t obj)594e6231be0SApple OSS Distributions iokit_remove_connect_reference(LIBKERN_CONSUMED io_object_t obj )
59588cc0b97SApple OSS Distributions {
596a5e72196SApple OSS Distributions 	if (!obj) {
597a5e72196SApple OSS Distributions 		return;
598a5e72196SApple OSS Distributions 	}
59994d3b452SApple OSS Distributions 	obj->release();
60094d3b452SApple OSS Distributions }
60188cc0b97SApple OSS Distributions 
60294d3b452SApple OSS Distributions enum {
60394d3b452SApple OSS Distributions 	kIPCLockNone  = 0,
60494d3b452SApple OSS Distributions 	kIPCLockRead  = 1,
60594d3b452SApple OSS Distributions 	kIPCLockWrite = 2
60694d3b452SApple OSS Distributions };
60794d3b452SApple OSS Distributions 
60894d3b452SApple OSS Distributions void
ipcEnter(int locking)60994d3b452SApple OSS Distributions IOUserClient::ipcEnter(int locking)
61094d3b452SApple OSS Distributions {
61194d3b452SApple OSS Distributions 	switch (locking) {
61294d3b452SApple OSS Distributions 	case kIPCLockWrite:
61394d3b452SApple OSS Distributions 		IORWLockWrite(&lock);
61494d3b452SApple OSS Distributions 		break;
61594d3b452SApple OSS Distributions 	case kIPCLockRead:
61694d3b452SApple OSS Distributions 		IORWLockRead(&lock);
61794d3b452SApple OSS Distributions 		break;
61894d3b452SApple OSS Distributions 	case kIPCLockNone:
61994d3b452SApple OSS Distributions 		break;
62094d3b452SApple OSS Distributions 	default:
62194d3b452SApple OSS Distributions 		panic("ipcEnter");
62294d3b452SApple OSS Distributions 	}
62394d3b452SApple OSS Distributions 
62494d3b452SApple OSS Distributions 	OSIncrementAtomic(&__ipc);
62594d3b452SApple OSS Distributions }
62694d3b452SApple OSS Distributions 
62794d3b452SApple OSS Distributions void
ipcExit(int locking)62894d3b452SApple OSS Distributions IOUserClient::ipcExit(int locking)
62994d3b452SApple OSS Distributions {
63094d3b452SApple OSS Distributions 	bool finalize = false;
63194d3b452SApple OSS Distributions 
63294d3b452SApple OSS Distributions 	assert(__ipc);
63394d3b452SApple OSS Distributions 	if (1 == OSDecrementAtomic(&__ipc) && isInactive()) {
63488cc0b97SApple OSS Distributions 		IOLockLock(gIOObjectPortLock);
63594d3b452SApple OSS Distributions 		if ((finalize = __ipcFinal)) {
63694d3b452SApple OSS Distributions 			__ipcFinal = false;
637a5e72196SApple OSS Distributions 		}
63888cc0b97SApple OSS Distributions 		IOLockUnlock(gIOObjectPortLock);
639a5e72196SApple OSS Distributions 		if (finalize) {
64094d3b452SApple OSS Distributions 			scheduleFinalize(true);
641a5e72196SApple OSS Distributions 		}
64288cc0b97SApple OSS Distributions 	}
64394d3b452SApple OSS Distributions 	switch (locking) {
64494d3b452SApple OSS Distributions 	case kIPCLockWrite:
64594d3b452SApple OSS Distributions 	case kIPCLockRead:
64694d3b452SApple OSS Distributions 		IORWLockUnlock(&lock);
64794d3b452SApple OSS Distributions 		break;
64894d3b452SApple OSS Distributions 	case kIPCLockNone:
64994d3b452SApple OSS Distributions 		break;
65094d3b452SApple OSS Distributions 	default:
65194d3b452SApple OSS Distributions 		panic("ipcExit");
65294d3b452SApple OSS Distributions 	}
65388cc0b97SApple OSS Distributions }
65488cc0b97SApple OSS Distributions 
6551031c584SApple OSS Distributions void
iokit_kobject_retain(io_kobject_t machPort)6561031c584SApple OSS Distributions iokit_kobject_retain(io_kobject_t machPort)
6571031c584SApple OSS Distributions {
6581031c584SApple OSS Distributions 	assert(OSDynamicCast(IOMachPort, machPort));
6591031c584SApple OSS Distributions 	machPort->retain();
6601031c584SApple OSS Distributions }
6611031c584SApple OSS Distributions 
6621031c584SApple OSS Distributions io_object_t
iokit_copy_object_for_consumed_kobject(LIBKERN_CONSUMED io_kobject_t machPort,natural_t type)6631031c584SApple OSS Distributions iokit_copy_object_for_consumed_kobject(LIBKERN_CONSUMED io_kobject_t machPort, natural_t type)
6641031c584SApple OSS Distributions {
6651031c584SApple OSS Distributions 	io_object_t  result;
6661031c584SApple OSS Distributions 
6671031c584SApple OSS Distributions 	assert(OSDynamicCast(IOMachPort, machPort));
6681031c584SApple OSS Distributions 
6691031c584SApple OSS Distributions 	IOLockLock(&machPort->lock);
6701031c584SApple OSS Distributions 	result = machPort->object;
6711031c584SApple OSS Distributions 	if (result) {
6721031c584SApple OSS Distributions 		iokit_add_reference(result, type);
6731031c584SApple OSS Distributions 	}
6741031c584SApple OSS Distributions 	IOLockUnlock(&machPort->lock);
6751031c584SApple OSS Distributions 	machPort->release();
6761031c584SApple OSS Distributions 	return result;
6771031c584SApple OSS Distributions }
6781031c584SApple OSS Distributions 
67988cc0b97SApple OSS Distributions bool
finalizeUserReferences(OSObject * obj)68088cc0b97SApple OSS Distributions IOUserClient::finalizeUserReferences(OSObject * obj)
68188cc0b97SApple OSS Distributions {
68288cc0b97SApple OSS Distributions 	IOUserClient * uc;
68388cc0b97SApple OSS Distributions 	bool           ok = true;
68488cc0b97SApple OSS Distributions 
685a5e72196SApple OSS Distributions 	if ((uc = OSDynamicCast(IOUserClient, obj))) {
68688cc0b97SApple OSS Distributions 		IOLockLock(gIOObjectPortLock);
687a5e72196SApple OSS Distributions 		if ((uc->__ipcFinal = (0 != uc->__ipc))) {
688a5e72196SApple OSS Distributions 			ok = false;
689a5e72196SApple OSS Distributions 		}
69088cc0b97SApple OSS Distributions 		IOLockUnlock(gIOObjectPortLock);
69188cc0b97SApple OSS Distributions 	}
692a5e72196SApple OSS Distributions 	return ok;
69388cc0b97SApple OSS Distributions }
69488cc0b97SApple OSS Distributions 
695c1dac77fSApple OSS Distributions ipc_port_t
iokit_port_for_object(io_object_t obj,ipc_kobject_type_t type,ipc_kobject_t * kobj)6961031c584SApple OSS Distributions iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type, ipc_kobject_t * kobj )
697c1dac77fSApple OSS Distributions {
698a5e72196SApple OSS Distributions 	IOMachPort *machPort = NULL;
699a5e72196SApple OSS Distributions 	ipc_port_t   port = NULL;
700c1dac77fSApple OSS Distributions 
701a5e72196SApple OSS Distributions 	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, type);
702fad439e7SApple OSS Distributions 
703a5e72196SApple OSS Distributions 	lck_mtx_lock(gIOObjectPortLock);
704a5e72196SApple OSS Distributions 
705a5e72196SApple OSS Distributions 	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
706a5e72196SApple OSS Distributions 
707a5e72196SApple OSS Distributions 	if (__improbable(machPort == NULL)) {
708a5e72196SApple OSS Distributions 		machPort = IOMachPort::withObjectAndType(obj, type);
709a5e72196SApple OSS Distributions 		if (__improbable(machPort == NULL)) {
710a5e72196SApple OSS Distributions 			goto end;
711a5e72196SApple OSS Distributions 		}
712a5e72196SApple OSS Distributions 		SLIST_INSERT_HEAD(bucket, machPort, link);
713a5e72196SApple OSS Distributions 	} else {
714a5e72196SApple OSS Distributions 		machPort->mscount++;
715a5e72196SApple OSS Distributions 	}
716a5e72196SApple OSS Distributions 
717a5e72196SApple OSS Distributions 	iokit_retain_port(machPort->port);
718fad439e7SApple OSS Distributions 	port = machPort->port;
719fad439e7SApple OSS Distributions 
720a5e72196SApple OSS Distributions end:
7211031c584SApple OSS Distributions 	if (kobj) {
7221031c584SApple OSS Distributions 		*kobj = machPort;
7231031c584SApple OSS Distributions 	}
724a5e72196SApple OSS Distributions 	lck_mtx_unlock(gIOObjectPortLock);
725fad439e7SApple OSS Distributions 
726a5e72196SApple OSS Distributions 	return port;
727c1dac77fSApple OSS Distributions }
728c1dac77fSApple OSS Distributions 
729c1dac77fSApple OSS Distributions kern_return_t
iokit_client_died(io_object_t obj,ipc_port_t,ipc_kobject_type_t type,mach_port_mscount_t * mscount)730c1dac77fSApple OSS Distributions iokit_client_died( io_object_t obj, ipc_port_t /* port */,
731fad439e7SApple OSS Distributions     ipc_kobject_type_t type, mach_port_mscount_t * mscount )
732c1dac77fSApple OSS Distributions {
733c1dac77fSApple OSS Distributions 	IOUserClient *      client;
734c1dac77fSApple OSS Distributions 	IOMemoryMap *       map;
735368ad365SApple OSS Distributions 	IOUserNotification * notify;
736bb611c8fSApple OSS Distributions 	IOUserServerCheckInToken * token;
737c1dac77fSApple OSS Distributions 
738a5e72196SApple OSS Distributions 	if (!IOMachPort::noMoreSendersForObject( obj, type, mscount )) {
739a5e72196SApple OSS Distributions 		return kIOReturnNotReady;
740a5e72196SApple OSS Distributions 	}
741fad439e7SApple OSS Distributions 
742bb611c8fSApple OSS Distributions 	switch (type) {
743bb611c8fSApple OSS Distributions 	case IKOT_IOKIT_CONNECT:
744a5e72196SApple OSS Distributions 		if ((client = OSDynamicCast( IOUserClient, obj ))) {
745855239e5SApple OSS Distributions 			IOStatisticsClientCall();
746aca3beaaSApple OSS Distributions 			IORWLockWrite(&client->lock);
747c1dac77fSApple OSS Distributions 			client->clientDied();
748aca3beaaSApple OSS Distributions 			IORWLockUnlock(&client->lock);
749368ad365SApple OSS Distributions 		}
750bb611c8fSApple OSS Distributions 		break;
751bb611c8fSApple OSS Distributions 	case IKOT_IOKIT_OBJECT:
752a5e72196SApple OSS Distributions 		if ((map = OSDynamicCast( IOMemoryMap, obj ))) {
753c1dac77fSApple OSS Distributions 			map->taskDied();
754a5e72196SApple OSS Distributions 		} else if ((notify = OSDynamicCast( IOUserNotification, obj ))) {
755a5e72196SApple OSS Distributions 			notify->setNotification( NULL );
756a5e72196SApple OSS Distributions 		}
757bb611c8fSApple OSS Distributions 		break;
758bb611c8fSApple OSS Distributions 	case IKOT_IOKIT_IDENT:
759bb611c8fSApple OSS Distributions 		if ((token = OSDynamicCast( IOUserServerCheckInToken, obj ))) {
760e6231be0SApple OSS Distributions 			token->cancel();
761bb611c8fSApple OSS Distributions 		}
762bb611c8fSApple OSS Distributions 		break;
763368ad365SApple OSS Distributions 	}
764c1dac77fSApple OSS Distributions 
765a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
766c1dac77fSApple OSS Distributions }
767c1dac77fSApple OSS Distributions };      /* extern "C" */
768c1dac77fSApple OSS Distributions 
769c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
770c1dac77fSApple OSS Distributions 
771368ad365SApple OSS Distributions class IOServiceUserNotification : public IOUserNotification
772c1dac77fSApple OSS Distributions {
773a5e72196SApple OSS Distributions 	OSDeclareDefaultStructors(IOServiceUserNotification);
774c1dac77fSApple OSS Distributions 
775aca3beaaSApple OSS Distributions 	struct PingMsgKdata {
776c1dac77fSApple OSS Distributions 		mach_msg_header_t               msgHdr;
777aca3beaaSApple OSS Distributions 	};
778aca3beaaSApple OSS Distributions 	struct PingMsgUdata {
779e13b1fa5SApple OSS Distributions 		OSNotificationHeader64          notifyHeader;
780c1dac77fSApple OSS Distributions 	};
781c1dac77fSApple OSS Distributions 
78214e3d835SApple OSS Distributions 	enum { kMaxOutstanding = 1024 };
783c1dac77fSApple OSS Distributions 
784e6231be0SApple OSS Distributions 	ipc_port_t          remotePort;
785e6231be0SApple OSS Distributions 	void                *msgReference;
786e6231be0SApple OSS Distributions 	mach_msg_size_t     msgReferenceSize;
787e6231be0SApple OSS Distributions 	natural_t           msgType;
788c1dac77fSApple OSS Distributions 	OSArray     *       newSet;
789c1dac77fSApple OSS Distributions 	bool                armed;
79088cc0b97SApple OSS Distributions 	bool                ipcLogged;
791c1dac77fSApple OSS Distributions 
792c1dac77fSApple OSS Distributions public:
793c1dac77fSApple OSS Distributions 
794c1dac77fSApple OSS Distributions 	virtual bool init( mach_port_t port, natural_t type,
795e13b1fa5SApple OSS Distributions 	    void * reference, vm_size_t referenceSize,
796e13b1fa5SApple OSS Distributions 	    bool clientIs64 );
7970f3703acSApple OSS Distributions 	virtual void free() APPLE_KEXT_OVERRIDE;
79876e12aa3SApple OSS Distributions 	void invalidatePort(void);
799c1dac77fSApple OSS Distributions 
800c1dac77fSApple OSS Distributions 	static bool _handler( void * target,
8013ca3bd55SApple OSS Distributions 	    void * ref, IOService * newService, IONotifier * notifier );
802c1dac77fSApple OSS Distributions 	virtual bool handler( void * ref, IOService * newService );
803c1dac77fSApple OSS Distributions 
8040f3703acSApple OSS Distributions 	virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
805cc9a6355SApple OSS Distributions 	virtual OSObject * copyNextObject() APPLE_KEXT_OVERRIDE;
806c1dac77fSApple OSS Distributions };
807c1dac77fSApple OSS Distributions 
808c1dac77fSApple OSS Distributions class IOServiceMessageUserNotification : public IOUserNotification
809c1dac77fSApple OSS Distributions {
810a5e72196SApple OSS Distributions 	OSDeclareDefaultStructors(IOServiceMessageUserNotification);
811c1dac77fSApple OSS Distributions 
812aca3beaaSApple OSS Distributions 	struct PingMsgKdata {
813368ad365SApple OSS Distributions 		mach_msg_header_t               msgHdr;
814368ad365SApple OSS Distributions 		mach_msg_body_t                 msgBody;
815368ad365SApple OSS Distributions 		mach_msg_port_descriptor_t      ports[1];
816aca3beaaSApple OSS Distributions 	};
817aca3beaaSApple OSS Distributions 	struct PingMsgUdata {
8183ca3bd55SApple OSS Distributions 		OSNotificationHeader64          notifyHeader __attribute__ ((packed));
819368ad365SApple OSS Distributions 	};
820368ad365SApple OSS Distributions 
821e6231be0SApple OSS Distributions 	ipc_port_t          remotePort;
822e6231be0SApple OSS Distributions 	void                *msgReference;
823e6231be0SApple OSS Distributions 	mach_msg_size_t     msgReferenceSize;
824e6231be0SApple OSS Distributions 	mach_msg_size_t     msgExtraSize;
825e6231be0SApple OSS Distributions 	natural_t           msgType;
826e13b1fa5SApple OSS Distributions 	uint8_t             clientIs64;
827e13b1fa5SApple OSS Distributions 	int                 owningPID;
82888cc0b97SApple OSS Distributions 	bool                ipcLogged;
829368ad365SApple OSS Distributions 
830c1dac77fSApple OSS Distributions public:
831c1dac77fSApple OSS Distributions 
832c1dac77fSApple OSS Distributions 	virtual bool init( mach_port_t port, natural_t type,
833e13b1fa5SApple OSS Distributions 	    void * reference, vm_size_t referenceSize,
834e13b1fa5SApple OSS Distributions 	    bool clientIs64 );
835e13b1fa5SApple OSS Distributions 
8360f3703acSApple OSS Distributions 	virtual void free() APPLE_KEXT_OVERRIDE;
83776e12aa3SApple OSS Distributions 	void invalidatePort(void);
838c1dac77fSApple OSS Distributions 
839c1dac77fSApple OSS Distributions 	static IOReturn _handler( void * target, void * ref,
840c1dac77fSApple OSS Distributions 	    UInt32 messageType, IOService * provider,
841c1dac77fSApple OSS Distributions 	    void * messageArgument, vm_size_t argSize );
842c1dac77fSApple OSS Distributions 	virtual IOReturn handler( void * ref,
843c1dac77fSApple OSS Distributions 	    UInt32 messageType, IOService * provider,
844c1dac77fSApple OSS Distributions 	    void * messageArgument, vm_size_t argSize );
845c1dac77fSApple OSS Distributions 
8460f3703acSApple OSS Distributions 	virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
847cc9a6355SApple OSS Distributions 	virtual OSObject * copyNextObject() APPLE_KEXT_OVERRIDE;
848c1dac77fSApple OSS Distributions };
849c1dac77fSApple OSS Distributions 
850c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
851c1dac77fSApple OSS Distributions 
852c1dac77fSApple OSS Distributions #undef super
8538dd02465SApple OSS Distributions #define super IOUserIterator
854a5e72196SApple OSS Distributions OSDefineMetaClass( IOUserNotification, IOUserIterator );
855a5e72196SApple OSS Distributions OSDefineAbstractStructors( IOUserNotification, IOUserIterator );
856c1dac77fSApple OSS Distributions 
857c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
858c1dac77fSApple OSS Distributions 
859a5e72196SApple OSS Distributions void
free(void)860a5e72196SApple OSS Distributions IOUserNotification::free( void )
861c1dac77fSApple OSS Distributions {
862e6231be0SApple OSS Distributions #if DEVELOPMENT || DEBUG
863e6231be0SApple OSS Distributions 	IOLockLock( gIOObjectPortLock);
864e6231be0SApple OSS Distributions 
865e6231be0SApple OSS Distributions 	assert(userIteratorObject == NULL);
866e6231be0SApple OSS Distributions 
867e6231be0SApple OSS Distributions 	IOLockUnlock( gIOObjectPortLock);
868e6231be0SApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
869c1dac77fSApple OSS Distributions 
870c1dac77fSApple OSS Distributions 	super::free();
871c1dac77fSApple OSS Distributions }
872c1dac77fSApple OSS Distributions 
873c1dac77fSApple OSS Distributions 
874a5e72196SApple OSS Distributions void
setNotification(IONotifier * notify)875a5e72196SApple OSS Distributions IOUserNotification::setNotification( IONotifier * notify )
876c1dac77fSApple OSS Distributions {
8778dd02465SApple OSS Distributions 	OSObject * previousNotify;
878c1dac77fSApple OSS Distributions 
879e6231be0SApple OSS Distributions 	/*
880e6231be0SApple OSS Distributions 	 * We must retain this object here before proceeding.
881e6231be0SApple OSS Distributions 	 * Two threads may race in setNotification(). If one thread sets a new notifier while the
882e6231be0SApple OSS Distributions 	 * other thread sets the notifier to NULL, it is possible for the second thread to call release()
883e6231be0SApple OSS Distributions 	 * before the first thread calls retain(). Without the retain here, this thread interleaving
884e6231be0SApple OSS Distributions 	 * would cause the object to get released and freed before it is retained by the first thread,
885e6231be0SApple OSS Distributions 	 * which is a UaF.
886e6231be0SApple OSS Distributions 	 */
887e6231be0SApple OSS Distributions 	retain();
888e6231be0SApple OSS Distributions 
889368ad365SApple OSS Distributions 	IOLockLock( gIOObjectPortLock);
890368ad365SApple OSS Distributions 
891e6231be0SApple OSS Distributions 	previousNotify = userIteratorObject;
892e6231be0SApple OSS Distributions 	userIteratorObject = notify;
893368ad365SApple OSS Distributions 
894368ad365SApple OSS Distributions 	IOLockUnlock( gIOObjectPortLock);
895368ad365SApple OSS Distributions 
896a5e72196SApple OSS Distributions 	if (previousNotify) {
8978dd02465SApple OSS Distributions 		assert(OSDynamicCast(IONotifier, previousNotify));
8988dd02465SApple OSS Distributions 		((IONotifier *)previousNotify)->remove();
899e6231be0SApple OSS Distributions 
900e6231be0SApple OSS Distributions 		if (notify == NULL) {
901e6231be0SApple OSS Distributions 			release();
9028dd02465SApple OSS Distributions 		}
903e6231be0SApple OSS Distributions 	} else if (notify) {
904e6231be0SApple OSS Distributions 		// new IONotifier, retain the object. release() will happen in setNotification(NULL)
905e6231be0SApple OSS Distributions 		retain();
906e6231be0SApple OSS Distributions 	}
907e6231be0SApple OSS Distributions 
908e6231be0SApple OSS Distributions 	release(); // paired with retain() at beginning of this method
909c1dac77fSApple OSS Distributions }
910c1dac77fSApple OSS Distributions 
911a5e72196SApple OSS Distributions void
reset()912a5e72196SApple OSS Distributions IOUserNotification::reset()
913c1dac77fSApple OSS Distributions {
914c1dac77fSApple OSS Distributions 	// ?
915c1dac77fSApple OSS Distributions }
916c1dac77fSApple OSS Distributions 
917a5e72196SApple OSS Distributions bool
isValid()918a5e72196SApple OSS Distributions IOUserNotification::isValid()
919c1dac77fSApple OSS Distributions {
920a5e72196SApple OSS Distributions 	return true;
921c1dac77fSApple OSS Distributions }
922c1dac77fSApple OSS Distributions 
923c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
924c1dac77fSApple OSS Distributions 
925c1dac77fSApple OSS Distributions #undef super
926c1dac77fSApple OSS Distributions #define super IOUserNotification
OSDefineMetaClassAndStructors(IOServiceUserNotification,IOUserNotification)927c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification)
928c1dac77fSApple OSS Distributions 
929c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
930c1dac77fSApple OSS Distributions 
931a5e72196SApple OSS Distributions bool
932a5e72196SApple OSS Distributions IOServiceUserNotification::init( mach_port_t port, natural_t type,
933e13b1fa5SApple OSS Distributions     void * reference, vm_size_t referenceSize,
934e13b1fa5SApple OSS Distributions     bool clientIs64 )
935c1dac77fSApple OSS Distributions {
936a5e72196SApple OSS Distributions 	if (!super::init()) {
937a5e72196SApple OSS Distributions 		return false;
938a5e72196SApple OSS Distributions 	}
939d0c1fef6SApple OSS Distributions 
940c1dac77fSApple OSS Distributions 	newSet = OSArray::withCapacity( 1 );
941a5e72196SApple OSS Distributions 	if (!newSet) {
942a5e72196SApple OSS Distributions 		return false;
943a5e72196SApple OSS Distributions 	}
944c1dac77fSApple OSS Distributions 
945a5e72196SApple OSS Distributions 	if (referenceSize > sizeof(OSAsyncReference64)) {
946a5e72196SApple OSS Distributions 		return false;
947a5e72196SApple OSS Distributions 	}
948e13b1fa5SApple OSS Distributions 
949e6231be0SApple OSS Distributions 	msgReferenceSize = mach_round_msg((mach_msg_size_t)referenceSize);
950e6231be0SApple OSS Distributions 	msgReference = IOMallocZeroData(msgReferenceSize);
951e6231be0SApple OSS Distributions 	if (!msgReference) {
952a5e72196SApple OSS Distributions 		return false;
953a5e72196SApple OSS Distributions 	}
954368ad365SApple OSS Distributions 
955e6231be0SApple OSS Distributions 	remotePort = port;
956e6231be0SApple OSS Distributions 	msgType = type;
957e6231be0SApple OSS Distributions 	bcopy( reference, msgReference, referenceSize );
958368ad365SApple OSS Distributions 
959a5e72196SApple OSS Distributions 	return true;
960c1dac77fSApple OSS Distributions }
961c1dac77fSApple OSS Distributions 
962a5e72196SApple OSS Distributions void
invalidatePort(void)963a5e72196SApple OSS Distributions IOServiceUserNotification::invalidatePort(void)
96476e12aa3SApple OSS Distributions {
965e6231be0SApple OSS Distributions 	remotePort = MACH_PORT_NULL;
96676e12aa3SApple OSS Distributions }
96776e12aa3SApple OSS Distributions 
968a5e72196SApple OSS Distributions void
free(void)969a5e72196SApple OSS Distributions IOServiceUserNotification::free( void )
970c1dac77fSApple OSS Distributions {
971e6231be0SApple OSS Distributions 	if (remotePort) {
972e6231be0SApple OSS Distributions 		iokit_release_port_send(remotePort);
973e6231be0SApple OSS Distributions 	}
974e6231be0SApple OSS Distributions 	IOFreeData(msgReference, msgReferenceSize);
975e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(newSet);
976c1dac77fSApple OSS Distributions 
977c1dac77fSApple OSS Distributions 	super::free();
978c1dac77fSApple OSS Distributions }
979c1dac77fSApple OSS Distributions 
980a5e72196SApple OSS Distributions bool
_handler(void * target,void * ref,IOService * newService,IONotifier * notifier)981a5e72196SApple OSS Distributions IOServiceUserNotification::_handler( void * target,
982a5e72196SApple OSS Distributions     void * ref, IOService * newService, IONotifier * notifier )
983a5e72196SApple OSS Distributions {
984e6231be0SApple OSS Distributions 	IOServiceUserNotification * targetObj = (IOServiceUserNotification *)target;
985e6231be0SApple OSS Distributions 	bool ret;
986e6231be0SApple OSS Distributions 
987e6231be0SApple OSS Distributions 	targetObj->retain();
988e6231be0SApple OSS Distributions 	ret = targetObj->handler( ref, newService );
989e6231be0SApple OSS Distributions 	targetObj->release();
990e6231be0SApple OSS Distributions 	return ret;
991a5e72196SApple OSS Distributions }
992a5e72196SApple OSS Distributions 
993a5e72196SApple OSS Distributions bool
handler(void * ref,IOService * newService)994a5e72196SApple OSS Distributions IOServiceUserNotification::handler( void * ref,
995c1dac77fSApple OSS Distributions     IOService * newService )
996c1dac77fSApple OSS Distributions {
997c1dac77fSApple OSS Distributions 	unsigned int        count;
998c1dac77fSApple OSS Distributions 	kern_return_t       kr;
999fad439e7SApple OSS Distributions 	ipc_port_t          port = NULL;
1000c1dac77fSApple OSS Distributions 	bool                sendPing = false;
1001aca3beaaSApple OSS Distributions 	mach_msg_size_t     msgSize, payloadSize;
1002c1dac77fSApple OSS Distributions 
1003aca3beaaSApple OSS Distributions 	IOTakeLock( &lock );
1004c1dac77fSApple OSS Distributions 
1005c1dac77fSApple OSS Distributions 	count = newSet->getCount();
1006c1dac77fSApple OSS Distributions 	if (count < kMaxOutstanding) {
1007c1dac77fSApple OSS Distributions 		newSet->setObject( newService );
1008a5e72196SApple OSS Distributions 		if ((sendPing = (armed && (0 == count)))) {
1009c1dac77fSApple OSS Distributions 			armed = false;
1010c1dac77fSApple OSS Distributions 		}
1011a5e72196SApple OSS Distributions 	}
1012c1dac77fSApple OSS Distributions 
1013aca3beaaSApple OSS Distributions 	IOUnlock( &lock );
1014c1dac77fSApple OSS Distributions 
1015e6231be0SApple OSS Distributions 	if (kIOServiceTerminatedNotificationType == msgType) {
10161031c584SApple OSS Distributions 		lck_mtx_lock(gIOObjectPortLock);
10171031c584SApple OSS Distributions 		newService->setMachPortHoldDestroy(true);
10181031c584SApple OSS Distributions 		lck_mtx_unlock(gIOObjectPortLock);
1019a5e72196SApple OSS Distributions 	}
1020368ad365SApple OSS Distributions 
1021c1dac77fSApple OSS Distributions 	if (sendPing) {
10221031c584SApple OSS Distributions 		port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT, NULL );
1023c1dac77fSApple OSS Distributions 
1024aca3beaaSApple OSS Distributions 		payloadSize = sizeof(PingMsgUdata) - sizeof(OSAsyncReference64) + msgReferenceSize;
1025aca3beaaSApple OSS Distributions 		msgSize = (mach_msg_size_t)(sizeof(PingMsgKdata) + payloadSize);
1026aca3beaaSApple OSS Distributions 
1027aca3beaaSApple OSS Distributions 		kr = kernel_mach_msg_send_with_builder_internal(0, payloadSize,
1028*8d741a5dSApple OSS Distributions 		    MACH_SEND_KERNEL_IMPORTANCE, MACH_MSG_TIMEOUT_NONE, NULL,
1029aca3beaaSApple OSS Distributions 		    ^(mach_msg_header_t *hdr, __assert_only mach_msg_descriptor_t *descs, void *payload){
1030aca3beaaSApple OSS Distributions 			PingMsgUdata *udata = (PingMsgUdata *)payload;
1031e6231be0SApple OSS Distributions 
1032aca3beaaSApple OSS Distributions 			hdr->msgh_remote_port    = remotePort;
1033aca3beaaSApple OSS Distributions 			hdr->msgh_local_port     = port;
1034aca3beaaSApple OSS Distributions 			hdr->msgh_bits           = MACH_MSGH_BITS(
1035e6231be0SApple OSS Distributions 				MACH_MSG_TYPE_COPY_SEND /*remote*/,
1036e6231be0SApple OSS Distributions 				MACH_MSG_TYPE_MAKE_SEND /*local*/);
1037aca3beaaSApple OSS Distributions 			hdr->msgh_size           = msgSize;
1038aca3beaaSApple OSS Distributions 			hdr->msgh_id             = kOSNotificationMessageID;
1039e6231be0SApple OSS Distributions 
1040aca3beaaSApple OSS Distributions 			assert(descs == NULL);
1041aca3beaaSApple OSS Distributions 			/* End of kernel processed data */
1042e6231be0SApple OSS Distributions 
1043aca3beaaSApple OSS Distributions 			udata->notifyHeader.size          = 0;
1044aca3beaaSApple OSS Distributions 			udata->notifyHeader.type          = msgType;
1045aca3beaaSApple OSS Distributions 
1046aca3beaaSApple OSS Distributions 			assert((char *)udata->notifyHeader.reference + msgReferenceSize <= (char *)payload + payloadSize);
1047aca3beaaSApple OSS Distributions 			bcopy( msgReference, udata->notifyHeader.reference, msgReferenceSize );
1048e6231be0SApple OSS Distributions 		});
1049e6231be0SApple OSS Distributions 
1050a5e72196SApple OSS Distributions 		if (port) {
1051fad439e7SApple OSS Distributions 			iokit_release_port( port );
1052a5e72196SApple OSS Distributions 		}
1053fad439e7SApple OSS Distributions 
1054a5e72196SApple OSS Distributions 		if ((KERN_SUCCESS != kr) && !ipcLogged) {
105588cc0b97SApple OSS Distributions 			ipcLogged = true;
1056e6231be0SApple OSS Distributions 			IOLog("%s: kernel_mach_msg_send (0x%x)\n", __PRETTY_FUNCTION__, kr );
105788cc0b97SApple OSS Distributions 		}
1058c1dac77fSApple OSS Distributions 	}
1059c1dac77fSApple OSS Distributions 
1060a5e72196SApple OSS Distributions 	return true;
1061c1dac77fSApple OSS Distributions }
1062a5e72196SApple OSS Distributions OSObject *
getNextObject()1063a5e72196SApple OSS Distributions IOServiceUserNotification::getNextObject()
1064c1dac77fSApple OSS Distributions {
1065cc9a6355SApple OSS Distributions 	assert(false);
1066a5e72196SApple OSS Distributions 	return NULL;
1067cc9a6355SApple OSS Distributions }
1068cc9a6355SApple OSS Distributions 
1069a5e72196SApple OSS Distributions OSObject *
copyNextObject()1070a5e72196SApple OSS Distributions IOServiceUserNotification::copyNextObject()
1071cc9a6355SApple OSS Distributions {
1072c1dac77fSApple OSS Distributions 	unsigned int        count;
1073c1dac77fSApple OSS Distributions 	OSObject *          result;
1074c1dac77fSApple OSS Distributions 
1075aca3beaaSApple OSS Distributions 	IOLockLock(&lock);
1076c1dac77fSApple OSS Distributions 
1077c1dac77fSApple OSS Distributions 	count = newSet->getCount();
1078c1dac77fSApple OSS Distributions 	if (count) {
1079c1dac77fSApple OSS Distributions 		result = newSet->getObject( count - 1 );
1080c1dac77fSApple OSS Distributions 		result->retain();
1081c1dac77fSApple OSS Distributions 		newSet->removeObject( count - 1);
1082c1dac77fSApple OSS Distributions 	} else {
1083a5e72196SApple OSS Distributions 		result = NULL;
1084c1dac77fSApple OSS Distributions 		armed = true;
1085c1dac77fSApple OSS Distributions 	}
1086c1dac77fSApple OSS Distributions 
1087aca3beaaSApple OSS Distributions 	IOLockUnlock(&lock);
108888cc0b97SApple OSS Distributions 
1089a5e72196SApple OSS Distributions 	return result;
1090c1dac77fSApple OSS Distributions }
1091c1dac77fSApple OSS Distributions 
1092c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1093c1dac77fSApple OSS Distributions 
OSDefineMetaClassAndStructors(IOServiceMessageUserNotification,IOUserNotification)1094c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification)
1095c1dac77fSApple OSS Distributions 
1096c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1097c1dac77fSApple OSS Distributions 
1098a5e72196SApple OSS Distributions bool
1099a5e72196SApple OSS Distributions IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
1100e6231be0SApple OSS Distributions     void * reference, vm_size_t referenceSize, bool client64 )
1101c1dac77fSApple OSS Distributions {
1102a5e72196SApple OSS Distributions 	if (!super::init()) {
1103a5e72196SApple OSS Distributions 		return false;
1104a5e72196SApple OSS Distributions 	}
1105368ad365SApple OSS Distributions 
1106a5e72196SApple OSS Distributions 	if (referenceSize > sizeof(OSAsyncReference64)) {
1107a5e72196SApple OSS Distributions 		return false;
1108a5e72196SApple OSS Distributions 	}
1109e13b1fa5SApple OSS Distributions 
1110e13b1fa5SApple OSS Distributions 	clientIs64 = client64;
1111e13b1fa5SApple OSS Distributions 
1112e13b1fa5SApple OSS Distributions 	owningPID = proc_selfpid();
1113e13b1fa5SApple OSS Distributions 
1114e6231be0SApple OSS Distributions 	msgReferenceSize = mach_round_msg((mach_msg_size_t)referenceSize);
1115e6231be0SApple OSS Distributions 	msgReference = IOMallocZeroData(msgReferenceSize);
1116e6231be0SApple OSS Distributions 	if (!msgReference) {
1117a5e72196SApple OSS Distributions 		return false;
1118a5e72196SApple OSS Distributions 	}
1119368ad365SApple OSS Distributions 
1120e6231be0SApple OSS Distributions 	remotePort = port;
1121e6231be0SApple OSS Distributions 	msgType = type;
1122e6231be0SApple OSS Distributions 	bcopy( reference, msgReference, referenceSize );
1123368ad365SApple OSS Distributions 
1124a5e72196SApple OSS Distributions 	return true;
1125c1dac77fSApple OSS Distributions }
1126c1dac77fSApple OSS Distributions 
1127a5e72196SApple OSS Distributions void
invalidatePort(void)1128a5e72196SApple OSS Distributions IOServiceMessageUserNotification::invalidatePort(void)
112976e12aa3SApple OSS Distributions {
1130e6231be0SApple OSS Distributions 	remotePort = MACH_PORT_NULL;
113176e12aa3SApple OSS Distributions }
113276e12aa3SApple OSS Distributions 
1133a5e72196SApple OSS Distributions void
free(void)1134a5e72196SApple OSS Distributions IOServiceMessageUserNotification::free( void )
1135c1dac77fSApple OSS Distributions {
1136e6231be0SApple OSS Distributions 	if (remotePort) {
1137e6231be0SApple OSS Distributions 		iokit_release_port_send(remotePort);
1138e6231be0SApple OSS Distributions 	}
1139e6231be0SApple OSS Distributions 	IOFreeData(msgReference, msgReferenceSize);
1140368ad365SApple OSS Distributions 
1141c1dac77fSApple OSS Distributions 	super::free();
1142d0c1fef6SApple OSS Distributions }
1143c1dac77fSApple OSS Distributions 
1144a5e72196SApple OSS Distributions IOReturn
_handler(void * target,void * ref,UInt32 messageType,IOService * provider,void * argument,vm_size_t argSize)1145a5e72196SApple OSS Distributions IOServiceMessageUserNotification::_handler( void * target, void * ref,
1146c1dac77fSApple OSS Distributions     UInt32 messageType, IOService * provider,
1147c1dac77fSApple OSS Distributions     void * argument, vm_size_t argSize )
1148c1dac77fSApple OSS Distributions {
1149e6231be0SApple OSS Distributions 	IOServiceMessageUserNotification * targetObj = (IOServiceMessageUserNotification *)target;
1150e6231be0SApple OSS Distributions 	IOReturn ret;
1151e6231be0SApple OSS Distributions 
1152e6231be0SApple OSS Distributions 	targetObj->retain();
1153e6231be0SApple OSS Distributions 	ret = targetObj->handler(
1154a5e72196SApple OSS Distributions 		ref, messageType, provider, argument, argSize);
1155e6231be0SApple OSS Distributions 	targetObj->release();
1156e6231be0SApple OSS Distributions 	return ret;
1157c1dac77fSApple OSS Distributions }
1158c1dac77fSApple OSS Distributions 
1159a5e72196SApple OSS Distributions IOReturn
handler(void * ref,UInt32 messageType,IOService * provider,void * messageArgument,vm_size_t callerArgSize)1160a5e72196SApple OSS Distributions IOServiceMessageUserNotification::handler( void * ref,
1161c1dac77fSApple OSS Distributions     UInt32 messageType, IOService * provider,
116288cc0b97SApple OSS Distributions     void * messageArgument, vm_size_t callerArgSize )
1163c1dac77fSApple OSS Distributions {
1164c1dac77fSApple OSS Distributions 	kern_return_t                kr;
116588cc0b97SApple OSS Distributions 	vm_size_t                    argSize;
1166bb611c8fSApple OSS Distributions 	mach_msg_size_t              thisMsgSize;
1167368ad365SApple OSS Distributions 	ipc_port_t                   thisPort, providerPort;
1168e13b1fa5SApple OSS Distributions 
1169a5e72196SApple OSS Distributions 	if (kIOMessageCopyClientID == messageType) {
1170d0c1fef6SApple OSS Distributions 		*((void **) messageArgument) = OSNumber::withNumber(owningPID, 32);
1171a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
1172e13b1fa5SApple OSS Distributions 	}
1173c1dac77fSApple OSS Distributions 
1174a5e72196SApple OSS Distributions 	if (callerArgSize == 0) {
1175a5e72196SApple OSS Distributions 		if (clientIs64) {
1176e6231be0SApple OSS Distributions 			argSize = sizeof(io_user_reference_t);
1177a5e72196SApple OSS Distributions 		} else {
1178a5e72196SApple OSS Distributions 			argSize = sizeof(uint32_t);
1179e13b1fa5SApple OSS Distributions 		}
1180a5e72196SApple OSS Distributions 	} else {
1181a5e72196SApple OSS Distributions 		if (callerArgSize > kIOUserNotifyMaxMessageSize) {
1182cc9a6355SApple OSS Distributions 			callerArgSize = kIOUserNotifyMaxMessageSize;
1183a5e72196SApple OSS Distributions 		}
118488cc0b97SApple OSS Distributions 		argSize = callerArgSize;
1185c1dac77fSApple OSS Distributions 	}
1186a3bb9fccSApple OSS Distributions 
1187a3bb9fccSApple OSS Distributions 	// adjust message size for ipc restrictions
1188e6231be0SApple OSS Distributions 	natural_t type = msgType;
1189a3bb9fccSApple OSS Distributions 	type &= ~(kIOKitNoticationMsgSizeMask << kIOKitNoticationTypeSizeAdjShift);
1190a3bb9fccSApple OSS Distributions 	type |= ((argSize & kIOKitNoticationMsgSizeMask) << kIOKitNoticationTypeSizeAdjShift);
1191a3bb9fccSApple OSS Distributions 	argSize = (argSize + kIOKitNoticationMsgSizeMask) & ~kIOKitNoticationMsgSizeMask;
1192a3bb9fccSApple OSS Distributions 
1193e6231be0SApple OSS Distributions 	mach_msg_size_t extraSize = kIOUserNotifyMaxMessageSize + sizeof(IOServiceInterestContent64);
1194aca3beaaSApple OSS Distributions 	mach_msg_size_t msgSize = (mach_msg_size_t) (sizeof(PingMsgKdata) +
1195aca3beaaSApple OSS Distributions 	    sizeof(PingMsgUdata) - sizeof(OSAsyncReference64) + msgReferenceSize);
1196e6231be0SApple OSS Distributions 
1197e6231be0SApple OSS Distributions 	if (os_add3_overflow(msgSize, offsetof(IOServiceInterestContent64, messageArgument), argSize, &thisMsgSize)) {
1198bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
1199bb611c8fSApple OSS Distributions 	}
1200aca3beaaSApple OSS Distributions 	mach_msg_size_t payloadSize = thisMsgSize - sizeof(PingMsgKdata);
1201c1dac77fSApple OSS Distributions 
12021031c584SApple OSS Distributions 	providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT, NULL );
12031031c584SApple OSS Distributions 	thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT, NULL );
120488cc0b97SApple OSS Distributions 
1205aca3beaaSApple OSS Distributions 	kr = kernel_mach_msg_send_with_builder_internal(1, payloadSize,
1206*8d741a5dSApple OSS Distributions 	    MACH_SEND_KERNEL_IMPORTANCE, MACH_MSG_TIMEOUT_NONE, NULL,
1207aca3beaaSApple OSS Distributions 	    ^(mach_msg_header_t *hdr, mach_msg_descriptor_t *descs, void *payload){
1208aca3beaaSApple OSS Distributions 		mach_msg_port_descriptor_t *port_desc = (mach_msg_port_descriptor_t *)descs;
1209aca3beaaSApple OSS Distributions 		PingMsgUdata *udata = (PingMsgUdata *)payload;
1210e6231be0SApple OSS Distributions 		IOServiceInterestContent64 * data;
1211aca3beaaSApple OSS Distributions 		mach_msg_size_t dataOffset;
1212e6231be0SApple OSS Distributions 
1213aca3beaaSApple OSS Distributions 		hdr->msgh_remote_port    = remotePort;
1214aca3beaaSApple OSS Distributions 		hdr->msgh_local_port     = thisPort;
1215aca3beaaSApple OSS Distributions 		hdr->msgh_bits           = MACH_MSGH_BITS_COMPLEX
1216e6231be0SApple OSS Distributions 		|  MACH_MSGH_BITS(
1217e6231be0SApple OSS Distributions 			MACH_MSG_TYPE_COPY_SEND /*remote*/,
1218e6231be0SApple OSS Distributions 			MACH_MSG_TYPE_MAKE_SEND /*local*/);
1219aca3beaaSApple OSS Distributions 		hdr->msgh_size           = thisMsgSize;
1220aca3beaaSApple OSS Distributions 		hdr->msgh_id             = kOSNotificationMessageID;
1221e6231be0SApple OSS Distributions 
1222aca3beaaSApple OSS Distributions 		/* body.msgh_descriptor_count is set automatically after the closure */
1223e6231be0SApple OSS Distributions 
1224aca3beaaSApple OSS Distributions 		port_desc[0].name              = providerPort;
1225aca3beaaSApple OSS Distributions 		port_desc[0].disposition       = MACH_MSG_TYPE_MAKE_SEND;
1226aca3beaaSApple OSS Distributions 		port_desc[0].type              = MACH_MSG_PORT_DESCRIPTOR;
1227aca3beaaSApple OSS Distributions 		/* End of kernel processed data */
1228e6231be0SApple OSS Distributions 
1229aca3beaaSApple OSS Distributions 		udata->notifyHeader.size          = extraSize;
1230aca3beaaSApple OSS Distributions 		udata->notifyHeader.type          = type;
1231aca3beaaSApple OSS Distributions 		bcopy( msgReference, udata->notifyHeader.reference, msgReferenceSize );
1232e6231be0SApple OSS Distributions 
1233aca3beaaSApple OSS Distributions 		/* data is after msgReference */
1234aca3beaaSApple OSS Distributions 		dataOffset = sizeof(PingMsgUdata) - sizeof(OSAsyncReference64) + msgReferenceSize;
1235aca3beaaSApple OSS Distributions 		data = (IOServiceInterestContent64 *) (((uint8_t *) udata) + dataOffset);
123688cc0b97SApple OSS Distributions 		data->messageType = messageType;
123788cc0b97SApple OSS Distributions 
1238a5e72196SApple OSS Distributions 		if (callerArgSize == 0) {
1239aca3beaaSApple OSS Distributions 		        assert((char *)data->messageArgument + argSize <= (char *)payload + payloadSize);
124088cc0b97SApple OSS Distributions 		        data->messageArgument[0] = (io_user_reference_t) messageArgument;
1241a5e72196SApple OSS Distributions 		        if (!clientIs64) {
124288cc0b97SApple OSS Distributions 		                data->messageArgument[0] |= (data->messageArgument[0] << 32);
124388cc0b97SApple OSS Distributions 			}
1244a5e72196SApple OSS Distributions 		} else {
1245aca3beaaSApple OSS Distributions 		        assert((char *)data->messageArgument + callerArgSize <= (char *)payload + payloadSize);
124688cc0b97SApple OSS Distributions 		        bcopy(messageArgument, data->messageArgument, callerArgSize);
124788cc0b97SApple OSS Distributions 		}
1248e6231be0SApple OSS Distributions 	});
124988cc0b97SApple OSS Distributions 
1250a5e72196SApple OSS Distributions 	if (thisPort) {
1251368ad365SApple OSS Distributions 		iokit_release_port( thisPort );
1252a5e72196SApple OSS Distributions 	}
1253a5e72196SApple OSS Distributions 	if (providerPort) {
1254368ad365SApple OSS Distributions 		iokit_release_port( providerPort );
1255a5e72196SApple OSS Distributions 	}
1256fad439e7SApple OSS Distributions 
1257e6231be0SApple OSS Distributions 	if (kr == MACH_SEND_NO_BUFFER) {
1258e6231be0SApple OSS Distributions 		return kIOReturnNoMemory;
1259a5e72196SApple OSS Distributions 	}
126088cc0b97SApple OSS Distributions 
1261a5e72196SApple OSS Distributions 	if ((KERN_SUCCESS != kr) && !ipcLogged) {
126288cc0b97SApple OSS Distributions 		ipcLogged = true;
1263e6231be0SApple OSS Distributions 		IOLog("%s: kernel_mach_msg_send (0x%x)\n", __PRETTY_FUNCTION__, kr );
126488cc0b97SApple OSS Distributions 	}
1265c1dac77fSApple OSS Distributions 
1266a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
1267c1dac77fSApple OSS Distributions }
1268c1dac77fSApple OSS Distributions 
1269a5e72196SApple OSS Distributions OSObject *
getNextObject()1270a5e72196SApple OSS Distributions IOServiceMessageUserNotification::getNextObject()
1271c1dac77fSApple OSS Distributions {
1272a5e72196SApple OSS Distributions 	return NULL;
1273c1dac77fSApple OSS Distributions }
1274c1dac77fSApple OSS Distributions 
1275a5e72196SApple OSS Distributions OSObject *
copyNextObject()1276a5e72196SApple OSS Distributions IOServiceMessageUserNotification::copyNextObject()
1277cc9a6355SApple OSS Distributions {
1278a5e72196SApple OSS Distributions 	return NULL;
1279cc9a6355SApple OSS Distributions }
1280cc9a6355SApple OSS Distributions 
1281c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1282c1dac77fSApple OSS Distributions 
1283c1dac77fSApple OSS Distributions #undef super
1284c1dac77fSApple OSS Distributions #define super IOService
1285c1dac77fSApple OSS Distributions OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
1286c1dac77fSApple OSS Distributions 
128788cc0b97SApple OSS Distributions IOLock       * gIOUserClientOwnersLock;
128888cc0b97SApple OSS Distributions 
1289aca3beaaSApple OSS Distributions static_assert(offsetof(IOUserClient, __opaque_end) -
1290aca3beaaSApple OSS Distributions     offsetof(IOUserClient, __opaque_start) == sizeof(void *) * 9,
1291aca3beaaSApple OSS Distributions     "ABI check: Opaque ivars for IOUserClient must be 9 void * big");
1292aca3beaaSApple OSS Distributions 
1293a5e72196SApple OSS Distributions void
initialize(void)1294a5e72196SApple OSS Distributions IOUserClient::initialize( void )
1295c1dac77fSApple OSS Distributions {
1296c1dac77fSApple OSS Distributions 	gIOObjectPortLock       = IOLockAlloc();
129788cc0b97SApple OSS Distributions 	gIOUserClientOwnersLock = IOLockAlloc();
1298a5e72196SApple OSS Distributions 	gIOUserServerLock       = IOLockAlloc();
129988cc0b97SApple OSS Distributions 	assert(gIOObjectPortLock && gIOUserClientOwnersLock);
1300bb611c8fSApple OSS Distributions 
1301bb611c8fSApple OSS Distributions #if IOTRACKING
1302bb611c8fSApple OSS Distributions 	IOTrackingQueueCollectUser(IOUserIterator::gMetaClass.getTracking());
1303bb611c8fSApple OSS Distributions 	IOTrackingQueueCollectUser(IOServiceMessageUserNotification::gMetaClass.getTracking());
1304bb611c8fSApple OSS Distributions 	IOTrackingQueueCollectUser(IOServiceUserNotification::gMetaClass.getTracking());
1305bb611c8fSApple OSS Distributions 	IOTrackingQueueCollectUser(IOUserClient::gMetaClass.getTracking());
1306bb611c8fSApple OSS Distributions 	IOTrackingQueueCollectUser(IOMachPort::gMetaClass.getTracking());
1307bb611c8fSApple OSS Distributions #endif /* IOTRACKING */
1308c1dac77fSApple OSS Distributions }
1309c1dac77fSApple OSS Distributions 
1310a5e72196SApple OSS Distributions void
1311bb611c8fSApple OSS Distributions #if __LP64__
1312bb611c8fSApple OSS Distributions __attribute__((__noreturn__))
1313bb611c8fSApple OSS Distributions #endif
setAsyncReference(OSAsyncReference asyncRef,mach_port_t wakePort,void * callback,void * refcon)1314a5e72196SApple OSS Distributions IOUserClient::setAsyncReference(OSAsyncReference asyncRef,
1315c1dac77fSApple OSS Distributions     mach_port_t wakePort,
1316c1dac77fSApple OSS Distributions     void *callback, void *refcon)
1317c1dac77fSApple OSS Distributions {
1318bb611c8fSApple OSS Distributions #if __LP64__
1319bb611c8fSApple OSS Distributions 	panic("setAsyncReference not valid for 64b");
1320bb611c8fSApple OSS Distributions #else
13213ca3bd55SApple OSS Distributions 	asyncRef[kIOAsyncReservedIndex]      = ((uintptr_t) wakePort)
1322e13b1fa5SApple OSS Distributions 	    | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
13233ca3bd55SApple OSS Distributions 	asyncRef[kIOAsyncCalloutFuncIndex]   = (uintptr_t) callback;
13243ca3bd55SApple OSS Distributions 	asyncRef[kIOAsyncCalloutRefconIndex] = (uintptr_t) refcon;
1325bb611c8fSApple OSS Distributions #endif
1326c1dac77fSApple OSS Distributions }
1327c1dac77fSApple OSS Distributions 
1328a5e72196SApple OSS Distributions void
setAsyncReference64(OSAsyncReference64 asyncRef,mach_port_t wakePort,mach_vm_address_t callback,io_user_reference_t refcon)1329a5e72196SApple OSS Distributions IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef,
1330e13b1fa5SApple OSS Distributions     mach_port_t wakePort,
1331e13b1fa5SApple OSS Distributions     mach_vm_address_t callback, io_user_reference_t refcon)
1332c1dac77fSApple OSS Distributions {
1333e13b1fa5SApple OSS Distributions 	asyncRef[kIOAsyncReservedIndex]      = ((io_user_reference_t) wakePort)
1334e13b1fa5SApple OSS Distributions 	    | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
1335e13b1fa5SApple OSS Distributions 	asyncRef[kIOAsyncCalloutFuncIndex]   = (io_user_reference_t) callback;
1336e13b1fa5SApple OSS Distributions 	asyncRef[kIOAsyncCalloutRefconIndex] = refcon;
1337368ad365SApple OSS Distributions }
1338e13b1fa5SApple OSS Distributions 
1339a5e72196SApple OSS Distributions void
setAsyncReference64(OSAsyncReference64 asyncRef,mach_port_t wakePort,mach_vm_address_t callback,io_user_reference_t refcon,task_t task)1340a5e72196SApple OSS Distributions IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef,
1341186b8fceSApple OSS Distributions     mach_port_t wakePort,
1342186b8fceSApple OSS Distributions     mach_vm_address_t callback, io_user_reference_t refcon, task_t task)
1343186b8fceSApple OSS Distributions {
1344186b8fceSApple OSS Distributions 	setAsyncReference64(asyncRef, wakePort, callback, refcon);
1345186b8fceSApple OSS Distributions 	if (vm_map_is_64bit(get_task_map(task))) {
1346186b8fceSApple OSS Distributions 		asyncRef[kIOAsyncReservedIndex] |= kIOUCAsync64Flag;
1347186b8fceSApple OSS Distributions 	}
1348186b8fceSApple OSS Distributions }
1349186b8fceSApple OSS Distributions 
1350a5e72196SApple OSS Distributions static OSDictionary *
CopyConsoleUser(UInt32 uid)1351a5e72196SApple OSS Distributions CopyConsoleUser(UInt32 uid)
1352368ad365SApple OSS Distributions {
1353368ad365SApple OSS Distributions 	OSArray * array;
1354a5e72196SApple OSS Distributions 	OSDictionary * user = NULL;
1355368ad365SApple OSS Distributions 
1356e6231be0SApple OSS Distributions 	OSObject * ioProperty = IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey);
1357e6231be0SApple OSS Distributions 	if ((array = OSDynamicCast(OSArray, ioProperty))) {
1358368ad365SApple OSS Distributions 		for (unsigned int idx = 0;
1359368ad365SApple OSS Distributions 		    (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
1360e13b1fa5SApple OSS Distributions 		    idx++) {
1361368ad365SApple OSS Distributions 			OSNumber * num;
1362e13b1fa5SApple OSS Distributions 
1363368ad365SApple OSS Distributions 			if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionUIDKey)))
1364e13b1fa5SApple OSS Distributions 			    && (uid == num->unsigned32BitValue())) {
1365e13b1fa5SApple OSS Distributions 				user->retain();
1366368ad365SApple OSS Distributions 				break;
1367368ad365SApple OSS Distributions 			}
1368e13b1fa5SApple OSS Distributions 		}
1369368ad365SApple OSS Distributions 	}
1370e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(ioProperty);
1371e13b1fa5SApple OSS Distributions 	return user;
1372e13b1fa5SApple OSS Distributions }
1373e13b1fa5SApple OSS Distributions 
1374a5e72196SApple OSS Distributions static OSDictionary *
CopyUserOnConsole(void)1375a5e72196SApple OSS Distributions CopyUserOnConsole(void)
1376855239e5SApple OSS Distributions {
1377855239e5SApple OSS Distributions 	OSArray * array;
1378a5e72196SApple OSS Distributions 	OSDictionary * user = NULL;
1379855239e5SApple OSS Distributions 
1380e6231be0SApple OSS Distributions 	OSObject * ioProperty = IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey);
1381e6231be0SApple OSS Distributions 	if ((array = OSDynamicCast(OSArray, ioProperty))) {
1382855239e5SApple OSS Distributions 		for (unsigned int idx = 0;
1383855239e5SApple OSS Distributions 		    (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
1384a5e72196SApple OSS Distributions 		    idx++) {
1385a5e72196SApple OSS Distributions 			if (kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey)) {
1386855239e5SApple OSS Distributions 				user->retain();
1387855239e5SApple OSS Distributions 				break;
1388855239e5SApple OSS Distributions 			}
1389855239e5SApple OSS Distributions 		}
1390855239e5SApple OSS Distributions 	}
1391e6231be0SApple OSS Distributions 	OSSafeReleaseNULL(ioProperty);
1392a5e72196SApple OSS Distributions 	return user;
1393855239e5SApple OSS Distributions }
1394855239e5SApple OSS Distributions 
1395a5e72196SApple OSS Distributions IOReturn
clientHasAuthorization(task_t task,IOService * service)1396a5e72196SApple OSS Distributions IOUserClient::clientHasAuthorization( task_t task,
1397a3bb9fccSApple OSS Distributions     IOService * service )
1398a3bb9fccSApple OSS Distributions {
1399a3bb9fccSApple OSS Distributions 	proc_t p;
1400a3bb9fccSApple OSS Distributions 
1401a3bb9fccSApple OSS Distributions 	p = (proc_t) get_bsdtask_info(task);
1402a5e72196SApple OSS Distributions 	if (p) {
1403a3bb9fccSApple OSS Distributions 		uint64_t authorizationID;
1404a3bb9fccSApple OSS Distributions 
1405a3bb9fccSApple OSS Distributions 		authorizationID = proc_uniqueid(p);
1406a5e72196SApple OSS Distributions 		if (authorizationID) {
1407a5e72196SApple OSS Distributions 			if (service->getAuthorizationID() == authorizationID) {
1408a5e72196SApple OSS Distributions 				return kIOReturnSuccess;
1409a3bb9fccSApple OSS Distributions 			}
1410a3bb9fccSApple OSS Distributions 		}
1411a3bb9fccSApple OSS Distributions 	}
1412a3bb9fccSApple OSS Distributions 
1413a5e72196SApple OSS Distributions 	return kIOReturnNotPermitted;
1414a3bb9fccSApple OSS Distributions }
1415a3bb9fccSApple OSS Distributions 
1416a5e72196SApple OSS Distributions IOReturn
clientHasPrivilege(void * securityToken,const char * privilegeName)1417a5e72196SApple OSS Distributions IOUserClient::clientHasPrivilege( void * securityToken,
1418e13b1fa5SApple OSS Distributions     const char * privilegeName )
1419e13b1fa5SApple OSS Distributions {
1420e13b1fa5SApple OSS Distributions 	kern_return_t           kr;
1421e13b1fa5SApple OSS Distributions 	security_token_t        token;
1422e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  count;
1423e13b1fa5SApple OSS Distributions 	task_t                  task;
1424e13b1fa5SApple OSS Distributions 	OSDictionary *          user;
1425e13b1fa5SApple OSS Distributions 	bool                    secureConsole;
1426e13b1fa5SApple OSS Distributions 
1427855239e5SApple OSS Distributions 
1428855239e5SApple OSS Distributions 	if (!strncmp(privilegeName, kIOClientPrivilegeForeground,
1429a5e72196SApple OSS Distributions 	    sizeof(kIOClientPrivilegeForeground))) {
1430a5e72196SApple OSS Distributions 		if (task_is_gpu_denied(current_task())) {
1431a5e72196SApple OSS Distributions 			return kIOReturnNotPrivileged;
1432a5e72196SApple OSS Distributions 		} else {
1433a5e72196SApple OSS Distributions 			return kIOReturnSuccess;
1434a5e72196SApple OSS Distributions 		}
1435855239e5SApple OSS Distributions 	}
1436855239e5SApple OSS Distributions 
1437855239e5SApple OSS Distributions 	if (!strncmp(privilegeName, kIOClientPrivilegeConsoleSession,
1438a5e72196SApple OSS Distributions 	    sizeof(kIOClientPrivilegeConsoleSession))) {
1439855239e5SApple OSS Distributions 		kauth_cred_t cred;
1440855239e5SApple OSS Distributions 		proc_t       p;
1441855239e5SApple OSS Distributions 
1442855239e5SApple OSS Distributions 		task = (task_t) securityToken;
1443a5e72196SApple OSS Distributions 		if (!task) {
1444855239e5SApple OSS Distributions 			task = current_task();
1445a5e72196SApple OSS Distributions 		}
1446855239e5SApple OSS Distributions 		p = (proc_t) get_bsdtask_info(task);
1447855239e5SApple OSS Distributions 		kr = kIOReturnNotPrivileged;
1448855239e5SApple OSS Distributions 
1449a5e72196SApple OSS Distributions 		if (p && (cred = kauth_cred_proc_ref(p))) {
1450855239e5SApple OSS Distributions 			user = CopyUserOnConsole();
1451a5e72196SApple OSS Distributions 			if (user) {
1452855239e5SApple OSS Distributions 				OSNumber * num;
1453855239e5SApple OSS Distributions 				if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionAuditIDKey)))
1454a5e72196SApple OSS Distributions 				    && (cred->cr_audit.as_aia_p->ai_asid == (au_asid_t) num->unsigned32BitValue())) {
1455855239e5SApple OSS Distributions 					kr = kIOReturnSuccess;
1456855239e5SApple OSS Distributions 				}
1457855239e5SApple OSS Distributions 				user->release();
1458855239e5SApple OSS Distributions 			}
1459855239e5SApple OSS Distributions 			kauth_cred_unref(&cred);
1460855239e5SApple OSS Distributions 		}
1461a5e72196SApple OSS Distributions 		return kr;
1462855239e5SApple OSS Distributions 	}
1463855239e5SApple OSS Distributions 
14643ca3bd55SApple OSS Distributions 	if ((secureConsole = !strncmp(privilegeName, kIOClientPrivilegeSecureConsoleProcess,
1465a5e72196SApple OSS Distributions 	    sizeof(kIOClientPrivilegeSecureConsoleProcess)))) {
1466e13b1fa5SApple OSS Distributions 		task = (task_t)((IOUCProcessToken *)securityToken)->token;
1467a5e72196SApple OSS Distributions 	} else {
1468e13b1fa5SApple OSS Distributions 		task = (task_t)securityToken;
1469a5e72196SApple OSS Distributions 	}
1470e13b1fa5SApple OSS Distributions 
1471e13b1fa5SApple OSS Distributions 	count = TASK_SECURITY_TOKEN_COUNT;
1472e13b1fa5SApple OSS Distributions 	kr = task_info( task, TASK_SECURITY_TOKEN, (task_info_t) &token, &count );
1473e13b1fa5SApple OSS Distributions 
1474a5e72196SApple OSS Distributions 	if (KERN_SUCCESS != kr) {
1475a5e72196SApple OSS Distributions 	} else if (!strncmp(privilegeName, kIOClientPrivilegeAdministrator,
14763ca3bd55SApple OSS Distributions 	    sizeof(kIOClientPrivilegeAdministrator))) {
1477a5e72196SApple OSS Distributions 		if (0 != token.val[0]) {
1478e13b1fa5SApple OSS Distributions 			kr = kIOReturnNotPrivileged;
1479a5e72196SApple OSS Distributions 		}
14803ca3bd55SApple OSS Distributions 	} else if (!strncmp(privilegeName, kIOClientPrivilegeLocalUser,
14813ca3bd55SApple OSS Distributions 	    sizeof(kIOClientPrivilegeLocalUser))) {
1482e13b1fa5SApple OSS Distributions 		user = CopyConsoleUser(token.val[0]);
1483a5e72196SApple OSS Distributions 		if (user) {
1484e13b1fa5SApple OSS Distributions 			user->release();
1485a5e72196SApple OSS Distributions 		} else {
1486e13b1fa5SApple OSS Distributions 			kr = kIOReturnNotPrivileged;
1487a5e72196SApple OSS Distributions 		}
14883ca3bd55SApple OSS Distributions 	} else if (secureConsole || !strncmp(privilegeName, kIOClientPrivilegeConsoleUser,
14893ca3bd55SApple OSS Distributions 	    sizeof(kIOClientPrivilegeConsoleUser))) {
1490e13b1fa5SApple OSS Distributions 		user = CopyConsoleUser(token.val[0]);
1491e13b1fa5SApple OSS Distributions 		if (user) {
1492a5e72196SApple OSS Distributions 			if (user->getObject(gIOConsoleSessionOnConsoleKey) != kOSBooleanTrue) {
1493e13b1fa5SApple OSS Distributions 				kr = kIOReturnNotPrivileged;
1494a5e72196SApple OSS Distributions 			} else if (secureConsole) {
1495e13b1fa5SApple OSS Distributions 				OSNumber * pid = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionSecureInputPIDKey));
1496a5e72196SApple OSS Distributions 				if (pid && pid->unsigned32BitValue() != ((IOUCProcessToken *)securityToken)->pid) {
1497368ad365SApple OSS Distributions 					kr = kIOReturnNotPrivileged;
1498368ad365SApple OSS Distributions 				}
1499a5e72196SApple OSS Distributions 			}
1500e13b1fa5SApple OSS Distributions 			user->release();
1501a5e72196SApple OSS Distributions 		} else {
1502e13b1fa5SApple OSS Distributions 			kr = kIOReturnNotPrivileged;
1503a5e72196SApple OSS Distributions 		}
1504a5e72196SApple OSS Distributions 	} else {
1505368ad365SApple OSS Distributions 		kr = kIOReturnUnsupported;
1506c1dac77fSApple OSS Distributions 	}
1507c1dac77fSApple OSS Distributions 
1508a5e72196SApple OSS Distributions 	return kr;
1509a5e72196SApple OSS Distributions }
1510a5e72196SApple OSS Distributions 
1511a5e72196SApple OSS Distributions OSDictionary *
copyClientEntitlements(task_t task)1512a5e72196SApple OSS Distributions IOUserClient::copyClientEntitlements(task_t task)
1513a3bb9fccSApple OSS Distributions {
1514a3bb9fccSApple OSS Distributions 	proc_t p = NULL;
1515a3bb9fccSApple OSS Distributions 	pid_t pid = 0;
1516a3bb9fccSApple OSS Distributions 	OSDictionary *entitlements = NULL;
1517a3bb9fccSApple OSS Distributions 
1518a3bb9fccSApple OSS Distributions 	p = (proc_t)get_bsdtask_info(task);
1519a5e72196SApple OSS Distributions 	if (p == NULL) {
1520bb611c8fSApple OSS Distributions 		return NULL;
1521a5e72196SApple OSS Distributions 	}
1522a3bb9fccSApple OSS Distributions 	pid = proc_pid(p);
1523a3bb9fccSApple OSS Distributions 
1524a5e72196SApple OSS Distributions 	if (cs_entitlements_dictionary_copy(p, (void **)&entitlements) == 0) {
1525a5e72196SApple OSS Distributions 		if (entitlements) {
1526a5e72196SApple OSS Distributions 			return entitlements;
1527a5e72196SApple OSS Distributions 		}
1528a5e72196SApple OSS Distributions 	}
1529a3bb9fccSApple OSS Distributions 
1530e6231be0SApple OSS Distributions 	// If the above fails, thats it
1531bb611c8fSApple OSS Distributions 	return NULL;
1532a5e72196SApple OSS Distributions }
1533a5e72196SApple OSS Distributions 
1534bb611c8fSApple OSS Distributions OSDictionary *
copyClientEntitlementsVnode(vnode_t vnode,off_t offset)1535bb611c8fSApple OSS Distributions IOUserClient::copyClientEntitlementsVnode(vnode_t vnode, off_t offset)
1536bb611c8fSApple OSS Distributions {
1537e6231be0SApple OSS Distributions 	OSDictionary *entitlements = NULL;
1538bb611c8fSApple OSS Distributions 
1539e6231be0SApple OSS Distributions 	if (cs_entitlements_dictionary_copy_vnode(vnode, offset, (void**)&entitlements) != 0) {
1540bb611c8fSApple OSS Distributions 		return NULL;
1541bb611c8fSApple OSS Distributions 	}
1542e6231be0SApple OSS Distributions 	return entitlements;
1543bb611c8fSApple OSS Distributions }
1544bb611c8fSApple OSS Distributions 
1545a5e72196SApple OSS Distributions OSObject *
copyClientEntitlement(task_t task,const char * entitlement)1546a5e72196SApple OSS Distributions IOUserClient::copyClientEntitlement( task_t task,
1547a5e72196SApple OSS Distributions     const char * entitlement )
1548a5e72196SApple OSS Distributions {
1549aca3beaaSApple OSS Distributions 	void *entitlement_object = NULL;
1550a5e72196SApple OSS Distributions 
1551aca3beaaSApple OSS Distributions 	if (task == NULL) {
1552aca3beaaSApple OSS Distributions 		task = current_task();
1553aca3beaaSApple OSS Distributions 	}
1554aca3beaaSApple OSS Distributions 
1555aca3beaaSApple OSS Distributions 	/* Validate input arguments */
1556aca3beaaSApple OSS Distributions 	if (task == kernel_task || entitlement == NULL) {
1557e6231be0SApple OSS Distributions 		return NULL;
1558e6231be0SApple OSS Distributions 	}
1559aca3beaaSApple OSS Distributions 	proc_t proc = (proc_t)get_bsdtask_info(task);
1560aca3beaaSApple OSS Distributions 
1561aca3beaaSApple OSS Distributions 	kern_return_t ret = amfi->OSEntitlements.copyEntitlementAsOSObjectWithProc(
1562aca3beaaSApple OSS Distributions 		proc,
1563aca3beaaSApple OSS Distributions 		entitlement,
1564aca3beaaSApple OSS Distributions 		&entitlement_object);
1565aca3beaaSApple OSS Distributions 
1566aca3beaaSApple OSS Distributions 	if (ret != KERN_SUCCESS) {
1567e6231be0SApple OSS Distributions 		return NULL;
1568e6231be0SApple OSS Distributions 	}
1569aca3beaaSApple OSS Distributions 	assert(entitlement_object != NULL);
1570e6231be0SApple OSS Distributions 
1571aca3beaaSApple OSS Distributions 	return (OSObject*)entitlement_object;
1572a3bb9fccSApple OSS Distributions }
1573a3bb9fccSApple OSS Distributions 
1574bb611c8fSApple OSS Distributions OSObject *
copyClientEntitlementVnode(struct vnode * vnode,off_t offset,const char * entitlement)1575bb611c8fSApple OSS Distributions IOUserClient::copyClientEntitlementVnode(
1576bb611c8fSApple OSS Distributions 	struct vnode *vnode,
1577bb611c8fSApple OSS Distributions 	off_t offset,
1578bb611c8fSApple OSS Distributions 	const char *entitlement)
1579bb611c8fSApple OSS Distributions {
1580bb611c8fSApple OSS Distributions 	OSDictionary *entitlements;
1581bb611c8fSApple OSS Distributions 	OSObject *value;
1582bb611c8fSApple OSS Distributions 
1583bb611c8fSApple OSS Distributions 	entitlements = copyClientEntitlementsVnode(vnode, offset);
1584bb611c8fSApple OSS Distributions 	if (entitlements == NULL) {
1585bb611c8fSApple OSS Distributions 		return NULL;
1586bb611c8fSApple OSS Distributions 	}
1587bb611c8fSApple OSS Distributions 
1588bb611c8fSApple OSS Distributions 	/* Fetch the entitlement value from the dictionary. */
1589bb611c8fSApple OSS Distributions 	value = entitlements->getObject(entitlement);
1590bb611c8fSApple OSS Distributions 	if (value != NULL) {
1591bb611c8fSApple OSS Distributions 		value->retain();
1592bb611c8fSApple OSS Distributions 	}
1593bb611c8fSApple OSS Distributions 
1594bb611c8fSApple OSS Distributions 	entitlements->release();
1595bb611c8fSApple OSS Distributions 	return value;
1596bb611c8fSApple OSS Distributions }
1597bb611c8fSApple OSS Distributions 
1598a5e72196SApple OSS Distributions bool
init()1599a5e72196SApple OSS Distributions IOUserClient::init()
1600e13b1fa5SApple OSS Distributions {
1601a5e72196SApple OSS Distributions 	if (getPropertyTable() || super::init()) {
1602855239e5SApple OSS Distributions 		return reserve();
1603a5e72196SApple OSS Distributions 	}
1604855239e5SApple OSS Distributions 
1605855239e5SApple OSS Distributions 	return false;
1606e13b1fa5SApple OSS Distributions }
1607e13b1fa5SApple OSS Distributions 
1608a5e72196SApple OSS Distributions bool
init(OSDictionary * dictionary)1609a5e72196SApple OSS Distributions IOUserClient::init(OSDictionary * dictionary)
1610e13b1fa5SApple OSS Distributions {
1611a5e72196SApple OSS Distributions 	if (getPropertyTable() || super::init(dictionary)) {
1612855239e5SApple OSS Distributions 		return reserve();
1613a5e72196SApple OSS Distributions 	}
1614855239e5SApple OSS Distributions 
1615855239e5SApple OSS Distributions 	return false;
1616e13b1fa5SApple OSS Distributions }
1617e13b1fa5SApple OSS Distributions 
1618a5e72196SApple OSS Distributions bool
initWithTask(task_t owningTask,void * securityID,UInt32 type)1619a5e72196SApple OSS Distributions IOUserClient::initWithTask(task_t owningTask,
1620c1dac77fSApple OSS Distributions     void * securityID,
1621c1dac77fSApple OSS Distributions     UInt32 type )
1622c1dac77fSApple OSS Distributions {
1623a5e72196SApple OSS Distributions 	if (getPropertyTable() || super::init()) {
1624855239e5SApple OSS Distributions 		return reserve();
1625a5e72196SApple OSS Distributions 	}
1626855239e5SApple OSS Distributions 
1627855239e5SApple OSS Distributions 	return false;
1628c1dac77fSApple OSS Distributions }
1629c1dac77fSApple OSS Distributions 
1630a5e72196SApple OSS Distributions bool
initWithTask(task_t owningTask,void * securityID,UInt32 type,OSDictionary * properties)1631a5e72196SApple OSS Distributions IOUserClient::initWithTask(task_t owningTask,
1632c1dac77fSApple OSS Distributions     void * securityID,
1633c1dac77fSApple OSS Distributions     UInt32 type,
1634c1dac77fSApple OSS Distributions     OSDictionary * properties )
1635c1dac77fSApple OSS Distributions {
1636c1dac77fSApple OSS Distributions 	bool ok;
1637c1dac77fSApple OSS Distributions 
1638c1dac77fSApple OSS Distributions 	ok = super::init( properties );
1639c1dac77fSApple OSS Distributions 	ok &= initWithTask( owningTask, securityID, type );
1640c1dac77fSApple OSS Distributions 
1641a5e72196SApple OSS Distributions 	return ok;
1642c1dac77fSApple OSS Distributions }
1643c1dac77fSApple OSS Distributions 
1644a5e72196SApple OSS Distributions bool
reserve()1645a5e72196SApple OSS Distributions IOUserClient::reserve()
1646855239e5SApple OSS Distributions {
1647855239e5SApple OSS Distributions 	if (!reserved) {
1648e6231be0SApple OSS Distributions 		reserved = IOMallocType(ExpansionData);
1649855239e5SApple OSS Distributions 	}
1650186b8fceSApple OSS Distributions 	setTerminateDefer(NULL, true);
1651855239e5SApple OSS Distributions 	IOStatisticsRegisterCounter();
1652aca3beaaSApple OSS Distributions 	IORWLockInlineInit(&lock);
1653aca3beaaSApple OSS Distributions 	IOLockInlineInit(&filterLock);
1654855239e5SApple OSS Distributions 
1655855239e5SApple OSS Distributions 	return true;
1656855239e5SApple OSS Distributions }
1657855239e5SApple OSS Distributions 
1658a5e72196SApple OSS Distributions struct IOUserClientOwner {
165988cc0b97SApple OSS Distributions 	task_t         task;
166088cc0b97SApple OSS Distributions 	queue_chain_t  taskLink;
166188cc0b97SApple OSS Distributions 	IOUserClient * uc;
166288cc0b97SApple OSS Distributions 	queue_chain_t  ucLink;
166388cc0b97SApple OSS Distributions };
166488cc0b97SApple OSS Distributions 
166588cc0b97SApple OSS Distributions IOReturn
registerOwner(task_t task)166688cc0b97SApple OSS Distributions IOUserClient::registerOwner(task_t task)
166788cc0b97SApple OSS Distributions {
166888cc0b97SApple OSS Distributions 	IOUserClientOwner * owner;
166988cc0b97SApple OSS Distributions 	IOReturn            ret;
167088cc0b97SApple OSS Distributions 	bool                newOwner;
167188cc0b97SApple OSS Distributions 
167288cc0b97SApple OSS Distributions 	IOLockLock(gIOUserClientOwnersLock);
167388cc0b97SApple OSS Distributions 
167488cc0b97SApple OSS Distributions 	newOwner = true;
167588cc0b97SApple OSS Distributions 	ret = kIOReturnSuccess;
167688cc0b97SApple OSS Distributions 
1677a5e72196SApple OSS Distributions 	if (!owners.next) {
1678a5e72196SApple OSS Distributions 		queue_init(&owners);
1679a5e72196SApple OSS Distributions 	} else {
168088cc0b97SApple OSS Distributions 		queue_iterate(&owners, owner, IOUserClientOwner *, ucLink)
168188cc0b97SApple OSS Distributions 		{
1682a5e72196SApple OSS Distributions 			if (task != owner->task) {
1683a5e72196SApple OSS Distributions 				continue;
1684a5e72196SApple OSS Distributions 			}
168588cc0b97SApple OSS Distributions 			newOwner = false;
168688cc0b97SApple OSS Distributions 			break;
168788cc0b97SApple OSS Distributions 		}
168888cc0b97SApple OSS Distributions 	}
1689a5e72196SApple OSS Distributions 	if (newOwner) {
1690e6231be0SApple OSS Distributions 		owner = IOMallocType(IOUserClientOwner);
1691e6231be0SApple OSS Distributions 
169288cc0b97SApple OSS Distributions 		owner->task = task;
169388cc0b97SApple OSS Distributions 		owner->uc   = this;
169488cc0b97SApple OSS Distributions 		queue_enter_first(&owners, owner, IOUserClientOwner *, ucLink);
169588cc0b97SApple OSS Distributions 		queue_enter_first(task_io_user_clients(task), owner, IOUserClientOwner *, taskLink);
1696a5e72196SApple OSS Distributions 		if (messageAppSuspended) {
1697a5e72196SApple OSS Distributions 			task_set_message_app_suspended(task, true);
1698a5e72196SApple OSS Distributions 		}
169988cc0b97SApple OSS Distributions 	}
170088cc0b97SApple OSS Distributions 
170188cc0b97SApple OSS Distributions 	IOLockUnlock(gIOUserClientOwnersLock);
170288cc0b97SApple OSS Distributions 
1703a5e72196SApple OSS Distributions 	return ret;
170488cc0b97SApple OSS Distributions }
170588cc0b97SApple OSS Distributions 
170688cc0b97SApple OSS Distributions void
noMoreSenders(void)170788cc0b97SApple OSS Distributions IOUserClient::noMoreSenders(void)
170888cc0b97SApple OSS Distributions {
170988cc0b97SApple OSS Distributions 	IOUserClientOwner * owner;
1710a5e72196SApple OSS Distributions 	IOUserClientOwner * iter;
1711a5e72196SApple OSS Distributions 	queue_head_t      * taskque;
1712a5e72196SApple OSS Distributions 	bool                hasMessageAppSuspended;
171388cc0b97SApple OSS Distributions 
171488cc0b97SApple OSS Distributions 	IOLockLock(gIOUserClientOwnersLock);
171588cc0b97SApple OSS Distributions 
1716a5e72196SApple OSS Distributions 	if (owners.next) {
1717a5e72196SApple OSS Distributions 		while (!queue_empty(&owners)) {
171888cc0b97SApple OSS Distributions 			owner = (IOUserClientOwner *)(void *) queue_first(&owners);
1719a5e72196SApple OSS Distributions 			taskque = task_io_user_clients(owner->task);
1720a5e72196SApple OSS Distributions 			queue_remove(taskque, owner, IOUserClientOwner *, taskLink);
1721a5e72196SApple OSS Distributions 			hasMessageAppSuspended = false;
1722a5e72196SApple OSS Distributions 			queue_iterate(taskque, iter, IOUserClientOwner *, taskLink) {
1723a5e72196SApple OSS Distributions 				hasMessageAppSuspended = iter->uc->messageAppSuspended;
1724a5e72196SApple OSS Distributions 				if (hasMessageAppSuspended) {
1725a5e72196SApple OSS Distributions 					break;
1726a5e72196SApple OSS Distributions 				}
1727a5e72196SApple OSS Distributions 			}
1728a5e72196SApple OSS Distributions 			task_set_message_app_suspended(owner->task, hasMessageAppSuspended);
172988cc0b97SApple OSS Distributions 			queue_remove(&owners, owner, IOUserClientOwner *, ucLink);
1730e6231be0SApple OSS Distributions 			IOFreeType(owner, IOUserClientOwner);
173188cc0b97SApple OSS Distributions 		}
173288cc0b97SApple OSS Distributions 		owners.next = owners.prev = NULL;
173388cc0b97SApple OSS Distributions 	}
173488cc0b97SApple OSS Distributions 
173588cc0b97SApple OSS Distributions 	IOLockUnlock(gIOUserClientOwnersLock);
173688cc0b97SApple OSS Distributions }
173788cc0b97SApple OSS Distributions 
1738a5e72196SApple OSS Distributions 
1739a5e72196SApple OSS Distributions extern "C" void
iokit_task_app_suspended_changed(task_t task)1740a5e72196SApple OSS Distributions iokit_task_app_suspended_changed(task_t task)
1741a5e72196SApple OSS Distributions {
1742a5e72196SApple OSS Distributions 	queue_head_t      * taskque;
1743a5e72196SApple OSS Distributions 	IOUserClientOwner * owner;
1744a5e72196SApple OSS Distributions 	OSSet             * set;
1745a5e72196SApple OSS Distributions 
1746a5e72196SApple OSS Distributions 	IOLockLock(gIOUserClientOwnersLock);
1747a5e72196SApple OSS Distributions 
1748a5e72196SApple OSS Distributions 	taskque = task_io_user_clients(task);
1749a5e72196SApple OSS Distributions 	set = NULL;
1750a5e72196SApple OSS Distributions 	queue_iterate(taskque, owner, IOUserClientOwner *, taskLink) {
1751a5e72196SApple OSS Distributions 		if (!owner->uc->messageAppSuspended) {
1752a5e72196SApple OSS Distributions 			continue;
1753a5e72196SApple OSS Distributions 		}
1754a5e72196SApple OSS Distributions 		if (!set) {
1755a5e72196SApple OSS Distributions 			set = OSSet::withCapacity(4);
1756a5e72196SApple OSS Distributions 			if (!set) {
1757a5e72196SApple OSS Distributions 				break;
1758a5e72196SApple OSS Distributions 			}
1759a5e72196SApple OSS Distributions 		}
1760a5e72196SApple OSS Distributions 		set->setObject(owner->uc);
1761a5e72196SApple OSS Distributions 	}
1762a5e72196SApple OSS Distributions 
1763a5e72196SApple OSS Distributions 	IOLockUnlock(gIOUserClientOwnersLock);
1764a5e72196SApple OSS Distributions 
1765a5e72196SApple OSS Distributions 	if (set) {
1766a5e72196SApple OSS Distributions 		set->iterateObjects(^bool (OSObject * obj) {
1767a5e72196SApple OSS Distributions 			IOUserClient      * uc;
1768a5e72196SApple OSS Distributions 
1769a5e72196SApple OSS Distributions 			uc = (typeof(uc))obj;
1770a5e72196SApple OSS Distributions #if 0
1771a5e72196SApple OSS Distributions 			{
1772a5e72196SApple OSS Distributions 			        OSString          * str;
1773a5e72196SApple OSS Distributions 			        str = IOCopyLogNameForPID(task_pid(task));
1774a5e72196SApple OSS Distributions 			        IOLog("iokit_task_app_suspended_changed(%s) %s %d\n", str ? str->getCStringNoCopy() : "",
1775a5e72196SApple OSS Distributions 			        uc->getName(), task_is_app_suspended(task));
1776a5e72196SApple OSS Distributions 			        OSSafeReleaseNULL(str);
1777a5e72196SApple OSS Distributions 			}
1778a5e72196SApple OSS Distributions #endif
1779a5e72196SApple OSS Distributions 			uc->message(kIOMessageTaskAppSuspendedChange, NULL);
1780a5e72196SApple OSS Distributions 
1781a5e72196SApple OSS Distributions 			return false;
1782a5e72196SApple OSS Distributions 		});
1783a5e72196SApple OSS Distributions 		set->release();
1784a5e72196SApple OSS Distributions 	}
1785a5e72196SApple OSS Distributions }
1786a5e72196SApple OSS Distributions 
178794d3b452SApple OSS Distributions static kern_return_t
iokit_task_terminate_phase1(task_t task)178894d3b452SApple OSS Distributions iokit_task_terminate_phase1(task_t task)
178988cc0b97SApple OSS Distributions {
179088cc0b97SApple OSS Distributions 	queue_head_t      * taskque;
179194d3b452SApple OSS Distributions 	IOUserClientOwner * iter;
179294d3b452SApple OSS Distributions 	OSSet             * userServers = NULL;
179394d3b452SApple OSS Distributions 
179494d3b452SApple OSS Distributions 	if (!task_is_driver(task)) {
179594d3b452SApple OSS Distributions 		return KERN_SUCCESS;
179694d3b452SApple OSS Distributions 	}
179794d3b452SApple OSS Distributions 	userServers = OSSet::withCapacity(1);
179888cc0b97SApple OSS Distributions 
179988cc0b97SApple OSS Distributions 	IOLockLock(gIOUserClientOwnersLock);
180088cc0b97SApple OSS Distributions 
180188cc0b97SApple OSS Distributions 	taskque = task_io_user_clients(task);
180294d3b452SApple OSS Distributions 	queue_iterate(taskque, iter, IOUserClientOwner *, taskLink) {
180394d3b452SApple OSS Distributions 		userServers->setObject(iter->uc);
180494d3b452SApple OSS Distributions 	}
180594d3b452SApple OSS Distributions 	IOLockUnlock(gIOUserClientOwnersLock);
180694d3b452SApple OSS Distributions 
180794d3b452SApple OSS Distributions 	if (userServers) {
180894d3b452SApple OSS Distributions 		IOUserServer * userServer;
180994d3b452SApple OSS Distributions 		while ((userServer = OSRequiredCast(IOUserServer, userServers->getAnyObject()))) {
181094d3b452SApple OSS Distributions 			userServer->clientDied();
181194d3b452SApple OSS Distributions 			userServers->removeObject(userServer);
181294d3b452SApple OSS Distributions 		}
181394d3b452SApple OSS Distributions 		userServers->release();
181494d3b452SApple OSS Distributions 	}
181594d3b452SApple OSS Distributions 	return KERN_SUCCESS;
181694d3b452SApple OSS Distributions }
181794d3b452SApple OSS Distributions 
181894d3b452SApple OSS Distributions static kern_return_t
iokit_task_terminate_phase2(task_t task)181994d3b452SApple OSS Distributions iokit_task_terminate_phase2(task_t task)
182094d3b452SApple OSS Distributions {
182194d3b452SApple OSS Distributions 	queue_head_t      * taskque;
182294d3b452SApple OSS Distributions 	IOUserClientOwner * owner;
182394d3b452SApple OSS Distributions 	IOUserClient      * dead;
182494d3b452SApple OSS Distributions 	IOUserClient      * uc;
182594d3b452SApple OSS Distributions 
182694d3b452SApple OSS Distributions 	IOLockLock(gIOUserClientOwnersLock);
182794d3b452SApple OSS Distributions 	taskque = task_io_user_clients(task);
182888cc0b97SApple OSS Distributions 	dead = NULL;
1829a5e72196SApple OSS Distributions 	while (!queue_empty(taskque)) {
183088cc0b97SApple OSS Distributions 		owner = (IOUserClientOwner *)(void *) queue_first(taskque);
183188cc0b97SApple OSS Distributions 		uc = owner->uc;
183288cc0b97SApple OSS Distributions 		queue_remove(taskque, owner, IOUserClientOwner *, taskLink);
183388cc0b97SApple OSS Distributions 		queue_remove(&uc->owners, owner, IOUserClientOwner *, ucLink);
1834a5e72196SApple OSS Distributions 		if (queue_empty(&uc->owners)) {
183588cc0b97SApple OSS Distributions 			uc->retain();
183688cc0b97SApple OSS Distributions 			IOLog("destroying out of band connect for %s\n", uc->getName());
183788cc0b97SApple OSS Distributions 			// now using the uc queue head as a singly linked queue,
183888cc0b97SApple OSS Distributions 			// leaving .next as NULL to mark it empty
183988cc0b97SApple OSS Distributions 			uc->owners.next = NULL;
184088cc0b97SApple OSS Distributions 			uc->owners.prev = (queue_entry_t) dead;
184188cc0b97SApple OSS Distributions 			dead = uc;
184288cc0b97SApple OSS Distributions 		}
1843e6231be0SApple OSS Distributions 		IOFreeType(owner, IOUserClientOwner);
184488cc0b97SApple OSS Distributions 	}
184588cc0b97SApple OSS Distributions 	IOLockUnlock(gIOUserClientOwnersLock);
184688cc0b97SApple OSS Distributions 
1847a5e72196SApple OSS Distributions 	while (dead) {
184888cc0b97SApple OSS Distributions 		uc = dead;
184988cc0b97SApple OSS Distributions 		dead = (IOUserClient *)(void *) dead->owners.prev;
185088cc0b97SApple OSS Distributions 		uc->owners.prev = NULL;
1851a5e72196SApple OSS Distributions 		if (uc->sharedInstance || !uc->closed) {
1852a5e72196SApple OSS Distributions 			uc->clientDied();
1853a5e72196SApple OSS Distributions 		}
185488cc0b97SApple OSS Distributions 		uc->release();
185588cc0b97SApple OSS Distributions 	}
185688cc0b97SApple OSS Distributions 
1857a5e72196SApple OSS Distributions 	return KERN_SUCCESS;
185888cc0b97SApple OSS Distributions }
185988cc0b97SApple OSS Distributions 
186094d3b452SApple OSS Distributions extern "C" kern_return_t
iokit_task_terminate(task_t task,int phase)186194d3b452SApple OSS Distributions iokit_task_terminate(task_t task, int phase)
186294d3b452SApple OSS Distributions {
186394d3b452SApple OSS Distributions 	switch (phase) {
186494d3b452SApple OSS Distributions 	case 1:
186594d3b452SApple OSS Distributions 		return iokit_task_terminate_phase1(task);
186694d3b452SApple OSS Distributions 	case 2:
186794d3b452SApple OSS Distributions 		return iokit_task_terminate_phase2(task);
186894d3b452SApple OSS Distributions 	default:
186994d3b452SApple OSS Distributions 		panic("iokit_task_terminate phase %d", phase);
187094d3b452SApple OSS Distributions 	}
187194d3b452SApple OSS Distributions }
187294d3b452SApple OSS Distributions 
1873bb611c8fSApple OSS Distributions struct IOUCFilterPolicy {
1874bb611c8fSApple OSS Distributions 	task_t             task;
1875bb611c8fSApple OSS Distributions 	io_filter_policy_t filterPolicy;
1876bb611c8fSApple OSS Distributions 	IOUCFilterPolicy * next;
1877bb611c8fSApple OSS Distributions };
1878bb611c8fSApple OSS Distributions 
1879bb611c8fSApple OSS Distributions io_filter_policy_t
filterForTask(task_t task,io_filter_policy_t addFilterPolicy)1880bb611c8fSApple OSS Distributions IOUserClient::filterForTask(task_t task, io_filter_policy_t addFilterPolicy)
1881bb611c8fSApple OSS Distributions {
1882bb611c8fSApple OSS Distributions 	IOUCFilterPolicy * elem;
1883bb611c8fSApple OSS Distributions 	io_filter_policy_t filterPolicy;
1884bb611c8fSApple OSS Distributions 
1885bb611c8fSApple OSS Distributions 	filterPolicy = 0;
1886aca3beaaSApple OSS Distributions 	IOLockLock(&filterLock);
1887bb611c8fSApple OSS Distributions 
1888bb611c8fSApple OSS Distributions 	for (elem = reserved->filterPolicies; elem && (elem->task != task); elem = elem->next) {
1889bb611c8fSApple OSS Distributions 	}
1890bb611c8fSApple OSS Distributions 
1891bb611c8fSApple OSS Distributions 	if (elem) {
1892bb611c8fSApple OSS Distributions 		if (addFilterPolicy) {
1893bb611c8fSApple OSS Distributions 			assert(addFilterPolicy == elem->filterPolicy);
1894bb611c8fSApple OSS Distributions 		}
1895bb611c8fSApple OSS Distributions 		filterPolicy = elem->filterPolicy;
1896bb611c8fSApple OSS Distributions 	} else if (addFilterPolicy) {
1897e6231be0SApple OSS Distributions 		elem = IOMallocType(IOUCFilterPolicy);
1898bb611c8fSApple OSS Distributions 		elem->task               = task;
1899bb611c8fSApple OSS Distributions 		elem->filterPolicy       = addFilterPolicy;
1900bb611c8fSApple OSS Distributions 		elem->next               = reserved->filterPolicies;
1901bb611c8fSApple OSS Distributions 		reserved->filterPolicies = elem;
1902bb611c8fSApple OSS Distributions 		filterPolicy = addFilterPolicy;
1903bb611c8fSApple OSS Distributions 	}
1904bb611c8fSApple OSS Distributions 
1905aca3beaaSApple OSS Distributions 	IOLockUnlock(&filterLock);
1906bb611c8fSApple OSS Distributions 	return filterPolicy;
1907bb611c8fSApple OSS Distributions }
1908bb611c8fSApple OSS Distributions 
1909a5e72196SApple OSS Distributions void
free()1910a5e72196SApple OSS Distributions IOUserClient::free()
1911c1dac77fSApple OSS Distributions {
1912a5e72196SApple OSS Distributions 	if (mappings) {
1913a5e72196SApple OSS Distributions 		mappings->release();
1914a5e72196SApple OSS Distributions 	}
1915c1dac77fSApple OSS Distributions 
1916855239e5SApple OSS Distributions 	IOStatisticsUnregisterCounter();
1917855239e5SApple OSS Distributions 
191888cc0b97SApple OSS Distributions 	assert(!owners.next);
191988cc0b97SApple OSS Distributions 	assert(!owners.prev);
192088cc0b97SApple OSS Distributions 
1921a5e72196SApple OSS Distributions 	if (reserved) {
1922bb611c8fSApple OSS Distributions 		IOUCFilterPolicy * elem;
1923bb611c8fSApple OSS Distributions 		IOUCFilterPolicy * nextElem;
1924bb611c8fSApple OSS Distributions 		for (elem = reserved->filterPolicies; elem; elem = nextElem) {
1925bb611c8fSApple OSS Distributions 			nextElem = elem->next;
1926bb611c8fSApple OSS Distributions 			if (elem->filterPolicy && gIOUCFilterCallbacks->io_filter_release) {
1927bb611c8fSApple OSS Distributions 				gIOUCFilterCallbacks->io_filter_release(elem->filterPolicy);
1928bb611c8fSApple OSS Distributions 			}
1929e6231be0SApple OSS Distributions 			IOFreeType(elem, IOUCFilterPolicy);
1930bb611c8fSApple OSS Distributions 		}
1931e6231be0SApple OSS Distributions 		IOFreeType(reserved, ExpansionData);
1932aca3beaaSApple OSS Distributions 		IORWLockInlineDestroy(&lock);
1933aca3beaaSApple OSS Distributions 		IOLockInlineDestroy(&filterLock);
1934a5e72196SApple OSS Distributions 	}
1935855239e5SApple OSS Distributions 
1936c1dac77fSApple OSS Distributions 	super::free();
1937c1dac77fSApple OSS Distributions }
1938c1dac77fSApple OSS Distributions 
19395c2921b0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
19405c2921b0SApple OSS Distributions 
OSDefineMetaClassAndAbstractStructors(IOUserClient2022,IOUserClient)19415c2921b0SApple OSS Distributions OSDefineMetaClassAndAbstractStructors( IOUserClient2022, IOUserClient )
19425c2921b0SApple OSS Distributions 
19435c2921b0SApple OSS Distributions 
19445c2921b0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
19455c2921b0SApple OSS Distributions 
1946a5e72196SApple OSS Distributions IOReturn
1947a5e72196SApple OSS Distributions IOUserClient::clientDied( void )
1948c1dac77fSApple OSS Distributions {
194988cc0b97SApple OSS Distributions 	IOReturn ret = kIOReturnNotReady;
195088cc0b97SApple OSS Distributions 
1951a5e72196SApple OSS Distributions 	if (sharedInstance || OSCompareAndSwap8(0, 1, &closed)) {
195288cc0b97SApple OSS Distributions 		ret = clientClose();
195388cc0b97SApple OSS Distributions 	}
195488cc0b97SApple OSS Distributions 
1955a5e72196SApple OSS Distributions 	return ret;
1956c1dac77fSApple OSS Distributions }
1957c1dac77fSApple OSS Distributions 
1958a5e72196SApple OSS Distributions IOReturn
clientClose(void)1959a5e72196SApple OSS Distributions IOUserClient::clientClose( void )
1960c1dac77fSApple OSS Distributions {
1961a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
1962c1dac77fSApple OSS Distributions }
1963c1dac77fSApple OSS Distributions 
1964a5e72196SApple OSS Distributions IOService *
getService(void)1965a5e72196SApple OSS Distributions IOUserClient::getService( void )
1966c1dac77fSApple OSS Distributions {
1967a5e72196SApple OSS Distributions 	return NULL;
1968c1dac77fSApple OSS Distributions }
1969c1dac77fSApple OSS Distributions 
1970a5e72196SApple OSS Distributions IOReturn
registerNotificationPort(mach_port_t,UInt32,UInt32)1971a5e72196SApple OSS Distributions IOUserClient::registerNotificationPort(
1972c1dac77fSApple OSS Distributions 	mach_port_t     /* port */,
1973c1dac77fSApple OSS Distributions 	UInt32          /* type */,
1974c1dac77fSApple OSS Distributions 	UInt32          /* refCon */)
1975c1dac77fSApple OSS Distributions {
1976a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
1977c1dac77fSApple OSS Distributions }
1978c1dac77fSApple OSS Distributions 
1979a5e72196SApple OSS Distributions IOReturn
registerNotificationPort(mach_port_t port,UInt32 type,io_user_reference_t refCon)1980a5e72196SApple OSS Distributions IOUserClient::registerNotificationPort(
19813ca3bd55SApple OSS Distributions 	mach_port_t port,
19823ca3bd55SApple OSS Distributions 	UInt32          type,
19833ca3bd55SApple OSS Distributions 	io_user_reference_t refCon)
19843ca3bd55SApple OSS Distributions {
1985a5e72196SApple OSS Distributions 	return registerNotificationPort(port, type, (UInt32) refCon);
19863ca3bd55SApple OSS Distributions }
19873ca3bd55SApple OSS Distributions 
1988a5e72196SApple OSS Distributions IOReturn
getNotificationSemaphore(UInt32 notification_type,semaphore_t * semaphore)1989a5e72196SApple OSS Distributions IOUserClient::getNotificationSemaphore( UInt32 notification_type,
1990c1dac77fSApple OSS Distributions     semaphore_t * semaphore )
1991c1dac77fSApple OSS Distributions {
1992a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
1993c1dac77fSApple OSS Distributions }
1994c1dac77fSApple OSS Distributions 
1995a5e72196SApple OSS Distributions IOReturn
connectClient(IOUserClient *)1996a5e72196SApple OSS Distributions IOUserClient::connectClient( IOUserClient * /* client */ )
1997c1dac77fSApple OSS Distributions {
1998a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
1999c1dac77fSApple OSS Distributions }
2000c1dac77fSApple OSS Distributions 
2001a5e72196SApple OSS Distributions IOReturn
clientMemoryForType(UInt32 type,IOOptionBits * options,IOMemoryDescriptor ** memory)2002a5e72196SApple OSS Distributions IOUserClient::clientMemoryForType( UInt32 type,
2003c1dac77fSApple OSS Distributions     IOOptionBits * options,
2004c1dac77fSApple OSS Distributions     IOMemoryDescriptor ** memory )
2005c1dac77fSApple OSS Distributions {
2006a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2007c1dac77fSApple OSS Distributions }
2008c1dac77fSApple OSS Distributions 
2009bb611c8fSApple OSS Distributions IOReturn
clientMemoryForType(UInt32 type,IOOptionBits * options,OSSharedPtr<IOMemoryDescriptor> & memory)2010bb611c8fSApple OSS Distributions IOUserClient::clientMemoryForType( UInt32 type,
2011bb611c8fSApple OSS Distributions     IOOptionBits * options,
2012bb611c8fSApple OSS Distributions     OSSharedPtr<IOMemoryDescriptor>& memory )
2013bb611c8fSApple OSS Distributions {
2014bb611c8fSApple OSS Distributions 	IOMemoryDescriptor* memoryRaw = nullptr;
2015bb611c8fSApple OSS Distributions 	IOReturn result = clientMemoryForType(type, options, &memoryRaw);
2016bb611c8fSApple OSS Distributions 	memory.reset(memoryRaw, OSNoRetain);
2017bb611c8fSApple OSS Distributions 	return result;
2018bb611c8fSApple OSS Distributions }
2019bb611c8fSApple OSS Distributions 
20203ca3bd55SApple OSS Distributions #if !__LP64__
2021a5e72196SApple OSS Distributions IOMemoryMap *
mapClientMemory(IOOptionBits type,task_t task,IOOptionBits mapFlags,IOVirtualAddress atAddress)2022a5e72196SApple OSS Distributions IOUserClient::mapClientMemory(
2023c1dac77fSApple OSS Distributions 	IOOptionBits            type,
2024c1dac77fSApple OSS Distributions 	task_t                  task,
2025fad439e7SApple OSS Distributions 	IOOptionBits            mapFlags,
2026fad439e7SApple OSS Distributions 	IOVirtualAddress        atAddress )
2027c1dac77fSApple OSS Distributions {
2028a5e72196SApple OSS Distributions 	return NULL;
2029c1dac77fSApple OSS Distributions }
20303ca3bd55SApple OSS Distributions #endif
2031c1dac77fSApple OSS Distributions 
2032a5e72196SApple OSS Distributions IOMemoryMap *
mapClientMemory64(IOOptionBits type,task_t task,IOOptionBits mapFlags,mach_vm_address_t atAddress)2033a5e72196SApple OSS Distributions IOUserClient::mapClientMemory64(
2034e13b1fa5SApple OSS Distributions 	IOOptionBits            type,
2035e13b1fa5SApple OSS Distributions 	task_t                  task,
2036e13b1fa5SApple OSS Distributions 	IOOptionBits            mapFlags,
2037e13b1fa5SApple OSS Distributions 	mach_vm_address_t       atAddress )
2038e13b1fa5SApple OSS Distributions {
2039e13b1fa5SApple OSS Distributions 	IOReturn            err;
2040e13b1fa5SApple OSS Distributions 	IOOptionBits        options = 0;
2041a5e72196SApple OSS Distributions 	IOMemoryDescriptor * memory = NULL;
2042a5e72196SApple OSS Distributions 	IOMemoryMap *       map = NULL;
2043e13b1fa5SApple OSS Distributions 
2044e13b1fa5SApple OSS Distributions 	err = clientMemoryForType((UInt32) type, &options, &memory );
2045e13b1fa5SApple OSS Distributions 
2046e13b1fa5SApple OSS Distributions 	if (memory && (kIOReturnSuccess == err)) {
204788cc0b97SApple OSS Distributions 		FAKE_STACK_FRAME(getMetaClass());
204888cc0b97SApple OSS Distributions 
2049e13b1fa5SApple OSS Distributions 		options = (options & ~kIOMapUserOptionsMask)
2050e13b1fa5SApple OSS Distributions 		    | (mapFlags & kIOMapUserOptionsMask);
2051e13b1fa5SApple OSS Distributions 		map = memory->createMappingInTask( task, atAddress, options );
2052e13b1fa5SApple OSS Distributions 		memory->release();
205388cc0b97SApple OSS Distributions 
205488cc0b97SApple OSS Distributions 		FAKE_STACK_FRAME_END();
2055e13b1fa5SApple OSS Distributions 	}
2056e13b1fa5SApple OSS Distributions 
2057a5e72196SApple OSS Distributions 	return map;
2058e13b1fa5SApple OSS Distributions }
2059e13b1fa5SApple OSS Distributions 
2060a5e72196SApple OSS Distributions IOReturn
exportObjectToClient(task_t task,OSObject * obj,io_object_t * clientObj)2061a5e72196SApple OSS Distributions IOUserClient::exportObjectToClient(task_t task,
2062c1dac77fSApple OSS Distributions     OSObject *obj, io_object_t *clientObj)
2063c1dac77fSApple OSS Distributions {
2064c1dac77fSApple OSS Distributions 	mach_port_name_t    name;
2065c1dac77fSApple OSS Distributions 
2066c1dac77fSApple OSS Distributions 	name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
2067c1dac77fSApple OSS Distributions 
2068a5e72196SApple OSS Distributions 	*clientObj = (io_object_t)(uintptr_t) name;
2069cc9a6355SApple OSS Distributions 
2070a5e72196SApple OSS Distributions 	if (obj) {
2071a5e72196SApple OSS Distributions 		obj->release();
2072a5e72196SApple OSS Distributions 	}
2073cc9a6355SApple OSS Distributions 
2074c1dac77fSApple OSS Distributions 	return kIOReturnSuccess;
2075c1dac77fSApple OSS Distributions }
2076c1dac77fSApple OSS Distributions 
2077a5e72196SApple OSS Distributions IOReturn
copyPortNameForObjectInTask(task_t task,OSObject * obj,mach_port_name_t * port_name)2078a5e72196SApple OSS Distributions IOUserClient::copyPortNameForObjectInTask(task_t task,
2079cc9a6355SApple OSS Distributions     OSObject *obj, mach_port_name_t * port_name)
2080cc9a6355SApple OSS Distributions {
2081cc9a6355SApple OSS Distributions 	mach_port_name_t    name;
2082cc9a6355SApple OSS Distributions 
2083cc9a6355SApple OSS Distributions 	name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_IDENT );
2084cc9a6355SApple OSS Distributions 
2085cc9a6355SApple OSS Distributions 	*(mach_port_name_t *) port_name = name;
2086cc9a6355SApple OSS Distributions 
2087cc9a6355SApple OSS Distributions 	return kIOReturnSuccess;
2088cc9a6355SApple OSS Distributions }
2089cc9a6355SApple OSS Distributions 
2090a5e72196SApple OSS Distributions IOReturn
copyObjectForPortNameInTask(task_t task,mach_port_name_t port_name,OSObject ** obj)2091a5e72196SApple OSS Distributions IOUserClient::copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
2092cc9a6355SApple OSS Distributions     OSObject **obj)
2093cc9a6355SApple OSS Distributions {
2094cc9a6355SApple OSS Distributions 	OSObject * object;
2095cc9a6355SApple OSS Distributions 
2096cc9a6355SApple OSS Distributions 	object = iokit_lookup_object_with_port_name(port_name, IKOT_IOKIT_IDENT, task);
2097cc9a6355SApple OSS Distributions 
2098cc9a6355SApple OSS Distributions 	*obj = object;
2099cc9a6355SApple OSS Distributions 
2100a5e72196SApple OSS Distributions 	return object ? kIOReturnSuccess : kIOReturnIPCError;
2101cc9a6355SApple OSS Distributions }
2102cc9a6355SApple OSS Distributions 
2103a5e72196SApple OSS Distributions IOReturn
copyObjectForPortNameInTask(task_t task,mach_port_name_t port_name,OSSharedPtr<OSObject> & obj)2104bb611c8fSApple OSS Distributions IOUserClient::copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
2105bb611c8fSApple OSS Distributions     OSSharedPtr<OSObject>& obj)
2106bb611c8fSApple OSS Distributions {
2107bb611c8fSApple OSS Distributions 	OSObject* objRaw = NULL;
2108bb611c8fSApple OSS Distributions 	IOReturn result = copyObjectForPortNameInTask(task, port_name, &objRaw);
2109bb611c8fSApple OSS Distributions 	obj.reset(objRaw, OSNoRetain);
2110bb611c8fSApple OSS Distributions 	return result;
2111bb611c8fSApple OSS Distributions }
2112bb611c8fSApple OSS Distributions 
2113bb611c8fSApple OSS Distributions IOReturn
adjustPortNameReferencesInTask(task_t task,mach_port_name_t port_name,mach_port_delta_t delta)2114a5e72196SApple OSS Distributions IOUserClient::adjustPortNameReferencesInTask(task_t task, mach_port_name_t port_name, mach_port_delta_t delta)
2115cc9a6355SApple OSS Distributions {
2116a5e72196SApple OSS Distributions 	return iokit_mod_send_right(task, port_name, delta);
2117cc9a6355SApple OSS Distributions }
2118cc9a6355SApple OSS Distributions 
2119a5e72196SApple OSS Distributions IOExternalMethod *
getExternalMethodForIndex(UInt32)2120a5e72196SApple OSS Distributions IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
2121c1dac77fSApple OSS Distributions {
2122a5e72196SApple OSS Distributions 	return NULL;
2123c1dac77fSApple OSS Distributions }
2124c1dac77fSApple OSS Distributions 
2125a5e72196SApple OSS Distributions IOExternalAsyncMethod *
getExternalAsyncMethodForIndex(UInt32)2126a5e72196SApple OSS Distributions IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
2127c1dac77fSApple OSS Distributions {
2128a5e72196SApple OSS Distributions 	return NULL;
2129c1dac77fSApple OSS Distributions }
2130c1dac77fSApple OSS Distributions 
2131a5e72196SApple OSS Distributions IOExternalTrap *
2132a5e72196SApple OSS Distributions IOUserClient::
getExternalTrapForIndex(UInt32 index)213388cc0b97SApple OSS Distributions getExternalTrapForIndex(UInt32 index)
213488cc0b97SApple OSS Distributions {
213588cc0b97SApple OSS Distributions 	return NULL;
213688cc0b97SApple OSS Distributions }
213788cc0b97SApple OSS Distributions 
213888cc0b97SApple OSS Distributions #pragma clang diagnostic push
213988cc0b97SApple OSS Distributions #pragma clang diagnostic ignored "-Wdeprecated-declarations"
214088cc0b97SApple OSS Distributions 
214188cc0b97SApple OSS Distributions // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
214288cc0b97SApple OSS Distributions // functions can break clients of kexts implementing getExternalMethodForIndex()
2143a5e72196SApple OSS Distributions IOExternalMethod *
2144a5e72196SApple OSS Distributions IOUserClient::
getTargetAndMethodForIndex(IOService ** targetP,UInt32 index)2145c1dac77fSApple OSS Distributions getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
2146c1dac77fSApple OSS Distributions {
2147c1dac77fSApple OSS Distributions 	IOExternalMethod *method = getExternalMethodForIndex(index);
2148c1dac77fSApple OSS Distributions 
2149a5e72196SApple OSS Distributions 	if (method) {
2150c1dac77fSApple OSS Distributions 		*targetP = (IOService *) method->object;
2151a5e72196SApple OSS Distributions 	}
2152c1dac77fSApple OSS Distributions 
2153c1dac77fSApple OSS Distributions 	return method;
2154c1dac77fSApple OSS Distributions }
2155c1dac77fSApple OSS Distributions 
2156bb611c8fSApple OSS Distributions IOExternalMethod *
2157bb611c8fSApple OSS Distributions IOUserClient::
getTargetAndMethodForIndex(OSSharedPtr<IOService> & targetP,UInt32 index)2158bb611c8fSApple OSS Distributions getTargetAndMethodForIndex(OSSharedPtr<IOService>& targetP, UInt32 index)
2159bb611c8fSApple OSS Distributions {
2160bb611c8fSApple OSS Distributions 	IOService* targetPRaw = NULL;
2161bb611c8fSApple OSS Distributions 	IOExternalMethod* result = getTargetAndMethodForIndex(&targetPRaw, index);
2162bb611c8fSApple OSS Distributions 	targetP.reset(targetPRaw, OSRetain);
2163bb611c8fSApple OSS Distributions 	return result;
2164bb611c8fSApple OSS Distributions }
2165bb611c8fSApple OSS Distributions 
2166a5e72196SApple OSS Distributions IOExternalAsyncMethod *
2167a5e72196SApple OSS Distributions IOUserClient::
getAsyncTargetAndMethodForIndex(IOService ** targetP,UInt32 index)2168c1dac77fSApple OSS Distributions getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
2169c1dac77fSApple OSS Distributions {
2170c1dac77fSApple OSS Distributions 	IOExternalAsyncMethod *method = getExternalAsyncMethodForIndex(index);
2171c1dac77fSApple OSS Distributions 
2172a5e72196SApple OSS Distributions 	if (method) {
2173c1dac77fSApple OSS Distributions 		*targetP = (IOService *) method->object;
2174a5e72196SApple OSS Distributions 	}
2175c1dac77fSApple OSS Distributions 
2176c1dac77fSApple OSS Distributions 	return method;
2177c1dac77fSApple OSS Distributions }
2178c1dac77fSApple OSS Distributions 
2179bb611c8fSApple OSS Distributions IOExternalAsyncMethod *
2180bb611c8fSApple OSS Distributions IOUserClient::
getAsyncTargetAndMethodForIndex(OSSharedPtr<IOService> & targetP,UInt32 index)2181bb611c8fSApple OSS Distributions getAsyncTargetAndMethodForIndex(OSSharedPtr<IOService>& targetP, UInt32 index)
2182bb611c8fSApple OSS Distributions {
2183bb611c8fSApple OSS Distributions 	IOService* targetPRaw = NULL;
2184bb611c8fSApple OSS Distributions 	IOExternalAsyncMethod* result = getAsyncTargetAndMethodForIndex(&targetPRaw, index);
2185bb611c8fSApple OSS Distributions 	targetP.reset(targetPRaw, OSRetain);
2186bb611c8fSApple OSS Distributions 	return result;
2187bb611c8fSApple OSS Distributions }
2188bb611c8fSApple OSS Distributions 
2189a5e72196SApple OSS Distributions IOExternalTrap *
2190a5e72196SApple OSS Distributions IOUserClient::
getTargetAndTrapForIndex(IOService ** targetP,UInt32 index)2191c1dac77fSApple OSS Distributions getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
2192c1dac77fSApple OSS Distributions {
2193c1dac77fSApple OSS Distributions 	IOExternalTrap *trap = getExternalTrapForIndex(index);
2194c1dac77fSApple OSS Distributions 
2195c1dac77fSApple OSS Distributions 	if (trap) {
2196c1dac77fSApple OSS Distributions 		*targetP = trap->object;
2197c1dac77fSApple OSS Distributions 	}
2198c1dac77fSApple OSS Distributions 
2199c1dac77fSApple OSS Distributions 	return trap;
2200c1dac77fSApple OSS Distributions }
220188cc0b97SApple OSS Distributions #pragma clang diagnostic pop
2202c1dac77fSApple OSS Distributions 
2203a5e72196SApple OSS Distributions IOReturn
releaseAsyncReference64(OSAsyncReference64 reference)2204a5e72196SApple OSS Distributions IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference)
22053ca3bd55SApple OSS Distributions {
22063ca3bd55SApple OSS Distributions 	mach_port_t port;
22073ca3bd55SApple OSS Distributions 	port = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags);
22083ca3bd55SApple OSS Distributions 
2209a5e72196SApple OSS Distributions 	if (MACH_PORT_NULL != port) {
22103ca3bd55SApple OSS Distributions 		iokit_release_port_send(port);
22113ca3bd55SApple OSS Distributions 	}
22123ca3bd55SApple OSS Distributions 
2213a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2214a5e72196SApple OSS Distributions }
2215a5e72196SApple OSS Distributions 
2216a5e72196SApple OSS Distributions IOReturn
releaseNotificationPort(mach_port_t port)2217a5e72196SApple OSS Distributions IOUserClient::releaseNotificationPort(mach_port_t port)
22183ca3bd55SApple OSS Distributions {
2219a5e72196SApple OSS Distributions 	if (MACH_PORT_NULL != port) {
22203ca3bd55SApple OSS Distributions 		iokit_release_port_send(port);
22213ca3bd55SApple OSS Distributions 	}
22223ca3bd55SApple OSS Distributions 
2223a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2224a5e72196SApple OSS Distributions }
2225a5e72196SApple OSS Distributions 
2226a5e72196SApple OSS Distributions IOReturn
sendAsyncResult(OSAsyncReference reference,IOReturn result,void * args[],UInt32 numArgs)2227a5e72196SApple OSS Distributions IOUserClient::sendAsyncResult(OSAsyncReference reference,
2228c1dac77fSApple OSS Distributions     IOReturn result, void *args[], UInt32 numArgs)
2229c1dac77fSApple OSS Distributions {
2230e13b1fa5SApple OSS Distributions 	OSAsyncReference64  reference64;
22315c2921b0SApple OSS Distributions 	OSBoundedArray<io_user_reference_t, kMaxAsyncArgs> args64;
2232e13b1fa5SApple OSS Distributions 	unsigned int        idx;
2233e13b1fa5SApple OSS Distributions 
2234a5e72196SApple OSS Distributions 	if (numArgs > kMaxAsyncArgs) {
2235e13b1fa5SApple OSS Distributions 		return kIOReturnMessageTooLarge;
2236e13b1fa5SApple OSS Distributions 	}
2237e13b1fa5SApple OSS Distributions 
2238a5e72196SApple OSS Distributions 	for (idx = 0; idx < kOSAsyncRef64Count; idx++) {
2239a5e72196SApple OSS Distributions 		reference64[idx] = REF64(reference[idx]);
2240a5e72196SApple OSS Distributions 	}
2241a5e72196SApple OSS Distributions 
2242a5e72196SApple OSS Distributions 	for (idx = 0; idx < numArgs; idx++) {
2243a5e72196SApple OSS Distributions 		args64[idx] = REF64(args[idx]);
2244a5e72196SApple OSS Distributions 	}
2245a5e72196SApple OSS Distributions 
22465c2921b0SApple OSS Distributions 	return sendAsyncResult64(reference64, result, args64.data(), numArgs);
2247a5e72196SApple OSS Distributions }
2248a5e72196SApple OSS Distributions 
2249a5e72196SApple OSS Distributions IOReturn
sendAsyncResult64WithOptions(OSAsyncReference64 reference,IOReturn result,io_user_reference_t args[],UInt32 numArgs,IOOptionBits options)2250a5e72196SApple OSS Distributions IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference,
2251186b8fceSApple OSS Distributions     IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options)
2252186b8fceSApple OSS Distributions {
2253186b8fceSApple OSS Distributions 	return _sendAsyncResult64(reference, result, args, numArgs, options);
2254186b8fceSApple OSS Distributions }
2255186b8fceSApple OSS Distributions 
2256a5e72196SApple OSS Distributions IOReturn
sendAsyncResult64(OSAsyncReference64 reference,IOReturn result,io_user_reference_t args[],UInt32 numArgs)2257a5e72196SApple OSS Distributions IOUserClient::sendAsyncResult64(OSAsyncReference64 reference,
2258e13b1fa5SApple OSS Distributions     IOReturn result, io_user_reference_t args[], UInt32 numArgs)
2259e13b1fa5SApple OSS Distributions {
2260186b8fceSApple OSS Distributions 	return _sendAsyncResult64(reference, result, args, numArgs, 0);
2261186b8fceSApple OSS Distributions }
2262186b8fceSApple OSS Distributions 
2263a5e72196SApple OSS Distributions IOReturn
_sendAsyncResult64(OSAsyncReference64 reference,IOReturn result,io_user_reference_t args[],UInt32 numArgs,IOOptionBits options)2264a5e72196SApple OSS Distributions IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference,
2265186b8fceSApple OSS Distributions     IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options)
2266186b8fceSApple OSS Distributions {
2267a5e72196SApple OSS Distributions 	struct ReplyMsg {
2268c1dac77fSApple OSS Distributions 		mach_msg_header_t msgHdr;
2269a5e72196SApple OSS Distributions 		union{
2270a5e72196SApple OSS Distributions 			struct{
2271c1dac77fSApple OSS Distributions 				OSNotificationHeader     notifyHdr;
2272c1dac77fSApple OSS Distributions 				IOAsyncCompletionContent asyncContent;
2273e13b1fa5SApple OSS Distributions 				uint32_t                 args[kMaxAsyncArgs];
2274e13b1fa5SApple OSS Distributions 			} msg32;
2275a5e72196SApple OSS Distributions 			struct{
2276e13b1fa5SApple OSS Distributions 				OSNotificationHeader64   notifyHdr;
2277e13b1fa5SApple OSS Distributions 				IOAsyncCompletionContent asyncContent;
22783ca3bd55SApple OSS Distributions 				io_user_reference_t      args[kMaxAsyncArgs] __attribute__ ((packed));
2279e13b1fa5SApple OSS Distributions 			} msg64;
2280e13b1fa5SApple OSS Distributions 		} m;
2281c1dac77fSApple OSS Distributions 	};
2282c1dac77fSApple OSS Distributions 	ReplyMsg      replyMsg;
2283c1dac77fSApple OSS Distributions 	mach_port_t   replyPort;
2284c1dac77fSApple OSS Distributions 	kern_return_t kr;
2285c1dac77fSApple OSS Distributions 
2286c1dac77fSApple OSS Distributions 	// If no reply port, do nothing.
2287e13b1fa5SApple OSS Distributions 	replyPort = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags);
2288a5e72196SApple OSS Distributions 	if (replyPort == MACH_PORT_NULL) {
2289c1dac77fSApple OSS Distributions 		return kIOReturnSuccess;
2290a5e72196SApple OSS Distributions 	}
2291c1dac77fSApple OSS Distributions 
2292a5e72196SApple OSS Distributions 	if (numArgs > kMaxAsyncArgs) {
2293c1dac77fSApple OSS Distributions 		return kIOReturnMessageTooLarge;
2294a5e72196SApple OSS Distributions 	}
2295e13b1fa5SApple OSS Distributions 
229688cc0b97SApple OSS Distributions 	bzero(&replyMsg, sizeof(replyMsg));
2297368ad365SApple OSS Distributions 	replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
2298368ad365SApple OSS Distributions 	    0 /*local*/);
2299c1dac77fSApple OSS Distributions 	replyMsg.msgHdr.msgh_remote_port = replyPort;
2300a5e72196SApple OSS Distributions 	replyMsg.msgHdr.msgh_local_port  = NULL;
2301c1dac77fSApple OSS Distributions 	replyMsg.msgHdr.msgh_id          = kOSNotificationMessageID;
2302a5e72196SApple OSS Distributions 	if (kIOUCAsync64Flag & reference[0]) {
2303e13b1fa5SApple OSS Distributions 		replyMsg.msgHdr.msgh_size =
2304e13b1fa5SApple OSS Distributions 		    sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg64)
2305e13b1fa5SApple OSS Distributions 		    - (kMaxAsyncArgs - numArgs) * sizeof(io_user_reference_t);
2306e13b1fa5SApple OSS Distributions 		replyMsg.m.msg64.notifyHdr.size = sizeof(IOAsyncCompletionContent)
2307e13b1fa5SApple OSS Distributions 		    + numArgs * sizeof(io_user_reference_t);
2308e13b1fa5SApple OSS Distributions 		replyMsg.m.msg64.notifyHdr.type = kIOAsyncCompletionNotificationType;
2309bb611c8fSApple OSS Distributions 		/* Copy reference except for reference[0], which is left as 0 from the earlier bzero */
2310bb611c8fSApple OSS Distributions 		bcopy(&reference[1], &replyMsg.m.msg64.notifyHdr.reference[1], sizeof(OSAsyncReference64) - sizeof(reference[0]));
2311c1dac77fSApple OSS Distributions 
2312e13b1fa5SApple OSS Distributions 		replyMsg.m.msg64.asyncContent.result = result;
2313a5e72196SApple OSS Distributions 		if (numArgs) {
2314e13b1fa5SApple OSS Distributions 			bcopy(args, replyMsg.m.msg64.args, numArgs * sizeof(io_user_reference_t));
2315e13b1fa5SApple OSS Distributions 		}
2316a5e72196SApple OSS Distributions 	} else {
2317e13b1fa5SApple OSS Distributions 		unsigned int idx;
2318c1dac77fSApple OSS Distributions 
2319e13b1fa5SApple OSS Distributions 		replyMsg.msgHdr.msgh_size =
2320e13b1fa5SApple OSS Distributions 		    sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg32)
2321e13b1fa5SApple OSS Distributions 		    - (kMaxAsyncArgs - numArgs) * sizeof(uint32_t);
2322e13b1fa5SApple OSS Distributions 
2323e13b1fa5SApple OSS Distributions 		replyMsg.m.msg32.notifyHdr.size = sizeof(IOAsyncCompletionContent)
2324e13b1fa5SApple OSS Distributions 		    + numArgs * sizeof(uint32_t);
2325e13b1fa5SApple OSS Distributions 		replyMsg.m.msg32.notifyHdr.type = kIOAsyncCompletionNotificationType;
2326e13b1fa5SApple OSS Distributions 
2327bb611c8fSApple OSS Distributions 		/* Skip reference[0] which is left as 0 from the earlier bzero */
2328bb611c8fSApple OSS Distributions 		for (idx = 1; idx < kOSAsyncRefCount; idx++) {
2329e13b1fa5SApple OSS Distributions 			replyMsg.m.msg32.notifyHdr.reference[idx] = REF32(reference[idx]);
2330a5e72196SApple OSS Distributions 		}
2331e13b1fa5SApple OSS Distributions 
2332e13b1fa5SApple OSS Distributions 		replyMsg.m.msg32.asyncContent.result = result;
2333e13b1fa5SApple OSS Distributions 
2334a5e72196SApple OSS Distributions 		for (idx = 0; idx < numArgs; idx++) {
2335e13b1fa5SApple OSS Distributions 			replyMsg.m.msg32.args[idx] = REF32(args[idx]);
2336e13b1fa5SApple OSS Distributions 		}
2337a5e72196SApple OSS Distributions 	}
2338e13b1fa5SApple OSS Distributions 
2339186b8fceSApple OSS Distributions 	if ((options & kIOUserNotifyOptionCanDrop) != 0) {
2340186b8fceSApple OSS Distributions 		kr = mach_msg_send_from_kernel_with_options( &replyMsg.msgHdr,
2341*8d741a5dSApple OSS Distributions 		    replyMsg.msgHdr.msgh_size, MACH64_SEND_TIMEOUT, MACH_MSG_TIMEOUT_NONE);
2342186b8fceSApple OSS Distributions 	} else {
2343186b8fceSApple OSS Distributions 		/* Fail on full queue. */
2344*8d741a5dSApple OSS Distributions 		kr = mach_msg_send_from_kernel(&replyMsg.msgHdr,
2345c1dac77fSApple OSS Distributions 		    replyMsg.msgHdr.msgh_size);
2346186b8fceSApple OSS Distributions 	}
2347a5e72196SApple OSS Distributions 	if ((KERN_SUCCESS != kr) && (MACH_SEND_TIMED_OUT != kr) && !(kIOUCAsyncErrorLoggedFlag & reference[0])) {
234888cc0b97SApple OSS Distributions 		reference[0] |= kIOUCAsyncErrorLoggedFlag;
2349*8d741a5dSApple OSS Distributions 		IOLog("%s: mach_msg_send_from_kernel(0x%x)\n", __PRETTY_FUNCTION__, kr );
235088cc0b97SApple OSS Distributions 	}
2351c1dac77fSApple OSS Distributions 	return kr;
2352c1dac77fSApple OSS Distributions }
2353c1dac77fSApple OSS Distributions 
2354e13b1fa5SApple OSS Distributions 
2355c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2356c1dac77fSApple OSS Distributions 
2357c1dac77fSApple OSS Distributions extern "C" {
2358c1dac77fSApple OSS Distributions #define CHECK(cls, obj, out)                      \
2359c1dac77fSApple OSS Distributions 	cls * out;                              \
2360c1dac77fSApple OSS Distributions 	if( !(out = OSDynamicCast( cls, obj)))  \
2361c1dac77fSApple OSS Distributions 	    return( kIOReturnBadArgument )
2362c1dac77fSApple OSS Distributions 
23638dd02465SApple OSS Distributions #define CHECKLOCKED(cls, obj, out)                                        \
23648dd02465SApple OSS Distributions 	IOUserIterator * oIter;                                         \
23658dd02465SApple OSS Distributions 	cls * out;                                                      \
23668dd02465SApple OSS Distributions 	if( !(oIter = OSDynamicCast(IOUserIterator, obj)))              \
23678dd02465SApple OSS Distributions 	    return (kIOReturnBadArgument);                              \
23688dd02465SApple OSS Distributions 	if( !(out = OSDynamicCast(cls, oIter->userIteratorObject)))     \
23698dd02465SApple OSS Distributions 	    return (kIOReturnBadArgument)
23708dd02465SApple OSS Distributions 
2371a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2372a3bb9fccSApple OSS Distributions 
23730f3703acSApple OSS Distributions // Create a vm_map_copy_t or kalloc'ed data for memory
23740f3703acSApple OSS Distributions // to be copied out. ipc will free after the copyout.
23750f3703acSApple OSS Distributions 
2376a5e72196SApple OSS Distributions static kern_return_t
copyoutkdata(const void * data,vm_size_t len,io_buf_ptr_t * buf)2377a5e72196SApple OSS Distributions copyoutkdata( const void * data, vm_size_t len,
23780f3703acSApple OSS Distributions     io_buf_ptr_t * buf )
23790f3703acSApple OSS Distributions {
23800f3703acSApple OSS Distributions 	kern_return_t       err;
23810f3703acSApple OSS Distributions 	vm_map_copy_t       copy;
23820f3703acSApple OSS Distributions 
23830f3703acSApple OSS Distributions 	err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
23840f3703acSApple OSS Distributions 	    false /* src_destroy */, &copy);
23850f3703acSApple OSS Distributions 
23860f3703acSApple OSS Distributions 	assert( err == KERN_SUCCESS );
2387a5e72196SApple OSS Distributions 	if (err == KERN_SUCCESS) {
23880f3703acSApple OSS Distributions 		*buf = (char *) copy;
2389a5e72196SApple OSS Distributions 	}
23900f3703acSApple OSS Distributions 
2391a5e72196SApple OSS Distributions 	return err;
23920f3703acSApple OSS Distributions }
23930f3703acSApple OSS Distributions 
23940f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
23950f3703acSApple OSS Distributions 
2396a3bb9fccSApple OSS Distributions /* Routine io_server_version */
2397a5e72196SApple OSS Distributions kern_return_t
is_io_server_version(mach_port_t main_port,uint64_t * version)2398a5e72196SApple OSS Distributions is_io_server_version(
23995c2921b0SApple OSS Distributions 	mach_port_t main_port,
2400a3bb9fccSApple OSS Distributions 	uint64_t *version)
2401a3bb9fccSApple OSS Distributions {
2402a3bb9fccSApple OSS Distributions 	*version = IOKIT_SERVER_VERSION;
2403a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2404a3bb9fccSApple OSS Distributions }
2405a3bb9fccSApple OSS Distributions 
2406c1dac77fSApple OSS Distributions /* Routine io_object_get_class */
2407a5e72196SApple OSS Distributions kern_return_t
is_io_object_get_class(io_object_t object,io_name_t className)2408a5e72196SApple OSS Distributions is_io_object_get_class(
2409c1dac77fSApple OSS Distributions 	io_object_t object,
2410c1dac77fSApple OSS Distributions 	io_name_t className )
2411c1dac77fSApple OSS Distributions {
241214e3d835SApple OSS Distributions 	const OSMetaClass* my_obj = NULL;
241314e3d835SApple OSS Distributions 
2414a5e72196SApple OSS Distributions 	if (!object) {
2415a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2416a5e72196SApple OSS Distributions 	}
2417c1dac77fSApple OSS Distributions 
241814e3d835SApple OSS Distributions 	my_obj = object->getMetaClass();
241914e3d835SApple OSS Distributions 	if (!my_obj) {
2420a5e72196SApple OSS Distributions 		return kIOReturnNotFound;
242114e3d835SApple OSS Distributions 	}
242214e3d835SApple OSS Distributions 
242388cc0b97SApple OSS Distributions 	strlcpy( className, my_obj->getClassName(), sizeof(io_name_t));
24240f3703acSApple OSS Distributions 
2425a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2426c1dac77fSApple OSS Distributions }
2427c1dac77fSApple OSS Distributions 
242814e3d835SApple OSS Distributions /* Routine io_object_get_superclass */
2429a5e72196SApple OSS Distributions kern_return_t
is_io_object_get_superclass(mach_port_t main_port,io_name_t obj_name,io_name_t class_name)2430a5e72196SApple OSS Distributions is_io_object_get_superclass(
24315c2921b0SApple OSS Distributions 	mach_port_t main_port,
243214e3d835SApple OSS Distributions 	io_name_t obj_name,
243314e3d835SApple OSS Distributions 	io_name_t class_name)
243414e3d835SApple OSS Distributions {
243576e12aa3SApple OSS Distributions 	IOReturn            ret;
243676e12aa3SApple OSS Distributions 	const OSMetaClass * meta;
243776e12aa3SApple OSS Distributions 	const OSMetaClass * super;
243876e12aa3SApple OSS Distributions 	const OSSymbol    * name;
243976e12aa3SApple OSS Distributions 	const char        * cstr;
244014e3d835SApple OSS Distributions 
2441a5e72196SApple OSS Distributions 	if (!obj_name || !class_name) {
2442a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2443a5e72196SApple OSS Distributions 	}
24445c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
2445a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
2446a5e72196SApple OSS Distributions 	}
244714e3d835SApple OSS Distributions 
244876e12aa3SApple OSS Distributions 	ret = kIOReturnNotFound;
2449a5e72196SApple OSS Distributions 	meta = NULL;
2450a5e72196SApple OSS Distributions 	do{
245176e12aa3SApple OSS Distributions 		name = OSSymbol::withCString(obj_name);
2452a5e72196SApple OSS Distributions 		if (!name) {
2453a5e72196SApple OSS Distributions 			break;
2454a5e72196SApple OSS Distributions 		}
24555c2921b0SApple OSS Distributions 		meta = OSMetaClass::copyMetaClassWithName(name);
2456a5e72196SApple OSS Distributions 		if (!meta) {
2457a5e72196SApple OSS Distributions 			break;
2458a5e72196SApple OSS Distributions 		}
245976e12aa3SApple OSS Distributions 		super = meta->getSuperClass();
2460a5e72196SApple OSS Distributions 		if (!super) {
2461a5e72196SApple OSS Distributions 			break;
2462a5e72196SApple OSS Distributions 		}
246376e12aa3SApple OSS Distributions 		cstr = super->getClassName();
2464a5e72196SApple OSS Distributions 		if (!cstr) {
2465a5e72196SApple OSS Distributions 			break;
2466a5e72196SApple OSS Distributions 		}
246776e12aa3SApple OSS Distributions 		strlcpy(class_name, cstr, sizeof(io_name_t));
246876e12aa3SApple OSS Distributions 		ret = kIOReturnSuccess;
2469a5e72196SApple OSS Distributions 	}while (false);
247014e3d835SApple OSS Distributions 
247176e12aa3SApple OSS Distributions 	OSSafeReleaseNULL(name);
2472a5e72196SApple OSS Distributions 	if (meta) {
2473a5e72196SApple OSS Distributions 		meta->releaseMetaClass();
2474a5e72196SApple OSS Distributions 	}
247514e3d835SApple OSS Distributions 
2476a5e72196SApple OSS Distributions 	return ret;
247714e3d835SApple OSS Distributions }
247814e3d835SApple OSS Distributions 
247914e3d835SApple OSS Distributions /* Routine io_object_get_bundle_identifier */
2480a5e72196SApple OSS Distributions kern_return_t
is_io_object_get_bundle_identifier(mach_port_t main_port,io_name_t obj_name,io_name_t bundle_name)2481a5e72196SApple OSS Distributions is_io_object_get_bundle_identifier(
24825c2921b0SApple OSS Distributions 	mach_port_t main_port,
248314e3d835SApple OSS Distributions 	io_name_t obj_name,
248414e3d835SApple OSS Distributions 	io_name_t bundle_name)
248514e3d835SApple OSS Distributions {
248676e12aa3SApple OSS Distributions 	IOReturn            ret;
248776e12aa3SApple OSS Distributions 	const OSMetaClass * meta;
248876e12aa3SApple OSS Distributions 	const OSSymbol    * name;
248976e12aa3SApple OSS Distributions 	const OSSymbol    * identifier;
249076e12aa3SApple OSS Distributions 	const char        * cstr;
249114e3d835SApple OSS Distributions 
2492a5e72196SApple OSS Distributions 	if (!obj_name || !bundle_name) {
2493a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2494a5e72196SApple OSS Distributions 	}
24955c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
2496a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
2497a5e72196SApple OSS Distributions 	}
249814e3d835SApple OSS Distributions 
249976e12aa3SApple OSS Distributions 	ret = kIOReturnNotFound;
2500a5e72196SApple OSS Distributions 	meta = NULL;
2501a5e72196SApple OSS Distributions 	do{
250276e12aa3SApple OSS Distributions 		name = OSSymbol::withCString(obj_name);
2503a5e72196SApple OSS Distributions 		if (!name) {
2504a5e72196SApple OSS Distributions 			break;
2505a5e72196SApple OSS Distributions 		}
25065c2921b0SApple OSS Distributions 		meta = OSMetaClass::copyMetaClassWithName(name);
2507a5e72196SApple OSS Distributions 		if (!meta) {
2508a5e72196SApple OSS Distributions 			break;
2509a5e72196SApple OSS Distributions 		}
251076e12aa3SApple OSS Distributions 		identifier = meta->getKmodName();
2511a5e72196SApple OSS Distributions 		if (!identifier) {
2512a5e72196SApple OSS Distributions 			break;
2513a5e72196SApple OSS Distributions 		}
251476e12aa3SApple OSS Distributions 		cstr = identifier->getCStringNoCopy();
2515a5e72196SApple OSS Distributions 		if (!cstr) {
2516a5e72196SApple OSS Distributions 			break;
2517a5e72196SApple OSS Distributions 		}
2518e13b1fa5SApple OSS Distributions 		strlcpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t));
251976e12aa3SApple OSS Distributions 		ret = kIOReturnSuccess;
2520a5e72196SApple OSS Distributions 	}while (false);
252114e3d835SApple OSS Distributions 
252276e12aa3SApple OSS Distributions 	OSSafeReleaseNULL(name);
2523a5e72196SApple OSS Distributions 	if (meta) {
2524a5e72196SApple OSS Distributions 		meta->releaseMetaClass();
2525a5e72196SApple OSS Distributions 	}
252676e12aa3SApple OSS Distributions 
2527a5e72196SApple OSS Distributions 	return ret;
252814e3d835SApple OSS Distributions }
252914e3d835SApple OSS Distributions 
2530c1dac77fSApple OSS Distributions /* Routine io_object_conforms_to */
2531a5e72196SApple OSS Distributions kern_return_t
is_io_object_conforms_to(io_object_t object,io_name_t className,boolean_t * conforms)2532a5e72196SApple OSS Distributions is_io_object_conforms_to(
2533c1dac77fSApple OSS Distributions 	io_object_t object,
2534c1dac77fSApple OSS Distributions 	io_name_t className,
2535c1dac77fSApple OSS Distributions 	boolean_t *conforms )
2536c1dac77fSApple OSS Distributions {
2537a5e72196SApple OSS Distributions 	if (!object) {
2538a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2539a5e72196SApple OSS Distributions 	}
2540c1dac77fSApple OSS Distributions 
2541a5e72196SApple OSS Distributions 	*conforms = (NULL != object->metaCast( className ));
25420f3703acSApple OSS Distributions 
2543a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2544c1dac77fSApple OSS Distributions }
2545c1dac77fSApple OSS Distributions 
2546c1dac77fSApple OSS Distributions /* Routine io_object_get_retain_count */
2547a5e72196SApple OSS Distributions kern_return_t
is_io_object_get_retain_count(io_object_t object,uint32_t * retainCount)2548a5e72196SApple OSS Distributions is_io_object_get_retain_count(
2549c1dac77fSApple OSS Distributions 	io_object_t object,
2550e13b1fa5SApple OSS Distributions 	uint32_t *retainCount )
2551c1dac77fSApple OSS Distributions {
2552a5e72196SApple OSS Distributions 	if (!object) {
2553a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2554a5e72196SApple OSS Distributions 	}
2555c1dac77fSApple OSS Distributions 
2556c1dac77fSApple OSS Distributions 	*retainCount = object->getRetainCount();
2557a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2558c1dac77fSApple OSS Distributions }
2559c1dac77fSApple OSS Distributions 
2560c1dac77fSApple OSS Distributions /* Routine io_iterator_next */
2561a5e72196SApple OSS Distributions kern_return_t
is_io_iterator_next(io_object_t iterator,io_object_t * object)2562a5e72196SApple OSS Distributions is_io_iterator_next(
2563c1dac77fSApple OSS Distributions 	io_object_t iterator,
2564c1dac77fSApple OSS Distributions 	io_object_t *object )
2565c1dac77fSApple OSS Distributions {
25668dd02465SApple OSS Distributions 	IOReturn    ret;
2567c1dac77fSApple OSS Distributions 	OSObject *  obj;
2568cc9a6355SApple OSS Distributions 	OSIterator * iter;
2569cc9a6355SApple OSS Distributions 	IOUserIterator * uiter;
2570c1dac77fSApple OSS Distributions 
2571a5e72196SApple OSS Distributions 	if ((uiter = OSDynamicCast(IOUserIterator, iterator))) {
2572cc9a6355SApple OSS Distributions 		obj = uiter->copyNextObject();
2573a5e72196SApple OSS Distributions 	} else if ((iter = OSDynamicCast(OSIterator, iterator))) {
2574c1dac77fSApple OSS Distributions 		obj = iter->getNextObject();
2575a5e72196SApple OSS Distributions 		if (obj) {
2576a5e72196SApple OSS Distributions 			obj->retain();
2577cc9a6355SApple OSS Distributions 		}
2578a5e72196SApple OSS Distributions 	} else {
2579a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2580cc9a6355SApple OSS Distributions 	}
2581cc9a6355SApple OSS Distributions 
2582c1dac77fSApple OSS Distributions 	if (obj) {
2583c1dac77fSApple OSS Distributions 		*object = obj;
25848dd02465SApple OSS Distributions 		ret = kIOReturnSuccess;
2585a5e72196SApple OSS Distributions 	} else {
25868dd02465SApple OSS Distributions 		ret = kIOReturnNoDevice;
2587a5e72196SApple OSS Distributions 	}
25888dd02465SApple OSS Distributions 
2589a5e72196SApple OSS Distributions 	return ret;
2590c1dac77fSApple OSS Distributions }
2591c1dac77fSApple OSS Distributions 
2592c1dac77fSApple OSS Distributions /* Routine io_iterator_reset */
2593a5e72196SApple OSS Distributions kern_return_t
is_io_iterator_reset(io_object_t iterator)2594a5e72196SApple OSS Distributions is_io_iterator_reset(
2595c1dac77fSApple OSS Distributions 	io_object_t iterator )
2596c1dac77fSApple OSS Distributions {
2597c1dac77fSApple OSS Distributions 	CHECK( OSIterator, iterator, iter );
2598c1dac77fSApple OSS Distributions 
2599c1dac77fSApple OSS Distributions 	iter->reset();
2600c1dac77fSApple OSS Distributions 
2601a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2602c1dac77fSApple OSS Distributions }
2603c1dac77fSApple OSS Distributions 
2604c1dac77fSApple OSS Distributions /* Routine io_iterator_is_valid */
2605a5e72196SApple OSS Distributions kern_return_t
is_io_iterator_is_valid(io_object_t iterator,boolean_t * is_valid)2606a5e72196SApple OSS Distributions is_io_iterator_is_valid(
2607c1dac77fSApple OSS Distributions 	io_object_t iterator,
2608c1dac77fSApple OSS Distributions 	boolean_t *is_valid )
2609c1dac77fSApple OSS Distributions {
2610c1dac77fSApple OSS Distributions 	CHECK( OSIterator, iterator, iter );
2611c1dac77fSApple OSS Distributions 
2612c1dac77fSApple OSS Distributions 	*is_valid = iter->isValid();
2613c1dac77fSApple OSS Distributions 
2614a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
2615c1dac77fSApple OSS Distributions }
2616c1dac77fSApple OSS Distributions 
2617a5e72196SApple OSS Distributions static kern_return_t
internal_io_service_match_property_table(io_service_t _service,const char * matching,mach_msg_type_number_t matching_size,boolean_t * matches)2618a5e72196SApple OSS Distributions internal_io_service_match_property_table(
2619c1dac77fSApple OSS Distributions 	io_service_t _service,
2620a3bb9fccSApple OSS Distributions 	const char * matching,
2621a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matching_size,
2622c1dac77fSApple OSS Distributions 	boolean_t *matches)
2623c1dac77fSApple OSS Distributions {
2624c1dac77fSApple OSS Distributions 	CHECK( IOService, _service, service );
2625c1dac77fSApple OSS Distributions 
2626c1dac77fSApple OSS Distributions 	kern_return_t       kr;
2627c1dac77fSApple OSS Distributions 	OSObject *          obj;
2628c1dac77fSApple OSS Distributions 	OSDictionary *      dict;
2629c1dac77fSApple OSS Distributions 
263088cc0b97SApple OSS Distributions 	assert(matching_size);
2631bb611c8fSApple OSS Distributions 
2632bb611c8fSApple OSS Distributions 
263388cc0b97SApple OSS Distributions 	obj = OSUnserializeXML(matching, matching_size);
26348dd02465SApple OSS Distributions 
263588cc0b97SApple OSS Distributions 	if ((dict = OSDynamicCast( OSDictionary, obj))) {
2636bb611c8fSApple OSS Distributions 		IOTaskRegistryCompatibilityMatching(current_task(), dict);
2637c1dac77fSApple OSS Distributions 		*matches = service->passiveMatch( dict );
2638c1dac77fSApple OSS Distributions 		kr = kIOReturnSuccess;
2639a5e72196SApple OSS Distributions 	} else {
2640c1dac77fSApple OSS Distributions 		kr = kIOReturnBadArgument;
2641a5e72196SApple OSS Distributions 	}
2642c1dac77fSApple OSS Distributions 
2643a5e72196SApple OSS Distributions 	if (obj) {
2644c1dac77fSApple OSS Distributions 		obj->release();
2645a5e72196SApple OSS Distributions 	}
2646c1dac77fSApple OSS Distributions 
2647a5e72196SApple OSS Distributions 	return kr;
2648c1dac77fSApple OSS Distributions }
2649c1dac77fSApple OSS Distributions 
2650a3bb9fccSApple OSS Distributions /* Routine io_service_match_property_table */
2651a5e72196SApple OSS Distributions kern_return_t
is_io_service_match_property_table(io_service_t service,io_string_t matching,boolean_t * matches)2652a5e72196SApple OSS Distributions is_io_service_match_property_table(
2653a3bb9fccSApple OSS Distributions 	io_service_t service,
2654a3bb9fccSApple OSS Distributions 	io_string_t matching,
2655a3bb9fccSApple OSS Distributions 	boolean_t *matches )
2656a3bb9fccSApple OSS Distributions {
2657a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2658a3bb9fccSApple OSS Distributions }
2659a3bb9fccSApple OSS Distributions 
2660a3bb9fccSApple OSS Distributions 
2661368ad365SApple OSS Distributions /* Routine io_service_match_property_table_ool */
2662a5e72196SApple OSS Distributions kern_return_t
is_io_service_match_property_table_ool(io_object_t service,io_buf_ptr_t matching,mach_msg_type_number_t matchingCnt,kern_return_t * result,boolean_t * matches)2663a5e72196SApple OSS Distributions is_io_service_match_property_table_ool(
2664368ad365SApple OSS Distributions 	io_object_t service,
2665368ad365SApple OSS Distributions 	io_buf_ptr_t matching,
2666368ad365SApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
2667e13b1fa5SApple OSS Distributions 	kern_return_t *result,
2668368ad365SApple OSS Distributions 	boolean_t *matches )
2669368ad365SApple OSS Distributions {
2670368ad365SApple OSS Distributions 	kern_return_t         kr;
2671368ad365SApple OSS Distributions 	vm_offset_t           data;
267214e3d835SApple OSS Distributions 	vm_map_offset_t       map_data;
2673368ad365SApple OSS Distributions 
267414e3d835SApple OSS Distributions 	kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
267514e3d835SApple OSS Distributions 	data = CAST_DOWN(vm_offset_t, map_data);
2676368ad365SApple OSS Distributions 
2677368ad365SApple OSS Distributions 	if (KERN_SUCCESS == kr) {
2678368ad365SApple OSS Distributions 		// must return success after vm_map_copyout() succeeds
2679a3bb9fccSApple OSS Distributions 		*result = internal_io_service_match_property_table(service,
2680a3bb9fccSApple OSS Distributions 		    (const char *)data, matchingCnt, matches );
2681368ad365SApple OSS Distributions 		vm_deallocate( kernel_map, data, matchingCnt );
2682368ad365SApple OSS Distributions 	}
2683368ad365SApple OSS Distributions 
2684a5e72196SApple OSS Distributions 	return kr;
2685368ad365SApple OSS Distributions }
2686368ad365SApple OSS Distributions 
2687a3bb9fccSApple OSS Distributions /* Routine io_service_match_property_table_bin */
2688a5e72196SApple OSS Distributions kern_return_t
is_io_service_match_property_table_bin(io_object_t service,io_struct_inband_t matching,mach_msg_type_number_t matchingCnt,boolean_t * matches)2689a5e72196SApple OSS Distributions is_io_service_match_property_table_bin(
2690a3bb9fccSApple OSS Distributions 	io_object_t service,
2691a3bb9fccSApple OSS Distributions 	io_struct_inband_t matching,
2692a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
2693a3bb9fccSApple OSS Distributions 	boolean_t *matches)
2694a3bb9fccSApple OSS Distributions {
2695a5e72196SApple OSS Distributions 	return internal_io_service_match_property_table(service, matching, matchingCnt, matches);
2696a3bb9fccSApple OSS Distributions }
2697a3bb9fccSApple OSS Distributions 
2698a5e72196SApple OSS Distributions static kern_return_t
internal_io_service_get_matching_services(mach_port_t main_port,const char * matching,mach_msg_type_number_t matching_size,io_iterator_t * existing)2699a5e72196SApple OSS Distributions internal_io_service_get_matching_services(
27005c2921b0SApple OSS Distributions 	mach_port_t main_port,
2701a3bb9fccSApple OSS Distributions 	const char * matching,
2702a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matching_size,
2703c1dac77fSApple OSS Distributions 	io_iterator_t *existing )
2704c1dac77fSApple OSS Distributions {
2705c1dac77fSApple OSS Distributions 	kern_return_t       kr;
2706c1dac77fSApple OSS Distributions 	OSObject *          obj;
2707c1dac77fSApple OSS Distributions 	OSDictionary *      dict;
2708c1dac77fSApple OSS Distributions 
27095c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
2710a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
2711a5e72196SApple OSS Distributions 	}
2712c1dac77fSApple OSS Distributions 
271388cc0b97SApple OSS Distributions 	assert(matching_size);
271488cc0b97SApple OSS Distributions 	obj = OSUnserializeXML(matching, matching_size);
271588cc0b97SApple OSS Distributions 
2716c1dac77fSApple OSS Distributions 	if ((dict = OSDynamicCast( OSDictionary, obj))) {
2717bb611c8fSApple OSS Distributions 		IOTaskRegistryCompatibilityMatching(current_task(), dict);
27188dd02465SApple OSS Distributions 		*existing = IOUserIterator::withIterator(IOService::getMatchingServices( dict ));
2719c1dac77fSApple OSS Distributions 		kr = kIOReturnSuccess;
2720a5e72196SApple OSS Distributions 	} else {
2721c1dac77fSApple OSS Distributions 		kr = kIOReturnBadArgument;
2722a5e72196SApple OSS Distributions 	}
2723c1dac77fSApple OSS Distributions 
2724a5e72196SApple OSS Distributions 	if (obj) {
2725c1dac77fSApple OSS Distributions 		obj->release();
2726a5e72196SApple OSS Distributions 	}
2727c1dac77fSApple OSS Distributions 
2728a5e72196SApple OSS Distributions 	return kr;
2729c1dac77fSApple OSS Distributions }
2730c1dac77fSApple OSS Distributions 
2731a3bb9fccSApple OSS Distributions /* Routine io_service_get_matching_services */
2732a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_matching_services(mach_port_t main_port,io_string_t matching,io_iterator_t * existing)2733a5e72196SApple OSS Distributions is_io_service_get_matching_services(
27345c2921b0SApple OSS Distributions 	mach_port_t main_port,
2735a3bb9fccSApple OSS Distributions 	io_string_t matching,
2736a3bb9fccSApple OSS Distributions 	io_iterator_t *existing )
2737a3bb9fccSApple OSS Distributions {
2738a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2739a3bb9fccSApple OSS Distributions }
2740a3bb9fccSApple OSS Distributions 
2741368ad365SApple OSS Distributions /* Routine io_service_get_matching_services_ool */
2742a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_matching_services_ool(mach_port_t main_port,io_buf_ptr_t matching,mach_msg_type_number_t matchingCnt,kern_return_t * result,io_object_t * existing)2743a5e72196SApple OSS Distributions is_io_service_get_matching_services_ool(
27445c2921b0SApple OSS Distributions 	mach_port_t main_port,
2745368ad365SApple OSS Distributions 	io_buf_ptr_t matching,
2746368ad365SApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
2747e13b1fa5SApple OSS Distributions 	kern_return_t *result,
2748368ad365SApple OSS Distributions 	io_object_t *existing )
2749368ad365SApple OSS Distributions {
2750368ad365SApple OSS Distributions 	kern_return_t       kr;
2751368ad365SApple OSS Distributions 	vm_offset_t         data;
275214e3d835SApple OSS Distributions 	vm_map_offset_t     map_data;
2753368ad365SApple OSS Distributions 
275414e3d835SApple OSS Distributions 	kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
275514e3d835SApple OSS Distributions 	data = CAST_DOWN(vm_offset_t, map_data);
2756368ad365SApple OSS Distributions 
2757368ad365SApple OSS Distributions 	if (KERN_SUCCESS == kr) {
2758368ad365SApple OSS Distributions 		// must return success after vm_map_copyout() succeeds
275988cc0b97SApple OSS Distributions 		// and mig will copy out objects on success
2760a5e72196SApple OSS Distributions 		*existing = NULL;
27615c2921b0SApple OSS Distributions 		*result = internal_io_service_get_matching_services(main_port,
2762a3bb9fccSApple OSS Distributions 		    (const char *) data, matchingCnt, existing);
2763368ad365SApple OSS Distributions 		vm_deallocate( kernel_map, data, matchingCnt );
2764368ad365SApple OSS Distributions 	}
2765368ad365SApple OSS Distributions 
2766a5e72196SApple OSS Distributions 	return kr;
2767368ad365SApple OSS Distributions }
2768368ad365SApple OSS Distributions 
2769a3bb9fccSApple OSS Distributions /* Routine io_service_get_matching_services_bin */
2770a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_matching_services_bin(mach_port_t main_port,io_struct_inband_t matching,mach_msg_type_number_t matchingCnt,io_object_t * existing)2771a5e72196SApple OSS Distributions is_io_service_get_matching_services_bin(
27725c2921b0SApple OSS Distributions 	mach_port_t main_port,
2773a3bb9fccSApple OSS Distributions 	io_struct_inband_t matching,
2774a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
2775a3bb9fccSApple OSS Distributions 	io_object_t *existing)
2776a3bb9fccSApple OSS Distributions {
27775c2921b0SApple OSS Distributions 	return internal_io_service_get_matching_services(main_port, matching, matchingCnt, existing);
2778a3bb9fccSApple OSS Distributions }
2779a3bb9fccSApple OSS Distributions 
2780a3bb9fccSApple OSS Distributions 
2781a5e72196SApple OSS Distributions static kern_return_t
internal_io_service_get_matching_service(mach_port_t main_port,const char * matching,mach_msg_type_number_t matching_size,io_service_t * service)2782a5e72196SApple OSS Distributions internal_io_service_get_matching_service(
27835c2921b0SApple OSS Distributions 	mach_port_t main_port,
2784a3bb9fccSApple OSS Distributions 	const char * matching,
2785a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matching_size,
2786d0c1fef6SApple OSS Distributions 	io_service_t *service )
2787d0c1fef6SApple OSS Distributions {
2788d0c1fef6SApple OSS Distributions 	kern_return_t       kr;
2789d0c1fef6SApple OSS Distributions 	OSObject *          obj;
2790d0c1fef6SApple OSS Distributions 	OSDictionary *      dict;
2791d0c1fef6SApple OSS Distributions 
27925c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
2793a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
2794a5e72196SApple OSS Distributions 	}
2795d0c1fef6SApple OSS Distributions 
279688cc0b97SApple OSS Distributions 	assert(matching_size);
279788cc0b97SApple OSS Distributions 	obj = OSUnserializeXML(matching, matching_size);
279888cc0b97SApple OSS Distributions 
2799d0c1fef6SApple OSS Distributions 	if ((dict = OSDynamicCast( OSDictionary, obj))) {
2800bb611c8fSApple OSS Distributions 		IOTaskRegistryCompatibilityMatching(current_task(), dict);
2801d0c1fef6SApple OSS Distributions 		*service = IOService::copyMatchingService( dict );
2802d0c1fef6SApple OSS Distributions 		kr = *service ? kIOReturnSuccess : kIOReturnNotFound;
2803a5e72196SApple OSS Distributions 	} else {
2804d0c1fef6SApple OSS Distributions 		kr = kIOReturnBadArgument;
2805a5e72196SApple OSS Distributions 	}
2806d0c1fef6SApple OSS Distributions 
2807a5e72196SApple OSS Distributions 	if (obj) {
2808d0c1fef6SApple OSS Distributions 		obj->release();
2809a5e72196SApple OSS Distributions 	}
2810d0c1fef6SApple OSS Distributions 
2811a5e72196SApple OSS Distributions 	return kr;
2812d0c1fef6SApple OSS Distributions }
2813d0c1fef6SApple OSS Distributions 
2814a3bb9fccSApple OSS Distributions /* Routine io_service_get_matching_service */
2815a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_matching_service(mach_port_t main_port,io_string_t matching,io_service_t * service)2816a5e72196SApple OSS Distributions is_io_service_get_matching_service(
28175c2921b0SApple OSS Distributions 	mach_port_t main_port,
2818a3bb9fccSApple OSS Distributions 	io_string_t matching,
2819a3bb9fccSApple OSS Distributions 	io_service_t *service )
2820a3bb9fccSApple OSS Distributions {
2821a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2822a3bb9fccSApple OSS Distributions }
2823a3bb9fccSApple OSS Distributions 
2824d0c1fef6SApple OSS Distributions /* Routine io_service_get_matching_services_ool */
2825a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_matching_service_ool(mach_port_t main_port,io_buf_ptr_t matching,mach_msg_type_number_t matchingCnt,kern_return_t * result,io_object_t * service)2826a5e72196SApple OSS Distributions is_io_service_get_matching_service_ool(
28275c2921b0SApple OSS Distributions 	mach_port_t main_port,
2828d0c1fef6SApple OSS Distributions 	io_buf_ptr_t matching,
2829d0c1fef6SApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
2830d0c1fef6SApple OSS Distributions 	kern_return_t *result,
2831d0c1fef6SApple OSS Distributions 	io_object_t *service )
2832d0c1fef6SApple OSS Distributions {
2833d0c1fef6SApple OSS Distributions 	kern_return_t       kr;
2834d0c1fef6SApple OSS Distributions 	vm_offset_t         data;
2835d0c1fef6SApple OSS Distributions 	vm_map_offset_t     map_data;
2836d0c1fef6SApple OSS Distributions 
2837d0c1fef6SApple OSS Distributions 	kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
2838d0c1fef6SApple OSS Distributions 	data = CAST_DOWN(vm_offset_t, map_data);
2839d0c1fef6SApple OSS Distributions 
2840d0c1fef6SApple OSS Distributions 	if (KERN_SUCCESS == kr) {
2841d0c1fef6SApple OSS Distributions 		// must return success after vm_map_copyout() succeeds
284288cc0b97SApple OSS Distributions 		// and mig will copy out objects on success
2843a5e72196SApple OSS Distributions 		*service = NULL;
28445c2921b0SApple OSS Distributions 		*result = internal_io_service_get_matching_service(main_port,
2845a3bb9fccSApple OSS Distributions 		    (const char *) data, matchingCnt, service );
2846d0c1fef6SApple OSS Distributions 		vm_deallocate( kernel_map, data, matchingCnt );
2847d0c1fef6SApple OSS Distributions 	}
2848d0c1fef6SApple OSS Distributions 
2849a5e72196SApple OSS Distributions 	return kr;
2850d0c1fef6SApple OSS Distributions }
2851d0c1fef6SApple OSS Distributions 
2852a3bb9fccSApple OSS Distributions /* Routine io_service_get_matching_service_bin */
2853a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_matching_service_bin(mach_port_t main_port,io_struct_inband_t matching,mach_msg_type_number_t matchingCnt,io_object_t * service)2854a5e72196SApple OSS Distributions is_io_service_get_matching_service_bin(
28555c2921b0SApple OSS Distributions 	mach_port_t main_port,
2856a3bb9fccSApple OSS Distributions 	io_struct_inband_t matching,
2857a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
2858a3bb9fccSApple OSS Distributions 	io_object_t *service)
2859a3bb9fccSApple OSS Distributions {
28605c2921b0SApple OSS Distributions 	return internal_io_service_get_matching_service(main_port, matching, matchingCnt, service);
2861a3bb9fccSApple OSS Distributions }
2862d0c1fef6SApple OSS Distributions 
2863a5e72196SApple OSS Distributions static kern_return_t
internal_io_service_add_notification(mach_port_t main_port,io_name_t notification_type,const char * matching,size_t matching_size,mach_port_t port,void * reference,vm_size_t referenceSize,bool client64,io_object_t * notification)2864a5e72196SApple OSS Distributions internal_io_service_add_notification(
28655c2921b0SApple OSS Distributions 	mach_port_t main_port,
2866c1dac77fSApple OSS Distributions 	io_name_t notification_type,
2867a3bb9fccSApple OSS Distributions 	const char * matching,
2868a3bb9fccSApple OSS Distributions 	size_t matching_size,
2869c1dac77fSApple OSS Distributions 	mach_port_t port,
2870e13b1fa5SApple OSS Distributions 	void * reference,
2871e13b1fa5SApple OSS Distributions 	vm_size_t referenceSize,
2872e13b1fa5SApple OSS Distributions 	bool client64,
2873c1dac77fSApple OSS Distributions 	io_object_t * notification )
2874c1dac77fSApple OSS Distributions {
2875a5e72196SApple OSS Distributions 	IOServiceUserNotification * userNotify = NULL;
2876a5e72196SApple OSS Distributions 	IONotifier *                notify = NULL;
2877c1dac77fSApple OSS Distributions 	const OSSymbol *            sym;
2878bb611c8fSApple OSS Distributions 	OSObject *                  obj;
2879c1dac77fSApple OSS Distributions 	OSDictionary *              dict;
2880c1dac77fSApple OSS Distributions 	IOReturn                    err;
2881bb611c8fSApple OSS Distributions 	natural_t                   userMsgType;
2882c1dac77fSApple OSS Distributions 
28835c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
2884a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
2885a5e72196SApple OSS Distributions 	}
2886c1dac77fSApple OSS Distributions 
2887c1dac77fSApple OSS Distributions 	do {
2888c1dac77fSApple OSS Distributions 		err = kIOReturnNoResources;
2889c1dac77fSApple OSS Distributions 
2890a5e72196SApple OSS Distributions 		if (matching_size > (sizeof(io_struct_inband_t) * 1024)) {
2891a5e72196SApple OSS Distributions 			return kIOReturnMessageTooLarge;
2892a5e72196SApple OSS Distributions 		}
2893cc9a6355SApple OSS Distributions 
2894a5e72196SApple OSS Distributions 		if (!(sym = OSSymbol::withCString( notification_type ))) {
2895c1dac77fSApple OSS Distributions 			err = kIOReturnNoResources;
2896a5e72196SApple OSS Distributions 		}
2897c1dac77fSApple OSS Distributions 
289888cc0b97SApple OSS Distributions 		assert(matching_size);
2899bb611c8fSApple OSS Distributions 		obj = OSUnserializeXML(matching, matching_size);
2900bb611c8fSApple OSS Distributions 		dict = OSDynamicCast(OSDictionary, obj);
2901a3bb9fccSApple OSS Distributions 		if (!dict) {
2902c1dac77fSApple OSS Distributions 			err = kIOReturnBadArgument;
2903c1dac77fSApple OSS Distributions 			continue;
2904c1dac77fSApple OSS Distributions 		}
2905bb611c8fSApple OSS Distributions 		IOTaskRegistryCompatibilityMatching(current_task(), dict);
2906c1dac77fSApple OSS Distributions 
2907c1dac77fSApple OSS Distributions 		if ((sym == gIOPublishNotification)
2908a5e72196SApple OSS Distributions 		    || (sym == gIOFirstPublishNotification)) {
2909c1dac77fSApple OSS Distributions 			userMsgType = kIOServicePublishNotificationType;
2910a5e72196SApple OSS Distributions 		} else if ((sym == gIOMatchedNotification)
2911a5e72196SApple OSS Distributions 		    || (sym == gIOFirstMatchNotification)) {
2912c1dac77fSApple OSS Distributions 			userMsgType = kIOServiceMatchedNotificationType;
2913a5e72196SApple OSS Distributions 		} else if ((sym == gIOTerminatedNotification)
2914a5e72196SApple OSS Distributions 		    || (sym == gIOWillTerminateNotification)) {
2915c1dac77fSApple OSS Distributions 			userMsgType = kIOServiceTerminatedNotificationType;
2916a5e72196SApple OSS Distributions 		} else {
2917c1dac77fSApple OSS Distributions 			userMsgType = kLastIOKitNotificationType;
2918a5e72196SApple OSS Distributions 		}
2919c1dac77fSApple OSS Distributions 
2920c1dac77fSApple OSS Distributions 		userNotify = new IOServiceUserNotification;
2921c1dac77fSApple OSS Distributions 
2922c1dac77fSApple OSS Distributions 		if (userNotify && !userNotify->init( port, userMsgType,
2923e13b1fa5SApple OSS Distributions 		    reference, referenceSize, client64)) {
2924c1dac77fSApple OSS Distributions 			userNotify->release();
2925a5e72196SApple OSS Distributions 			userNotify = NULL;
2926c1dac77fSApple OSS Distributions 		}
2927a5e72196SApple OSS Distributions 		if (!userNotify) {
2928c1dac77fSApple OSS Distributions 			continue;
2929a5e72196SApple OSS Distributions 		}
2930c1dac77fSApple OSS Distributions 
29313ca3bd55SApple OSS Distributions 		notify = IOService::addMatchingNotification( sym, dict,
2932c1dac77fSApple OSS Distributions 		    &userNotify->_handler, userNotify );
2933c1dac77fSApple OSS Distributions 		if (notify) {
2934c1dac77fSApple OSS Distributions 			*notification = userNotify;
2935c1dac77fSApple OSS Distributions 			userNotify->setNotification( notify );
2936c1dac77fSApple OSS Distributions 			err = kIOReturnSuccess;
2937a5e72196SApple OSS Distributions 		} else {
2938c1dac77fSApple OSS Distributions 			err = kIOReturnUnsupported;
2939a5e72196SApple OSS Distributions 		}
2940c1dac77fSApple OSS Distributions 	} while (false);
2941c1dac77fSApple OSS Distributions 
2942a5e72196SApple OSS Distributions 	if ((kIOReturnSuccess != err) && userNotify) {
2943e6231be0SApple OSS Distributions 		userNotify->setNotification(NULL);
294476e12aa3SApple OSS Distributions 		userNotify->invalidatePort();
294576e12aa3SApple OSS Distributions 		userNotify->release();
2946a5e72196SApple OSS Distributions 		userNotify = NULL;
294776e12aa3SApple OSS Distributions 	}
294876e12aa3SApple OSS Distributions 
2949a5e72196SApple OSS Distributions 	if (sym) {
2950c1dac77fSApple OSS Distributions 		sym->release();
2951a5e72196SApple OSS Distributions 	}
2952bb611c8fSApple OSS Distributions 	if (obj) {
2953bb611c8fSApple OSS Distributions 		obj->release();
2954a5e72196SApple OSS Distributions 	}
2955c1dac77fSApple OSS Distributions 
2956a5e72196SApple OSS Distributions 	return err;
2957c1dac77fSApple OSS Distributions }
2958c1dac77fSApple OSS Distributions 
2959e13b1fa5SApple OSS Distributions 
2960e13b1fa5SApple OSS Distributions /* Routine io_service_add_notification */
2961a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_notification(mach_port_t main_port,io_name_t notification_type,io_string_t matching,mach_port_t port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,io_object_t * notification)2962a5e72196SApple OSS Distributions is_io_service_add_notification(
29635c2921b0SApple OSS Distributions 	mach_port_t main_port,
2964e13b1fa5SApple OSS Distributions 	io_name_t notification_type,
2965e13b1fa5SApple OSS Distributions 	io_string_t matching,
2966e13b1fa5SApple OSS Distributions 	mach_port_t port,
2967e13b1fa5SApple OSS Distributions 	io_async_ref_t reference,
2968e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
2969e13b1fa5SApple OSS Distributions 	io_object_t * notification )
2970e13b1fa5SApple OSS Distributions {
2971a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2972e13b1fa5SApple OSS Distributions }
2973e13b1fa5SApple OSS Distributions 
2974e13b1fa5SApple OSS Distributions /* Routine io_service_add_notification_64 */
2975a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_notification_64(mach_port_t main_port,io_name_t notification_type,io_string_t matching,mach_port_t wake_port,io_async_ref64_t reference,mach_msg_type_number_t referenceCnt,io_object_t * notification)2976a5e72196SApple OSS Distributions is_io_service_add_notification_64(
29775c2921b0SApple OSS Distributions 	mach_port_t main_port,
2978e13b1fa5SApple OSS Distributions 	io_name_t notification_type,
2979e13b1fa5SApple OSS Distributions 	io_string_t matching,
2980e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
2981e13b1fa5SApple OSS Distributions 	io_async_ref64_t reference,
2982e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
2983e13b1fa5SApple OSS Distributions 	io_object_t *notification )
2984e13b1fa5SApple OSS Distributions {
2985a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
2986e13b1fa5SApple OSS Distributions }
2987e13b1fa5SApple OSS Distributions 
2988a3bb9fccSApple OSS Distributions /* Routine io_service_add_notification_bin */
2989a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_notification_bin(mach_port_t main_port,io_name_t notification_type,io_struct_inband_t matching,mach_msg_type_number_t matchingCnt,mach_port_t wake_port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,io_object_t * notification)2990a5e72196SApple OSS Distributions is_io_service_add_notification_bin
2991a3bb9fccSApple OSS Distributions (
29925c2921b0SApple OSS Distributions 	mach_port_t main_port,
2993a3bb9fccSApple OSS Distributions 	io_name_t notification_type,
2994a3bb9fccSApple OSS Distributions 	io_struct_inband_t matching,
2995a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
2996a3bb9fccSApple OSS Distributions 	mach_port_t wake_port,
2997a3bb9fccSApple OSS Distributions 	io_async_ref_t reference,
2998a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
2999a3bb9fccSApple OSS Distributions 	io_object_t *notification)
3000a3bb9fccSApple OSS Distributions {
3001a5e72196SApple OSS Distributions 	io_async_ref_t zreference;
3002a5e72196SApple OSS Distributions 
3003a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF_COUNT) {
3004a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3005a5e72196SApple OSS Distributions 	}
3006a5e72196SApple OSS Distributions 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
3007a5e72196SApple OSS Distributions 	bzero(&zreference[referenceCnt], (ASYNC_REF_COUNT - referenceCnt) * sizeof(zreference[0]));
3008a5e72196SApple OSS Distributions 
30095c2921b0SApple OSS Distributions 	return internal_io_service_add_notification(main_port, notification_type,
3010a5e72196SApple OSS Distributions 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref_t),
3011a5e72196SApple OSS Distributions 	           false, notification);
3012a3bb9fccSApple OSS Distributions }
3013a3bb9fccSApple OSS Distributions 
3014a3bb9fccSApple OSS Distributions /* Routine io_service_add_notification_bin_64 */
3015a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_notification_bin_64(mach_port_t main_port,io_name_t notification_type,io_struct_inband_t matching,mach_msg_type_number_t matchingCnt,mach_port_t wake_port,io_async_ref64_t reference,mach_msg_type_number_t referenceCnt,io_object_t * notification)3016a5e72196SApple OSS Distributions is_io_service_add_notification_bin_64
3017a3bb9fccSApple OSS Distributions (
30185c2921b0SApple OSS Distributions 	mach_port_t main_port,
3019a3bb9fccSApple OSS Distributions 	io_name_t notification_type,
3020a3bb9fccSApple OSS Distributions 	io_struct_inband_t matching,
3021a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
3022a3bb9fccSApple OSS Distributions 	mach_port_t wake_port,
3023a3bb9fccSApple OSS Distributions 	io_async_ref64_t reference,
3024a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
3025a3bb9fccSApple OSS Distributions 	io_object_t *notification)
3026a3bb9fccSApple OSS Distributions {
3027a5e72196SApple OSS Distributions 	io_async_ref64_t zreference;
3028a5e72196SApple OSS Distributions 
3029a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF64_COUNT) {
3030a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3031a5e72196SApple OSS Distributions 	}
3032a5e72196SApple OSS Distributions 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
3033a5e72196SApple OSS Distributions 	bzero(&zreference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(zreference[0]));
3034a5e72196SApple OSS Distributions 
30355c2921b0SApple OSS Distributions 	return internal_io_service_add_notification(main_port, notification_type,
3036a5e72196SApple OSS Distributions 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref64_t),
3037a5e72196SApple OSS Distributions 	           true, notification);
3038a3bb9fccSApple OSS Distributions }
3039e13b1fa5SApple OSS Distributions 
3040a5e72196SApple OSS Distributions static kern_return_t
internal_io_service_add_notification_ool(mach_port_t main_port,io_name_t notification_type,io_buf_ptr_t matching,mach_msg_type_number_t matchingCnt,mach_port_t wake_port,void * reference,vm_size_t referenceSize,bool client64,kern_return_t * result,io_object_t * notification)3041a5e72196SApple OSS Distributions internal_io_service_add_notification_ool(
30425c2921b0SApple OSS Distributions 	mach_port_t main_port,
3043368ad365SApple OSS Distributions 	io_name_t notification_type,
3044368ad365SApple OSS Distributions 	io_buf_ptr_t matching,
3045368ad365SApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
3046368ad365SApple OSS Distributions 	mach_port_t wake_port,
3047e13b1fa5SApple OSS Distributions 	void * reference,
3048e13b1fa5SApple OSS Distributions 	vm_size_t referenceSize,
3049e13b1fa5SApple OSS Distributions 	bool client64,
3050e13b1fa5SApple OSS Distributions 	kern_return_t *result,
3051368ad365SApple OSS Distributions 	io_object_t *notification )
3052368ad365SApple OSS Distributions {
3053368ad365SApple OSS Distributions 	kern_return_t       kr;
3054368ad365SApple OSS Distributions 	vm_offset_t         data;
305514e3d835SApple OSS Distributions 	vm_map_offset_t     map_data;
3056368ad365SApple OSS Distributions 
305714e3d835SApple OSS Distributions 	kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
305814e3d835SApple OSS Distributions 	data = CAST_DOWN(vm_offset_t, map_data);
3059368ad365SApple OSS Distributions 
3060368ad365SApple OSS Distributions 	if (KERN_SUCCESS == kr) {
3061368ad365SApple OSS Distributions 		// must return success after vm_map_copyout() succeeds
306288cc0b97SApple OSS Distributions 		// and mig will copy out objects on success
3063a5e72196SApple OSS Distributions 		*notification = NULL;
30645c2921b0SApple OSS Distributions 		*result = internal_io_service_add_notification( main_port, notification_type,
3065a3bb9fccSApple OSS Distributions 		    (char *) data, matchingCnt, wake_port, reference, referenceSize, client64, notification );
3066368ad365SApple OSS Distributions 		vm_deallocate( kernel_map, data, matchingCnt );
3067368ad365SApple OSS Distributions 	}
3068368ad365SApple OSS Distributions 
3069a5e72196SApple OSS Distributions 	return kr;
3070368ad365SApple OSS Distributions }
3071368ad365SApple OSS Distributions 
3072e13b1fa5SApple OSS Distributions /* Routine io_service_add_notification_ool */
3073a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_notification_ool(mach_port_t main_port,io_name_t notification_type,io_buf_ptr_t matching,mach_msg_type_number_t matchingCnt,mach_port_t wake_port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,kern_return_t * result,io_object_t * notification)3074a5e72196SApple OSS Distributions is_io_service_add_notification_ool(
30755c2921b0SApple OSS Distributions 	mach_port_t main_port,
3076e13b1fa5SApple OSS Distributions 	io_name_t notification_type,
3077e13b1fa5SApple OSS Distributions 	io_buf_ptr_t matching,
3078e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
3079e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
3080e13b1fa5SApple OSS Distributions 	io_async_ref_t reference,
3081e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
3082e13b1fa5SApple OSS Distributions 	kern_return_t *result,
3083e13b1fa5SApple OSS Distributions 	io_object_t *notification )
3084e13b1fa5SApple OSS Distributions {
3085a5e72196SApple OSS Distributions 	io_async_ref_t zreference;
3086a5e72196SApple OSS Distributions 
3087a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF_COUNT) {
3088a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3089a5e72196SApple OSS Distributions 	}
3090a5e72196SApple OSS Distributions 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
3091a5e72196SApple OSS Distributions 	bzero(&zreference[referenceCnt], (ASYNC_REF_COUNT - referenceCnt) * sizeof(zreference[0]));
3092a5e72196SApple OSS Distributions 
30935c2921b0SApple OSS Distributions 	return internal_io_service_add_notification_ool(main_port, notification_type,
3094a5e72196SApple OSS Distributions 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref_t),
3095a5e72196SApple OSS Distributions 	           false, result, notification);
3096e13b1fa5SApple OSS Distributions }
3097e13b1fa5SApple OSS Distributions 
3098e13b1fa5SApple OSS Distributions /* Routine io_service_add_notification_ool_64 */
3099a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_notification_ool_64(mach_port_t main_port,io_name_t notification_type,io_buf_ptr_t matching,mach_msg_type_number_t matchingCnt,mach_port_t wake_port,io_async_ref64_t reference,mach_msg_type_number_t referenceCnt,kern_return_t * result,io_object_t * notification)3100a5e72196SApple OSS Distributions is_io_service_add_notification_ool_64(
31015c2921b0SApple OSS Distributions 	mach_port_t main_port,
3102e13b1fa5SApple OSS Distributions 	io_name_t notification_type,
3103e13b1fa5SApple OSS Distributions 	io_buf_ptr_t matching,
3104e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t matchingCnt,
3105e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
3106e13b1fa5SApple OSS Distributions 	io_async_ref64_t reference,
3107e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
3108e13b1fa5SApple OSS Distributions 	kern_return_t *result,
3109e13b1fa5SApple OSS Distributions 	io_object_t *notification )
3110e13b1fa5SApple OSS Distributions {
3111a5e72196SApple OSS Distributions 	io_async_ref64_t zreference;
3112a5e72196SApple OSS Distributions 
3113a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF64_COUNT) {
3114a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3115a5e72196SApple OSS Distributions 	}
3116a5e72196SApple OSS Distributions 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
3117a5e72196SApple OSS Distributions 	bzero(&zreference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(zreference[0]));
3118a5e72196SApple OSS Distributions 
31195c2921b0SApple OSS Distributions 	return internal_io_service_add_notification_ool(main_port, notification_type,
3120a5e72196SApple OSS Distributions 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref64_t),
3121a5e72196SApple OSS Distributions 	           true, result, notification);
3122e13b1fa5SApple OSS Distributions }
3123368ad365SApple OSS Distributions 
3124c1dac77fSApple OSS Distributions /* Routine io_service_add_notification_old */
3125a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_notification_old(mach_port_t main_port,io_name_t notification_type,io_string_t matching,mach_port_t port,natural_t ref,io_object_t * notification)3126a5e72196SApple OSS Distributions is_io_service_add_notification_old(
31275c2921b0SApple OSS Distributions 	mach_port_t main_port,
3128c1dac77fSApple OSS Distributions 	io_name_t notification_type,
3129c1dac77fSApple OSS Distributions 	io_string_t matching,
3130c1dac77fSApple OSS Distributions 	mach_port_t port,
31313ca3bd55SApple OSS Distributions 	// for binary compatibility reasons, this must be natural_t for ILP32
3132c1dac77fSApple OSS Distributions 	natural_t ref,
3133c1dac77fSApple OSS Distributions 	io_object_t * notification )
3134c1dac77fSApple OSS Distributions {
31355c2921b0SApple OSS Distributions 	return is_io_service_add_notification( main_port, notification_type,
3136a5e72196SApple OSS Distributions 	           matching, port, &ref, 1, notification );
3137c1dac77fSApple OSS Distributions }
3138c1dac77fSApple OSS Distributions 
3139e13b1fa5SApple OSS Distributions 
3140a5e72196SApple OSS Distributions static kern_return_t
internal_io_service_add_interest_notification(io_object_t _service,io_name_t type_of_interest,mach_port_t port,void * reference,vm_size_t referenceSize,bool client64,io_object_t * notification)3141a5e72196SApple OSS Distributions internal_io_service_add_interest_notification(
3142c1dac77fSApple OSS Distributions 	io_object_t _service,
3143c1dac77fSApple OSS Distributions 	io_name_t type_of_interest,
3144c1dac77fSApple OSS Distributions 	mach_port_t port,
3145e13b1fa5SApple OSS Distributions 	void * reference,
3146e13b1fa5SApple OSS Distributions 	vm_size_t referenceSize,
3147e13b1fa5SApple OSS Distributions 	bool client64,
3148c1dac77fSApple OSS Distributions 	io_object_t * notification )
3149c1dac77fSApple OSS Distributions {
3150a5e72196SApple OSS Distributions 	IOServiceMessageUserNotification *  userNotify = NULL;
3151a5e72196SApple OSS Distributions 	IONotifier *                        notify = NULL;
3152c1dac77fSApple OSS Distributions 	const OSSymbol *                    sym;
3153c1dac77fSApple OSS Distributions 	IOReturn                            err;
3154c1dac77fSApple OSS Distributions 
3155c1dac77fSApple OSS Distributions 	CHECK( IOService, _service, service );
3156c1dac77fSApple OSS Distributions 
3157c1dac77fSApple OSS Distributions 	err = kIOReturnNoResources;
3158a5e72196SApple OSS Distributions 	if ((sym = OSSymbol::withCString( type_of_interest ))) {
3159a5e72196SApple OSS Distributions 		do {
3160c1dac77fSApple OSS Distributions 			userNotify = new IOServiceMessageUserNotification;
3161c1dac77fSApple OSS Distributions 
3162c1dac77fSApple OSS Distributions 			if (userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
3163e6231be0SApple OSS Distributions 			    reference, referenceSize, client64 )) {
3164c1dac77fSApple OSS Distributions 				userNotify->release();
3165a5e72196SApple OSS Distributions 				userNotify = NULL;
3166c1dac77fSApple OSS Distributions 			}
3167a5e72196SApple OSS Distributions 			if (!userNotify) {
3168c1dac77fSApple OSS Distributions 				continue;
3169a5e72196SApple OSS Distributions 			}
3170c1dac77fSApple OSS Distributions 
3171c1dac77fSApple OSS Distributions 			notify = service->registerInterest( sym,
3172c1dac77fSApple OSS Distributions 			    &userNotify->_handler, userNotify );
3173c1dac77fSApple OSS Distributions 			if (notify) {
3174c1dac77fSApple OSS Distributions 				*notification = userNotify;
3175c1dac77fSApple OSS Distributions 				userNotify->setNotification( notify );
3176c1dac77fSApple OSS Distributions 				err = kIOReturnSuccess;
3177a5e72196SApple OSS Distributions 			} else {
3178c1dac77fSApple OSS Distributions 				err = kIOReturnUnsupported;
317976e12aa3SApple OSS Distributions 			}
3180e6231be0SApple OSS Distributions 		} while (false);
318176e12aa3SApple OSS Distributions 
3182a5e72196SApple OSS Distributions 		sym->release();
3183a5e72196SApple OSS Distributions 	}
3184a5e72196SApple OSS Distributions 
3185a5e72196SApple OSS Distributions 	if ((kIOReturnSuccess != err) && userNotify) {
3186e6231be0SApple OSS Distributions 		userNotify->setNotification(NULL);
3187a5e72196SApple OSS Distributions 		userNotify->invalidatePort();
3188a5e72196SApple OSS Distributions 		userNotify->release();
3189a5e72196SApple OSS Distributions 		userNotify = NULL;
3190a5e72196SApple OSS Distributions 	}
3191a5e72196SApple OSS Distributions 
3192a5e72196SApple OSS Distributions 	return err;
3193c1dac77fSApple OSS Distributions }
3194c1dac77fSApple OSS Distributions 
3195e13b1fa5SApple OSS Distributions /* Routine io_service_add_message_notification */
3196a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_interest_notification(io_object_t service,io_name_t type_of_interest,mach_port_t port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,io_object_t * notification)3197a5e72196SApple OSS Distributions is_io_service_add_interest_notification(
3198e13b1fa5SApple OSS Distributions 	io_object_t service,
3199e13b1fa5SApple OSS Distributions 	io_name_t type_of_interest,
3200e13b1fa5SApple OSS Distributions 	mach_port_t port,
3201e13b1fa5SApple OSS Distributions 	io_async_ref_t reference,
3202e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
3203e13b1fa5SApple OSS Distributions 	io_object_t * notification )
3204e13b1fa5SApple OSS Distributions {
3205a5e72196SApple OSS Distributions 	io_async_ref_t zreference;
3206a5e72196SApple OSS Distributions 
3207a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF_COUNT) {
3208a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3209a5e72196SApple OSS Distributions 	}
3210a5e72196SApple OSS Distributions 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
3211a5e72196SApple OSS Distributions 	bzero(&zreference[referenceCnt], (ASYNC_REF_COUNT - referenceCnt) * sizeof(zreference[0]));
3212a5e72196SApple OSS Distributions 
3213a5e72196SApple OSS Distributions 	return internal_io_service_add_interest_notification(service, type_of_interest,
3214a5e72196SApple OSS Distributions 	           port, &zreference[0], sizeof(io_async_ref_t), false, notification);
3215e13b1fa5SApple OSS Distributions }
3216e13b1fa5SApple OSS Distributions 
3217e13b1fa5SApple OSS Distributions /* Routine io_service_add_interest_notification_64 */
3218a5e72196SApple OSS Distributions kern_return_t
is_io_service_add_interest_notification_64(io_object_t service,io_name_t type_of_interest,mach_port_t wake_port,io_async_ref64_t reference,mach_msg_type_number_t referenceCnt,io_object_t * notification)3219a5e72196SApple OSS Distributions is_io_service_add_interest_notification_64(
3220e13b1fa5SApple OSS Distributions 	io_object_t service,
3221e13b1fa5SApple OSS Distributions 	io_name_t type_of_interest,
3222e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
3223e13b1fa5SApple OSS Distributions 	io_async_ref64_t reference,
3224e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
3225e13b1fa5SApple OSS Distributions 	io_object_t *notification )
3226e13b1fa5SApple OSS Distributions {
3227a5e72196SApple OSS Distributions 	io_async_ref64_t zreference;
3228a5e72196SApple OSS Distributions 
3229a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF64_COUNT) {
3230a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3231a5e72196SApple OSS Distributions 	}
3232a5e72196SApple OSS Distributions 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
3233a5e72196SApple OSS Distributions 	bzero(&zreference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(zreference[0]));
3234a5e72196SApple OSS Distributions 
3235a5e72196SApple OSS Distributions 	return internal_io_service_add_interest_notification(service, type_of_interest,
3236a5e72196SApple OSS Distributions 	           wake_port, &zreference[0], sizeof(io_async_ref64_t), true, notification);
3237e13b1fa5SApple OSS Distributions }
3238e13b1fa5SApple OSS Distributions 
3239e13b1fa5SApple OSS Distributions 
3240c1dac77fSApple OSS Distributions /* Routine io_service_acknowledge_notification */
3241a5e72196SApple OSS Distributions kern_return_t
is_io_service_acknowledge_notification(io_object_t _service,natural_t notify_ref,natural_t response)3242a5e72196SApple OSS Distributions is_io_service_acknowledge_notification(
3243c1dac77fSApple OSS Distributions 	io_object_t _service,
3244c1dac77fSApple OSS Distributions 	natural_t notify_ref,
3245c1dac77fSApple OSS Distributions 	natural_t response )
3246c1dac77fSApple OSS Distributions {
3247c1dac77fSApple OSS Distributions 	CHECK( IOService, _service, service );
3248c1dac77fSApple OSS Distributions 
3249a5e72196SApple OSS Distributions 	return service->acknowledgeNotification((IONotificationRef)(uintptr_t) notify_ref,
3250a5e72196SApple OSS Distributions 	           (IOOptionBits) response );
3251c1dac77fSApple OSS Distributions }
3252c1dac77fSApple OSS Distributions 
3253c1dac77fSApple OSS Distributions /* Routine io_connect_get_semaphore */
3254a5e72196SApple OSS Distributions kern_return_t
is_io_connect_get_notification_semaphore(io_connect_t connection,natural_t notification_type,semaphore_t * semaphore)3255a5e72196SApple OSS Distributions is_io_connect_get_notification_semaphore(
3256c1dac77fSApple OSS Distributions 	io_connect_t connection,
3257c1dac77fSApple OSS Distributions 	natural_t notification_type,
3258c1dac77fSApple OSS Distributions 	semaphore_t *semaphore )
3259c1dac77fSApple OSS Distributions {
3260bb611c8fSApple OSS Distributions 	IOReturn ret;
3261c1dac77fSApple OSS Distributions 	CHECK( IOUserClient, connection, client );
3262c1dac77fSApple OSS Distributions 
3263855239e5SApple OSS Distributions 	IOStatisticsClientCall();
326494d3b452SApple OSS Distributions 	client->ipcEnter(kIPCLockWrite);
3265bb611c8fSApple OSS Distributions 	ret = client->getNotificationSemaphore((UInt32) notification_type,
3266a5e72196SApple OSS Distributions 	    semaphore );
326794d3b452SApple OSS Distributions 	client->ipcExit(kIPCLockWrite);
3268bb611c8fSApple OSS Distributions 
3269bb611c8fSApple OSS Distributions 	return ret;
3270c1dac77fSApple OSS Distributions }
3271c1dac77fSApple OSS Distributions 
3272c1dac77fSApple OSS Distributions /* Routine io_registry_get_root_entry */
3273a5e72196SApple OSS Distributions kern_return_t
is_io_registry_get_root_entry(mach_port_t main_port,io_object_t * root)3274a5e72196SApple OSS Distributions is_io_registry_get_root_entry(
32755c2921b0SApple OSS Distributions 	mach_port_t main_port,
3276c1dac77fSApple OSS Distributions 	io_object_t *root )
3277c1dac77fSApple OSS Distributions {
3278c1dac77fSApple OSS Distributions 	IORegistryEntry *   entry;
3279c1dac77fSApple OSS Distributions 
32805c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
3281a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
3282a5e72196SApple OSS Distributions 	}
3283c1dac77fSApple OSS Distributions 
3284c1dac77fSApple OSS Distributions 	entry = IORegistryEntry::getRegistryRoot();
3285a5e72196SApple OSS Distributions 	if (entry) {
3286c1dac77fSApple OSS Distributions 		entry->retain();
3287a5e72196SApple OSS Distributions 	}
3288c1dac77fSApple OSS Distributions 	*root = entry;
3289c1dac77fSApple OSS Distributions 
3290a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
3291c1dac77fSApple OSS Distributions }
3292c1dac77fSApple OSS Distributions 
3293c1dac77fSApple OSS Distributions /* Routine io_registry_create_iterator */
3294a5e72196SApple OSS Distributions kern_return_t
is_io_registry_create_iterator(mach_port_t main_port,io_name_t plane,uint32_t options,io_object_t * iterator)3295a5e72196SApple OSS Distributions is_io_registry_create_iterator(
32965c2921b0SApple OSS Distributions 	mach_port_t main_port,
3297c1dac77fSApple OSS Distributions 	io_name_t plane,
3298e13b1fa5SApple OSS Distributions 	uint32_t options,
3299c1dac77fSApple OSS Distributions 	io_object_t *iterator )
3300c1dac77fSApple OSS Distributions {
33015c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
3302a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
3303a5e72196SApple OSS Distributions 	}
3304c1dac77fSApple OSS Distributions 
33058dd02465SApple OSS Distributions 	*iterator = IOUserIterator::withIterator(
33068dd02465SApple OSS Distributions 		IORegistryIterator::iterateOver(
33078dd02465SApple OSS Distributions 			IORegistryEntry::getPlane( plane ), options ));
3308c1dac77fSApple OSS Distributions 
3309a5e72196SApple OSS Distributions 	return *iterator ? kIOReturnSuccess : kIOReturnBadArgument;
3310c1dac77fSApple OSS Distributions }
3311c1dac77fSApple OSS Distributions 
3312c1dac77fSApple OSS Distributions /* Routine io_registry_entry_create_iterator */
3313a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_create_iterator(io_object_t registry_entry,io_name_t plane,uint32_t options,io_object_t * iterator)3314a5e72196SApple OSS Distributions is_io_registry_entry_create_iterator(
3315c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
3316c1dac77fSApple OSS Distributions 	io_name_t plane,
3317e13b1fa5SApple OSS Distributions 	uint32_t options,
3318c1dac77fSApple OSS Distributions 	io_object_t *iterator )
3319c1dac77fSApple OSS Distributions {
3320c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
3321c1dac77fSApple OSS Distributions 
33228dd02465SApple OSS Distributions 	*iterator = IOUserIterator::withIterator(
33238dd02465SApple OSS Distributions 		IORegistryIterator::iterateOver( entry,
33248dd02465SApple OSS Distributions 		IORegistryEntry::getPlane( plane ), options ));
3325c1dac77fSApple OSS Distributions 
3326a5e72196SApple OSS Distributions 	return *iterator ? kIOReturnSuccess : kIOReturnBadArgument;
3327c1dac77fSApple OSS Distributions }
3328c1dac77fSApple OSS Distributions 
3329c1dac77fSApple OSS Distributions /* Routine io_registry_iterator_enter */
3330a5e72196SApple OSS Distributions kern_return_t
is_io_registry_iterator_enter_entry(io_object_t iterator)3331a5e72196SApple OSS Distributions is_io_registry_iterator_enter_entry(
3332c1dac77fSApple OSS Distributions 	io_object_t iterator )
3333c1dac77fSApple OSS Distributions {
33348dd02465SApple OSS Distributions 	CHECKLOCKED( IORegistryIterator, iterator, iter );
3335c1dac77fSApple OSS Distributions 
3336aca3beaaSApple OSS Distributions 	IOLockLock(&oIter->lock);
3337c1dac77fSApple OSS Distributions 	iter->enterEntry();
3338aca3beaaSApple OSS Distributions 	IOLockUnlock(&oIter->lock);
3339c1dac77fSApple OSS Distributions 
3340a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
3341c1dac77fSApple OSS Distributions }
3342c1dac77fSApple OSS Distributions 
3343c1dac77fSApple OSS Distributions /* Routine io_registry_iterator_exit */
3344a5e72196SApple OSS Distributions kern_return_t
is_io_registry_iterator_exit_entry(io_object_t iterator)3345a5e72196SApple OSS Distributions is_io_registry_iterator_exit_entry(
3346c1dac77fSApple OSS Distributions 	io_object_t iterator )
3347c1dac77fSApple OSS Distributions {
3348c1dac77fSApple OSS Distributions 	bool        didIt;
3349c1dac77fSApple OSS Distributions 
33508dd02465SApple OSS Distributions 	CHECKLOCKED( IORegistryIterator, iterator, iter );
3351c1dac77fSApple OSS Distributions 
3352aca3beaaSApple OSS Distributions 	IOLockLock(&oIter->lock);
3353c1dac77fSApple OSS Distributions 	didIt = iter->exitEntry();
3354aca3beaaSApple OSS Distributions 	IOLockUnlock(&oIter->lock);
3355c1dac77fSApple OSS Distributions 
3356a5e72196SApple OSS Distributions 	return didIt ? kIOReturnSuccess : kIOReturnNoDevice;
3357c1dac77fSApple OSS Distributions }
3358c1dac77fSApple OSS Distributions 
3359c1dac77fSApple OSS Distributions /* Routine io_registry_entry_from_path */
3360a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_from_path(mach_port_t main_port,io_string_t path,io_object_t * registry_entry)3361a5e72196SApple OSS Distributions is_io_registry_entry_from_path(
33625c2921b0SApple OSS Distributions 	mach_port_t main_port,
3363c1dac77fSApple OSS Distributions 	io_string_t path,
3364c1dac77fSApple OSS Distributions 	io_object_t *registry_entry )
3365c1dac77fSApple OSS Distributions {
3366c1dac77fSApple OSS Distributions 	IORegistryEntry *   entry;
3367c1dac77fSApple OSS Distributions 
33685c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
3369a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
3370a5e72196SApple OSS Distributions 	}
3371c1dac77fSApple OSS Distributions 
3372c1dac77fSApple OSS Distributions 	entry = IORegistryEntry::fromPath( path );
3373c1dac77fSApple OSS Distributions 
3374bb611c8fSApple OSS Distributions 	if (!entry && IOTaskRegistryCompatibility(current_task())) {
3375bb611c8fSApple OSS Distributions 		OSDictionary * matching;
3376bb611c8fSApple OSS Distributions 		const OSObject * objects[2] = { kOSBooleanTrue, NULL };
3377bb611c8fSApple OSS Distributions 		const OSSymbol * keys[2]    = { gIOCompatibilityMatchKey, gIOPathMatchKey };
3378bb611c8fSApple OSS Distributions 
3379bb611c8fSApple OSS Distributions 		objects[1] = OSString::withCStringNoCopy(path);
3380bb611c8fSApple OSS Distributions 		matching = OSDictionary::withObjects(objects, keys, 2, 2);
3381bb611c8fSApple OSS Distributions 		if (matching) {
3382bb611c8fSApple OSS Distributions 			entry = IOService::copyMatchingService(matching);
3383bb611c8fSApple OSS Distributions 		}
3384bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(matching);
3385bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(objects[1]);
3386bb611c8fSApple OSS Distributions 	}
3387bb611c8fSApple OSS Distributions 
3388c1dac77fSApple OSS Distributions 	*registry_entry = entry;
3389c1dac77fSApple OSS Distributions 
3390a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
3391c1dac77fSApple OSS Distributions }
3392c1dac77fSApple OSS Distributions 
33930f3703acSApple OSS Distributions 
33940f3703acSApple OSS Distributions /* Routine io_registry_entry_from_path */
3395a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_from_path_ool(mach_port_t main_port,io_string_inband_t path,io_buf_ptr_t path_ool,mach_msg_type_number_t path_oolCnt,kern_return_t * result,io_object_t * registry_entry)3396a5e72196SApple OSS Distributions is_io_registry_entry_from_path_ool(
33975c2921b0SApple OSS Distributions 	mach_port_t main_port,
33980f3703acSApple OSS Distributions 	io_string_inband_t path,
33990f3703acSApple OSS Distributions 	io_buf_ptr_t path_ool,
34000f3703acSApple OSS Distributions 	mach_msg_type_number_t path_oolCnt,
34010f3703acSApple OSS Distributions 	kern_return_t *result,
34020f3703acSApple OSS Distributions 	io_object_t *registry_entry)
34030f3703acSApple OSS Distributions {
34040f3703acSApple OSS Distributions 	IORegistryEntry *   entry;
34050f3703acSApple OSS Distributions 	vm_map_offset_t     map_data;
34060f3703acSApple OSS Distributions 	const char *        cpath;
34070f3703acSApple OSS Distributions 	IOReturn            res;
34080f3703acSApple OSS Distributions 	kern_return_t       err;
34090f3703acSApple OSS Distributions 
34105c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
3411a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
3412a5e72196SApple OSS Distributions 	}
34130f3703acSApple OSS Distributions 
34140f3703acSApple OSS Distributions 	map_data = 0;
3415a5e72196SApple OSS Distributions 	entry    = NULL;
34160f3703acSApple OSS Distributions 	res = err = KERN_SUCCESS;
3417a5e72196SApple OSS Distributions 	if (path[0]) {
3418a5e72196SApple OSS Distributions 		cpath = path;
3419a5e72196SApple OSS Distributions 	} else {
3420a5e72196SApple OSS Distributions 		if (!path_oolCnt) {
3421a5e72196SApple OSS Distributions 			return kIOReturnBadArgument;
3422a5e72196SApple OSS Distributions 		}
3423a5e72196SApple OSS Distributions 		if (path_oolCnt > (sizeof(io_struct_inband_t) * 1024)) {
3424a5e72196SApple OSS Distributions 			return kIOReturnMessageTooLarge;
3425a5e72196SApple OSS Distributions 		}
34260f3703acSApple OSS Distributions 
34270f3703acSApple OSS Distributions 		err = vm_map_copyout(kernel_map, &map_data, (vm_map_copy_t) path_ool);
3428a5e72196SApple OSS Distributions 		if (KERN_SUCCESS == err) {
34290f3703acSApple OSS Distributions 			// must return success to mig after vm_map_copyout() succeeds, so result is actual
34300f3703acSApple OSS Distributions 			cpath = CAST_DOWN(const char *, map_data);
3431a5e72196SApple OSS Distributions 			if (cpath[path_oolCnt - 1]) {
3432a5e72196SApple OSS Distributions 				res = kIOReturnBadArgument;
3433a5e72196SApple OSS Distributions 			}
34340f3703acSApple OSS Distributions 		}
34350f3703acSApple OSS Distributions 	}
34360f3703acSApple OSS Distributions 
3437a5e72196SApple OSS Distributions 	if ((KERN_SUCCESS == err) && (KERN_SUCCESS == res)) {
34380f3703acSApple OSS Distributions 		entry = IORegistryEntry::fromPath(cpath);
34390f3703acSApple OSS Distributions 		res = entry ? kIOReturnSuccess : kIOReturnNotFound;
34400f3703acSApple OSS Distributions 	}
34410f3703acSApple OSS Distributions 
3442a5e72196SApple OSS Distributions 	if (map_data) {
3443a5e72196SApple OSS Distributions 		vm_deallocate(kernel_map, map_data, path_oolCnt);
3444a5e72196SApple OSS Distributions 	}
34450f3703acSApple OSS Distributions 
3446a5e72196SApple OSS Distributions 	if (KERN_SUCCESS != err) {
3447a5e72196SApple OSS Distributions 		res = err;
3448a5e72196SApple OSS Distributions 	}
34490f3703acSApple OSS Distributions 	*registry_entry = entry;
34500f3703acSApple OSS Distributions 	*result = res;
34510f3703acSApple OSS Distributions 
3452a5e72196SApple OSS Distributions 	return err;
34530f3703acSApple OSS Distributions }
34540f3703acSApple OSS Distributions 
34550f3703acSApple OSS Distributions 
3456c1dac77fSApple OSS Distributions /* Routine io_registry_entry_in_plane */
3457a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_in_plane(io_object_t registry_entry,io_name_t plane,boolean_t * inPlane)3458a5e72196SApple OSS Distributions is_io_registry_entry_in_plane(
3459c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
3460c1dac77fSApple OSS Distributions 	io_name_t plane,
3461c1dac77fSApple OSS Distributions 	boolean_t *inPlane )
3462c1dac77fSApple OSS Distributions {
3463c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
3464c1dac77fSApple OSS Distributions 
3465c1dac77fSApple OSS Distributions 	*inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
3466c1dac77fSApple OSS Distributions 
3467a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
3468c1dac77fSApple OSS Distributions }
3469c1dac77fSApple OSS Distributions 
3470c1dac77fSApple OSS Distributions 
3471c1dac77fSApple OSS Distributions /* Routine io_registry_entry_get_path */
3472a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_path(io_object_t registry_entry,io_name_t plane,io_string_t path)3473a5e72196SApple OSS Distributions is_io_registry_entry_get_path(
3474c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
3475c1dac77fSApple OSS Distributions 	io_name_t plane,
3476c1dac77fSApple OSS Distributions 	io_string_t path )
3477c1dac77fSApple OSS Distributions {
3478c1dac77fSApple OSS Distributions 	int         length;
3479c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
3480c1dac77fSApple OSS Distributions 
3481c1dac77fSApple OSS Distributions 	length = sizeof(io_string_t);
3482a5e72196SApple OSS Distributions 	if (entry->getPath( path, &length, IORegistryEntry::getPlane( plane ))) {
3483a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
3484a5e72196SApple OSS Distributions 	} else {
3485a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
3486a5e72196SApple OSS Distributions 	}
3487c1dac77fSApple OSS Distributions }
3488c1dac77fSApple OSS Distributions 
34890f3703acSApple OSS Distributions /* Routine io_registry_entry_get_path */
3490a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_path_ool(io_object_t registry_entry,io_name_t plane,io_string_inband_t path,io_buf_ptr_t * path_ool,mach_msg_type_number_t * path_oolCnt)3491a5e72196SApple OSS Distributions is_io_registry_entry_get_path_ool(
34920f3703acSApple OSS Distributions 	io_object_t registry_entry,
34930f3703acSApple OSS Distributions 	io_name_t plane,
34940f3703acSApple OSS Distributions 	io_string_inband_t path,
34950f3703acSApple OSS Distributions 	io_buf_ptr_t *path_ool,
34960f3703acSApple OSS Distributions 	mach_msg_type_number_t *path_oolCnt)
34970f3703acSApple OSS Distributions {
34980f3703acSApple OSS Distributions 	enum   { kMaxPath = 16384 };
34990f3703acSApple OSS Distributions 	IOReturn err;
35000f3703acSApple OSS Distributions 	int      length;
35010f3703acSApple OSS Distributions 	char   * buf;
35020f3703acSApple OSS Distributions 
35030f3703acSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
35040f3703acSApple OSS Distributions 
35050f3703acSApple OSS Distributions 	*path_ool    = NULL;
35060f3703acSApple OSS Distributions 	*path_oolCnt = 0;
35070f3703acSApple OSS Distributions 	length = sizeof(io_string_inband_t);
3508a5e72196SApple OSS Distributions 	if (entry->getPath(path, &length, IORegistryEntry::getPlane(plane))) {
3509a5e72196SApple OSS Distributions 		err = kIOReturnSuccess;
3510a5e72196SApple OSS Distributions 	} else {
35110f3703acSApple OSS Distributions 		length = kMaxPath;
3512e6231be0SApple OSS Distributions 		buf = IONewData(char, length);
3513a5e72196SApple OSS Distributions 		if (!buf) {
3514a5e72196SApple OSS Distributions 			err = kIOReturnNoMemory;
3515a5e72196SApple OSS Distributions 		} else if (!entry->getPath(buf, &length, IORegistryEntry::getPlane(plane))) {
3516a5e72196SApple OSS Distributions 			err = kIOReturnError;
3517a5e72196SApple OSS Distributions 		} else {
35180f3703acSApple OSS Distributions 			*path_oolCnt = length;
35190f3703acSApple OSS Distributions 			err = copyoutkdata(buf, length, path_ool);
35200f3703acSApple OSS Distributions 		}
3521a5e72196SApple OSS Distributions 		if (buf) {
3522e6231be0SApple OSS Distributions 			IODeleteData(buf, char, kMaxPath);
3523a5e72196SApple OSS Distributions 		}
35240f3703acSApple OSS Distributions 	}
35250f3703acSApple OSS Distributions 
3526a5e72196SApple OSS Distributions 	return err;
35270f3703acSApple OSS Distributions }
35280f3703acSApple OSS Distributions 
3529c1dac77fSApple OSS Distributions 
3530c1dac77fSApple OSS Distributions /* Routine io_registry_entry_get_name */
3531a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_name(io_object_t registry_entry,io_name_t name)3532a5e72196SApple OSS Distributions is_io_registry_entry_get_name(
3533c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
3534c1dac77fSApple OSS Distributions 	io_name_t name )
3535c1dac77fSApple OSS Distributions {
3536c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
3537c1dac77fSApple OSS Distributions 
3538c1dac77fSApple OSS Distributions 	strncpy( name, entry->getName(), sizeof(io_name_t));
3539c1dac77fSApple OSS Distributions 
3540a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
3541c1dac77fSApple OSS Distributions }
3542c1dac77fSApple OSS Distributions 
3543c1dac77fSApple OSS Distributions /* Routine io_registry_entry_get_name_in_plane */
3544a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_name_in_plane(io_object_t registry_entry,io_name_t planeName,io_name_t name)3545a5e72196SApple OSS Distributions is_io_registry_entry_get_name_in_plane(
3546c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
35478149afccSApple OSS Distributions 	io_name_t planeName,
3548c1dac77fSApple OSS Distributions 	io_name_t name )
3549c1dac77fSApple OSS Distributions {
35508149afccSApple OSS Distributions 	const IORegistryPlane * plane;
3551c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
3552c1dac77fSApple OSS Distributions 
3553a5e72196SApple OSS Distributions 	if (planeName[0]) {
35548149afccSApple OSS Distributions 		plane = IORegistryEntry::getPlane( planeName );
3555a5e72196SApple OSS Distributions 	} else {
3556a5e72196SApple OSS Distributions 		plane = NULL;
3557a5e72196SApple OSS Distributions 	}
35588149afccSApple OSS Distributions 
35598149afccSApple OSS Distributions 	strncpy( name, entry->getName( plane), sizeof(io_name_t));
3560c1dac77fSApple OSS Distributions 
3561a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
3562c1dac77fSApple OSS Distributions }
3563c1dac77fSApple OSS Distributions 
35648149afccSApple OSS Distributions /* Routine io_registry_entry_get_location_in_plane */
3565a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_location_in_plane(io_object_t registry_entry,io_name_t planeName,io_name_t location)3566a5e72196SApple OSS Distributions is_io_registry_entry_get_location_in_plane(
35678149afccSApple OSS Distributions 	io_object_t registry_entry,
35688149afccSApple OSS Distributions 	io_name_t planeName,
35698149afccSApple OSS Distributions 	io_name_t location )
35708149afccSApple OSS Distributions {
35718149afccSApple OSS Distributions 	const IORegistryPlane * plane;
35728149afccSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
35738149afccSApple OSS Distributions 
3574a5e72196SApple OSS Distributions 	if (planeName[0]) {
35758149afccSApple OSS Distributions 		plane = IORegistryEntry::getPlane( planeName );
3576a5e72196SApple OSS Distributions 	} else {
3577a5e72196SApple OSS Distributions 		plane = NULL;
3578a5e72196SApple OSS Distributions 	}
35798149afccSApple OSS Distributions 
35808149afccSApple OSS Distributions 	const char * cstr = entry->getLocation( plane );
35818149afccSApple OSS Distributions 
35828149afccSApple OSS Distributions 	if (cstr) {
35838149afccSApple OSS Distributions 		strncpy( location, cstr, sizeof(io_name_t));
3584a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
3585a5e72196SApple OSS Distributions 	} else {
3586a5e72196SApple OSS Distributions 		return kIOReturnNotFound;
3587a5e72196SApple OSS Distributions 	}
35888149afccSApple OSS Distributions }
35898149afccSApple OSS Distributions 
35903ca3bd55SApple OSS Distributions /* Routine io_registry_entry_get_registry_entry_id */
3591a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_registry_entry_id(io_object_t registry_entry,uint64_t * entry_id)3592a5e72196SApple OSS Distributions is_io_registry_entry_get_registry_entry_id(
35933ca3bd55SApple OSS Distributions 	io_object_t registry_entry,
35943ca3bd55SApple OSS Distributions 	uint64_t *entry_id )
35953ca3bd55SApple OSS Distributions {
35963ca3bd55SApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
35973ca3bd55SApple OSS Distributions 
35983ca3bd55SApple OSS Distributions 	*entry_id = entry->getRegistryEntryID();
35993ca3bd55SApple OSS Distributions 
3600a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
36013ca3bd55SApple OSS Distributions }
36023ca3bd55SApple OSS Distributions 
3603bb611c8fSApple OSS Distributions 
3604bb611c8fSApple OSS Distributions static OSObject *
IOCopyPropertyCompatible(IORegistryEntry * regEntry,const char * name)3605bb611c8fSApple OSS Distributions IOCopyPropertyCompatible(IORegistryEntry * regEntry, const char * name)
3606bb611c8fSApple OSS Distributions {
3607bb611c8fSApple OSS Distributions 	OSObject     * obj;
3608e6231be0SApple OSS Distributions 	OSObject     * compatProperties;
3609bb611c8fSApple OSS Distributions 	OSDictionary * props;
3610bb611c8fSApple OSS Distributions 
3611bb611c8fSApple OSS Distributions 	obj = regEntry->copyProperty(name);
3612e6231be0SApple OSS Distributions 	if (obj) {
3613e6231be0SApple OSS Distributions 		return obj;
3614e6231be0SApple OSS Distributions 	}
3615e6231be0SApple OSS Distributions 
3616e6231be0SApple OSS Distributions 	compatProperties = regEntry->copyProperty(gIOUserServicePropertiesKey);
3617e6231be0SApple OSS Distributions 	if (!compatProperties
3618e6231be0SApple OSS Distributions 	    && IOTaskRegistryCompatibility(current_task())) {
3619e6231be0SApple OSS Distributions 		compatProperties = regEntry->copyProperty(gIOCompatibilityPropertiesKey);
3620e6231be0SApple OSS Distributions 	}
3621e6231be0SApple OSS Distributions 	if (compatProperties) {
3622e6231be0SApple OSS Distributions 		props = OSDynamicCast(OSDictionary, compatProperties);
3623bb611c8fSApple OSS Distributions 		if (props) {
3624bb611c8fSApple OSS Distributions 			obj = props->getObject(name);
3625bb611c8fSApple OSS Distributions 			if (obj) {
3626bb611c8fSApple OSS Distributions 				obj->retain();
3627bb611c8fSApple OSS Distributions 			}
3628bb611c8fSApple OSS Distributions 		}
3629e6231be0SApple OSS Distributions 		compatProperties->release();
3630bb611c8fSApple OSS Distributions 	}
3631bb611c8fSApple OSS Distributions 
3632bb611c8fSApple OSS Distributions 	return obj;
3633bb611c8fSApple OSS Distributions }
3634bb611c8fSApple OSS Distributions 
36358149afccSApple OSS Distributions /* Routine io_registry_entry_get_property */
3636a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_property_bytes(io_object_t registry_entry,io_name_t property_name,io_struct_inband_t buf,mach_msg_type_number_t * dataCnt)3637a5e72196SApple OSS Distributions is_io_registry_entry_get_property_bytes(
36388149afccSApple OSS Distributions 	io_object_t registry_entry,
36398149afccSApple OSS Distributions 	io_name_t property_name,
3640e13b1fa5SApple OSS Distributions 	io_struct_inband_t buf,
36418149afccSApple OSS Distributions 	mach_msg_type_number_t *dataCnt )
36428149afccSApple OSS Distributions {
36438149afccSApple OSS Distributions 	OSObject    *       obj;
36448149afccSApple OSS Distributions 	OSData      *       data;
36458149afccSApple OSS Distributions 	OSString    *       str;
36468149afccSApple OSS Distributions 	OSBoolean   *       boo;
36478149afccSApple OSS Distributions 	OSNumber    *       off;
36488149afccSApple OSS Distributions 	UInt64              offsetBytes;
36498149afccSApple OSS Distributions 	unsigned int        len = 0;
3650a5e72196SApple OSS Distributions 	const void *        bytes = NULL;
36518149afccSApple OSS Distributions 	IOReturn            ret = kIOReturnSuccess;
36528149afccSApple OSS Distributions 
36538149afccSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
36548149afccSApple OSS Distributions 
3655a3bb9fccSApple OSS Distributions #if CONFIG_MACF
3656a5e72196SApple OSS Distributions 	if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) {
3657a3bb9fccSApple OSS Distributions 		return kIOReturnNotPermitted;
3658a5e72196SApple OSS Distributions 	}
3659a3bb9fccSApple OSS Distributions #endif
3660a3bb9fccSApple OSS Distributions 
3661bb611c8fSApple OSS Distributions 	obj = IOCopyPropertyCompatible(entry, property_name);
3662a5e72196SApple OSS Distributions 	if (!obj) {
3663a5e72196SApple OSS Distributions 		return kIOReturnNoResources;
3664a5e72196SApple OSS Distributions 	}
36658149afccSApple OSS Distributions 
36668149afccSApple OSS Distributions 	// One day OSData will be a common container base class
36678149afccSApple OSS Distributions 	// until then...
36688149afccSApple OSS Distributions 	if ((data = OSDynamicCast( OSData, obj ))) {
36698149afccSApple OSS Distributions 		len = data->getLength();
36708149afccSApple OSS Distributions 		bytes = data->getBytesNoCopy();
3671a5e72196SApple OSS Distributions 		if (!data->isSerializable()) {
3672a5e72196SApple OSS Distributions 			len = 0;
3673a5e72196SApple OSS Distributions 		}
36748149afccSApple OSS Distributions 	} else if ((str = OSDynamicCast( OSString, obj ))) {
36758149afccSApple OSS Distributions 		len = str->getLength() + 1;
36768149afccSApple OSS Distributions 		bytes = str->getCStringNoCopy();
36778149afccSApple OSS Distributions 	} else if ((boo = OSDynamicCast( OSBoolean, obj ))) {
36788149afccSApple OSS Distributions 		len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
36798149afccSApple OSS Distributions 		bytes = boo->isTrue() ? "Yes" : "No";
36808149afccSApple OSS Distributions 	} else if ((off = OSDynamicCast( OSNumber, obj ))) {
36818149afccSApple OSS Distributions 		offsetBytes = off->unsigned64BitValue();
36828149afccSApple OSS Distributions 		len = off->numberOfBytes();
3683a5e72196SApple OSS Distributions 		if (len > sizeof(offsetBytes)) {
3684a5e72196SApple OSS Distributions 			len = sizeof(offsetBytes);
3685a5e72196SApple OSS Distributions 		}
36868149afccSApple OSS Distributions 		bytes = &offsetBytes;
3687368ad365SApple OSS Distributions #ifdef __BIG_ENDIAN__
36888149afccSApple OSS Distributions 		bytes = (const void *)
36898149afccSApple OSS Distributions 		    (((UInt32) bytes) + (sizeof(UInt64) - len));
36908149afccSApple OSS Distributions #endif
3691a5e72196SApple OSS Distributions 	} else {
36928149afccSApple OSS Distributions 		ret = kIOReturnBadArgument;
3693a5e72196SApple OSS Distributions 	}
36948149afccSApple OSS Distributions 
36958149afccSApple OSS Distributions 	if (bytes) {
3696a5e72196SApple OSS Distributions 		if (*dataCnt < len) {
36978149afccSApple OSS Distributions 			ret = kIOReturnIPCError;
3698a5e72196SApple OSS Distributions 		} else {
36998149afccSApple OSS Distributions 			*dataCnt = len;
37008149afccSApple OSS Distributions 			bcopy( bytes, buf, len );
37018149afccSApple OSS Distributions 		}
37028149afccSApple OSS Distributions 	}
37038149afccSApple OSS Distributions 	obj->release();
37048149afccSApple OSS Distributions 
3705a5e72196SApple OSS Distributions 	return ret;
37068149afccSApple OSS Distributions }
37078149afccSApple OSS Distributions 
3708e13b1fa5SApple OSS Distributions 
37098149afccSApple OSS Distributions /* Routine io_registry_entry_get_property */
3710a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_property(io_object_t registry_entry,io_name_t property_name,io_buf_ptr_t * properties,mach_msg_type_number_t * propertiesCnt)3711a5e72196SApple OSS Distributions is_io_registry_entry_get_property(
37128149afccSApple OSS Distributions 	io_object_t registry_entry,
37138149afccSApple OSS Distributions 	io_name_t property_name,
37148149afccSApple OSS Distributions 	io_buf_ptr_t *properties,
37158149afccSApple OSS Distributions 	mach_msg_type_number_t *propertiesCnt )
37168149afccSApple OSS Distributions {
37178149afccSApple OSS Distributions 	kern_return_t       err;
3718bb611c8fSApple OSS Distributions 	unsigned int        len;
37198149afccSApple OSS Distributions 	OSObject *          obj;
37208149afccSApple OSS Distributions 
37218149afccSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
37228149afccSApple OSS Distributions 
3723a3bb9fccSApple OSS Distributions #if CONFIG_MACF
3724a5e72196SApple OSS Distributions 	if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) {
3725a3bb9fccSApple OSS Distributions 		return kIOReturnNotPermitted;
3726a5e72196SApple OSS Distributions 	}
3727a3bb9fccSApple OSS Distributions #endif
3728a3bb9fccSApple OSS Distributions 
3729bb611c8fSApple OSS Distributions 	obj = IOCopyPropertyCompatible(entry, property_name);
3730a5e72196SApple OSS Distributions 	if (!obj) {
3731a5e72196SApple OSS Distributions 		return kIOReturnNotFound;
3732a5e72196SApple OSS Distributions 	}
37338149afccSApple OSS Distributions 
37348149afccSApple OSS Distributions 	OSSerialize * s = OSSerialize::withCapacity(4096);
37358149afccSApple OSS Distributions 	if (!s) {
37368149afccSApple OSS Distributions 		obj->release();
3737a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
37388149afccSApple OSS Distributions 	}
37398149afccSApple OSS Distributions 
37408149afccSApple OSS Distributions 	if (obj->serialize( s )) {
37418149afccSApple OSS Distributions 		len = s->getLength();
37428149afccSApple OSS Distributions 		*propertiesCnt = len;
37438149afccSApple OSS Distributions 		err = copyoutkdata( s->text(), len, properties );
3744a5e72196SApple OSS Distributions 	} else {
37458149afccSApple OSS Distributions 		err = kIOReturnUnsupported;
3746a5e72196SApple OSS Distributions 	}
37478149afccSApple OSS Distributions 
37488149afccSApple OSS Distributions 	s->release();
37498149afccSApple OSS Distributions 	obj->release();
37508149afccSApple OSS Distributions 
3751a5e72196SApple OSS Distributions 	return err;
37528149afccSApple OSS Distributions }
37538149afccSApple OSS Distributions 
37548149afccSApple OSS Distributions /* Routine io_registry_entry_get_property_recursively */
3755a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_property_recursively(io_object_t registry_entry,io_name_t plane,io_name_t property_name,uint32_t options,io_buf_ptr_t * properties,mach_msg_type_number_t * propertiesCnt)3756a5e72196SApple OSS Distributions is_io_registry_entry_get_property_recursively(
37578149afccSApple OSS Distributions 	io_object_t registry_entry,
37588149afccSApple OSS Distributions 	io_name_t plane,
37598149afccSApple OSS Distributions 	io_name_t property_name,
3760e13b1fa5SApple OSS Distributions 	uint32_t options,
37618149afccSApple OSS Distributions 	io_buf_ptr_t *properties,
37628149afccSApple OSS Distributions 	mach_msg_type_number_t *propertiesCnt )
37638149afccSApple OSS Distributions {
37648149afccSApple OSS Distributions 	kern_return_t       err;
3765bb611c8fSApple OSS Distributions 	unsigned int        len;
37668149afccSApple OSS Distributions 	OSObject *          obj;
37678149afccSApple OSS Distributions 
37688149afccSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
37698149afccSApple OSS Distributions 
3770a3bb9fccSApple OSS Distributions #if CONFIG_MACF
3771a5e72196SApple OSS Distributions 	if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) {
3772a3bb9fccSApple OSS Distributions 		return kIOReturnNotPermitted;
3773a5e72196SApple OSS Distributions 	}
3774a3bb9fccSApple OSS Distributions #endif
3775a3bb9fccSApple OSS Distributions 
37768149afccSApple OSS Distributions 	obj = entry->copyProperty( property_name,
37778149afccSApple OSS Distributions 	    IORegistryEntry::getPlane( plane ), options );
3778a5e72196SApple OSS Distributions 	if (!obj) {
3779a5e72196SApple OSS Distributions 		return kIOReturnNotFound;
3780a5e72196SApple OSS Distributions 	}
37818149afccSApple OSS Distributions 
37828149afccSApple OSS Distributions 	OSSerialize * s = OSSerialize::withCapacity(4096);
37838149afccSApple OSS Distributions 	if (!s) {
37848149afccSApple OSS Distributions 		obj->release();
3785a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
37868149afccSApple OSS Distributions 	}
37878149afccSApple OSS Distributions 
37888149afccSApple OSS Distributions 	if (obj->serialize( s )) {
37898149afccSApple OSS Distributions 		len = s->getLength();
37908149afccSApple OSS Distributions 		*propertiesCnt = len;
37918149afccSApple OSS Distributions 		err = copyoutkdata( s->text(), len, properties );
3792a5e72196SApple OSS Distributions 	} else {
37938149afccSApple OSS Distributions 		err = kIOReturnUnsupported;
3794a5e72196SApple OSS Distributions 	}
37958149afccSApple OSS Distributions 
37968149afccSApple OSS Distributions 	s->release();
37978149afccSApple OSS Distributions 	obj->release();
37988149afccSApple OSS Distributions 
3799a5e72196SApple OSS Distributions 	return err;
38008149afccSApple OSS Distributions }
3801c1dac77fSApple OSS Distributions 
3802c1dac77fSApple OSS Distributions /* Routine io_registry_entry_get_properties */
3803a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_properties(io_object_t registry_entry,io_buf_ptr_t * properties,mach_msg_type_number_t * propertiesCnt)3804a5e72196SApple OSS Distributions is_io_registry_entry_get_properties(
3805c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
3806c1dac77fSApple OSS Distributions 	io_buf_ptr_t *properties,
3807c1dac77fSApple OSS Distributions 	mach_msg_type_number_t *propertiesCnt )
3808c1dac77fSApple OSS Distributions {
3809a5e72196SApple OSS Distributions 	return kIOReturnUnsupported;
3810a3bb9fccSApple OSS Distributions }
3811a3bb9fccSApple OSS Distributions 
3812a3bb9fccSApple OSS Distributions #if CONFIG_MACF
3813a3bb9fccSApple OSS Distributions 
3814a5e72196SApple OSS Distributions struct GetPropertiesEditorRef {
3815a3bb9fccSApple OSS Distributions 	kauth_cred_t      cred;
3816a3bb9fccSApple OSS Distributions 	IORegistryEntry * entry;
3817a3bb9fccSApple OSS Distributions 	OSCollection    * root;
3818a3bb9fccSApple OSS Distributions };
3819a3bb9fccSApple OSS Distributions 
3820e6231be0SApple OSS Distributions static const LIBKERN_RETURNS_RETAINED OSMetaClassBase *
GetPropertiesEditor(void * reference,OSSerialize * s,OSCollection * container,const OSSymbol * name,const OSMetaClassBase * value)3821a3bb9fccSApple OSS Distributions GetPropertiesEditor(void                  * reference,
3822a3bb9fccSApple OSS Distributions     OSSerialize           * s,
3823a3bb9fccSApple OSS Distributions     OSCollection          * container,
3824a3bb9fccSApple OSS Distributions     const OSSymbol        * name,
3825a3bb9fccSApple OSS Distributions     const OSMetaClassBase * value)
3826a3bb9fccSApple OSS Distributions {
3827a3bb9fccSApple OSS Distributions 	GetPropertiesEditorRef * ref = (typeof(ref))reference;
3828a3bb9fccSApple OSS Distributions 
3829a5e72196SApple OSS Distributions 	if (!ref->root) {
3830a5e72196SApple OSS Distributions 		ref->root = container;
3831a5e72196SApple OSS Distributions 	}
3832a5e72196SApple OSS Distributions 	if (ref->root == container) {
3833a5e72196SApple OSS Distributions 		if (0 != mac_iokit_check_get_property(ref->cred, ref->entry, name->getCStringNoCopy())) {
3834a5e72196SApple OSS Distributions 			value = NULL;
3835a3bb9fccSApple OSS Distributions 		}
3836a3bb9fccSApple OSS Distributions 	}
3837a5e72196SApple OSS Distributions 	if (value) {
3838a5e72196SApple OSS Distributions 		value->retain();
3839a5e72196SApple OSS Distributions 	}
3840a5e72196SApple OSS Distributions 	return value;
3841a3bb9fccSApple OSS Distributions }
3842a3bb9fccSApple OSS Distributions 
3843a3bb9fccSApple OSS Distributions #endif /* CONFIG_MACF */
3844a3bb9fccSApple OSS Distributions 
3845bb611c8fSApple OSS Distributions /* Routine io_registry_entry_get_properties_bin_buf */
3846a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_properties_bin_buf(io_object_t registry_entry,mach_vm_address_t buf,mach_vm_size_t * bufsize,io_buf_ptr_t * properties,mach_msg_type_number_t * propertiesCnt)3847bb611c8fSApple OSS Distributions is_io_registry_entry_get_properties_bin_buf(
3848a3bb9fccSApple OSS Distributions 	io_object_t registry_entry,
3849bb611c8fSApple OSS Distributions 	mach_vm_address_t buf,
3850bb611c8fSApple OSS Distributions 	mach_vm_size_t *bufsize,
3851a3bb9fccSApple OSS Distributions 	io_buf_ptr_t *properties,
3852a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t *propertiesCnt)
3853a3bb9fccSApple OSS Distributions {
3854a3bb9fccSApple OSS Distributions 	kern_return_t          err = kIOReturnSuccess;
3855bb611c8fSApple OSS Distributions 	unsigned int           len;
3856bb611c8fSApple OSS Distributions 	OSObject             * compatProperties;
3857a3bb9fccSApple OSS Distributions 	OSSerialize          * s;
3858a5e72196SApple OSS Distributions 	OSSerialize::Editor    editor = NULL;
3859a5e72196SApple OSS Distributions 	void                 * editRef = NULL;
3860a3bb9fccSApple OSS Distributions 
3861a3bb9fccSApple OSS Distributions 	CHECK(IORegistryEntry, registry_entry, entry);
3862a3bb9fccSApple OSS Distributions 
3863a3bb9fccSApple OSS Distributions #if CONFIG_MACF
3864a3bb9fccSApple OSS Distributions 	GetPropertiesEditorRef ref;
3865a5e72196SApple OSS Distributions 	if (mac_iokit_check_filter_properties(kauth_cred_get(), entry)) {
3866a3bb9fccSApple OSS Distributions 		editor    = &GetPropertiesEditor;
3867a3bb9fccSApple OSS Distributions 		editRef   = &ref;
3868a3bb9fccSApple OSS Distributions 		ref.cred  = kauth_cred_get();
3869a3bb9fccSApple OSS Distributions 		ref.entry = entry;
3870a5e72196SApple OSS Distributions 		ref.root  = NULL;
3871a3bb9fccSApple OSS Distributions 	}
3872a3bb9fccSApple OSS Distributions #endif
3873a3bb9fccSApple OSS Distributions 
3874a3bb9fccSApple OSS Distributions 	s = OSSerialize::binaryWithCapacity(4096, editor, editRef);
3875a5e72196SApple OSS Distributions 	if (!s) {
3876a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
3877a5e72196SApple OSS Distributions 	}
3878a3bb9fccSApple OSS Distributions 
3879e6231be0SApple OSS Distributions 
3880e6231be0SApple OSS Distributions 	compatProperties = entry->copyProperty(gIOUserServicePropertiesKey);
3881e6231be0SApple OSS Distributions 	if (!compatProperties
3882e6231be0SApple OSS Distributions 	    && IOTaskRegistryCompatibility(current_task())) {
3883e6231be0SApple OSS Distributions 		compatProperties = entry->copyProperty(gIOCompatibilityPropertiesKey);
3884e6231be0SApple OSS Distributions 	}
3885e6231be0SApple OSS Distributions 
3886e6231be0SApple OSS Distributions 	if (compatProperties) {
3887bb611c8fSApple OSS Distributions 		OSDictionary * dict;
3888bb611c8fSApple OSS Distributions 
3889bb611c8fSApple OSS Distributions 		dict = entry->dictionaryWithProperties();
3890bb611c8fSApple OSS Distributions 		if (!dict) {
3891bb611c8fSApple OSS Distributions 			err = kIOReturnNoMemory;
3892bb611c8fSApple OSS Distributions 		} else {
3893e6231be0SApple OSS Distributions 			dict->removeObject(gIOUserServicePropertiesKey);
3894bb611c8fSApple OSS Distributions 			dict->removeObject(gIOCompatibilityPropertiesKey);
3895bb611c8fSApple OSS Distributions 			dict->merge(OSDynamicCast(OSDictionary, compatProperties));
3896bb611c8fSApple OSS Distributions 			if (!dict->serialize(s)) {
3897bb611c8fSApple OSS Distributions 				err = kIOReturnUnsupported;
3898bb611c8fSApple OSS Distributions 			}
3899bb611c8fSApple OSS Distributions 			dict->release();
3900bb611c8fSApple OSS Distributions 		}
3901bb611c8fSApple OSS Distributions 		compatProperties->release();
3902bb611c8fSApple OSS Distributions 	} else if (!entry->serializeProperties(s)) {
3903a5e72196SApple OSS Distributions 		err = kIOReturnUnsupported;
3904a5e72196SApple OSS Distributions 	}
3905a3bb9fccSApple OSS Distributions 
3906a5e72196SApple OSS Distributions 	if (kIOReturnSuccess == err) {
3907a3bb9fccSApple OSS Distributions 		len = s->getLength();
3908bb611c8fSApple OSS Distributions 		if (buf && bufsize && len <= *bufsize) {
3909bb611c8fSApple OSS Distributions 			*bufsize = len;
3910bb611c8fSApple OSS Distributions 			*propertiesCnt = 0;
3911bb611c8fSApple OSS Distributions 			*properties = nullptr;
3912bb611c8fSApple OSS Distributions 			if (copyout(s->text(), buf, len)) {
3913bb611c8fSApple OSS Distributions 				err = kIOReturnVMError;
3914bb611c8fSApple OSS Distributions 			} else {
3915bb611c8fSApple OSS Distributions 				err = kIOReturnSuccess;
3916bb611c8fSApple OSS Distributions 			}
3917bb611c8fSApple OSS Distributions 		} else {
3918bb611c8fSApple OSS Distributions 			if (bufsize) {
3919bb611c8fSApple OSS Distributions 				*bufsize = 0;
3920bb611c8fSApple OSS Distributions 			}
3921a3bb9fccSApple OSS Distributions 			*propertiesCnt = len;
3922a3bb9fccSApple OSS Distributions 			err = copyoutkdata( s->text(), len, properties );
3923a3bb9fccSApple OSS Distributions 		}
3924bb611c8fSApple OSS Distributions 	}
3925a3bb9fccSApple OSS Distributions 	s->release();
3926a3bb9fccSApple OSS Distributions 
3927a5e72196SApple OSS Distributions 	return err;
3928a3bb9fccSApple OSS Distributions }
3929a3bb9fccSApple OSS Distributions 
3930bb611c8fSApple OSS Distributions /* Routine io_registry_entry_get_properties_bin */
3931a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_properties_bin(io_object_t registry_entry,io_buf_ptr_t * properties,mach_msg_type_number_t * propertiesCnt)3932bb611c8fSApple OSS Distributions is_io_registry_entry_get_properties_bin(
3933bb611c8fSApple OSS Distributions 	io_object_t registry_entry,
3934bb611c8fSApple OSS Distributions 	io_buf_ptr_t *properties,
3935bb611c8fSApple OSS Distributions 	mach_msg_type_number_t *propertiesCnt)
3936bb611c8fSApple OSS Distributions {
3937bb611c8fSApple OSS Distributions 	return is_io_registry_entry_get_properties_bin_buf(registry_entry,
3938bb611c8fSApple OSS Distributions 	           0, NULL, properties, propertiesCnt);
3939bb611c8fSApple OSS Distributions }
3940bb611c8fSApple OSS Distributions 
3941bb611c8fSApple OSS Distributions /* Routine io_registry_entry_get_property_bin_buf */
3942bb611c8fSApple OSS Distributions kern_return_t
is_io_registry_entry_get_property_bin_buf(io_object_t registry_entry,io_name_t plane,io_name_t property_name,uint32_t options,mach_vm_address_t buf,mach_vm_size_t * bufsize,io_buf_ptr_t * properties,mach_msg_type_number_t * propertiesCnt)3943bb611c8fSApple OSS Distributions is_io_registry_entry_get_property_bin_buf(
3944a3bb9fccSApple OSS Distributions 	io_object_t registry_entry,
3945a3bb9fccSApple OSS Distributions 	io_name_t plane,
3946a3bb9fccSApple OSS Distributions 	io_name_t property_name,
3947a3bb9fccSApple OSS Distributions 	uint32_t options,
3948bb611c8fSApple OSS Distributions 	mach_vm_address_t buf,
3949bb611c8fSApple OSS Distributions 	mach_vm_size_t *bufsize,
3950a3bb9fccSApple OSS Distributions 	io_buf_ptr_t *properties,
3951a3bb9fccSApple OSS Distributions 	mach_msg_type_number_t *propertiesCnt )
3952a3bb9fccSApple OSS Distributions {
3953a3bb9fccSApple OSS Distributions 	kern_return_t       err;
3954bb611c8fSApple OSS Distributions 	unsigned int        len;
3955a3bb9fccSApple OSS Distributions 	OSObject *          obj;
3956a3bb9fccSApple OSS Distributions 	const OSSymbol *    sym;
3957a3bb9fccSApple OSS Distributions 
3958a3bb9fccSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
3959a3bb9fccSApple OSS Distributions 
3960a3bb9fccSApple OSS Distributions #if CONFIG_MACF
3961a5e72196SApple OSS Distributions 	if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) {
3962a3bb9fccSApple OSS Distributions 		return kIOReturnNotPermitted;
3963a5e72196SApple OSS Distributions 	}
3964a3bb9fccSApple OSS Distributions #endif
3965a3bb9fccSApple OSS Distributions 
396688cc0b97SApple OSS Distributions 	sym = OSSymbol::withCString(property_name);
3967a5e72196SApple OSS Distributions 	if (!sym) {
3968a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
396988cc0b97SApple OSS Distributions 	}
3970a5e72196SApple OSS Distributions 
3971e6231be0SApple OSS Distributions 	err = kIOReturnNotFound;
3972a5e72196SApple OSS Distributions 	if (gIORegistryEntryPropertyKeysKey == sym) {
3973a5e72196SApple OSS Distributions 		obj = entry->copyPropertyKeys();
3974a5e72196SApple OSS Distributions 	} else {
3975a5e72196SApple OSS Distributions 		if ((kIORegistryIterateRecursively & options) && plane[0]) {
3976bb611c8fSApple OSS Distributions 			obj = IOCopyPropertyCompatible(entry, property_name);
3977e6231be0SApple OSS Distributions 			if (obj == NULL) {
3978e6231be0SApple OSS Distributions 				IORegistryIterator * iter = IORegistryIterator::iterateOver(entry, IORegistryEntry::getPlane(plane), options);
3979bb611c8fSApple OSS Distributions 				if (iter) {
3980bb611c8fSApple OSS Distributions 					while ((NULL == obj) && (entry = iter->getNextObject())) {
3981e6231be0SApple OSS Distributions 						OSObject * currentObj = IOCopyPropertyCompatible(entry, property_name);
3982e6231be0SApple OSS Distributions #if CONFIG_MACF
3983e6231be0SApple OSS Distributions 						if (currentObj != NULL && 0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) {
3984e6231be0SApple OSS Distributions 							// Record that MAC hook blocked this entry and property, and continue to next entry
3985e6231be0SApple OSS Distributions 							err = kIOReturnNotPermitted;
3986e6231be0SApple OSS Distributions 							OSSafeReleaseNULL(currentObj);
3987e6231be0SApple OSS Distributions 							continue;
3988e6231be0SApple OSS Distributions 						}
3989e6231be0SApple OSS Distributions #endif
3990e6231be0SApple OSS Distributions 						obj = currentObj;
3991bb611c8fSApple OSS Distributions 					}
3992bb611c8fSApple OSS Distributions 					iter->release();
3993bb611c8fSApple OSS Distributions 				}
3994bb611c8fSApple OSS Distributions 			}
3995bb611c8fSApple OSS Distributions 		} else {
3996bb611c8fSApple OSS Distributions 			obj = IOCopyPropertyCompatible(entry, property_name);
3997a3bb9fccSApple OSS Distributions 		}
3998a5e72196SApple OSS Distributions 		if (obj && gIORemoveOnReadProperties->containsObject(sym)) {
3999a5e72196SApple OSS Distributions 			entry->removeProperty(sym);
4000a5e72196SApple OSS Distributions 		}
4001a3bb9fccSApple OSS Distributions 	}
4002a3bb9fccSApple OSS Distributions 
400388cc0b97SApple OSS Distributions 	sym->release();
4004a5e72196SApple OSS Distributions 	if (!obj) {
4005e6231be0SApple OSS Distributions 		return err;
4006a5e72196SApple OSS Distributions 	}
400788cc0b97SApple OSS Distributions 
4008a3bb9fccSApple OSS Distributions 	OSSerialize * s = OSSerialize::binaryWithCapacity(4096);
4009a3bb9fccSApple OSS Distributions 	if (!s) {
4010a3bb9fccSApple OSS Distributions 		obj->release();
4011a5e72196SApple OSS Distributions 		return kIOReturnNoMemory;
4012a3bb9fccSApple OSS Distributions 	}
4013a3bb9fccSApple OSS Distributions 
4014a3bb9fccSApple OSS Distributions 	if (obj->serialize( s )) {
4015c1dac77fSApple OSS Distributions 		len = s->getLength();
4016bb611c8fSApple OSS Distributions 		if (buf && bufsize && len <= *bufsize) {
4017bb611c8fSApple OSS Distributions 			*bufsize = len;
4018bb611c8fSApple OSS Distributions 			*propertiesCnt = 0;
4019bb611c8fSApple OSS Distributions 			*properties = nullptr;
4020bb611c8fSApple OSS Distributions 			if (copyout(s->text(), buf, len)) {
4021bb611c8fSApple OSS Distributions 				err = kIOReturnVMError;
4022bb611c8fSApple OSS Distributions 			} else {
4023bb611c8fSApple OSS Distributions 				err = kIOReturnSuccess;
4024bb611c8fSApple OSS Distributions 			}
4025bb611c8fSApple OSS Distributions 		} else {
4026bb611c8fSApple OSS Distributions 			if (bufsize) {
4027bb611c8fSApple OSS Distributions 				*bufsize = 0;
4028bb611c8fSApple OSS Distributions 			}
4029c1dac77fSApple OSS Distributions 			*propertiesCnt = len;
4030c1dac77fSApple OSS Distributions 			err = copyoutkdata( s->text(), len, properties );
4031bb611c8fSApple OSS Distributions 		}
4032a5e72196SApple OSS Distributions 	} else {
4033a5e72196SApple OSS Distributions 		err = kIOReturnUnsupported;
4034a5e72196SApple OSS Distributions 	}
4035c1dac77fSApple OSS Distributions 
4036c1dac77fSApple OSS Distributions 	s->release();
4037a3bb9fccSApple OSS Distributions 	obj->release();
4038c1dac77fSApple OSS Distributions 
4039a5e72196SApple OSS Distributions 	return err;
4040c1dac77fSApple OSS Distributions }
4041c1dac77fSApple OSS Distributions 
4042bb611c8fSApple OSS Distributions /* Routine io_registry_entry_get_property_bin */
4043bb611c8fSApple OSS Distributions kern_return_t
is_io_registry_entry_get_property_bin(io_object_t registry_entry,io_name_t plane,io_name_t property_name,uint32_t options,io_buf_ptr_t * properties,mach_msg_type_number_t * propertiesCnt)4044bb611c8fSApple OSS Distributions is_io_registry_entry_get_property_bin(
4045bb611c8fSApple OSS Distributions 	io_object_t registry_entry,
4046bb611c8fSApple OSS Distributions 	io_name_t plane,
4047bb611c8fSApple OSS Distributions 	io_name_t property_name,
4048bb611c8fSApple OSS Distributions 	uint32_t options,
4049bb611c8fSApple OSS Distributions 	io_buf_ptr_t *properties,
4050bb611c8fSApple OSS Distributions 	mach_msg_type_number_t *propertiesCnt )
4051bb611c8fSApple OSS Distributions {
4052bb611c8fSApple OSS Distributions 	return is_io_registry_entry_get_property_bin_buf(registry_entry, plane,
4053bb611c8fSApple OSS Distributions 	           property_name, options, 0, NULL, properties, propertiesCnt);
4054bb611c8fSApple OSS Distributions }
4055bb611c8fSApple OSS Distributions 
40560f3703acSApple OSS Distributions 
4057c1dac77fSApple OSS Distributions /* Routine io_registry_entry_set_properties */
4058a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_set_properties(io_object_t registry_entry,io_buf_ptr_t properties,mach_msg_type_number_t propertiesCnt,kern_return_t * result)4059a5e72196SApple OSS Distributions is_io_registry_entry_set_properties
4060c1dac77fSApple OSS Distributions (
4061c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
4062c1dac77fSApple OSS Distributions 	io_buf_ptr_t properties,
4063c1dac77fSApple OSS Distributions 	mach_msg_type_number_t propertiesCnt,
4064e13b1fa5SApple OSS Distributions 	kern_return_t * result)
4065c1dac77fSApple OSS Distributions {
4066c1dac77fSApple OSS Distributions 	OSObject *          obj;
4067c1dac77fSApple OSS Distributions 	kern_return_t       err;
4068c1dac77fSApple OSS Distributions 	IOReturn            res;
4069c1dac77fSApple OSS Distributions 	vm_offset_t         data;
407014e3d835SApple OSS Distributions 	vm_map_offset_t     map_data;
4071c1dac77fSApple OSS Distributions 
4072c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
4073c1dac77fSApple OSS Distributions 
4074a5e72196SApple OSS Distributions 	if (propertiesCnt > sizeof(io_struct_inband_t) * 1024) {
4075a5e72196SApple OSS Distributions 		return kIOReturnMessageTooLarge;
4076a5e72196SApple OSS Distributions 	}
4077186b8fceSApple OSS Distributions 
407814e3d835SApple OSS Distributions 	err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
407914e3d835SApple OSS Distributions 	data = CAST_DOWN(vm_offset_t, map_data);
4080c1dac77fSApple OSS Distributions 
4081c1dac77fSApple OSS Distributions 	if (KERN_SUCCESS == err) {
408288cc0b97SApple OSS Distributions 		FAKE_STACK_FRAME(entry->getMetaClass());
408388cc0b97SApple OSS Distributions 
4084c1dac77fSApple OSS Distributions 		// must return success after vm_map_copyout() succeeds
4085186b8fceSApple OSS Distributions 		obj = OSUnserializeXML((const char *) data, propertiesCnt );
4086c1dac77fSApple OSS Distributions 		vm_deallocate( kernel_map, data, propertiesCnt );
4087c1dac77fSApple OSS Distributions 
4088a5e72196SApple OSS Distributions 		if (!obj) {
4089c1dac77fSApple OSS Distributions 			res = kIOReturnBadArgument;
4090a5e72196SApple OSS Distributions 		}
4091855239e5SApple OSS Distributions #if CONFIG_MACF
4092855239e5SApple OSS Distributions 		else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
4093a5e72196SApple OSS Distributions 		    registry_entry, obj)) {
4094855239e5SApple OSS Distributions 			res = kIOReturnNotPermitted;
4095a3bb9fccSApple OSS Distributions 		}
4096855239e5SApple OSS Distributions #endif
4097a5e72196SApple OSS Distributions 		else {
4098e6231be0SApple OSS Distributions 			IOService    * service = OSDynamicCast(IOService, entry);
4099e6231be0SApple OSS Distributions 			OSDictionary * props = OSDynamicCast(OSDictionary, obj);
41005c2921b0SApple OSS Distributions 			OSObject     * allowable = entry->copyProperty(gIORegistryEntryAllowableSetPropertiesKey);
41015c2921b0SApple OSS Distributions 			OSArray      * allowableArray;
41025c2921b0SApple OSS Distributions 
41035c2921b0SApple OSS Distributions 			if (!allowable) {
41045c2921b0SApple OSS Distributions 				res = kIOReturnSuccess;
41055c2921b0SApple OSS Distributions 			} else {
41065c2921b0SApple OSS Distributions 				if (!props) {
41075c2921b0SApple OSS Distributions 					res = kIOReturnNotPermitted;
41085c2921b0SApple OSS Distributions 				} else if (!(allowableArray = OSDynamicCast(OSArray, allowable))) {
41095c2921b0SApple OSS Distributions 					res = kIOReturnNotPermitted;
41105c2921b0SApple OSS Distributions 				} else {
41115c2921b0SApple OSS Distributions 					bool allFound __block, found __block;
41125c2921b0SApple OSS Distributions 
41135c2921b0SApple OSS Distributions 					allFound = true;
41145c2921b0SApple OSS Distributions 					props->iterateObjects(^(const OSSymbol * key, OSObject * value) {
41155c2921b0SApple OSS Distributions 							found = false;
41165c2921b0SApple OSS Distributions 							for (unsigned int idx = 0; !found; idx++) {
41175c2921b0SApple OSS Distributions 							        OSObject * next = allowableArray->getObject(idx);
41185c2921b0SApple OSS Distributions 							        if (!next) {
41195c2921b0SApple OSS Distributions 							                break;
41205c2921b0SApple OSS Distributions 								}
41215c2921b0SApple OSS Distributions 							        found = next->isEqualTo(key);
41225c2921b0SApple OSS Distributions 							}
41235c2921b0SApple OSS Distributions 							allFound &= found;
41245c2921b0SApple OSS Distributions 							if (!found) {
41255c2921b0SApple OSS Distributions 							        IOLog("IORegistryEntrySetProperties(%s, %s) disallowed due to " kIORegistryEntryAllowableSetPropertiesKey "\n",
41265c2921b0SApple OSS Distributions 							        entry->getName(), key->getCStringNoCopy());
41275c2921b0SApple OSS Distributions 							}
41285c2921b0SApple OSS Distributions 							return !allFound;
41295c2921b0SApple OSS Distributions 						});
41305c2921b0SApple OSS Distributions 					res =  allFound ? kIOReturnSuccess : kIOReturnBadArgument;
41315c2921b0SApple OSS Distributions 				}
41325c2921b0SApple OSS Distributions 			}
41335c2921b0SApple OSS Distributions 			if (kIOReturnSuccess == res) {
41345c2921b0SApple OSS Distributions 				IOUserClient *
41355c2921b0SApple OSS Distributions 				    client = OSDynamicCast(IOUserClient, entry);
41365c2921b0SApple OSS Distributions 
41375c2921b0SApple OSS Distributions 				if (client && client->defaultLockingSetProperties) {
4138aca3beaaSApple OSS Distributions 					IORWLockWrite(&client->lock);
41395c2921b0SApple OSS Distributions 				}
41405c2921b0SApple OSS Distributions 
41415c2921b0SApple OSS Distributions 				if (!client && (kOSBooleanTrue == entry->getProperty(gIORegistryEntryDefaultLockingSetPropertiesKey))) {
41425c2921b0SApple OSS Distributions 					res = entry->runPropertyActionBlock(^IOReturn (void) {
41435c2921b0SApple OSS Distributions 							return entry->setProperties( obj );
41445c2921b0SApple OSS Distributions 						});
41455c2921b0SApple OSS Distributions 				} else {
41465c2921b0SApple OSS Distributions 					res = entry->setProperties( obj );
41475c2921b0SApple OSS Distributions 				}
41485c2921b0SApple OSS Distributions 
41495c2921b0SApple OSS Distributions 				if (client && client->defaultLockingSetProperties) {
4150aca3beaaSApple OSS Distributions 					IORWLockUnlock(&client->lock);
41515c2921b0SApple OSS Distributions 				}
4152e6231be0SApple OSS Distributions 				if (service && props && service->hasUserServer()) {
4153e6231be0SApple OSS Distributions 					res = service->UserSetProperties(props);
4154e6231be0SApple OSS Distributions 				}
4155a3bb9fccSApple OSS Distributions 			}
41565c2921b0SApple OSS Distributions 			OSSafeReleaseNULL(allowable);
41575c2921b0SApple OSS Distributions 		}
4158a5e72196SApple OSS Distributions 		if (obj) {
4159855239e5SApple OSS Distributions 			obj->release();
4160a5e72196SApple OSS Distributions 		}
416188cc0b97SApple OSS Distributions 
416288cc0b97SApple OSS Distributions 		FAKE_STACK_FRAME_END();
4163a5e72196SApple OSS Distributions 	} else {
4164c1dac77fSApple OSS Distributions 		res = err;
4165a5e72196SApple OSS Distributions 	}
4166c1dac77fSApple OSS Distributions 
4167c1dac77fSApple OSS Distributions 	*result = res;
4168a5e72196SApple OSS Distributions 	return err;
4169c1dac77fSApple OSS Distributions }
4170c1dac77fSApple OSS Distributions 
4171c1dac77fSApple OSS Distributions /* Routine io_registry_entry_get_child_iterator */
4172a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_child_iterator(io_object_t registry_entry,io_name_t plane,io_object_t * iterator)4173a5e72196SApple OSS Distributions is_io_registry_entry_get_child_iterator(
4174c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
4175c1dac77fSApple OSS Distributions 	io_name_t plane,
4176c1dac77fSApple OSS Distributions 	io_object_t *iterator )
4177c1dac77fSApple OSS Distributions {
4178c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
4179c1dac77fSApple OSS Distributions 
4180cc9a6355SApple OSS Distributions 	*iterator = IOUserIterator::withIterator(entry->getChildIterator(
4181cc9a6355SApple OSS Distributions 		    IORegistryEntry::getPlane( plane )));
4182c1dac77fSApple OSS Distributions 
4183a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4184c1dac77fSApple OSS Distributions }
4185c1dac77fSApple OSS Distributions 
4186c1dac77fSApple OSS Distributions /* Routine io_registry_entry_get_parent_iterator */
4187a5e72196SApple OSS Distributions kern_return_t
is_io_registry_entry_get_parent_iterator(io_object_t registry_entry,io_name_t plane,io_object_t * iterator)4188a5e72196SApple OSS Distributions is_io_registry_entry_get_parent_iterator(
4189c1dac77fSApple OSS Distributions 	io_object_t registry_entry,
4190c1dac77fSApple OSS Distributions 	io_name_t plane,
4191c1dac77fSApple OSS Distributions 	io_object_t *iterator)
4192c1dac77fSApple OSS Distributions {
4193c1dac77fSApple OSS Distributions 	CHECK( IORegistryEntry, registry_entry, entry );
4194c1dac77fSApple OSS Distributions 
4195cc9a6355SApple OSS Distributions 	*iterator = IOUserIterator::withIterator(entry->getParentIterator(
4196cc9a6355SApple OSS Distributions 		    IORegistryEntry::getPlane( plane )));
4197c1dac77fSApple OSS Distributions 
4198a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4199c1dac77fSApple OSS Distributions }
4200c1dac77fSApple OSS Distributions 
4201c1dac77fSApple OSS Distributions /* Routine io_service_get_busy_state */
4202a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_busy_state(io_object_t _service,uint32_t * busyState)4203a5e72196SApple OSS Distributions is_io_service_get_busy_state(
4204c1dac77fSApple OSS Distributions 	io_object_t _service,
4205e13b1fa5SApple OSS Distributions 	uint32_t *busyState )
4206c1dac77fSApple OSS Distributions {
4207c1dac77fSApple OSS Distributions 	CHECK( IOService, _service, service );
4208c1dac77fSApple OSS Distributions 
4209c1dac77fSApple OSS Distributions 	*busyState = service->getBusyState();
4210c1dac77fSApple OSS Distributions 
4211a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4212c1dac77fSApple OSS Distributions }
4213c1dac77fSApple OSS Distributions 
4214368ad365SApple OSS Distributions /* Routine io_service_get_state */
4215a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_state(io_object_t _service,uint64_t * state,uint32_t * busy_state,uint64_t * accumulated_busy_time)4216a5e72196SApple OSS Distributions is_io_service_get_state(
4217368ad365SApple OSS Distributions 	io_object_t _service,
42183ca3bd55SApple OSS Distributions 	uint64_t *state,
42193ca3bd55SApple OSS Distributions 	uint32_t *busy_state,
42203ca3bd55SApple OSS Distributions 	uint64_t *accumulated_busy_time )
4221368ad365SApple OSS Distributions {
4222368ad365SApple OSS Distributions 	CHECK( IOService, _service, service );
4223368ad365SApple OSS Distributions 
4224368ad365SApple OSS Distributions 	*state                 = service->getState();
42253ca3bd55SApple OSS Distributions 	*busy_state            = service->getBusyState();
42263ca3bd55SApple OSS Distributions 	*accumulated_busy_time = service->getAccumulatedBusyTime();
4227368ad365SApple OSS Distributions 
4228a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4229368ad365SApple OSS Distributions }
4230368ad365SApple OSS Distributions 
4231c1dac77fSApple OSS Distributions /* Routine io_service_wait_quiet */
4232a5e72196SApple OSS Distributions kern_return_t
is_io_service_wait_quiet(io_object_t _service,mach_timespec_t wait_time)4233a5e72196SApple OSS Distributions is_io_service_wait_quiet(
4234c1dac77fSApple OSS Distributions 	io_object_t _service,
4235c1dac77fSApple OSS Distributions 	mach_timespec_t wait_time )
4236c1dac77fSApple OSS Distributions {
42373ca3bd55SApple OSS Distributions 	uint64_t    timeoutNS;
42383ca3bd55SApple OSS Distributions 
4239c1dac77fSApple OSS Distributions 	CHECK( IOService, _service, service );
4240c1dac77fSApple OSS Distributions 
42413ca3bd55SApple OSS Distributions 	timeoutNS = wait_time.tv_sec;
42423ca3bd55SApple OSS Distributions 	timeoutNS *= kSecondScale;
42433ca3bd55SApple OSS Distributions 	timeoutNS += wait_time.tv_nsec;
42443ca3bd55SApple OSS Distributions 
4245a5e72196SApple OSS Distributions 	return service->waitQuiet(timeoutNS);
4246c1dac77fSApple OSS Distributions }
4247c1dac77fSApple OSS Distributions 
42485c2921b0SApple OSS Distributions /* Routine io_service_wait_quiet_with_options */
42495c2921b0SApple OSS Distributions kern_return_t
is_io_service_wait_quiet_with_options(io_object_t _service,mach_timespec_t wait_time,uint32_t options)42505c2921b0SApple OSS Distributions is_io_service_wait_quiet_with_options(
42515c2921b0SApple OSS Distributions 	io_object_t _service,
42525c2921b0SApple OSS Distributions 	mach_timespec_t wait_time,
42535c2921b0SApple OSS Distributions 	uint32_t options )
42545c2921b0SApple OSS Distributions {
42555c2921b0SApple OSS Distributions 	uint64_t    timeoutNS;
42565c2921b0SApple OSS Distributions 
42575c2921b0SApple OSS Distributions 	CHECK( IOService, _service, service );
42585c2921b0SApple OSS Distributions 
42595c2921b0SApple OSS Distributions 	timeoutNS = wait_time.tv_sec;
42605c2921b0SApple OSS Distributions 	timeoutNS *= kSecondScale;
42615c2921b0SApple OSS Distributions 	timeoutNS += wait_time.tv_nsec;
42625c2921b0SApple OSS Distributions 
42635c2921b0SApple OSS Distributions 	if ((options & kIOWaitQuietPanicOnFailure) && !IOCurrentTaskHasEntitlement(kIOWaitQuietPanicsEntitlement)) {
42645c2921b0SApple OSS Distributions 		OSString * taskName = IOCopyLogNameForPID(proc_selfpid());
42655c2921b0SApple OSS Distributions 		IOLog("IOServiceWaitQuietWithOptions(%s): Not entitled\n", taskName ? taskName->getCStringNoCopy() : "");
42665c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(taskName);
42675c2921b0SApple OSS Distributions 
42685c2921b0SApple OSS Distributions 		/* strip this option from the options before calling waitQuietWithOptions */
42695c2921b0SApple OSS Distributions 		options &= ~kIOWaitQuietPanicOnFailure;
42705c2921b0SApple OSS Distributions 	}
42715c2921b0SApple OSS Distributions 
42725c2921b0SApple OSS Distributions 	return service->waitQuietWithOptions(timeoutNS, options);
42735c2921b0SApple OSS Distributions }
42745c2921b0SApple OSS Distributions 
42755c2921b0SApple OSS Distributions 
4276c1dac77fSApple OSS Distributions /* Routine io_service_request_probe */
4277a5e72196SApple OSS Distributions kern_return_t
is_io_service_request_probe(io_object_t _service,uint32_t options)4278a5e72196SApple OSS Distributions is_io_service_request_probe(
4279c1dac77fSApple OSS Distributions 	io_object_t _service,
4280e13b1fa5SApple OSS Distributions 	uint32_t options )
4281c1dac77fSApple OSS Distributions {
4282c1dac77fSApple OSS Distributions 	CHECK( IOService, _service, service );
4283c1dac77fSApple OSS Distributions 
4284a5e72196SApple OSS Distributions 	return service->requestProbe( options );
4285c1dac77fSApple OSS Distributions }
4286c1dac77fSApple OSS Distributions 
4287a3bb9fccSApple OSS Distributions /* Routine io_service_get_authorization_id */
4288a5e72196SApple OSS Distributions kern_return_t
is_io_service_get_authorization_id(io_object_t _service,uint64_t * authorization_id)4289a5e72196SApple OSS Distributions is_io_service_get_authorization_id(
4290a3bb9fccSApple OSS Distributions 	io_object_t _service,
4291a3bb9fccSApple OSS Distributions 	uint64_t *authorization_id )
4292a3bb9fccSApple OSS Distributions {
4293a3bb9fccSApple OSS Distributions 	kern_return_t          kr;
4294a3bb9fccSApple OSS Distributions 
4295a3bb9fccSApple OSS Distributions 	CHECK( IOService, _service, service );
4296a3bb9fccSApple OSS Distributions 
4297a3bb9fccSApple OSS Distributions 	kr = IOUserClient::clientHasPrivilege((void *) current_task(),
4298a3bb9fccSApple OSS Distributions 	    kIOClientPrivilegeAdministrator );
4299a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != kr) {
4300a5e72196SApple OSS Distributions 		return kr;
4301a5e72196SApple OSS Distributions 	}
4302a3bb9fccSApple OSS Distributions 
43031031c584SApple OSS Distributions #if defined(XNU_TARGET_OS_OSX)
4304a3bb9fccSApple OSS Distributions 	*authorization_id = service->getAuthorizationID();
43051031c584SApple OSS Distributions #else /* defined(XNU_TARGET_OS_OSX) */
43061031c584SApple OSS Distributions 	*authorization_id = 0;
43071031c584SApple OSS Distributions 	kr = kIOReturnUnsupported;
43081031c584SApple OSS Distributions #endif /* defined(XNU_TARGET_OS_OSX) */
4309a3bb9fccSApple OSS Distributions 
4310a5e72196SApple OSS Distributions 	return kr;
4311a3bb9fccSApple OSS Distributions }
4312a3bb9fccSApple OSS Distributions 
4313a3bb9fccSApple OSS Distributions /* Routine io_service_set_authorization_id */
4314a5e72196SApple OSS Distributions kern_return_t
is_io_service_set_authorization_id(io_object_t _service,uint64_t authorization_id)4315a5e72196SApple OSS Distributions is_io_service_set_authorization_id(
4316a3bb9fccSApple OSS Distributions 	io_object_t _service,
4317a3bb9fccSApple OSS Distributions 	uint64_t authorization_id )
4318a3bb9fccSApple OSS Distributions {
4319a3bb9fccSApple OSS Distributions 	CHECK( IOService, _service, service );
4320a3bb9fccSApple OSS Distributions 
43211031c584SApple OSS Distributions #if defined(XNU_TARGET_OS_OSX)
4322a5e72196SApple OSS Distributions 	return service->setAuthorizationID( authorization_id );
43231031c584SApple OSS Distributions #else /* defined(XNU_TARGET_OS_OSX) */
43241031c584SApple OSS Distributions 	return kIOReturnUnsupported;
43251031c584SApple OSS Distributions #endif /* defined(XNU_TARGET_OS_OSX) */
4326a3bb9fccSApple OSS Distributions }
4327a3bb9fccSApple OSS Distributions 
4328e13b1fa5SApple OSS Distributions /* Routine io_service_open_ndr */
4329a5e72196SApple OSS Distributions kern_return_t
is_io_service_open_extended(io_object_t _service,task_t owningTask,uint32_t connect_type,NDR_record_t ndr,io_buf_ptr_t properties,mach_msg_type_number_t propertiesCnt,kern_return_t * result,io_object_t * connection)4330a5e72196SApple OSS Distributions is_io_service_open_extended(
4331e13b1fa5SApple OSS Distributions 	io_object_t _service,
4332e13b1fa5SApple OSS Distributions 	task_t owningTask,
4333e13b1fa5SApple OSS Distributions 	uint32_t connect_type,
4334e13b1fa5SApple OSS Distributions 	NDR_record_t ndr,
4335e13b1fa5SApple OSS Distributions 	io_buf_ptr_t properties,
4336e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t propertiesCnt,
4337e13b1fa5SApple OSS Distributions 	kern_return_t * result,
4338e13b1fa5SApple OSS Distributions 	io_object_t *connection )
4339e13b1fa5SApple OSS Distributions {
4340a5e72196SApple OSS Distributions 	IOUserClient * client = NULL;
4341e13b1fa5SApple OSS Distributions 	kern_return_t  err = KERN_SUCCESS;
4342e13b1fa5SApple OSS Distributions 	IOReturn       res = kIOReturnSuccess;
4343a5e72196SApple OSS Distributions 	OSDictionary * propertiesDict = NULL;
43445c2921b0SApple OSS Distributions 	bool           disallowAccess = false;
4345e13b1fa5SApple OSS Distributions 
4346e13b1fa5SApple OSS Distributions 	CHECK( IOService, _service, service );
4347e13b1fa5SApple OSS Distributions 
4348a5e72196SApple OSS Distributions 	if (!owningTask) {
4349a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4350a5e72196SApple OSS Distributions 	}
435188cc0b97SApple OSS Distributions 	assert(owningTask == current_task());
4352a5e72196SApple OSS Distributions 	if (owningTask != current_task()) {
4353a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4354a5e72196SApple OSS Distributions 	}
43550f3703acSApple OSS Distributions 
4356e6231be0SApple OSS Distributions #if CONFIG_MACF
4357e6231be0SApple OSS Distributions 	if (mac_iokit_check_open_service(kauth_cred_get(), service, connect_type) != 0) {
4358e6231be0SApple OSS Distributions 		return kIOReturnNotPermitted;
4359e6231be0SApple OSS Distributions 	}
4360e6231be0SApple OSS Distributions #endif
4361a5e72196SApple OSS Distributions 	do{
4362a5e72196SApple OSS Distributions 		if (properties) {
4363a5e72196SApple OSS Distributions 			return kIOReturnUnsupported;
4364a5e72196SApple OSS Distributions 		}
436576e12aa3SApple OSS Distributions #if 0
4366e13b1fa5SApple OSS Distributions 		{
4367e13b1fa5SApple OSS Distributions 			OSObject *      obj;
4368e13b1fa5SApple OSS Distributions 			vm_offset_t     data;
4369e13b1fa5SApple OSS Distributions 			vm_map_offset_t map_data;
4370e13b1fa5SApple OSS Distributions 
4371a5e72196SApple OSS Distributions 			if (propertiesCnt > sizeof(io_struct_inband_t)) {
4372a5e72196SApple OSS Distributions 				return kIOReturnMessageTooLarge;
4373a5e72196SApple OSS Distributions 			}
4374186b8fceSApple OSS Distributions 
4375e13b1fa5SApple OSS Distributions 			err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
4376e13b1fa5SApple OSS Distributions 			res = err;
4377e13b1fa5SApple OSS Distributions 			data = CAST_DOWN(vm_offset_t, map_data);
4378a5e72196SApple OSS Distributions 			if (KERN_SUCCESS == err) {
4379e13b1fa5SApple OSS Distributions 				// must return success after vm_map_copyout() succeeds
4380186b8fceSApple OSS Distributions 				obj = OSUnserializeXML((const char *) data, propertiesCnt );
4381e13b1fa5SApple OSS Distributions 				vm_deallocate( kernel_map, data, propertiesCnt );
4382e13b1fa5SApple OSS Distributions 				propertiesDict = OSDynamicCast(OSDictionary, obj);
4383a5e72196SApple OSS Distributions 				if (!propertiesDict) {
4384e13b1fa5SApple OSS Distributions 					res = kIOReturnBadArgument;
4385a5e72196SApple OSS Distributions 					if (obj) {
4386e13b1fa5SApple OSS Distributions 						obj->release();
4387e13b1fa5SApple OSS Distributions 					}
4388e13b1fa5SApple OSS Distributions 				}
4389a5e72196SApple OSS Distributions 			}
4390a5e72196SApple OSS Distributions 			if (kIOReturnSuccess != res) {
4391e13b1fa5SApple OSS Distributions 				break;
4392e13b1fa5SApple OSS Distributions 			}
4393a5e72196SApple OSS Distributions 		}
439476e12aa3SApple OSS Distributions #endif
4395e13b1fa5SApple OSS Distributions 		res = service->newUserClient( owningTask, (void *) owningTask,
4396e13b1fa5SApple OSS Distributions 		    connect_type, propertiesDict, &client );
4397e13b1fa5SApple OSS Distributions 
4398a5e72196SApple OSS Distributions 		if (propertiesDict) {
4399e13b1fa5SApple OSS Distributions 			propertiesDict->release();
4400a5e72196SApple OSS Distributions 		}
4401e13b1fa5SApple OSS Distributions 
4402e6231be0SApple OSS Distributions 		if (res == kIOReturnSuccess && OSDynamicCast(IOUserClient, client) == NULL) {
4403e6231be0SApple OSS Distributions 			// client should always be a IOUserClient
4404e6231be0SApple OSS Distributions 			res = kIOReturnError;
4405e6231be0SApple OSS Distributions 		}
4406e6231be0SApple OSS Distributions 
4407a5e72196SApple OSS Distributions 		if (res == kIOReturnSuccess) {
4408bb611c8fSApple OSS Distributions 			if (!client->reserved) {
4409bb611c8fSApple OSS Distributions 				if (!client->reserve()) {
4410bb611c8fSApple OSS Distributions 					client->clientClose();
4411bb611c8fSApple OSS Distributions 					OSSafeReleaseNULL(client);
4412bb611c8fSApple OSS Distributions 					res = kIOReturnNoMemory;
4413bb611c8fSApple OSS Distributions 				}
4414bb611c8fSApple OSS Distributions 			}
4415bb611c8fSApple OSS Distributions 		}
4416e13b1fa5SApple OSS Distributions 
4417bb611c8fSApple OSS Distributions 		if (res == kIOReturnSuccess) {
44185c2921b0SApple OSS Distributions 			OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
44195c2921b0SApple OSS Distributions 			if (creatorName) {
44205c2921b0SApple OSS Distributions 				client->setProperty(kIOUserClientCreatorKey, creatorName);
44215c2921b0SApple OSS Distributions 			}
44225c2921b0SApple OSS Distributions 			const char * creatorNameCStr = creatorName ? creatorName->getCStringNoCopy() : "<unknown>";
4423a5e72196SApple OSS Distributions 			client->sharedInstance = (NULL != client->getProperty(kIOUserClientSharedInstanceKey));
4424bb611c8fSApple OSS Distributions 			if (client->sharedInstance) {
4425bb611c8fSApple OSS Distributions 				IOLockLock(gIOUserClientOwnersLock);
4426bb611c8fSApple OSS Distributions 			}
4427aca3beaaSApple OSS Distributions 			if (!client->opened) {
4428aca3beaaSApple OSS Distributions 				client->opened = true;
4429bb611c8fSApple OSS Distributions 
4430a5e72196SApple OSS Distributions 				client->messageAppSuspended = (NULL != client->getProperty(kIOUserClientMessageAppSuspendedKey));
4431bb611c8fSApple OSS Distributions 				{
4432bb611c8fSApple OSS Distributions 					OSObject * obj;
4433bb611c8fSApple OSS Distributions 					extern const OSSymbol * gIOSurfaceIdentifier;
4434bb611c8fSApple OSS Distributions 					obj = client->getProperty(kIOUserClientDefaultLockingKey);
44355c2921b0SApple OSS Distributions 					bool hasProps = false;
44365c2921b0SApple OSS Distributions 
44375c2921b0SApple OSS Distributions 					client->uc2022 = (NULL != OSDynamicCast(IOUserClient2022, client));
4438bb611c8fSApple OSS Distributions 					if (obj) {
44395c2921b0SApple OSS Distributions 						hasProps = true;
4440bb611c8fSApple OSS Distributions 						client->defaultLocking = (kOSBooleanFalse != client->getProperty(kIOUserClientDefaultLockingKey));
44415c2921b0SApple OSS Distributions 					} else if (client->uc2022) {
44425c2921b0SApple OSS Distributions 						res = kIOReturnError;
44435c2921b0SApple OSS Distributions 					}
44445c2921b0SApple OSS Distributions 					obj = client->getProperty(kIOUserClientDefaultLockingSetPropertiesKey);
44455c2921b0SApple OSS Distributions 					if (obj) {
44465c2921b0SApple OSS Distributions 						hasProps = true;
44475c2921b0SApple OSS Distributions 						client->defaultLockingSetProperties = (kOSBooleanFalse != client->getProperty(kIOUserClientDefaultLockingSetPropertiesKey));
44485c2921b0SApple OSS Distributions 					} else if (client->uc2022) {
44495c2921b0SApple OSS Distributions 						res = kIOReturnError;
44505c2921b0SApple OSS Distributions 					}
44515c2921b0SApple OSS Distributions 					obj = client->getProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey);
44525c2921b0SApple OSS Distributions 					if (obj) {
44535c2921b0SApple OSS Distributions 						hasProps = true;
44545c2921b0SApple OSS Distributions 						client->defaultLockingSingleThreadExternalMethod = (kOSBooleanFalse != client->getProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey));
44555c2921b0SApple OSS Distributions 					} else if (client->uc2022) {
44565c2921b0SApple OSS Distributions 						res = kIOReturnError;
44575c2921b0SApple OSS Distributions 					}
44585c2921b0SApple OSS Distributions 					if (kIOReturnSuccess != res) {
44595c2921b0SApple OSS Distributions 						IOLog("IOUC %s requires kIOUserClientDefaultLockingKey, kIOUserClientDefaultLockingSetPropertiesKey, kIOUserClientDefaultLockingSingleThreadExternalMethodKey\n",
44605c2921b0SApple OSS Distributions 						    client->getMetaClass()->getClassName());
44615c2921b0SApple OSS Distributions 					}
44625c2921b0SApple OSS Distributions 					if (!hasProps) {
4463bb611c8fSApple OSS Distributions 						const OSMetaClass * meta;
4464bb611c8fSApple OSS Distributions 						OSKext            * kext;
4465bb611c8fSApple OSS Distributions 						meta = client->getMetaClass();
4466bb611c8fSApple OSS Distributions 						kext = meta->getKext();
4467bb611c8fSApple OSS Distributions 						if (!kext || !kext->hasDependency(gIOSurfaceIdentifier)) {
4468bb611c8fSApple OSS Distributions 							client->defaultLocking = true;
44695c2921b0SApple OSS Distributions 							client->defaultLockingSetProperties = false;
44705c2921b0SApple OSS Distributions 							client->defaultLockingSingleThreadExternalMethod = false;
4471bb611c8fSApple OSS Distributions 							client->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
4472bb611c8fSApple OSS Distributions 						}
4473bb611c8fSApple OSS Distributions 					}
4474bb611c8fSApple OSS Distributions 				}
4475bb611c8fSApple OSS Distributions 			}
4476bb611c8fSApple OSS Distributions 			if (client->sharedInstance) {
4477bb611c8fSApple OSS Distributions 				IOLockUnlock(gIOUserClientOwnersLock);
4478bb611c8fSApple OSS Distributions 			}
447988cc0b97SApple OSS Distributions 
44805c2921b0SApple OSS Distributions 			OSObject     * requiredEntitlement = client->copyProperty(gIOUserClientEntitlementsKey);
44815c2921b0SApple OSS Distributions 			OSString * requiredEntitlementString = OSDynamicCast(OSString, requiredEntitlement);
44825c2921b0SApple OSS Distributions 			//If this is an IOUserClient2022, having kIOUserClientEntitlementsKey is mandatory.
44835c2921b0SApple OSS Distributions 			//If it has kIOUserClientEntitlementsKey, the value must be either kOSBooleanFalse or an OSString
44845c2921b0SApple OSS Distributions 			//If the value is kOSBooleanFalse, we allow access.
44855c2921b0SApple OSS Distributions 			//If the value is an OSString, we allow access if the task has the named entitlement
44865c2921b0SApple OSS Distributions 			if (client->uc2022) {
44875c2921b0SApple OSS Distributions 				if (!requiredEntitlement) {
44885c2921b0SApple OSS Distributions 					IOLog("IOUC %s missing " kIOUserClientEntitlementsKey " property\n",
44895c2921b0SApple OSS Distributions 					    client->getMetaClass()->getClassName());
44905c2921b0SApple OSS Distributions 					disallowAccess = true;
44915c2921b0SApple OSS Distributions 				} else if (!requiredEntitlementString && requiredEntitlement != kOSBooleanFalse) {
44925c2921b0SApple OSS Distributions 					IOLog("IOUC %s had " kIOUserClientEntitlementsKey "with value not boolean false or string\n", client->getMetaClass()->getClassName());
44935c2921b0SApple OSS Distributions 					disallowAccess = true;
44945c2921b0SApple OSS Distributions 				}
44955c2921b0SApple OSS Distributions 			}
44965c2921b0SApple OSS Distributions 
44975c2921b0SApple OSS Distributions 			if (requiredEntitlement && disallowAccess == false) {
44985c2921b0SApple OSS Distributions 				if (kOSBooleanFalse == requiredEntitlement) {
44995c2921b0SApple OSS Distributions 					// allow
45005c2921b0SApple OSS Distributions 					disallowAccess = false;
45015c2921b0SApple OSS Distributions 				} else {
45025c2921b0SApple OSS Distributions 					disallowAccess = !IOTaskHasEntitlement(owningTask, requiredEntitlementString->getCStringNoCopy());
4503a5e72196SApple OSS Distributions 					if (disallowAccess) {
45045c2921b0SApple OSS Distributions 						IOLog("IOUC %s missing entitlement in process %s\n",
45055c2921b0SApple OSS Distributions 						    client->getMetaClass()->getClassName(), creatorNameCStr);
45065c2921b0SApple OSS Distributions 					}
45075c2921b0SApple OSS Distributions 				}
45085c2921b0SApple OSS Distributions 			}
45095c2921b0SApple OSS Distributions 
45105c2921b0SApple OSS Distributions 			OSSafeReleaseNULL(requiredEntitlement);
45115c2921b0SApple OSS Distributions 
45125c2921b0SApple OSS Distributions 			if (disallowAccess) {
45135c2921b0SApple OSS Distributions 				res = kIOReturnNotPrivileged;
4514a5e72196SApple OSS Distributions 			}
4515855239e5SApple OSS Distributions #if CONFIG_MACF
4516a5e72196SApple OSS Distributions 			else if (0 != mac_iokit_check_open(kauth_cred_get(), client, connect_type)) {
45175c2921b0SApple OSS Distributions 				IOLog("IOUC %s failed MACF in process %s\n",
45185c2921b0SApple OSS Distributions 				    client->getMetaClass()->getClassName(), creatorNameCStr);
4519855239e5SApple OSS Distributions 				res = kIOReturnNotPermitted;
4520a5e72196SApple OSS Distributions 			}
4521855239e5SApple OSS Distributions #endif
452288cc0b97SApple OSS Distributions 
4523bb611c8fSApple OSS Distributions 			if ((kIOReturnSuccess == res)
4524bb611c8fSApple OSS Distributions 			    && gIOUCFilterCallbacks
4525bb611c8fSApple OSS Distributions 			    && gIOUCFilterCallbacks->io_filter_resolver) {
4526bb611c8fSApple OSS Distributions 				io_filter_policy_t filterPolicy;
4527bb611c8fSApple OSS Distributions 				filterPolicy = client->filterForTask(owningTask, 0);
4528bb611c8fSApple OSS Distributions 				if (!filterPolicy) {
4529bb611c8fSApple OSS Distributions 					res = gIOUCFilterCallbacks->io_filter_resolver(owningTask, client, connect_type, &filterPolicy);
4530bb611c8fSApple OSS Distributions 					if (kIOReturnUnsupported == res) {
4531bb611c8fSApple OSS Distributions 						res = kIOReturnSuccess;
4532bb611c8fSApple OSS Distributions 					} else if (kIOReturnSuccess == res) {
4533bb611c8fSApple OSS Distributions 						client->filterForTask(owningTask, filterPolicy);
45345c2921b0SApple OSS Distributions 					} else {
45355c2921b0SApple OSS Distributions 						IOLog("IOUC %s failed sandbox in process %s\n",
45365c2921b0SApple OSS Distributions 						    client->getMetaClass()->getClassName(), creatorNameCStr);
4537bb611c8fSApple OSS Distributions 					}
4538bb611c8fSApple OSS Distributions 				}
4539bb611c8fSApple OSS Distributions 			}
4540bb611c8fSApple OSS Distributions 
4541a5e72196SApple OSS Distributions 			if (kIOReturnSuccess == res) {
4542a5e72196SApple OSS Distributions 				res = client->registerOwner(owningTask);
4543a5e72196SApple OSS Distributions 			}
45445c2921b0SApple OSS Distributions 			OSSafeReleaseNULL(creatorName);
454588cc0b97SApple OSS Distributions 
4546a5e72196SApple OSS Distributions 			if (kIOReturnSuccess != res) {
4547855239e5SApple OSS Distributions 				IOStatisticsClientCall();
4548e13b1fa5SApple OSS Distributions 				client->clientClose();
45495c2921b0SApple OSS Distributions 				client->setTerminateDefer(service, false);
4550e13b1fa5SApple OSS Distributions 				client->release();
4551a5e72196SApple OSS Distributions 				client = NULL;
4552e13b1fa5SApple OSS Distributions 				break;
4553e13b1fa5SApple OSS Distributions 			}
4554186b8fceSApple OSS Distributions 			client->setTerminateDefer(service, false);
4555e13b1fa5SApple OSS Distributions 		}
4556a5e72196SApple OSS Distributions 	}while (false);
4557e13b1fa5SApple OSS Distributions 
4558e13b1fa5SApple OSS Distributions 	*connection = client;
4559e13b1fa5SApple OSS Distributions 	*result = res;
4560e13b1fa5SApple OSS Distributions 
4561a5e72196SApple OSS Distributions 	return err;
4562e13b1fa5SApple OSS Distributions }
4563e13b1fa5SApple OSS Distributions 
4564c1dac77fSApple OSS Distributions /* Routine io_service_close */
4565a5e72196SApple OSS Distributions kern_return_t
is_io_service_close(io_connect_t connection)4566a5e72196SApple OSS Distributions is_io_service_close(
456794d3b452SApple OSS Distributions 	io_connect_t connection )
4568c1dac77fSApple OSS Distributions {
4569368ad365SApple OSS Distributions 	OSSet * mappings;
4570a5e72196SApple OSS Distributions 	if ((mappings = OSDynamicCast(OSSet, connection))) {
4571a5e72196SApple OSS Distributions 		return kIOReturnSuccess;
4572a5e72196SApple OSS Distributions 	}
4573368ad365SApple OSS Distributions 
4574c1dac77fSApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4575c1dac77fSApple OSS Distributions 
4576855239e5SApple OSS Distributions 	IOStatisticsClientCall();
457788cc0b97SApple OSS Distributions 
4578a5e72196SApple OSS Distributions 	if (client->sharedInstance || OSCompareAndSwap8(0, 1, &client->closed)) {
457994d3b452SApple OSS Distributions 		client->ipcEnter(kIPCLockWrite);
4580c1dac77fSApple OSS Distributions 		client->clientClose();
458194d3b452SApple OSS Distributions 		client->ipcExit(kIPCLockWrite);
4582a5e72196SApple OSS Distributions 	} else {
458388cc0b97SApple OSS Distributions 		IOLog("ignored is_io_service_close(0x%qx,%s)\n",
458488cc0b97SApple OSS Distributions 		    client->getRegistryEntryID(), client->getName());
458588cc0b97SApple OSS Distributions 	}
4586c1dac77fSApple OSS Distributions 
4587a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
4588c1dac77fSApple OSS Distributions }
4589c1dac77fSApple OSS Distributions 
4590c1dac77fSApple OSS Distributions /* Routine io_connect_get_service */
4591a5e72196SApple OSS Distributions kern_return_t
is_io_connect_get_service(io_connect_t connection,io_object_t * service)4592a5e72196SApple OSS Distributions is_io_connect_get_service(
459394d3b452SApple OSS Distributions 	io_connect_t connection,
4594c1dac77fSApple OSS Distributions 	io_object_t *service )
4595c1dac77fSApple OSS Distributions {
4596c1dac77fSApple OSS Distributions 	IOService * theService;
4597c1dac77fSApple OSS Distributions 
4598c1dac77fSApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4599c1dac77fSApple OSS Distributions 
460094d3b452SApple OSS Distributions 	client->ipcEnter(kIPCLockNone);
460194d3b452SApple OSS Distributions 
4602c1dac77fSApple OSS Distributions 	theService = client->getService();
4603a5e72196SApple OSS Distributions 	if (theService) {
4604c1dac77fSApple OSS Distributions 		theService->retain();
4605a5e72196SApple OSS Distributions 	}
4606c1dac77fSApple OSS Distributions 
460794d3b452SApple OSS Distributions 	client->ipcExit(kIPCLockNone);
460894d3b452SApple OSS Distributions 
4609c1dac77fSApple OSS Distributions 	*service = theService;
4610c1dac77fSApple OSS Distributions 
4611a5e72196SApple OSS Distributions 	return theService ? kIOReturnSuccess : kIOReturnUnsupported;
4612c1dac77fSApple OSS Distributions }
4613c1dac77fSApple OSS Distributions 
4614c1dac77fSApple OSS Distributions /* Routine io_connect_set_notification_port */
4615a5e72196SApple OSS Distributions kern_return_t
is_io_connect_set_notification_port(io_connect_t connection,uint32_t notification_type,mach_port_t port,uint32_t reference)4616a5e72196SApple OSS Distributions is_io_connect_set_notification_port(
461794d3b452SApple OSS Distributions 	io_connect_t connection,
4618e13b1fa5SApple OSS Distributions 	uint32_t notification_type,
4619c1dac77fSApple OSS Distributions 	mach_port_t port,
4620e13b1fa5SApple OSS Distributions 	uint32_t reference)
4621c1dac77fSApple OSS Distributions {
4622cc9a6355SApple OSS Distributions 	kern_return_t ret;
4623c1dac77fSApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4624c1dac77fSApple OSS Distributions 
4625855239e5SApple OSS Distributions 	IOStatisticsClientCall();
462694d3b452SApple OSS Distributions 
462794d3b452SApple OSS Distributions 	client->ipcEnter(kIPCLockWrite);
4628cc9a6355SApple OSS Distributions 	ret = client->registerNotificationPort( port, notification_type,
4629cc9a6355SApple OSS Distributions 	    (io_user_reference_t) reference );
463094d3b452SApple OSS Distributions 	client->ipcExit(kIPCLockWrite);
463194d3b452SApple OSS Distributions 
4632a5e72196SApple OSS Distributions 	return ret;
4633c1dac77fSApple OSS Distributions }
4634c1dac77fSApple OSS Distributions 
4635e13b1fa5SApple OSS Distributions /* Routine io_connect_set_notification_port */
4636a5e72196SApple OSS Distributions kern_return_t
is_io_connect_set_notification_port_64(io_connect_t connection,uint32_t notification_type,mach_port_t port,io_user_reference_t reference)4637a5e72196SApple OSS Distributions is_io_connect_set_notification_port_64(
463894d3b452SApple OSS Distributions 	io_connect_t connection,
4639e13b1fa5SApple OSS Distributions 	uint32_t notification_type,
4640e13b1fa5SApple OSS Distributions 	mach_port_t port,
4641e13b1fa5SApple OSS Distributions 	io_user_reference_t reference)
4642e13b1fa5SApple OSS Distributions {
4643cc9a6355SApple OSS Distributions 	kern_return_t ret;
4644e13b1fa5SApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4645e13b1fa5SApple OSS Distributions 
4646855239e5SApple OSS Distributions 	IOStatisticsClientCall();
464794d3b452SApple OSS Distributions 
464894d3b452SApple OSS Distributions 	client->ipcEnter(kIPCLockWrite);
4649cc9a6355SApple OSS Distributions 	ret = client->registerNotificationPort( port, notification_type,
4650cc9a6355SApple OSS Distributions 	    reference );
465194d3b452SApple OSS Distributions 	client->ipcExit(kIPCLockWrite);
465294d3b452SApple OSS Distributions 
4653a5e72196SApple OSS Distributions 	return ret;
4654e13b1fa5SApple OSS Distributions }
4655e13b1fa5SApple OSS Distributions 
4656e13b1fa5SApple OSS Distributions /* Routine io_connect_map_memory_into_task */
4657a5e72196SApple OSS Distributions kern_return_t
is_io_connect_map_memory_into_task(io_connect_t connection,uint32_t memory_type,task_t into_task,mach_vm_address_t * address,mach_vm_size_t * size,uint32_t flags)4658a5e72196SApple OSS Distributions is_io_connect_map_memory_into_task
4659e13b1fa5SApple OSS Distributions (
4660e13b1fa5SApple OSS Distributions 	io_connect_t connection,
4661e13b1fa5SApple OSS Distributions 	uint32_t memory_type,
4662e13b1fa5SApple OSS Distributions 	task_t into_task,
4663e13b1fa5SApple OSS Distributions 	mach_vm_address_t *address,
4664e13b1fa5SApple OSS Distributions 	mach_vm_size_t *size,
4665e13b1fa5SApple OSS Distributions 	uint32_t flags
4666e13b1fa5SApple OSS Distributions )
4667c1dac77fSApple OSS Distributions {
4668c1dac77fSApple OSS Distributions 	IOReturn            err;
4669c1dac77fSApple OSS Distributions 	IOMemoryMap *       map;
4670c1dac77fSApple OSS Distributions 
4671e13b1fa5SApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4672c1dac77fSApple OSS Distributions 
4673a5e72196SApple OSS Distributions 	if (!into_task) {
4674a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4675a5e72196SApple OSS Distributions 	}
46760f3703acSApple OSS Distributions 
4677855239e5SApple OSS Distributions 	IOStatisticsClientCall();
467894d3b452SApple OSS Distributions 
467994d3b452SApple OSS Distributions 	client->ipcEnter(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
4680e13b1fa5SApple OSS Distributions 	map = client->mapClientMemory64( memory_type, into_task, flags, *address );
4681c1dac77fSApple OSS Distributions 
4682c1dac77fSApple OSS Distributions 	if (map) {
4683e13b1fa5SApple OSS Distributions 		*address = map->getAddress();
4684a5e72196SApple OSS Distributions 		if (size) {
4685e13b1fa5SApple OSS Distributions 			*size = map->getSize();
4686a5e72196SApple OSS Distributions 		}
4687c1dac77fSApple OSS Distributions 
4688e13b1fa5SApple OSS Distributions 		if (client->sharedInstance
4689e13b1fa5SApple OSS Distributions 		    || (into_task != current_task())) {
4690c1dac77fSApple OSS Distributions 			// push a name out to the task owning the map,
4691c1dac77fSApple OSS Distributions 			// so we can clean up maps
4692e13b1fa5SApple OSS Distributions 			mach_port_name_t name __unused =
4693368ad365SApple OSS Distributions 			    IOMachPort::makeSendRightForTask(
4694e13b1fa5SApple OSS Distributions 				into_task, map, IKOT_IOKIT_OBJECT );
4695cc9a6355SApple OSS Distributions 			map->release();
4696c1dac77fSApple OSS Distributions 		} else {
4697c1dac77fSApple OSS Distributions 			// keep it with the user client
4698c1dac77fSApple OSS Distributions 			IOLockLock( gIOObjectPortLock);
4699a5e72196SApple OSS Distributions 			if (NULL == client->mappings) {
4700c1dac77fSApple OSS Distributions 				client->mappings = OSSet::withCapacity(2);
4701a5e72196SApple OSS Distributions 			}
4702a5e72196SApple OSS Distributions 			if (client->mappings) {
4703c1dac77fSApple OSS Distributions 				client->mappings->setObject( map);
4704a5e72196SApple OSS Distributions 			}
4705c1dac77fSApple OSS Distributions 			IOLockUnlock( gIOObjectPortLock);
4706c1dac77fSApple OSS Distributions 			map->release();
4707c1dac77fSApple OSS Distributions 		}
4708c1dac77fSApple OSS Distributions 		err = kIOReturnSuccess;
4709a5e72196SApple OSS Distributions 	} else {
4710c1dac77fSApple OSS Distributions 		err = kIOReturnBadArgument;
4711a5e72196SApple OSS Distributions 	}
4712c1dac77fSApple OSS Distributions 
471394d3b452SApple OSS Distributions 	client->ipcExit(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
471494d3b452SApple OSS Distributions 
4715a5e72196SApple OSS Distributions 	return err;
4716c1dac77fSApple OSS Distributions }
4717c1dac77fSApple OSS Distributions 
4718e13b1fa5SApple OSS Distributions /* Routine is_io_connect_map_memory */
4719a5e72196SApple OSS Distributions kern_return_t
is_io_connect_map_memory(io_object_t connect,uint32_t type,task_t task,uint32_t * mapAddr,uint32_t * mapSize,uint32_t flags)4720a5e72196SApple OSS Distributions is_io_connect_map_memory(
4721e13b1fa5SApple OSS Distributions 	io_object_t     connect,
4722e13b1fa5SApple OSS Distributions 	uint32_t        type,
4723e13b1fa5SApple OSS Distributions 	task_t          task,
4724a3bb9fccSApple OSS Distributions 	uint32_t  *     mapAddr,
4725a3bb9fccSApple OSS Distributions 	uint32_t  *     mapSize,
4726e13b1fa5SApple OSS Distributions 	uint32_t        flags )
4727e13b1fa5SApple OSS Distributions {
4728e13b1fa5SApple OSS Distributions 	IOReturn          err;
4729e13b1fa5SApple OSS Distributions 	mach_vm_address_t address;
4730e13b1fa5SApple OSS Distributions 	mach_vm_size_t    size;
4731e13b1fa5SApple OSS Distributions 
4732e13b1fa5SApple OSS Distributions 	address = SCALAR64(*mapAddr);
4733e13b1fa5SApple OSS Distributions 	size    = SCALAR64(*mapSize);
4734e13b1fa5SApple OSS Distributions 
4735e13b1fa5SApple OSS Distributions 	err = is_io_connect_map_memory_into_task(connect, type, task, &address, &size, flags);
4736e13b1fa5SApple OSS Distributions 
4737e13b1fa5SApple OSS Distributions 	*mapAddr = SCALAR32(address);
4738e13b1fa5SApple OSS Distributions 	*mapSize = SCALAR32(size);
4739e13b1fa5SApple OSS Distributions 
4740a5e72196SApple OSS Distributions 	return err;
4741e13b1fa5SApple OSS Distributions }
4742855239e5SApple OSS Distributions } /* extern "C" */
4743855239e5SApple OSS Distributions 
4744a5e72196SApple OSS Distributions IOMemoryMap *
removeMappingForDescriptor(IOMemoryDescriptor * mem)4745a5e72196SApple OSS Distributions IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor * mem)
474614e3d835SApple OSS Distributions {
474714e3d835SApple OSS Distributions 	OSIterator *  iter;
4748a5e72196SApple OSS Distributions 	IOMemoryMap * map = NULL;
474914e3d835SApple OSS Distributions 
475014e3d835SApple OSS Distributions 	IOLockLock(gIOObjectPortLock);
475114e3d835SApple OSS Distributions 
475214e3d835SApple OSS Distributions 	iter = OSCollectionIterator::withCollection(mappings);
4753a5e72196SApple OSS Distributions 	if (iter) {
4754a5e72196SApple OSS Distributions 		while ((map = OSDynamicCast(IOMemoryMap, iter->getNextObject()))) {
4755a5e72196SApple OSS Distributions 			if (mem == map->getMemoryDescriptor()) {
475614e3d835SApple OSS Distributions 				map->retain();
475714e3d835SApple OSS Distributions 				mappings->removeObject(map);
475814e3d835SApple OSS Distributions 				break;
475914e3d835SApple OSS Distributions 			}
476014e3d835SApple OSS Distributions 		}
476114e3d835SApple OSS Distributions 		iter->release();
476214e3d835SApple OSS Distributions 	}
476314e3d835SApple OSS Distributions 
476414e3d835SApple OSS Distributions 	IOLockUnlock(gIOObjectPortLock);
476514e3d835SApple OSS Distributions 
4766a5e72196SApple OSS Distributions 	return map;
476714e3d835SApple OSS Distributions }
476814e3d835SApple OSS Distributions 
4769855239e5SApple OSS Distributions extern "C" {
4770e13b1fa5SApple OSS Distributions /* Routine io_connect_unmap_memory_from_task */
4771a5e72196SApple OSS Distributions kern_return_t
is_io_connect_unmap_memory_from_task(io_connect_t connection,uint32_t memory_type,task_t from_task,mach_vm_address_t address)4772a5e72196SApple OSS Distributions is_io_connect_unmap_memory_from_task
4773e13b1fa5SApple OSS Distributions (
4774e13b1fa5SApple OSS Distributions 	io_connect_t connection,
4775e13b1fa5SApple OSS Distributions 	uint32_t memory_type,
4776e13b1fa5SApple OSS Distributions 	task_t from_task,
4777e13b1fa5SApple OSS Distributions 	mach_vm_address_t address)
4778c1dac77fSApple OSS Distributions {
4779c1dac77fSApple OSS Distributions 	IOReturn            err;
4780c1dac77fSApple OSS Distributions 	IOOptionBits        options = 0;
4781a5e72196SApple OSS Distributions 	IOMemoryDescriptor * memory = NULL;
4782c1dac77fSApple OSS Distributions 	IOMemoryMap *       map;
4783c1dac77fSApple OSS Distributions 
4784e13b1fa5SApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4785c1dac77fSApple OSS Distributions 
4786a5e72196SApple OSS Distributions 	if (!from_task) {
4787a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
4788a5e72196SApple OSS Distributions 	}
47890f3703acSApple OSS Distributions 
4790855239e5SApple OSS Distributions 	IOStatisticsClientCall();
479194d3b452SApple OSS Distributions 
479294d3b452SApple OSS Distributions 	client->ipcEnter(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
4793e13b1fa5SApple OSS Distributions 	err = client->clientMemoryForType((UInt32) memory_type, &options, &memory );
4794c1dac77fSApple OSS Distributions 
4795c1dac77fSApple OSS Distributions 	if (memory && (kIOReturnSuccess == err)) {
4796c1dac77fSApple OSS Distributions 		options = (options & ~kIOMapUserOptionsMask)
4797c1dac77fSApple OSS Distributions 		    | kIOMapAnywhere | kIOMapReference;
4798c1dac77fSApple OSS Distributions 
4799e13b1fa5SApple OSS Distributions 		map = memory->createMappingInTask( from_task, address, options );
4800c1dac77fSApple OSS Distributions 		memory->release();
4801a5e72196SApple OSS Distributions 		if (map) {
4802c1dac77fSApple OSS Distributions 			IOLockLock( gIOObjectPortLock);
4803a5e72196SApple OSS Distributions 			if (client->mappings) {
4804c1dac77fSApple OSS Distributions 				client->mappings->removeObject( map);
4805a5e72196SApple OSS Distributions 			}
4806c1dac77fSApple OSS Distributions 			IOLockUnlock( gIOObjectPortLock);
480714e3d835SApple OSS Distributions 
480814e3d835SApple OSS Distributions 			mach_port_name_t name = 0;
4809bb611c8fSApple OSS Distributions 			bool is_shared_instance_or_from_current_task = from_task != current_task() || client->sharedInstance;
4810bb611c8fSApple OSS Distributions 			if (is_shared_instance_or_from_current_task) {
4811e13b1fa5SApple OSS Distributions 				name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT );
4812cc9a6355SApple OSS Distributions 				map->release();
4813cc9a6355SApple OSS Distributions 			}
4814cc9a6355SApple OSS Distributions 
4815a5e72196SApple OSS Distributions 			if (name) {
48163ca3bd55SApple OSS Distributions 				map->userClientUnmap();
4817e13b1fa5SApple OSS Distributions 				err = iokit_mod_send_right( from_task, name, -2 );
481814e3d835SApple OSS Distributions 				err = kIOReturnSuccess;
4819a5e72196SApple OSS Distributions 			} else {
48208149afccSApple OSS Distributions 				IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
4821a5e72196SApple OSS Distributions 			}
4822bb611c8fSApple OSS Distributions 			if (!is_shared_instance_or_from_current_task) {
4823c1dac77fSApple OSS Distributions 				map->release();
482414e3d835SApple OSS Distributions 			}
4825a5e72196SApple OSS Distributions 		} else {
4826c1dac77fSApple OSS Distributions 			err = kIOReturnBadArgument;
4827c1dac77fSApple OSS Distributions 		}
4828c1dac77fSApple OSS Distributions 	}
4829c1dac77fSApple OSS Distributions 
483094d3b452SApple OSS Distributions 	client->ipcExit(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
483194d3b452SApple OSS Distributions 
4832a5e72196SApple OSS Distributions 	return err;
4833a5e72196SApple OSS Distributions }
4834a5e72196SApple OSS Distributions 
4835a5e72196SApple OSS Distributions kern_return_t
is_io_connect_unmap_memory(io_object_t connect,uint32_t type,task_t task,uint32_t mapAddr)4836a5e72196SApple OSS Distributions is_io_connect_unmap_memory(
4837e13b1fa5SApple OSS Distributions 	io_object_t     connect,
4838e13b1fa5SApple OSS Distributions 	uint32_t        type,
4839e13b1fa5SApple OSS Distributions 	task_t          task,
4840a3bb9fccSApple OSS Distributions 	uint32_t        mapAddr )
4841e13b1fa5SApple OSS Distributions {
4842e13b1fa5SApple OSS Distributions 	IOReturn            err;
4843e13b1fa5SApple OSS Distributions 	mach_vm_address_t   address;
4844e13b1fa5SApple OSS Distributions 
4845e13b1fa5SApple OSS Distributions 	address = SCALAR64(mapAddr);
4846e13b1fa5SApple OSS Distributions 
4847e13b1fa5SApple OSS Distributions 	err = is_io_connect_unmap_memory_from_task(connect, type, task, mapAddr);
4848e13b1fa5SApple OSS Distributions 
4849a5e72196SApple OSS Distributions 	return err;
4850e13b1fa5SApple OSS Distributions }
4851e13b1fa5SApple OSS Distributions 
4852c1dac77fSApple OSS Distributions 
4853c1dac77fSApple OSS Distributions /* Routine io_connect_add_client */
4854a5e72196SApple OSS Distributions kern_return_t
is_io_connect_add_client(io_connect_t connection,io_object_t connect_to)4855a5e72196SApple OSS Distributions is_io_connect_add_client(
485694d3b452SApple OSS Distributions 	io_connect_t connection,
4857c1dac77fSApple OSS Distributions 	io_object_t connect_to)
4858c1dac77fSApple OSS Distributions {
4859c1dac77fSApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4860c1dac77fSApple OSS Distributions 	CHECK( IOUserClient, connect_to, to );
4861c1dac77fSApple OSS Distributions 
4862bb611c8fSApple OSS Distributions 	IOReturn ret;
4863bb611c8fSApple OSS Distributions 
4864855239e5SApple OSS Distributions 	IOStatisticsClientCall();
486594d3b452SApple OSS Distributions 
486694d3b452SApple OSS Distributions 	client->ipcEnter(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
4867bb611c8fSApple OSS Distributions 	ret = client->connectClient( to );
486894d3b452SApple OSS Distributions 	client->ipcExit(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
486994d3b452SApple OSS Distributions 
4870bb611c8fSApple OSS Distributions 	return ret;
4871c1dac77fSApple OSS Distributions }
4872c1dac77fSApple OSS Distributions 
4873c1dac77fSApple OSS Distributions 
4874c1dac77fSApple OSS Distributions /* Routine io_connect_set_properties */
4875a5e72196SApple OSS Distributions kern_return_t
is_io_connect_set_properties(io_connect_t connection,io_buf_ptr_t properties,mach_msg_type_number_t propertiesCnt,kern_return_t * result)4876a5e72196SApple OSS Distributions is_io_connect_set_properties(
487794d3b452SApple OSS Distributions 	io_connect_t connection,
4878c1dac77fSApple OSS Distributions 	io_buf_ptr_t properties,
4879c1dac77fSApple OSS Distributions 	mach_msg_type_number_t propertiesCnt,
4880e13b1fa5SApple OSS Distributions 	kern_return_t * result)
4881c1dac77fSApple OSS Distributions {
4882a5e72196SApple OSS Distributions 	return is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result );
4883c1dac77fSApple OSS Distributions }
4884c1dac77fSApple OSS Distributions 
4885d0c1fef6SApple OSS Distributions /* Routine io_user_client_method */
4886a5e72196SApple OSS Distributions kern_return_t
is_io_connect_method_var_output(io_connect_t connection,uint32_t selector,io_scalar_inband64_t scalar_input,mach_msg_type_number_t scalar_inputCnt,io_struct_inband_t inband_input,mach_msg_type_number_t inband_inputCnt,mach_vm_address_t ool_input,mach_vm_size_t ool_input_size,io_struct_inband_t inband_output,mach_msg_type_number_t * inband_outputCnt,io_scalar_inband64_t scalar_output,mach_msg_type_number_t * scalar_outputCnt,io_buf_ptr_t * var_output,mach_msg_type_number_t * var_outputCnt)4887a5e72196SApple OSS Distributions is_io_connect_method_var_output
4888d0c1fef6SApple OSS Distributions (
4889d0c1fef6SApple OSS Distributions 	io_connect_t connection,
4890d0c1fef6SApple OSS Distributions 	uint32_t selector,
4891d0c1fef6SApple OSS Distributions 	io_scalar_inband64_t scalar_input,
4892d0c1fef6SApple OSS Distributions 	mach_msg_type_number_t scalar_inputCnt,
4893d0c1fef6SApple OSS Distributions 	io_struct_inband_t inband_input,
4894d0c1fef6SApple OSS Distributions 	mach_msg_type_number_t inband_inputCnt,
4895d0c1fef6SApple OSS Distributions 	mach_vm_address_t ool_input,
4896d0c1fef6SApple OSS Distributions 	mach_vm_size_t ool_input_size,
4897d0c1fef6SApple OSS Distributions 	io_struct_inband_t inband_output,
4898d0c1fef6SApple OSS Distributions 	mach_msg_type_number_t *inband_outputCnt,
4899d0c1fef6SApple OSS Distributions 	io_scalar_inband64_t scalar_output,
4900d0c1fef6SApple OSS Distributions 	mach_msg_type_number_t *scalar_outputCnt,
4901d0c1fef6SApple OSS Distributions 	io_buf_ptr_t *var_output,
4902d0c1fef6SApple OSS Distributions 	mach_msg_type_number_t *var_outputCnt
4903d0c1fef6SApple OSS Distributions )
4904d0c1fef6SApple OSS Distributions {
4905d0c1fef6SApple OSS Distributions 	CHECK( IOUserClient, connection, client );
4906d0c1fef6SApple OSS Distributions 
4907d0c1fef6SApple OSS Distributions 	IOExternalMethodArguments args;
4908d0c1fef6SApple OSS Distributions 	IOReturn ret;
4909a5e72196SApple OSS Distributions 	IOMemoryDescriptor * inputMD  = NULL;
4910a5e72196SApple OSS Distributions 	OSObject *           structureVariableOutputData = NULL;
4911d0c1fef6SApple OSS Distributions 
4912d0c1fef6SApple OSS Distributions 	bzero(&args.__reserved[0], sizeof(args.__reserved));
491388cc0b97SApple OSS Distributions 	args.__reservedA = 0;
4914d0c1fef6SApple OSS Distributions 	args.version = kIOExternalMethodArgumentsCurrentVersion;
4915d0c1fef6SApple OSS Distributions 
4916d0c1fef6SApple OSS Distributions 	args.selector = selector;
4917d0c1fef6SApple OSS Distributions 
4918d0c1fef6SApple OSS Distributions 	args.asyncWakePort               = MACH_PORT_NULL;
4919a5e72196SApple OSS Distributions 	args.asyncReference              = NULL;
4920d0c1fef6SApple OSS Distributions 	args.asyncReferenceCount         = 0;
4921d0c1fef6SApple OSS Distributions 	args.structureVariableOutputData = &structureVariableOutputData;
4922d0c1fef6SApple OSS Distributions 
4923d0c1fef6SApple OSS Distributions 	args.scalarInput = scalar_input;
4924d0c1fef6SApple OSS Distributions 	args.scalarInputCount = scalar_inputCnt;
4925d0c1fef6SApple OSS Distributions 	args.structureInput = inband_input;
4926d0c1fef6SApple OSS Distributions 	args.structureInputSize = inband_inputCnt;
4927d0c1fef6SApple OSS Distributions 
4928a5e72196SApple OSS Distributions 	if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) {
4929a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
4930a5e72196SApple OSS Distributions 	}
493176e12aa3SApple OSS Distributions 
4932a5e72196SApple OSS Distributions 	if (ool_input) {
4933d0c1fef6SApple OSS Distributions 		inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
493476e12aa3SApple OSS Distributions 		    kIODirectionOut | kIOMemoryMapCopyOnWrite,
493576e12aa3SApple OSS Distributions 		    current_task());
4936a5e72196SApple OSS Distributions 	}
4937d0c1fef6SApple OSS Distributions 
4938d0c1fef6SApple OSS Distributions 	args.structureInputDescriptor = inputMD;
4939d0c1fef6SApple OSS Distributions 
4940d0c1fef6SApple OSS Distributions 	args.scalarOutput = scalar_output;
4941d0c1fef6SApple OSS Distributions 	args.scalarOutputCount = *scalar_outputCnt;
4942a3bb9fccSApple OSS Distributions 	bzero(&scalar_output[0], *scalar_outputCnt * sizeof(scalar_output[0]));
4943d0c1fef6SApple OSS Distributions 	args.structureOutput = inband_output;
4944d0c1fef6SApple OSS Distributions 	args.structureOutputSize = *inband_outputCnt;
4945d0c1fef6SApple OSS Distributions 	args.structureOutputDescriptor = NULL;
4946d0c1fef6SApple OSS Distributions 	args.structureOutputDescriptorSize = 0;
4947d0c1fef6SApple OSS Distributions 
4948d0c1fef6SApple OSS Distributions 	IOStatisticsClientCall();
4949bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
4950bb611c8fSApple OSS Distributions 
4951bb611c8fSApple OSS Distributions 	io_filter_policy_t filterPolicy = client->filterForTask(current_task(), 0);
4952bb611c8fSApple OSS Distributions 	if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
4953e6231be0SApple OSS Distributions 		ret = gIOUCFilterCallbacks->io_filter_applier(client, filterPolicy, io_filter_type_external_method, selector);
4954bb611c8fSApple OSS Distributions 	}
49555c2921b0SApple OSS Distributions 
4956bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess == ret) {
49575c2921b0SApple OSS Distributions 		ret = client->callExternalMethod(selector, &args);
4958bb611c8fSApple OSS Distributions 	}
4959d0c1fef6SApple OSS Distributions 
4960d0c1fef6SApple OSS Distributions 	*scalar_outputCnt = args.scalarOutputCount;
4961d0c1fef6SApple OSS Distributions 	*inband_outputCnt = args.structureOutputSize;
4962d0c1fef6SApple OSS Distributions 
4963a5e72196SApple OSS Distributions 	if (var_outputCnt && var_output && (kIOReturnSuccess == ret)) {
4964d0c1fef6SApple OSS Distributions 		OSSerialize * serialize;
4965d0c1fef6SApple OSS Distributions 		OSData      * data;
4966bb611c8fSApple OSS Distributions 		unsigned int  len;
4967d0c1fef6SApple OSS Distributions 
4968a5e72196SApple OSS Distributions 		if ((serialize = OSDynamicCast(OSSerialize, structureVariableOutputData))) {
4969d0c1fef6SApple OSS Distributions 			len = serialize->getLength();
4970d0c1fef6SApple OSS Distributions 			*var_outputCnt = len;
4971d0c1fef6SApple OSS Distributions 			ret = copyoutkdata(serialize->text(), len, var_output);
4972a5e72196SApple OSS Distributions 		} else if ((data = OSDynamicCast(OSData, structureVariableOutputData))) {
49735c2921b0SApple OSS Distributions 			data->clipForCopyout();
4974d0c1fef6SApple OSS Distributions 			len = data->getLength();
4975d0c1fef6SApple OSS Distributions 			*var_outputCnt = len;
4976d0c1fef6SApple OSS Distributions 			ret = copyoutkdata(data->getBytesNoCopy(), len, var_output);
4977a5e72196SApple OSS Distributions 		} else {
4978d0c1fef6SApple OSS Distributions 			ret = kIOReturnUnderrun;
4979d0c1fef6SApple OSS Distributions 		}
4980d0c1fef6SApple OSS Distributions 	}
4981d0c1fef6SApple OSS Distributions 
4982a5e72196SApple OSS Distributions 	if (inputMD) {
4983d0c1fef6SApple OSS Distributions 		inputMD->release();
4984a5e72196SApple OSS Distributions 	}
4985a5e72196SApple OSS Distributions 	if (structureVariableOutputData) {
4986d0c1fef6SApple OSS Distributions 		structureVariableOutputData->release();
4987a5e72196SApple OSS Distributions 	}
4988d0c1fef6SApple OSS Distributions 
4989a5e72196SApple OSS Distributions 	return ret;
4990d0c1fef6SApple OSS Distributions }
4991c1dac77fSApple OSS Distributions 
4992e13b1fa5SApple OSS Distributions /* Routine io_user_client_method */
4993a5e72196SApple OSS Distributions kern_return_t
is_io_connect_method(io_connect_t connection,uint32_t selector,io_scalar_inband64_t scalar_input,mach_msg_type_number_t scalar_inputCnt,io_struct_inband_t inband_input,mach_msg_type_number_t inband_inputCnt,mach_vm_address_t ool_input,mach_vm_size_t ool_input_size,io_struct_inband_t inband_output,mach_msg_type_number_t * inband_outputCnt,io_scalar_inband64_t scalar_output,mach_msg_type_number_t * scalar_outputCnt,mach_vm_address_t ool_output,mach_vm_size_t * ool_output_size)4994a5e72196SApple OSS Distributions is_io_connect_method
4995e13b1fa5SApple OSS Distributions (
4996e13b1fa5SApple OSS Distributions 	io_connect_t connection,
4997e13b1fa5SApple OSS Distributions 	uint32_t selector,
4998e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t scalar_input,
4999e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_inputCnt,
5000e13b1fa5SApple OSS Distributions 	io_struct_inband_t inband_input,
5001e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t inband_inputCnt,
5002e13b1fa5SApple OSS Distributions 	mach_vm_address_t ool_input,
5003e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_input_size,
5004e13b1fa5SApple OSS Distributions 	io_struct_inband_t inband_output,
5005e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *inband_outputCnt,
5006855239e5SApple OSS Distributions 	io_scalar_inband64_t scalar_output,
5007855239e5SApple OSS Distributions 	mach_msg_type_number_t *scalar_outputCnt,
5008e13b1fa5SApple OSS Distributions 	mach_vm_address_t ool_output,
5009e13b1fa5SApple OSS Distributions 	mach_vm_size_t *ool_output_size
5010e13b1fa5SApple OSS Distributions )
5011e13b1fa5SApple OSS Distributions {
5012e13b1fa5SApple OSS Distributions 	CHECK( IOUserClient, connection, client );
5013e13b1fa5SApple OSS Distributions 
5014e13b1fa5SApple OSS Distributions 	IOExternalMethodArguments args;
5015e13b1fa5SApple OSS Distributions 	IOReturn ret;
5016a5e72196SApple OSS Distributions 	IOMemoryDescriptor * inputMD  = NULL;
5017a5e72196SApple OSS Distributions 	IOMemoryDescriptor * outputMD = NULL;
5018e13b1fa5SApple OSS Distributions 
5019e13b1fa5SApple OSS Distributions 	bzero(&args.__reserved[0], sizeof(args.__reserved));
502088cc0b97SApple OSS Distributions 	args.__reservedA = 0;
5021e13b1fa5SApple OSS Distributions 	args.version = kIOExternalMethodArgumentsCurrentVersion;
5022e13b1fa5SApple OSS Distributions 
5023e13b1fa5SApple OSS Distributions 	args.selector = selector;
5024e13b1fa5SApple OSS Distributions 
5025e13b1fa5SApple OSS Distributions 	args.asyncWakePort               = MACH_PORT_NULL;
5026a5e72196SApple OSS Distributions 	args.asyncReference              = NULL;
5027e13b1fa5SApple OSS Distributions 	args.asyncReferenceCount         = 0;
5028a5e72196SApple OSS Distributions 	args.structureVariableOutputData = NULL;
5029e13b1fa5SApple OSS Distributions 
5030e13b1fa5SApple OSS Distributions 	args.scalarInput = scalar_input;
5031e13b1fa5SApple OSS Distributions 	args.scalarInputCount = scalar_inputCnt;
5032e13b1fa5SApple OSS Distributions 	args.structureInput = inband_input;
5033e13b1fa5SApple OSS Distributions 	args.structureInputSize = inband_inputCnt;
5034e13b1fa5SApple OSS Distributions 
5035a5e72196SApple OSS Distributions 	if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) {
5036a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
5037a5e72196SApple OSS Distributions 	}
5038bb611c8fSApple OSS Distributions 	if (ool_output) {
5039bb611c8fSApple OSS Distributions 		if (*ool_output_size <= sizeof(io_struct_inband_t)) {
5040a5e72196SApple OSS Distributions 			return kIOReturnIPCError;
5041a5e72196SApple OSS Distributions 		}
5042bb611c8fSApple OSS Distributions 		if (*ool_output_size > UINT_MAX) {
5043bb611c8fSApple OSS Distributions 			return kIOReturnIPCError;
5044bb611c8fSApple OSS Distributions 		}
5045bb611c8fSApple OSS Distributions 	}
504676e12aa3SApple OSS Distributions 
5047a5e72196SApple OSS Distributions 	if (ool_input) {
5048e13b1fa5SApple OSS Distributions 		inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
504976e12aa3SApple OSS Distributions 		    kIODirectionOut | kIOMemoryMapCopyOnWrite,
505076e12aa3SApple OSS Distributions 		    current_task());
5051a5e72196SApple OSS Distributions 	}
5052e13b1fa5SApple OSS Distributions 
5053e13b1fa5SApple OSS Distributions 	args.structureInputDescriptor = inputMD;
5054e13b1fa5SApple OSS Distributions 
5055e13b1fa5SApple OSS Distributions 	args.scalarOutput = scalar_output;
5056e13b1fa5SApple OSS Distributions 	args.scalarOutputCount = *scalar_outputCnt;
5057a3bb9fccSApple OSS Distributions 	bzero(&scalar_output[0], *scalar_outputCnt * sizeof(scalar_output[0]));
5058e13b1fa5SApple OSS Distributions 	args.structureOutput = inband_output;
5059e13b1fa5SApple OSS Distributions 	args.structureOutputSize = *inband_outputCnt;
5060e13b1fa5SApple OSS Distributions 
5061a5e72196SApple OSS Distributions 	if (ool_output && ool_output_size) {
5062e13b1fa5SApple OSS Distributions 		outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
5063e13b1fa5SApple OSS Distributions 		    kIODirectionIn, current_task());
5064e13b1fa5SApple OSS Distributions 	}
5065e13b1fa5SApple OSS Distributions 
5066e13b1fa5SApple OSS Distributions 	args.structureOutputDescriptor = outputMD;
5067bb611c8fSApple OSS Distributions 	args.structureOutputDescriptorSize = ool_output_size
5068bb611c8fSApple OSS Distributions 	    ? ((typeof(args.structureOutputDescriptorSize)) * ool_output_size)
5069bb611c8fSApple OSS Distributions 	    : 0;
5070e13b1fa5SApple OSS Distributions 
5071855239e5SApple OSS Distributions 	IOStatisticsClientCall();
5072bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
5073bb611c8fSApple OSS Distributions 	io_filter_policy_t filterPolicy = client->filterForTask(current_task(), 0);
5074bb611c8fSApple OSS Distributions 	if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
5075e6231be0SApple OSS Distributions 		ret = gIOUCFilterCallbacks->io_filter_applier(client, filterPolicy, io_filter_type_external_method, selector);
5076bb611c8fSApple OSS Distributions 	}
5077bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess == ret) {
50785c2921b0SApple OSS Distributions 		ret = client->callExternalMethod( selector, &args );
5079bb611c8fSApple OSS Distributions 	}
5080e13b1fa5SApple OSS Distributions 
5081e13b1fa5SApple OSS Distributions 	*scalar_outputCnt = args.scalarOutputCount;
5082e13b1fa5SApple OSS Distributions 	*inband_outputCnt = args.structureOutputSize;
5083e13b1fa5SApple OSS Distributions 	*ool_output_size  = args.structureOutputDescriptorSize;
5084e13b1fa5SApple OSS Distributions 
5085a5e72196SApple OSS Distributions 	if (inputMD) {
5086e13b1fa5SApple OSS Distributions 		inputMD->release();
5087a5e72196SApple OSS Distributions 	}
5088a5e72196SApple OSS Distributions 	if (outputMD) {
5089e13b1fa5SApple OSS Distributions 		outputMD->release();
5090a5e72196SApple OSS Distributions 	}
5091e13b1fa5SApple OSS Distributions 
5092a5e72196SApple OSS Distributions 	return ret;
5093e13b1fa5SApple OSS Distributions }
5094e13b1fa5SApple OSS Distributions 
5095e13b1fa5SApple OSS Distributions /* Routine io_async_user_client_method */
5096a5e72196SApple OSS Distributions kern_return_t
is_io_connect_async_method(io_connect_t connection,mach_port_t wake_port,io_async_ref64_t reference,mach_msg_type_number_t referenceCnt,uint32_t selector,io_scalar_inband64_t scalar_input,mach_msg_type_number_t scalar_inputCnt,io_struct_inband_t inband_input,mach_msg_type_number_t inband_inputCnt,mach_vm_address_t ool_input,mach_vm_size_t ool_input_size,io_struct_inband_t inband_output,mach_msg_type_number_t * inband_outputCnt,io_scalar_inband64_t scalar_output,mach_msg_type_number_t * scalar_outputCnt,mach_vm_address_t ool_output,mach_vm_size_t * ool_output_size)5097a5e72196SApple OSS Distributions is_io_connect_async_method
5098e13b1fa5SApple OSS Distributions (
5099e13b1fa5SApple OSS Distributions 	io_connect_t connection,
5100e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
5101e13b1fa5SApple OSS Distributions 	io_async_ref64_t reference,
5102e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
5103e13b1fa5SApple OSS Distributions 	uint32_t selector,
5104e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t scalar_input,
5105e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_inputCnt,
5106e13b1fa5SApple OSS Distributions 	io_struct_inband_t inband_input,
5107e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t inband_inputCnt,
5108e13b1fa5SApple OSS Distributions 	mach_vm_address_t ool_input,
5109e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_input_size,
5110e13b1fa5SApple OSS Distributions 	io_struct_inband_t inband_output,
5111e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *inband_outputCnt,
5112855239e5SApple OSS Distributions 	io_scalar_inband64_t scalar_output,
5113855239e5SApple OSS Distributions 	mach_msg_type_number_t *scalar_outputCnt,
5114e13b1fa5SApple OSS Distributions 	mach_vm_address_t ool_output,
5115e13b1fa5SApple OSS Distributions 	mach_vm_size_t * ool_output_size
5116e13b1fa5SApple OSS Distributions )
5117e13b1fa5SApple OSS Distributions {
5118e13b1fa5SApple OSS Distributions 	CHECK( IOUserClient, connection, client );
5119e13b1fa5SApple OSS Distributions 
5120e13b1fa5SApple OSS Distributions 	IOExternalMethodArguments args;
5121e13b1fa5SApple OSS Distributions 	IOReturn ret;
5122a5e72196SApple OSS Distributions 	IOMemoryDescriptor * inputMD  = NULL;
5123a5e72196SApple OSS Distributions 	IOMemoryDescriptor * outputMD = NULL;
5124e13b1fa5SApple OSS Distributions 
5125bb611c8fSApple OSS Distributions 	if (referenceCnt < 1) {
5126bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
5127bb611c8fSApple OSS Distributions 	}
5128bb611c8fSApple OSS Distributions 
5129e13b1fa5SApple OSS Distributions 	bzero(&args.__reserved[0], sizeof(args.__reserved));
513088cc0b97SApple OSS Distributions 	args.__reservedA = 0;
5131e13b1fa5SApple OSS Distributions 	args.version = kIOExternalMethodArgumentsCurrentVersion;
5132e13b1fa5SApple OSS Distributions 
5133e13b1fa5SApple OSS Distributions 	reference[0]             = (io_user_reference_t) wake_port;
5134a5e72196SApple OSS Distributions 	if (vm_map_is_64bit(get_task_map(current_task()))) {
5135e13b1fa5SApple OSS Distributions 		reference[0]         |= kIOUCAsync64Flag;
5136a5e72196SApple OSS Distributions 	}
5137e13b1fa5SApple OSS Distributions 
5138e13b1fa5SApple OSS Distributions 	args.selector = selector;
5139e13b1fa5SApple OSS Distributions 
5140e13b1fa5SApple OSS Distributions 	args.asyncWakePort       = wake_port;
5141e13b1fa5SApple OSS Distributions 	args.asyncReference      = reference;
5142e13b1fa5SApple OSS Distributions 	args.asyncReferenceCount = referenceCnt;
5143e13b1fa5SApple OSS Distributions 
5144a5e72196SApple OSS Distributions 	args.structureVariableOutputData = NULL;
514576e12aa3SApple OSS Distributions 
5146e13b1fa5SApple OSS Distributions 	args.scalarInput = scalar_input;
5147e13b1fa5SApple OSS Distributions 	args.scalarInputCount = scalar_inputCnt;
5148e13b1fa5SApple OSS Distributions 	args.structureInput = inband_input;
5149e13b1fa5SApple OSS Distributions 	args.structureInputSize = inband_inputCnt;
5150e13b1fa5SApple OSS Distributions 
5151a5e72196SApple OSS Distributions 	if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) {
5152a5e72196SApple OSS Distributions 		return kIOReturnIPCError;
5153a5e72196SApple OSS Distributions 	}
5154bb611c8fSApple OSS Distributions 	if (ool_output) {
5155bb611c8fSApple OSS Distributions 		if (*ool_output_size <= sizeof(io_struct_inband_t)) {
5156a5e72196SApple OSS Distributions 			return kIOReturnIPCError;
5157a5e72196SApple OSS Distributions 		}
5158bb611c8fSApple OSS Distributions 		if (*ool_output_size > UINT_MAX) {
5159bb611c8fSApple OSS Distributions 			return kIOReturnIPCError;
5160bb611c8fSApple OSS Distributions 		}
5161bb611c8fSApple OSS Distributions 	}
516276e12aa3SApple OSS Distributions 
5163a5e72196SApple OSS Distributions 	if (ool_input) {
5164e13b1fa5SApple OSS Distributions 		inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
516576e12aa3SApple OSS Distributions 		    kIODirectionOut | kIOMemoryMapCopyOnWrite,
516676e12aa3SApple OSS Distributions 		    current_task());
5167a5e72196SApple OSS Distributions 	}
5168e13b1fa5SApple OSS Distributions 
5169e13b1fa5SApple OSS Distributions 	args.structureInputDescriptor = inputMD;
5170e13b1fa5SApple OSS Distributions 
5171e13b1fa5SApple OSS Distributions 	args.scalarOutput = scalar_output;
5172e13b1fa5SApple OSS Distributions 	args.scalarOutputCount = *scalar_outputCnt;
5173a3bb9fccSApple OSS Distributions 	bzero(&scalar_output[0], *scalar_outputCnt * sizeof(scalar_output[0]));
5174e13b1fa5SApple OSS Distributions 	args.structureOutput = inband_output;
5175e13b1fa5SApple OSS Distributions 	args.structureOutputSize = *inband_outputCnt;
5176e13b1fa5SApple OSS Distributions 
5177a5e72196SApple OSS Distributions 	if (ool_output) {
5178e13b1fa5SApple OSS Distributions 		outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
5179e13b1fa5SApple OSS Distributions 		    kIODirectionIn, current_task());
5180e13b1fa5SApple OSS Distributions 	}
5181e13b1fa5SApple OSS Distributions 
5182e13b1fa5SApple OSS Distributions 	args.structureOutputDescriptor = outputMD;
5183bb611c8fSApple OSS Distributions 	args.structureOutputDescriptorSize = ((typeof(args.structureOutputDescriptorSize)) * ool_output_size);
5184e13b1fa5SApple OSS Distributions 
5185855239e5SApple OSS Distributions 	IOStatisticsClientCall();
5186bb611c8fSApple OSS Distributions 	ret = kIOReturnSuccess;
5187bb611c8fSApple OSS Distributions 	io_filter_policy_t filterPolicy = client->filterForTask(current_task(), 0);
5188bb611c8fSApple OSS Distributions 	if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
5189e6231be0SApple OSS Distributions 		ret = gIOUCFilterCallbacks->io_filter_applier(client, filterPolicy, io_filter_type_external_async_method, selector);
5190bb611c8fSApple OSS Distributions 	}
5191bb611c8fSApple OSS Distributions 	if (kIOReturnSuccess == ret) {
51925c2921b0SApple OSS Distributions 		ret = client->callExternalMethod( selector, &args );
5193bb611c8fSApple OSS Distributions 	}
5194e13b1fa5SApple OSS Distributions 
5195a5e72196SApple OSS Distributions 	*scalar_outputCnt = args.scalarOutputCount;
5196e13b1fa5SApple OSS Distributions 	*inband_outputCnt = args.structureOutputSize;
5197e13b1fa5SApple OSS Distributions 	*ool_output_size  = args.structureOutputDescriptorSize;
5198e13b1fa5SApple OSS Distributions 
5199a5e72196SApple OSS Distributions 	if (inputMD) {
5200e13b1fa5SApple OSS Distributions 		inputMD->release();
5201a5e72196SApple OSS Distributions 	}
5202a5e72196SApple OSS Distributions 	if (outputMD) {
5203e13b1fa5SApple OSS Distributions 		outputMD->release();
5204a5e72196SApple OSS Distributions 	}
5205e13b1fa5SApple OSS Distributions 
5206a5e72196SApple OSS Distributions 	return ret;
5207e13b1fa5SApple OSS Distributions }
5208e13b1fa5SApple OSS Distributions 
5209c1dac77fSApple OSS Distributions /* Routine io_connect_method_scalarI_scalarO */
5210a5e72196SApple OSS Distributions kern_return_t
is_io_connect_method_scalarI_scalarO(io_object_t connect,uint32_t index,io_scalar_inband_t input,mach_msg_type_number_t inputCount,io_scalar_inband_t output,mach_msg_type_number_t * outputCount)5211a5e72196SApple OSS Distributions is_io_connect_method_scalarI_scalarO(
5212c1dac77fSApple OSS Distributions 	io_object_t        connect,
5213e13b1fa5SApple OSS Distributions 	uint32_t           index,
5214e13b1fa5SApple OSS Distributions 	io_scalar_inband_t       input,
5215e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t   inputCount,
5216e13b1fa5SApple OSS Distributions 	io_scalar_inband_t       output,
5217e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t * outputCount )
5218c1dac77fSApple OSS Distributions {
5219c1dac77fSApple OSS Distributions 	IOReturn err;
5220e13b1fa5SApple OSS Distributions 	uint32_t i;
5221e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _input;
5222e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _output;
5223c1dac77fSApple OSS Distributions 
5224e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t struct_outputCnt = 0;
5225e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5226e13b1fa5SApple OSS Distributions 
5227a3bb9fccSApple OSS Distributions 	bzero(&_output[0], sizeof(_output));
5228a5e72196SApple OSS Distributions 	for (i = 0; i < inputCount; i++) {
5229e13b1fa5SApple OSS Distributions 		_input[i] = SCALAR64(input[i]);
5230a5e72196SApple OSS Distributions 	}
5231e13b1fa5SApple OSS Distributions 
5232e13b1fa5SApple OSS Distributions 	err = is_io_connect_method(connect, index,
5233e13b1fa5SApple OSS Distributions 	    _input, inputCount,
5234e13b1fa5SApple OSS Distributions 	    NULL, 0,
5235e13b1fa5SApple OSS Distributions 	    0, 0,
5236e13b1fa5SApple OSS Distributions 	    NULL, &struct_outputCnt,
5237855239e5SApple OSS Distributions 	    _output, outputCount,
5238e13b1fa5SApple OSS Distributions 	    0, &ool_output_size);
5239e13b1fa5SApple OSS Distributions 
5240a5e72196SApple OSS Distributions 	for (i = 0; i < *outputCount; i++) {
5241e13b1fa5SApple OSS Distributions 		output[i] = SCALAR32(_output[i]);
5242e13b1fa5SApple OSS Distributions 	}
5243e13b1fa5SApple OSS Distributions 
5244a5e72196SApple OSS Distributions 	return err;
5245a5e72196SApple OSS Distributions }
5246a5e72196SApple OSS Distributions 
5247a5e72196SApple OSS Distributions kern_return_t
shim_io_connect_method_scalarI_scalarO(IOExternalMethod * method,IOService * object,const io_user_scalar_t * input,mach_msg_type_number_t inputCount,io_user_scalar_t * output,mach_msg_type_number_t * outputCount)5248a5e72196SApple OSS Distributions shim_io_connect_method_scalarI_scalarO(
5249e13b1fa5SApple OSS Distributions 	IOExternalMethod *      method,
5250e13b1fa5SApple OSS Distributions 	IOService *             object,
5251e13b1fa5SApple OSS Distributions 	const io_user_scalar_t * input,
5252e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t   inputCount,
5253e13b1fa5SApple OSS Distributions 	io_user_scalar_t * output,
5254e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t * outputCount )
5255e13b1fa5SApple OSS Distributions {
5256e13b1fa5SApple OSS Distributions 	IOMethod            func;
5257e13b1fa5SApple OSS Distributions 	io_scalar_inband_t  _output;
5258e13b1fa5SApple OSS Distributions 	IOReturn            err;
5259c1dac77fSApple OSS Distributions 	err = kIOReturnBadArgument;
5260e13b1fa5SApple OSS Distributions 
5261a3bb9fccSApple OSS Distributions 	bzero(&_output[0], sizeof(_output));
5262e13b1fa5SApple OSS Distributions 	do {
5263a5e72196SApple OSS Distributions 		if (inputCount != method->count0) {
526488cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
526588cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
5266c1dac77fSApple OSS Distributions 			continue;
5267e13b1fa5SApple OSS Distributions 		}
5268a5e72196SApple OSS Distributions 		if (*outputCount != method->count1) {
526988cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1);
527088cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
5271c1dac77fSApple OSS Distributions 			continue;
5272e13b1fa5SApple OSS Distributions 		}
5273c1dac77fSApple OSS Distributions 
5274c1dac77fSApple OSS Distributions 		func = method->func;
5275c1dac77fSApple OSS Distributions 
5276c1dac77fSApple OSS Distributions 		switch (inputCount) {
5277c1dac77fSApple OSS Distributions 		case 6:
5278e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5279e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]), ARG32(input[5]));
5280c1dac77fSApple OSS Distributions 			break;
5281c1dac77fSApple OSS Distributions 		case 5:
5282e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5283e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]),
5284e13b1fa5SApple OSS Distributions 			    &_output[0] );
5285c1dac77fSApple OSS Distributions 			break;
5286c1dac77fSApple OSS Distributions 		case 4:
5287e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5288e13b1fa5SApple OSS Distributions 			    ARG32(input[3]),
5289e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1] );
5290c1dac77fSApple OSS Distributions 			break;
5291c1dac77fSApple OSS Distributions 		case 3:
5292e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5293e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1], &_output[2] );
5294c1dac77fSApple OSS Distributions 			break;
5295c1dac77fSApple OSS Distributions 		case 2:
5296e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]),
5297e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1], &_output[2],
5298e13b1fa5SApple OSS Distributions 			    &_output[3] );
5299c1dac77fSApple OSS Distributions 			break;
5300c1dac77fSApple OSS Distributions 		case 1:
5301e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]),
5302e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1], &_output[2],
5303e13b1fa5SApple OSS Distributions 			    &_output[3], &_output[4] );
5304c1dac77fSApple OSS Distributions 			break;
5305c1dac77fSApple OSS Distributions 		case 0:
5306e13b1fa5SApple OSS Distributions 			err = (object->*func)(  &_output[0], &_output[1], &_output[2],
5307e13b1fa5SApple OSS Distributions 			    &_output[3], &_output[4], &_output[5] );
5308c1dac77fSApple OSS Distributions 			break;
5309c1dac77fSApple OSS Distributions 
5310c1dac77fSApple OSS Distributions 		default:
5311e13b1fa5SApple OSS Distributions 			IOLog("%s: Bad method table\n", object->getName());
5312c1dac77fSApple OSS Distributions 		}
5313a5e72196SApple OSS Distributions 	}while (false);
5314c1dac77fSApple OSS Distributions 
5315e13b1fa5SApple OSS Distributions 	uint32_t i;
5316a5e72196SApple OSS Distributions 	for (i = 0; i < *outputCount; i++) {
5317e13b1fa5SApple OSS Distributions 		output[i] = SCALAR32(_output[i]);
5318a5e72196SApple OSS Distributions 	}
5319c1dac77fSApple OSS Distributions 
5320a5e72196SApple OSS Distributions 	return err;
5321c1dac77fSApple OSS Distributions }
5322c1dac77fSApple OSS Distributions 
5323e13b1fa5SApple OSS Distributions /* Routine io_async_method_scalarI_scalarO */
5324a5e72196SApple OSS Distributions kern_return_t
is_io_async_method_scalarI_scalarO(io_object_t connect,mach_port_t wake_port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,uint32_t index,io_scalar_inband_t input,mach_msg_type_number_t inputCount,io_scalar_inband_t output,mach_msg_type_number_t * outputCount)5325a5e72196SApple OSS Distributions is_io_async_method_scalarI_scalarO(
5326e13b1fa5SApple OSS Distributions 	io_object_t        connect,
5327e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
5328e13b1fa5SApple OSS Distributions 	io_async_ref_t reference,
5329e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
5330e13b1fa5SApple OSS Distributions 	uint32_t           index,
5331e13b1fa5SApple OSS Distributions 	io_scalar_inband_t       input,
5332e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t   inputCount,
5333e13b1fa5SApple OSS Distributions 	io_scalar_inband_t       output,
5334e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t * outputCount )
5335e13b1fa5SApple OSS Distributions {
5336e13b1fa5SApple OSS Distributions 	IOReturn err;
5337e13b1fa5SApple OSS Distributions 	uint32_t i;
5338e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _input;
5339e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _output;
5340e13b1fa5SApple OSS Distributions 	io_async_ref64_t _reference;
5341e13b1fa5SApple OSS Distributions 
5342a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF64_COUNT) {
5343a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
5344a5e72196SApple OSS Distributions 	}
5345a3bb9fccSApple OSS Distributions 	bzero(&_output[0], sizeof(_output));
5346a5e72196SApple OSS Distributions 	for (i = 0; i < referenceCnt; i++) {
5347e13b1fa5SApple OSS Distributions 		_reference[i] = REF64(reference[i]);
5348a5e72196SApple OSS Distributions 	}
5349a5e72196SApple OSS Distributions 	bzero(&_reference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(_reference[0]));
5350e13b1fa5SApple OSS Distributions 
5351e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t struct_outputCnt = 0;
5352e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5353e13b1fa5SApple OSS Distributions 
5354a5e72196SApple OSS Distributions 	for (i = 0; i < inputCount; i++) {
5355e13b1fa5SApple OSS Distributions 		_input[i] = SCALAR64(input[i]);
5356a5e72196SApple OSS Distributions 	}
5357e13b1fa5SApple OSS Distributions 
5358e13b1fa5SApple OSS Distributions 	err = is_io_connect_async_method(connect,
5359e13b1fa5SApple OSS Distributions 	    wake_port, _reference, referenceCnt,
5360e13b1fa5SApple OSS Distributions 	    index,
5361e13b1fa5SApple OSS Distributions 	    _input, inputCount,
5362e13b1fa5SApple OSS Distributions 	    NULL, 0,
5363e13b1fa5SApple OSS Distributions 	    0, 0,
5364e13b1fa5SApple OSS Distributions 	    NULL, &struct_outputCnt,
5365855239e5SApple OSS Distributions 	    _output, outputCount,
5366e13b1fa5SApple OSS Distributions 	    0, &ool_output_size);
5367e13b1fa5SApple OSS Distributions 
5368a5e72196SApple OSS Distributions 	for (i = 0; i < *outputCount; i++) {
5369e13b1fa5SApple OSS Distributions 		output[i] = SCALAR32(_output[i]);
5370a5e72196SApple OSS Distributions 	}
5371e13b1fa5SApple OSS Distributions 
5372a5e72196SApple OSS Distributions 	return err;
5373e13b1fa5SApple OSS Distributions }
5374e13b1fa5SApple OSS Distributions /* Routine io_async_method_scalarI_structureO */
5375a5e72196SApple OSS Distributions kern_return_t
is_io_async_method_scalarI_structureO(io_object_t connect,mach_port_t wake_port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,uint32_t index,io_scalar_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t output,mach_msg_type_number_t * outputCount)5376a5e72196SApple OSS Distributions is_io_async_method_scalarI_structureO(
5377e13b1fa5SApple OSS Distributions 	io_object_t     connect,
5378e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
5379e13b1fa5SApple OSS Distributions 	io_async_ref_t reference,
5380e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
5381e13b1fa5SApple OSS Distributions 	uint32_t        index,
5382e13b1fa5SApple OSS Distributions 	io_scalar_inband_t input,
5383e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5384e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
5385e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *        outputCount )
5386e13b1fa5SApple OSS Distributions {
5387e13b1fa5SApple OSS Distributions 	uint32_t i;
5388e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _input;
5389e13b1fa5SApple OSS Distributions 	io_async_ref64_t _reference;
5390e13b1fa5SApple OSS Distributions 
5391a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF64_COUNT) {
5392a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
5393a5e72196SApple OSS Distributions 	}
5394a5e72196SApple OSS Distributions 	for (i = 0; i < referenceCnt; i++) {
5395e13b1fa5SApple OSS Distributions 		_reference[i] = REF64(reference[i]);
5396a5e72196SApple OSS Distributions 	}
5397a5e72196SApple OSS Distributions 	bzero(&_reference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(_reference[0]));
5398e13b1fa5SApple OSS Distributions 
5399e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_outputCnt = 0;
5400e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5401e13b1fa5SApple OSS Distributions 
5402a5e72196SApple OSS Distributions 	for (i = 0; i < inputCount; i++) {
5403e13b1fa5SApple OSS Distributions 		_input[i] = SCALAR64(input[i]);
5404a5e72196SApple OSS Distributions 	}
5405e13b1fa5SApple OSS Distributions 
5406a5e72196SApple OSS Distributions 	return is_io_connect_async_method(connect,
5407e13b1fa5SApple OSS Distributions 	           wake_port, _reference, referenceCnt,
5408e13b1fa5SApple OSS Distributions 	           index,
5409e13b1fa5SApple OSS Distributions 	           _input, inputCount,
5410e13b1fa5SApple OSS Distributions 	           NULL, 0,
5411e13b1fa5SApple OSS Distributions 	           0, 0,
5412e13b1fa5SApple OSS Distributions 	           output, outputCount,
5413855239e5SApple OSS Distributions 	           NULL, &scalar_outputCnt,
5414a5e72196SApple OSS Distributions 	           0, &ool_output_size);
5415e13b1fa5SApple OSS Distributions }
5416e13b1fa5SApple OSS Distributions 
5417e13b1fa5SApple OSS Distributions /* Routine io_async_method_scalarI_structureI */
5418a5e72196SApple OSS Distributions kern_return_t
is_io_async_method_scalarI_structureI(io_connect_t connect,mach_port_t wake_port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,uint32_t index,io_scalar_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t inputStruct,mach_msg_type_number_t inputStructCount)5419a5e72196SApple OSS Distributions is_io_async_method_scalarI_structureI(
5420e13b1fa5SApple OSS Distributions 	io_connect_t            connect,
5421e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
5422e13b1fa5SApple OSS Distributions 	io_async_ref_t reference,
5423e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
5424e13b1fa5SApple OSS Distributions 	uint32_t                index,
5425e13b1fa5SApple OSS Distributions 	io_scalar_inband_t      input,
5426e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5427e13b1fa5SApple OSS Distributions 	io_struct_inband_t      inputStruct,
5428e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputStructCount )
5429e13b1fa5SApple OSS Distributions {
5430e13b1fa5SApple OSS Distributions 	uint32_t i;
5431e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _input;
5432e13b1fa5SApple OSS Distributions 	io_async_ref64_t _reference;
5433e13b1fa5SApple OSS Distributions 
5434a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF64_COUNT) {
5435a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
5436a5e72196SApple OSS Distributions 	}
5437a5e72196SApple OSS Distributions 	for (i = 0; i < referenceCnt; i++) {
5438e13b1fa5SApple OSS Distributions 		_reference[i] = REF64(reference[i]);
5439a5e72196SApple OSS Distributions 	}
5440a5e72196SApple OSS Distributions 	bzero(&_reference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(_reference[0]));
5441e13b1fa5SApple OSS Distributions 
5442e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_outputCnt = 0;
5443e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t inband_outputCnt = 0;
5444e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5445e13b1fa5SApple OSS Distributions 
5446a5e72196SApple OSS Distributions 	for (i = 0; i < inputCount; i++) {
5447e13b1fa5SApple OSS Distributions 		_input[i] = SCALAR64(input[i]);
5448a5e72196SApple OSS Distributions 	}
5449e13b1fa5SApple OSS Distributions 
5450a5e72196SApple OSS Distributions 	return is_io_connect_async_method(connect,
5451e13b1fa5SApple OSS Distributions 	           wake_port, _reference, referenceCnt,
5452e13b1fa5SApple OSS Distributions 	           index,
5453e13b1fa5SApple OSS Distributions 	           _input, inputCount,
5454e13b1fa5SApple OSS Distributions 	           inputStruct, inputStructCount,
5455e13b1fa5SApple OSS Distributions 	           0, 0,
5456e13b1fa5SApple OSS Distributions 	           NULL, &inband_outputCnt,
5457855239e5SApple OSS Distributions 	           NULL, &scalar_outputCnt,
5458a5e72196SApple OSS Distributions 	           0, &ool_output_size);
5459e13b1fa5SApple OSS Distributions }
5460e13b1fa5SApple OSS Distributions 
5461e13b1fa5SApple OSS Distributions /* Routine io_async_method_structureI_structureO */
5462a5e72196SApple OSS Distributions kern_return_t
is_io_async_method_structureI_structureO(io_object_t connect,mach_port_t wake_port,io_async_ref_t reference,mach_msg_type_number_t referenceCnt,uint32_t index,io_struct_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t output,mach_msg_type_number_t * outputCount)5463a5e72196SApple OSS Distributions is_io_async_method_structureI_structureO(
5464e13b1fa5SApple OSS Distributions 	io_object_t     connect,
5465e13b1fa5SApple OSS Distributions 	mach_port_t wake_port,
5466e13b1fa5SApple OSS Distributions 	io_async_ref_t reference,
5467e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t referenceCnt,
5468e13b1fa5SApple OSS Distributions 	uint32_t        index,
5469e13b1fa5SApple OSS Distributions 	io_struct_inband_t              input,
5470e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5471e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
5472e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *        outputCount )
5473e13b1fa5SApple OSS Distributions {
5474e13b1fa5SApple OSS Distributions 	uint32_t i;
5475e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_outputCnt = 0;
5476e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5477e13b1fa5SApple OSS Distributions 	io_async_ref64_t _reference;
5478e13b1fa5SApple OSS Distributions 
5479a5e72196SApple OSS Distributions 	if (referenceCnt > ASYNC_REF64_COUNT) {
5480a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
5481a5e72196SApple OSS Distributions 	}
5482a5e72196SApple OSS Distributions 	for (i = 0; i < referenceCnt; i++) {
5483e13b1fa5SApple OSS Distributions 		_reference[i] = REF64(reference[i]);
5484a5e72196SApple OSS Distributions 	}
5485a5e72196SApple OSS Distributions 	bzero(&_reference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(_reference[0]));
5486e13b1fa5SApple OSS Distributions 
5487a5e72196SApple OSS Distributions 	return is_io_connect_async_method(connect,
5488e13b1fa5SApple OSS Distributions 	           wake_port, _reference, referenceCnt,
5489e13b1fa5SApple OSS Distributions 	           index,
5490e13b1fa5SApple OSS Distributions 	           NULL, 0,
5491e13b1fa5SApple OSS Distributions 	           input, inputCount,
5492e13b1fa5SApple OSS Distributions 	           0, 0,
5493e13b1fa5SApple OSS Distributions 	           output, outputCount,
5494855239e5SApple OSS Distributions 	           NULL, &scalar_outputCnt,
5495a5e72196SApple OSS Distributions 	           0, &ool_output_size);
5496e13b1fa5SApple OSS Distributions }
5497e13b1fa5SApple OSS Distributions 
5498e13b1fa5SApple OSS Distributions 
5499a5e72196SApple OSS Distributions kern_return_t
shim_io_async_method_scalarI_scalarO(IOExternalAsyncMethod * method,IOService * object,mach_port_t asyncWakePort,io_user_reference_t * asyncReference,uint32_t asyncReferenceCount,const io_user_scalar_t * input,mach_msg_type_number_t inputCount,io_user_scalar_t * output,mach_msg_type_number_t * outputCount)5500a5e72196SApple OSS Distributions shim_io_async_method_scalarI_scalarO(
5501e13b1fa5SApple OSS Distributions 	IOExternalAsyncMethod * method,
5502e13b1fa5SApple OSS Distributions 	IOService *             object,
5503e13b1fa5SApple OSS Distributions 	mach_port_t             asyncWakePort,
5504e13b1fa5SApple OSS Distributions 	io_user_reference_t *   asyncReference,
5505e13b1fa5SApple OSS Distributions 	uint32_t                asyncReferenceCount,
5506e13b1fa5SApple OSS Distributions 	const io_user_scalar_t * input,
5507e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t   inputCount,
5508e13b1fa5SApple OSS Distributions 	io_user_scalar_t * output,
5509e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t * outputCount )
5510e13b1fa5SApple OSS Distributions {
5511e13b1fa5SApple OSS Distributions 	IOAsyncMethod       func;
5512e13b1fa5SApple OSS Distributions 	uint32_t            i;
5513e13b1fa5SApple OSS Distributions 	io_scalar_inband_t  _output;
5514e13b1fa5SApple OSS Distributions 	IOReturn            err;
5515e13b1fa5SApple OSS Distributions 	io_async_ref_t      reference;
5516e13b1fa5SApple OSS Distributions 
5517a3bb9fccSApple OSS Distributions 	bzero(&_output[0], sizeof(_output));
5518a5e72196SApple OSS Distributions 	for (i = 0; i < asyncReferenceCount; i++) {
5519e13b1fa5SApple OSS Distributions 		reference[i] = REF32(asyncReference[i]);
5520a5e72196SApple OSS Distributions 	}
5521e13b1fa5SApple OSS Distributions 
5522e13b1fa5SApple OSS Distributions 	err = kIOReturnBadArgument;
5523e13b1fa5SApple OSS Distributions 
5524e13b1fa5SApple OSS Distributions 	do {
5525a5e72196SApple OSS Distributions 		if (inputCount != method->count0) {
552688cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
552788cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
5528e13b1fa5SApple OSS Distributions 			continue;
5529e13b1fa5SApple OSS Distributions 		}
5530a5e72196SApple OSS Distributions 		if (*outputCount != method->count1) {
553188cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1);
553288cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
5533e13b1fa5SApple OSS Distributions 			continue;
5534e13b1fa5SApple OSS Distributions 		}
5535e13b1fa5SApple OSS Distributions 
5536e13b1fa5SApple OSS Distributions 		func = method->func;
5537e13b1fa5SApple OSS Distributions 
5538e13b1fa5SApple OSS Distributions 		switch (inputCount) {
5539e13b1fa5SApple OSS Distributions 		case 6:
5540e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5541e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5542e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]), ARG32(input[5]));
5543e13b1fa5SApple OSS Distributions 			break;
5544e13b1fa5SApple OSS Distributions 		case 5:
5545e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5546e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5547e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]),
5548e13b1fa5SApple OSS Distributions 			    &_output[0] );
5549e13b1fa5SApple OSS Distributions 			break;
5550e13b1fa5SApple OSS Distributions 		case 4:
5551e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5552e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5553e13b1fa5SApple OSS Distributions 			    ARG32(input[3]),
5554e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1] );
5555e13b1fa5SApple OSS Distributions 			break;
5556e13b1fa5SApple OSS Distributions 		case 3:
5557e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5558e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5559e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1], &_output[2] );
5560e13b1fa5SApple OSS Distributions 			break;
5561e13b1fa5SApple OSS Distributions 		case 2:
5562e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5563e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]),
5564e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1], &_output[2],
5565e13b1fa5SApple OSS Distributions 			    &_output[3] );
5566e13b1fa5SApple OSS Distributions 			break;
5567e13b1fa5SApple OSS Distributions 		case 1:
5568e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5569e13b1fa5SApple OSS Distributions 			    ARG32(input[0]),
5570e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1], &_output[2],
5571e13b1fa5SApple OSS Distributions 			    &_output[3], &_output[4] );
5572e13b1fa5SApple OSS Distributions 			break;
5573e13b1fa5SApple OSS Distributions 		case 0:
5574e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5575e13b1fa5SApple OSS Distributions 			    &_output[0], &_output[1], &_output[2],
5576e13b1fa5SApple OSS Distributions 			    &_output[3], &_output[4], &_output[5] );
5577e13b1fa5SApple OSS Distributions 			break;
5578e13b1fa5SApple OSS Distributions 
5579e13b1fa5SApple OSS Distributions 		default:
5580e13b1fa5SApple OSS Distributions 			IOLog("%s: Bad method table\n", object->getName());
5581e13b1fa5SApple OSS Distributions 		}
5582a5e72196SApple OSS Distributions 	}while (false);
5583e13b1fa5SApple OSS Distributions 
5584a5e72196SApple OSS Distributions 	for (i = 0; i < *outputCount; i++) {
5585e13b1fa5SApple OSS Distributions 		output[i] = SCALAR32(_output[i]);
5586a5e72196SApple OSS Distributions 	}
5587e13b1fa5SApple OSS Distributions 
5588a5e72196SApple OSS Distributions 	return err;
5589e13b1fa5SApple OSS Distributions }
5590e13b1fa5SApple OSS Distributions 
5591e13b1fa5SApple OSS Distributions 
5592c1dac77fSApple OSS Distributions /* Routine io_connect_method_scalarI_structureO */
5593a5e72196SApple OSS Distributions kern_return_t
is_io_connect_method_scalarI_structureO(io_object_t connect,uint32_t index,io_scalar_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t output,mach_msg_type_number_t * outputCount)5594a5e72196SApple OSS Distributions is_io_connect_method_scalarI_structureO(
5595c1dac77fSApple OSS Distributions 	io_object_t     connect,
5596e13b1fa5SApple OSS Distributions 	uint32_t        index,
5597e13b1fa5SApple OSS Distributions 	io_scalar_inband_t input,
5598e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5599e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
5600e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *        outputCount )
5601c1dac77fSApple OSS Distributions {
5602e13b1fa5SApple OSS Distributions 	uint32_t i;
5603e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _input;
5604e13b1fa5SApple OSS Distributions 
5605e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_outputCnt = 0;
5606e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5607e13b1fa5SApple OSS Distributions 
5608a5e72196SApple OSS Distributions 	for (i = 0; i < inputCount; i++) {
5609e13b1fa5SApple OSS Distributions 		_input[i] = SCALAR64(input[i]);
5610a5e72196SApple OSS Distributions 	}
5611e13b1fa5SApple OSS Distributions 
5612a5e72196SApple OSS Distributions 	return is_io_connect_method(connect, index,
5613e13b1fa5SApple OSS Distributions 	           _input, inputCount,
5614e13b1fa5SApple OSS Distributions 	           NULL, 0,
5615e13b1fa5SApple OSS Distributions 	           0, 0,
5616e13b1fa5SApple OSS Distributions 	           output, outputCount,
5617855239e5SApple OSS Distributions 	           NULL, &scalar_outputCnt,
5618a5e72196SApple OSS Distributions 	           0, &ool_output_size);
5619e13b1fa5SApple OSS Distributions }
5620e13b1fa5SApple OSS Distributions 
5621a5e72196SApple OSS Distributions kern_return_t
shim_io_connect_method_scalarI_structureO(IOExternalMethod * method,IOService * object,const io_user_scalar_t * input,mach_msg_type_number_t inputCount,io_struct_inband_t output,IOByteCount * outputCount)5622a5e72196SApple OSS Distributions shim_io_connect_method_scalarI_structureO(
5623e13b1fa5SApple OSS Distributions 
5624e13b1fa5SApple OSS Distributions 	IOExternalMethod *      method,
5625e13b1fa5SApple OSS Distributions 	IOService *             object,
5626e13b1fa5SApple OSS Distributions 	const io_user_scalar_t * input,
5627e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5628e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
56293ca3bd55SApple OSS Distributions 	IOByteCount *   outputCount )
5630e13b1fa5SApple OSS Distributions {
5631c1dac77fSApple OSS Distributions 	IOMethod            func;
5632e13b1fa5SApple OSS Distributions 	IOReturn            err;
5633c1dac77fSApple OSS Distributions 
5634c1dac77fSApple OSS Distributions 	err = kIOReturnBadArgument;
5635e13b1fa5SApple OSS Distributions 
5636e13b1fa5SApple OSS Distributions 	do {
5637a5e72196SApple OSS Distributions 		if (inputCount != method->count0) {
563888cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
563988cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
5640c1dac77fSApple OSS Distributions 			continue;
5641e13b1fa5SApple OSS Distributions 		}
5642e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count1)
5643a5e72196SApple OSS Distributions 		    && (*outputCount != method->count1)) {
564488cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
564588cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
5646c1dac77fSApple OSS Distributions 			continue;
5647e13b1fa5SApple OSS Distributions 		}
5648c1dac77fSApple OSS Distributions 
5649c1dac77fSApple OSS Distributions 		func = method->func;
5650c1dac77fSApple OSS Distributions 
5651c1dac77fSApple OSS Distributions 		switch (inputCount) {
5652c1dac77fSApple OSS Distributions 		case 5:
5653e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5654e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]),
5655c1dac77fSApple OSS Distributions 			    output );
5656c1dac77fSApple OSS Distributions 			break;
5657c1dac77fSApple OSS Distributions 		case 4:
5658e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5659e13b1fa5SApple OSS Distributions 			    ARG32(input[3]),
5660c1dac77fSApple OSS Distributions 			    output, (void *)outputCount );
5661c1dac77fSApple OSS Distributions 			break;
5662c1dac77fSApple OSS Distributions 		case 3:
5663e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5664a5e72196SApple OSS Distributions 			    output, (void *)outputCount, NULL );
5665c1dac77fSApple OSS Distributions 			break;
5666c1dac77fSApple OSS Distributions 		case 2:
5667e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]), ARG32(input[1]),
5668a5e72196SApple OSS Distributions 			    output, (void *)outputCount, NULL, NULL );
5669c1dac77fSApple OSS Distributions 			break;
5670c1dac77fSApple OSS Distributions 		case 1:
5671e13b1fa5SApple OSS Distributions 			err = (object->*func)(  ARG32(input[0]),
5672a5e72196SApple OSS Distributions 			    output, (void *)outputCount, NULL, NULL, NULL );
5673c1dac77fSApple OSS Distributions 			break;
5674c1dac77fSApple OSS Distributions 		case 0:
5675a5e72196SApple OSS Distributions 			err = (object->*func)(  output, (void *)outputCount, NULL, NULL, NULL, NULL );
5676c1dac77fSApple OSS Distributions 			break;
5677c1dac77fSApple OSS Distributions 
5678c1dac77fSApple OSS Distributions 		default:
5679e13b1fa5SApple OSS Distributions 			IOLog("%s: Bad method table\n", object->getName());
5680c1dac77fSApple OSS Distributions 		}
5681a5e72196SApple OSS Distributions 	}while (false);
5682c1dac77fSApple OSS Distributions 
5683a5e72196SApple OSS Distributions 	return err;
5684e13b1fa5SApple OSS Distributions }
5685e13b1fa5SApple OSS Distributions 
5686e13b1fa5SApple OSS Distributions 
5687a5e72196SApple OSS Distributions kern_return_t
shim_io_async_method_scalarI_structureO(IOExternalAsyncMethod * method,IOService * object,mach_port_t asyncWakePort,io_user_reference_t * asyncReference,uint32_t asyncReferenceCount,const io_user_scalar_t * input,mach_msg_type_number_t inputCount,io_struct_inband_t output,mach_msg_type_number_t * outputCount)5688a5e72196SApple OSS Distributions shim_io_async_method_scalarI_structureO(
5689e13b1fa5SApple OSS Distributions 	IOExternalAsyncMethod * method,
5690e13b1fa5SApple OSS Distributions 	IOService *             object,
5691e13b1fa5SApple OSS Distributions 	mach_port_t             asyncWakePort,
5692e13b1fa5SApple OSS Distributions 	io_user_reference_t *   asyncReference,
5693e13b1fa5SApple OSS Distributions 	uint32_t                asyncReferenceCount,
5694e13b1fa5SApple OSS Distributions 	const io_user_scalar_t * input,
5695e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5696e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
5697e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *        outputCount )
5698e13b1fa5SApple OSS Distributions {
5699e13b1fa5SApple OSS Distributions 	IOAsyncMethod       func;
5700e13b1fa5SApple OSS Distributions 	uint32_t            i;
5701e13b1fa5SApple OSS Distributions 	IOReturn            err;
5702e13b1fa5SApple OSS Distributions 	io_async_ref_t      reference;
5703e13b1fa5SApple OSS Distributions 
5704a5e72196SApple OSS Distributions 	for (i = 0; i < asyncReferenceCount; i++) {
5705e13b1fa5SApple OSS Distributions 		reference[i] = REF32(asyncReference[i]);
5706a5e72196SApple OSS Distributions 	}
5707e13b1fa5SApple OSS Distributions 
5708e13b1fa5SApple OSS Distributions 	err = kIOReturnBadArgument;
5709e13b1fa5SApple OSS Distributions 	do {
5710a5e72196SApple OSS Distributions 		if (inputCount != method->count0) {
571188cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
571288cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
5713e13b1fa5SApple OSS Distributions 			continue;
5714e13b1fa5SApple OSS Distributions 		}
5715e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count1)
5716a5e72196SApple OSS Distributions 		    && (*outputCount != method->count1)) {
571788cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
571888cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
5719e13b1fa5SApple OSS Distributions 			continue;
5720e13b1fa5SApple OSS Distributions 		}
5721e13b1fa5SApple OSS Distributions 
5722e13b1fa5SApple OSS Distributions 		func = method->func;
5723e13b1fa5SApple OSS Distributions 
5724e13b1fa5SApple OSS Distributions 		switch (inputCount) {
5725e13b1fa5SApple OSS Distributions 		case 5:
5726e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5727e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5728e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]),
5729e13b1fa5SApple OSS Distributions 			    output );
5730e13b1fa5SApple OSS Distributions 			break;
5731e13b1fa5SApple OSS Distributions 		case 4:
5732e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5733e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5734e13b1fa5SApple OSS Distributions 			    ARG32(input[3]),
5735e13b1fa5SApple OSS Distributions 			    output, (void *)outputCount );
5736e13b1fa5SApple OSS Distributions 			break;
5737e13b1fa5SApple OSS Distributions 		case 3:
5738e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5739e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5740a5e72196SApple OSS Distributions 			    output, (void *)outputCount, NULL );
5741e13b1fa5SApple OSS Distributions 			break;
5742e13b1fa5SApple OSS Distributions 		case 2:
5743e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5744e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]),
5745a5e72196SApple OSS Distributions 			    output, (void *)outputCount, NULL, NULL );
5746e13b1fa5SApple OSS Distributions 			break;
5747e13b1fa5SApple OSS Distributions 		case 1:
5748e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5749e13b1fa5SApple OSS Distributions 			    ARG32(input[0]),
5750a5e72196SApple OSS Distributions 			    output, (void *)outputCount, NULL, NULL, NULL );
5751e13b1fa5SApple OSS Distributions 			break;
5752e13b1fa5SApple OSS Distributions 		case 0:
5753e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5754a5e72196SApple OSS Distributions 			    output, (void *)outputCount, NULL, NULL, NULL, NULL );
5755e13b1fa5SApple OSS Distributions 			break;
5756e13b1fa5SApple OSS Distributions 
5757e13b1fa5SApple OSS Distributions 		default:
5758e13b1fa5SApple OSS Distributions 			IOLog("%s: Bad method table\n", object->getName());
5759e13b1fa5SApple OSS Distributions 		}
5760a5e72196SApple OSS Distributions 	}while (false);
5761c1dac77fSApple OSS Distributions 
5762a5e72196SApple OSS Distributions 	return err;
5763c1dac77fSApple OSS Distributions }
5764c1dac77fSApple OSS Distributions 
5765c1dac77fSApple OSS Distributions /* Routine io_connect_method_scalarI_structureI */
5766a5e72196SApple OSS Distributions kern_return_t
is_io_connect_method_scalarI_structureI(io_connect_t connect,uint32_t index,io_scalar_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t inputStruct,mach_msg_type_number_t inputStructCount)5767a5e72196SApple OSS Distributions is_io_connect_method_scalarI_structureI(
5768c1dac77fSApple OSS Distributions 	io_connect_t            connect,
5769e13b1fa5SApple OSS Distributions 	uint32_t                index,
5770e13b1fa5SApple OSS Distributions 	io_scalar_inband_t      input,
5771e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5772e13b1fa5SApple OSS Distributions 	io_struct_inband_t      inputStruct,
5773e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputStructCount )
5774c1dac77fSApple OSS Distributions {
5775e13b1fa5SApple OSS Distributions 	uint32_t i;
5776e13b1fa5SApple OSS Distributions 	io_scalar_inband64_t _input;
5777e13b1fa5SApple OSS Distributions 
5778e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_outputCnt = 0;
5779e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t inband_outputCnt = 0;
5780e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5781e13b1fa5SApple OSS Distributions 
5782a5e72196SApple OSS Distributions 	for (i = 0; i < inputCount; i++) {
5783e13b1fa5SApple OSS Distributions 		_input[i] = SCALAR64(input[i]);
5784a5e72196SApple OSS Distributions 	}
5785e13b1fa5SApple OSS Distributions 
5786a5e72196SApple OSS Distributions 	return is_io_connect_method(connect, index,
5787e13b1fa5SApple OSS Distributions 	           _input, inputCount,
5788e13b1fa5SApple OSS Distributions 	           inputStruct, inputStructCount,
5789e13b1fa5SApple OSS Distributions 	           0, 0,
5790e13b1fa5SApple OSS Distributions 	           NULL, &inband_outputCnt,
5791855239e5SApple OSS Distributions 	           NULL, &scalar_outputCnt,
5792a5e72196SApple OSS Distributions 	           0, &ool_output_size);
5793e13b1fa5SApple OSS Distributions }
5794e13b1fa5SApple OSS Distributions 
5795a5e72196SApple OSS Distributions kern_return_t
shim_io_connect_method_scalarI_structureI(IOExternalMethod * method,IOService * object,const io_user_scalar_t * input,mach_msg_type_number_t inputCount,io_struct_inband_t inputStruct,mach_msg_type_number_t inputStructCount)5796a5e72196SApple OSS Distributions shim_io_connect_method_scalarI_structureI(
5797e13b1fa5SApple OSS Distributions 	IOExternalMethod *  method,
5798e13b1fa5SApple OSS Distributions 	IOService *         object,
5799e13b1fa5SApple OSS Distributions 	const io_user_scalar_t * input,
5800e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5801e13b1fa5SApple OSS Distributions 	io_struct_inband_t              inputStruct,
5802e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputStructCount )
5803e13b1fa5SApple OSS Distributions {
5804c1dac77fSApple OSS Distributions 	IOMethod            func;
5805e13b1fa5SApple OSS Distributions 	IOReturn            err = kIOReturnBadArgument;
5806c1dac77fSApple OSS Distributions 
5807a5e72196SApple OSS Distributions 	do{
5808a5e72196SApple OSS Distributions 		if (inputCount != method->count0) {
580988cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
581088cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
5811c1dac77fSApple OSS Distributions 			continue;
5812e13b1fa5SApple OSS Distributions 		}
5813e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count1)
5814a5e72196SApple OSS Distributions 		    && (inputStructCount != method->count1)) {
581588cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputStructCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
581688cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputStructCount, uint64_t, (uint64_t)method->count1);
5817c1dac77fSApple OSS Distributions 			continue;
5818e13b1fa5SApple OSS Distributions 		}
5819c1dac77fSApple OSS Distributions 
5820c1dac77fSApple OSS Distributions 		func = method->func;
5821c1dac77fSApple OSS Distributions 
5822c1dac77fSApple OSS Distributions 		switch (inputCount) {
5823c1dac77fSApple OSS Distributions 		case 5:
5824e13b1fa5SApple OSS Distributions 			err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5825e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]),
5826c1dac77fSApple OSS Distributions 			    inputStruct );
5827c1dac77fSApple OSS Distributions 			break;
5828c1dac77fSApple OSS Distributions 		case 4:
5829e13b1fa5SApple OSS Distributions 			err = (object->*func)( ARG32(input[0]), ARG32(input[1]), (void *)  input[2],
5830e13b1fa5SApple OSS Distributions 			    ARG32(input[3]),
5831186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount );
5832c1dac77fSApple OSS Distributions 			break;
5833c1dac77fSApple OSS Distributions 		case 3:
5834e13b1fa5SApple OSS Distributions 			err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5835186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount,
5836a5e72196SApple OSS Distributions 			    NULL );
5837c1dac77fSApple OSS Distributions 			break;
5838c1dac77fSApple OSS Distributions 		case 2:
5839e13b1fa5SApple OSS Distributions 			err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
5840186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount,
5841a5e72196SApple OSS Distributions 			    NULL, NULL );
5842c1dac77fSApple OSS Distributions 			break;
5843c1dac77fSApple OSS Distributions 		case 1:
5844e13b1fa5SApple OSS Distributions 			err = (object->*func)( ARG32(input[0]),
5845186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount,
5846a5e72196SApple OSS Distributions 			    NULL, NULL, NULL );
5847c1dac77fSApple OSS Distributions 			break;
5848c1dac77fSApple OSS Distributions 		case 0:
5849186b8fceSApple OSS Distributions 			err = (object->*func)( inputStruct, (void *)(uintptr_t)inputStructCount,
5850a5e72196SApple OSS Distributions 			    NULL, NULL, NULL, NULL );
5851c1dac77fSApple OSS Distributions 			break;
5852c1dac77fSApple OSS Distributions 
5853c1dac77fSApple OSS Distributions 		default:
5854e13b1fa5SApple OSS Distributions 			IOLog("%s: Bad method table\n", object->getName());
5855c1dac77fSApple OSS Distributions 		}
5856a5e72196SApple OSS Distributions 	}while (false);
5857c1dac77fSApple OSS Distributions 
5858a5e72196SApple OSS Distributions 	return err;
5859e13b1fa5SApple OSS Distributions }
5860e13b1fa5SApple OSS Distributions 
5861a5e72196SApple OSS Distributions kern_return_t
shim_io_async_method_scalarI_structureI(IOExternalAsyncMethod * method,IOService * object,mach_port_t asyncWakePort,io_user_reference_t * asyncReference,uint32_t asyncReferenceCount,const io_user_scalar_t * input,mach_msg_type_number_t inputCount,io_struct_inband_t inputStruct,mach_msg_type_number_t inputStructCount)5862a5e72196SApple OSS Distributions shim_io_async_method_scalarI_structureI(
5863e13b1fa5SApple OSS Distributions 	IOExternalAsyncMethod * method,
5864e13b1fa5SApple OSS Distributions 	IOService *             object,
5865e13b1fa5SApple OSS Distributions 	mach_port_t             asyncWakePort,
5866e13b1fa5SApple OSS Distributions 	io_user_reference_t *   asyncReference,
5867e13b1fa5SApple OSS Distributions 	uint32_t                asyncReferenceCount,
5868e13b1fa5SApple OSS Distributions 	const io_user_scalar_t * input,
5869e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5870e13b1fa5SApple OSS Distributions 	io_struct_inband_t              inputStruct,
5871e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputStructCount )
5872e13b1fa5SApple OSS Distributions {
5873e13b1fa5SApple OSS Distributions 	IOAsyncMethod       func;
5874e13b1fa5SApple OSS Distributions 	uint32_t            i;
5875e13b1fa5SApple OSS Distributions 	IOReturn            err = kIOReturnBadArgument;
5876e13b1fa5SApple OSS Distributions 	io_async_ref_t      reference;
5877e13b1fa5SApple OSS Distributions 
5878a5e72196SApple OSS Distributions 	for (i = 0; i < asyncReferenceCount; i++) {
5879e13b1fa5SApple OSS Distributions 		reference[i] = REF32(asyncReference[i]);
5880a5e72196SApple OSS Distributions 	}
5881e13b1fa5SApple OSS Distributions 
5882a5e72196SApple OSS Distributions 	do{
5883a5e72196SApple OSS Distributions 		if (inputCount != method->count0) {
588488cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
588588cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
5886e13b1fa5SApple OSS Distributions 			continue;
5887e13b1fa5SApple OSS Distributions 		}
5888e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count1)
5889a5e72196SApple OSS Distributions 		    && (inputStructCount != method->count1)) {
589088cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputStructCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
589188cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputStructCount, uint64_t, (uint64_t)method->count1);
5892e13b1fa5SApple OSS Distributions 			continue;
5893e13b1fa5SApple OSS Distributions 		}
5894e13b1fa5SApple OSS Distributions 
5895e13b1fa5SApple OSS Distributions 		func = method->func;
5896e13b1fa5SApple OSS Distributions 
5897e13b1fa5SApple OSS Distributions 		switch (inputCount) {
5898e13b1fa5SApple OSS Distributions 		case 5:
5899e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5900e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5901e13b1fa5SApple OSS Distributions 			    ARG32(input[3]), ARG32(input[4]),
5902e13b1fa5SApple OSS Distributions 			    inputStruct );
5903e13b1fa5SApple OSS Distributions 			break;
5904e13b1fa5SApple OSS Distributions 		case 4:
5905e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5906e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5907e13b1fa5SApple OSS Distributions 			    ARG32(input[3]),
5908186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount );
5909e13b1fa5SApple OSS Distributions 			break;
5910e13b1fa5SApple OSS Distributions 		case 3:
5911e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5912e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
5913186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount,
5914a5e72196SApple OSS Distributions 			    NULL );
5915e13b1fa5SApple OSS Distributions 			break;
5916e13b1fa5SApple OSS Distributions 		case 2:
5917e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5918e13b1fa5SApple OSS Distributions 			    ARG32(input[0]), ARG32(input[1]),
5919186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount,
5920a5e72196SApple OSS Distributions 			    NULL, NULL );
5921e13b1fa5SApple OSS Distributions 			break;
5922e13b1fa5SApple OSS Distributions 		case 1:
5923e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5924e13b1fa5SApple OSS Distributions 			    ARG32(input[0]),
5925186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount,
5926a5e72196SApple OSS Distributions 			    NULL, NULL, NULL );
5927e13b1fa5SApple OSS Distributions 			break;
5928e13b1fa5SApple OSS Distributions 		case 0:
5929e13b1fa5SApple OSS Distributions 			err = (object->*func)(  reference,
5930186b8fceSApple OSS Distributions 			    inputStruct, (void *)(uintptr_t)inputStructCount,
5931a5e72196SApple OSS Distributions 			    NULL, NULL, NULL, NULL );
5932e13b1fa5SApple OSS Distributions 			break;
5933e13b1fa5SApple OSS Distributions 
5934e13b1fa5SApple OSS Distributions 		default:
5935e13b1fa5SApple OSS Distributions 			IOLog("%s: Bad method table\n", object->getName());
5936e13b1fa5SApple OSS Distributions 		}
5937a5e72196SApple OSS Distributions 	}while (false);
5938c1dac77fSApple OSS Distributions 
5939a5e72196SApple OSS Distributions 	return err;
5940c1dac77fSApple OSS Distributions }
5941c1dac77fSApple OSS Distributions 
5942c1dac77fSApple OSS Distributions /* Routine io_connect_method_structureI_structureO */
5943a5e72196SApple OSS Distributions kern_return_t
is_io_connect_method_structureI_structureO(io_object_t connect,uint32_t index,io_struct_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t output,mach_msg_type_number_t * outputCount)5944a5e72196SApple OSS Distributions is_io_connect_method_structureI_structureO(
5945c1dac77fSApple OSS Distributions 	io_object_t     connect,
5946e13b1fa5SApple OSS Distributions 	uint32_t        index,
5947e13b1fa5SApple OSS Distributions 	io_struct_inband_t              input,
5948e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5949e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
5950e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *        outputCount )
5951c1dac77fSApple OSS Distributions {
5952e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t scalar_outputCnt = 0;
5953e13b1fa5SApple OSS Distributions 	mach_vm_size_t ool_output_size = 0;
5954e13b1fa5SApple OSS Distributions 
5955a5e72196SApple OSS Distributions 	return is_io_connect_method(connect, index,
5956e13b1fa5SApple OSS Distributions 	           NULL, 0,
5957e13b1fa5SApple OSS Distributions 	           input, inputCount,
5958e13b1fa5SApple OSS Distributions 	           0, 0,
5959e13b1fa5SApple OSS Distributions 	           output, outputCount,
5960855239e5SApple OSS Distributions 	           NULL, &scalar_outputCnt,
5961a5e72196SApple OSS Distributions 	           0, &ool_output_size);
5962e13b1fa5SApple OSS Distributions }
5963e13b1fa5SApple OSS Distributions 
5964a5e72196SApple OSS Distributions kern_return_t
shim_io_connect_method_structureI_structureO(IOExternalMethod * method,IOService * object,io_struct_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t output,IOByteCount * outputCount)5965a5e72196SApple OSS Distributions shim_io_connect_method_structureI_structureO(
5966e13b1fa5SApple OSS Distributions 	IOExternalMethod *  method,
5967e13b1fa5SApple OSS Distributions 	IOService *         object,
5968e13b1fa5SApple OSS Distributions 	io_struct_inband_t              input,
5969e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
5970e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
59713ca3bd55SApple OSS Distributions 	IOByteCount *   outputCount )
5972e13b1fa5SApple OSS Distributions {
5973c1dac77fSApple OSS Distributions 	IOMethod            func;
5974e13b1fa5SApple OSS Distributions 	IOReturn            err = kIOReturnBadArgument;
5975c1dac77fSApple OSS Distributions 
5976a5e72196SApple OSS Distributions 	do{
5977e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count0)
5978a5e72196SApple OSS Distributions 		    && (inputCount != method->count0)) {
597988cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0, (uint64_t)kIOUCVariableStructureSize);
598088cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
5981c1dac77fSApple OSS Distributions 			continue;
5982e13b1fa5SApple OSS Distributions 		}
5983e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count1)
5984a5e72196SApple OSS Distributions 		    && (*outputCount != method->count1)) {
598588cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
598688cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
5987c1dac77fSApple OSS Distributions 			continue;
5988e13b1fa5SApple OSS Distributions 		}
5989c1dac77fSApple OSS Distributions 
5990c1dac77fSApple OSS Distributions 		func = method->func;
5991c1dac77fSApple OSS Distributions 
5992c1dac77fSApple OSS Distributions 		if (method->count1) {
5993c1dac77fSApple OSS Distributions 			if (method->count0) {
5994c1dac77fSApple OSS Distributions 				err = (object->*func)( input, output,
5995a5e72196SApple OSS Distributions 				    (void *)(uintptr_t)inputCount, outputCount, NULL, NULL );
5996c1dac77fSApple OSS Distributions 			} else {
5997a5e72196SApple OSS Distributions 				err = (object->*func)( output, outputCount, NULL, NULL, NULL, NULL );
5998c1dac77fSApple OSS Distributions 			}
5999c1dac77fSApple OSS Distributions 		} else {
6000a5e72196SApple OSS Distributions 			err = (object->*func)( input, (void *)(uintptr_t)inputCount, NULL, NULL, NULL, NULL );
6001c1dac77fSApple OSS Distributions 		}
6002a5e72196SApple OSS Distributions 	}while (false);
6003c1dac77fSApple OSS Distributions 
6004c1dac77fSApple OSS Distributions 
6005a5e72196SApple OSS Distributions 	return err;
6006c1dac77fSApple OSS Distributions }
6007c1dac77fSApple OSS Distributions 
6008a5e72196SApple OSS Distributions kern_return_t
shim_io_async_method_structureI_structureO(IOExternalAsyncMethod * method,IOService * object,mach_port_t asyncWakePort,io_user_reference_t * asyncReference,uint32_t asyncReferenceCount,io_struct_inband_t input,mach_msg_type_number_t inputCount,io_struct_inband_t output,mach_msg_type_number_t * outputCount)6009a5e72196SApple OSS Distributions shim_io_async_method_structureI_structureO(
6010e13b1fa5SApple OSS Distributions 	IOExternalAsyncMethod * method,
6011e13b1fa5SApple OSS Distributions 	IOService *             object,
6012e13b1fa5SApple OSS Distributions 	mach_port_t           asyncWakePort,
6013e13b1fa5SApple OSS Distributions 	io_user_reference_t * asyncReference,
6014e13b1fa5SApple OSS Distributions 	uint32_t              asyncReferenceCount,
6015e13b1fa5SApple OSS Distributions 	io_struct_inband_t              input,
6016e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t  inputCount,
6017e13b1fa5SApple OSS Distributions 	io_struct_inband_t              output,
6018e13b1fa5SApple OSS Distributions 	mach_msg_type_number_t *        outputCount )
6019c1dac77fSApple OSS Distributions {
6020c1dac77fSApple OSS Distributions 	IOAsyncMethod       func;
6021e13b1fa5SApple OSS Distributions 	uint32_t            i;
6022e13b1fa5SApple OSS Distributions 	IOReturn            err;
6023e13b1fa5SApple OSS Distributions 	io_async_ref_t      reference;
6024c1dac77fSApple OSS Distributions 
6025a5e72196SApple OSS Distributions 	for (i = 0; i < asyncReferenceCount; i++) {
6026e13b1fa5SApple OSS Distributions 		reference[i] = REF32(asyncReference[i]);
6027a5e72196SApple OSS Distributions 	}
6028e13b1fa5SApple OSS Distributions 
6029c1dac77fSApple OSS Distributions 	err = kIOReturnBadArgument;
6030a5e72196SApple OSS Distributions 	do{
6031e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count0)
6032a5e72196SApple OSS Distributions 		    && (inputCount != method->count0)) {
603388cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0, (uint64_t)kIOUCVariableStructureSize);
603488cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
6035c1dac77fSApple OSS Distributions 			continue;
6036e13b1fa5SApple OSS Distributions 		}
6037e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != method->count1)
6038a5e72196SApple OSS Distributions 		    && (*outputCount != method->count1)) {
603988cc0b97SApple OSS Distributions 			IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
604088cc0b97SApple OSS Distributions 			DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
6041c1dac77fSApple OSS Distributions 			continue;
6042e13b1fa5SApple OSS Distributions 		}
6043c1dac77fSApple OSS Distributions 
6044c1dac77fSApple OSS Distributions 		func = method->func;
6045c1dac77fSApple OSS Distributions 
6046c1dac77fSApple OSS Distributions 		if (method->count1) {
6047c1dac77fSApple OSS Distributions 			if (method->count0) {
6048c1dac77fSApple OSS Distributions 				err = (object->*func)( reference,
6049c1dac77fSApple OSS Distributions 				    input, output,
6050a5e72196SApple OSS Distributions 				    (void *)(uintptr_t)inputCount, outputCount, NULL, NULL );
6051c1dac77fSApple OSS Distributions 			} else {
6052c1dac77fSApple OSS Distributions 				err = (object->*func)( reference,
6053a5e72196SApple OSS Distributions 				    output, outputCount, NULL, NULL, NULL, NULL );
6054c1dac77fSApple OSS Distributions 			}
6055c1dac77fSApple OSS Distributions 		} else {
6056c1dac77fSApple OSS Distributions 			err = (object->*func)( reference,
6057a5e72196SApple OSS Distributions 			    input, (void *)(uintptr_t)inputCount, NULL, NULL, NULL, NULL );
6058c1dac77fSApple OSS Distributions 		}
6059a5e72196SApple OSS Distributions 	}while (false);
6060c1dac77fSApple OSS Distributions 
6061a5e72196SApple OSS Distributions 	return err;
6062c1dac77fSApple OSS Distributions }
6063e13b1fa5SApple OSS Distributions 
6064c1dac77fSApple OSS Distributions /* Routine io_catalog_send_data */
6065a5e72196SApple OSS Distributions kern_return_t
is_io_catalog_send_data(mach_port_t main_port,uint32_t flag,io_buf_ptr_t inData,mach_msg_type_number_t inDataCount,kern_return_t * result)6066a5e72196SApple OSS Distributions is_io_catalog_send_data(
60675c2921b0SApple OSS Distributions 	mach_port_t             main_port,
6068e13b1fa5SApple OSS Distributions 	uint32_t                flag,
6069c1dac77fSApple OSS Distributions 	io_buf_ptr_t            inData,
6070c1dac77fSApple OSS Distributions 	mach_msg_type_number_t  inDataCount,
6071e13b1fa5SApple OSS Distributions 	kern_return_t *         result)
6072c1dac77fSApple OSS Distributions {
6073e6231be0SApple OSS Distributions 	// Allow sending catalog data if there is no kextd and the kernel is DEVELOPMENT || DEBUG
6074e6231be0SApple OSS Distributions #if NO_KEXTD && !(DEVELOPMENT || DEBUG)
607576e12aa3SApple OSS Distributions 	return kIOReturnNotPrivileged;
6076e6231be0SApple OSS Distributions #else /* NO_KEXTD && !(DEVELOPMENT || DEBUG) */
6077a5e72196SApple OSS Distributions 	OSObject * obj = NULL;
6078c1dac77fSApple OSS Distributions 	vm_offset_t data;
6079c1dac77fSApple OSS Distributions 	kern_return_t kr = kIOReturnError;
6080c1dac77fSApple OSS Distributions 
6081c1dac77fSApple OSS Distributions 	//printf("io_catalog_send_data called. flag: %d\n", flag);
6082c1dac77fSApple OSS Distributions 
60835c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
6084c1dac77fSApple OSS Distributions 		return kIOReturnNotPrivileged;
6085a5e72196SApple OSS Distributions 	}
6086c1dac77fSApple OSS Distributions 
6087a5e72196SApple OSS Distributions 	if ((flag != kIOCatalogRemoveKernelLinker__Removed &&
60883ca3bd55SApple OSS Distributions 	    flag != kIOCatalogKextdActive &&
60893ca3bd55SApple OSS Distributions 	    flag != kIOCatalogKextdFinishedLaunching) &&
6090a5e72196SApple OSS Distributions 	    (!inData || !inDataCount)) {
6091c1dac77fSApple OSS Distributions 		return kIOReturnBadArgument;
60923ca3bd55SApple OSS Distributions 	}
6093c1dac77fSApple OSS Distributions 
6094e6231be0SApple OSS Distributions 	if (!IOCurrentTaskHasEntitlement(kIOCatalogManagementEntitlement)) {
609576e12aa3SApple OSS Distributions 		OSString * taskName = IOCopyLogNameForPID(proc_selfpid());
609676e12aa3SApple OSS Distributions 		IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName ? taskName->getCStringNoCopy() : "");
609776e12aa3SApple OSS Distributions 		OSSafeReleaseNULL(taskName);
609876e12aa3SApple OSS Distributions 		// For now, fake success to not break applications relying on this function succeeding.
609976e12aa3SApple OSS Distributions 		// See <rdar://problem/32554970> for more details.
610076e12aa3SApple OSS Distributions 		return kIOReturnSuccess;
610176e12aa3SApple OSS Distributions 	}
610276e12aa3SApple OSS Distributions 
610314e3d835SApple OSS Distributions 	if (inData) {
610414e3d835SApple OSS Distributions 		vm_map_offset_t map_data;
610514e3d835SApple OSS Distributions 
6106a5e72196SApple OSS Distributions 		if (inDataCount > sizeof(io_struct_inband_t) * 1024) {
6107a5e72196SApple OSS Distributions 			return kIOReturnMessageTooLarge;
6108a5e72196SApple OSS Distributions 		}
6109186b8fceSApple OSS Distributions 
611014e3d835SApple OSS Distributions 		kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData);
611114e3d835SApple OSS Distributions 		data = CAST_DOWN(vm_offset_t, map_data);
611214e3d835SApple OSS Distributions 
6113a5e72196SApple OSS Distributions 		if (kr != KERN_SUCCESS) {
6114c1dac77fSApple OSS Distributions 			return kr;
6115a5e72196SApple OSS Distributions 		}
6116c1dac77fSApple OSS Distributions 
6117c1dac77fSApple OSS Distributions 		// must return success after vm_map_copyout() succeeds
6118c1dac77fSApple OSS Distributions 
6119c1dac77fSApple OSS Distributions 		if (inDataCount) {
6120186b8fceSApple OSS Distributions 			obj = (OSObject *)OSUnserializeXML((const char *)data, inDataCount);
6121c1dac77fSApple OSS Distributions 			vm_deallocate( kernel_map, data, inDataCount );
6122c1dac77fSApple OSS Distributions 			if (!obj) {
6123c1dac77fSApple OSS Distributions 				*result = kIOReturnNoMemory;
6124a5e72196SApple OSS Distributions 				return KERN_SUCCESS;
6125c1dac77fSApple OSS Distributions 			}
6126c1dac77fSApple OSS Distributions 		}
6127c1dac77fSApple OSS Distributions 	}
6128c1dac77fSApple OSS Distributions 
6129c1dac77fSApple OSS Distributions 	switch (flag) {
6130855239e5SApple OSS Distributions 	case kIOCatalogResetDrivers:
6131855239e5SApple OSS Distributions 	case kIOCatalogResetDriversNoMatch: {
6132855239e5SApple OSS Distributions 		OSArray * array;
6133855239e5SApple OSS Distributions 
6134855239e5SApple OSS Distributions 		array = OSDynamicCast(OSArray, obj);
6135855239e5SApple OSS Distributions 		if (array) {
6136855239e5SApple OSS Distributions 			if (!gIOCatalogue->resetAndAddDrivers(array,
6137855239e5SApple OSS Distributions 			    flag == kIOCatalogResetDrivers)) {
6138855239e5SApple OSS Distributions 				kr = kIOReturnError;
6139855239e5SApple OSS Distributions 			}
6140855239e5SApple OSS Distributions 		} else {
6141855239e5SApple OSS Distributions 			kr = kIOReturnBadArgument;
6142855239e5SApple OSS Distributions 		}
6143855239e5SApple OSS Distributions 	}
6144855239e5SApple OSS Distributions 	break;
6145855239e5SApple OSS Distributions 
6146c1dac77fSApple OSS Distributions 	case kIOCatalogAddDrivers:
6147c1dac77fSApple OSS Distributions 	case kIOCatalogAddDriversNoMatch: {
6148c1dac77fSApple OSS Distributions 		OSArray * array;
6149c1dac77fSApple OSS Distributions 
6150c1dac77fSApple OSS Distributions 		array = OSDynamicCast(OSArray, obj);
6151c1dac77fSApple OSS Distributions 		if (array) {
6152c1dac77fSApple OSS Distributions 			if (!gIOCatalogue->addDrivers( array,
6153c1dac77fSApple OSS Distributions 			    flag == kIOCatalogAddDrivers)) {
6154c1dac77fSApple OSS Distributions 				kr = kIOReturnError;
6155c1dac77fSApple OSS Distributions 			}
6156a5e72196SApple OSS Distributions 		} else {
6157c1dac77fSApple OSS Distributions 			kr = kIOReturnBadArgument;
6158c1dac77fSApple OSS Distributions 		}
6159c1dac77fSApple OSS Distributions 	}
6160c1dac77fSApple OSS Distributions 	break;
6161c1dac77fSApple OSS Distributions 
6162c1dac77fSApple OSS Distributions 	case kIOCatalogRemoveDrivers:
6163c1dac77fSApple OSS Distributions 	case kIOCatalogRemoveDriversNoMatch: {
6164c1dac77fSApple OSS Distributions 		OSDictionary * dict;
6165c1dac77fSApple OSS Distributions 
6166c1dac77fSApple OSS Distributions 		dict = OSDynamicCast(OSDictionary, obj);
6167c1dac77fSApple OSS Distributions 		if (dict) {
6168c1dac77fSApple OSS Distributions 			if (!gIOCatalogue->removeDrivers( dict,
6169c1dac77fSApple OSS Distributions 			    flag == kIOCatalogRemoveDrivers )) {
6170c1dac77fSApple OSS Distributions 				kr = kIOReturnError;
6171c1dac77fSApple OSS Distributions 			}
6172a5e72196SApple OSS Distributions 		} else {
6173c1dac77fSApple OSS Distributions 			kr = kIOReturnBadArgument;
6174c1dac77fSApple OSS Distributions 		}
6175c1dac77fSApple OSS Distributions 	}
6176c1dac77fSApple OSS Distributions 	break;
6177c1dac77fSApple OSS Distributions 
6178a5e72196SApple OSS Distributions 	case kIOCatalogStartMatching__Removed:
6179a5e72196SApple OSS Distributions 	case kIOCatalogRemoveKernelLinker__Removed:
61803ca3bd55SApple OSS Distributions 	case kIOCatalogKextdActive:
6181bb611c8fSApple OSS Distributions 	case kIOCatalogKextdFinishedLaunching:
6182bb611c8fSApple OSS Distributions 		kr = KERN_NOT_SUPPORTED;
6183e13b1fa5SApple OSS Distributions 		break;
6184e13b1fa5SApple OSS Distributions 
6185c1dac77fSApple OSS Distributions 	default:
6186c1dac77fSApple OSS Distributions 		kr = kIOReturnBadArgument;
6187c1dac77fSApple OSS Distributions 		break;
6188c1dac77fSApple OSS Distributions 	}
6189c1dac77fSApple OSS Distributions 
6190a5e72196SApple OSS Distributions 	if (obj) {
6191a5e72196SApple OSS Distributions 		obj->release();
6192a5e72196SApple OSS Distributions 	}
6193c1dac77fSApple OSS Distributions 
6194c1dac77fSApple OSS Distributions 	*result = kr;
6195a5e72196SApple OSS Distributions 	return KERN_SUCCESS;
6196e6231be0SApple OSS Distributions #endif /* NO_KEXTD && !(DEVELOPMENT || DEBUG) */
6197c1dac77fSApple OSS Distributions }
6198c1dac77fSApple OSS Distributions 
6199c1dac77fSApple OSS Distributions /* Routine io_catalog_terminate */
6200a5e72196SApple OSS Distributions kern_return_t
is_io_catalog_terminate(mach_port_t main_port,uint32_t flag,io_name_t name)6201a5e72196SApple OSS Distributions is_io_catalog_terminate(
62025c2921b0SApple OSS Distributions 	mach_port_t main_port,
6203e13b1fa5SApple OSS Distributions 	uint32_t flag,
6204c1dac77fSApple OSS Distributions 	io_name_t name )
6205c1dac77fSApple OSS Distributions {
6206c1dac77fSApple OSS Distributions 	kern_return_t          kr;
6207c1dac77fSApple OSS Distributions 
62085c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
6209c1dac77fSApple OSS Distributions 		return kIOReturnNotPrivileged;
6210a5e72196SApple OSS Distributions 	}
6211c1dac77fSApple OSS Distributions 
6212c1dac77fSApple OSS Distributions 	kr = IOUserClient::clientHasPrivilege((void *) current_task(),
6213c1dac77fSApple OSS Distributions 	    kIOClientPrivilegeAdministrator );
6214a5e72196SApple OSS Distributions 	if (kIOReturnSuccess != kr) {
6215a5e72196SApple OSS Distributions 		return kr;
6216a5e72196SApple OSS Distributions 	}
6217c1dac77fSApple OSS Distributions 
6218c1dac77fSApple OSS Distributions 	switch (flag) {
6219855239e5SApple OSS Distributions #if !defined(SECURE_KERNEL)
6220c1dac77fSApple OSS Distributions 	case kIOCatalogServiceTerminate:
62215c2921b0SApple OSS Distributions 		kr = gIOCatalogue->terminateDrivers(NULL, name, false);
6222c1dac77fSApple OSS Distributions 		break;
6223c1dac77fSApple OSS Distributions 
6224c1dac77fSApple OSS Distributions 	case kIOCatalogModuleUnload:
6225c1dac77fSApple OSS Distributions 	case kIOCatalogModuleTerminate:
6226c1dac77fSApple OSS Distributions 		kr = gIOCatalogue->terminateDriversForModule(name,
6227c1dac77fSApple OSS Distributions 		    flag == kIOCatalogModuleUnload);
6228c1dac77fSApple OSS Distributions 		break;
6229855239e5SApple OSS Distributions #endif
6230c1dac77fSApple OSS Distributions 
6231c1dac77fSApple OSS Distributions 	default:
6232c1dac77fSApple OSS Distributions 		kr = kIOReturnBadArgument;
6233c1dac77fSApple OSS Distributions 		break;
6234c1dac77fSApple OSS Distributions 	}
6235c1dac77fSApple OSS Distributions 
6236a5e72196SApple OSS Distributions 	return kr;
6237c1dac77fSApple OSS Distributions }
6238c1dac77fSApple OSS Distributions 
6239c1dac77fSApple OSS Distributions /* Routine io_catalog_get_data */
6240a5e72196SApple OSS Distributions kern_return_t
is_io_catalog_get_data(mach_port_t main_port,uint32_t flag,io_buf_ptr_t * outData,mach_msg_type_number_t * outDataCount)6241a5e72196SApple OSS Distributions is_io_catalog_get_data(
62425c2921b0SApple OSS Distributions 	mach_port_t             main_port,
6243e13b1fa5SApple OSS Distributions 	uint32_t                flag,
6244c1dac77fSApple OSS Distributions 	io_buf_ptr_t            *outData,
6245c1dac77fSApple OSS Distributions 	mach_msg_type_number_t  *outDataCount)
6246c1dac77fSApple OSS Distributions {
6247c1dac77fSApple OSS Distributions 	kern_return_t kr = kIOReturnSuccess;
6248c1dac77fSApple OSS Distributions 	OSSerialize * s;
6249c1dac77fSApple OSS Distributions 
62505c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
6251c1dac77fSApple OSS Distributions 		return kIOReturnNotPrivileged;
6252a5e72196SApple OSS Distributions 	}
6253c1dac77fSApple OSS Distributions 
6254c1dac77fSApple OSS Distributions 	//printf("io_catalog_get_data called. flag: %d\n", flag);
6255c1dac77fSApple OSS Distributions 
6256c1dac77fSApple OSS Distributions 	s = OSSerialize::withCapacity(4096);
6257a5e72196SApple OSS Distributions 	if (!s) {
6258c1dac77fSApple OSS Distributions 		return kIOReturnNoMemory;
6259a5e72196SApple OSS Distributions 	}
6260c1dac77fSApple OSS Distributions 
6261368ad365SApple OSS Distributions 	kr = gIOCatalogue->serializeData(flag, s);
6262c1dac77fSApple OSS Distributions 
6263c1dac77fSApple OSS Distributions 	if (kr == kIOReturnSuccess) {
6264e7776783SApple OSS Distributions 		mach_vm_address_t data;
6265c1dac77fSApple OSS Distributions 		vm_map_copy_t copy;
6266bb611c8fSApple OSS Distributions 		unsigned int size;
6267c1dac77fSApple OSS Distributions 
6268c1dac77fSApple OSS Distributions 		size = s->getLength();
6269*8d741a5dSApple OSS Distributions 		kr = mach_vm_allocate_kernel(kernel_map, &data, size,
6270*8d741a5dSApple OSS Distributions 		    VM_MAP_KERNEL_FLAGS_ANYWHERE(.vm_tag = VM_KERN_MEMORY_IOKIT));
6271c1dac77fSApple OSS Distributions 		if (kr == kIOReturnSuccess) {
6272c1dac77fSApple OSS Distributions 			bcopy(s->text(), (void *)data, size);
6273e7776783SApple OSS Distributions 			kr = vm_map_copyin(kernel_map, data, size, true, &copy);
6274c1dac77fSApple OSS Distributions 			*outData = (char *)copy;
6275c1dac77fSApple OSS Distributions 			*outDataCount = size;
6276c1dac77fSApple OSS Distributions 		}
6277c1dac77fSApple OSS Distributions 	}
6278c1dac77fSApple OSS Distributions 
6279c1dac77fSApple OSS Distributions 	s->release();
6280c1dac77fSApple OSS Distributions 
6281c1dac77fSApple OSS Distributions 	return kr;
6282c1dac77fSApple OSS Distributions }
6283c1dac77fSApple OSS Distributions 
6284c1dac77fSApple OSS Distributions /* Routine io_catalog_get_gen_count */
6285a5e72196SApple OSS Distributions kern_return_t
is_io_catalog_get_gen_count(mach_port_t main_port,uint32_t * genCount)6286a5e72196SApple OSS Distributions is_io_catalog_get_gen_count(
62875c2921b0SApple OSS Distributions 	mach_port_t             main_port,
6288e13b1fa5SApple OSS Distributions 	uint32_t                *genCount)
6289c1dac77fSApple OSS Distributions {
62905c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
6291c1dac77fSApple OSS Distributions 		return kIOReturnNotPrivileged;
6292a5e72196SApple OSS Distributions 	}
6293c1dac77fSApple OSS Distributions 
6294c1dac77fSApple OSS Distributions 	//printf("io_catalog_get_gen_count called.\n");
6295c1dac77fSApple OSS Distributions 
6296a5e72196SApple OSS Distributions 	if (!genCount) {
6297c1dac77fSApple OSS Distributions 		return kIOReturnBadArgument;
6298a5e72196SApple OSS Distributions 	}
6299c1dac77fSApple OSS Distributions 
6300c1dac77fSApple OSS Distributions 	*genCount = gIOCatalogue->getGenerationCount();
6301c1dac77fSApple OSS Distributions 
6302c1dac77fSApple OSS Distributions 	return kIOReturnSuccess;
6303c1dac77fSApple OSS Distributions }
6304c1dac77fSApple OSS Distributions 
63053ca3bd55SApple OSS Distributions /* Routine io_catalog_module_loaded.
63063ca3bd55SApple OSS Distributions  * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
63073ca3bd55SApple OSS Distributions  */
6308a5e72196SApple OSS Distributions kern_return_t
is_io_catalog_module_loaded(mach_port_t main_port,io_name_t name)6309a5e72196SApple OSS Distributions is_io_catalog_module_loaded(
63105c2921b0SApple OSS Distributions 	mach_port_t             main_port,
6311c1dac77fSApple OSS Distributions 	io_name_t               name)
6312c1dac77fSApple OSS Distributions {
63135c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
6314c1dac77fSApple OSS Distributions 		return kIOReturnNotPrivileged;
6315a5e72196SApple OSS Distributions 	}
6316c1dac77fSApple OSS Distributions 
6317c1dac77fSApple OSS Distributions 	//printf("io_catalog_module_loaded called. name %s\n", name);
6318c1dac77fSApple OSS Distributions 
6319a5e72196SApple OSS Distributions 	if (!name) {
6320c1dac77fSApple OSS Distributions 		return kIOReturnBadArgument;
6321a5e72196SApple OSS Distributions 	}
6322c1dac77fSApple OSS Distributions 
6323c1dac77fSApple OSS Distributions 	gIOCatalogue->moduleHasLoaded(name);
6324c1dac77fSApple OSS Distributions 
6325c1dac77fSApple OSS Distributions 	return kIOReturnSuccess;
6326c1dac77fSApple OSS Distributions }
6327c1dac77fSApple OSS Distributions 
6328a5e72196SApple OSS Distributions kern_return_t
is_io_catalog_reset(mach_port_t main_port,uint32_t flag)6329a5e72196SApple OSS Distributions is_io_catalog_reset(
63305c2921b0SApple OSS Distributions 	mach_port_t             main_port,
6331e13b1fa5SApple OSS Distributions 	uint32_t                flag)
6332c1dac77fSApple OSS Distributions {
63335c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
6334c1dac77fSApple OSS Distributions 		return kIOReturnNotPrivileged;
6335a5e72196SApple OSS Distributions 	}
6336c1dac77fSApple OSS Distributions 
6337c1dac77fSApple OSS Distributions 	switch (flag) {
6338c1dac77fSApple OSS Distributions 	case kIOCatalogResetDefault:
6339c1dac77fSApple OSS Distributions 		gIOCatalogue->reset();
6340c1dac77fSApple OSS Distributions 		break;
6341c1dac77fSApple OSS Distributions 
6342c1dac77fSApple OSS Distributions 	default:
6343c1dac77fSApple OSS Distributions 		return kIOReturnBadArgument;
6344c1dac77fSApple OSS Distributions 	}
6345c1dac77fSApple OSS Distributions 
6346c1dac77fSApple OSS Distributions 	return kIOReturnSuccess;
6347c1dac77fSApple OSS Distributions }
6348c1dac77fSApple OSS Distributions 
6349a5e72196SApple OSS Distributions kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args * args)6350a5e72196SApple OSS Distributions iokit_user_client_trap(struct iokit_user_client_trap_args *args)
6351c1dac77fSApple OSS Distributions {
6352c1dac77fSApple OSS Distributions 	kern_return_t    result = kIOReturnBadArgument;
6353c1dac77fSApple OSS Distributions 	IOUserClient   * userClient;
6354a5e72196SApple OSS Distributions 	OSObject       * object;
6355a5e72196SApple OSS Distributions 	uintptr_t        ref;
6356e6231be0SApple OSS Distributions 	mach_port_name_t portName;
6357c1dac77fSApple OSS Distributions 
6358a5e72196SApple OSS Distributions 	ref     = (uintptr_t) args->userClientRef;
6359e6231be0SApple OSS Distributions 
6360e6231be0SApple OSS Distributions 	if ((ref == MACH_PORT_DEAD) || (ref == (uintptr_t) MACH_PORT_NULL)) {
6361e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
6362e6231be0SApple OSS Distributions 	}
6363e6231be0SApple OSS Distributions 	// kobject port names always have b0-1 set, so we use these bits as flags to
6364e6231be0SApple OSS Distributions 	// iokit_user_client_trap()
6365e6231be0SApple OSS Distributions 	// keep this up to date with ipc_entry_name_mask();
6366e6231be0SApple OSS Distributions 	portName = (mach_port_name_t) (ref | 3);
6367e6231be0SApple OSS Distributions 	if (((1ULL << 32) & ref) || !(1 & ref)) {
6368e6231be0SApple OSS Distributions 		object = iokit_lookup_uext_ref_current_task(portName);
6369a5e72196SApple OSS Distributions 		if (object) {
6370a5e72196SApple OSS Distributions 			result = IOUserServerUEXTTrap(object, args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
6371a5e72196SApple OSS Distributions 		}
6372a5e72196SApple OSS Distributions 		OSSafeReleaseNULL(object);
6373e6231be0SApple OSS Distributions 	} else {
6374e6231be0SApple OSS Distributions 		io_object_t ref_current_task = iokit_lookup_connect_ref_current_task((mach_port_name_t) ref);
6375e6231be0SApple OSS Distributions 		if ((userClient = OSDynamicCast(IOUserClient, ref_current_task))) {
6376bb611c8fSApple OSS Distributions 			IOExternalTrap *trap = NULL;
6377c1dac77fSApple OSS Distributions 			IOService *target = NULL;
6378c1dac77fSApple OSS Distributions 
6379bb611c8fSApple OSS Distributions 			result = kIOReturnSuccess;
6380bb611c8fSApple OSS Distributions 			io_filter_policy_t filterPolicy = userClient->filterForTask(current_task(), 0);
6381bb611c8fSApple OSS Distributions 			if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
6382e6231be0SApple OSS Distributions 				result = gIOUCFilterCallbacks->io_filter_applier(userClient, filterPolicy, io_filter_type_trap, args->index);
6383bb611c8fSApple OSS Distributions 			}
6384bb611c8fSApple OSS Distributions 			if (kIOReturnSuccess == result) {
638514e3d835SApple OSS Distributions 				trap = userClient->getTargetAndTrapForIndex(&target, args->index);
6386bb611c8fSApple OSS Distributions 			}
6387c1dac77fSApple OSS Distributions 			if (trap && target) {
6388c1dac77fSApple OSS Distributions 				IOTrap func;
6389c1dac77fSApple OSS Distributions 
6390c1dac77fSApple OSS Distributions 				func = trap->func;
6391c1dac77fSApple OSS Distributions 
6392c1dac77fSApple OSS Distributions 				if (func) {
639314e3d835SApple OSS Distributions 					result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
6394c1dac77fSApple OSS Distributions 				}
6395c1dac77fSApple OSS Distributions 			}
6396c1dac77fSApple OSS Distributions 
639788cc0b97SApple OSS Distributions 			iokit_remove_connect_reference(userClient);
6398e6231be0SApple OSS Distributions 		} else {
6399e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(ref_current_task);
6400e6231be0SApple OSS Distributions 		}
6401c1dac77fSApple OSS Distributions 	}
6402c1dac77fSApple OSS Distributions 
6403c1dac77fSApple OSS Distributions 	return result;
6404c1dac77fSApple OSS Distributions }
6405c1dac77fSApple OSS Distributions 
6406cc9a6355SApple OSS Distributions /* Routine io_device_tree_entry_exists_with_name */
6407a5e72196SApple OSS Distributions kern_return_t
is_io_device_tree_entry_exists_with_name(mach_port_t main_port,io_name_t name,boolean_t * exists)6408a5e72196SApple OSS Distributions is_io_device_tree_entry_exists_with_name(
64095c2921b0SApple OSS Distributions 	mach_port_t main_port,
6410cc9a6355SApple OSS Distributions 	io_name_t name,
6411cc9a6355SApple OSS Distributions 	boolean_t *exists )
6412cc9a6355SApple OSS Distributions {
6413cc9a6355SApple OSS Distributions 	OSCollectionIterator *iter;
6414cc9a6355SApple OSS Distributions 
64155c2921b0SApple OSS Distributions 	if (main_port != main_device_port) {
6416a5e72196SApple OSS Distributions 		return kIOReturnNotPrivileged;
6417a5e72196SApple OSS Distributions 	}
6418cc9a6355SApple OSS Distributions 
6419cc9a6355SApple OSS Distributions 	iter = IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive, name);
6420cc9a6355SApple OSS Distributions 	*exists = iter && iter->getNextObject();
6421cc9a6355SApple OSS Distributions 	OSSafeReleaseNULL(iter);
6422cc9a6355SApple OSS Distributions 
6423cc9a6355SApple OSS Distributions 	return kIOReturnSuccess;
6424cc9a6355SApple OSS Distributions }
6425855239e5SApple OSS Distributions } /* extern "C" */
6426855239e5SApple OSS Distributions 
6427a5e72196SApple OSS Distributions IOReturn
callExternalMethod(uint32_t selector,IOExternalMethodArguments * args)64285c2921b0SApple OSS Distributions IOUserClient::callExternalMethod(uint32_t selector, IOExternalMethodArguments * args)
64295c2921b0SApple OSS Distributions {
64305c2921b0SApple OSS Distributions 	IOReturn ret;
64315c2921b0SApple OSS Distributions 
643294d3b452SApple OSS Distributions 	ipcEnter(defaultLocking ? (defaultLockingSingleThreadExternalMethod ? kIPCLockWrite : kIPCLockRead) : kIPCLockNone);
64335c2921b0SApple OSS Distributions 	if (uc2022) {
64345c2921b0SApple OSS Distributions 		ret = ((IOUserClient2022 *) this)->externalMethod(selector, (IOExternalMethodArgumentsOpaque *) args);
64355c2921b0SApple OSS Distributions 	} else {
64365c2921b0SApple OSS Distributions 		ret = externalMethod(selector, args);
64375c2921b0SApple OSS Distributions 	}
643894d3b452SApple OSS Distributions 	ipcExit(defaultLocking ? (defaultLockingSingleThreadExternalMethod ? kIPCLockWrite : kIPCLockRead) : kIPCLockNone);
643994d3b452SApple OSS Distributions 
64405c2921b0SApple OSS Distributions 	return ret;
64415c2921b0SApple OSS Distributions }
64425c2921b0SApple OSS Distributions 
64435c2921b0SApple OSS Distributions MIG_SERVER_ROUTINE IOReturn
externalMethod(uint32_t selector,IOExternalMethodArguments * arguments,IOExternalMethodDispatch * dispatch,OSObject * target,void * reference)64445c2921b0SApple OSS Distributions IOUserClient2022::externalMethod(uint32_t selector, IOExternalMethodArguments * arguments,
64455c2921b0SApple OSS Distributions     IOExternalMethodDispatch *dispatch,
64465c2921b0SApple OSS Distributions     OSObject *target, void *reference)
64475c2921b0SApple OSS Distributions {
64485c2921b0SApple OSS Distributions 	panic("wrong externalMethod for IOUserClient2022");
64495c2921b0SApple OSS Distributions }
64505c2921b0SApple OSS Distributions 
64515c2921b0SApple OSS Distributions IOReturn
dispatchExternalMethod(uint32_t selector,IOExternalMethodArgumentsOpaque * arguments,const IOExternalMethodDispatch2022 dispatchArray[],size_t dispatchArrayCount,OSObject * target,void * reference)64525c2921b0SApple OSS Distributions IOUserClient2022::dispatchExternalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque *arguments,
64535c2921b0SApple OSS Distributions     const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
64545c2921b0SApple OSS Distributions     OSObject * target, void * reference)
64555c2921b0SApple OSS Distributions {
64565c2921b0SApple OSS Distributions 	IOReturn    err;
64575c2921b0SApple OSS Distributions 	IOExternalMethodArguments * args = (typeof(args))arguments;
64585c2921b0SApple OSS Distributions 	const IOExternalMethodDispatch2022 * dispatch;
64595c2921b0SApple OSS Distributions 
64605c2921b0SApple OSS Distributions 	if (!dispatchArray) {
64615c2921b0SApple OSS Distributions 		return kIOReturnError;
64625c2921b0SApple OSS Distributions 	}
64635c2921b0SApple OSS Distributions 	if (selector >= dispatchArrayCount) {
64645c2921b0SApple OSS Distributions 		return kIOReturnBadArgument;
64655c2921b0SApple OSS Distributions 	}
64665c2921b0SApple OSS Distributions 	dispatch = &dispatchArray[selector];
64675c2921b0SApple OSS Distributions 
64685c2921b0SApple OSS Distributions 	uint32_t count;
64695c2921b0SApple OSS Distributions 	count = dispatch->checkScalarInputCount;
64705c2921b0SApple OSS Distributions 	if ((kIOUCVariableStructureSize != count) && (count != args->scalarInputCount)) {
64715c2921b0SApple OSS Distributions 		return kIOReturnBadArgument;
64725c2921b0SApple OSS Distributions 	}
64735c2921b0SApple OSS Distributions 
64745c2921b0SApple OSS Distributions 	count = dispatch->checkStructureInputSize;
64755c2921b0SApple OSS Distributions 	if ((kIOUCVariableStructureSize != count)
64765c2921b0SApple OSS Distributions 	    && (count != ((args->structureInputDescriptor)
64775c2921b0SApple OSS Distributions 	    ? args->structureInputDescriptor->getLength() : args->structureInputSize))) {
64785c2921b0SApple OSS Distributions 		return kIOReturnBadArgument;
64795c2921b0SApple OSS Distributions 	}
64805c2921b0SApple OSS Distributions 
64815c2921b0SApple OSS Distributions 	count = dispatch->checkScalarOutputCount;
64825c2921b0SApple OSS Distributions 	if ((kIOUCVariableStructureSize != count) && (count != args->scalarOutputCount)) {
64835c2921b0SApple OSS Distributions 		return kIOReturnBadArgument;
64845c2921b0SApple OSS Distributions 	}
64855c2921b0SApple OSS Distributions 
64865c2921b0SApple OSS Distributions 	count = dispatch->checkStructureOutputSize;
64875c2921b0SApple OSS Distributions 	if ((kIOUCVariableStructureSize != count)
64885c2921b0SApple OSS Distributions 	    && (count != ((args->structureOutputDescriptor)
64895c2921b0SApple OSS Distributions 	    ? args->structureOutputDescriptor->getLength() : args->structureOutputSize))) {
64905c2921b0SApple OSS Distributions 		return kIOReturnBadArgument;
64915c2921b0SApple OSS Distributions 	}
64925c2921b0SApple OSS Distributions 
64935c2921b0SApple OSS Distributions 	if (args->asyncWakePort && !dispatch->allowAsync) {
64945c2921b0SApple OSS Distributions 		return kIOReturnBadArgument;
64955c2921b0SApple OSS Distributions 	}
64965c2921b0SApple OSS Distributions 
64975c2921b0SApple OSS Distributions 	if (dispatch->checkEntitlement) {
64985c2921b0SApple OSS Distributions 		if (!IOCurrentTaskHasEntitlement(dispatch->checkEntitlement)) {
64995c2921b0SApple OSS Distributions 			return kIOReturnNotPrivileged;
65005c2921b0SApple OSS Distributions 		}
65015c2921b0SApple OSS Distributions 	}
65025c2921b0SApple OSS Distributions 
65035c2921b0SApple OSS Distributions 	if (dispatch->function) {
65045c2921b0SApple OSS Distributions 		err = (*dispatch->function)(target, reference, args);
65055c2921b0SApple OSS Distributions 	} else {
65065c2921b0SApple OSS Distributions 		err = kIOReturnNoCompletion; /* implementer can dispatch */
65075c2921b0SApple OSS Distributions 	}
65085c2921b0SApple OSS Distributions 	return err;
65095c2921b0SApple OSS Distributions }
65105c2921b0SApple OSS Distributions 
65115c2921b0SApple OSS Distributions IOReturn
externalMethod(uint32_t selector,IOExternalMethodArguments * args,IOExternalMethodDispatch * dispatch,OSObject * target,void * reference)6512a5e72196SApple OSS Distributions IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,
6513e13b1fa5SApple OSS Distributions     IOExternalMethodDispatch * dispatch, OSObject * target, void * reference )
6514e13b1fa5SApple OSS Distributions {
6515e13b1fa5SApple OSS Distributions 	IOReturn    err;
6516e13b1fa5SApple OSS Distributions 	IOService * object;
65173ca3bd55SApple OSS Distributions 	IOByteCount structureOutputSize;
6518e13b1fa5SApple OSS Distributions 
6519a5e72196SApple OSS Distributions 	if (dispatch) {
6520e13b1fa5SApple OSS Distributions 		uint32_t count;
6521e13b1fa5SApple OSS Distributions 		count = dispatch->checkScalarInputCount;
6522a5e72196SApple OSS Distributions 		if ((kIOUCVariableStructureSize != count) && (count != args->scalarInputCount)) {
6523a5e72196SApple OSS Distributions 			return kIOReturnBadArgument;
6524e13b1fa5SApple OSS Distributions 		}
6525e13b1fa5SApple OSS Distributions 
6526e13b1fa5SApple OSS Distributions 		count = dispatch->checkStructureInputSize;
6527e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != count)
6528e13b1fa5SApple OSS Distributions 		    && (count != ((args->structureInputDescriptor)
6529a5e72196SApple OSS Distributions 		    ? args->structureInputDescriptor->getLength() : args->structureInputSize))) {
6530a5e72196SApple OSS Distributions 			return kIOReturnBadArgument;
6531e13b1fa5SApple OSS Distributions 		}
6532e13b1fa5SApple OSS Distributions 
6533e13b1fa5SApple OSS Distributions 		count = dispatch->checkScalarOutputCount;
6534a5e72196SApple OSS Distributions 		if ((kIOUCVariableStructureSize != count) && (count != args->scalarOutputCount)) {
6535a5e72196SApple OSS Distributions 			return kIOReturnBadArgument;
6536e13b1fa5SApple OSS Distributions 		}
6537e13b1fa5SApple OSS Distributions 
6538e13b1fa5SApple OSS Distributions 		count = dispatch->checkStructureOutputSize;
6539e13b1fa5SApple OSS Distributions 		if ((kIOUCVariableStructureSize != count)
6540e13b1fa5SApple OSS Distributions 		    && (count != ((args->structureOutputDescriptor)
6541a5e72196SApple OSS Distributions 		    ? args->structureOutputDescriptor->getLength() : args->structureOutputSize))) {
6542a5e72196SApple OSS Distributions 			return kIOReturnBadArgument;
6543e13b1fa5SApple OSS Distributions 		}
6544e13b1fa5SApple OSS Distributions 
6545a5e72196SApple OSS Distributions 		if (dispatch->function) {
6546e13b1fa5SApple OSS Distributions 			err = (*dispatch->function)(target, reference, args);
6547a5e72196SApple OSS Distributions 		} else {
65485c2921b0SApple OSS Distributions 			err = kIOReturnNoCompletion; /* implementer can dispatch */
6549a5e72196SApple OSS Distributions 		}
6550a5e72196SApple OSS Distributions 		return err;
6551e13b1fa5SApple OSS Distributions 	}
6552e13b1fa5SApple OSS Distributions 
65533ca3bd55SApple OSS Distributions 
6554e13b1fa5SApple OSS Distributions 	// pre-Leopard API's don't do ool structs
6555a5e72196SApple OSS Distributions 	if (args->structureInputDescriptor || args->structureOutputDescriptor) {
6556e13b1fa5SApple OSS Distributions 		err = kIOReturnIPCError;
6557a5e72196SApple OSS Distributions 		return err;
6558e13b1fa5SApple OSS Distributions 	}
6559e13b1fa5SApple OSS Distributions 
65603ca3bd55SApple OSS Distributions 	structureOutputSize = args->structureOutputSize;
65613ca3bd55SApple OSS Distributions 
6562a5e72196SApple OSS Distributions 	if (args->asyncWakePort) {
6563e13b1fa5SApple OSS Distributions 		IOExternalAsyncMethod * method;
6564a5e72196SApple OSS Distributions 		object = NULL;
6565a5e72196SApple OSS Distributions 		if (!(method = getAsyncTargetAndMethodForIndex(&object, selector)) || !object) {
6566a5e72196SApple OSS Distributions 			return kIOReturnUnsupported;
6567855239e5SApple OSS Distributions 		}
6568855239e5SApple OSS Distributions 
6569a5e72196SApple OSS Distributions 		if (kIOUCForegroundOnly & method->flags) {
6570a5e72196SApple OSS Distributions 			if (task_is_gpu_denied(current_task())) {
6571a5e72196SApple OSS Distributions 				return kIOReturnNotPermitted;
6572a5e72196SApple OSS Distributions 			}
6573a5e72196SApple OSS Distributions 		}
6574a5e72196SApple OSS Distributions 
6575a5e72196SApple OSS Distributions 		switch (method->flags & kIOUCTypeMask) {
6576e13b1fa5SApple OSS Distributions 		case kIOUCScalarIStructI:
6577e13b1fa5SApple OSS Distributions 			err = shim_io_async_method_scalarI_structureI( method, object,
6578e13b1fa5SApple OSS Distributions 			    args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
6579e13b1fa5SApple OSS Distributions 			    args->scalarInput, args->scalarInputCount,
6580e13b1fa5SApple OSS Distributions 			    (char *)args->structureInput, args->structureInputSize );
6581e13b1fa5SApple OSS Distributions 			break;
6582e13b1fa5SApple OSS Distributions 
6583e13b1fa5SApple OSS Distributions 		case kIOUCScalarIScalarO:
6584e13b1fa5SApple OSS Distributions 			err = shim_io_async_method_scalarI_scalarO( method, object,
6585e13b1fa5SApple OSS Distributions 			    args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
6586e13b1fa5SApple OSS Distributions 			    args->scalarInput, args->scalarInputCount,
6587e13b1fa5SApple OSS Distributions 			    args->scalarOutput, &args->scalarOutputCount );
6588e13b1fa5SApple OSS Distributions 			break;
6589e13b1fa5SApple OSS Distributions 
6590e13b1fa5SApple OSS Distributions 		case kIOUCScalarIStructO:
6591e13b1fa5SApple OSS Distributions 			err = shim_io_async_method_scalarI_structureO( method, object,
6592e13b1fa5SApple OSS Distributions 			    args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
6593e13b1fa5SApple OSS Distributions 			    args->scalarInput, args->scalarInputCount,
6594e13b1fa5SApple OSS Distributions 			    (char *) args->structureOutput, &args->structureOutputSize );
6595e13b1fa5SApple OSS Distributions 			break;
6596e13b1fa5SApple OSS Distributions 
6597e13b1fa5SApple OSS Distributions 
6598e13b1fa5SApple OSS Distributions 		case kIOUCStructIStructO:
6599e13b1fa5SApple OSS Distributions 			err = shim_io_async_method_structureI_structureO( method, object,
6600e13b1fa5SApple OSS Distributions 			    args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
6601e13b1fa5SApple OSS Distributions 			    (char *)args->structureInput, args->structureInputSize,
6602e13b1fa5SApple OSS Distributions 			    (char *) args->structureOutput, &args->structureOutputSize );
6603e13b1fa5SApple OSS Distributions 			break;
6604e13b1fa5SApple OSS Distributions 
6605e13b1fa5SApple OSS Distributions 		default:
6606e13b1fa5SApple OSS Distributions 			err = kIOReturnBadArgument;
6607e13b1fa5SApple OSS Distributions 			break;
6608e13b1fa5SApple OSS Distributions 		}
6609a5e72196SApple OSS Distributions 	} else {
6610e13b1fa5SApple OSS Distributions 		IOExternalMethod *      method;
6611a5e72196SApple OSS Distributions 		object = NULL;
6612a5e72196SApple OSS Distributions 		if (!(method = getTargetAndMethodForIndex(&object, selector)) || !object) {
6613a5e72196SApple OSS Distributions 			return kIOReturnUnsupported;
6614855239e5SApple OSS Distributions 		}
6615855239e5SApple OSS Distributions 
6616a5e72196SApple OSS Distributions 		if (kIOUCForegroundOnly & method->flags) {
6617a5e72196SApple OSS Distributions 			if (task_is_gpu_denied(current_task())) {
6618a5e72196SApple OSS Distributions 				return kIOReturnNotPermitted;
6619a5e72196SApple OSS Distributions 			}
6620a5e72196SApple OSS Distributions 		}
6621a5e72196SApple OSS Distributions 
6622a5e72196SApple OSS Distributions 		switch (method->flags & kIOUCTypeMask) {
6623e13b1fa5SApple OSS Distributions 		case kIOUCScalarIStructI:
6624e13b1fa5SApple OSS Distributions 			err = shim_io_connect_method_scalarI_structureI( method, object,
6625e13b1fa5SApple OSS Distributions 			    args->scalarInput, args->scalarInputCount,
6626e13b1fa5SApple OSS Distributions 			    (char *) args->structureInput, args->structureInputSize );
6627e13b1fa5SApple OSS Distributions 			break;
6628e13b1fa5SApple OSS Distributions 
6629e13b1fa5SApple OSS Distributions 		case kIOUCScalarIScalarO:
6630e13b1fa5SApple OSS Distributions 			err = shim_io_connect_method_scalarI_scalarO( method, object,
6631e13b1fa5SApple OSS Distributions 			    args->scalarInput, args->scalarInputCount,
6632e13b1fa5SApple OSS Distributions 			    args->scalarOutput, &args->scalarOutputCount );
6633e13b1fa5SApple OSS Distributions 			break;
6634e13b1fa5SApple OSS Distributions 
6635e13b1fa5SApple OSS Distributions 		case kIOUCScalarIStructO:
6636e13b1fa5SApple OSS Distributions 			err = shim_io_connect_method_scalarI_structureO( method, object,
6637e13b1fa5SApple OSS Distributions 			    args->scalarInput, args->scalarInputCount,
66383ca3bd55SApple OSS Distributions 			    (char *) args->structureOutput, &structureOutputSize );
6639e13b1fa5SApple OSS Distributions 			break;
6640e13b1fa5SApple OSS Distributions 
6641e13b1fa5SApple OSS Distributions 
6642e13b1fa5SApple OSS Distributions 		case kIOUCStructIStructO:
6643e13b1fa5SApple OSS Distributions 			err = shim_io_connect_method_structureI_structureO( method, object,
6644e13b1fa5SApple OSS Distributions 			    (char *) args->structureInput, args->structureInputSize,
66453ca3bd55SApple OSS Distributions 			    (char *) args->structureOutput, &structureOutputSize );
6646e13b1fa5SApple OSS Distributions 			break;
6647e13b1fa5SApple OSS Distributions 
6648e13b1fa5SApple OSS Distributions 		default:
6649e13b1fa5SApple OSS Distributions 			err = kIOReturnBadArgument;
6650e13b1fa5SApple OSS Distributions 			break;
6651e13b1fa5SApple OSS Distributions 		}
6652e13b1fa5SApple OSS Distributions 	}
66533ca3bd55SApple OSS Distributions 
6654bb611c8fSApple OSS Distributions 	if (structureOutputSize > UINT_MAX) {
6655bb611c8fSApple OSS Distributions 		structureOutputSize = 0;
6656bb611c8fSApple OSS Distributions 		err = kIOReturnBadArgument;
6657bb611c8fSApple OSS Distributions 	}
6658bb611c8fSApple OSS Distributions 
6659bb611c8fSApple OSS Distributions 	args->structureOutputSize = ((typeof(args->structureOutputSize))structureOutputSize);
66603ca3bd55SApple OSS Distributions 
6661a5e72196SApple OSS Distributions 	return err;
6662e13b1fa5SApple OSS Distributions }
6663e13b1fa5SApple OSS Distributions 
6664bb611c8fSApple OSS Distributions IOReturn
registerFilterCallbacks(const struct io_filter_callbacks * callbacks,size_t size)6665bb611c8fSApple OSS Distributions IOUserClient::registerFilterCallbacks(const struct io_filter_callbacks *callbacks, size_t size)
6666bb611c8fSApple OSS Distributions {
6667bb611c8fSApple OSS Distributions 	if (size < sizeof(*callbacks)) {
6668bb611c8fSApple OSS Distributions 		return kIOReturnBadArgument;
6669bb611c8fSApple OSS Distributions 	}
6670bb611c8fSApple OSS Distributions 	if (!OSCompareAndSwapPtr(NULL, __DECONST(void *, callbacks), &gIOUCFilterCallbacks)) {
6671bb611c8fSApple OSS Distributions 		return kIOReturnBusy;
6672bb611c8fSApple OSS Distributions 	}
6673bb611c8fSApple OSS Distributions 	return kIOReturnSuccess;
6674bb611c8fSApple OSS Distributions }
6675bb611c8fSApple OSS Distributions 
66765c2921b0SApple OSS Distributions 
66773ca3bd55SApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 0);
6678c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 1);
6679c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 2);
6680c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 3);
6681c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 4);
6682c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 5);
6683c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 6);
6684c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 7);
6685c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 8);
6686c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 9);
6687c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 10);
6688c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 11);
6689c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 12);
6690c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 13);
6691c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 14);
6692c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient, 15);
66935c2921b0SApple OSS Distributions 
66945c2921b0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient2022, 0);
66955c2921b0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient2022, 1);
66965c2921b0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient2022, 2);
66975c2921b0SApple OSS Distributions OSMetaClassDefineReservedUnused(IOUserClient2022, 3);
6698