2 * Copyright (c) 1998-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <libkern/c++/OSKext.h>
31 #include <IOKit/IOKitServer.h>
32 #include <IOKit/IOKitKeysPrivate.h>
33 #include <IOKit/IOUserClient.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IORegistryEntry.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOMemoryDescriptor.h>
38 #include <IOKit/IOBufferMemoryDescriptor.h>
39 #include <IOKit/IOLib.h>
40 #include <IOKit/IOBSD.h>
41 #include <IOKit/IOStatisticsPrivate.h>
42 #include <IOKit/IOTimeStamp.h>
43 #include <IOKit/IODeviceTreeSupport.h>
44 #include <IOKit/IOUserServer.h>
45 #include <IOKit/system.h>
46 #include <libkern/OSDebug.h>
47 #include <DriverKit/OSAction.h>
49 #include <sys/kauth.h>
50 #include <sys/codesign.h>
58 #include <security/mac_framework.h>
60 #include <sys/kauth.h>
64 #endif /* CONFIG_MACF */
66 #include <IOKit/assert.h>
68 #include "IOServicePrivate.h"
69 #include "IOKitKernelInternal.h"
71 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
72 #define SCALAR32(x) ((uint32_t )x)
73 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
74 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
75 #define REF32(x) ((int)(x))
78 kIOUCAsync0Flags
= 3ULL,
79 kIOUCAsync64Flag
= 1ULL,
80 kIOUCAsyncErrorLoggedFlag
= 2ULL
85 #define IOStatisticsRegisterCounter() \
87 reserved->counter = IOStatistics::registerUserClient(this); \
90 #define IOStatisticsUnregisterCounter() \
93 IOStatistics::unregisterUserClient(reserved->counter); \
96 #define IOStatisticsClientCall() \
98 IOStatistics::countUserClientCall(client); \
103 #define IOStatisticsRegisterCounter()
104 #define IOStatisticsUnregisterCounter()
105 #define IOStatisticsClientCall()
107 #endif /* IOKITSTATS */
109 #if DEVELOPMENT || DEBUG
111 #define FAKE_STACK_FRAME(a) \
112 const void ** __frameptr; \
113 const void * __retaddr; \
114 __frameptr = (typeof(__frameptr)) __builtin_frame_address(0); \
115 __retaddr = __frameptr[1]; \
118 #define FAKE_STACK_FRAME_END() \
119 __frameptr[1] = __retaddr;
121 #else /* DEVELOPMENT || DEBUG */
123 #define FAKE_STACK_FRAME(a)
124 #define FAKE_STACK_FRAME_END()
126 #endif /* DEVELOPMENT || DEBUG */
128 #define ASYNC_REF_COUNT (sizeof(io_async_ref_t) / sizeof(natural_t))
129 #define ASYNC_REF64_COUNT (sizeof(io_async_ref64_t) / sizeof(io_user_reference_t))
131 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
134 #include <mach/mach_traps.h>
135 #include <vm/vm_map.h>
138 struct IOMachPortHashList
;
140 static_assert(IKOT_MAX_TYPE
<= 255);
142 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
144 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
145 class IOMachPort
: public OSObject
147 OSDeclareDefaultStructors(IOMachPort
);
149 SLIST_ENTRY(IOMachPort
) link
;
156 static IOMachPort
* withObjectAndType(OSObject
*obj
, ipc_kobject_type_t type
);
158 static IOMachPortHashList
* bucketForObject(OSObject
*obj
,
159 ipc_kobject_type_t type
);
161 static IOMachPort
* portForObjectInBucket(IOMachPortHashList
*bucket
, OSObject
*obj
, ipc_kobject_type_t type
);
163 static bool noMoreSendersForObject( OSObject
* obj
,
164 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
165 static void releasePortForObject( OSObject
* obj
,
166 ipc_kobject_type_t type
);
167 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
169 static mach_port_name_t
makeSendRightForTask( task_t task
,
170 io_object_t obj
, ipc_kobject_type_t type
);
172 virtual void free() APPLE_KEXT_OVERRIDE
;
175 #define super OSObject
176 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
178 static IOLock
* gIOObjectPortLock
;
179 IOLock
* gIOUserServerLock
;
181 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
183 SLIST_HEAD(IOMachPortHashList
, IOMachPort
);
186 #define PORT_HASH_SIZE 256
188 #define PORT_HASH_SIZE 4096
189 #endif /* CONFIG_EMBEDDED */
191 IOMachPortHashList ports
[PORT_HASH_SIZE
];
194 IOMachPortInitialize(void)
196 for (size_t i
= 0; i
< PORT_HASH_SIZE
; i
++) {
197 SLIST_INIT(&ports
[i
]);
202 IOMachPort::bucketForObject(OSObject
*obj
, ipc_kobject_type_t type
)
204 return &ports
[os_hash_kernel_pointer(obj
) % PORT_HASH_SIZE
];
208 IOMachPort::portForObjectInBucket(IOMachPortHashList
*bucket
, OSObject
*obj
, ipc_kobject_type_t type
)
210 IOMachPort
*machPort
;
212 SLIST_FOREACH(machPort
, bucket
, link
) {
213 if (machPort
->object
== obj
&& machPort
->type
== type
) {
221 IOMachPort::withObjectAndType(OSObject
*obj
, ipc_kobject_type_t type
)
223 IOMachPort
*machPort
= NULL
;
225 machPort
= new IOMachPort
;
226 if (__improbable(machPort
&& !machPort
->init())) {
230 machPort
->object
= obj
;
231 machPort
->type
= (typeof(machPort
->type
))type
;
232 machPort
->port
= iokit_alloc_object_port(obj
, type
);
234 obj
->taggedRetain(OSTypeID(OSCollection
));
241 IOMachPort::noMoreSendersForObject( OSObject
* obj
,
242 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
244 IOMachPort
*machPort
= NULL
;
247 bool destroyed
= true;
249 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
253 lck_mtx_lock(gIOObjectPortLock
);
255 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
258 destroyed
= (machPort
->mscount
<= *mscount
);
260 *mscount
= machPort
->mscount
;
261 lck_mtx_unlock(gIOObjectPortLock
);
263 if ((IKOT_IOKIT_CONNECT
== type
) && (uc
= OSDynamicCast(IOUserClient
, obj
))) {
266 SLIST_REMOVE(bucket
, machPort
, IOMachPort
, link
);
268 lck_mtx_unlock(gIOObjectPortLock
);
271 obj
->taggedRelease(OSTypeID(OSCollection
));
274 lck_mtx_unlock(gIOObjectPortLock
);
277 if ((IKOT_UEXT_OBJECT
== type
) && (action
= OSDynamicCast(OSAction
, obj
))) {
287 IOMachPort::releasePortForObject( OSObject
* obj
,
288 ipc_kobject_type_t type
)
290 IOMachPort
*machPort
;
291 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
293 assert(IKOT_IOKIT_CONNECT
!= type
);
295 lck_mtx_lock(gIOObjectPortLock
);
297 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
299 if (machPort
&& !machPort
->holdDestroy
) {
301 SLIST_REMOVE(bucket
, machPort
, IOMachPort
, link
);
303 lck_mtx_unlock(gIOObjectPortLock
);
306 obj
->taggedRelease(OSTypeID(OSCollection
));
309 lck_mtx_unlock(gIOObjectPortLock
);
314 IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
316 IOMachPort
* machPort
;
318 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
319 lck_mtx_lock(gIOObjectPortLock
);
321 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
324 machPort
->holdDestroy
= true;
327 lck_mtx_unlock(gIOObjectPortLock
);
331 IOMachPortDestroyUserReferences(OSObject
* obj
, natural_t type
)
333 IOMachPort::releasePortForObject(obj
, type
);
337 IOUserClient::destroyUserReferences( OSObject
* obj
)
339 IOMachPort
*machPort
;
341 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
344 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
347 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, IKOT_IOKIT_CONNECT
);
348 IOMachPortHashList
*mappingBucket
= NULL
;
350 lck_mtx_lock(gIOObjectPortLock
);
352 IOUserClient
* uc
= OSDynamicCast(IOUserClient
, obj
);
353 if (uc
&& uc
->mappings
) {
354 mappingBucket
= IOMachPort::bucketForObject(uc
->mappings
, IKOT_IOKIT_CONNECT
);
357 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, IKOT_IOKIT_CONNECT
);
359 if (machPort
== NULL
) {
360 lck_mtx_unlock(gIOObjectPortLock
);
364 SLIST_REMOVE(bucket
, machPort
, IOMachPort
, link
);
365 obj
->taggedRelease(OSTypeID(OSCollection
));
370 uc
->mappings
->taggedRetain(OSTypeID(OSCollection
));
371 machPort
->object
= uc
->mappings
;
372 SLIST_INSERT_HEAD(mappingBucket
, machPort
, link
);
373 iokit_switch_object_port(machPort
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
375 lck_mtx_unlock(gIOObjectPortLock
);
377 uc
->mappings
->release();
380 lck_mtx_unlock(gIOObjectPortLock
);
384 lck_mtx_unlock(gIOObjectPortLock
);
395 IOMachPort::makeSendRightForTask( task_t task
,
396 io_object_t obj
, ipc_kobject_type_t type
)
398 return iokit_make_send_right( task
, obj
, type
);
402 IOMachPort::free( void )
405 iokit_destroy_object_port( port
);
410 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
412 class IOUserIterator
: public OSIterator
414 OSDeclareDefaultStructors(IOUserIterator
);
416 OSObject
* userIteratorObject
;
419 static IOUserIterator
* withIterator(LIBKERN_CONSUMED OSIterator
* iter
);
420 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
421 virtual void free() APPLE_KEXT_OVERRIDE
;
423 virtual void reset() APPLE_KEXT_OVERRIDE
;
424 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
425 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
426 virtual OSObject
* copyNextObject();
429 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
431 class IOUserNotification
: public IOUserIterator
433 OSDeclareDefaultStructors(IOUserNotification
);
435 #define holdNotify userIteratorObject
439 virtual void free() APPLE_KEXT_OVERRIDE
;
441 virtual void setNotification( IONotifier
* obj
);
443 virtual void reset() APPLE_KEXT_OVERRIDE
;
444 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
447 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
449 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
452 IOUserIterator::withIterator(OSIterator
* iter
)
460 me
= new IOUserIterator
;
461 if (me
&& !me
->init()) {
468 me
->userIteratorObject
= iter
;
474 IOUserIterator::init( void )
476 if (!OSObject::init()) {
480 lock
= IOLockAlloc();
489 IOUserIterator::free()
491 if (userIteratorObject
) {
492 userIteratorObject
->release();
501 IOUserIterator::reset()
504 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
505 ((OSIterator
*)userIteratorObject
)->reset();
510 IOUserIterator::isValid()
515 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
516 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
523 IOUserIterator::getNextObject()
530 IOUserIterator::copyNextObject()
532 OSObject
* ret
= NULL
;
535 if (userIteratorObject
) {
536 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
546 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
548 // functions called from osfmk/device/iokit_rpc.c
551 iokit_port_object_description(io_object_t obj
, kobject_description_t desc
)
553 IORegistryEntry
* regEntry
;
554 IOUserNotification
* __unused noti
;
555 _IOServiceNotifier
* __unused serviceNoti
;
556 OSSerialize
* __unused s
;
558 if ((regEntry
= OSDynamicCast(IORegistryEntry
, obj
))) {
559 snprintf(desc
, KOBJECT_DESCRIPTION_LENGTH
, "%s(0x%qx)", obj
->getMetaClass()->getClassName(), regEntry
->getRegistryEntryID());
560 #if DEVELOPMENT || DEBUG
561 } else if ((noti
= OSDynamicCast(IOUserNotification
, obj
))
562 && ((serviceNoti
= OSDynamicCast(_IOServiceNotifier
, noti
->holdNotify
)))) {
563 s
= OSSerialize::withCapacity(page_size
);
564 if (s
&& serviceNoti
->matching
->serialize(s
)) {
565 snprintf(desc
, KOBJECT_DESCRIPTION_LENGTH
, "%s(%s)", obj
->getMetaClass()->getClassName(), s
->text());
567 OSSafeReleaseNULL(s
);
568 #endif /* DEVELOPMENT || DEBUG */
570 snprintf(desc
, KOBJECT_DESCRIPTION_LENGTH
, "%s", obj
->getMetaClass()->getClassName());
575 iokit_add_reference( io_object_t obj
, natural_t type
)
583 if ((IKOT_IOKIT_CONNECT
== type
)
584 && (uc
= OSDynamicCast(IOUserClient
, obj
))) {
585 OSIncrementAtomic(&uc
->__ipc
);
592 iokit_remove_reference( io_object_t obj
)
600 iokit_remove_connect_reference( io_object_t obj
)
603 bool finalize
= false;
609 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) {
610 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive()) {
611 IOLockLock(gIOObjectPortLock
);
612 if ((finalize
= uc
->__ipcFinal
)) {
613 uc
->__ipcFinal
= false;
615 IOLockUnlock(gIOObjectPortLock
);
618 uc
->scheduleFinalize(true);
626 IOUserClient::finalizeUserReferences(OSObject
* obj
)
631 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) {
632 IOLockLock(gIOObjectPortLock
);
633 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) {
636 IOLockUnlock(gIOObjectPortLock
);
642 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
644 IOMachPort
*machPort
= NULL
;
645 ipc_port_t port
= NULL
;
647 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
649 lck_mtx_lock(gIOObjectPortLock
);
651 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
653 if (__improbable(machPort
== NULL
)) {
654 machPort
= IOMachPort::withObjectAndType(obj
, type
);
655 if (__improbable(machPort
== NULL
)) {
658 SLIST_INSERT_HEAD(bucket
, machPort
, link
);
663 iokit_retain_port(machPort
->port
);
664 port
= machPort
->port
;
667 lck_mtx_unlock(gIOObjectPortLock
);
673 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
674 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
676 IOUserClient
* client
;
678 IOUserNotification
* notify
;
680 if (!IOMachPort::noMoreSendersForObject( obj
, type
, mscount
)) {
681 return kIOReturnNotReady
;
684 if (IKOT_IOKIT_CONNECT
== type
) {
685 if ((client
= OSDynamicCast( IOUserClient
, obj
))) {
686 IOStatisticsClientCall();
687 IOLockLock(client
->lock
);
688 client
->clientDied();
689 IOLockUnlock(client
->lock
);
691 } else if (IKOT_IOKIT_OBJECT
== type
) {
692 if ((map
= OSDynamicCast( IOMemoryMap
, obj
))) {
694 } else if ((notify
= OSDynamicCast( IOUserNotification
, obj
))) {
695 notify
->setNotification( NULL
);
699 return kIOReturnSuccess
;
703 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
705 class IOServiceUserNotification
: public IOUserNotification
707 OSDeclareDefaultStructors(IOServiceUserNotification
);
710 mach_msg_header_t msgHdr
;
711 OSNotificationHeader64 notifyHeader
;
714 enum { kMaxOutstanding
= 1024 };
724 virtual bool init( mach_port_t port
, natural_t type
,
725 void * reference
, vm_size_t referenceSize
,
727 virtual void free() APPLE_KEXT_OVERRIDE
;
728 void invalidatePort(void);
730 static bool _handler( void * target
,
731 void * ref
, IOService
* newService
, IONotifier
* notifier
);
732 virtual bool handler( void * ref
, IOService
* newService
);
734 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
735 virtual OSObject
* copyNextObject() APPLE_KEXT_OVERRIDE
;
738 class IOServiceMessageUserNotification
: public IOUserNotification
740 OSDeclareDefaultStructors(IOServiceMessageUserNotification
);
743 mach_msg_header_t msgHdr
;
744 mach_msg_body_t msgBody
;
745 mach_msg_port_descriptor_t ports
[1];
746 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
757 virtual bool init( mach_port_t port
, natural_t type
,
758 void * reference
, vm_size_t referenceSize
,
762 virtual void free() APPLE_KEXT_OVERRIDE
;
763 void invalidatePort(void);
765 static IOReturn
_handler( void * target
, void * ref
,
766 UInt32 messageType
, IOService
* provider
,
767 void * messageArgument
, vm_size_t argSize
);
768 virtual IOReturn
handler( void * ref
,
769 UInt32 messageType
, IOService
* provider
,
770 void * messageArgument
, vm_size_t argSize
);
772 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
773 virtual OSObject
* copyNextObject() APPLE_KEXT_OVERRIDE
;
776 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
779 #define super IOUserIterator
780 OSDefineMetaClass( IOUserNotification
, IOUserIterator
);
781 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
);
783 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
786 IOUserNotification::free( void )
789 assert(OSDynamicCast(IONotifier
, holdNotify
));
790 ((IONotifier
*)holdNotify
)->remove();
793 // can't be in handler now
800 IOUserNotification::setNotification( IONotifier
* notify
)
802 OSObject
* previousNotify
;
804 IOLockLock( gIOObjectPortLock
);
806 previousNotify
= holdNotify
;
809 IOLockUnlock( gIOObjectPortLock
);
811 if (previousNotify
) {
812 assert(OSDynamicCast(IONotifier
, previousNotify
));
813 ((IONotifier
*)previousNotify
)->remove();
818 IOUserNotification::reset()
824 IOUserNotification::isValid()
829 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
832 #define super IOUserNotification
833 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
835 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
838 IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
839 void * reference
, vm_size_t referenceSize
,
842 if (!super::init()) {
846 newSet
= OSArray::withCapacity( 1 );
851 if (referenceSize
> sizeof(OSAsyncReference64
)) {
855 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
856 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
861 bzero( pingMsg
, msgSize
);
863 pingMsg
->msgHdr
.msgh_remote_port
= port
;
864 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
865 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
866 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
867 pingMsg
->msgHdr
.msgh_size
= msgSize
;
868 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
870 pingMsg
->notifyHeader
.size
= 0;
871 pingMsg
->notifyHeader
.type
= type
;
872 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
878 IOServiceUserNotification::invalidatePort(void)
881 pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
886 IOServiceUserNotification::free( void )
898 if (_pingMsg
&& _msgSize
) {
899 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
900 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
902 IOFree(_pingMsg
, _msgSize
);
911 IOServiceUserNotification::_handler( void * target
,
912 void * ref
, IOService
* newService
, IONotifier
* notifier
)
914 return ((IOServiceUserNotification
*) target
)->handler( ref
, newService
);
918 IOServiceUserNotification::handler( void * ref
,
919 IOService
* newService
)
923 ipc_port_t port
= NULL
;
924 bool sendPing
= false;
928 count
= newSet
->getCount();
929 if (count
< kMaxOutstanding
) {
930 newSet
->setObject( newService
);
931 if ((sendPing
= (armed
&& (0 == count
)))) {
938 if (kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
) {
939 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
943 if ((port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
))) {
944 pingMsg
->msgHdr
.msgh_local_port
= port
;
946 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
949 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
950 pingMsg
->msgHdr
.msgh_size
,
951 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
954 iokit_release_port( port
);
957 if ((KERN_SUCCESS
!= kr
) && !ipcLogged
) {
959 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
966 IOServiceUserNotification::getNextObject()
973 IOServiceUserNotification::copyNextObject()
980 count
= newSet
->getCount();
982 result
= newSet
->getObject( count
- 1 );
984 newSet
->removeObject( count
- 1);
995 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
997 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
999 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1002 IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
1003 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
1006 if (!super::init()) {
1010 if (referenceSize
> sizeof(OSAsyncReference64
)) {
1014 clientIs64
= client64
;
1016 owningPID
= proc_selfpid();
1018 extraSize
+= sizeof(IOServiceInterestContent64
);
1019 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
1020 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
1025 bzero( pingMsg
, msgSize
);
1027 pingMsg
->msgHdr
.msgh_remote_port
= port
;
1028 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
1030 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1031 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
1032 pingMsg
->msgHdr
.msgh_size
= msgSize
;
1033 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
1035 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
1037 pingMsg
->ports
[0].name
= NULL
;
1038 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
1039 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
1041 pingMsg
->notifyHeader
.size
= extraSize
;
1042 pingMsg
->notifyHeader
.type
= type
;
1043 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
1049 IOServiceMessageUserNotification::invalidatePort(void)
1052 pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
1057 IOServiceMessageUserNotification::free( void )
1067 if (_pingMsg
&& _msgSize
) {
1068 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
1069 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
1071 IOFree( _pingMsg
, _msgSize
);
1076 IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
1077 UInt32 messageType
, IOService
* provider
,
1078 void * argument
, vm_size_t argSize
)
1080 return ((IOServiceMessageUserNotification
*) target
)->handler(
1081 ref
, messageType
, provider
, argument
, argSize
);
1085 IOServiceMessageUserNotification::handler( void * ref
,
1086 UInt32 messageType
, IOService
* provider
,
1087 void * messageArgument
, vm_size_t callerArgSize
)
1089 enum { kLocalMsgSize
= 0x100 };
1090 uint64_t stackMsg
[kLocalMsgSize
/ sizeof(uint64_t)];
1094 vm_size_t thisMsgSize
;
1095 ipc_port_t thisPort
, providerPort
;
1096 struct PingMsg
* thisMsg
;
1097 IOServiceInterestContent64
* data
;
1099 if (kIOMessageCopyClientID
== messageType
) {
1100 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
1101 return kIOReturnSuccess
;
1104 if (callerArgSize
== 0) {
1106 argSize
= sizeof(data
->messageArgument
[0]);
1108 argSize
= sizeof(uint32_t);
1111 if (callerArgSize
> kIOUserNotifyMaxMessageSize
) {
1112 callerArgSize
= kIOUserNotifyMaxMessageSize
;
1114 argSize
= callerArgSize
;
1117 // adjust message size for ipc restrictions
1119 type
= pingMsg
->notifyHeader
.type
;
1120 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
1121 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
1122 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
1124 thisMsgSize
= msgSize
1125 + sizeof(IOServiceInterestContent64
)
1126 - sizeof(data
->messageArgument
)
1129 if (thisMsgSize
> sizeof(stackMsg
)) {
1130 allocMsg
= IOMalloc(thisMsgSize
);
1132 return kIOReturnNoMemory
;
1134 thisMsg
= (typeof(thisMsg
))allocMsg
;
1137 thisMsg
= (typeof(thisMsg
))stackMsg
;
1140 bcopy(pingMsg
, thisMsg
, msgSize
);
1141 thisMsg
->notifyHeader
.type
= type
;
1142 data
= (IOServiceInterestContent64
*) (((uint8_t *) thisMsg
) + msgSize
);
1143 // == pingMsg->notifyHeader.content;
1144 data
->messageType
= messageType
;
1146 if (callerArgSize
== 0) {
1147 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
1149 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
1152 bcopy( messageArgument
, data
->messageArgument
, callerArgSize
);
1153 bzero((void *)(((uintptr_t) &data
->messageArgument
[0]) + callerArgSize
), argSize
- callerArgSize
);
1156 thisMsg
->notifyHeader
.type
= type
;
1157 thisMsg
->msgHdr
.msgh_size
= thisMsgSize
;
1159 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
1160 thisMsg
->ports
[0].name
= providerPort
;
1161 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
1162 thisMsg
->msgHdr
.msgh_local_port
= thisPort
;
1164 kr
= mach_msg_send_from_kernel_with_options( &thisMsg
->msgHdr
,
1165 thisMsg
->msgHdr
.msgh_size
,
1166 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
1169 iokit_release_port( thisPort
);
1172 iokit_release_port( providerPort
);
1176 IOFree(allocMsg
, thisMsgSize
);
1179 if ((KERN_SUCCESS
!= kr
) && !ipcLogged
) {
1181 IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1184 return kIOReturnSuccess
;
1188 IOServiceMessageUserNotification::getNextObject()
1194 IOServiceMessageUserNotification::copyNextObject()
1199 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1202 #define super IOService
1203 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1205 IOLock
* gIOUserClientOwnersLock
;
1208 IOUserClient::initialize( void )
1210 gIOObjectPortLock
= IOLockAlloc();
1211 gIOUserClientOwnersLock
= IOLockAlloc();
1212 gIOUserServerLock
= IOLockAlloc();
1213 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1217 IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1218 mach_port_t wakePort
,
1219 void *callback
, void *refcon
)
1221 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1222 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1223 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1224 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1228 IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1229 mach_port_t wakePort
,
1230 mach_vm_address_t callback
, io_user_reference_t refcon
)
1232 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1233 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1234 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1235 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1239 IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1240 mach_port_t wakePort
,
1241 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1243 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1244 if (vm_map_is_64bit(get_task_map(task
))) {
1245 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1249 static OSDictionary
*
1250 CopyConsoleUser(UInt32 uid
)
1253 OSDictionary
* user
= NULL
;
1255 if ((array
= OSDynamicCast(OSArray
,
1256 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
)))) {
1257 for (unsigned int idx
= 0;
1258 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1262 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1263 && (uid
== num
->unsigned32BitValue())) {
1273 static OSDictionary
*
1274 CopyUserOnConsole(void)
1277 OSDictionary
* user
= NULL
;
1279 if ((array
= OSDynamicCast(OSArray
,
1280 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
)))) {
1281 for (unsigned int idx
= 0;
1282 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1284 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
)) {
1295 IOUserClient::clientHasAuthorization( task_t task
,
1296 IOService
* service
)
1300 p
= (proc_t
) get_bsdtask_info(task
);
1302 uint64_t authorizationID
;
1304 authorizationID
= proc_uniqueid(p
);
1305 if (authorizationID
) {
1306 if (service
->getAuthorizationID() == authorizationID
) {
1307 return kIOReturnSuccess
;
1312 return kIOReturnNotPermitted
;
1316 IOUserClient::clientHasPrivilege( void * securityToken
,
1317 const char * privilegeName
)
1320 security_token_t token
;
1321 mach_msg_type_number_t count
;
1323 OSDictionary
* user
;
1327 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1328 sizeof(kIOClientPrivilegeForeground
))) {
1329 if (task_is_gpu_denied(current_task())) {
1330 return kIOReturnNotPrivileged
;
1332 return kIOReturnSuccess
;
1336 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1337 sizeof(kIOClientPrivilegeConsoleSession
))) {
1341 task
= (task_t
) securityToken
;
1343 task
= current_task();
1345 p
= (proc_t
) get_bsdtask_info(task
);
1346 kr
= kIOReturnNotPrivileged
;
1348 if (p
&& (cred
= kauth_cred_proc_ref(p
))) {
1349 user
= CopyUserOnConsole();
1352 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1353 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue())) {
1354 kr
= kIOReturnSuccess
;
1358 kauth_cred_unref(&cred
);
1363 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1364 sizeof(kIOClientPrivilegeSecureConsoleProcess
)))) {
1365 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1367 task
= (task_t
)securityToken
;
1370 count
= TASK_SECURITY_TOKEN_COUNT
;
1371 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1373 if (KERN_SUCCESS
!= kr
) {
1374 } else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1375 sizeof(kIOClientPrivilegeAdministrator
))) {
1376 if (0 != token
.val
[0]) {
1377 kr
= kIOReturnNotPrivileged
;
1379 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1380 sizeof(kIOClientPrivilegeLocalUser
))) {
1381 user
= CopyConsoleUser(token
.val
[0]);
1385 kr
= kIOReturnNotPrivileged
;
1387 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1388 sizeof(kIOClientPrivilegeConsoleUser
))) {
1389 user
= CopyConsoleUser(token
.val
[0]);
1391 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
) {
1392 kr
= kIOReturnNotPrivileged
;
1393 } else if (secureConsole
) {
1394 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1395 if (pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
) {
1396 kr
= kIOReturnNotPrivileged
;
1401 kr
= kIOReturnNotPrivileged
;
1404 kr
= kIOReturnUnsupported
;
1411 IOUserClient::copyClientEntitlements(task_t task
)
1413 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1418 void *entitlements_blob
= NULL
;
1419 char *entitlements_data
= NULL
;
1420 OSObject
*entitlements_obj
= NULL
;
1421 OSDictionary
*entitlements
= NULL
;
1422 OSString
*errorString
= NULL
;
1424 p
= (proc_t
)get_bsdtask_info(task
);
1430 if (cs_entitlements_dictionary_copy(p
, (void **)&entitlements
) == 0) {
1432 return entitlements
;
1436 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0) {
1440 if (len
<= offsetof(CS_GenericBlob
, data
)) {
1445 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1446 * we'll try to parse in the kernel.
1448 len
-= offsetof(CS_GenericBlob
, data
);
1449 if (len
> MAX_ENTITLEMENTS_LEN
) {
1450 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n",
1451 proc_best_name(p
), pid
, len
, MAX_ENTITLEMENTS_LEN
);
1456 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1457 * what is stored in the entitlements blob. Copy the string and
1460 entitlements_data
= (char *)IOMalloc(len
+ 1);
1461 if (entitlements_data
== NULL
) {
1464 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1465 entitlements_data
[len
] = '\0';
1467 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1468 if (errorString
!= NULL
) {
1469 IOLog("failed to parse entitlements for %s[%u]: %s\n",
1470 proc_best_name(p
), pid
, errorString
->getCStringNoCopy());
1473 if (entitlements_obj
== NULL
) {
1477 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1478 if (entitlements
== NULL
) {
1481 entitlements_obj
= NULL
;
1484 if (entitlements_data
!= NULL
) {
1485 IOFree(entitlements_data
, len
+ 1);
1487 if (entitlements_obj
!= NULL
) {
1488 entitlements_obj
->release();
1490 if (errorString
!= NULL
) {
1491 errorString
->release();
1493 return entitlements
;
1497 IOUserClient::copyClientEntitlement( task_t task
,
1498 const char * entitlement
)
1500 OSDictionary
*entitlements
;
1503 entitlements
= copyClientEntitlements(task
);
1504 if (entitlements
== NULL
) {
1508 /* Fetch the entitlement value from the dictionary. */
1509 value
= entitlements
->getObject(entitlement
);
1510 if (value
!= NULL
) {
1514 entitlements
->release();
1519 IOUserClient::init()
1521 if (getPropertyTable() || super::init()) {
1529 IOUserClient::init(OSDictionary
* dictionary
)
1531 if (getPropertyTable() || super::init(dictionary
)) {
1539 IOUserClient::initWithTask(task_t owningTask
,
1543 if (getPropertyTable() || super::init()) {
1551 IOUserClient::initWithTask(task_t owningTask
,
1554 OSDictionary
* properties
)
1558 ok
= super::init( properties
);
1559 ok
&= initWithTask( owningTask
, securityID
, type
);
1565 IOUserClient::reserve()
1568 reserved
= IONew(ExpansionData
, 1);
1573 setTerminateDefer(NULL
, true);
1574 IOStatisticsRegisterCounter();
1579 struct IOUserClientOwner
{
1581 queue_chain_t taskLink
;
1583 queue_chain_t ucLink
;
1587 IOUserClient::registerOwner(task_t task
)
1589 IOUserClientOwner
* owner
;
1593 IOLockLock(gIOUserClientOwnersLock
);
1596 ret
= kIOReturnSuccess
;
1599 queue_init(&owners
);
1601 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1603 if (task
!= owner
->task
) {
1611 owner
= IONew(IOUserClientOwner
, 1);
1613 ret
= kIOReturnNoMemory
;
1617 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1618 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1619 if (messageAppSuspended
) {
1620 task_set_message_app_suspended(task
, true);
1625 IOLockUnlock(gIOUserClientOwnersLock
);
1631 IOUserClient::noMoreSenders(void)
1633 IOUserClientOwner
* owner
;
1634 IOUserClientOwner
* iter
;
1635 queue_head_t
* taskque
;
1636 bool hasMessageAppSuspended
;
1638 IOLockLock(gIOUserClientOwnersLock
);
1641 while (!queue_empty(&owners
)) {
1642 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1643 taskque
= task_io_user_clients(owner
->task
);
1644 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1645 hasMessageAppSuspended
= false;
1646 queue_iterate(taskque
, iter
, IOUserClientOwner
*, taskLink
) {
1647 hasMessageAppSuspended
= iter
->uc
->messageAppSuspended
;
1648 if (hasMessageAppSuspended
) {
1652 task_set_message_app_suspended(owner
->task
, hasMessageAppSuspended
);
1653 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1654 IODelete(owner
, IOUserClientOwner
, 1);
1656 owners
.next
= owners
.prev
= NULL
;
1659 IOLockUnlock(gIOUserClientOwnersLock
);
1664 iokit_task_app_suspended_changed(task_t task
)
1666 queue_head_t
* taskque
;
1667 IOUserClientOwner
* owner
;
1670 IOLockLock(gIOUserClientOwnersLock
);
1672 taskque
= task_io_user_clients(task
);
1674 queue_iterate(taskque
, owner
, IOUserClientOwner
*, taskLink
) {
1675 if (!owner
->uc
->messageAppSuspended
) {
1679 set
= OSSet::withCapacity(4);
1684 set
->setObject(owner
->uc
);
1687 IOLockUnlock(gIOUserClientOwnersLock
);
1690 set
->iterateObjects(^bool (OSObject
* obj
) {
1693 uc
= (typeof(uc
))obj
;
1697 str
= IOCopyLogNameForPID(task_pid(task
));
1698 IOLog("iokit_task_app_suspended_changed(%s) %s %d\n", str
? str
->getCStringNoCopy() : "",
1699 uc
->getName(), task_is_app_suspended(task
));
1700 OSSafeReleaseNULL(str
);
1703 uc
->message(kIOMessageTaskAppSuspendedChange
, NULL
);
1711 extern "C" kern_return_t
1712 iokit_task_terminate(task_t task
)
1714 IOUserClientOwner
* owner
;
1715 IOUserClient
* dead
;
1717 queue_head_t
* taskque
;
1719 IOLockLock(gIOUserClientOwnersLock
);
1721 taskque
= task_io_user_clients(task
);
1723 while (!queue_empty(taskque
)) {
1724 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1726 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1727 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1728 if (queue_empty(&uc
->owners
)) {
1730 IOLog("destroying out of band connect for %s\n", uc
->getName());
1731 // now using the uc queue head as a singly linked queue,
1732 // leaving .next as NULL to mark it empty
1733 uc
->owners
.next
= NULL
;
1734 uc
->owners
.prev
= (queue_entry_t
) dead
;
1737 IODelete(owner
, IOUserClientOwner
, 1);
1740 IOLockUnlock(gIOUserClientOwnersLock
);
1744 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1745 uc
->owners
.prev
= NULL
;
1746 if (uc
->sharedInstance
|| !uc
->closed
) {
1752 return KERN_SUCCESS
;
1756 IOUserClient::free()
1759 mappings
->release();
1765 IOStatisticsUnregisterCounter();
1767 assert(!owners
.next
);
1768 assert(!owners
.prev
);
1771 IODelete(reserved
, ExpansionData
, 1);
1778 IOUserClient::clientDied( void )
1780 IOReturn ret
= kIOReturnNotReady
;
1782 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
)) {
1783 ret
= clientClose();
1790 IOUserClient::clientClose( void )
1792 return kIOReturnUnsupported
;
1796 IOUserClient::getService( void )
1802 IOUserClient::registerNotificationPort(
1803 mach_port_t
/* port */,
1805 UInt32
/* refCon */)
1807 return kIOReturnUnsupported
;
1811 IOUserClient::registerNotificationPort(
1814 io_user_reference_t refCon
)
1816 return registerNotificationPort(port
, type
, (UInt32
) refCon
);
1820 IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1821 semaphore_t
* semaphore
)
1823 return kIOReturnUnsupported
;
1827 IOUserClient::connectClient( IOUserClient
* /* client */ )
1829 return kIOReturnUnsupported
;
1833 IOUserClient::clientMemoryForType( UInt32 type
,
1834 IOOptionBits
* options
,
1835 IOMemoryDescriptor
** memory
)
1837 return kIOReturnUnsupported
;
1842 IOUserClient::mapClientMemory(
1845 IOOptionBits mapFlags
,
1846 IOVirtualAddress atAddress
)
1853 IOUserClient::mapClientMemory64(
1856 IOOptionBits mapFlags
,
1857 mach_vm_address_t atAddress
)
1860 IOOptionBits options
= 0;
1861 IOMemoryDescriptor
* memory
= NULL
;
1862 IOMemoryMap
* map
= NULL
;
1864 err
= clientMemoryForType((UInt32
) type
, &options
, &memory
);
1866 if (memory
&& (kIOReturnSuccess
== err
)) {
1867 FAKE_STACK_FRAME(getMetaClass());
1869 options
= (options
& ~kIOMapUserOptionsMask
)
1870 | (mapFlags
& kIOMapUserOptionsMask
);
1871 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1874 FAKE_STACK_FRAME_END();
1881 IOUserClient::exportObjectToClient(task_t task
,
1882 OSObject
*obj
, io_object_t
*clientObj
)
1884 mach_port_name_t name
;
1886 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1888 *clientObj
= (io_object_t
)(uintptr_t) name
;
1894 return kIOReturnSuccess
;
1898 IOUserClient::copyPortNameForObjectInTask(task_t task
,
1899 OSObject
*obj
, mach_port_name_t
* port_name
)
1901 mach_port_name_t name
;
1903 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_IDENT
);
1905 *(mach_port_name_t
*) port_name
= name
;
1907 return kIOReturnSuccess
;
1911 IOUserClient::copyObjectForPortNameInTask(task_t task
, mach_port_name_t port_name
,
1916 object
= iokit_lookup_object_with_port_name(port_name
, IKOT_IOKIT_IDENT
, task
);
1920 return object
? kIOReturnSuccess
: kIOReturnIPCError
;
1924 IOUserClient::adjustPortNameReferencesInTask(task_t task
, mach_port_name_t port_name
, mach_port_delta_t delta
)
1926 return iokit_mod_send_right(task
, port_name
, delta
);
1930 IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1935 IOExternalAsyncMethod
*
1936 IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1943 getExternalTrapForIndex(UInt32 index
)
1948 #pragma clang diagnostic push
1949 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1951 // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
1952 // functions can break clients of kexts implementing getExternalMethodForIndex()
1955 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1957 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1960 *targetP
= (IOService
*) method
->object
;
1966 IOExternalAsyncMethod
*
1968 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1970 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1973 *targetP
= (IOService
*) method
->object
;
1981 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1983 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1986 *targetP
= trap
->object
;
1991 #pragma clang diagnostic pop
1994 IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1997 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1999 if (MACH_PORT_NULL
!= port
) {
2000 iokit_release_port_send(port
);
2003 return kIOReturnSuccess
;
2007 IOUserClient::releaseNotificationPort(mach_port_t port
)
2009 if (MACH_PORT_NULL
!= port
) {
2010 iokit_release_port_send(port
);
2013 return kIOReturnSuccess
;
2017 IOUserClient::sendAsyncResult(OSAsyncReference reference
,
2018 IOReturn result
, void *args
[], UInt32 numArgs
)
2020 OSAsyncReference64 reference64
;
2021 io_user_reference_t args64
[kMaxAsyncArgs
];
2024 if (numArgs
> kMaxAsyncArgs
) {
2025 return kIOReturnMessageTooLarge
;
2028 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++) {
2029 reference64
[idx
] = REF64(reference
[idx
]);
2032 for (idx
= 0; idx
< numArgs
; idx
++) {
2033 args64
[idx
] = REF64(args
[idx
]);
2036 return sendAsyncResult64(reference64
, result
, args64
, numArgs
);
2040 IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
2041 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
2043 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
2047 IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
2048 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
2050 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
2054 IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
2055 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
2058 mach_msg_header_t msgHdr
;
2061 OSNotificationHeader notifyHdr
;
2062 IOAsyncCompletionContent asyncContent
;
2063 uint32_t args
[kMaxAsyncArgs
];
2066 OSNotificationHeader64 notifyHdr
;
2067 IOAsyncCompletionContent asyncContent
;
2068 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
2073 mach_port_t replyPort
;
2076 // If no reply port, do nothing.
2077 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
2078 if (replyPort
== MACH_PORT_NULL
) {
2079 return kIOReturnSuccess
;
2082 if (numArgs
> kMaxAsyncArgs
) {
2083 return kIOReturnMessageTooLarge
;
2086 bzero(&replyMsg
, sizeof(replyMsg
));
2087 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
2089 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
2090 replyMsg
.msgHdr
.msgh_local_port
= NULL
;
2091 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
2092 if (kIOUCAsync64Flag
& reference
[0]) {
2093 replyMsg
.msgHdr
.msgh_size
=
2094 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
2095 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
2096 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
2097 + numArgs
* sizeof(io_user_reference_t
);
2098 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
2099 /* Copy reference except for reference[0], which is left as 0 from the earlier bzero */
2100 bcopy(&reference
[1], &replyMsg
.m
.msg64
.notifyHdr
.reference
[1], sizeof(OSAsyncReference64
) - sizeof(reference
[0]));
2102 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
2104 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
2109 replyMsg
.msgHdr
.msgh_size
=
2110 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
2111 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
2113 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
2114 + numArgs
* sizeof(uint32_t);
2115 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
2117 /* Skip reference[0] which is left as 0 from the earlier bzero */
2118 for (idx
= 1; idx
< kOSAsyncRefCount
; idx
++) {
2119 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
2122 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
2124 for (idx
= 0; idx
< numArgs
; idx
++) {
2125 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
2129 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
2130 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
2131 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
2133 /* Fail on full queue. */
2134 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
2135 replyMsg
.msgHdr
.msgh_size
);
2137 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
) && !(kIOUCAsyncErrorLoggedFlag
& reference
[0])) {
2138 reference
[0] |= kIOUCAsyncErrorLoggedFlag
;
2139 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
2145 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2148 #define CHECK(cls, obj, out) \
2150 if( !(out = OSDynamicCast( cls, obj))) \
2151 return( kIOReturnBadArgument )
2153 #define CHECKLOCKED(cls, obj, out) \
2154 IOUserIterator * oIter; \
2156 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
2157 return (kIOReturnBadArgument); \
2158 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
2159 return (kIOReturnBadArgument)
2161 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2163 // Create a vm_map_copy_t or kalloc'ed data for memory
2164 // to be copied out. ipc will free after the copyout.
2166 static kern_return_t
2167 copyoutkdata( const void * data
, vm_size_t len
,
2168 io_buf_ptr_t
* buf
)
2173 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
2174 false /* src_destroy */, ©
);
2176 assert( err
== KERN_SUCCESS
);
2177 if (err
== KERN_SUCCESS
) {
2178 *buf
= (char *) copy
;
2184 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2186 /* Routine io_server_version */
2188 is_io_server_version(
2189 mach_port_t master_port
,
2192 *version
= IOKIT_SERVER_VERSION
;
2193 return kIOReturnSuccess
;
2196 /* Routine io_object_get_class */
2198 is_io_object_get_class(
2200 io_name_t className
)
2202 const OSMetaClass
* my_obj
= NULL
;
2205 return kIOReturnBadArgument
;
2208 my_obj
= object
->getMetaClass();
2210 return kIOReturnNotFound
;
2213 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
2215 return kIOReturnSuccess
;
2218 /* Routine io_object_get_superclass */
2220 is_io_object_get_superclass(
2221 mach_port_t master_port
,
2223 io_name_t class_name
)
2226 const OSMetaClass
* meta
;
2227 const OSMetaClass
* super
;
2228 const OSSymbol
* name
;
2231 if (!obj_name
|| !class_name
) {
2232 return kIOReturnBadArgument
;
2234 if (master_port
!= master_device_port
) {
2235 return kIOReturnNotPrivileged
;
2238 ret
= kIOReturnNotFound
;
2241 name
= OSSymbol::withCString(obj_name
);
2245 meta
= OSMetaClass::copyMetaClassWithName(name
);
2249 super
= meta
->getSuperClass();
2253 cstr
= super
->getClassName();
2257 strlcpy(class_name
, cstr
, sizeof(io_name_t
));
2258 ret
= kIOReturnSuccess
;
2261 OSSafeReleaseNULL(name
);
2263 meta
->releaseMetaClass();
2269 /* Routine io_object_get_bundle_identifier */
2271 is_io_object_get_bundle_identifier(
2272 mach_port_t master_port
,
2274 io_name_t bundle_name
)
2277 const OSMetaClass
* meta
;
2278 const OSSymbol
* name
;
2279 const OSSymbol
* identifier
;
2282 if (!obj_name
|| !bundle_name
) {
2283 return kIOReturnBadArgument
;
2285 if (master_port
!= master_device_port
) {
2286 return kIOReturnNotPrivileged
;
2289 ret
= kIOReturnNotFound
;
2292 name
= OSSymbol::withCString(obj_name
);
2296 meta
= OSMetaClass::copyMetaClassWithName(name
);
2300 identifier
= meta
->getKmodName();
2304 cstr
= identifier
->getCStringNoCopy();
2308 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
2309 ret
= kIOReturnSuccess
;
2312 OSSafeReleaseNULL(name
);
2314 meta
->releaseMetaClass();
2320 /* Routine io_object_conforms_to */
2322 is_io_object_conforms_to(
2324 io_name_t className
,
2325 boolean_t
*conforms
)
2328 return kIOReturnBadArgument
;
2331 *conforms
= (NULL
!= object
->metaCast( className
));
2333 return kIOReturnSuccess
;
2336 /* Routine io_object_get_retain_count */
2338 is_io_object_get_retain_count(
2340 uint32_t *retainCount
)
2343 return kIOReturnBadArgument
;
2346 *retainCount
= object
->getRetainCount();
2347 return kIOReturnSuccess
;
2350 /* Routine io_iterator_next */
2352 is_io_iterator_next(
2353 io_object_t iterator
,
2354 io_object_t
*object
)
2359 IOUserIterator
* uiter
;
2361 if ((uiter
= OSDynamicCast(IOUserIterator
, iterator
))) {
2362 obj
= uiter
->copyNextObject();
2363 } else if ((iter
= OSDynamicCast(OSIterator
, iterator
))) {
2364 obj
= iter
->getNextObject();
2369 return kIOReturnBadArgument
;
2374 ret
= kIOReturnSuccess
;
2376 ret
= kIOReturnNoDevice
;
2382 /* Routine io_iterator_reset */
2384 is_io_iterator_reset(
2385 io_object_t iterator
)
2387 CHECK( OSIterator
, iterator
, iter
);
2391 return kIOReturnSuccess
;
2394 /* Routine io_iterator_is_valid */
2396 is_io_iterator_is_valid(
2397 io_object_t iterator
,
2398 boolean_t
*is_valid
)
2400 CHECK( OSIterator
, iterator
, iter
);
2402 *is_valid
= iter
->isValid();
2404 return kIOReturnSuccess
;
2408 static kern_return_t
2409 internal_io_service_match_property_table(
2410 io_service_t _service
,
2411 const char * matching
,
2412 mach_msg_type_number_t matching_size
,
2415 CHECK( IOService
, _service
, service
);
2419 OSDictionary
* dict
;
2421 assert(matching_size
);
2422 obj
= OSUnserializeXML(matching
, matching_size
);
2424 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2425 *matches
= service
->passiveMatch( dict
);
2426 kr
= kIOReturnSuccess
;
2428 kr
= kIOReturnBadArgument
;
2438 /* Routine io_service_match_property_table */
2440 is_io_service_match_property_table(
2441 io_service_t service
,
2442 io_string_t matching
,
2443 boolean_t
*matches
)
2445 return kIOReturnUnsupported
;
2449 /* Routine io_service_match_property_table_ool */
2451 is_io_service_match_property_table_ool(
2452 io_object_t service
,
2453 io_buf_ptr_t matching
,
2454 mach_msg_type_number_t matchingCnt
,
2455 kern_return_t
*result
,
2456 boolean_t
*matches
)
2460 vm_map_offset_t map_data
;
2462 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2463 data
= CAST_DOWN(vm_offset_t
, map_data
);
2465 if (KERN_SUCCESS
== kr
) {
2466 // must return success after vm_map_copyout() succeeds
2467 *result
= internal_io_service_match_property_table(service
,
2468 (const char *)data
, matchingCnt
, matches
);
2469 vm_deallocate( kernel_map
, data
, matchingCnt
);
2475 /* Routine io_service_match_property_table_bin */
2477 is_io_service_match_property_table_bin(
2478 io_object_t service
,
2479 io_struct_inband_t matching
,
2480 mach_msg_type_number_t matchingCnt
,
2483 return internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
);
2486 static kern_return_t
2487 internal_io_service_get_matching_services(
2488 mach_port_t master_port
,
2489 const char * matching
,
2490 mach_msg_type_number_t matching_size
,
2491 io_iterator_t
*existing
)
2495 OSDictionary
* dict
;
2497 if (master_port
!= master_device_port
) {
2498 return kIOReturnNotPrivileged
;
2501 assert(matching_size
);
2502 obj
= OSUnserializeXML(matching
, matching_size
);
2504 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2505 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2506 kr
= kIOReturnSuccess
;
2508 kr
= kIOReturnBadArgument
;
2518 /* Routine io_service_get_matching_services */
2520 is_io_service_get_matching_services(
2521 mach_port_t master_port
,
2522 io_string_t matching
,
2523 io_iterator_t
*existing
)
2525 return kIOReturnUnsupported
;
2528 /* Routine io_service_get_matching_services_ool */
2530 is_io_service_get_matching_services_ool(
2531 mach_port_t master_port
,
2532 io_buf_ptr_t matching
,
2533 mach_msg_type_number_t matchingCnt
,
2534 kern_return_t
*result
,
2535 io_object_t
*existing
)
2539 vm_map_offset_t map_data
;
2541 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2542 data
= CAST_DOWN(vm_offset_t
, map_data
);
2544 if (KERN_SUCCESS
== kr
) {
2545 // must return success after vm_map_copyout() succeeds
2546 // and mig will copy out objects on success
2548 *result
= internal_io_service_get_matching_services(master_port
,
2549 (const char *) data
, matchingCnt
, existing
);
2550 vm_deallocate( kernel_map
, data
, matchingCnt
);
2556 /* Routine io_service_get_matching_services_bin */
2558 is_io_service_get_matching_services_bin(
2559 mach_port_t master_port
,
2560 io_struct_inband_t matching
,
2561 mach_msg_type_number_t matchingCnt
,
2562 io_object_t
*existing
)
2564 return internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
);
2568 static kern_return_t
2569 internal_io_service_get_matching_service(
2570 mach_port_t master_port
,
2571 const char * matching
,
2572 mach_msg_type_number_t matching_size
,
2573 io_service_t
*service
)
2577 OSDictionary
* dict
;
2579 if (master_port
!= master_device_port
) {
2580 return kIOReturnNotPrivileged
;
2583 assert(matching_size
);
2584 obj
= OSUnserializeXML(matching
, matching_size
);
2586 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2587 *service
= IOService::copyMatchingService( dict
);
2588 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2590 kr
= kIOReturnBadArgument
;
2600 /* Routine io_service_get_matching_service */
2602 is_io_service_get_matching_service(
2603 mach_port_t master_port
,
2604 io_string_t matching
,
2605 io_service_t
*service
)
2607 return kIOReturnUnsupported
;
2610 /* Routine io_service_get_matching_services_ool */
2612 is_io_service_get_matching_service_ool(
2613 mach_port_t master_port
,
2614 io_buf_ptr_t matching
,
2615 mach_msg_type_number_t matchingCnt
,
2616 kern_return_t
*result
,
2617 io_object_t
*service
)
2621 vm_map_offset_t map_data
;
2623 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2624 data
= CAST_DOWN(vm_offset_t
, map_data
);
2626 if (KERN_SUCCESS
== kr
) {
2627 // must return success after vm_map_copyout() succeeds
2628 // and mig will copy out objects on success
2630 *result
= internal_io_service_get_matching_service(master_port
,
2631 (const char *) data
, matchingCnt
, service
);
2632 vm_deallocate( kernel_map
, data
, matchingCnt
);
2638 /* Routine io_service_get_matching_service_bin */
2640 is_io_service_get_matching_service_bin(
2641 mach_port_t master_port
,
2642 io_struct_inband_t matching
,
2643 mach_msg_type_number_t matchingCnt
,
2644 io_object_t
*service
)
2646 return internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
);
2649 static kern_return_t
2650 internal_io_service_add_notification(
2651 mach_port_t master_port
,
2652 io_name_t notification_type
,
2653 const char * matching
,
2654 size_t matching_size
,
2657 vm_size_t referenceSize
,
2659 io_object_t
* notification
)
2661 IOServiceUserNotification
* userNotify
= NULL
;
2662 IONotifier
* notify
= NULL
;
2663 const OSSymbol
* sym
;
2664 OSDictionary
* dict
;
2666 unsigned long int userMsgType
;
2668 if (master_port
!= master_device_port
) {
2669 return kIOReturnNotPrivileged
;
2673 err
= kIOReturnNoResources
;
2675 if (matching_size
> (sizeof(io_struct_inband_t
) * 1024)) {
2676 return kIOReturnMessageTooLarge
;
2679 if (!(sym
= OSSymbol::withCString( notification_type
))) {
2680 err
= kIOReturnNoResources
;
2683 assert(matching_size
);
2684 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2686 err
= kIOReturnBadArgument
;
2690 if ((sym
== gIOPublishNotification
)
2691 || (sym
== gIOFirstPublishNotification
)) {
2692 userMsgType
= kIOServicePublishNotificationType
;
2693 } else if ((sym
== gIOMatchedNotification
)
2694 || (sym
== gIOFirstMatchNotification
)) {
2695 userMsgType
= kIOServiceMatchedNotificationType
;
2696 } else if ((sym
== gIOTerminatedNotification
)
2697 || (sym
== gIOWillTerminateNotification
)) {
2698 userMsgType
= kIOServiceTerminatedNotificationType
;
2700 userMsgType
= kLastIOKitNotificationType
;
2703 userNotify
= new IOServiceUserNotification
;
2705 if (userNotify
&& !userNotify
->init( port
, userMsgType
,
2706 reference
, referenceSize
, client64
)) {
2707 userNotify
->release();
2714 notify
= IOService::addMatchingNotification( sym
, dict
,
2715 &userNotify
->_handler
, userNotify
);
2717 *notification
= userNotify
;
2718 userNotify
->setNotification( notify
);
2719 err
= kIOReturnSuccess
;
2721 err
= kIOReturnUnsupported
;
2725 if ((kIOReturnSuccess
!= err
) && userNotify
) {
2726 userNotify
->invalidatePort();
2727 userNotify
->release();
2742 /* Routine io_service_add_notification */
2744 is_io_service_add_notification(
2745 mach_port_t master_port
,
2746 io_name_t notification_type
,
2747 io_string_t matching
,
2749 io_async_ref_t reference
,
2750 mach_msg_type_number_t referenceCnt
,
2751 io_object_t
* notification
)
2753 return kIOReturnUnsupported
;
2756 /* Routine io_service_add_notification_64 */
2758 is_io_service_add_notification_64(
2759 mach_port_t master_port
,
2760 io_name_t notification_type
,
2761 io_string_t matching
,
2762 mach_port_t wake_port
,
2763 io_async_ref64_t reference
,
2764 mach_msg_type_number_t referenceCnt
,
2765 io_object_t
*notification
)
2767 return kIOReturnUnsupported
;
2770 /* Routine io_service_add_notification_bin */
2772 is_io_service_add_notification_bin
2774 mach_port_t master_port
,
2775 io_name_t notification_type
,
2776 io_struct_inband_t matching
,
2777 mach_msg_type_number_t matchingCnt
,
2778 mach_port_t wake_port
,
2779 io_async_ref_t reference
,
2780 mach_msg_type_number_t referenceCnt
,
2781 io_object_t
*notification
)
2783 io_async_ref_t zreference
;
2785 if (referenceCnt
> ASYNC_REF_COUNT
) {
2786 return kIOReturnBadArgument
;
2788 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2789 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2791 return internal_io_service_add_notification(master_port
, notification_type
,
2792 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref_t
),
2793 false, notification
);
2796 /* Routine io_service_add_notification_bin_64 */
2798 is_io_service_add_notification_bin_64
2800 mach_port_t master_port
,
2801 io_name_t notification_type
,
2802 io_struct_inband_t matching
,
2803 mach_msg_type_number_t matchingCnt
,
2804 mach_port_t wake_port
,
2805 io_async_ref64_t reference
,
2806 mach_msg_type_number_t referenceCnt
,
2807 io_object_t
*notification
)
2809 io_async_ref64_t zreference
;
2811 if (referenceCnt
> ASYNC_REF64_COUNT
) {
2812 return kIOReturnBadArgument
;
2814 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2815 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2817 return internal_io_service_add_notification(master_port
, notification_type
,
2818 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref64_t
),
2819 true, notification
);
2822 static kern_return_t
2823 internal_io_service_add_notification_ool(
2824 mach_port_t master_port
,
2825 io_name_t notification_type
,
2826 io_buf_ptr_t matching
,
2827 mach_msg_type_number_t matchingCnt
,
2828 mach_port_t wake_port
,
2830 vm_size_t referenceSize
,
2832 kern_return_t
*result
,
2833 io_object_t
*notification
)
2837 vm_map_offset_t map_data
;
2839 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2840 data
= CAST_DOWN(vm_offset_t
, map_data
);
2842 if (KERN_SUCCESS
== kr
) {
2843 // must return success after vm_map_copyout() succeeds
2844 // and mig will copy out objects on success
2845 *notification
= NULL
;
2846 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2847 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2848 vm_deallocate( kernel_map
, data
, matchingCnt
);
2854 /* Routine io_service_add_notification_ool */
2856 is_io_service_add_notification_ool(
2857 mach_port_t master_port
,
2858 io_name_t notification_type
,
2859 io_buf_ptr_t matching
,
2860 mach_msg_type_number_t matchingCnt
,
2861 mach_port_t wake_port
,
2862 io_async_ref_t reference
,
2863 mach_msg_type_number_t referenceCnt
,
2864 kern_return_t
*result
,
2865 io_object_t
*notification
)
2867 io_async_ref_t zreference
;
2869 if (referenceCnt
> ASYNC_REF_COUNT
) {
2870 return kIOReturnBadArgument
;
2872 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2873 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2875 return internal_io_service_add_notification_ool(master_port
, notification_type
,
2876 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref_t
),
2877 false, result
, notification
);
2880 /* Routine io_service_add_notification_ool_64 */
2882 is_io_service_add_notification_ool_64(
2883 mach_port_t master_port
,
2884 io_name_t notification_type
,
2885 io_buf_ptr_t matching
,
2886 mach_msg_type_number_t matchingCnt
,
2887 mach_port_t wake_port
,
2888 io_async_ref64_t reference
,
2889 mach_msg_type_number_t referenceCnt
,
2890 kern_return_t
*result
,
2891 io_object_t
*notification
)
2893 io_async_ref64_t zreference
;
2895 if (referenceCnt
> ASYNC_REF64_COUNT
) {
2896 return kIOReturnBadArgument
;
2898 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2899 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2901 return internal_io_service_add_notification_ool(master_port
, notification_type
,
2902 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref64_t
),
2903 true, result
, notification
);
2906 /* Routine io_service_add_notification_old */
2908 is_io_service_add_notification_old(
2909 mach_port_t master_port
,
2910 io_name_t notification_type
,
2911 io_string_t matching
,
2913 // for binary compatibility reasons, this must be natural_t for ILP32
2915 io_object_t
* notification
)
2917 return is_io_service_add_notification( master_port
, notification_type
,
2918 matching
, port
, &ref
, 1, notification
);
2922 static kern_return_t
2923 internal_io_service_add_interest_notification(
2924 io_object_t _service
,
2925 io_name_t type_of_interest
,
2928 vm_size_t referenceSize
,
2930 io_object_t
* notification
)
2932 IOServiceMessageUserNotification
* userNotify
= NULL
;
2933 IONotifier
* notify
= NULL
;
2934 const OSSymbol
* sym
;
2937 CHECK( IOService
, _service
, service
);
2939 err
= kIOReturnNoResources
;
2940 if ((sym
= OSSymbol::withCString( type_of_interest
))) {
2942 userNotify
= new IOServiceMessageUserNotification
;
2944 if (userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2945 reference
, referenceSize
,
2946 kIOUserNotifyMaxMessageSize
,
2948 userNotify
->release();
2955 notify
= service
->registerInterest( sym
,
2956 &userNotify
->_handler
, userNotify
);
2958 *notification
= userNotify
;
2959 userNotify
->setNotification( notify
);
2960 err
= kIOReturnSuccess
;
2962 err
= kIOReturnUnsupported
;
2969 if ((kIOReturnSuccess
!= err
) && userNotify
) {
2970 userNotify
->invalidatePort();
2971 userNotify
->release();
2978 /* Routine io_service_add_message_notification */
2980 is_io_service_add_interest_notification(
2981 io_object_t service
,
2982 io_name_t type_of_interest
,
2984 io_async_ref_t reference
,
2985 mach_msg_type_number_t referenceCnt
,
2986 io_object_t
* notification
)
2988 io_async_ref_t zreference
;
2990 if (referenceCnt
> ASYNC_REF_COUNT
) {
2991 return kIOReturnBadArgument
;
2993 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2994 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2996 return internal_io_service_add_interest_notification(service
, type_of_interest
,
2997 port
, &zreference
[0], sizeof(io_async_ref_t
), false, notification
);
3000 /* Routine io_service_add_interest_notification_64 */
3002 is_io_service_add_interest_notification_64(
3003 io_object_t service
,
3004 io_name_t type_of_interest
,
3005 mach_port_t wake_port
,
3006 io_async_ref64_t reference
,
3007 mach_msg_type_number_t referenceCnt
,
3008 io_object_t
*notification
)
3010 io_async_ref64_t zreference
;
3012 if (referenceCnt
> ASYNC_REF64_COUNT
) {
3013 return kIOReturnBadArgument
;
3015 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
3016 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
3018 return internal_io_service_add_interest_notification(service
, type_of_interest
,
3019 wake_port
, &zreference
[0], sizeof(io_async_ref64_t
), true, notification
);
3023 /* Routine io_service_acknowledge_notification */
3025 is_io_service_acknowledge_notification(
3026 io_object_t _service
,
3027 natural_t notify_ref
,
3028 natural_t response
)
3030 CHECK( IOService
, _service
, service
);
3032 return service
->acknowledgeNotification((IONotificationRef
)(uintptr_t) notify_ref
,
3033 (IOOptionBits
) response
);
3036 /* Routine io_connect_get_semaphore */
3038 is_io_connect_get_notification_semaphore(
3039 io_connect_t connection
,
3040 natural_t notification_type
,
3041 semaphore_t
*semaphore
)
3043 CHECK( IOUserClient
, connection
, client
);
3045 IOStatisticsClientCall();
3046 return client
->getNotificationSemaphore((UInt32
) notification_type
,
3050 /* Routine io_registry_get_root_entry */
3052 is_io_registry_get_root_entry(
3053 mach_port_t master_port
,
3056 IORegistryEntry
* entry
;
3058 if (master_port
!= master_device_port
) {
3059 return kIOReturnNotPrivileged
;
3062 entry
= IORegistryEntry::getRegistryRoot();
3068 return kIOReturnSuccess
;
3071 /* Routine io_registry_create_iterator */
3073 is_io_registry_create_iterator(
3074 mach_port_t master_port
,
3077 io_object_t
*iterator
)
3079 if (master_port
!= master_device_port
) {
3080 return kIOReturnNotPrivileged
;
3083 *iterator
= IOUserIterator::withIterator(
3084 IORegistryIterator::iterateOver(
3085 IORegistryEntry::getPlane( plane
), options
));
3087 return *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
;
3090 /* Routine io_registry_entry_create_iterator */
3092 is_io_registry_entry_create_iterator(
3093 io_object_t registry_entry
,
3096 io_object_t
*iterator
)
3098 CHECK( IORegistryEntry
, registry_entry
, entry
);
3100 *iterator
= IOUserIterator::withIterator(
3101 IORegistryIterator::iterateOver( entry
,
3102 IORegistryEntry::getPlane( plane
), options
));
3104 return *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
;
3107 /* Routine io_registry_iterator_enter */
3109 is_io_registry_iterator_enter_entry(
3110 io_object_t iterator
)
3112 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
3114 IOLockLock(oIter
->lock
);
3116 IOLockUnlock(oIter
->lock
);
3118 return kIOReturnSuccess
;
3121 /* Routine io_registry_iterator_exit */
3123 is_io_registry_iterator_exit_entry(
3124 io_object_t iterator
)
3128 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
3130 IOLockLock(oIter
->lock
);
3131 didIt
= iter
->exitEntry();
3132 IOLockUnlock(oIter
->lock
);
3134 return didIt
? kIOReturnSuccess
: kIOReturnNoDevice
;
3137 /* Routine io_registry_entry_from_path */
3139 is_io_registry_entry_from_path(
3140 mach_port_t master_port
,
3142 io_object_t
*registry_entry
)
3144 IORegistryEntry
* entry
;
3146 if (master_port
!= master_device_port
) {
3147 return kIOReturnNotPrivileged
;
3150 entry
= IORegistryEntry::fromPath( path
);
3152 *registry_entry
= entry
;
3154 return kIOReturnSuccess
;
3158 /* Routine io_registry_entry_from_path */
3160 is_io_registry_entry_from_path_ool(
3161 mach_port_t master_port
,
3162 io_string_inband_t path
,
3163 io_buf_ptr_t path_ool
,
3164 mach_msg_type_number_t path_oolCnt
,
3165 kern_return_t
*result
,
3166 io_object_t
*registry_entry
)
3168 IORegistryEntry
* entry
;
3169 vm_map_offset_t map_data
;
3174 if (master_port
!= master_device_port
) {
3175 return kIOReturnNotPrivileged
;
3180 res
= err
= KERN_SUCCESS
;
3185 return kIOReturnBadArgument
;
3187 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) {
3188 return kIOReturnMessageTooLarge
;
3191 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
3192 if (KERN_SUCCESS
== err
) {
3193 // must return success to mig after vm_map_copyout() succeeds, so result is actual
3194 cpath
= CAST_DOWN(const char *, map_data
);
3195 if (cpath
[path_oolCnt
- 1]) {
3196 res
= kIOReturnBadArgument
;
3201 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
)) {
3202 entry
= IORegistryEntry::fromPath(cpath
);
3203 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
3207 vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
3210 if (KERN_SUCCESS
!= err
) {
3213 *registry_entry
= entry
;
3220 /* Routine io_registry_entry_in_plane */
3222 is_io_registry_entry_in_plane(
3223 io_object_t registry_entry
,
3225 boolean_t
*inPlane
)
3227 CHECK( IORegistryEntry
, registry_entry
, entry
);
3229 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
3231 return kIOReturnSuccess
;
3235 /* Routine io_registry_entry_get_path */
3237 is_io_registry_entry_get_path(
3238 io_object_t registry_entry
,
3243 CHECK( IORegistryEntry
, registry_entry
, entry
);
3245 length
= sizeof(io_string_t
);
3246 if (entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
))) {
3247 return kIOReturnSuccess
;
3249 return kIOReturnBadArgument
;
3253 /* Routine io_registry_entry_get_path */
3255 is_io_registry_entry_get_path_ool(
3256 io_object_t registry_entry
,
3258 io_string_inband_t path
,
3259 io_buf_ptr_t
*path_ool
,
3260 mach_msg_type_number_t
*path_oolCnt
)
3262 enum { kMaxPath
= 16384 };
3267 CHECK( IORegistryEntry
, registry_entry
, entry
);
3271 length
= sizeof(io_string_inband_t
);
3272 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) {
3273 err
= kIOReturnSuccess
;
3276 buf
= IONew(char, length
);
3278 err
= kIOReturnNoMemory
;
3279 } else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) {
3280 err
= kIOReturnError
;
3282 *path_oolCnt
= length
;
3283 err
= copyoutkdata(buf
, length
, path_ool
);
3286 IODelete(buf
, char, kMaxPath
);
3294 /* Routine io_registry_entry_get_name */
3296 is_io_registry_entry_get_name(
3297 io_object_t registry_entry
,
3300 CHECK( IORegistryEntry
, registry_entry
, entry
);
3302 strncpy( name
, entry
->getName(), sizeof(io_name_t
));
3304 return kIOReturnSuccess
;
3307 /* Routine io_registry_entry_get_name_in_plane */
3309 is_io_registry_entry_get_name_in_plane(
3310 io_object_t registry_entry
,
3311 io_name_t planeName
,
3314 const IORegistryPlane
* plane
;
3315 CHECK( IORegistryEntry
, registry_entry
, entry
);
3318 plane
= IORegistryEntry::getPlane( planeName
);
3323 strncpy( name
, entry
->getName( plane
), sizeof(io_name_t
));
3325 return kIOReturnSuccess
;
3328 /* Routine io_registry_entry_get_location_in_plane */
3330 is_io_registry_entry_get_location_in_plane(
3331 io_object_t registry_entry
,
3332 io_name_t planeName
,
3333 io_name_t location
)
3335 const IORegistryPlane
* plane
;
3336 CHECK( IORegistryEntry
, registry_entry
, entry
);
3339 plane
= IORegistryEntry::getPlane( planeName
);
3344 const char * cstr
= entry
->getLocation( plane
);
3347 strncpy( location
, cstr
, sizeof(io_name_t
));
3348 return kIOReturnSuccess
;
3350 return kIOReturnNotFound
;
3354 /* Routine io_registry_entry_get_registry_entry_id */
3356 is_io_registry_entry_get_registry_entry_id(
3357 io_object_t registry_entry
,
3358 uint64_t *entry_id
)
3360 CHECK( IORegistryEntry
, registry_entry
, entry
);
3362 *entry_id
= entry
->getRegistryEntryID();
3364 return kIOReturnSuccess
;
3367 /* Routine io_registry_entry_get_property */
3369 is_io_registry_entry_get_property_bytes(
3370 io_object_t registry_entry
,
3371 io_name_t property_name
,
3372 io_struct_inband_t buf
,
3373 mach_msg_type_number_t
*dataCnt
)
3381 unsigned int len
= 0;
3382 const void * bytes
= NULL
;
3383 IOReturn ret
= kIOReturnSuccess
;
3385 CHECK( IORegistryEntry
, registry_entry
, entry
);
3388 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3389 return kIOReturnNotPermitted
;
3393 obj
= entry
->copyProperty(property_name
);
3395 return kIOReturnNoResources
;
3398 // One day OSData will be a common container base class
3400 if ((data
= OSDynamicCast( OSData
, obj
))) {
3401 len
= data
->getLength();
3402 bytes
= data
->getBytesNoCopy();
3403 if (!data
->isSerializable()) {
3406 } else if ((str
= OSDynamicCast( OSString
, obj
))) {
3407 len
= str
->getLength() + 1;
3408 bytes
= str
->getCStringNoCopy();
3409 } else if ((boo
= OSDynamicCast( OSBoolean
, obj
))) {
3410 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
3411 bytes
= boo
->isTrue() ? "Yes" : "No";
3412 } else if ((off
= OSDynamicCast( OSNumber
, obj
))) {
3413 offsetBytes
= off
->unsigned64BitValue();
3414 len
= off
->numberOfBytes();
3415 if (len
> sizeof(offsetBytes
)) {
3416 len
= sizeof(offsetBytes
);
3418 bytes
= &offsetBytes
;
3419 #ifdef __BIG_ENDIAN__
3420 bytes
= (const void *)
3421 (((UInt32
) bytes
) + (sizeof(UInt64
) - len
));
3424 ret
= kIOReturnBadArgument
;
3428 if (*dataCnt
< len
) {
3429 ret
= kIOReturnIPCError
;
3432 bcopy( bytes
, buf
, len
);
3441 /* Routine io_registry_entry_get_property */
3443 is_io_registry_entry_get_property(
3444 io_object_t registry_entry
,
3445 io_name_t property_name
,
3446 io_buf_ptr_t
*properties
,
3447 mach_msg_type_number_t
*propertiesCnt
)
3453 CHECK( IORegistryEntry
, registry_entry
, entry
);
3456 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3457 return kIOReturnNotPermitted
;
3461 obj
= entry
->copyProperty(property_name
);
3463 return kIOReturnNotFound
;
3466 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3469 return kIOReturnNoMemory
;
3472 if (obj
->serialize( s
)) {
3473 len
= s
->getLength();
3474 *propertiesCnt
= len
;
3475 err
= copyoutkdata( s
->text(), len
, properties
);
3477 err
= kIOReturnUnsupported
;
3486 /* Routine io_registry_entry_get_property_recursively */
3488 is_io_registry_entry_get_property_recursively(
3489 io_object_t registry_entry
,
3491 io_name_t property_name
,
3493 io_buf_ptr_t
*properties
,
3494 mach_msg_type_number_t
*propertiesCnt
)
3500 CHECK( IORegistryEntry
, registry_entry
, entry
);
3503 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3504 return kIOReturnNotPermitted
;
3508 obj
= entry
->copyProperty( property_name
,
3509 IORegistryEntry::getPlane( plane
), options
);
3511 return kIOReturnNotFound
;
3514 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3517 return kIOReturnNoMemory
;
3520 if (obj
->serialize( s
)) {
3521 len
= s
->getLength();
3522 *propertiesCnt
= len
;
3523 err
= copyoutkdata( s
->text(), len
, properties
);
3525 err
= kIOReturnUnsupported
;
3534 /* Routine io_registry_entry_get_properties */
3536 is_io_registry_entry_get_properties(
3537 io_object_t registry_entry
,
3538 io_buf_ptr_t
*properties
,
3539 mach_msg_type_number_t
*propertiesCnt
)
3541 return kIOReturnUnsupported
;
3546 struct GetPropertiesEditorRef
{
3548 IORegistryEntry
* entry
;
3549 OSCollection
* root
;
3552 static const OSMetaClassBase
*
3553 GetPropertiesEditor(void * reference
,
3555 OSCollection
* container
,
3556 const OSSymbol
* name
,
3557 const OSMetaClassBase
* value
)
3559 GetPropertiesEditorRef
* ref
= (typeof(ref
))reference
;
3562 ref
->root
= container
;
3564 if (ref
->root
== container
) {
3565 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy())) {
3575 #endif /* CONFIG_MACF */
3577 /* Routine io_registry_entry_get_properties_bin_buf */
3579 is_io_registry_entry_get_properties_bin_buf(
3580 io_object_t registry_entry
,
3581 mach_vm_address_t buf
,
3582 mach_vm_size_t
*bufsize
,
3583 io_buf_ptr_t
*properties
,
3584 mach_msg_type_number_t
*propertiesCnt
)
3586 kern_return_t err
= kIOReturnSuccess
;
3589 OSSerialize::Editor editor
= NULL
;
3590 void * editRef
= NULL
;
3592 CHECK(IORegistryEntry
, registry_entry
, entry
);
3595 GetPropertiesEditorRef ref
;
3596 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
3597 editor
= &GetPropertiesEditor
;
3599 ref
.cred
= kauth_cred_get();
3605 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3607 return kIOReturnNoMemory
;
3610 if (!entry
->serializeProperties(s
)) {
3611 err
= kIOReturnUnsupported
;
3614 if (kIOReturnSuccess
== err
) {
3615 len
= s
->getLength();
3616 if (buf
&& bufsize
&& len
<= *bufsize
) {
3619 *properties
= nullptr;
3620 if (copyout(s
->text(), buf
, len
)) {
3621 err
= kIOReturnVMError
;
3623 err
= kIOReturnSuccess
;
3629 *propertiesCnt
= len
;
3630 err
= copyoutkdata( s
->text(), len
, properties
);
3638 /* Routine io_registry_entry_get_properties_bin */
3640 is_io_registry_entry_get_properties_bin(
3641 io_object_t registry_entry
,
3642 io_buf_ptr_t
*properties
,
3643 mach_msg_type_number_t
*propertiesCnt
)
3645 return is_io_registry_entry_get_properties_bin_buf(registry_entry
,
3646 0, NULL
, properties
, propertiesCnt
);
3649 /* Routine io_registry_entry_get_property_bin_buf */
3651 is_io_registry_entry_get_property_bin_buf(
3652 io_object_t registry_entry
,
3654 io_name_t property_name
,
3656 mach_vm_address_t buf
,
3657 mach_vm_size_t
*bufsize
,
3658 io_buf_ptr_t
*properties
,
3659 mach_msg_type_number_t
*propertiesCnt
)
3664 const OSSymbol
* sym
;
3666 CHECK( IORegistryEntry
, registry_entry
, entry
);
3669 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3670 return kIOReturnNotPermitted
;
3674 sym
= OSSymbol::withCString(property_name
);
3676 return kIOReturnNoMemory
;
3679 if (gIORegistryEntryPropertyKeysKey
== sym
) {
3680 obj
= entry
->copyPropertyKeys();
3682 if ((kIORegistryIterateRecursively
& options
) && plane
[0]) {
3683 obj
= entry
->copyProperty(property_name
,
3684 IORegistryEntry::getPlane(plane
), options
);
3686 obj
= entry
->copyProperty(property_name
);
3688 if (obj
&& gIORemoveOnReadProperties
->containsObject(sym
)) {
3689 entry
->removeProperty(sym
);
3695 return kIOReturnNotFound
;
3698 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3701 return kIOReturnNoMemory
;
3704 if (obj
->serialize( s
)) {
3705 len
= s
->getLength();
3706 if (buf
&& bufsize
&& len
<= *bufsize
) {
3709 *properties
= nullptr;
3710 if (copyout(s
->text(), buf
, len
)) {
3711 err
= kIOReturnVMError
;
3713 err
= kIOReturnSuccess
;
3719 *propertiesCnt
= len
;
3720 err
= copyoutkdata( s
->text(), len
, properties
);
3723 err
= kIOReturnUnsupported
;
3732 /* Routine io_registry_entry_get_property_bin */
3734 is_io_registry_entry_get_property_bin(
3735 io_object_t registry_entry
,
3737 io_name_t property_name
,
3739 io_buf_ptr_t
*properties
,
3740 mach_msg_type_number_t
*propertiesCnt
)
3742 return is_io_registry_entry_get_property_bin_buf(registry_entry
, plane
,
3743 property_name
, options
, 0, NULL
, properties
, propertiesCnt
);
3747 /* Routine io_registry_entry_set_properties */
3749 is_io_registry_entry_set_properties
3751 io_object_t registry_entry
,
3752 io_buf_ptr_t properties
,
3753 mach_msg_type_number_t propertiesCnt
,
3754 kern_return_t
* result
)
3760 vm_map_offset_t map_data
;
3762 CHECK( IORegistryEntry
, registry_entry
, entry
);
3764 if (propertiesCnt
> sizeof(io_struct_inband_t
) * 1024) {
3765 return kIOReturnMessageTooLarge
;
3768 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3769 data
= CAST_DOWN(vm_offset_t
, map_data
);
3771 if (KERN_SUCCESS
== err
) {
3772 FAKE_STACK_FRAME(entry
->getMetaClass());
3774 // must return success after vm_map_copyout() succeeds
3775 obj
= OSUnserializeXML((const char *) data
, propertiesCnt
);
3776 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3779 res
= kIOReturnBadArgument
;
3782 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3783 registry_entry
, obj
)) {
3784 res
= kIOReturnNotPermitted
;
3788 res
= entry
->setProperties( obj
);
3795 FAKE_STACK_FRAME_END();
3804 /* Routine io_registry_entry_get_child_iterator */
3806 is_io_registry_entry_get_child_iterator(
3807 io_object_t registry_entry
,
3809 io_object_t
*iterator
)
3811 CHECK( IORegistryEntry
, registry_entry
, entry
);
3813 *iterator
= IOUserIterator::withIterator(entry
->getChildIterator(
3814 IORegistryEntry::getPlane( plane
)));
3816 return kIOReturnSuccess
;
3819 /* Routine io_registry_entry_get_parent_iterator */
3821 is_io_registry_entry_get_parent_iterator(
3822 io_object_t registry_entry
,
3824 io_object_t
*iterator
)
3826 CHECK( IORegistryEntry
, registry_entry
, entry
);
3828 *iterator
= IOUserIterator::withIterator(entry
->getParentIterator(
3829 IORegistryEntry::getPlane( plane
)));
3831 return kIOReturnSuccess
;
3834 /* Routine io_service_get_busy_state */
3836 is_io_service_get_busy_state(
3837 io_object_t _service
,
3838 uint32_t *busyState
)
3840 CHECK( IOService
, _service
, service
);
3842 *busyState
= service
->getBusyState();
3844 return kIOReturnSuccess
;
3847 /* Routine io_service_get_state */
3849 is_io_service_get_state(
3850 io_object_t _service
,
3852 uint32_t *busy_state
,
3853 uint64_t *accumulated_busy_time
)
3855 CHECK( IOService
, _service
, service
);
3857 *state
= service
->getState();
3858 *busy_state
= service
->getBusyState();
3859 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3861 return kIOReturnSuccess
;
3864 /* Routine io_service_wait_quiet */
3866 is_io_service_wait_quiet(
3867 io_object_t _service
,
3868 mach_timespec_t wait_time
)
3872 CHECK( IOService
, _service
, service
);
3874 timeoutNS
= wait_time
.tv_sec
;
3875 timeoutNS
*= kSecondScale
;
3876 timeoutNS
+= wait_time
.tv_nsec
;
3878 return service
->waitQuiet(timeoutNS
);
3881 /* Routine io_service_request_probe */
3883 is_io_service_request_probe(
3884 io_object_t _service
,
3887 CHECK( IOService
, _service
, service
);
3889 return service
->requestProbe( options
);
3892 /* Routine io_service_get_authorization_id */
3894 is_io_service_get_authorization_id(
3895 io_object_t _service
,
3896 uint64_t *authorization_id
)
3900 CHECK( IOService
, _service
, service
);
3902 kr
= IOUserClient::clientHasPrivilege((void *) current_task(),
3903 kIOClientPrivilegeAdministrator
);
3904 if (kIOReturnSuccess
!= kr
) {
3908 *authorization_id
= service
->getAuthorizationID();
3913 /* Routine io_service_set_authorization_id */
3915 is_io_service_set_authorization_id(
3916 io_object_t _service
,
3917 uint64_t authorization_id
)
3919 CHECK( IOService
, _service
, service
);
3921 return service
->setAuthorizationID( authorization_id
);
3924 /* Routine io_service_open_ndr */
3926 is_io_service_open_extended(
3927 io_object_t _service
,
3929 uint32_t connect_type
,
3931 io_buf_ptr_t properties
,
3932 mach_msg_type_number_t propertiesCnt
,
3933 kern_return_t
* result
,
3934 io_object_t
*connection
)
3936 IOUserClient
* client
= NULL
;
3937 kern_return_t err
= KERN_SUCCESS
;
3938 IOReturn res
= kIOReturnSuccess
;
3939 OSDictionary
* propertiesDict
= NULL
;
3941 bool disallowAccess
;
3943 CHECK( IOService
, _service
, service
);
3946 return kIOReturnBadArgument
;
3948 assert(owningTask
== current_task());
3949 if (owningTask
!= current_task()) {
3950 return kIOReturnBadArgument
;
3955 return kIOReturnUnsupported
;
3961 vm_map_offset_t map_data
;
3963 if (propertiesCnt
> sizeof(io_struct_inband_t
)) {
3964 return kIOReturnMessageTooLarge
;
3967 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3969 data
= CAST_DOWN(vm_offset_t
, map_data
);
3970 if (KERN_SUCCESS
== err
) {
3971 // must return success after vm_map_copyout() succeeds
3972 obj
= OSUnserializeXML((const char *) data
, propertiesCnt
);
3973 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3974 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3975 if (!propertiesDict
) {
3976 res
= kIOReturnBadArgument
;
3982 if (kIOReturnSuccess
!= res
) {
3987 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3989 if (!propertiesDict
) {
3990 propertiesDict
= OSDictionary::withCapacity(4);
3992 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3994 if (propertiesDict
) {
3995 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
4001 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
4002 connect_type
, propertiesDict
, &client
);
4004 if (propertiesDict
) {
4005 propertiesDict
->release();
4008 if (res
== kIOReturnSuccess
) {
4009 assert( OSDynamicCast(IOUserClient
, client
));
4011 client
->sharedInstance
= (NULL
!= client
->getProperty(kIOUserClientSharedInstanceKey
));
4012 client
->messageAppSuspended
= (NULL
!= client
->getProperty(kIOUserClientMessageAppSuspendedKey
));
4013 client
->closed
= false;
4014 client
->lock
= IOLockAlloc();
4016 disallowAccess
= (crossEndian
4017 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
4018 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
4019 if (disallowAccess
) {
4020 res
= kIOReturnUnsupported
;
4023 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
)) {
4024 res
= kIOReturnNotPermitted
;
4028 if (kIOReturnSuccess
== res
) {
4029 res
= client
->registerOwner(owningTask
);
4032 if (kIOReturnSuccess
!= res
) {
4033 IOStatisticsClientCall();
4034 client
->clientClose();
4039 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
4041 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
4042 creatorName
->release();
4044 client
->setTerminateDefer(service
, false);
4048 *connection
= client
;
4054 /* Routine io_service_close */
4056 is_io_service_close(
4057 io_object_t connection
)
4060 if ((mappings
= OSDynamicCast(OSSet
, connection
))) {
4061 return kIOReturnSuccess
;
4064 CHECK( IOUserClient
, connection
, client
);
4066 IOStatisticsClientCall();
4068 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
)) {
4069 IOLockLock(client
->lock
);
4070 client
->clientClose();
4071 IOLockUnlock(client
->lock
);
4073 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
4074 client
->getRegistryEntryID(), client
->getName());
4077 return kIOReturnSuccess
;
4080 /* Routine io_connect_get_service */
4082 is_io_connect_get_service(
4083 io_object_t connection
,
4084 io_object_t
*service
)
4086 IOService
* theService
;
4088 CHECK( IOUserClient
, connection
, client
);
4090 theService
= client
->getService();
4092 theService
->retain();
4095 *service
= theService
;
4097 return theService
? kIOReturnSuccess
: kIOReturnUnsupported
;
4100 /* Routine io_connect_set_notification_port */
4102 is_io_connect_set_notification_port(
4103 io_object_t connection
,
4104 uint32_t notification_type
,
4109 CHECK( IOUserClient
, connection
, client
);
4111 IOStatisticsClientCall();
4112 IOLockLock(client
->lock
);
4113 ret
= client
->registerNotificationPort( port
, notification_type
,
4114 (io_user_reference_t
) reference
);
4115 IOLockUnlock(client
->lock
);
4119 /* Routine io_connect_set_notification_port */
4121 is_io_connect_set_notification_port_64(
4122 io_object_t connection
,
4123 uint32_t notification_type
,
4125 io_user_reference_t reference
)
4128 CHECK( IOUserClient
, connection
, client
);
4130 IOStatisticsClientCall();
4131 IOLockLock(client
->lock
);
4132 ret
= client
->registerNotificationPort( port
, notification_type
,
4134 IOLockUnlock(client
->lock
);
4138 /* Routine io_connect_map_memory_into_task */
4140 is_io_connect_map_memory_into_task
4142 io_connect_t connection
,
4143 uint32_t memory_type
,
4145 mach_vm_address_t
*address
,
4146 mach_vm_size_t
*size
,
4153 CHECK( IOUserClient
, connection
, client
);
4156 return kIOReturnBadArgument
;
4159 IOStatisticsClientCall();
4160 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
4163 *address
= map
->getAddress();
4165 *size
= map
->getSize();
4168 if (client
->sharedInstance
4169 || (into_task
!= current_task())) {
4170 // push a name out to the task owning the map,
4171 // so we can clean up maps
4172 mach_port_name_t name __unused
=
4173 IOMachPort::makeSendRightForTask(
4174 into_task
, map
, IKOT_IOKIT_OBJECT
);
4177 // keep it with the user client
4178 IOLockLock( gIOObjectPortLock
);
4179 if (NULL
== client
->mappings
) {
4180 client
->mappings
= OSSet::withCapacity(2);
4182 if (client
->mappings
) {
4183 client
->mappings
->setObject( map
);
4185 IOLockUnlock( gIOObjectPortLock
);
4188 err
= kIOReturnSuccess
;
4190 err
= kIOReturnBadArgument
;
4196 /* Routine is_io_connect_map_memory */
4198 is_io_connect_map_memory(
4199 io_object_t connect
,
4207 mach_vm_address_t address
;
4208 mach_vm_size_t size
;
4210 address
= SCALAR64(*mapAddr
);
4211 size
= SCALAR64(*mapSize
);
4213 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
4215 *mapAddr
= SCALAR32(address
);
4216 *mapSize
= SCALAR32(size
);
4223 IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
4226 IOMemoryMap
* map
= NULL
;
4228 IOLockLock(gIOObjectPortLock
);
4230 iter
= OSCollectionIterator::withCollection(mappings
);
4232 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject()))) {
4233 if (mem
== map
->getMemoryDescriptor()) {
4235 mappings
->removeObject(map
);
4242 IOLockUnlock(gIOObjectPortLock
);
4248 /* Routine io_connect_unmap_memory_from_task */
4250 is_io_connect_unmap_memory_from_task
4252 io_connect_t connection
,
4253 uint32_t memory_type
,
4255 mach_vm_address_t address
)
4258 IOOptionBits options
= 0;
4259 IOMemoryDescriptor
* memory
= NULL
;
4262 CHECK( IOUserClient
, connection
, client
);
4265 return kIOReturnBadArgument
;
4268 IOStatisticsClientCall();
4269 err
= client
->clientMemoryForType((UInt32
) memory_type
, &options
, &memory
);
4271 if (memory
&& (kIOReturnSuccess
== err
)) {
4272 options
= (options
& ~kIOMapUserOptionsMask
)
4273 | kIOMapAnywhere
| kIOMapReference
;
4275 map
= memory
->createMappingInTask( from_task
, address
, options
);
4278 IOLockLock( gIOObjectPortLock
);
4279 if (client
->mappings
) {
4280 client
->mappings
->removeObject( map
);
4282 IOLockUnlock( gIOObjectPortLock
);
4284 mach_port_name_t name
= 0;
4285 if (from_task
!= current_task()) {
4286 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
4291 map
->userClientUnmap();
4292 err
= iokit_mod_send_right( from_task
, name
, -2 );
4293 err
= kIOReturnSuccess
;
4295 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
4297 if (from_task
== current_task()) {
4301 err
= kIOReturnBadArgument
;
4309 is_io_connect_unmap_memory(
4310 io_object_t connect
,
4316 mach_vm_address_t address
;
4318 address
= SCALAR64(mapAddr
);
4320 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
4326 /* Routine io_connect_add_client */
4328 is_io_connect_add_client(
4329 io_object_t connection
,
4330 io_object_t connect_to
)
4332 CHECK( IOUserClient
, connection
, client
);
4333 CHECK( IOUserClient
, connect_to
, to
);
4335 IOStatisticsClientCall();
4336 return client
->connectClient( to
);
4340 /* Routine io_connect_set_properties */
4342 is_io_connect_set_properties(
4343 io_object_t connection
,
4344 io_buf_ptr_t properties
,
4345 mach_msg_type_number_t propertiesCnt
,
4346 kern_return_t
* result
)
4348 return is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
);
4351 /* Routine io_user_client_method */
4353 is_io_connect_method_var_output
4355 io_connect_t connection
,
4357 io_scalar_inband64_t scalar_input
,
4358 mach_msg_type_number_t scalar_inputCnt
,
4359 io_struct_inband_t inband_input
,
4360 mach_msg_type_number_t inband_inputCnt
,
4361 mach_vm_address_t ool_input
,
4362 mach_vm_size_t ool_input_size
,
4363 io_struct_inband_t inband_output
,
4364 mach_msg_type_number_t
*inband_outputCnt
,
4365 io_scalar_inband64_t scalar_output
,
4366 mach_msg_type_number_t
*scalar_outputCnt
,
4367 io_buf_ptr_t
*var_output
,
4368 mach_msg_type_number_t
*var_outputCnt
4371 CHECK( IOUserClient
, connection
, client
);
4373 IOExternalMethodArguments args
;
4375 IOMemoryDescriptor
* inputMD
= NULL
;
4376 OSObject
* structureVariableOutputData
= NULL
;
4378 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4379 args
.__reservedA
= 0;
4380 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4382 args
.selector
= selector
;
4384 args
.asyncWakePort
= MACH_PORT_NULL
;
4385 args
.asyncReference
= NULL
;
4386 args
.asyncReferenceCount
= 0;
4387 args
.structureVariableOutputData
= &structureVariableOutputData
;
4389 args
.scalarInput
= scalar_input
;
4390 args
.scalarInputCount
= scalar_inputCnt
;
4391 args
.structureInput
= inband_input
;
4392 args
.structureInputSize
= inband_inputCnt
;
4394 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4395 return kIOReturnIPCError
;
4399 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4400 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4404 args
.structureInputDescriptor
= inputMD
;
4406 args
.scalarOutput
= scalar_output
;
4407 args
.scalarOutputCount
= *scalar_outputCnt
;
4408 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4409 args
.structureOutput
= inband_output
;
4410 args
.structureOutputSize
= *inband_outputCnt
;
4411 args
.structureOutputDescriptor
= NULL
;
4412 args
.structureOutputDescriptorSize
= 0;
4414 IOStatisticsClientCall();
4415 ret
= client
->externalMethod( selector
, &args
);
4417 *scalar_outputCnt
= args
.scalarOutputCount
;
4418 *inband_outputCnt
= args
.structureOutputSize
;
4420 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
)) {
4421 OSSerialize
* serialize
;
4425 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
))) {
4426 len
= serialize
->getLength();
4427 *var_outputCnt
= len
;
4428 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
4429 } else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
))) {
4430 len
= data
->getLength();
4431 *var_outputCnt
= len
;
4432 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
4434 ret
= kIOReturnUnderrun
;
4441 if (structureVariableOutputData
) {
4442 structureVariableOutputData
->release();
4448 /* Routine io_user_client_method */
4450 is_io_connect_method
4452 io_connect_t connection
,
4454 io_scalar_inband64_t scalar_input
,
4455 mach_msg_type_number_t scalar_inputCnt
,
4456 io_struct_inband_t inband_input
,
4457 mach_msg_type_number_t inband_inputCnt
,
4458 mach_vm_address_t ool_input
,
4459 mach_vm_size_t ool_input_size
,
4460 io_struct_inband_t inband_output
,
4461 mach_msg_type_number_t
*inband_outputCnt
,
4462 io_scalar_inband64_t scalar_output
,
4463 mach_msg_type_number_t
*scalar_outputCnt
,
4464 mach_vm_address_t ool_output
,
4465 mach_vm_size_t
*ool_output_size
4468 CHECK( IOUserClient
, connection
, client
);
4470 IOExternalMethodArguments args
;
4472 IOMemoryDescriptor
* inputMD
= NULL
;
4473 IOMemoryDescriptor
* outputMD
= NULL
;
4475 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4476 args
.__reservedA
= 0;
4477 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4479 args
.selector
= selector
;
4481 args
.asyncWakePort
= MACH_PORT_NULL
;
4482 args
.asyncReference
= NULL
;
4483 args
.asyncReferenceCount
= 0;
4484 args
.structureVariableOutputData
= NULL
;
4486 args
.scalarInput
= scalar_input
;
4487 args
.scalarInputCount
= scalar_inputCnt
;
4488 args
.structureInput
= inband_input
;
4489 args
.structureInputSize
= inband_inputCnt
;
4491 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4492 return kIOReturnIPCError
;
4494 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) {
4495 return kIOReturnIPCError
;
4499 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4500 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4504 args
.structureInputDescriptor
= inputMD
;
4506 args
.scalarOutput
= scalar_output
;
4507 args
.scalarOutputCount
= *scalar_outputCnt
;
4508 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4509 args
.structureOutput
= inband_output
;
4510 args
.structureOutputSize
= *inband_outputCnt
;
4512 if (ool_output
&& ool_output_size
) {
4513 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4514 kIODirectionIn
, current_task());
4517 args
.structureOutputDescriptor
= outputMD
;
4518 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
4520 IOStatisticsClientCall();
4521 ret
= client
->externalMethod( selector
, &args
);
4523 *scalar_outputCnt
= args
.scalarOutputCount
;
4524 *inband_outputCnt
= args
.structureOutputSize
;
4525 *ool_output_size
= args
.structureOutputDescriptorSize
;
4531 outputMD
->release();
4537 /* Routine io_async_user_client_method */
4539 is_io_connect_async_method
4541 io_connect_t connection
,
4542 mach_port_t wake_port
,
4543 io_async_ref64_t reference
,
4544 mach_msg_type_number_t referenceCnt
,
4546 io_scalar_inband64_t scalar_input
,
4547 mach_msg_type_number_t scalar_inputCnt
,
4548 io_struct_inband_t inband_input
,
4549 mach_msg_type_number_t inband_inputCnt
,
4550 mach_vm_address_t ool_input
,
4551 mach_vm_size_t ool_input_size
,
4552 io_struct_inband_t inband_output
,
4553 mach_msg_type_number_t
*inband_outputCnt
,
4554 io_scalar_inband64_t scalar_output
,
4555 mach_msg_type_number_t
*scalar_outputCnt
,
4556 mach_vm_address_t ool_output
,
4557 mach_vm_size_t
* ool_output_size
4560 CHECK( IOUserClient
, connection
, client
);
4562 IOExternalMethodArguments args
;
4564 IOMemoryDescriptor
* inputMD
= NULL
;
4565 IOMemoryDescriptor
* outputMD
= NULL
;
4567 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4568 args
.__reservedA
= 0;
4569 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4571 reference
[0] = (io_user_reference_t
) wake_port
;
4572 if (vm_map_is_64bit(get_task_map(current_task()))) {
4573 reference
[0] |= kIOUCAsync64Flag
;
4576 args
.selector
= selector
;
4578 args
.asyncWakePort
= wake_port
;
4579 args
.asyncReference
= reference
;
4580 args
.asyncReferenceCount
= referenceCnt
;
4582 args
.structureVariableOutputData
= NULL
;
4584 args
.scalarInput
= scalar_input
;
4585 args
.scalarInputCount
= scalar_inputCnt
;
4586 args
.structureInput
= inband_input
;
4587 args
.structureInputSize
= inband_inputCnt
;
4589 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4590 return kIOReturnIPCError
;
4592 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) {
4593 return kIOReturnIPCError
;
4597 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4598 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4602 args
.structureInputDescriptor
= inputMD
;
4604 args
.scalarOutput
= scalar_output
;
4605 args
.scalarOutputCount
= *scalar_outputCnt
;
4606 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4607 args
.structureOutput
= inband_output
;
4608 args
.structureOutputSize
= *inband_outputCnt
;
4611 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4612 kIODirectionIn
, current_task());
4615 args
.structureOutputDescriptor
= outputMD
;
4616 args
.structureOutputDescriptorSize
= *ool_output_size
;
4618 IOStatisticsClientCall();
4619 ret
= client
->externalMethod( selector
, &args
);
4621 *scalar_outputCnt
= args
.scalarOutputCount
;
4622 *inband_outputCnt
= args
.structureOutputSize
;
4623 *ool_output_size
= args
.structureOutputDescriptorSize
;
4629 outputMD
->release();
4635 /* Routine io_connect_method_scalarI_scalarO */
4637 is_io_connect_method_scalarI_scalarO(
4638 io_object_t connect
,
4640 io_scalar_inband_t input
,
4641 mach_msg_type_number_t inputCount
,
4642 io_scalar_inband_t output
,
4643 mach_msg_type_number_t
* outputCount
)
4647 io_scalar_inband64_t _input
;
4648 io_scalar_inband64_t _output
;
4650 mach_msg_type_number_t struct_outputCnt
= 0;
4651 mach_vm_size_t ool_output_size
= 0;
4653 bzero(&_output
[0], sizeof(_output
));
4654 for (i
= 0; i
< inputCount
; i
++) {
4655 _input
[i
] = SCALAR64(input
[i
]);
4658 err
= is_io_connect_method(connect
, index
,
4662 NULL
, &struct_outputCnt
,
4663 _output
, outputCount
,
4664 0, &ool_output_size
);
4666 for (i
= 0; i
< *outputCount
; i
++) {
4667 output
[i
] = SCALAR32(_output
[i
]);
4674 shim_io_connect_method_scalarI_scalarO(
4675 IOExternalMethod
* method
,
4677 const io_user_scalar_t
* input
,
4678 mach_msg_type_number_t inputCount
,
4679 io_user_scalar_t
* output
,
4680 mach_msg_type_number_t
* outputCount
)
4683 io_scalar_inband_t _output
;
4685 err
= kIOReturnBadArgument
;
4687 bzero(&_output
[0], sizeof(_output
));
4689 if (inputCount
!= method
->count0
) {
4690 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4691 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4694 if (*outputCount
!= method
->count1
) {
4695 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4696 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4700 func
= method
->func
;
4702 switch (inputCount
) {
4704 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4705 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]));
4708 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4709 ARG32(input
[3]), ARG32(input
[4]),
4713 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4715 &_output
[0], &_output
[1] );
4718 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4719 &_output
[0], &_output
[1], &_output
[2] );
4722 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4723 &_output
[0], &_output
[1], &_output
[2],
4727 err
= (object
->*func
)( ARG32(input
[0]),
4728 &_output
[0], &_output
[1], &_output
[2],
4729 &_output
[3], &_output
[4] );
4732 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
4733 &_output
[3], &_output
[4], &_output
[5] );
4737 IOLog("%s: Bad method table\n", object
->getName());
4742 for (i
= 0; i
< *outputCount
; i
++) {
4743 output
[i
] = SCALAR32(_output
[i
]);
4749 /* Routine io_async_method_scalarI_scalarO */
4751 is_io_async_method_scalarI_scalarO(
4752 io_object_t connect
,
4753 mach_port_t wake_port
,
4754 io_async_ref_t reference
,
4755 mach_msg_type_number_t referenceCnt
,
4757 io_scalar_inband_t input
,
4758 mach_msg_type_number_t inputCount
,
4759 io_scalar_inband_t output
,
4760 mach_msg_type_number_t
* outputCount
)
4764 io_scalar_inband64_t _input
;
4765 io_scalar_inband64_t _output
;
4766 io_async_ref64_t _reference
;
4768 if (referenceCnt
> ASYNC_REF64_COUNT
) {
4769 return kIOReturnBadArgument
;
4771 bzero(&_output
[0], sizeof(_output
));
4772 for (i
= 0; i
< referenceCnt
; i
++) {
4773 _reference
[i
] = REF64(reference
[i
]);
4775 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
4777 mach_msg_type_number_t struct_outputCnt
= 0;
4778 mach_vm_size_t ool_output_size
= 0;
4780 for (i
= 0; i
< inputCount
; i
++) {
4781 _input
[i
] = SCALAR64(input
[i
]);
4784 err
= is_io_connect_async_method(connect
,
4785 wake_port
, _reference
, referenceCnt
,
4790 NULL
, &struct_outputCnt
,
4791 _output
, outputCount
,
4792 0, &ool_output_size
);
4794 for (i
= 0; i
< *outputCount
; i
++) {
4795 output
[i
] = SCALAR32(_output
[i
]);
4800 /* Routine io_async_method_scalarI_structureO */
4802 is_io_async_method_scalarI_structureO(
4803 io_object_t connect
,
4804 mach_port_t wake_port
,
4805 io_async_ref_t reference
,
4806 mach_msg_type_number_t referenceCnt
,
4808 io_scalar_inband_t input
,
4809 mach_msg_type_number_t inputCount
,
4810 io_struct_inband_t output
,
4811 mach_msg_type_number_t
* outputCount
)
4814 io_scalar_inband64_t _input
;
4815 io_async_ref64_t _reference
;
4817 if (referenceCnt
> ASYNC_REF64_COUNT
) {
4818 return kIOReturnBadArgument
;
4820 for (i
= 0; i
< referenceCnt
; i
++) {
4821 _reference
[i
] = REF64(reference
[i
]);
4823 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
4825 mach_msg_type_number_t scalar_outputCnt
= 0;
4826 mach_vm_size_t ool_output_size
= 0;
4828 for (i
= 0; i
< inputCount
; i
++) {
4829 _input
[i
] = SCALAR64(input
[i
]);
4832 return is_io_connect_async_method(connect
,
4833 wake_port
, _reference
, referenceCnt
,
4838 output
, outputCount
,
4839 NULL
, &scalar_outputCnt
,
4840 0, &ool_output_size
);
4843 /* Routine io_async_method_scalarI_structureI */
4845 is_io_async_method_scalarI_structureI(
4846 io_connect_t connect
,
4847 mach_port_t wake_port
,
4848 io_async_ref_t reference
,
4849 mach_msg_type_number_t referenceCnt
,
4851 io_scalar_inband_t input
,
4852 mach_msg_type_number_t inputCount
,
4853 io_struct_inband_t inputStruct
,
4854 mach_msg_type_number_t inputStructCount
)
4857 io_scalar_inband64_t _input
;
4858 io_async_ref64_t _reference
;
4860 if (referenceCnt
> ASYNC_REF64_COUNT
) {
4861 return kIOReturnBadArgument
;
4863 for (i
= 0; i
< referenceCnt
; i
++) {
4864 _reference
[i
] = REF64(reference
[i
]);
4866 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
4868 mach_msg_type_number_t scalar_outputCnt
= 0;
4869 mach_msg_type_number_t inband_outputCnt
= 0;
4870 mach_vm_size_t ool_output_size
= 0;
4872 for (i
= 0; i
< inputCount
; i
++) {
4873 _input
[i
] = SCALAR64(input
[i
]);
4876 return is_io_connect_async_method(connect
,
4877 wake_port
, _reference
, referenceCnt
,
4880 inputStruct
, inputStructCount
,
4882 NULL
, &inband_outputCnt
,
4883 NULL
, &scalar_outputCnt
,
4884 0, &ool_output_size
);
4887 /* Routine io_async_method_structureI_structureO */
4889 is_io_async_method_structureI_structureO(
4890 io_object_t connect
,
4891 mach_port_t wake_port
,
4892 io_async_ref_t reference
,
4893 mach_msg_type_number_t referenceCnt
,
4895 io_struct_inband_t input
,
4896 mach_msg_type_number_t inputCount
,
4897 io_struct_inband_t output
,
4898 mach_msg_type_number_t
* outputCount
)
4901 mach_msg_type_number_t scalar_outputCnt
= 0;
4902 mach_vm_size_t ool_output_size
= 0;
4903 io_async_ref64_t _reference
;
4905 if (referenceCnt
> ASYNC_REF64_COUNT
) {
4906 return kIOReturnBadArgument
;
4908 for (i
= 0; i
< referenceCnt
; i
++) {
4909 _reference
[i
] = REF64(reference
[i
]);
4911 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
4913 return is_io_connect_async_method(connect
,
4914 wake_port
, _reference
, referenceCnt
,
4919 output
, outputCount
,
4920 NULL
, &scalar_outputCnt
,
4921 0, &ool_output_size
);
4926 shim_io_async_method_scalarI_scalarO(
4927 IOExternalAsyncMethod
* method
,
4929 mach_port_t asyncWakePort
,
4930 io_user_reference_t
* asyncReference
,
4931 uint32_t asyncReferenceCount
,
4932 const io_user_scalar_t
* input
,
4933 mach_msg_type_number_t inputCount
,
4934 io_user_scalar_t
* output
,
4935 mach_msg_type_number_t
* outputCount
)
4939 io_scalar_inband_t _output
;
4941 io_async_ref_t reference
;
4943 bzero(&_output
[0], sizeof(_output
));
4944 for (i
= 0; i
< asyncReferenceCount
; i
++) {
4945 reference
[i
] = REF32(asyncReference
[i
]);
4948 err
= kIOReturnBadArgument
;
4951 if (inputCount
!= method
->count0
) {
4952 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4953 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4956 if (*outputCount
!= method
->count1
) {
4957 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4958 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4962 func
= method
->func
;
4964 switch (inputCount
) {
4966 err
= (object
->*func
)( reference
,
4967 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4968 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]));
4971 err
= (object
->*func
)( reference
,
4972 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4973 ARG32(input
[3]), ARG32(input
[4]),
4977 err
= (object
->*func
)( reference
,
4978 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4980 &_output
[0], &_output
[1] );
4983 err
= (object
->*func
)( reference
,
4984 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4985 &_output
[0], &_output
[1], &_output
[2] );
4988 err
= (object
->*func
)( reference
,
4989 ARG32(input
[0]), ARG32(input
[1]),
4990 &_output
[0], &_output
[1], &_output
[2],
4994 err
= (object
->*func
)( reference
,
4996 &_output
[0], &_output
[1], &_output
[2],
4997 &_output
[3], &_output
[4] );
5000 err
= (object
->*func
)( reference
,
5001 &_output
[0], &_output
[1], &_output
[2],
5002 &_output
[3], &_output
[4], &_output
[5] );
5006 IOLog("%s: Bad method table\n", object
->getName());
5010 for (i
= 0; i
< *outputCount
; i
++) {
5011 output
[i
] = SCALAR32(_output
[i
]);
5018 /* Routine io_connect_method_scalarI_structureO */
5020 is_io_connect_method_scalarI_structureO(
5021 io_object_t connect
,
5023 io_scalar_inband_t input
,
5024 mach_msg_type_number_t inputCount
,
5025 io_struct_inband_t output
,
5026 mach_msg_type_number_t
* outputCount
)
5029 io_scalar_inband64_t _input
;
5031 mach_msg_type_number_t scalar_outputCnt
= 0;
5032 mach_vm_size_t ool_output_size
= 0;
5034 for (i
= 0; i
< inputCount
; i
++) {
5035 _input
[i
] = SCALAR64(input
[i
]);
5038 return is_io_connect_method(connect
, index
,
5042 output
, outputCount
,
5043 NULL
, &scalar_outputCnt
,
5044 0, &ool_output_size
);
5048 shim_io_connect_method_scalarI_structureO(
5050 IOExternalMethod
* method
,
5052 const io_user_scalar_t
* input
,
5053 mach_msg_type_number_t inputCount
,
5054 io_struct_inband_t output
,
5055 IOByteCount
* outputCount
)
5060 err
= kIOReturnBadArgument
;
5063 if (inputCount
!= method
->count0
) {
5064 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5065 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5068 if ((kIOUCVariableStructureSize
!= method
->count1
)
5069 && (*outputCount
!= method
->count1
)) {
5070 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
);
5071 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5075 func
= method
->func
;
5077 switch (inputCount
) {
5079 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5080 ARG32(input
[3]), ARG32(input
[4]),
5084 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5086 output
, (void *)outputCount
);
5089 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5090 output
, (void *)outputCount
, NULL
);
5093 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
5094 output
, (void *)outputCount
, NULL
, NULL
);
5097 err
= (object
->*func
)( ARG32(input
[0]),
5098 output
, (void *)outputCount
, NULL
, NULL
, NULL
);
5101 err
= (object
->*func
)( output
, (void *)outputCount
, NULL
, NULL
, NULL
, NULL
);
5105 IOLog("%s: Bad method table\n", object
->getName());
5114 shim_io_async_method_scalarI_structureO(
5115 IOExternalAsyncMethod
* method
,
5117 mach_port_t asyncWakePort
,
5118 io_user_reference_t
* asyncReference
,
5119 uint32_t asyncReferenceCount
,
5120 const io_user_scalar_t
* input
,
5121 mach_msg_type_number_t inputCount
,
5122 io_struct_inband_t output
,
5123 mach_msg_type_number_t
* outputCount
)
5128 io_async_ref_t reference
;
5130 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5131 reference
[i
] = REF32(asyncReference
[i
]);
5134 err
= kIOReturnBadArgument
;
5136 if (inputCount
!= method
->count0
) {
5137 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5138 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5141 if ((kIOUCVariableStructureSize
!= method
->count1
)
5142 && (*outputCount
!= method
->count1
)) {
5143 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
);
5144 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5148 func
= method
->func
;
5150 switch (inputCount
) {
5152 err
= (object
->*func
)( reference
,
5153 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5154 ARG32(input
[3]), ARG32(input
[4]),
5158 err
= (object
->*func
)( reference
,
5159 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5161 output
, (void *)outputCount
);
5164 err
= (object
->*func
)( reference
,
5165 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5166 output
, (void *)outputCount
, NULL
);
5169 err
= (object
->*func
)( reference
,
5170 ARG32(input
[0]), ARG32(input
[1]),
5171 output
, (void *)outputCount
, NULL
, NULL
);
5174 err
= (object
->*func
)( reference
,
5176 output
, (void *)outputCount
, NULL
, NULL
, NULL
);
5179 err
= (object
->*func
)( reference
,
5180 output
, (void *)outputCount
, NULL
, NULL
, NULL
, NULL
);
5184 IOLog("%s: Bad method table\n", object
->getName());
5191 /* Routine io_connect_method_scalarI_structureI */
5193 is_io_connect_method_scalarI_structureI(
5194 io_connect_t connect
,
5196 io_scalar_inband_t input
,
5197 mach_msg_type_number_t inputCount
,
5198 io_struct_inband_t inputStruct
,
5199 mach_msg_type_number_t inputStructCount
)
5202 io_scalar_inband64_t _input
;
5204 mach_msg_type_number_t scalar_outputCnt
= 0;
5205 mach_msg_type_number_t inband_outputCnt
= 0;
5206 mach_vm_size_t ool_output_size
= 0;
5208 for (i
= 0; i
< inputCount
; i
++) {
5209 _input
[i
] = SCALAR64(input
[i
]);
5212 return is_io_connect_method(connect
, index
,
5214 inputStruct
, inputStructCount
,
5216 NULL
, &inband_outputCnt
,
5217 NULL
, &scalar_outputCnt
,
5218 0, &ool_output_size
);
5222 shim_io_connect_method_scalarI_structureI(
5223 IOExternalMethod
* method
,
5225 const io_user_scalar_t
* input
,
5226 mach_msg_type_number_t inputCount
,
5227 io_struct_inband_t inputStruct
,
5228 mach_msg_type_number_t inputStructCount
)
5231 IOReturn err
= kIOReturnBadArgument
;
5234 if (inputCount
!= method
->count0
) {
5235 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5236 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5239 if ((kIOUCVariableStructureSize
!= method
->count1
)
5240 && (inputStructCount
!= method
->count1
)) {
5241 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
);
5242 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
5246 func
= method
->func
;
5248 switch (inputCount
) {
5250 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5251 ARG32(input
[3]), ARG32(input
[4]),
5255 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
5257 inputStruct
, (void *)(uintptr_t)inputStructCount
);
5260 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5261 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5265 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
5266 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5270 err
= (object
->*func
)( ARG32(input
[0]),
5271 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5275 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
5276 NULL
, NULL
, NULL
, NULL
);
5280 IOLog("%s: Bad method table\n", object
->getName());
5288 shim_io_async_method_scalarI_structureI(
5289 IOExternalAsyncMethod
* method
,
5291 mach_port_t asyncWakePort
,
5292 io_user_reference_t
* asyncReference
,
5293 uint32_t asyncReferenceCount
,
5294 const io_user_scalar_t
* input
,
5295 mach_msg_type_number_t inputCount
,
5296 io_struct_inband_t inputStruct
,
5297 mach_msg_type_number_t inputStructCount
)
5301 IOReturn err
= kIOReturnBadArgument
;
5302 io_async_ref_t reference
;
5304 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5305 reference
[i
] = REF32(asyncReference
[i
]);
5309 if (inputCount
!= method
->count0
) {
5310 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5311 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5314 if ((kIOUCVariableStructureSize
!= method
->count1
)
5315 && (inputStructCount
!= method
->count1
)) {
5316 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
);
5317 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
5321 func
= method
->func
;
5323 switch (inputCount
) {
5325 err
= (object
->*func
)( reference
,
5326 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5327 ARG32(input
[3]), ARG32(input
[4]),
5331 err
= (object
->*func
)( reference
,
5332 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5334 inputStruct
, (void *)(uintptr_t)inputStructCount
);
5337 err
= (object
->*func
)( reference
,
5338 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5339 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5343 err
= (object
->*func
)( reference
,
5344 ARG32(input
[0]), ARG32(input
[1]),
5345 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5349 err
= (object
->*func
)( reference
,
5351 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5355 err
= (object
->*func
)( reference
,
5356 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5357 NULL
, NULL
, NULL
, NULL
);
5361 IOLog("%s: Bad method table\n", object
->getName());
5368 /* Routine io_connect_method_structureI_structureO */
5370 is_io_connect_method_structureI_structureO(
5371 io_object_t connect
,
5373 io_struct_inband_t input
,
5374 mach_msg_type_number_t inputCount
,
5375 io_struct_inband_t output
,
5376 mach_msg_type_number_t
* outputCount
)
5378 mach_msg_type_number_t scalar_outputCnt
= 0;
5379 mach_vm_size_t ool_output_size
= 0;
5381 return is_io_connect_method(connect
, index
,
5385 output
, outputCount
,
5386 NULL
, &scalar_outputCnt
,
5387 0, &ool_output_size
);
5391 shim_io_connect_method_structureI_structureO(
5392 IOExternalMethod
* method
,
5394 io_struct_inband_t input
,
5395 mach_msg_type_number_t inputCount
,
5396 io_struct_inband_t output
,
5397 IOByteCount
* outputCount
)
5400 IOReturn err
= kIOReturnBadArgument
;
5403 if ((kIOUCVariableStructureSize
!= method
->count0
)
5404 && (inputCount
!= method
->count0
)) {
5405 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
);
5406 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5409 if ((kIOUCVariableStructureSize
!= method
->count1
)
5410 && (*outputCount
!= method
->count1
)) {
5411 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
);
5412 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5416 func
= method
->func
;
5418 if (method
->count1
) {
5419 if (method
->count0
) {
5420 err
= (object
->*func
)( input
, output
,
5421 (void *)(uintptr_t)inputCount
, outputCount
, NULL
, NULL
);
5423 err
= (object
->*func
)( output
, outputCount
, NULL
, NULL
, NULL
, NULL
);
5426 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, NULL
, NULL
, NULL
, NULL
);
5435 shim_io_async_method_structureI_structureO(
5436 IOExternalAsyncMethod
* method
,
5438 mach_port_t asyncWakePort
,
5439 io_user_reference_t
* asyncReference
,
5440 uint32_t asyncReferenceCount
,
5441 io_struct_inband_t input
,
5442 mach_msg_type_number_t inputCount
,
5443 io_struct_inband_t output
,
5444 mach_msg_type_number_t
* outputCount
)
5449 io_async_ref_t reference
;
5451 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5452 reference
[i
] = REF32(asyncReference
[i
]);
5455 err
= kIOReturnBadArgument
;
5457 if ((kIOUCVariableStructureSize
!= method
->count0
)
5458 && (inputCount
!= method
->count0
)) {
5459 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
);
5460 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5463 if ((kIOUCVariableStructureSize
!= method
->count1
)
5464 && (*outputCount
!= method
->count1
)) {
5465 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
);
5466 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5470 func
= method
->func
;
5472 if (method
->count1
) {
5473 if (method
->count0
) {
5474 err
= (object
->*func
)( reference
,
5476 (void *)(uintptr_t)inputCount
, outputCount
, NULL
, NULL
);
5478 err
= (object
->*func
)( reference
,
5479 output
, outputCount
, NULL
, NULL
, NULL
, NULL
);
5482 err
= (object
->*func
)( reference
,
5483 input
, (void *)(uintptr_t)inputCount
, NULL
, NULL
, NULL
, NULL
);
5491 bool gIOKextdClearedBusy
= false;
5494 /* Routine io_catalog_send_data */
5496 is_io_catalog_send_data(
5497 mach_port_t master_port
,
5499 io_buf_ptr_t inData
,
5500 mach_msg_type_number_t inDataCount
,
5501 kern_return_t
* result
)
5504 return kIOReturnNotPrivileged
;
5505 #else /* NO_KEXTD */
5506 OSObject
* obj
= NULL
;
5508 kern_return_t kr
= kIOReturnError
;
5510 //printf("io_catalog_send_data called. flag: %d\n", flag);
5512 if (master_port
!= master_device_port
) {
5513 return kIOReturnNotPrivileged
;
5516 if ((flag
!= kIOCatalogRemoveKernelLinker__Removed
&&
5517 flag
!= kIOCatalogKextdActive
&&
5518 flag
!= kIOCatalogKextdFinishedLaunching
) &&
5519 (!inData
|| !inDataCount
)) {
5520 return kIOReturnBadArgument
;
5523 if (!IOTaskHasEntitlement(current_task(), kOSKextManagementEntitlement
)) {
5524 OSString
* taskName
= IOCopyLogNameForPID(proc_selfpid());
5525 IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName
? taskName
->getCStringNoCopy() : "");
5526 OSSafeReleaseNULL(taskName
);
5527 // For now, fake success to not break applications relying on this function succeeding.
5528 // See <rdar://problem/32554970> for more details.
5529 return kIOReturnSuccess
;
5533 vm_map_offset_t map_data
;
5535 if (inDataCount
> sizeof(io_struct_inband_t
) * 1024) {
5536 return kIOReturnMessageTooLarge
;
5539 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
5540 data
= CAST_DOWN(vm_offset_t
, map_data
);
5542 if (kr
!= KERN_SUCCESS
) {
5546 // must return success after vm_map_copyout() succeeds
5549 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
5550 vm_deallocate( kernel_map
, data
, inDataCount
);
5552 *result
= kIOReturnNoMemory
;
5553 return KERN_SUCCESS
;
5559 case kIOCatalogResetDrivers
:
5560 case kIOCatalogResetDriversNoMatch
: {
5563 array
= OSDynamicCast(OSArray
, obj
);
5565 if (!gIOCatalogue
->resetAndAddDrivers(array
,
5566 flag
== kIOCatalogResetDrivers
)) {
5567 kr
= kIOReturnError
;
5570 kr
= kIOReturnBadArgument
;
5575 case kIOCatalogAddDrivers
:
5576 case kIOCatalogAddDriversNoMatch
: {
5579 array
= OSDynamicCast(OSArray
, obj
);
5581 if (!gIOCatalogue
->addDrivers( array
,
5582 flag
== kIOCatalogAddDrivers
)) {
5583 kr
= kIOReturnError
;
5586 kr
= kIOReturnBadArgument
;
5591 case kIOCatalogRemoveDrivers
:
5592 case kIOCatalogRemoveDriversNoMatch
: {
5593 OSDictionary
* dict
;
5595 dict
= OSDynamicCast(OSDictionary
, obj
);
5597 if (!gIOCatalogue
->removeDrivers( dict
,
5598 flag
== kIOCatalogRemoveDrivers
)) {
5599 kr
= kIOReturnError
;
5602 kr
= kIOReturnBadArgument
;
5607 case kIOCatalogStartMatching__Removed
:
5608 case kIOCatalogRemoveKernelLinker__Removed
:
5609 kr
= KERN_NOT_SUPPORTED
;
5612 case kIOCatalogKextdActive
:
5614 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
5615 OSKext::setKextdActive();
5617 /* Dump all nonloaded startup extensions; kextd will now send them
5620 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
5622 kr
= kIOReturnSuccess
;
5625 case kIOCatalogKextdFinishedLaunching
: {
5627 if (!gIOKextdClearedBusy
) {
5628 IOService::kextdLaunched();
5629 gIOKextdClearedBusy
= true;
5632 kr
= kIOReturnSuccess
;
5637 kr
= kIOReturnBadArgument
;
5646 return KERN_SUCCESS
;
5647 #endif /* NO_KEXTD */
5650 /* Routine io_catalog_terminate */
5652 is_io_catalog_terminate(
5653 mach_port_t master_port
,
5659 if (master_port
!= master_device_port
) {
5660 return kIOReturnNotPrivileged
;
5663 kr
= IOUserClient::clientHasPrivilege((void *) current_task(),
5664 kIOClientPrivilegeAdministrator
);
5665 if (kIOReturnSuccess
!= kr
) {
5670 #if !defined(SECURE_KERNEL)
5671 case kIOCatalogServiceTerminate
:
5672 kr
= gIOCatalogue
->terminateDrivers(NULL
, name
);
5675 case kIOCatalogModuleUnload
:
5676 case kIOCatalogModuleTerminate
:
5677 kr
= gIOCatalogue
->terminateDriversForModule(name
,
5678 flag
== kIOCatalogModuleUnload
);
5683 kr
= kIOReturnBadArgument
;
5690 /* Routine io_catalog_get_data */
5692 is_io_catalog_get_data(
5693 mach_port_t master_port
,
5695 io_buf_ptr_t
*outData
,
5696 mach_msg_type_number_t
*outDataCount
)
5698 kern_return_t kr
= kIOReturnSuccess
;
5701 if (master_port
!= master_device_port
) {
5702 return kIOReturnNotPrivileged
;
5705 //printf("io_catalog_get_data called. flag: %d\n", flag);
5707 s
= OSSerialize::withCapacity(4096);
5709 return kIOReturnNoMemory
;
5712 kr
= gIOCatalogue
->serializeData(flag
, s
);
5714 if (kr
== kIOReturnSuccess
) {
5719 size
= s
->getLength();
5720 kr
= vm_allocate_kernel(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
);
5721 if (kr
== kIOReturnSuccess
) {
5722 bcopy(s
->text(), (void *)data
, size
);
5723 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
5724 (vm_map_size_t
)size
, true, ©
);
5725 *outData
= (char *)copy
;
5726 *outDataCount
= size
;
5735 /* Routine io_catalog_get_gen_count */
5737 is_io_catalog_get_gen_count(
5738 mach_port_t master_port
,
5741 if (master_port
!= master_device_port
) {
5742 return kIOReturnNotPrivileged
;
5745 //printf("io_catalog_get_gen_count called.\n");
5748 return kIOReturnBadArgument
;
5751 *genCount
= gIOCatalogue
->getGenerationCount();
5753 return kIOReturnSuccess
;
5756 /* Routine io_catalog_module_loaded.
5757 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
5760 is_io_catalog_module_loaded(
5761 mach_port_t master_port
,
5764 if (master_port
!= master_device_port
) {
5765 return kIOReturnNotPrivileged
;
5768 //printf("io_catalog_module_loaded called. name %s\n", name);
5771 return kIOReturnBadArgument
;
5774 gIOCatalogue
->moduleHasLoaded(name
);
5776 return kIOReturnSuccess
;
5780 is_io_catalog_reset(
5781 mach_port_t master_port
,
5784 if (master_port
!= master_device_port
) {
5785 return kIOReturnNotPrivileged
;
5789 case kIOCatalogResetDefault
:
5790 gIOCatalogue
->reset();
5794 return kIOReturnBadArgument
;
5797 return kIOReturnSuccess
;
5801 iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5803 kern_return_t result
= kIOReturnBadArgument
;
5804 IOUserClient
* userClient
;
5808 ref
= (uintptr_t) args
->userClientRef
;
5809 if ((1ULL << 32) & ref
) {
5810 object
= iokit_lookup_uext_ref_current_task((mach_port_name_t
) ref
);
5812 result
= IOUserServerUEXTTrap(object
, args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5814 OSSafeReleaseNULL(object
);
5815 } else if ((userClient
= OSDynamicCast(IOUserClient
, iokit_lookup_connect_ref_current_task((mach_port_name_t
) ref
)))) {
5816 IOExternalTrap
*trap
;
5817 IOService
*target
= NULL
;
5819 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5821 if (trap
&& target
) {
5827 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5831 iokit_remove_connect_reference(userClient
);
5837 /* Routine io_device_tree_entry_exists_with_name */
5839 is_io_device_tree_entry_exists_with_name(
5840 mach_port_t master_port
,
5844 OSCollectionIterator
*iter
;
5846 if (master_port
!= master_device_port
) {
5847 return kIOReturnNotPrivileged
;
5850 iter
= IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive
, name
);
5851 *exists
= iter
&& iter
->getNextObject();
5852 OSSafeReleaseNULL(iter
);
5854 return kIOReturnSuccess
;
5859 IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5860 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5864 IOByteCount structureOutputSize
;
5868 count
= dispatch
->checkScalarInputCount
;
5869 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
)) {
5870 return kIOReturnBadArgument
;
5873 count
= dispatch
->checkStructureInputSize
;
5874 if ((kIOUCVariableStructureSize
!= count
)
5875 && (count
!= ((args
->structureInputDescriptor
)
5876 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
))) {
5877 return kIOReturnBadArgument
;
5880 count
= dispatch
->checkScalarOutputCount
;
5881 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
)) {
5882 return kIOReturnBadArgument
;
5885 count
= dispatch
->checkStructureOutputSize
;
5886 if ((kIOUCVariableStructureSize
!= count
)
5887 && (count
!= ((args
->structureOutputDescriptor
)
5888 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
))) {
5889 return kIOReturnBadArgument
;
5892 if (dispatch
->function
) {
5893 err
= (*dispatch
->function
)(target
, reference
, args
);
5895 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5901 // pre-Leopard API's don't do ool structs
5902 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
) {
5903 err
= kIOReturnIPCError
;
5907 structureOutputSize
= args
->structureOutputSize
;
5909 if (args
->asyncWakePort
) {
5910 IOExternalAsyncMethod
* method
;
5912 if (!(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
) {
5913 return kIOReturnUnsupported
;
5916 if (kIOUCForegroundOnly
& method
->flags
) {
5917 if (task_is_gpu_denied(current_task())) {
5918 return kIOReturnNotPermitted
;
5922 switch (method
->flags
& kIOUCTypeMask
) {
5923 case kIOUCScalarIStructI
:
5924 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5925 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5926 args
->scalarInput
, args
->scalarInputCount
,
5927 (char *)args
->structureInput
, args
->structureInputSize
);
5930 case kIOUCScalarIScalarO
:
5931 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5932 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5933 args
->scalarInput
, args
->scalarInputCount
,
5934 args
->scalarOutput
, &args
->scalarOutputCount
);
5937 case kIOUCScalarIStructO
:
5938 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5939 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5940 args
->scalarInput
, args
->scalarInputCount
,
5941 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5945 case kIOUCStructIStructO
:
5946 err
= shim_io_async_method_structureI_structureO( method
, object
,
5947 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5948 (char *)args
->structureInput
, args
->structureInputSize
,
5949 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5953 err
= kIOReturnBadArgument
;
5957 IOExternalMethod
* method
;
5959 if (!(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
) {
5960 return kIOReturnUnsupported
;
5963 if (kIOUCForegroundOnly
& method
->flags
) {
5964 if (task_is_gpu_denied(current_task())) {
5965 return kIOReturnNotPermitted
;
5969 switch (method
->flags
& kIOUCTypeMask
) {
5970 case kIOUCScalarIStructI
:
5971 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5972 args
->scalarInput
, args
->scalarInputCount
,
5973 (char *) args
->structureInput
, args
->structureInputSize
);
5976 case kIOUCScalarIScalarO
:
5977 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5978 args
->scalarInput
, args
->scalarInputCount
,
5979 args
->scalarOutput
, &args
->scalarOutputCount
);
5982 case kIOUCScalarIStructO
:
5983 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5984 args
->scalarInput
, args
->scalarInputCount
,
5985 (char *) args
->structureOutput
, &structureOutputSize
);
5989 case kIOUCStructIStructO
:
5990 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5991 (char *) args
->structureInput
, args
->structureInputSize
,
5992 (char *) args
->structureOutput
, &structureOutputSize
);
5996 err
= kIOReturnBadArgument
;
6001 args
->structureOutputSize
= structureOutputSize
;
6007 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
6008 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
6010 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
6011 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
6013 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
6014 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
6015 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
6016 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
6017 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
6018 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
6019 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
6020 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
6021 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
6022 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
6023 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
6024 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
6025 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
6026 OSMetaClassDefineReservedUnused(IOUserClient
, 15);