2 * Copyright (c) 1998-2014 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/system.h>
45 #include <libkern/OSDebug.h>
47 #include <sys/kauth.h>
48 #include <sys/codesign.h>
55 #include <security/mac_framework.h>
57 #include <sys/kauth.h>
61 #endif /* CONFIG_MACF */
63 #include <IOKit/assert.h>
65 #include "IOServicePrivate.h"
66 #include "IOKitKernelInternal.h"
68 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
69 #define SCALAR32(x) ((uint32_t )x)
70 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
71 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
72 #define REF32(x) ((int)(x))
75 kIOUCAsync0Flags
= 3ULL,
76 kIOUCAsync64Flag
= 1ULL,
77 kIOUCAsyncErrorLoggedFlag
= 2ULL
82 #define IOStatisticsRegisterCounter() \
84 reserved->counter = IOStatistics::registerUserClient(this); \
87 #define IOStatisticsUnregisterCounter() \
90 IOStatistics::unregisterUserClient(reserved->counter); \
93 #define IOStatisticsClientCall() \
95 IOStatistics::countUserClientCall(client); \
100 #define IOStatisticsRegisterCounter()
101 #define IOStatisticsUnregisterCounter()
102 #define IOStatisticsClientCall()
104 #endif /* IOKITSTATS */
106 #if DEVELOPMENT || DEBUG
108 #define FAKE_STACK_FRAME(a) \
109 const void ** __frameptr; \
110 const void * __retaddr; \
111 __frameptr = (typeof(__frameptr)) __builtin_frame_address(0); \
112 __retaddr = __frameptr[1]; \
115 #define FAKE_STACK_FRAME_END() \
116 __frameptr[1] = __retaddr;
118 #else /* DEVELOPMENT || DEBUG */
120 #define FAKE_STACK_FRAME(a)
121 #define FAKE_STACK_FRAME_END()
123 #endif /* DEVELOPMENT || DEBUG */
125 #define ASYNC_REF_COUNT (sizeof(io_async_ref_t) / sizeof(natural_t))
126 #define ASYNC_REF64_COUNT (sizeof(io_async_ref64_t) / sizeof(io_user_reference_t))
128 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
131 #include <mach/mach_traps.h>
132 #include <vm/vm_map.h>
135 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
137 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
139 class IOMachPort
: public OSObject
141 OSDeclareDefaultStructors(IOMachPort
)
148 static IOMachPort
* portForObject( OSObject
* obj
,
149 ipc_kobject_type_t type
);
150 static bool noMoreSendersForObject( OSObject
* obj
,
151 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
152 static void releasePortForObject( OSObject
* obj
,
153 ipc_kobject_type_t type
);
154 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
156 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
158 static mach_port_name_t
makeSendRightForTask( task_t task
,
159 io_object_t obj
, ipc_kobject_type_t type
);
161 virtual void free() APPLE_KEXT_OVERRIDE
;
164 #define super OSObject
165 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
167 static IOLock
* gIOObjectPortLock
;
169 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
171 // not in dictForType() for debugging ease
172 static OSDictionary
* gIOObjectPorts
;
173 static OSDictionary
* gIOConnectPorts
;
174 static OSDictionary
* gIOIdentifierPorts
;
177 IOMachPort::dictForType( ipc_kobject_type_t type
)
179 OSDictionary
** dict
;
182 case IKOT_IOKIT_OBJECT
:
183 dict
= &gIOObjectPorts
;
185 case IKOT_IOKIT_CONNECT
:
186 dict
= &gIOConnectPorts
;
188 case IKOT_IOKIT_IDENT
:
189 dict
= &gIOIdentifierPorts
;
192 panic("dictForType %d", type
);
198 *dict
= OSDictionary::withCapacity( 1 );
205 IOMachPort::portForObject( OSObject
* obj
,
206 ipc_kobject_type_t type
)
208 IOMachPort
* inst
= 0;
211 IOTakeLock( gIOObjectPortLock
);
214 dict
= dictForType( type
);
219 if ((inst
= (IOMachPort
*)
220 dict
->getObject((const OSSymbol
*) obj
))) {
226 inst
= new IOMachPort
;
227 if (inst
&& !inst
->init()) {
232 inst
->port
= iokit_alloc_object_port( obj
, type
);
235 dict
->setObject((const OSSymbol
*) obj
, inst
);
243 IOUnlock( gIOObjectPortLock
);
249 IOMachPort::noMoreSendersForObject( OSObject
* obj
,
250 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
253 IOMachPort
* machPort
;
255 bool destroyed
= true;
257 IOTakeLock( gIOObjectPortLock
);
259 if ((dict
= dictForType( type
))) {
262 machPort
= (IOMachPort
*) dict
->getObject((const OSSymbol
*) obj
);
264 destroyed
= (machPort
->mscount
<= *mscount
);
266 *mscount
= machPort
->mscount
;
268 if ((IKOT_IOKIT_CONNECT
== type
) && (uc
= OSDynamicCast(IOUserClient
, obj
))) {
271 dict
->removeObject((const OSSymbol
*) obj
);
277 IOUnlock( gIOObjectPortLock
);
283 IOMachPort::releasePortForObject( OSObject
* obj
,
284 ipc_kobject_type_t type
)
287 IOMachPort
* machPort
;
289 assert(IKOT_IOKIT_CONNECT
!= type
);
291 IOTakeLock( gIOObjectPortLock
);
293 if ((dict
= dictForType( type
))) {
295 machPort
= (IOMachPort
*) dict
->getObject((const OSSymbol
*) obj
);
296 if (machPort
&& !machPort
->holdDestroy
) {
297 dict
->removeObject((const OSSymbol
*) obj
);
302 IOUnlock( gIOObjectPortLock
);
306 IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
309 IOMachPort
* machPort
;
311 IOLockLock( gIOObjectPortLock
);
313 if ((dict
= dictForType( type
))) {
314 machPort
= (IOMachPort
*) dict
->getObject((const OSSymbol
*) obj
);
316 machPort
->holdDestroy
= true;
320 IOLockUnlock( gIOObjectPortLock
);
324 IOUserClient::destroyUserReferences( OSObject
* obj
)
326 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
329 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
333 IOTakeLock( gIOObjectPortLock
);
336 if ((dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
))) {
338 port
= (IOMachPort
*) dict
->getObject((const OSSymbol
*) obj
);
341 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) {
344 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
345 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
347 uc
->mappings
->release();
351 dict
->removeObject((const OSSymbol
*) obj
);
355 IOUnlock( gIOObjectPortLock
);
359 IOMachPort::makeSendRightForTask( task_t task
,
360 io_object_t obj
, ipc_kobject_type_t type
)
362 return iokit_make_send_right( task
, obj
, type
);
366 IOMachPort::free( void )
369 iokit_destroy_object_port( port
);
374 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
376 class IOUserIterator
: public OSIterator
378 OSDeclareDefaultStructors(IOUserIterator
)
380 OSObject
* userIteratorObject
;
383 static IOUserIterator
* withIterator(LIBKERN_CONSUMED OSIterator
* iter
);
384 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
385 virtual void free() APPLE_KEXT_OVERRIDE
;
387 virtual void reset() APPLE_KEXT_OVERRIDE
;
388 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
389 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
390 virtual OSObject
* copyNextObject();
393 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
395 class IOUserNotification
: public IOUserIterator
397 OSDeclareDefaultStructors(IOUserNotification
)
399 #define holdNotify userIteratorObject
403 virtual void free() APPLE_KEXT_OVERRIDE
;
405 virtual void setNotification( IONotifier
* obj
);
407 virtual void reset() APPLE_KEXT_OVERRIDE
;
408 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
411 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
413 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
416 IOUserIterator::withIterator(OSIterator
* iter
)
424 me
= new IOUserIterator
;
425 if (me
&& !me
->init()) {
432 me
->userIteratorObject
= iter
;
438 IOUserIterator::init( void )
440 if (!OSObject::init()) {
444 lock
= IOLockAlloc();
453 IOUserIterator::free()
455 if (userIteratorObject
) {
456 userIteratorObject
->release();
465 IOUserIterator::reset()
468 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
469 ((OSIterator
*)userIteratorObject
)->reset();
474 IOUserIterator::isValid()
479 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
480 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
487 IOUserIterator::getNextObject()
494 IOUserIterator::copyNextObject()
496 OSObject
* ret
= NULL
;
499 if (userIteratorObject
) {
500 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
510 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
512 // functions called from osfmk/device/iokit_rpc.c
515 iokit_add_reference( io_object_t obj
, ipc_kobject_type_t type
)
523 if ((IKOT_IOKIT_CONNECT
== type
)
524 && (uc
= OSDynamicCast(IOUserClient
, obj
))) {
525 OSIncrementAtomic(&uc
->__ipc
);
532 iokit_remove_reference( io_object_t obj
)
540 iokit_remove_connect_reference( io_object_t obj
)
543 bool finalize
= false;
549 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) {
550 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive()) {
551 IOLockLock(gIOObjectPortLock
);
552 if ((finalize
= uc
->__ipcFinal
)) {
553 uc
->__ipcFinal
= false;
555 IOLockUnlock(gIOObjectPortLock
);
558 uc
->scheduleFinalize(true);
566 IOUserClient::finalizeUserReferences(OSObject
* obj
)
571 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) {
572 IOLockLock(gIOObjectPortLock
);
573 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) {
576 IOLockUnlock(gIOObjectPortLock
);
582 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
584 IOMachPort
* machPort
;
587 if ((machPort
= IOMachPort::portForObject( obj
, type
))) {
588 port
= machPort
->port
;
590 iokit_retain_port( port
);
602 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
603 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
605 IOUserClient
* client
;
607 IOUserNotification
* notify
;
609 if (!IOMachPort::noMoreSendersForObject( obj
, type
, mscount
)) {
610 return kIOReturnNotReady
;
613 if (IKOT_IOKIT_CONNECT
== type
) {
614 if ((client
= OSDynamicCast( IOUserClient
, obj
))) {
615 IOStatisticsClientCall();
616 IOLockLock(client
->lock
);
617 client
->clientDied();
618 IOLockUnlock(client
->lock
);
620 } else if (IKOT_IOKIT_OBJECT
== type
) {
621 if ((map
= OSDynamicCast( IOMemoryMap
, obj
))) {
623 } else if ((notify
= OSDynamicCast( IOUserNotification
, obj
))) {
624 notify
->setNotification( 0 );
628 return kIOReturnSuccess
;
632 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
634 class IOServiceUserNotification
: public IOUserNotification
636 OSDeclareDefaultStructors(IOServiceUserNotification
)
639 mach_msg_header_t msgHdr
;
640 OSNotificationHeader64 notifyHeader
;
643 enum { kMaxOutstanding
= 1024 };
653 virtual bool init( mach_port_t port
, natural_t type
,
654 void * reference
, vm_size_t referenceSize
,
656 virtual void free() APPLE_KEXT_OVERRIDE
;
657 void invalidatePort(void);
659 static bool _handler( void * target
,
660 void * ref
, IOService
* newService
, IONotifier
* notifier
);
661 virtual bool handler( void * ref
, IOService
* newService
);
663 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
664 virtual OSObject
* copyNextObject() APPLE_KEXT_OVERRIDE
;
667 class IOServiceMessageUserNotification
: public IOUserNotification
669 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
672 mach_msg_header_t msgHdr
;
673 mach_msg_body_t msgBody
;
674 mach_msg_port_descriptor_t ports
[1];
675 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
686 virtual bool init( mach_port_t port
, natural_t type
,
687 void * reference
, vm_size_t referenceSize
,
691 virtual void free() APPLE_KEXT_OVERRIDE
;
692 void invalidatePort(void);
694 static IOReturn
_handler( void * target
, void * ref
,
695 UInt32 messageType
, IOService
* provider
,
696 void * messageArgument
, vm_size_t argSize
);
697 virtual IOReturn
handler( void * ref
,
698 UInt32 messageType
, IOService
* provider
,
699 void * messageArgument
, vm_size_t argSize
);
701 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
702 virtual OSObject
* copyNextObject() APPLE_KEXT_OVERRIDE
;
705 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
708 #define super IOUserIterator
709 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
710 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
712 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
715 IOUserNotification::free( void )
718 assert(OSDynamicCast(IONotifier
, holdNotify
));
719 ((IONotifier
*)holdNotify
)->remove();
722 // can't be in handler now
729 IOUserNotification::setNotification( IONotifier
* notify
)
731 OSObject
* previousNotify
;
733 IOLockLock( gIOObjectPortLock
);
735 previousNotify
= holdNotify
;
738 IOLockUnlock( gIOObjectPortLock
);
740 if (previousNotify
) {
741 assert(OSDynamicCast(IONotifier
, previousNotify
));
742 ((IONotifier
*)previousNotify
)->remove();
747 IOUserNotification::reset()
753 IOUserNotification::isValid()
758 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
761 #define super IOUserNotification
762 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
764 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
767 IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
768 void * reference
, vm_size_t referenceSize
,
771 if (!super::init()) {
775 newSet
= OSArray::withCapacity( 1 );
780 if (referenceSize
> sizeof(OSAsyncReference64
)) {
784 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
785 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
790 bzero( pingMsg
, msgSize
);
792 pingMsg
->msgHdr
.msgh_remote_port
= port
;
793 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
794 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
795 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
796 pingMsg
->msgHdr
.msgh_size
= msgSize
;
797 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
799 pingMsg
->notifyHeader
.size
= 0;
800 pingMsg
->notifyHeader
.type
= type
;
801 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
807 IOServiceUserNotification::invalidatePort(void)
810 pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
815 IOServiceUserNotification::free( void )
827 if (_pingMsg
&& _msgSize
) {
828 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
829 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
831 IOFree(_pingMsg
, _msgSize
);
840 IOServiceUserNotification::_handler( void * target
,
841 void * ref
, IOService
* newService
, IONotifier
* notifier
)
843 return ((IOServiceUserNotification
*) target
)->handler( ref
, newService
);
847 IOServiceUserNotification::handler( void * ref
,
848 IOService
* newService
)
852 ipc_port_t port
= NULL
;
853 bool sendPing
= false;
857 count
= newSet
->getCount();
858 if (count
< kMaxOutstanding
) {
859 newSet
->setObject( newService
);
860 if ((sendPing
= (armed
&& (0 == count
)))) {
867 if (kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
) {
868 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
872 if ((port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
))) {
873 pingMsg
->msgHdr
.msgh_local_port
= port
;
875 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
878 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
879 pingMsg
->msgHdr
.msgh_size
,
880 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
883 iokit_release_port( port
);
886 if ((KERN_SUCCESS
!= kr
) && !ipcLogged
) {
888 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
895 IOServiceUserNotification::getNextObject()
902 IOServiceUserNotification::copyNextObject()
909 count
= newSet
->getCount();
911 result
= newSet
->getObject( count
- 1 );
913 newSet
->removeObject( count
- 1);
924 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
926 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
928 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
931 IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
932 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
935 if (!super::init()) {
939 if (referenceSize
> sizeof(OSAsyncReference64
)) {
943 clientIs64
= client64
;
945 owningPID
= proc_selfpid();
947 extraSize
+= sizeof(IOServiceInterestContent64
);
948 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
949 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
954 bzero( pingMsg
, msgSize
);
956 pingMsg
->msgHdr
.msgh_remote_port
= port
;
957 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
959 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
960 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
961 pingMsg
->msgHdr
.msgh_size
= msgSize
;
962 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
964 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
966 pingMsg
->ports
[0].name
= 0;
967 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
968 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
970 pingMsg
->notifyHeader
.size
= extraSize
;
971 pingMsg
->notifyHeader
.type
= type
;
972 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
978 IOServiceMessageUserNotification::invalidatePort(void)
981 pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
986 IOServiceMessageUserNotification::free( void )
996 if (_pingMsg
&& _msgSize
) {
997 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
998 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
1000 IOFree( _pingMsg
, _msgSize
);
1005 IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
1006 UInt32 messageType
, IOService
* provider
,
1007 void * argument
, vm_size_t argSize
)
1009 return ((IOServiceMessageUserNotification
*) target
)->handler(
1010 ref
, messageType
, provider
, argument
, argSize
);
1014 IOServiceMessageUserNotification::handler( void * ref
,
1015 UInt32 messageType
, IOService
* provider
,
1016 void * messageArgument
, vm_size_t callerArgSize
)
1018 enum { kLocalMsgSize
= 0x100 };
1019 uint64_t stackMsg
[kLocalMsgSize
/ sizeof(uint64_t)];
1023 vm_size_t thisMsgSize
;
1024 ipc_port_t thisPort
, providerPort
;
1025 struct PingMsg
* thisMsg
;
1026 IOServiceInterestContent64
* data
;
1028 if (kIOMessageCopyClientID
== messageType
) {
1029 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
1030 return kIOReturnSuccess
;
1033 if (callerArgSize
== 0) {
1035 argSize
= sizeof(data
->messageArgument
[0]);
1037 argSize
= sizeof(uint32_t);
1040 if (callerArgSize
> kIOUserNotifyMaxMessageSize
) {
1041 callerArgSize
= kIOUserNotifyMaxMessageSize
;
1043 argSize
= callerArgSize
;
1046 // adjust message size for ipc restrictions
1048 type
= pingMsg
->notifyHeader
.type
;
1049 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
1050 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
1051 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
1053 thisMsgSize
= msgSize
1054 + sizeof(IOServiceInterestContent64
)
1055 - sizeof(data
->messageArgument
)
1058 if (thisMsgSize
> sizeof(stackMsg
)) {
1059 allocMsg
= IOMalloc(thisMsgSize
);
1061 return kIOReturnNoMemory
;
1063 thisMsg
= (typeof(thisMsg
))allocMsg
;
1066 thisMsg
= (typeof(thisMsg
))stackMsg
;
1069 bcopy(pingMsg
, thisMsg
, msgSize
);
1070 thisMsg
->notifyHeader
.type
= type
;
1071 data
= (IOServiceInterestContent64
*) (((uint8_t *) thisMsg
) + msgSize
);
1072 // == pingMsg->notifyHeader.content;
1073 data
->messageType
= messageType
;
1075 if (callerArgSize
== 0) {
1076 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
1078 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
1081 bcopy( messageArgument
, data
->messageArgument
, callerArgSize
);
1082 bzero((void *)(((uintptr_t) &data
->messageArgument
[0]) + callerArgSize
), argSize
- callerArgSize
);
1085 thisMsg
->notifyHeader
.type
= type
;
1086 thisMsg
->msgHdr
.msgh_size
= thisMsgSize
;
1088 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
1089 thisMsg
->ports
[0].name
= providerPort
;
1090 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
1091 thisMsg
->msgHdr
.msgh_local_port
= thisPort
;
1093 kr
= mach_msg_send_from_kernel_with_options( &thisMsg
->msgHdr
,
1094 thisMsg
->msgHdr
.msgh_size
,
1095 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
1098 iokit_release_port( thisPort
);
1101 iokit_release_port( providerPort
);
1105 IOFree(allocMsg
, thisMsgSize
);
1108 if ((KERN_SUCCESS
!= kr
) && !ipcLogged
) {
1110 IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1113 return kIOReturnSuccess
;
1117 IOServiceMessageUserNotification::getNextObject()
1123 IOServiceMessageUserNotification::copyNextObject()
1128 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1131 #define super IOService
1132 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1134 IOLock
* gIOUserClientOwnersLock
;
1137 IOUserClient::initialize( void )
1139 gIOObjectPortLock
= IOLockAlloc();
1140 gIOUserClientOwnersLock
= IOLockAlloc();
1141 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1145 IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1146 mach_port_t wakePort
,
1147 void *callback
, void *refcon
)
1149 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1150 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1151 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1152 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1156 IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1157 mach_port_t wakePort
,
1158 mach_vm_address_t callback
, io_user_reference_t refcon
)
1160 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1161 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1162 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1163 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1167 IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1168 mach_port_t wakePort
,
1169 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1171 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1172 if (vm_map_is_64bit(get_task_map(task
))) {
1173 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1177 static OSDictionary
*
1178 CopyConsoleUser(UInt32 uid
)
1181 OSDictionary
* user
= 0;
1183 if ((array
= OSDynamicCast(OSArray
,
1184 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
)))) {
1185 for (unsigned int idx
= 0;
1186 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1190 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1191 && (uid
== num
->unsigned32BitValue())) {
1201 static OSDictionary
*
1202 CopyUserOnConsole(void)
1205 OSDictionary
* user
= 0;
1207 if ((array
= OSDynamicCast(OSArray
,
1208 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
)))) {
1209 for (unsigned int idx
= 0;
1210 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1212 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
)) {
1223 IOUserClient::clientHasAuthorization( task_t task
,
1224 IOService
* service
)
1228 p
= (proc_t
) get_bsdtask_info(task
);
1230 uint64_t authorizationID
;
1232 authorizationID
= proc_uniqueid(p
);
1233 if (authorizationID
) {
1234 if (service
->getAuthorizationID() == authorizationID
) {
1235 return kIOReturnSuccess
;
1240 return kIOReturnNotPermitted
;
1244 IOUserClient::clientHasPrivilege( void * securityToken
,
1245 const char * privilegeName
)
1248 security_token_t token
;
1249 mach_msg_type_number_t count
;
1251 OSDictionary
* user
;
1255 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1256 sizeof(kIOClientPrivilegeForeground
))) {
1257 if (task_is_gpu_denied(current_task())) {
1258 return kIOReturnNotPrivileged
;
1260 return kIOReturnSuccess
;
1264 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1265 sizeof(kIOClientPrivilegeConsoleSession
))) {
1269 task
= (task_t
) securityToken
;
1271 task
= current_task();
1273 p
= (proc_t
) get_bsdtask_info(task
);
1274 kr
= kIOReturnNotPrivileged
;
1276 if (p
&& (cred
= kauth_cred_proc_ref(p
))) {
1277 user
= CopyUserOnConsole();
1280 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1281 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue())) {
1282 kr
= kIOReturnSuccess
;
1286 kauth_cred_unref(&cred
);
1291 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1292 sizeof(kIOClientPrivilegeSecureConsoleProcess
)))) {
1293 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1295 task
= (task_t
)securityToken
;
1298 count
= TASK_SECURITY_TOKEN_COUNT
;
1299 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1301 if (KERN_SUCCESS
!= kr
) {
1302 } else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1303 sizeof(kIOClientPrivilegeAdministrator
))) {
1304 if (0 != token
.val
[0]) {
1305 kr
= kIOReturnNotPrivileged
;
1307 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1308 sizeof(kIOClientPrivilegeLocalUser
))) {
1309 user
= CopyConsoleUser(token
.val
[0]);
1313 kr
= kIOReturnNotPrivileged
;
1315 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1316 sizeof(kIOClientPrivilegeConsoleUser
))) {
1317 user
= CopyConsoleUser(token
.val
[0]);
1319 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
) {
1320 kr
= kIOReturnNotPrivileged
;
1321 } else if (secureConsole
) {
1322 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1323 if (pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
) {
1324 kr
= kIOReturnNotPrivileged
;
1329 kr
= kIOReturnNotPrivileged
;
1332 kr
= kIOReturnUnsupported
;
1339 IOUserClient::copyClientEntitlement( task_t task
,
1340 const char * entitlement
)
1342 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1346 char procname
[MAXCOMLEN
+ 1] = "";
1348 void *entitlements_blob
= NULL
;
1349 char *entitlements_data
= NULL
;
1350 OSObject
*entitlements_obj
= NULL
;
1351 OSDictionary
*entitlements
= NULL
;
1352 OSString
*errorString
= NULL
;
1353 OSObject
*value
= NULL
;
1355 p
= (proc_t
)get_bsdtask_info(task
);
1360 proc_name(pid
, procname
, (int)sizeof(procname
));
1362 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0) {
1366 if (len
<= offsetof(CS_GenericBlob
, data
)) {
1371 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1372 * we'll try to parse in the kernel.
1374 len
-= offsetof(CS_GenericBlob
, data
);
1375 if (len
> MAX_ENTITLEMENTS_LEN
) {
1376 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1381 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1382 * what is stored in the entitlements blob. Copy the string and
1385 entitlements_data
= (char *)IOMalloc(len
+ 1);
1386 if (entitlements_data
== NULL
) {
1389 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1390 entitlements_data
[len
] = '\0';
1392 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1393 if (errorString
!= NULL
) {
1394 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1397 if (entitlements_obj
== NULL
) {
1401 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1402 if (entitlements
== NULL
) {
1406 /* Fetch the entitlement value from the dictionary. */
1407 value
= entitlements
->getObject(entitlement
);
1408 if (value
!= NULL
) {
1413 if (entitlements_data
!= NULL
) {
1414 IOFree(entitlements_data
, len
+ 1);
1416 if (entitlements_obj
!= NULL
) {
1417 entitlements_obj
->release();
1419 if (errorString
!= NULL
) {
1420 errorString
->release();
1426 IOUserClient::init()
1428 if (getPropertyTable() || super::init()) {
1436 IOUserClient::init(OSDictionary
* dictionary
)
1438 if (getPropertyTable() || super::init(dictionary
)) {
1446 IOUserClient::initWithTask(task_t owningTask
,
1450 if (getPropertyTable() || super::init()) {
1458 IOUserClient::initWithTask(task_t owningTask
,
1461 OSDictionary
* properties
)
1465 ok
= super::init( properties
);
1466 ok
&= initWithTask( owningTask
, securityID
, type
);
1472 IOUserClient::reserve()
1475 reserved
= IONew(ExpansionData
, 1);
1480 setTerminateDefer(NULL
, true);
1481 IOStatisticsRegisterCounter();
1486 struct IOUserClientOwner
{
1488 queue_chain_t taskLink
;
1490 queue_chain_t ucLink
;
1494 IOUserClient::registerOwner(task_t task
)
1496 IOUserClientOwner
* owner
;
1500 IOLockLock(gIOUserClientOwnersLock
);
1503 ret
= kIOReturnSuccess
;
1506 queue_init(&owners
);
1508 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1510 if (task
!= owner
->task
) {
1518 owner
= IONew(IOUserClientOwner
, 1);
1520 ret
= kIOReturnNoMemory
;
1524 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1525 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1529 IOLockUnlock(gIOUserClientOwnersLock
);
1535 IOUserClient::noMoreSenders(void)
1537 IOUserClientOwner
* owner
;
1539 IOLockLock(gIOUserClientOwnersLock
);
1542 while (!queue_empty(&owners
)) {
1543 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1544 queue_remove(task_io_user_clients(owner
->task
), owner
, IOUserClientOwner
*, taskLink
);
1545 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1546 IODelete(owner
, IOUserClientOwner
, 1);
1548 owners
.next
= owners
.prev
= NULL
;
1551 IOLockUnlock(gIOUserClientOwnersLock
);
1554 extern "C" kern_return_t
1555 iokit_task_terminate(task_t task
)
1557 IOUserClientOwner
* owner
;
1558 IOUserClient
* dead
;
1560 queue_head_t
* taskque
;
1562 IOLockLock(gIOUserClientOwnersLock
);
1564 taskque
= task_io_user_clients(task
);
1566 while (!queue_empty(taskque
)) {
1567 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1569 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1570 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1571 if (queue_empty(&uc
->owners
)) {
1573 IOLog("destroying out of band connect for %s\n", uc
->getName());
1574 // now using the uc queue head as a singly linked queue,
1575 // leaving .next as NULL to mark it empty
1576 uc
->owners
.next
= NULL
;
1577 uc
->owners
.prev
= (queue_entry_t
) dead
;
1580 IODelete(owner
, IOUserClientOwner
, 1);
1583 IOLockUnlock(gIOUserClientOwnersLock
);
1587 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1588 uc
->owners
.prev
= NULL
;
1589 if (uc
->sharedInstance
|| !uc
->closed
) {
1595 return KERN_SUCCESS
;
1599 IOUserClient::free()
1602 mappings
->release();
1608 IOStatisticsUnregisterCounter();
1610 assert(!owners
.next
);
1611 assert(!owners
.prev
);
1614 IODelete(reserved
, ExpansionData
, 1);
1621 IOUserClient::clientDied( void )
1623 IOReturn ret
= kIOReturnNotReady
;
1625 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
)) {
1626 ret
= clientClose();
1633 IOUserClient::clientClose( void )
1635 return kIOReturnUnsupported
;
1639 IOUserClient::getService( void )
1645 IOUserClient::registerNotificationPort(
1646 mach_port_t
/* port */,
1648 UInt32
/* refCon */)
1650 return kIOReturnUnsupported
;
1654 IOUserClient::registerNotificationPort(
1657 io_user_reference_t refCon
)
1659 return registerNotificationPort(port
, type
, (UInt32
) refCon
);
1663 IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1664 semaphore_t
* semaphore
)
1666 return kIOReturnUnsupported
;
1670 IOUserClient::connectClient( IOUserClient
* /* client */ )
1672 return kIOReturnUnsupported
;
1676 IOUserClient::clientMemoryForType( UInt32 type
,
1677 IOOptionBits
* options
,
1678 IOMemoryDescriptor
** memory
)
1680 return kIOReturnUnsupported
;
1685 IOUserClient::mapClientMemory(
1688 IOOptionBits mapFlags
,
1689 IOVirtualAddress atAddress
)
1696 IOUserClient::mapClientMemory64(
1699 IOOptionBits mapFlags
,
1700 mach_vm_address_t atAddress
)
1703 IOOptionBits options
= 0;
1704 IOMemoryDescriptor
* memory
= 0;
1705 IOMemoryMap
* map
= 0;
1707 err
= clientMemoryForType((UInt32
) type
, &options
, &memory
);
1709 if (memory
&& (kIOReturnSuccess
== err
)) {
1710 FAKE_STACK_FRAME(getMetaClass());
1712 options
= (options
& ~kIOMapUserOptionsMask
)
1713 | (mapFlags
& kIOMapUserOptionsMask
);
1714 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1717 FAKE_STACK_FRAME_END();
1724 IOUserClient::exportObjectToClient(task_t task
,
1725 OSObject
*obj
, io_object_t
*clientObj
)
1727 mach_port_name_t name
;
1729 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1731 *clientObj
= (io_object_t
)(uintptr_t) name
;
1737 return kIOReturnSuccess
;
1741 IOUserClient::copyPortNameForObjectInTask(task_t task
,
1742 OSObject
*obj
, mach_port_name_t
* port_name
)
1744 mach_port_name_t name
;
1746 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_IDENT
);
1748 *(mach_port_name_t
*) port_name
= name
;
1750 return kIOReturnSuccess
;
1754 IOUserClient::copyObjectForPortNameInTask(task_t task
, mach_port_name_t port_name
,
1759 object
= iokit_lookup_object_with_port_name(port_name
, IKOT_IOKIT_IDENT
, task
);
1763 return object
? kIOReturnSuccess
: kIOReturnIPCError
;
1767 IOUserClient::adjustPortNameReferencesInTask(task_t task
, mach_port_name_t port_name
, mach_port_delta_t delta
)
1769 return iokit_mod_send_right(task
, port_name
, delta
);
1773 IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1778 IOExternalAsyncMethod
*
1779 IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1786 getExternalTrapForIndex(UInt32 index
)
1791 #pragma clang diagnostic push
1792 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1794 // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
1795 // functions can break clients of kexts implementing getExternalMethodForIndex()
1798 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1800 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1803 *targetP
= (IOService
*) method
->object
;
1809 IOExternalAsyncMethod
*
1811 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1813 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1816 *targetP
= (IOService
*) method
->object
;
1824 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1826 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1829 *targetP
= trap
->object
;
1834 #pragma clang diagnostic pop
1837 IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1840 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1842 if (MACH_PORT_NULL
!= port
) {
1843 iokit_release_port_send(port
);
1846 return kIOReturnSuccess
;
1850 IOUserClient::releaseNotificationPort(mach_port_t port
)
1852 if (MACH_PORT_NULL
!= port
) {
1853 iokit_release_port_send(port
);
1856 return kIOReturnSuccess
;
1860 IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1861 IOReturn result
, void *args
[], UInt32 numArgs
)
1863 OSAsyncReference64 reference64
;
1864 io_user_reference_t args64
[kMaxAsyncArgs
];
1867 if (numArgs
> kMaxAsyncArgs
) {
1868 return kIOReturnMessageTooLarge
;
1871 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++) {
1872 reference64
[idx
] = REF64(reference
[idx
]);
1875 for (idx
= 0; idx
< numArgs
; idx
++) {
1876 args64
[idx
] = REF64(args
[idx
]);
1879 return sendAsyncResult64(reference64
, result
, args64
, numArgs
);
1883 IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1884 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1886 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1890 IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1891 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1893 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1897 IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1898 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1901 mach_msg_header_t msgHdr
;
1904 OSNotificationHeader notifyHdr
;
1905 IOAsyncCompletionContent asyncContent
;
1906 uint32_t args
[kMaxAsyncArgs
];
1909 OSNotificationHeader64 notifyHdr
;
1910 IOAsyncCompletionContent asyncContent
;
1911 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1916 mach_port_t replyPort
;
1919 // If no reply port, do nothing.
1920 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1921 if (replyPort
== MACH_PORT_NULL
) {
1922 return kIOReturnSuccess
;
1925 if (numArgs
> kMaxAsyncArgs
) {
1926 return kIOReturnMessageTooLarge
;
1929 bzero(&replyMsg
, sizeof(replyMsg
));
1930 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1932 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1933 replyMsg
.msgHdr
.msgh_local_port
= 0;
1934 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1935 if (kIOUCAsync64Flag
& reference
[0]) {
1936 replyMsg
.msgHdr
.msgh_size
=
1937 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1938 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1939 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1940 + numArgs
* sizeof(io_user_reference_t
);
1941 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1942 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1944 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1946 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1951 replyMsg
.msgHdr
.msgh_size
=
1952 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1953 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1955 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1956 + numArgs
* sizeof(uint32_t);
1957 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1959 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++) {
1960 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1963 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1965 for (idx
= 0; idx
< numArgs
; idx
++) {
1966 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1970 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1971 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1972 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1974 /* Fail on full queue. */
1975 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1976 replyMsg
.msgHdr
.msgh_size
);
1978 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
) && !(kIOUCAsyncErrorLoggedFlag
& reference
[0])) {
1979 reference
[0] |= kIOUCAsyncErrorLoggedFlag
;
1980 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1986 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1989 #define CHECK(cls, obj, out) \
1991 if( !(out = OSDynamicCast( cls, obj))) \
1992 return( kIOReturnBadArgument )
1994 #define CHECKLOCKED(cls, obj, out) \
1995 IOUserIterator * oIter; \
1997 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1998 return (kIOReturnBadArgument); \
1999 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
2000 return (kIOReturnBadArgument)
2002 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004 // Create a vm_map_copy_t or kalloc'ed data for memory
2005 // to be copied out. ipc will free after the copyout.
2007 static kern_return_t
2008 copyoutkdata( const void * data
, vm_size_t len
,
2009 io_buf_ptr_t
* buf
)
2014 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
2015 false /* src_destroy */, ©
);
2017 assert( err
== KERN_SUCCESS
);
2018 if (err
== KERN_SUCCESS
) {
2019 *buf
= (char *) copy
;
2025 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2027 /* Routine io_server_version */
2029 is_io_server_version(
2030 mach_port_t master_port
,
2033 *version
= IOKIT_SERVER_VERSION
;
2034 return kIOReturnSuccess
;
2037 /* Routine io_object_get_class */
2039 is_io_object_get_class(
2041 io_name_t className
)
2043 const OSMetaClass
* my_obj
= NULL
;
2046 return kIOReturnBadArgument
;
2049 my_obj
= object
->getMetaClass();
2051 return kIOReturnNotFound
;
2054 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
2056 return kIOReturnSuccess
;
2059 /* Routine io_object_get_superclass */
2061 is_io_object_get_superclass(
2062 mach_port_t master_port
,
2064 io_name_t class_name
)
2067 const OSMetaClass
* meta
;
2068 const OSMetaClass
* super
;
2069 const OSSymbol
* name
;
2072 if (!obj_name
|| !class_name
) {
2073 return kIOReturnBadArgument
;
2075 if (master_port
!= master_device_port
) {
2076 return kIOReturnNotPrivileged
;
2079 ret
= kIOReturnNotFound
;
2082 name
= OSSymbol::withCString(obj_name
);
2086 meta
= OSMetaClass::copyMetaClassWithName(name
);
2090 super
= meta
->getSuperClass();
2094 cstr
= super
->getClassName();
2098 strlcpy(class_name
, cstr
, sizeof(io_name_t
));
2099 ret
= kIOReturnSuccess
;
2102 OSSafeReleaseNULL(name
);
2104 meta
->releaseMetaClass();
2110 /* Routine io_object_get_bundle_identifier */
2112 is_io_object_get_bundle_identifier(
2113 mach_port_t master_port
,
2115 io_name_t bundle_name
)
2118 const OSMetaClass
* meta
;
2119 const OSSymbol
* name
;
2120 const OSSymbol
* identifier
;
2123 if (!obj_name
|| !bundle_name
) {
2124 return kIOReturnBadArgument
;
2126 if (master_port
!= master_device_port
) {
2127 return kIOReturnNotPrivileged
;
2130 ret
= kIOReturnNotFound
;
2133 name
= OSSymbol::withCString(obj_name
);
2137 meta
= OSMetaClass::copyMetaClassWithName(name
);
2141 identifier
= meta
->getKmodName();
2145 cstr
= identifier
->getCStringNoCopy();
2149 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
2150 ret
= kIOReturnSuccess
;
2153 OSSafeReleaseNULL(name
);
2155 meta
->releaseMetaClass();
2161 /* Routine io_object_conforms_to */
2163 is_io_object_conforms_to(
2165 io_name_t className
,
2166 boolean_t
*conforms
)
2169 return kIOReturnBadArgument
;
2172 *conforms
= (0 != object
->metaCast( className
));
2174 return kIOReturnSuccess
;
2177 /* Routine io_object_get_retain_count */
2179 is_io_object_get_retain_count(
2181 uint32_t *retainCount
)
2184 return kIOReturnBadArgument
;
2187 *retainCount
= object
->getRetainCount();
2188 return kIOReturnSuccess
;
2191 /* Routine io_iterator_next */
2193 is_io_iterator_next(
2194 io_object_t iterator
,
2195 io_object_t
*object
)
2200 IOUserIterator
* uiter
;
2202 if ((uiter
= OSDynamicCast(IOUserIterator
, iterator
))) {
2203 obj
= uiter
->copyNextObject();
2204 } else if ((iter
= OSDynamicCast(OSIterator
, iterator
))) {
2205 obj
= iter
->getNextObject();
2210 return kIOReturnBadArgument
;
2215 ret
= kIOReturnSuccess
;
2217 ret
= kIOReturnNoDevice
;
2223 /* Routine io_iterator_reset */
2225 is_io_iterator_reset(
2226 io_object_t iterator
)
2228 CHECK( OSIterator
, iterator
, iter
);
2232 return kIOReturnSuccess
;
2235 /* Routine io_iterator_is_valid */
2237 is_io_iterator_is_valid(
2238 io_object_t iterator
,
2239 boolean_t
*is_valid
)
2241 CHECK( OSIterator
, iterator
, iter
);
2243 *is_valid
= iter
->isValid();
2245 return kIOReturnSuccess
;
2249 static kern_return_t
2250 internal_io_service_match_property_table(
2251 io_service_t _service
,
2252 const char * matching
,
2253 mach_msg_type_number_t matching_size
,
2256 CHECK( IOService
, _service
, service
);
2260 OSDictionary
* dict
;
2262 assert(matching_size
);
2263 obj
= OSUnserializeXML(matching
, matching_size
);
2265 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2266 *matches
= service
->passiveMatch( dict
);
2267 kr
= kIOReturnSuccess
;
2269 kr
= kIOReturnBadArgument
;
2279 /* Routine io_service_match_property_table */
2281 is_io_service_match_property_table(
2282 io_service_t service
,
2283 io_string_t matching
,
2284 boolean_t
*matches
)
2286 return kIOReturnUnsupported
;
2290 /* Routine io_service_match_property_table_ool */
2292 is_io_service_match_property_table_ool(
2293 io_object_t service
,
2294 io_buf_ptr_t matching
,
2295 mach_msg_type_number_t matchingCnt
,
2296 kern_return_t
*result
,
2297 boolean_t
*matches
)
2301 vm_map_offset_t map_data
;
2303 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2304 data
= CAST_DOWN(vm_offset_t
, map_data
);
2306 if (KERN_SUCCESS
== kr
) {
2307 // must return success after vm_map_copyout() succeeds
2308 *result
= internal_io_service_match_property_table(service
,
2309 (const char *)data
, matchingCnt
, matches
);
2310 vm_deallocate( kernel_map
, data
, matchingCnt
);
2316 /* Routine io_service_match_property_table_bin */
2318 is_io_service_match_property_table_bin(
2319 io_object_t service
,
2320 io_struct_inband_t matching
,
2321 mach_msg_type_number_t matchingCnt
,
2324 return internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
);
2327 static kern_return_t
2328 internal_io_service_get_matching_services(
2329 mach_port_t master_port
,
2330 const char * matching
,
2331 mach_msg_type_number_t matching_size
,
2332 io_iterator_t
*existing
)
2336 OSDictionary
* dict
;
2338 if (master_port
!= master_device_port
) {
2339 return kIOReturnNotPrivileged
;
2342 assert(matching_size
);
2343 obj
= OSUnserializeXML(matching
, matching_size
);
2345 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2346 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2347 kr
= kIOReturnSuccess
;
2349 kr
= kIOReturnBadArgument
;
2359 /* Routine io_service_get_matching_services */
2361 is_io_service_get_matching_services(
2362 mach_port_t master_port
,
2363 io_string_t matching
,
2364 io_iterator_t
*existing
)
2366 return kIOReturnUnsupported
;
2369 /* Routine io_service_get_matching_services_ool */
2371 is_io_service_get_matching_services_ool(
2372 mach_port_t master_port
,
2373 io_buf_ptr_t matching
,
2374 mach_msg_type_number_t matchingCnt
,
2375 kern_return_t
*result
,
2376 io_object_t
*existing
)
2380 vm_map_offset_t map_data
;
2382 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2383 data
= CAST_DOWN(vm_offset_t
, map_data
);
2385 if (KERN_SUCCESS
== kr
) {
2386 // must return success after vm_map_copyout() succeeds
2387 // and mig will copy out objects on success
2389 *result
= internal_io_service_get_matching_services(master_port
,
2390 (const char *) data
, matchingCnt
, existing
);
2391 vm_deallocate( kernel_map
, data
, matchingCnt
);
2397 /* Routine io_service_get_matching_services_bin */
2399 is_io_service_get_matching_services_bin(
2400 mach_port_t master_port
,
2401 io_struct_inband_t matching
,
2402 mach_msg_type_number_t matchingCnt
,
2403 io_object_t
*existing
)
2405 return internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
);
2409 static kern_return_t
2410 internal_io_service_get_matching_service(
2411 mach_port_t master_port
,
2412 const char * matching
,
2413 mach_msg_type_number_t matching_size
,
2414 io_service_t
*service
)
2418 OSDictionary
* dict
;
2420 if (master_port
!= master_device_port
) {
2421 return kIOReturnNotPrivileged
;
2424 assert(matching_size
);
2425 obj
= OSUnserializeXML(matching
, matching_size
);
2427 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2428 *service
= IOService::copyMatchingService( dict
);
2429 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2431 kr
= kIOReturnBadArgument
;
2441 /* Routine io_service_get_matching_service */
2443 is_io_service_get_matching_service(
2444 mach_port_t master_port
,
2445 io_string_t matching
,
2446 io_service_t
*service
)
2448 return kIOReturnUnsupported
;
2451 /* Routine io_service_get_matching_services_ool */
2453 is_io_service_get_matching_service_ool(
2454 mach_port_t master_port
,
2455 io_buf_ptr_t matching
,
2456 mach_msg_type_number_t matchingCnt
,
2457 kern_return_t
*result
,
2458 io_object_t
*service
)
2462 vm_map_offset_t map_data
;
2464 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2465 data
= CAST_DOWN(vm_offset_t
, map_data
);
2467 if (KERN_SUCCESS
== kr
) {
2468 // must return success after vm_map_copyout() succeeds
2469 // and mig will copy out objects on success
2471 *result
= internal_io_service_get_matching_service(master_port
,
2472 (const char *) data
, matchingCnt
, service
);
2473 vm_deallocate( kernel_map
, data
, matchingCnt
);
2479 /* Routine io_service_get_matching_service_bin */
2481 is_io_service_get_matching_service_bin(
2482 mach_port_t master_port
,
2483 io_struct_inband_t matching
,
2484 mach_msg_type_number_t matchingCnt
,
2485 io_object_t
*service
)
2487 return internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
);
2490 static kern_return_t
2491 internal_io_service_add_notification(
2492 mach_port_t master_port
,
2493 io_name_t notification_type
,
2494 const char * matching
,
2495 size_t matching_size
,
2498 vm_size_t referenceSize
,
2500 io_object_t
* notification
)
2502 IOServiceUserNotification
* userNotify
= 0;
2503 IONotifier
* notify
= 0;
2504 const OSSymbol
* sym
;
2505 OSDictionary
* dict
;
2507 unsigned long int userMsgType
;
2509 if (master_port
!= master_device_port
) {
2510 return kIOReturnNotPrivileged
;
2514 err
= kIOReturnNoResources
;
2516 if (matching_size
> (sizeof(io_struct_inband_t
) * 1024)) {
2517 return kIOReturnMessageTooLarge
;
2520 if (!(sym
= OSSymbol::withCString( notification_type
))) {
2521 err
= kIOReturnNoResources
;
2524 assert(matching_size
);
2525 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2527 err
= kIOReturnBadArgument
;
2531 if ((sym
== gIOPublishNotification
)
2532 || (sym
== gIOFirstPublishNotification
)) {
2533 userMsgType
= kIOServicePublishNotificationType
;
2534 } else if ((sym
== gIOMatchedNotification
)
2535 || (sym
== gIOFirstMatchNotification
)) {
2536 userMsgType
= kIOServiceMatchedNotificationType
;
2537 } else if ((sym
== gIOTerminatedNotification
)
2538 || (sym
== gIOWillTerminateNotification
)) {
2539 userMsgType
= kIOServiceTerminatedNotificationType
;
2541 userMsgType
= kLastIOKitNotificationType
;
2544 userNotify
= new IOServiceUserNotification
;
2546 if (userNotify
&& !userNotify
->init( port
, userMsgType
,
2547 reference
, referenceSize
, client64
)) {
2548 userNotify
->release();
2555 notify
= IOService::addMatchingNotification( sym
, dict
,
2556 &userNotify
->_handler
, userNotify
);
2558 *notification
= userNotify
;
2559 userNotify
->setNotification( notify
);
2560 err
= kIOReturnSuccess
;
2562 err
= kIOReturnUnsupported
;
2566 if ((kIOReturnSuccess
!= err
) && userNotify
) {
2567 userNotify
->invalidatePort();
2568 userNotify
->release();
2583 /* Routine io_service_add_notification */
2585 is_io_service_add_notification(
2586 mach_port_t master_port
,
2587 io_name_t notification_type
,
2588 io_string_t matching
,
2590 io_async_ref_t reference
,
2591 mach_msg_type_number_t referenceCnt
,
2592 io_object_t
* notification
)
2594 return kIOReturnUnsupported
;
2597 /* Routine io_service_add_notification_64 */
2599 is_io_service_add_notification_64(
2600 mach_port_t master_port
,
2601 io_name_t notification_type
,
2602 io_string_t matching
,
2603 mach_port_t wake_port
,
2604 io_async_ref64_t reference
,
2605 mach_msg_type_number_t referenceCnt
,
2606 io_object_t
*notification
)
2608 return kIOReturnUnsupported
;
2611 /* Routine io_service_add_notification_bin */
2613 is_io_service_add_notification_bin
2615 mach_port_t master_port
,
2616 io_name_t notification_type
,
2617 io_struct_inband_t matching
,
2618 mach_msg_type_number_t matchingCnt
,
2619 mach_port_t wake_port
,
2620 io_async_ref_t reference
,
2621 mach_msg_type_number_t referenceCnt
,
2622 io_object_t
*notification
)
2624 io_async_ref_t zreference
;
2626 if (referenceCnt
> ASYNC_REF_COUNT
) {
2627 return kIOReturnBadArgument
;
2629 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2630 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2632 return internal_io_service_add_notification(master_port
, notification_type
,
2633 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref_t
),
2634 false, notification
);
2637 /* Routine io_service_add_notification_bin_64 */
2639 is_io_service_add_notification_bin_64
2641 mach_port_t master_port
,
2642 io_name_t notification_type
,
2643 io_struct_inband_t matching
,
2644 mach_msg_type_number_t matchingCnt
,
2645 mach_port_t wake_port
,
2646 io_async_ref64_t reference
,
2647 mach_msg_type_number_t referenceCnt
,
2648 io_object_t
*notification
)
2650 io_async_ref64_t zreference
;
2652 if (referenceCnt
> ASYNC_REF64_COUNT
) {
2653 return kIOReturnBadArgument
;
2655 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2656 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2658 return internal_io_service_add_notification(master_port
, notification_type
,
2659 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref64_t
),
2660 true, notification
);
2663 static kern_return_t
2664 internal_io_service_add_notification_ool(
2665 mach_port_t master_port
,
2666 io_name_t notification_type
,
2667 io_buf_ptr_t matching
,
2668 mach_msg_type_number_t matchingCnt
,
2669 mach_port_t wake_port
,
2671 vm_size_t referenceSize
,
2673 kern_return_t
*result
,
2674 io_object_t
*notification
)
2678 vm_map_offset_t map_data
;
2680 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2681 data
= CAST_DOWN(vm_offset_t
, map_data
);
2683 if (KERN_SUCCESS
== kr
) {
2684 // must return success after vm_map_copyout() succeeds
2685 // and mig will copy out objects on success
2687 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2688 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2689 vm_deallocate( kernel_map
, data
, matchingCnt
);
2695 /* Routine io_service_add_notification_ool */
2697 is_io_service_add_notification_ool(
2698 mach_port_t master_port
,
2699 io_name_t notification_type
,
2700 io_buf_ptr_t matching
,
2701 mach_msg_type_number_t matchingCnt
,
2702 mach_port_t wake_port
,
2703 io_async_ref_t reference
,
2704 mach_msg_type_number_t referenceCnt
,
2705 kern_return_t
*result
,
2706 io_object_t
*notification
)
2708 io_async_ref_t zreference
;
2710 if (referenceCnt
> ASYNC_REF_COUNT
) {
2711 return kIOReturnBadArgument
;
2713 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2714 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2716 return internal_io_service_add_notification_ool(master_port
, notification_type
,
2717 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref_t
),
2718 false, result
, notification
);
2721 /* Routine io_service_add_notification_ool_64 */
2723 is_io_service_add_notification_ool_64(
2724 mach_port_t master_port
,
2725 io_name_t notification_type
,
2726 io_buf_ptr_t matching
,
2727 mach_msg_type_number_t matchingCnt
,
2728 mach_port_t wake_port
,
2729 io_async_ref64_t reference
,
2730 mach_msg_type_number_t referenceCnt
,
2731 kern_return_t
*result
,
2732 io_object_t
*notification
)
2734 io_async_ref64_t zreference
;
2736 if (referenceCnt
> ASYNC_REF64_COUNT
) {
2737 return kIOReturnBadArgument
;
2739 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2740 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2742 return internal_io_service_add_notification_ool(master_port
, notification_type
,
2743 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref64_t
),
2744 true, result
, notification
);
2747 /* Routine io_service_add_notification_old */
2749 is_io_service_add_notification_old(
2750 mach_port_t master_port
,
2751 io_name_t notification_type
,
2752 io_string_t matching
,
2754 // for binary compatibility reasons, this must be natural_t for ILP32
2756 io_object_t
* notification
)
2758 return is_io_service_add_notification( master_port
, notification_type
,
2759 matching
, port
, &ref
, 1, notification
);
2763 static kern_return_t
2764 internal_io_service_add_interest_notification(
2765 io_object_t _service
,
2766 io_name_t type_of_interest
,
2769 vm_size_t referenceSize
,
2771 io_object_t
* notification
)
2773 IOServiceMessageUserNotification
* userNotify
= 0;
2774 IONotifier
* notify
= 0;
2775 const OSSymbol
* sym
;
2778 CHECK( IOService
, _service
, service
);
2780 err
= kIOReturnNoResources
;
2781 if ((sym
= OSSymbol::withCString( type_of_interest
))) {
2783 userNotify
= new IOServiceMessageUserNotification
;
2785 if (userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2786 reference
, referenceSize
,
2787 kIOUserNotifyMaxMessageSize
,
2789 userNotify
->release();
2796 notify
= service
->registerInterest( sym
,
2797 &userNotify
->_handler
, userNotify
);
2799 *notification
= userNotify
;
2800 userNotify
->setNotification( notify
);
2801 err
= kIOReturnSuccess
;
2803 err
= kIOReturnUnsupported
;
2810 if ((kIOReturnSuccess
!= err
) && userNotify
) {
2811 userNotify
->invalidatePort();
2812 userNotify
->release();
2819 /* Routine io_service_add_message_notification */
2821 is_io_service_add_interest_notification(
2822 io_object_t service
,
2823 io_name_t type_of_interest
,
2825 io_async_ref_t reference
,
2826 mach_msg_type_number_t referenceCnt
,
2827 io_object_t
* notification
)
2829 io_async_ref_t zreference
;
2831 if (referenceCnt
> ASYNC_REF_COUNT
) {
2832 return kIOReturnBadArgument
;
2834 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2835 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2837 return internal_io_service_add_interest_notification(service
, type_of_interest
,
2838 port
, &zreference
[0], sizeof(io_async_ref_t
), false, notification
);
2841 /* Routine io_service_add_interest_notification_64 */
2843 is_io_service_add_interest_notification_64(
2844 io_object_t service
,
2845 io_name_t type_of_interest
,
2846 mach_port_t wake_port
,
2847 io_async_ref64_t reference
,
2848 mach_msg_type_number_t referenceCnt
,
2849 io_object_t
*notification
)
2851 io_async_ref64_t zreference
;
2853 if (referenceCnt
> ASYNC_REF64_COUNT
) {
2854 return kIOReturnBadArgument
;
2856 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2857 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2859 return internal_io_service_add_interest_notification(service
, type_of_interest
,
2860 wake_port
, &zreference
[0], sizeof(io_async_ref64_t
), true, notification
);
2864 /* Routine io_service_acknowledge_notification */
2866 is_io_service_acknowledge_notification(
2867 io_object_t _service
,
2868 natural_t notify_ref
,
2869 natural_t response
)
2871 CHECK( IOService
, _service
, service
);
2873 return service
->acknowledgeNotification((IONotificationRef
)(uintptr_t) notify_ref
,
2874 (IOOptionBits
) response
);
2877 /* Routine io_connect_get_semaphore */
2879 is_io_connect_get_notification_semaphore(
2880 io_connect_t connection
,
2881 natural_t notification_type
,
2882 semaphore_t
*semaphore
)
2884 CHECK( IOUserClient
, connection
, client
);
2886 IOStatisticsClientCall();
2887 return client
->getNotificationSemaphore((UInt32
) notification_type
,
2891 /* Routine io_registry_get_root_entry */
2893 is_io_registry_get_root_entry(
2894 mach_port_t master_port
,
2897 IORegistryEntry
* entry
;
2899 if (master_port
!= master_device_port
) {
2900 return kIOReturnNotPrivileged
;
2903 entry
= IORegistryEntry::getRegistryRoot();
2909 return kIOReturnSuccess
;
2912 /* Routine io_registry_create_iterator */
2914 is_io_registry_create_iterator(
2915 mach_port_t master_port
,
2918 io_object_t
*iterator
)
2920 if (master_port
!= master_device_port
) {
2921 return kIOReturnNotPrivileged
;
2924 *iterator
= IOUserIterator::withIterator(
2925 IORegistryIterator::iterateOver(
2926 IORegistryEntry::getPlane( plane
), options
));
2928 return *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
;
2931 /* Routine io_registry_entry_create_iterator */
2933 is_io_registry_entry_create_iterator(
2934 io_object_t registry_entry
,
2937 io_object_t
*iterator
)
2939 CHECK( IORegistryEntry
, registry_entry
, entry
);
2941 *iterator
= IOUserIterator::withIterator(
2942 IORegistryIterator::iterateOver( entry
,
2943 IORegistryEntry::getPlane( plane
), options
));
2945 return *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
;
2948 /* Routine io_registry_iterator_enter */
2950 is_io_registry_iterator_enter_entry(
2951 io_object_t iterator
)
2953 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2955 IOLockLock(oIter
->lock
);
2957 IOLockUnlock(oIter
->lock
);
2959 return kIOReturnSuccess
;
2962 /* Routine io_registry_iterator_exit */
2964 is_io_registry_iterator_exit_entry(
2965 io_object_t iterator
)
2969 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2971 IOLockLock(oIter
->lock
);
2972 didIt
= iter
->exitEntry();
2973 IOLockUnlock(oIter
->lock
);
2975 return didIt
? kIOReturnSuccess
: kIOReturnNoDevice
;
2978 /* Routine io_registry_entry_from_path */
2980 is_io_registry_entry_from_path(
2981 mach_port_t master_port
,
2983 io_object_t
*registry_entry
)
2985 IORegistryEntry
* entry
;
2987 if (master_port
!= master_device_port
) {
2988 return kIOReturnNotPrivileged
;
2991 entry
= IORegistryEntry::fromPath( path
);
2993 *registry_entry
= entry
;
2995 return kIOReturnSuccess
;
2999 /* Routine io_registry_entry_from_path */
3001 is_io_registry_entry_from_path_ool(
3002 mach_port_t master_port
,
3003 io_string_inband_t path
,
3004 io_buf_ptr_t path_ool
,
3005 mach_msg_type_number_t path_oolCnt
,
3006 kern_return_t
*result
,
3007 io_object_t
*registry_entry
)
3009 IORegistryEntry
* entry
;
3010 vm_map_offset_t map_data
;
3015 if (master_port
!= master_device_port
) {
3016 return kIOReturnNotPrivileged
;
3021 res
= err
= KERN_SUCCESS
;
3026 return kIOReturnBadArgument
;
3028 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) {
3029 return kIOReturnMessageTooLarge
;
3032 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
3033 if (KERN_SUCCESS
== err
) {
3034 // must return success to mig after vm_map_copyout() succeeds, so result is actual
3035 cpath
= CAST_DOWN(const char *, map_data
);
3036 if (cpath
[path_oolCnt
- 1]) {
3037 res
= kIOReturnBadArgument
;
3042 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
)) {
3043 entry
= IORegistryEntry::fromPath(cpath
);
3044 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
3048 vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
3051 if (KERN_SUCCESS
!= err
) {
3054 *registry_entry
= entry
;
3061 /* Routine io_registry_entry_in_plane */
3063 is_io_registry_entry_in_plane(
3064 io_object_t registry_entry
,
3066 boolean_t
*inPlane
)
3068 CHECK( IORegistryEntry
, registry_entry
, entry
);
3070 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
3072 return kIOReturnSuccess
;
3076 /* Routine io_registry_entry_get_path */
3078 is_io_registry_entry_get_path(
3079 io_object_t registry_entry
,
3084 CHECK( IORegistryEntry
, registry_entry
, entry
);
3086 length
= sizeof(io_string_t
);
3087 if (entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
))) {
3088 return kIOReturnSuccess
;
3090 return kIOReturnBadArgument
;
3094 /* Routine io_registry_entry_get_path */
3096 is_io_registry_entry_get_path_ool(
3097 io_object_t registry_entry
,
3099 io_string_inband_t path
,
3100 io_buf_ptr_t
*path_ool
,
3101 mach_msg_type_number_t
*path_oolCnt
)
3103 enum { kMaxPath
= 16384 };
3108 CHECK( IORegistryEntry
, registry_entry
, entry
);
3112 length
= sizeof(io_string_inband_t
);
3113 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) {
3114 err
= kIOReturnSuccess
;
3117 buf
= IONew(char, length
);
3119 err
= kIOReturnNoMemory
;
3120 } else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) {
3121 err
= kIOReturnError
;
3123 *path_oolCnt
= length
;
3124 err
= copyoutkdata(buf
, length
, path_ool
);
3127 IODelete(buf
, char, kMaxPath
);
3135 /* Routine io_registry_entry_get_name */
3137 is_io_registry_entry_get_name(
3138 io_object_t registry_entry
,
3141 CHECK( IORegistryEntry
, registry_entry
, entry
);
3143 strncpy( name
, entry
->getName(), sizeof(io_name_t
));
3145 return kIOReturnSuccess
;
3148 /* Routine io_registry_entry_get_name_in_plane */
3150 is_io_registry_entry_get_name_in_plane(
3151 io_object_t registry_entry
,
3152 io_name_t planeName
,
3155 const IORegistryPlane
* plane
;
3156 CHECK( IORegistryEntry
, registry_entry
, entry
);
3159 plane
= IORegistryEntry::getPlane( planeName
);
3164 strncpy( name
, entry
->getName( plane
), sizeof(io_name_t
));
3166 return kIOReturnSuccess
;
3169 /* Routine io_registry_entry_get_location_in_plane */
3171 is_io_registry_entry_get_location_in_plane(
3172 io_object_t registry_entry
,
3173 io_name_t planeName
,
3174 io_name_t location
)
3176 const IORegistryPlane
* plane
;
3177 CHECK( IORegistryEntry
, registry_entry
, entry
);
3180 plane
= IORegistryEntry::getPlane( planeName
);
3185 const char * cstr
= entry
->getLocation( plane
);
3188 strncpy( location
, cstr
, sizeof(io_name_t
));
3189 return kIOReturnSuccess
;
3191 return kIOReturnNotFound
;
3195 /* Routine io_registry_entry_get_registry_entry_id */
3197 is_io_registry_entry_get_registry_entry_id(
3198 io_object_t registry_entry
,
3199 uint64_t *entry_id
)
3201 CHECK( IORegistryEntry
, registry_entry
, entry
);
3203 *entry_id
= entry
->getRegistryEntryID();
3205 return kIOReturnSuccess
;
3208 /* Routine io_registry_entry_get_property */
3210 is_io_registry_entry_get_property_bytes(
3211 io_object_t registry_entry
,
3212 io_name_t property_name
,
3213 io_struct_inband_t buf
,
3214 mach_msg_type_number_t
*dataCnt
)
3222 unsigned int len
= 0;
3223 const void * bytes
= 0;
3224 IOReturn ret
= kIOReturnSuccess
;
3226 CHECK( IORegistryEntry
, registry_entry
, entry
);
3229 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3230 return kIOReturnNotPermitted
;
3234 obj
= entry
->copyProperty(property_name
);
3236 return kIOReturnNoResources
;
3239 // One day OSData will be a common container base class
3241 if ((data
= OSDynamicCast( OSData
, obj
))) {
3242 len
= data
->getLength();
3243 bytes
= data
->getBytesNoCopy();
3244 if (!data
->isSerializable()) {
3247 } else if ((str
= OSDynamicCast( OSString
, obj
))) {
3248 len
= str
->getLength() + 1;
3249 bytes
= str
->getCStringNoCopy();
3250 } else if ((boo
= OSDynamicCast( OSBoolean
, obj
))) {
3251 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
3252 bytes
= boo
->isTrue() ? "Yes" : "No";
3253 } else if ((off
= OSDynamicCast( OSNumber
, obj
))) {
3254 offsetBytes
= off
->unsigned64BitValue();
3255 len
= off
->numberOfBytes();
3256 if (len
> sizeof(offsetBytes
)) {
3257 len
= sizeof(offsetBytes
);
3259 bytes
= &offsetBytes
;
3260 #ifdef __BIG_ENDIAN__
3261 bytes
= (const void *)
3262 (((UInt32
) bytes
) + (sizeof(UInt64
) - len
));
3265 ret
= kIOReturnBadArgument
;
3269 if (*dataCnt
< len
) {
3270 ret
= kIOReturnIPCError
;
3273 bcopy( bytes
, buf
, len
);
3282 /* Routine io_registry_entry_get_property */
3284 is_io_registry_entry_get_property(
3285 io_object_t registry_entry
,
3286 io_name_t property_name
,
3287 io_buf_ptr_t
*properties
,
3288 mach_msg_type_number_t
*propertiesCnt
)
3294 CHECK( IORegistryEntry
, registry_entry
, entry
);
3297 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3298 return kIOReturnNotPermitted
;
3302 obj
= entry
->copyProperty(property_name
);
3304 return kIOReturnNotFound
;
3307 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3310 return kIOReturnNoMemory
;
3313 if (obj
->serialize( s
)) {
3314 len
= s
->getLength();
3315 *propertiesCnt
= len
;
3316 err
= copyoutkdata( s
->text(), len
, properties
);
3318 err
= kIOReturnUnsupported
;
3327 /* Routine io_registry_entry_get_property_recursively */
3329 is_io_registry_entry_get_property_recursively(
3330 io_object_t registry_entry
,
3332 io_name_t property_name
,
3334 io_buf_ptr_t
*properties
,
3335 mach_msg_type_number_t
*propertiesCnt
)
3341 CHECK( IORegistryEntry
, registry_entry
, entry
);
3344 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3345 return kIOReturnNotPermitted
;
3349 obj
= entry
->copyProperty( property_name
,
3350 IORegistryEntry::getPlane( plane
), options
);
3352 return kIOReturnNotFound
;
3355 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3358 return kIOReturnNoMemory
;
3361 if (obj
->serialize( s
)) {
3362 len
= s
->getLength();
3363 *propertiesCnt
= len
;
3364 err
= copyoutkdata( s
->text(), len
, properties
);
3366 err
= kIOReturnUnsupported
;
3375 /* Routine io_registry_entry_get_properties */
3377 is_io_registry_entry_get_properties(
3378 io_object_t registry_entry
,
3379 io_buf_ptr_t
*properties
,
3380 mach_msg_type_number_t
*propertiesCnt
)
3382 return kIOReturnUnsupported
;
3387 struct GetPropertiesEditorRef
{
3389 IORegistryEntry
* entry
;
3390 OSCollection
* root
;
3393 static const OSMetaClassBase
*
3394 GetPropertiesEditor(void * reference
,
3396 OSCollection
* container
,
3397 const OSSymbol
* name
,
3398 const OSMetaClassBase
* value
)
3400 GetPropertiesEditorRef
* ref
= (typeof(ref
))reference
;
3403 ref
->root
= container
;
3405 if (ref
->root
== container
) {
3406 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy())) {
3416 #endif /* CONFIG_MACF */
3418 /* Routine io_registry_entry_get_properties */
3420 is_io_registry_entry_get_properties_bin(
3421 io_object_t registry_entry
,
3422 io_buf_ptr_t
*properties
,
3423 mach_msg_type_number_t
*propertiesCnt
)
3425 kern_return_t err
= kIOReturnSuccess
;
3428 OSSerialize::Editor editor
= 0;
3431 CHECK(IORegistryEntry
, registry_entry
, entry
);
3434 GetPropertiesEditorRef ref
;
3435 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
3436 editor
= &GetPropertiesEditor
;
3438 ref
.cred
= kauth_cred_get();
3444 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3446 return kIOReturnNoMemory
;
3449 if (!entry
->serializeProperties(s
)) {
3450 err
= kIOReturnUnsupported
;
3453 if (kIOReturnSuccess
== err
) {
3454 len
= s
->getLength();
3455 *propertiesCnt
= len
;
3456 err
= copyoutkdata(s
->text(), len
, properties
);
3463 /* Routine io_registry_entry_get_property_bin */
3465 is_io_registry_entry_get_property_bin(
3466 io_object_t registry_entry
,
3468 io_name_t property_name
,
3470 io_buf_ptr_t
*properties
,
3471 mach_msg_type_number_t
*propertiesCnt
)
3476 const OSSymbol
* sym
;
3478 CHECK( IORegistryEntry
, registry_entry
, entry
);
3481 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3482 return kIOReturnNotPermitted
;
3486 sym
= OSSymbol::withCString(property_name
);
3488 return kIOReturnNoMemory
;
3491 if (gIORegistryEntryPropertyKeysKey
== sym
) {
3492 obj
= entry
->copyPropertyKeys();
3494 if ((kIORegistryIterateRecursively
& options
) && plane
[0]) {
3495 obj
= entry
->copyProperty(property_name
,
3496 IORegistryEntry::getPlane(plane
), options
);
3498 obj
= entry
->copyProperty(property_name
);
3500 if (obj
&& gIORemoveOnReadProperties
->containsObject(sym
)) {
3501 entry
->removeProperty(sym
);
3507 return kIOReturnNotFound
;
3510 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3513 return kIOReturnNoMemory
;
3516 if (obj
->serialize( s
)) {
3517 len
= s
->getLength();
3518 *propertiesCnt
= len
;
3519 err
= copyoutkdata( s
->text(), len
, properties
);
3521 err
= kIOReturnUnsupported
;
3531 /* Routine io_registry_entry_set_properties */
3533 is_io_registry_entry_set_properties
3535 io_object_t registry_entry
,
3536 io_buf_ptr_t properties
,
3537 mach_msg_type_number_t propertiesCnt
,
3538 kern_return_t
* result
)
3544 vm_map_offset_t map_data
;
3546 CHECK( IORegistryEntry
, registry_entry
, entry
);
3548 if (propertiesCnt
> sizeof(io_struct_inband_t
) * 1024) {
3549 return kIOReturnMessageTooLarge
;
3552 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3553 data
= CAST_DOWN(vm_offset_t
, map_data
);
3555 if (KERN_SUCCESS
== err
) {
3556 FAKE_STACK_FRAME(entry
->getMetaClass());
3558 // must return success after vm_map_copyout() succeeds
3559 obj
= OSUnserializeXML((const char *) data
, propertiesCnt
);
3560 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3563 res
= kIOReturnBadArgument
;
3566 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3567 registry_entry
, obj
)) {
3568 res
= kIOReturnNotPermitted
;
3572 res
= entry
->setProperties( obj
);
3579 FAKE_STACK_FRAME_END();
3588 /* Routine io_registry_entry_get_child_iterator */
3590 is_io_registry_entry_get_child_iterator(
3591 io_object_t registry_entry
,
3593 io_object_t
*iterator
)
3595 CHECK( IORegistryEntry
, registry_entry
, entry
);
3597 *iterator
= IOUserIterator::withIterator(entry
->getChildIterator(
3598 IORegistryEntry::getPlane( plane
)));
3600 return kIOReturnSuccess
;
3603 /* Routine io_registry_entry_get_parent_iterator */
3605 is_io_registry_entry_get_parent_iterator(
3606 io_object_t registry_entry
,
3608 io_object_t
*iterator
)
3610 CHECK( IORegistryEntry
, registry_entry
, entry
);
3612 *iterator
= IOUserIterator::withIterator(entry
->getParentIterator(
3613 IORegistryEntry::getPlane( plane
)));
3615 return kIOReturnSuccess
;
3618 /* Routine io_service_get_busy_state */
3620 is_io_service_get_busy_state(
3621 io_object_t _service
,
3622 uint32_t *busyState
)
3624 CHECK( IOService
, _service
, service
);
3626 *busyState
= service
->getBusyState();
3628 return kIOReturnSuccess
;
3631 /* Routine io_service_get_state */
3633 is_io_service_get_state(
3634 io_object_t _service
,
3636 uint32_t *busy_state
,
3637 uint64_t *accumulated_busy_time
)
3639 CHECK( IOService
, _service
, service
);
3641 *state
= service
->getState();
3642 *busy_state
= service
->getBusyState();
3643 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3645 return kIOReturnSuccess
;
3648 /* Routine io_service_wait_quiet */
3650 is_io_service_wait_quiet(
3651 io_object_t _service
,
3652 mach_timespec_t wait_time
)
3656 CHECK( IOService
, _service
, service
);
3658 timeoutNS
= wait_time
.tv_sec
;
3659 timeoutNS
*= kSecondScale
;
3660 timeoutNS
+= wait_time
.tv_nsec
;
3662 return service
->waitQuiet(timeoutNS
);
3665 /* Routine io_service_request_probe */
3667 is_io_service_request_probe(
3668 io_object_t _service
,
3671 CHECK( IOService
, _service
, service
);
3673 return service
->requestProbe( options
);
3676 /* Routine io_service_get_authorization_id */
3678 is_io_service_get_authorization_id(
3679 io_object_t _service
,
3680 uint64_t *authorization_id
)
3684 CHECK( IOService
, _service
, service
);
3686 kr
= IOUserClient::clientHasPrivilege((void *) current_task(),
3687 kIOClientPrivilegeAdministrator
);
3688 if (kIOReturnSuccess
!= kr
) {
3692 *authorization_id
= service
->getAuthorizationID();
3697 /* Routine io_service_set_authorization_id */
3699 is_io_service_set_authorization_id(
3700 io_object_t _service
,
3701 uint64_t authorization_id
)
3703 CHECK( IOService
, _service
, service
);
3705 return service
->setAuthorizationID( authorization_id
);
3708 /* Routine io_service_open_ndr */
3710 is_io_service_open_extended(
3711 io_object_t _service
,
3713 uint32_t connect_type
,
3715 io_buf_ptr_t properties
,
3716 mach_msg_type_number_t propertiesCnt
,
3717 kern_return_t
* result
,
3718 io_object_t
*connection
)
3720 IOUserClient
* client
= 0;
3721 kern_return_t err
= KERN_SUCCESS
;
3722 IOReturn res
= kIOReturnSuccess
;
3723 OSDictionary
* propertiesDict
= 0;
3725 bool disallowAccess
;
3727 CHECK( IOService
, _service
, service
);
3730 return kIOReturnBadArgument
;
3732 assert(owningTask
== current_task());
3733 if (owningTask
!= current_task()) {
3734 return kIOReturnBadArgument
;
3739 return kIOReturnUnsupported
;
3745 vm_map_offset_t map_data
;
3747 if (propertiesCnt
> sizeof(io_struct_inband_t
)) {
3748 return kIOReturnMessageTooLarge
;
3751 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3753 data
= CAST_DOWN(vm_offset_t
, map_data
);
3754 if (KERN_SUCCESS
== err
) {
3755 // must return success after vm_map_copyout() succeeds
3756 obj
= OSUnserializeXML((const char *) data
, propertiesCnt
);
3757 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3758 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3759 if (!propertiesDict
) {
3760 res
= kIOReturnBadArgument
;
3766 if (kIOReturnSuccess
!= res
) {
3771 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3773 if (!propertiesDict
) {
3774 propertiesDict
= OSDictionary::withCapacity(4);
3776 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3778 if (propertiesDict
) {
3779 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3785 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3786 connect_type
, propertiesDict
, &client
);
3788 if (propertiesDict
) {
3789 propertiesDict
->release();
3792 if (res
== kIOReturnSuccess
) {
3793 assert( OSDynamicCast(IOUserClient
, client
));
3795 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3796 client
->closed
= false;
3797 client
->lock
= IOLockAlloc();
3799 disallowAccess
= (crossEndian
3800 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3801 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3802 if (disallowAccess
) {
3803 res
= kIOReturnUnsupported
;
3806 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
)) {
3807 res
= kIOReturnNotPermitted
;
3811 if (kIOReturnSuccess
== res
) {
3812 res
= client
->registerOwner(owningTask
);
3815 if (kIOReturnSuccess
!= res
) {
3816 IOStatisticsClientCall();
3817 client
->clientClose();
3822 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3824 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3825 creatorName
->release();
3827 client
->setTerminateDefer(service
, false);
3831 *connection
= client
;
3837 /* Routine io_service_close */
3839 is_io_service_close(
3840 io_object_t connection
)
3843 if ((mappings
= OSDynamicCast(OSSet
, connection
))) {
3844 return kIOReturnSuccess
;
3847 CHECK( IOUserClient
, connection
, client
);
3849 IOStatisticsClientCall();
3851 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
)) {
3852 IOLockLock(client
->lock
);
3853 client
->clientClose();
3854 IOLockUnlock(client
->lock
);
3856 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3857 client
->getRegistryEntryID(), client
->getName());
3860 return kIOReturnSuccess
;
3863 /* Routine io_connect_get_service */
3865 is_io_connect_get_service(
3866 io_object_t connection
,
3867 io_object_t
*service
)
3869 IOService
* theService
;
3871 CHECK( IOUserClient
, connection
, client
);
3873 theService
= client
->getService();
3875 theService
->retain();
3878 *service
= theService
;
3880 return theService
? kIOReturnSuccess
: kIOReturnUnsupported
;
3883 /* Routine io_connect_set_notification_port */
3885 is_io_connect_set_notification_port(
3886 io_object_t connection
,
3887 uint32_t notification_type
,
3892 CHECK( IOUserClient
, connection
, client
);
3894 IOStatisticsClientCall();
3895 IOLockLock(client
->lock
);
3896 ret
= client
->registerNotificationPort( port
, notification_type
,
3897 (io_user_reference_t
) reference
);
3898 IOLockUnlock(client
->lock
);
3902 /* Routine io_connect_set_notification_port */
3904 is_io_connect_set_notification_port_64(
3905 io_object_t connection
,
3906 uint32_t notification_type
,
3908 io_user_reference_t reference
)
3911 CHECK( IOUserClient
, connection
, client
);
3913 IOStatisticsClientCall();
3914 IOLockLock(client
->lock
);
3915 ret
= client
->registerNotificationPort( port
, notification_type
,
3917 IOLockUnlock(client
->lock
);
3921 /* Routine io_connect_map_memory_into_task */
3923 is_io_connect_map_memory_into_task
3925 io_connect_t connection
,
3926 uint32_t memory_type
,
3928 mach_vm_address_t
*address
,
3929 mach_vm_size_t
*size
,
3936 CHECK( IOUserClient
, connection
, client
);
3939 return kIOReturnBadArgument
;
3942 IOStatisticsClientCall();
3943 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3946 *address
= map
->getAddress();
3948 *size
= map
->getSize();
3951 if (client
->sharedInstance
3952 || (into_task
!= current_task())) {
3953 // push a name out to the task owning the map,
3954 // so we can clean up maps
3955 mach_port_name_t name __unused
=
3956 IOMachPort::makeSendRightForTask(
3957 into_task
, map
, IKOT_IOKIT_OBJECT
);
3960 // keep it with the user client
3961 IOLockLock( gIOObjectPortLock
);
3962 if (0 == client
->mappings
) {
3963 client
->mappings
= OSSet::withCapacity(2);
3965 if (client
->mappings
) {
3966 client
->mappings
->setObject( map
);
3968 IOLockUnlock( gIOObjectPortLock
);
3971 err
= kIOReturnSuccess
;
3973 err
= kIOReturnBadArgument
;
3979 /* Routine is_io_connect_map_memory */
3981 is_io_connect_map_memory(
3982 io_object_t connect
,
3990 mach_vm_address_t address
;
3991 mach_vm_size_t size
;
3993 address
= SCALAR64(*mapAddr
);
3994 size
= SCALAR64(*mapSize
);
3996 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3998 *mapAddr
= SCALAR32(address
);
3999 *mapSize
= SCALAR32(size
);
4006 IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
4009 IOMemoryMap
* map
= 0;
4011 IOLockLock(gIOObjectPortLock
);
4013 iter
= OSCollectionIterator::withCollection(mappings
);
4015 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject()))) {
4016 if (mem
== map
->getMemoryDescriptor()) {
4018 mappings
->removeObject(map
);
4025 IOLockUnlock(gIOObjectPortLock
);
4031 /* Routine io_connect_unmap_memory_from_task */
4033 is_io_connect_unmap_memory_from_task
4035 io_connect_t connection
,
4036 uint32_t memory_type
,
4038 mach_vm_address_t address
)
4041 IOOptionBits options
= 0;
4042 IOMemoryDescriptor
* memory
= 0;
4045 CHECK( IOUserClient
, connection
, client
);
4048 return kIOReturnBadArgument
;
4051 IOStatisticsClientCall();
4052 err
= client
->clientMemoryForType((UInt32
) memory_type
, &options
, &memory
);
4054 if (memory
&& (kIOReturnSuccess
== err
)) {
4055 options
= (options
& ~kIOMapUserOptionsMask
)
4056 | kIOMapAnywhere
| kIOMapReference
;
4058 map
= memory
->createMappingInTask( from_task
, address
, options
);
4061 IOLockLock( gIOObjectPortLock
);
4062 if (client
->mappings
) {
4063 client
->mappings
->removeObject( map
);
4065 IOLockUnlock( gIOObjectPortLock
);
4067 mach_port_name_t name
= 0;
4068 if (from_task
!= current_task()) {
4069 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
4074 map
->userClientUnmap();
4075 err
= iokit_mod_send_right( from_task
, name
, -2 );
4076 err
= kIOReturnSuccess
;
4078 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
4080 if (from_task
== current_task()) {
4084 err
= kIOReturnBadArgument
;
4092 is_io_connect_unmap_memory(
4093 io_object_t connect
,
4099 mach_vm_address_t address
;
4101 address
= SCALAR64(mapAddr
);
4103 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
4109 /* Routine io_connect_add_client */
4111 is_io_connect_add_client(
4112 io_object_t connection
,
4113 io_object_t connect_to
)
4115 CHECK( IOUserClient
, connection
, client
);
4116 CHECK( IOUserClient
, connect_to
, to
);
4118 IOStatisticsClientCall();
4119 return client
->connectClient( to
);
4123 /* Routine io_connect_set_properties */
4125 is_io_connect_set_properties(
4126 io_object_t connection
,
4127 io_buf_ptr_t properties
,
4128 mach_msg_type_number_t propertiesCnt
,
4129 kern_return_t
* result
)
4131 return is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
);
4134 /* Routine io_user_client_method */
4136 is_io_connect_method_var_output
4138 io_connect_t connection
,
4140 io_scalar_inband64_t scalar_input
,
4141 mach_msg_type_number_t scalar_inputCnt
,
4142 io_struct_inband_t inband_input
,
4143 mach_msg_type_number_t inband_inputCnt
,
4144 mach_vm_address_t ool_input
,
4145 mach_vm_size_t ool_input_size
,
4146 io_struct_inband_t inband_output
,
4147 mach_msg_type_number_t
*inband_outputCnt
,
4148 io_scalar_inband64_t scalar_output
,
4149 mach_msg_type_number_t
*scalar_outputCnt
,
4150 io_buf_ptr_t
*var_output
,
4151 mach_msg_type_number_t
*var_outputCnt
4154 CHECK( IOUserClient
, connection
, client
);
4156 IOExternalMethodArguments args
;
4158 IOMemoryDescriptor
* inputMD
= 0;
4159 OSObject
* structureVariableOutputData
= 0;
4161 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4162 args
.__reservedA
= 0;
4163 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4165 args
.selector
= selector
;
4167 args
.asyncWakePort
= MACH_PORT_NULL
;
4168 args
.asyncReference
= 0;
4169 args
.asyncReferenceCount
= 0;
4170 args
.structureVariableOutputData
= &structureVariableOutputData
;
4172 args
.scalarInput
= scalar_input
;
4173 args
.scalarInputCount
= scalar_inputCnt
;
4174 args
.structureInput
= inband_input
;
4175 args
.structureInputSize
= inband_inputCnt
;
4177 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4178 return kIOReturnIPCError
;
4182 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4183 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4187 args
.structureInputDescriptor
= inputMD
;
4189 args
.scalarOutput
= scalar_output
;
4190 args
.scalarOutputCount
= *scalar_outputCnt
;
4191 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4192 args
.structureOutput
= inband_output
;
4193 args
.structureOutputSize
= *inband_outputCnt
;
4194 args
.structureOutputDescriptor
= NULL
;
4195 args
.structureOutputDescriptorSize
= 0;
4197 IOStatisticsClientCall();
4198 ret
= client
->externalMethod( selector
, &args
);
4200 *scalar_outputCnt
= args
.scalarOutputCount
;
4201 *inband_outputCnt
= args
.structureOutputSize
;
4203 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
)) {
4204 OSSerialize
* serialize
;
4208 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
))) {
4209 len
= serialize
->getLength();
4210 *var_outputCnt
= len
;
4211 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
4212 } else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
))) {
4213 len
= data
->getLength();
4214 *var_outputCnt
= len
;
4215 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
4217 ret
= kIOReturnUnderrun
;
4224 if (structureVariableOutputData
) {
4225 structureVariableOutputData
->release();
4231 /* Routine io_user_client_method */
4233 is_io_connect_method
4235 io_connect_t connection
,
4237 io_scalar_inband64_t scalar_input
,
4238 mach_msg_type_number_t scalar_inputCnt
,
4239 io_struct_inband_t inband_input
,
4240 mach_msg_type_number_t inband_inputCnt
,
4241 mach_vm_address_t ool_input
,
4242 mach_vm_size_t ool_input_size
,
4243 io_struct_inband_t inband_output
,
4244 mach_msg_type_number_t
*inband_outputCnt
,
4245 io_scalar_inband64_t scalar_output
,
4246 mach_msg_type_number_t
*scalar_outputCnt
,
4247 mach_vm_address_t ool_output
,
4248 mach_vm_size_t
*ool_output_size
4251 CHECK( IOUserClient
, connection
, client
);
4253 IOExternalMethodArguments args
;
4255 IOMemoryDescriptor
* inputMD
= 0;
4256 IOMemoryDescriptor
* outputMD
= 0;
4258 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4259 args
.__reservedA
= 0;
4260 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4262 args
.selector
= selector
;
4264 args
.asyncWakePort
= MACH_PORT_NULL
;
4265 args
.asyncReference
= 0;
4266 args
.asyncReferenceCount
= 0;
4267 args
.structureVariableOutputData
= 0;
4269 args
.scalarInput
= scalar_input
;
4270 args
.scalarInputCount
= scalar_inputCnt
;
4271 args
.structureInput
= inband_input
;
4272 args
.structureInputSize
= inband_inputCnt
;
4274 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4275 return kIOReturnIPCError
;
4277 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) {
4278 return kIOReturnIPCError
;
4282 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4283 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4287 args
.structureInputDescriptor
= inputMD
;
4289 args
.scalarOutput
= scalar_output
;
4290 args
.scalarOutputCount
= *scalar_outputCnt
;
4291 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4292 args
.structureOutput
= inband_output
;
4293 args
.structureOutputSize
= *inband_outputCnt
;
4295 if (ool_output
&& ool_output_size
) {
4296 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4297 kIODirectionIn
, current_task());
4300 args
.structureOutputDescriptor
= outputMD
;
4301 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
4303 IOStatisticsClientCall();
4304 ret
= client
->externalMethod( selector
, &args
);
4306 *scalar_outputCnt
= args
.scalarOutputCount
;
4307 *inband_outputCnt
= args
.structureOutputSize
;
4308 *ool_output_size
= args
.structureOutputDescriptorSize
;
4314 outputMD
->release();
4320 /* Routine io_async_user_client_method */
4322 is_io_connect_async_method
4324 io_connect_t connection
,
4325 mach_port_t wake_port
,
4326 io_async_ref64_t reference
,
4327 mach_msg_type_number_t referenceCnt
,
4329 io_scalar_inband64_t scalar_input
,
4330 mach_msg_type_number_t scalar_inputCnt
,
4331 io_struct_inband_t inband_input
,
4332 mach_msg_type_number_t inband_inputCnt
,
4333 mach_vm_address_t ool_input
,
4334 mach_vm_size_t ool_input_size
,
4335 io_struct_inband_t inband_output
,
4336 mach_msg_type_number_t
*inband_outputCnt
,
4337 io_scalar_inband64_t scalar_output
,
4338 mach_msg_type_number_t
*scalar_outputCnt
,
4339 mach_vm_address_t ool_output
,
4340 mach_vm_size_t
* ool_output_size
4343 CHECK( IOUserClient
, connection
, client
);
4345 IOExternalMethodArguments args
;
4347 IOMemoryDescriptor
* inputMD
= 0;
4348 IOMemoryDescriptor
* outputMD
= 0;
4350 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4351 args
.__reservedA
= 0;
4352 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4354 reference
[0] = (io_user_reference_t
) wake_port
;
4355 if (vm_map_is_64bit(get_task_map(current_task()))) {
4356 reference
[0] |= kIOUCAsync64Flag
;
4359 args
.selector
= selector
;
4361 args
.asyncWakePort
= wake_port
;
4362 args
.asyncReference
= reference
;
4363 args
.asyncReferenceCount
= referenceCnt
;
4365 args
.structureVariableOutputData
= 0;
4367 args
.scalarInput
= scalar_input
;
4368 args
.scalarInputCount
= scalar_inputCnt
;
4369 args
.structureInput
= inband_input
;
4370 args
.structureInputSize
= inband_inputCnt
;
4372 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4373 return kIOReturnIPCError
;
4375 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) {
4376 return kIOReturnIPCError
;
4380 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4381 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4385 args
.structureInputDescriptor
= inputMD
;
4387 args
.scalarOutput
= scalar_output
;
4388 args
.scalarOutputCount
= *scalar_outputCnt
;
4389 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4390 args
.structureOutput
= inband_output
;
4391 args
.structureOutputSize
= *inband_outputCnt
;
4394 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4395 kIODirectionIn
, current_task());
4398 args
.structureOutputDescriptor
= outputMD
;
4399 args
.structureOutputDescriptorSize
= *ool_output_size
;
4401 IOStatisticsClientCall();
4402 ret
= client
->externalMethod( selector
, &args
);
4404 *inband_outputCnt
= args
.structureOutputSize
;
4405 *ool_output_size
= args
.structureOutputDescriptorSize
;
4411 outputMD
->release();
4417 /* Routine io_connect_method_scalarI_scalarO */
4419 is_io_connect_method_scalarI_scalarO(
4420 io_object_t connect
,
4422 io_scalar_inband_t input
,
4423 mach_msg_type_number_t inputCount
,
4424 io_scalar_inband_t output
,
4425 mach_msg_type_number_t
* outputCount
)
4429 io_scalar_inband64_t _input
;
4430 io_scalar_inband64_t _output
;
4432 mach_msg_type_number_t struct_outputCnt
= 0;
4433 mach_vm_size_t ool_output_size
= 0;
4435 bzero(&_output
[0], sizeof(_output
));
4436 for (i
= 0; i
< inputCount
; i
++) {
4437 _input
[i
] = SCALAR64(input
[i
]);
4440 err
= is_io_connect_method(connect
, index
,
4444 NULL
, &struct_outputCnt
,
4445 _output
, outputCount
,
4446 0, &ool_output_size
);
4448 for (i
= 0; i
< *outputCount
; i
++) {
4449 output
[i
] = SCALAR32(_output
[i
]);
4456 shim_io_connect_method_scalarI_scalarO(
4457 IOExternalMethod
* method
,
4459 const io_user_scalar_t
* input
,
4460 mach_msg_type_number_t inputCount
,
4461 io_user_scalar_t
* output
,
4462 mach_msg_type_number_t
* outputCount
)
4465 io_scalar_inband_t _output
;
4467 err
= kIOReturnBadArgument
;
4469 bzero(&_output
[0], sizeof(_output
));
4471 if (inputCount
!= method
->count0
) {
4472 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4473 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4476 if (*outputCount
!= method
->count1
) {
4477 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4478 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4482 func
= method
->func
;
4484 switch (inputCount
) {
4486 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4487 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]));
4490 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4491 ARG32(input
[3]), ARG32(input
[4]),
4495 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4497 &_output
[0], &_output
[1] );
4500 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4501 &_output
[0], &_output
[1], &_output
[2] );
4504 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4505 &_output
[0], &_output
[1], &_output
[2],
4509 err
= (object
->*func
)( ARG32(input
[0]),
4510 &_output
[0], &_output
[1], &_output
[2],
4511 &_output
[3], &_output
[4] );
4514 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
4515 &_output
[3], &_output
[4], &_output
[5] );
4519 IOLog("%s: Bad method table\n", object
->getName());
4524 for (i
= 0; i
< *outputCount
; i
++) {
4525 output
[i
] = SCALAR32(_output
[i
]);
4531 /* Routine io_async_method_scalarI_scalarO */
4533 is_io_async_method_scalarI_scalarO(
4534 io_object_t connect
,
4535 mach_port_t wake_port
,
4536 io_async_ref_t reference
,
4537 mach_msg_type_number_t referenceCnt
,
4539 io_scalar_inband_t input
,
4540 mach_msg_type_number_t inputCount
,
4541 io_scalar_inband_t output
,
4542 mach_msg_type_number_t
* outputCount
)
4546 io_scalar_inband64_t _input
;
4547 io_scalar_inband64_t _output
;
4548 io_async_ref64_t _reference
;
4550 bzero(&_output
[0], sizeof(_output
));
4551 for (i
= 0; i
< referenceCnt
; i
++) {
4552 _reference
[i
] = REF64(reference
[i
]);
4555 mach_msg_type_number_t struct_outputCnt
= 0;
4556 mach_vm_size_t ool_output_size
= 0;
4558 for (i
= 0; i
< inputCount
; i
++) {
4559 _input
[i
] = SCALAR64(input
[i
]);
4562 err
= is_io_connect_async_method(connect
,
4563 wake_port
, _reference
, referenceCnt
,
4568 NULL
, &struct_outputCnt
,
4569 _output
, outputCount
,
4570 0, &ool_output_size
);
4572 for (i
= 0; i
< *outputCount
; i
++) {
4573 output
[i
] = SCALAR32(_output
[i
]);
4578 /* Routine io_async_method_scalarI_structureO */
4580 is_io_async_method_scalarI_structureO(
4581 io_object_t connect
,
4582 mach_port_t wake_port
,
4583 io_async_ref_t reference
,
4584 mach_msg_type_number_t referenceCnt
,
4586 io_scalar_inband_t input
,
4587 mach_msg_type_number_t inputCount
,
4588 io_struct_inband_t output
,
4589 mach_msg_type_number_t
* outputCount
)
4592 io_scalar_inband64_t _input
;
4593 io_async_ref64_t _reference
;
4595 for (i
= 0; i
< referenceCnt
; i
++) {
4596 _reference
[i
] = REF64(reference
[i
]);
4599 mach_msg_type_number_t scalar_outputCnt
= 0;
4600 mach_vm_size_t ool_output_size
= 0;
4602 for (i
= 0; i
< inputCount
; i
++) {
4603 _input
[i
] = SCALAR64(input
[i
]);
4606 return is_io_connect_async_method(connect
,
4607 wake_port
, _reference
, referenceCnt
,
4612 output
, outputCount
,
4613 NULL
, &scalar_outputCnt
,
4614 0, &ool_output_size
);
4617 /* Routine io_async_method_scalarI_structureI */
4619 is_io_async_method_scalarI_structureI(
4620 io_connect_t connect
,
4621 mach_port_t wake_port
,
4622 io_async_ref_t reference
,
4623 mach_msg_type_number_t referenceCnt
,
4625 io_scalar_inband_t input
,
4626 mach_msg_type_number_t inputCount
,
4627 io_struct_inband_t inputStruct
,
4628 mach_msg_type_number_t inputStructCount
)
4631 io_scalar_inband64_t _input
;
4632 io_async_ref64_t _reference
;
4634 for (i
= 0; i
< referenceCnt
; i
++) {
4635 _reference
[i
] = REF64(reference
[i
]);
4638 mach_msg_type_number_t scalar_outputCnt
= 0;
4639 mach_msg_type_number_t inband_outputCnt
= 0;
4640 mach_vm_size_t ool_output_size
= 0;
4642 for (i
= 0; i
< inputCount
; i
++) {
4643 _input
[i
] = SCALAR64(input
[i
]);
4646 return is_io_connect_async_method(connect
,
4647 wake_port
, _reference
, referenceCnt
,
4650 inputStruct
, inputStructCount
,
4652 NULL
, &inband_outputCnt
,
4653 NULL
, &scalar_outputCnt
,
4654 0, &ool_output_size
);
4657 /* Routine io_async_method_structureI_structureO */
4659 is_io_async_method_structureI_structureO(
4660 io_object_t connect
,
4661 mach_port_t wake_port
,
4662 io_async_ref_t reference
,
4663 mach_msg_type_number_t referenceCnt
,
4665 io_struct_inband_t input
,
4666 mach_msg_type_number_t inputCount
,
4667 io_struct_inband_t output
,
4668 mach_msg_type_number_t
* outputCount
)
4671 mach_msg_type_number_t scalar_outputCnt
= 0;
4672 mach_vm_size_t ool_output_size
= 0;
4673 io_async_ref64_t _reference
;
4675 for (i
= 0; i
< referenceCnt
; i
++) {
4676 _reference
[i
] = REF64(reference
[i
]);
4679 return is_io_connect_async_method(connect
,
4680 wake_port
, _reference
, referenceCnt
,
4685 output
, outputCount
,
4686 NULL
, &scalar_outputCnt
,
4687 0, &ool_output_size
);
4692 shim_io_async_method_scalarI_scalarO(
4693 IOExternalAsyncMethod
* method
,
4695 mach_port_t asyncWakePort
,
4696 io_user_reference_t
* asyncReference
,
4697 uint32_t asyncReferenceCount
,
4698 const io_user_scalar_t
* input
,
4699 mach_msg_type_number_t inputCount
,
4700 io_user_scalar_t
* output
,
4701 mach_msg_type_number_t
* outputCount
)
4705 io_scalar_inband_t _output
;
4707 io_async_ref_t reference
;
4709 bzero(&_output
[0], sizeof(_output
));
4710 for (i
= 0; i
< asyncReferenceCount
; i
++) {
4711 reference
[i
] = REF32(asyncReference
[i
]);
4714 err
= kIOReturnBadArgument
;
4717 if (inputCount
!= method
->count0
) {
4718 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4719 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4722 if (*outputCount
!= method
->count1
) {
4723 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4724 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4728 func
= method
->func
;
4730 switch (inputCount
) {
4732 err
= (object
->*func
)( reference
,
4733 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4734 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]));
4737 err
= (object
->*func
)( reference
,
4738 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4739 ARG32(input
[3]), ARG32(input
[4]),
4743 err
= (object
->*func
)( reference
,
4744 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4746 &_output
[0], &_output
[1] );
4749 err
= (object
->*func
)( reference
,
4750 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4751 &_output
[0], &_output
[1], &_output
[2] );
4754 err
= (object
->*func
)( reference
,
4755 ARG32(input
[0]), ARG32(input
[1]),
4756 &_output
[0], &_output
[1], &_output
[2],
4760 err
= (object
->*func
)( reference
,
4762 &_output
[0], &_output
[1], &_output
[2],
4763 &_output
[3], &_output
[4] );
4766 err
= (object
->*func
)( reference
,
4767 &_output
[0], &_output
[1], &_output
[2],
4768 &_output
[3], &_output
[4], &_output
[5] );
4772 IOLog("%s: Bad method table\n", object
->getName());
4776 for (i
= 0; i
< *outputCount
; i
++) {
4777 output
[i
] = SCALAR32(_output
[i
]);
4784 /* Routine io_connect_method_scalarI_structureO */
4786 is_io_connect_method_scalarI_structureO(
4787 io_object_t connect
,
4789 io_scalar_inband_t input
,
4790 mach_msg_type_number_t inputCount
,
4791 io_struct_inband_t output
,
4792 mach_msg_type_number_t
* outputCount
)
4795 io_scalar_inband64_t _input
;
4797 mach_msg_type_number_t scalar_outputCnt
= 0;
4798 mach_vm_size_t ool_output_size
= 0;
4800 for (i
= 0; i
< inputCount
; i
++) {
4801 _input
[i
] = SCALAR64(input
[i
]);
4804 return is_io_connect_method(connect
, index
,
4808 output
, outputCount
,
4809 NULL
, &scalar_outputCnt
,
4810 0, &ool_output_size
);
4814 shim_io_connect_method_scalarI_structureO(
4816 IOExternalMethod
* method
,
4818 const io_user_scalar_t
* input
,
4819 mach_msg_type_number_t inputCount
,
4820 io_struct_inband_t output
,
4821 IOByteCount
* outputCount
)
4826 err
= kIOReturnBadArgument
;
4829 if (inputCount
!= method
->count0
) {
4830 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4831 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4834 if ((kIOUCVariableStructureSize
!= method
->count1
)
4835 && (*outputCount
!= method
->count1
)) {
4836 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
);
4837 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4841 func
= method
->func
;
4843 switch (inputCount
) {
4845 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4846 ARG32(input
[3]), ARG32(input
[4]),
4850 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4852 output
, (void *)outputCount
);
4855 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4856 output
, (void *)outputCount
, 0 );
4859 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4860 output
, (void *)outputCount
, 0, 0 );
4863 err
= (object
->*func
)( ARG32(input
[0]),
4864 output
, (void *)outputCount
, 0, 0, 0 );
4867 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4871 IOLog("%s: Bad method table\n", object
->getName());
4880 shim_io_async_method_scalarI_structureO(
4881 IOExternalAsyncMethod
* method
,
4883 mach_port_t asyncWakePort
,
4884 io_user_reference_t
* asyncReference
,
4885 uint32_t asyncReferenceCount
,
4886 const io_user_scalar_t
* input
,
4887 mach_msg_type_number_t inputCount
,
4888 io_struct_inband_t output
,
4889 mach_msg_type_number_t
* outputCount
)
4894 io_async_ref_t reference
;
4896 for (i
= 0; i
< asyncReferenceCount
; i
++) {
4897 reference
[i
] = REF32(asyncReference
[i
]);
4900 err
= kIOReturnBadArgument
;
4902 if (inputCount
!= method
->count0
) {
4903 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4904 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4907 if ((kIOUCVariableStructureSize
!= method
->count1
)
4908 && (*outputCount
!= method
->count1
)) {
4909 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
);
4910 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4914 func
= method
->func
;
4916 switch (inputCount
) {
4918 err
= (object
->*func
)( reference
,
4919 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4920 ARG32(input
[3]), ARG32(input
[4]),
4924 err
= (object
->*func
)( reference
,
4925 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4927 output
, (void *)outputCount
);
4930 err
= (object
->*func
)( reference
,
4931 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4932 output
, (void *)outputCount
, 0 );
4935 err
= (object
->*func
)( reference
,
4936 ARG32(input
[0]), ARG32(input
[1]),
4937 output
, (void *)outputCount
, 0, 0 );
4940 err
= (object
->*func
)( reference
,
4942 output
, (void *)outputCount
, 0, 0, 0 );
4945 err
= (object
->*func
)( reference
,
4946 output
, (void *)outputCount
, 0, 0, 0, 0 );
4950 IOLog("%s: Bad method table\n", object
->getName());
4957 /* Routine io_connect_method_scalarI_structureI */
4959 is_io_connect_method_scalarI_structureI(
4960 io_connect_t connect
,
4962 io_scalar_inband_t input
,
4963 mach_msg_type_number_t inputCount
,
4964 io_struct_inband_t inputStruct
,
4965 mach_msg_type_number_t inputStructCount
)
4968 io_scalar_inband64_t _input
;
4970 mach_msg_type_number_t scalar_outputCnt
= 0;
4971 mach_msg_type_number_t inband_outputCnt
= 0;
4972 mach_vm_size_t ool_output_size
= 0;
4974 for (i
= 0; i
< inputCount
; i
++) {
4975 _input
[i
] = SCALAR64(input
[i
]);
4978 return is_io_connect_method(connect
, index
,
4980 inputStruct
, inputStructCount
,
4982 NULL
, &inband_outputCnt
,
4983 NULL
, &scalar_outputCnt
,
4984 0, &ool_output_size
);
4988 shim_io_connect_method_scalarI_structureI(
4989 IOExternalMethod
* method
,
4991 const io_user_scalar_t
* input
,
4992 mach_msg_type_number_t inputCount
,
4993 io_struct_inband_t inputStruct
,
4994 mach_msg_type_number_t inputStructCount
)
4997 IOReturn err
= kIOReturnBadArgument
;
5000 if (inputCount
!= method
->count0
) {
5001 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5002 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5005 if ((kIOUCVariableStructureSize
!= method
->count1
)
5006 && (inputStructCount
!= method
->count1
)) {
5007 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
);
5008 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
5012 func
= method
->func
;
5014 switch (inputCount
) {
5016 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5017 ARG32(input
[3]), ARG32(input
[4]),
5021 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
5023 inputStruct
, (void *)(uintptr_t)inputStructCount
);
5026 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5027 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5031 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
5032 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5036 err
= (object
->*func
)( ARG32(input
[0]),
5037 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5041 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
5046 IOLog("%s: Bad method table\n", object
->getName());
5054 shim_io_async_method_scalarI_structureI(
5055 IOExternalAsyncMethod
* method
,
5057 mach_port_t asyncWakePort
,
5058 io_user_reference_t
* asyncReference
,
5059 uint32_t asyncReferenceCount
,
5060 const io_user_scalar_t
* input
,
5061 mach_msg_type_number_t inputCount
,
5062 io_struct_inband_t inputStruct
,
5063 mach_msg_type_number_t inputStructCount
)
5067 IOReturn err
= kIOReturnBadArgument
;
5068 io_async_ref_t reference
;
5070 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5071 reference
[i
] = REF32(asyncReference
[i
]);
5075 if (inputCount
!= method
->count0
) {
5076 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5077 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5080 if ((kIOUCVariableStructureSize
!= method
->count1
)
5081 && (inputStructCount
!= method
->count1
)) {
5082 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
);
5083 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
5087 func
= method
->func
;
5089 switch (inputCount
) {
5091 err
= (object
->*func
)( reference
,
5092 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5093 ARG32(input
[3]), ARG32(input
[4]),
5097 err
= (object
->*func
)( reference
,
5098 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5100 inputStruct
, (void *)(uintptr_t)inputStructCount
);
5103 err
= (object
->*func
)( reference
,
5104 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5105 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5109 err
= (object
->*func
)( reference
,
5110 ARG32(input
[0]), ARG32(input
[1]),
5111 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5115 err
= (object
->*func
)( reference
,
5117 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5121 err
= (object
->*func
)( reference
,
5122 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5127 IOLog("%s: Bad method table\n", object
->getName());
5134 /* Routine io_connect_method_structureI_structureO */
5136 is_io_connect_method_structureI_structureO(
5137 io_object_t connect
,
5139 io_struct_inband_t input
,
5140 mach_msg_type_number_t inputCount
,
5141 io_struct_inband_t output
,
5142 mach_msg_type_number_t
* outputCount
)
5144 mach_msg_type_number_t scalar_outputCnt
= 0;
5145 mach_vm_size_t ool_output_size
= 0;
5147 return is_io_connect_method(connect
, index
,
5151 output
, outputCount
,
5152 NULL
, &scalar_outputCnt
,
5153 0, &ool_output_size
);
5157 shim_io_connect_method_structureI_structureO(
5158 IOExternalMethod
* method
,
5160 io_struct_inband_t input
,
5161 mach_msg_type_number_t inputCount
,
5162 io_struct_inband_t output
,
5163 IOByteCount
* outputCount
)
5166 IOReturn err
= kIOReturnBadArgument
;
5169 if ((kIOUCVariableStructureSize
!= method
->count0
)
5170 && (inputCount
!= method
->count0
)) {
5171 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
);
5172 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5175 if ((kIOUCVariableStructureSize
!= method
->count1
)
5176 && (*outputCount
!= method
->count1
)) {
5177 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
);
5178 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5182 func
= method
->func
;
5184 if (method
->count1
) {
5185 if (method
->count0
) {
5186 err
= (object
->*func
)( input
, output
,
5187 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
5189 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
5192 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
5201 shim_io_async_method_structureI_structureO(
5202 IOExternalAsyncMethod
* method
,
5204 mach_port_t asyncWakePort
,
5205 io_user_reference_t
* asyncReference
,
5206 uint32_t asyncReferenceCount
,
5207 io_struct_inband_t input
,
5208 mach_msg_type_number_t inputCount
,
5209 io_struct_inband_t output
,
5210 mach_msg_type_number_t
* outputCount
)
5215 io_async_ref_t reference
;
5217 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5218 reference
[i
] = REF32(asyncReference
[i
]);
5221 err
= kIOReturnBadArgument
;
5223 if ((kIOUCVariableStructureSize
!= method
->count0
)
5224 && (inputCount
!= method
->count0
)) {
5225 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
);
5226 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5229 if ((kIOUCVariableStructureSize
!= method
->count1
)
5230 && (*outputCount
!= method
->count1
)) {
5231 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
);
5232 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5236 func
= method
->func
;
5238 if (method
->count1
) {
5239 if (method
->count0
) {
5240 err
= (object
->*func
)( reference
,
5242 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
5244 err
= (object
->*func
)( reference
,
5245 output
, outputCount
, 0, 0, 0, 0 );
5248 err
= (object
->*func
)( reference
,
5249 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
5257 bool gIOKextdClearedBusy
= false;
5260 /* Routine io_catalog_send_data */
5262 is_io_catalog_send_data(
5263 mach_port_t master_port
,
5265 io_buf_ptr_t inData
,
5266 mach_msg_type_number_t inDataCount
,
5267 kern_return_t
* result
)
5270 return kIOReturnNotPrivileged
;
5271 #else /* NO_KEXTD */
5274 kern_return_t kr
= kIOReturnError
;
5276 //printf("io_catalog_send_data called. flag: %d\n", flag);
5278 if (master_port
!= master_device_port
) {
5279 return kIOReturnNotPrivileged
;
5282 if ((flag
!= kIOCatalogRemoveKernelLinker
&&
5283 flag
!= kIOCatalogKextdActive
&&
5284 flag
!= kIOCatalogKextdFinishedLaunching
) &&
5285 (!inData
|| !inDataCount
)) {
5286 return kIOReturnBadArgument
;
5289 if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-secure-management")) {
5290 OSString
* taskName
= IOCopyLogNameForPID(proc_selfpid());
5291 IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName
? taskName
->getCStringNoCopy() : "");
5292 OSSafeReleaseNULL(taskName
);
5293 // For now, fake success to not break applications relying on this function succeeding.
5294 // See <rdar://problem/32554970> for more details.
5295 return kIOReturnSuccess
;
5299 vm_map_offset_t map_data
;
5301 if (inDataCount
> sizeof(io_struct_inband_t
) * 1024) {
5302 return kIOReturnMessageTooLarge
;
5305 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
5306 data
= CAST_DOWN(vm_offset_t
, map_data
);
5308 if (kr
!= KERN_SUCCESS
) {
5312 // must return success after vm_map_copyout() succeeds
5315 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
5316 vm_deallocate( kernel_map
, data
, inDataCount
);
5318 *result
= kIOReturnNoMemory
;
5319 return KERN_SUCCESS
;
5325 case kIOCatalogResetDrivers
:
5326 case kIOCatalogResetDriversNoMatch
: {
5329 array
= OSDynamicCast(OSArray
, obj
);
5331 if (!gIOCatalogue
->resetAndAddDrivers(array
,
5332 flag
== kIOCatalogResetDrivers
)) {
5333 kr
= kIOReturnError
;
5336 kr
= kIOReturnBadArgument
;
5341 case kIOCatalogAddDrivers
:
5342 case kIOCatalogAddDriversNoMatch
: {
5345 array
= OSDynamicCast(OSArray
, obj
);
5347 if (!gIOCatalogue
->addDrivers( array
,
5348 flag
== kIOCatalogAddDrivers
)) {
5349 kr
= kIOReturnError
;
5352 kr
= kIOReturnBadArgument
;
5357 case kIOCatalogRemoveDrivers
:
5358 case kIOCatalogRemoveDriversNoMatch
: {
5359 OSDictionary
* dict
;
5361 dict
= OSDynamicCast(OSDictionary
, obj
);
5363 if (!gIOCatalogue
->removeDrivers( dict
,
5364 flag
== kIOCatalogRemoveDrivers
)) {
5365 kr
= kIOReturnError
;
5368 kr
= kIOReturnBadArgument
;
5373 case kIOCatalogStartMatching
: {
5374 OSDictionary
* dict
;
5376 dict
= OSDynamicCast(OSDictionary
, obj
);
5378 if (!gIOCatalogue
->startMatching( dict
)) {
5379 kr
= kIOReturnError
;
5382 kr
= kIOReturnBadArgument
;
5387 case kIOCatalogRemoveKernelLinker
:
5388 kr
= KERN_NOT_SUPPORTED
;
5391 case kIOCatalogKextdActive
:
5393 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
5394 OSKext::setKextdActive();
5396 /* Dump all nonloaded startup extensions; kextd will now send them
5399 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
5401 kr
= kIOReturnSuccess
;
5404 case kIOCatalogKextdFinishedLaunching
: {
5406 if (!gIOKextdClearedBusy
) {
5407 IOService
* serviceRoot
= IOService::getServiceRoot();
5409 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
5410 serviceRoot
->adjustBusy(-1);
5411 gIOKextdClearedBusy
= true;
5415 kr
= kIOReturnSuccess
;
5420 kr
= kIOReturnBadArgument
;
5429 return KERN_SUCCESS
;
5430 #endif /* NO_KEXTD */
5433 /* Routine io_catalog_terminate */
5435 is_io_catalog_terminate(
5436 mach_port_t master_port
,
5442 if (master_port
!= master_device_port
) {
5443 return kIOReturnNotPrivileged
;
5446 kr
= IOUserClient::clientHasPrivilege((void *) current_task(),
5447 kIOClientPrivilegeAdministrator
);
5448 if (kIOReturnSuccess
!= kr
) {
5453 #if !defined(SECURE_KERNEL)
5454 case kIOCatalogServiceTerminate
:
5456 IOService
* service
;
5458 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
5459 kIORegistryIterateRecursively
);
5461 return kIOReturnNoMemory
;
5466 while ((service
= (IOService
*)iter
->getNextObject())) {
5467 if (service
->metaCast(name
)) {
5468 if (!service
->terminate( kIOServiceRequired
5469 | kIOServiceSynchronous
)) {
5470 kr
= kIOReturnUnsupported
;
5475 } while (!service
&& !iter
->isValid());
5479 case kIOCatalogModuleUnload
:
5480 case kIOCatalogModuleTerminate
:
5481 kr
= gIOCatalogue
->terminateDriversForModule(name
,
5482 flag
== kIOCatalogModuleUnload
);
5487 kr
= kIOReturnBadArgument
;
5494 /* Routine io_catalog_get_data */
5496 is_io_catalog_get_data(
5497 mach_port_t master_port
,
5499 io_buf_ptr_t
*outData
,
5500 mach_msg_type_number_t
*outDataCount
)
5502 kern_return_t kr
= kIOReturnSuccess
;
5505 if (master_port
!= master_device_port
) {
5506 return kIOReturnNotPrivileged
;
5509 //printf("io_catalog_get_data called. flag: %d\n", flag);
5511 s
= OSSerialize::withCapacity(4096);
5513 return kIOReturnNoMemory
;
5516 kr
= gIOCatalogue
->serializeData(flag
, s
);
5518 if (kr
== kIOReturnSuccess
) {
5523 size
= s
->getLength();
5524 kr
= vm_allocate_kernel(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
);
5525 if (kr
== kIOReturnSuccess
) {
5526 bcopy(s
->text(), (void *)data
, size
);
5527 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
5528 (vm_map_size_t
)size
, true, ©
);
5529 *outData
= (char *)copy
;
5530 *outDataCount
= size
;
5539 /* Routine io_catalog_get_gen_count */
5541 is_io_catalog_get_gen_count(
5542 mach_port_t master_port
,
5545 if (master_port
!= master_device_port
) {
5546 return kIOReturnNotPrivileged
;
5549 //printf("io_catalog_get_gen_count called.\n");
5552 return kIOReturnBadArgument
;
5555 *genCount
= gIOCatalogue
->getGenerationCount();
5557 return kIOReturnSuccess
;
5560 /* Routine io_catalog_module_loaded.
5561 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
5564 is_io_catalog_module_loaded(
5565 mach_port_t master_port
,
5568 if (master_port
!= master_device_port
) {
5569 return kIOReturnNotPrivileged
;
5572 //printf("io_catalog_module_loaded called. name %s\n", name);
5575 return kIOReturnBadArgument
;
5578 gIOCatalogue
->moduleHasLoaded(name
);
5580 return kIOReturnSuccess
;
5584 is_io_catalog_reset(
5585 mach_port_t master_port
,
5588 if (master_port
!= master_device_port
) {
5589 return kIOReturnNotPrivileged
;
5593 case kIOCatalogResetDefault
:
5594 gIOCatalogue
->reset();
5598 return kIOReturnBadArgument
;
5601 return kIOReturnSuccess
;
5605 iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5607 kern_return_t result
= kIOReturnBadArgument
;
5608 IOUserClient
*userClient
;
5610 if ((userClient
= OSDynamicCast(IOUserClient
,
5611 iokit_lookup_connect_ref_current_task((mach_port_name_t
)(uintptr_t)args
->userClientRef
)))) {
5612 IOExternalTrap
*trap
;
5613 IOService
*target
= NULL
;
5615 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5617 if (trap
&& target
) {
5623 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5627 iokit_remove_connect_reference(userClient
);
5633 /* Routine io_device_tree_entry_exists_with_name */
5635 is_io_device_tree_entry_exists_with_name(
5636 mach_port_t master_port
,
5640 OSCollectionIterator
*iter
;
5642 if (master_port
!= master_device_port
) {
5643 return kIOReturnNotPrivileged
;
5646 iter
= IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive
, name
);
5647 *exists
= iter
&& iter
->getNextObject();
5648 OSSafeReleaseNULL(iter
);
5650 return kIOReturnSuccess
;
5655 IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5656 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5660 IOByteCount structureOutputSize
;
5664 count
= dispatch
->checkScalarInputCount
;
5665 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
)) {
5666 return kIOReturnBadArgument
;
5669 count
= dispatch
->checkStructureInputSize
;
5670 if ((kIOUCVariableStructureSize
!= count
)
5671 && (count
!= ((args
->structureInputDescriptor
)
5672 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
))) {
5673 return kIOReturnBadArgument
;
5676 count
= dispatch
->checkScalarOutputCount
;
5677 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
)) {
5678 return kIOReturnBadArgument
;
5681 count
= dispatch
->checkStructureOutputSize
;
5682 if ((kIOUCVariableStructureSize
!= count
)
5683 && (count
!= ((args
->structureOutputDescriptor
)
5684 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
))) {
5685 return kIOReturnBadArgument
;
5688 if (dispatch
->function
) {
5689 err
= (*dispatch
->function
)(target
, reference
, args
);
5691 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5697 // pre-Leopard API's don't do ool structs
5698 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
) {
5699 err
= kIOReturnIPCError
;
5703 structureOutputSize
= args
->structureOutputSize
;
5705 if (args
->asyncWakePort
) {
5706 IOExternalAsyncMethod
* method
;
5708 if (!(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
) {
5709 return kIOReturnUnsupported
;
5712 if (kIOUCForegroundOnly
& method
->flags
) {
5713 if (task_is_gpu_denied(current_task())) {
5714 return kIOReturnNotPermitted
;
5718 switch (method
->flags
& kIOUCTypeMask
) {
5719 case kIOUCScalarIStructI
:
5720 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5721 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5722 args
->scalarInput
, args
->scalarInputCount
,
5723 (char *)args
->structureInput
, args
->structureInputSize
);
5726 case kIOUCScalarIScalarO
:
5727 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5728 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5729 args
->scalarInput
, args
->scalarInputCount
,
5730 args
->scalarOutput
, &args
->scalarOutputCount
);
5733 case kIOUCScalarIStructO
:
5734 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5735 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5736 args
->scalarInput
, args
->scalarInputCount
,
5737 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5741 case kIOUCStructIStructO
:
5742 err
= shim_io_async_method_structureI_structureO( method
, object
,
5743 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5744 (char *)args
->structureInput
, args
->structureInputSize
,
5745 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5749 err
= kIOReturnBadArgument
;
5753 IOExternalMethod
* method
;
5755 if (!(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
) {
5756 return kIOReturnUnsupported
;
5759 if (kIOUCForegroundOnly
& method
->flags
) {
5760 if (task_is_gpu_denied(current_task())) {
5761 return kIOReturnNotPermitted
;
5765 switch (method
->flags
& kIOUCTypeMask
) {
5766 case kIOUCScalarIStructI
:
5767 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5768 args
->scalarInput
, args
->scalarInputCount
,
5769 (char *) args
->structureInput
, args
->structureInputSize
);
5772 case kIOUCScalarIScalarO
:
5773 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5774 args
->scalarInput
, args
->scalarInputCount
,
5775 args
->scalarOutput
, &args
->scalarOutputCount
);
5778 case kIOUCScalarIStructO
:
5779 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5780 args
->scalarInput
, args
->scalarInputCount
,
5781 (char *) args
->structureOutput
, &structureOutputSize
);
5785 case kIOUCStructIStructO
:
5786 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5787 (char *) args
->structureInput
, args
->structureInputSize
,
5788 (char *) args
->structureOutput
, &structureOutputSize
);
5792 err
= kIOReturnBadArgument
;
5797 args
->structureOutputSize
= structureOutputSize
;
5803 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5804 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5806 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5807 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5809 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5810 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5811 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5812 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5813 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5814 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5815 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5816 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5817 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5818 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5819 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5820 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5821 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5822 OSMetaClassDefineReservedUnused(IOUserClient
, 15);