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/IOStatisticsPrivate.h>
41 #include <IOKit/IOTimeStamp.h>
42 #include <IOKit/system.h>
43 #include <libkern/OSDebug.h>
45 #include <sys/kauth.h>
46 #include <sys/codesign.h>
51 #include <security/mac_framework.h>
53 #include <sys/kauth.h>
57 #endif /* CONFIG_MACF */
59 #include <IOKit/assert.h>
61 #include "IOServicePrivate.h"
62 #include "IOKitKernelInternal.h"
64 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
65 #define SCALAR32(x) ((uint32_t )x)
66 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
67 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
68 #define REF32(x) ((int)(x))
72 kIOUCAsync0Flags
= 3ULL,
73 kIOUCAsync64Flag
= 1ULL
78 #define IOStatisticsRegisterCounter() \
80 reserved->counter = IOStatistics::registerUserClient(this); \
83 #define IOStatisticsUnregisterCounter() \
86 IOStatistics::unregisterUserClient(reserved->counter); \
89 #define IOStatisticsClientCall() \
91 IOStatistics::countUserClientCall(client); \
96 #define IOStatisticsRegisterCounter()
97 #define IOStatisticsUnregisterCounter()
98 #define IOStatisticsClientCall()
100 #endif /* IOKITSTATS */
102 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 // definitions we should get from osfmk
106 //typedef struct ipc_port * ipc_port_t;
107 typedef natural_t ipc_kobject_type_t
;
109 #define IKOT_IOKIT_SPARE 27
110 #define IKOT_IOKIT_CONNECT 29
111 #define IKOT_IOKIT_OBJECT 30
115 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
116 ipc_kobject_type_t type
);
118 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
120 extern mach_port_name_t
iokit_make_send_right( task_t task
,
121 io_object_t obj
, ipc_kobject_type_t type
);
123 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
125 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
127 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
129 extern ipc_port_t master_device_port
;
131 extern void iokit_retain_port( ipc_port_t port
);
132 extern void iokit_release_port( ipc_port_t port
);
133 extern void iokit_release_port_send( ipc_port_t port
);
135 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
137 #include <mach/mach_traps.h>
138 #include <vm/vm_map.h>
143 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
145 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
147 class IOMachPort
: public OSObject
149 OSDeclareDefaultStructors(IOMachPort
)
156 static IOMachPort
* portForObject( OSObject
* obj
,
157 ipc_kobject_type_t type
);
158 static bool noMoreSendersForObject( OSObject
* obj
,
159 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
160 static void releasePortForObject( OSObject
* obj
,
161 ipc_kobject_type_t type
);
162 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
164 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
166 static mach_port_name_t
makeSendRightForTask( task_t task
,
167 io_object_t obj
, ipc_kobject_type_t type
);
169 virtual void free() APPLE_KEXT_OVERRIDE
;
172 #define super OSObject
173 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
175 static IOLock
* gIOObjectPortLock
;
177 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
179 // not in dictForType() for debugging ease
180 static OSDictionary
* gIOObjectPorts
;
181 static OSDictionary
* gIOConnectPorts
;
183 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
185 OSDictionary
** dict
;
187 if( IKOT_IOKIT_OBJECT
== type
)
188 dict
= &gIOObjectPorts
;
189 else if( IKOT_IOKIT_CONNECT
== type
)
190 dict
= &gIOConnectPorts
;
195 *dict
= OSDictionary::withCapacity( 1 );
200 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
201 ipc_kobject_type_t type
)
203 IOMachPort
* inst
= 0;
206 IOTakeLock( gIOObjectPortLock
);
210 dict
= dictForType( type
);
214 if( (inst
= (IOMachPort
*)
215 dict
->getObject( (const OSSymbol
*) obj
))) {
221 inst
= new IOMachPort
;
222 if( inst
&& !inst
->init()) {
227 inst
->port
= iokit_alloc_object_port( obj
, type
);
230 dict
->setObject( (const OSSymbol
*) obj
, inst
);
240 IOUnlock( gIOObjectPortLock
);
245 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
246 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
249 IOMachPort
* machPort
;
251 bool destroyed
= true;
253 IOTakeLock( gIOObjectPortLock
);
255 if( (dict
= dictForType( type
))) {
258 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
260 destroyed
= (machPort
->mscount
<= *mscount
);
261 if (!destroyed
) *mscount
= machPort
->mscount
;
264 if ((IKOT_IOKIT_CONNECT
== type
) && (uc
= OSDynamicCast(IOUserClient
, obj
)))
268 dict
->removeObject( (const OSSymbol
*) obj
);
274 IOUnlock( gIOObjectPortLock
);
279 void IOMachPort::releasePortForObject( OSObject
* obj
,
280 ipc_kobject_type_t type
)
283 IOMachPort
* machPort
;
285 assert(IKOT_IOKIT_CONNECT
!= type
);
287 IOTakeLock( gIOObjectPortLock
);
289 if( (dict
= dictForType( type
))) {
291 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
292 if( machPort
&& !machPort
->holdDestroy
)
293 dict
->removeObject( (const OSSymbol
*) obj
);
297 IOUnlock( gIOObjectPortLock
);
300 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
303 IOMachPort
* machPort
;
305 IOLockLock( gIOObjectPortLock
);
307 if( (dict
= dictForType( type
))) {
308 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
310 machPort
->holdDestroy
= true;
313 IOLockUnlock( gIOObjectPortLock
);
316 void IOUserClient::destroyUserReferences( OSObject
* obj
)
318 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
321 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
325 IOTakeLock( gIOObjectPortLock
);
328 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
331 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
335 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
340 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
341 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
343 uc
->mappings
->release();
347 dict
->removeObject( (const OSSymbol
*) obj
);
351 IOUnlock( gIOObjectPortLock
);
354 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
355 io_object_t obj
, ipc_kobject_type_t type
)
357 return( iokit_make_send_right( task
, obj
, type
));
360 void IOMachPort::free( void )
363 iokit_destroy_object_port( port
);
367 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
369 class IOUserIterator
: public OSIterator
371 OSDeclareDefaultStructors(IOUserIterator
)
373 OSObject
* userIteratorObject
;
376 static IOUserIterator
* withIterator(OSIterator
* iter
);
377 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
378 virtual void free() APPLE_KEXT_OVERRIDE
;
380 virtual void reset() APPLE_KEXT_OVERRIDE
;
381 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
382 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
385 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
387 class IOUserNotification
: public IOUserIterator
389 OSDeclareDefaultStructors(IOUserNotification
)
391 #define holdNotify userIteratorObject
395 virtual void free() APPLE_KEXT_OVERRIDE
;
397 virtual void setNotification( IONotifier
* obj
);
399 virtual void reset() APPLE_KEXT_OVERRIDE
;
400 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
403 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
405 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
408 IOUserIterator::withIterator(OSIterator
* iter
)
412 if (!iter
) return (0);
414 me
= new IOUserIterator
;
415 if (me
&& !me
->init())
421 me
->userIteratorObject
= iter
;
427 IOUserIterator::init( void )
429 if (!OSObject::init()) return (false);
431 lock
= IOLockAlloc();
439 IOUserIterator::free()
441 if (userIteratorObject
) userIteratorObject
->release();
442 if (lock
) IOLockFree(lock
);
447 IOUserIterator::reset()
450 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
451 ((OSIterator
*)userIteratorObject
)->reset();
456 IOUserIterator::isValid()
461 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
462 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
469 IOUserIterator::getNextObject()
474 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
475 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
481 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
484 // functions called from osfmk/device/iokit_rpc.c
487 iokit_add_reference( io_object_t obj
)
494 iokit_remove_reference( io_object_t obj
)
501 iokit_add_connect_reference( io_object_t obj
)
507 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) OSIncrementAtomic(&uc
->__ipc
);
513 iokit_remove_connect_reference( io_object_t obj
)
516 bool finalize
= false;
520 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
522 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive())
524 IOLockLock(gIOObjectPortLock
);
525 if ((finalize
= uc
->__ipcFinal
)) uc
->__ipcFinal
= false;
526 IOLockUnlock(gIOObjectPortLock
);
528 if (finalize
) uc
->scheduleFinalize(true);
535 IOUserClient::finalizeUserReferences(OSObject
* obj
)
540 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
542 IOLockLock(gIOObjectPortLock
);
543 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) ok
= false;
544 IOLockUnlock(gIOObjectPortLock
);
550 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
552 IOMachPort
* machPort
;
555 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
557 port
= machPort
->port
;
559 iokit_retain_port( port
);
570 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
571 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
573 IOUserClient
* client
;
575 IOUserNotification
* notify
;
577 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
578 return( kIOReturnNotReady
);
580 if( IKOT_IOKIT_CONNECT
== type
)
582 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
584 IOStatisticsClientCall();
585 client
->clientDied();
588 else if( IKOT_IOKIT_OBJECT
== type
)
590 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
592 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
593 notify
->setNotification( 0 );
596 return( kIOReturnSuccess
);
601 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
603 class IOServiceUserNotification
: public IOUserNotification
605 OSDeclareDefaultStructors(IOServiceUserNotification
)
608 mach_msg_header_t msgHdr
;
609 OSNotificationHeader64 notifyHeader
;
612 enum { kMaxOutstanding
= 1024 };
617 OSObject
* lastEntry
;
622 virtual bool init( mach_port_t port
, natural_t type
,
623 void * reference
, vm_size_t referenceSize
,
625 virtual void free() APPLE_KEXT_OVERRIDE
;
627 static bool _handler( void * target
,
628 void * ref
, IOService
* newService
, IONotifier
* notifier
);
629 virtual bool handler( void * ref
, IOService
* newService
);
631 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
634 class IOServiceMessageUserNotification
: public IOUserNotification
636 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
639 mach_msg_header_t msgHdr
;
640 mach_msg_body_t msgBody
;
641 mach_msg_port_descriptor_t ports
[1];
642 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
652 virtual bool init( mach_port_t port
, natural_t type
,
653 void * reference
, vm_size_t referenceSize
,
657 virtual void free() APPLE_KEXT_OVERRIDE
;
659 static IOReturn
_handler( void * target
, void * ref
,
660 UInt32 messageType
, IOService
* provider
,
661 void * messageArgument
, vm_size_t argSize
);
662 virtual IOReturn
handler( void * ref
,
663 UInt32 messageType
, IOService
* provider
,
664 void * messageArgument
, vm_size_t argSize
);
666 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
669 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
672 #define super IOUserIterator
673 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
674 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
676 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
678 void IOUserNotification::free( void )
682 assert(OSDynamicCast(IONotifier
, holdNotify
));
683 ((IONotifier
*)holdNotify
)->remove();
686 // can't be in handler now
692 void IOUserNotification::setNotification( IONotifier
* notify
)
694 OSObject
* previousNotify
;
696 IOLockLock( gIOObjectPortLock
);
698 previousNotify
= holdNotify
;
701 IOLockUnlock( gIOObjectPortLock
);
705 assert(OSDynamicCast(IONotifier
, previousNotify
));
706 ((IONotifier
*)previousNotify
)->remove();
710 void IOUserNotification::reset()
715 bool IOUserNotification::isValid()
720 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
723 #define super IOUserNotification
724 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
726 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
728 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
729 void * reference
, vm_size_t referenceSize
,
735 newSet
= OSArray::withCapacity( 1 );
739 if (referenceSize
> sizeof(OSAsyncReference64
))
742 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
743 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
747 bzero( pingMsg
, msgSize
);
749 pingMsg
->msgHdr
.msgh_remote_port
= port
;
750 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
751 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
752 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
753 pingMsg
->msgHdr
.msgh_size
= msgSize
;
754 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
756 pingMsg
->notifyHeader
.size
= 0;
757 pingMsg
->notifyHeader
.type
= type
;
758 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
763 void IOServiceUserNotification::free( void )
768 OSObject
* _lastEntry
;
772 _lastEntry
= lastEntry
;
777 if( _pingMsg
&& _msgSize
) {
778 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
779 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
781 IOFree(_pingMsg
, _msgSize
);
785 _lastEntry
->release();
791 bool IOServiceUserNotification::_handler( void * target
,
792 void * ref
, IOService
* newService
, IONotifier
* notifier
)
794 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
797 bool IOServiceUserNotification::handler( void * ref
,
798 IOService
* newService
)
802 ipc_port_t port
= NULL
;
803 bool sendPing
= false;
807 count
= newSet
->getCount();
808 if( count
< kMaxOutstanding
) {
810 newSet
->setObject( newService
);
811 if( (sendPing
= (armed
&& (0 == count
))))
817 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
818 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
821 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
822 pingMsg
->msgHdr
.msgh_local_port
= port
;
824 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
826 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
827 pingMsg
->msgHdr
.msgh_size
,
828 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
831 iokit_release_port( port
);
833 if( KERN_SUCCESS
!= kr
)
834 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
840 OSObject
* IOServiceUserNotification::getNextObject()
848 lastEntry
->release();
850 count
= newSet
->getCount();
852 result
= newSet
->getObject( count
- 1 );
854 newSet
->removeObject( count
- 1);
866 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
868 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
870 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
872 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
873 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
879 if (referenceSize
> sizeof(OSAsyncReference64
))
882 clientIs64
= client64
;
884 owningPID
= proc_selfpid();
886 extraSize
+= sizeof(IOServiceInterestContent64
);
887 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
+ extraSize
;
888 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
892 bzero( pingMsg
, msgSize
);
894 pingMsg
->msgHdr
.msgh_remote_port
= port
;
895 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
897 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
898 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
899 pingMsg
->msgHdr
.msgh_size
= msgSize
;
900 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
902 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
904 pingMsg
->ports
[0].name
= 0;
905 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
906 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
908 pingMsg
->notifyHeader
.size
= extraSize
;
909 pingMsg
->notifyHeader
.type
= type
;
910 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
915 void IOServiceMessageUserNotification::free( void )
925 if( _pingMsg
&& _msgSize
) {
926 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
927 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
929 IOFree( _pingMsg
, _msgSize
);
933 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
934 UInt32 messageType
, IOService
* provider
,
935 void * argument
, vm_size_t argSize
)
937 return( ((IOServiceMessageUserNotification
*) target
)->handler(
938 ref
, messageType
, provider
, argument
, argSize
));
941 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
942 UInt32 messageType
, IOService
* provider
,
943 void * messageArgument
, vm_size_t argSize
)
946 ipc_port_t thisPort
, providerPort
;
947 IOServiceInterestContent64
* data
= (IOServiceInterestContent64
*)
948 ((((uint8_t *) pingMsg
) + msgSize
) - pingMsg
->notifyHeader
.size
);
949 // == pingMsg->notifyHeader.content;
951 if (kIOMessageCopyClientID
== messageType
)
953 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
954 return (kIOReturnSuccess
);
957 data
->messageType
= messageType
;
961 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
963 argSize
= sizeof(data
->messageArgument
[0]);
966 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
967 argSize
= sizeof(uint32_t);
972 if( argSize
> kIOUserNotifyMaxMessageSize
)
973 argSize
= kIOUserNotifyMaxMessageSize
;
974 bcopy( messageArgument
, data
->messageArgument
, argSize
);
977 // adjust message size for ipc restrictions
979 type
= pingMsg
->notifyHeader
.type
;
980 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
981 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
982 pingMsg
->notifyHeader
.type
= type
;
983 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
985 pingMsg
->msgHdr
.msgh_size
= msgSize
- pingMsg
->notifyHeader
.size
986 + sizeof( IOServiceInterestContent64
)
987 - sizeof( data
->messageArgument
)
990 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
991 pingMsg
->ports
[0].name
= providerPort
;
992 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
993 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
994 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
995 pingMsg
->msgHdr
.msgh_size
,
996 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
999 iokit_release_port( thisPort
);
1001 iokit_release_port( providerPort
);
1003 if( KERN_SUCCESS
!= kr
)
1004 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1006 return( kIOReturnSuccess
);
1009 OSObject
* IOServiceMessageUserNotification::getNextObject()
1014 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1017 #define super IOService
1018 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1020 IOLock
* gIOUserClientOwnersLock
;
1022 void IOUserClient::initialize( void )
1024 gIOObjectPortLock
= IOLockAlloc();
1025 gIOUserClientOwnersLock
= IOLockAlloc();
1026 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1029 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1030 mach_port_t wakePort
,
1031 void *callback
, void *refcon
)
1033 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1034 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1035 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1036 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1039 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1040 mach_port_t wakePort
,
1041 mach_vm_address_t callback
, io_user_reference_t refcon
)
1043 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1044 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1045 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1046 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1049 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1050 mach_port_t wakePort
,
1051 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1053 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1054 if (vm_map_is_64bit(get_task_map(task
))) {
1055 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1059 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
1062 OSDictionary
* user
= 0;
1064 if ((array
= OSDynamicCast(OSArray
,
1065 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1067 for (unsigned int idx
= 0;
1068 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1072 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1073 && (uid
== num
->unsigned32BitValue())) {
1083 static OSDictionary
* CopyUserOnConsole(void)
1086 OSDictionary
* user
= 0;
1088 if ((array
= OSDynamicCast(OSArray
,
1089 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1091 for (unsigned int idx
= 0;
1092 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1095 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
1106 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
1107 IOService
* service
)
1111 p
= (proc_t
) get_bsdtask_info(task
);
1114 uint64_t authorizationID
;
1116 authorizationID
= proc_uniqueid(p
);
1117 if (authorizationID
)
1119 if (service
->getAuthorizationID() == authorizationID
)
1121 return (kIOReturnSuccess
);
1126 return (kIOReturnNotPermitted
);
1129 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
1130 const char * privilegeName
)
1133 security_token_t token
;
1134 mach_msg_type_number_t count
;
1136 OSDictionary
* user
;
1140 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1141 sizeof(kIOClientPrivilegeForeground
)))
1143 if (task_is_gpu_denied(current_task()))
1144 return (kIOReturnNotPrivileged
);
1146 return (kIOReturnSuccess
);
1149 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1150 sizeof(kIOClientPrivilegeConsoleSession
)))
1155 task
= (task_t
) securityToken
;
1157 task
= current_task();
1158 p
= (proc_t
) get_bsdtask_info(task
);
1159 kr
= kIOReturnNotPrivileged
;
1161 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1163 user
= CopyUserOnConsole();
1167 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1168 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1170 kr
= kIOReturnSuccess
;
1174 kauth_cred_unref(&cred
);
1179 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1180 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1181 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1183 task
= (task_t
)securityToken
;
1185 count
= TASK_SECURITY_TOKEN_COUNT
;
1186 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1188 if (KERN_SUCCESS
!= kr
)
1190 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1191 sizeof(kIOClientPrivilegeAdministrator
))) {
1192 if (0 != token
.val
[0])
1193 kr
= kIOReturnNotPrivileged
;
1194 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1195 sizeof(kIOClientPrivilegeLocalUser
))) {
1196 user
= CopyConsoleUser(token
.val
[0]);
1200 kr
= kIOReturnNotPrivileged
;
1201 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1202 sizeof(kIOClientPrivilegeConsoleUser
))) {
1203 user
= CopyConsoleUser(token
.val
[0]);
1205 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1206 kr
= kIOReturnNotPrivileged
;
1207 else if ( secureConsole
) {
1208 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1209 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1210 kr
= kIOReturnNotPrivileged
;
1215 kr
= kIOReturnNotPrivileged
;
1217 kr
= kIOReturnUnsupported
;
1222 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1223 const char * entitlement
)
1225 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1229 char procname
[MAXCOMLEN
+ 1] = "";
1231 void *entitlements_blob
= NULL
;
1232 char *entitlements_data
= NULL
;
1233 OSObject
*entitlements_obj
= NULL
;
1234 OSDictionary
*entitlements
= NULL
;
1235 OSString
*errorString
= NULL
;
1236 OSObject
*value
= NULL
;
1238 p
= (proc_t
)get_bsdtask_info(task
);
1242 proc_name(pid
, procname
, (int)sizeof(procname
));
1244 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1247 if (len
<= offsetof(CS_GenericBlob
, data
))
1251 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1252 * we'll try to parse in the kernel.
1254 len
-= offsetof(CS_GenericBlob
, data
);
1255 if (len
> MAX_ENTITLEMENTS_LEN
) {
1256 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1261 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1262 * what is stored in the entitlements blob. Copy the string and
1265 entitlements_data
= (char *)IOMalloc(len
+ 1);
1266 if (entitlements_data
== NULL
)
1268 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1269 entitlements_data
[len
] = '\0';
1271 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1272 if (errorString
!= NULL
) {
1273 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1276 if (entitlements_obj
== NULL
)
1279 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1280 if (entitlements
== NULL
)
1283 /* Fetch the entitlement value from the dictionary. */
1284 value
= entitlements
->getObject(entitlement
);
1289 if (entitlements_data
!= NULL
)
1290 IOFree(entitlements_data
, len
+ 1);
1291 if (entitlements_obj
!= NULL
)
1292 entitlements_obj
->release();
1293 if (errorString
!= NULL
)
1294 errorString
->release();
1298 bool IOUserClient::init()
1300 if (getPropertyTable() || super::init())
1306 bool IOUserClient::init(OSDictionary
* dictionary
)
1308 if (getPropertyTable() || super::init(dictionary
))
1314 bool IOUserClient::initWithTask(task_t owningTask
,
1318 if (getPropertyTable() || super::init())
1324 bool IOUserClient::initWithTask(task_t owningTask
,
1327 OSDictionary
* properties
)
1331 ok
= super::init( properties
);
1332 ok
&= initWithTask( owningTask
, securityID
, type
);
1337 bool IOUserClient::reserve()
1340 reserved
= IONew(ExpansionData
, 1);
1345 setTerminateDefer(NULL
, true);
1346 IOStatisticsRegisterCounter();
1351 struct IOUserClientOwner
1354 queue_chain_t taskLink
;
1356 queue_chain_t ucLink
;
1360 IOUserClient::registerOwner(task_t task
)
1362 IOUserClientOwner
* owner
;
1366 IOLockLock(gIOUserClientOwnersLock
);
1369 ret
= kIOReturnSuccess
;
1371 if (!owners
.next
) queue_init(&owners
);
1374 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1376 if (task
!= owner
->task
) continue;
1383 owner
= IONew(IOUserClientOwner
, 1);
1384 if (!newOwner
) ret
= kIOReturnNoMemory
;
1389 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1390 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1394 IOLockUnlock(gIOUserClientOwnersLock
);
1400 IOUserClient::noMoreSenders(void)
1402 IOUserClientOwner
* owner
;
1404 IOLockLock(gIOUserClientOwnersLock
);
1408 while (!queue_empty(&owners
))
1410 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1411 queue_remove(task_io_user_clients(owner
->task
), owner
, IOUserClientOwner
*, taskLink
);
1412 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1413 IODelete(owner
, IOUserClientOwner
, 1);
1415 owners
.next
= owners
.prev
= NULL
;
1418 IOLockUnlock(gIOUserClientOwnersLock
);
1421 extern "C" kern_return_t
1422 iokit_task_terminate(task_t task
)
1424 IOUserClientOwner
* owner
;
1425 IOUserClient
* dead
;
1427 queue_head_t
* taskque
;
1429 IOLockLock(gIOUserClientOwnersLock
);
1431 taskque
= task_io_user_clients(task
);
1433 while (!queue_empty(taskque
))
1435 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1437 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1438 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1439 if (queue_empty(&uc
->owners
))
1442 IOLog("destroying out of band connect for %s\n", uc
->getName());
1443 // now using the uc queue head as a singly linked queue,
1444 // leaving .next as NULL to mark it empty
1445 uc
->owners
.next
= NULL
;
1446 uc
->owners
.prev
= (queue_entry_t
) dead
;
1449 IODelete(owner
, IOUserClientOwner
, 1);
1452 IOLockUnlock(gIOUserClientOwnersLock
);
1457 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1458 uc
->owners
.prev
= NULL
;
1459 if (uc
->sharedInstance
|| !uc
->closed
) uc
->clientDied();
1463 return (KERN_SUCCESS
);
1466 void IOUserClient::free()
1468 if( mappings
) mappings
->release();
1470 IOStatisticsUnregisterCounter();
1472 assert(!owners
.next
);
1473 assert(!owners
.prev
);
1475 if (reserved
) IODelete(reserved
, ExpansionData
, 1);
1480 IOReturn
IOUserClient::clientDied( void )
1482 IOReturn ret
= kIOReturnNotReady
;
1484 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
))
1486 ret
= clientClose();
1492 IOReturn
IOUserClient::clientClose( void )
1494 return( kIOReturnUnsupported
);
1497 IOService
* IOUserClient::getService( void )
1502 IOReturn
IOUserClient::registerNotificationPort(
1503 mach_port_t
/* port */,
1505 UInt32
/* refCon */)
1507 return( kIOReturnUnsupported
);
1510 IOReturn
IOUserClient::registerNotificationPort(
1513 io_user_reference_t refCon
)
1515 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1518 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1519 semaphore_t
* semaphore
)
1521 return( kIOReturnUnsupported
);
1524 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1526 return( kIOReturnUnsupported
);
1529 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1530 IOOptionBits
* options
,
1531 IOMemoryDescriptor
** memory
)
1533 return( kIOReturnUnsupported
);
1537 IOMemoryMap
* IOUserClient::mapClientMemory(
1540 IOOptionBits mapFlags
,
1541 IOVirtualAddress atAddress
)
1547 IOMemoryMap
* IOUserClient::mapClientMemory64(
1550 IOOptionBits mapFlags
,
1551 mach_vm_address_t atAddress
)
1554 IOOptionBits options
= 0;
1555 IOMemoryDescriptor
* memory
;
1556 IOMemoryMap
* map
= 0;
1558 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1560 if( memory
&& (kIOReturnSuccess
== err
)) {
1562 options
= (options
& ~kIOMapUserOptionsMask
)
1563 | (mapFlags
& kIOMapUserOptionsMask
);
1564 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1571 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1572 OSObject
*obj
, io_object_t
*clientObj
)
1574 mach_port_name_t name
;
1576 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1578 *(mach_port_name_t
*)clientObj
= name
;
1579 return kIOReturnSuccess
;
1582 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1587 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1592 IOExternalMethod
* IOUserClient::
1593 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1595 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1598 *targetP
= (IOService
*) method
->object
;
1603 IOExternalAsyncMethod
* IOUserClient::
1604 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1606 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1609 *targetP
= (IOService
*) method
->object
;
1614 IOExternalTrap
* IOUserClient::
1615 getExternalTrapForIndex(UInt32 index
)
1620 IOExternalTrap
* IOUserClient::
1621 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1623 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1626 *targetP
= trap
->object
;
1632 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1635 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1637 if (MACH_PORT_NULL
!= port
)
1638 iokit_release_port_send(port
);
1640 return (kIOReturnSuccess
);
1643 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1645 if (MACH_PORT_NULL
!= port
)
1646 iokit_release_port_send(port
);
1648 return (kIOReturnSuccess
);
1651 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1652 IOReturn result
, void *args
[], UInt32 numArgs
)
1654 OSAsyncReference64 reference64
;
1655 io_user_reference_t args64
[kMaxAsyncArgs
];
1658 if (numArgs
> kMaxAsyncArgs
)
1659 return kIOReturnMessageTooLarge
;
1661 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1662 reference64
[idx
] = REF64(reference
[idx
]);
1664 for (idx
= 0; idx
< numArgs
; idx
++)
1665 args64
[idx
] = REF64(args
[idx
]);
1667 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1670 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1671 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1673 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1676 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1677 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1679 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1682 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1683 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1687 mach_msg_header_t msgHdr
;
1692 OSNotificationHeader notifyHdr
;
1693 IOAsyncCompletionContent asyncContent
;
1694 uint32_t args
[kMaxAsyncArgs
];
1698 OSNotificationHeader64 notifyHdr
;
1699 IOAsyncCompletionContent asyncContent
;
1700 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1705 mach_port_t replyPort
;
1708 // If no reply port, do nothing.
1709 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1710 if (replyPort
== MACH_PORT_NULL
)
1711 return kIOReturnSuccess
;
1713 if (numArgs
> kMaxAsyncArgs
)
1714 return kIOReturnMessageTooLarge
;
1716 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1718 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1719 replyMsg
.msgHdr
.msgh_local_port
= 0;
1720 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1721 if (kIOUCAsync64Flag
& reference
[0])
1723 replyMsg
.msgHdr
.msgh_size
=
1724 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1725 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1726 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1727 + numArgs
* sizeof(io_user_reference_t
);
1728 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1729 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1731 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1733 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1739 replyMsg
.msgHdr
.msgh_size
=
1740 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1741 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1743 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1744 + numArgs
* sizeof(uint32_t);
1745 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1747 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1748 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1750 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1752 for (idx
= 0; idx
< numArgs
; idx
++)
1753 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1756 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1757 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1758 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1760 /* Fail on full queue. */
1761 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1762 replyMsg
.msgHdr
.msgh_size
);
1764 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
))
1765 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1770 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1774 #define CHECK(cls,obj,out) \
1776 if( !(out = OSDynamicCast( cls, obj))) \
1777 return( kIOReturnBadArgument )
1779 #define CHECKLOCKED(cls,obj,out) \
1780 IOUserIterator * oIter; \
1782 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1783 return (kIOReturnBadArgument); \
1784 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
1785 return (kIOReturnBadArgument)
1787 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1789 // Create a vm_map_copy_t or kalloc'ed data for memory
1790 // to be copied out. ipc will free after the copyout.
1792 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1793 io_buf_ptr_t
* buf
)
1798 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1799 false /* src_destroy */, ©
);
1801 assert( err
== KERN_SUCCESS
);
1802 if( err
== KERN_SUCCESS
)
1803 *buf
= (char *) copy
;
1808 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1810 /* Routine io_server_version */
1811 kern_return_t
is_io_server_version(
1812 mach_port_t master_port
,
1815 *version
= IOKIT_SERVER_VERSION
;
1816 return (kIOReturnSuccess
);
1819 /* Routine io_object_get_class */
1820 kern_return_t
is_io_object_get_class(
1822 io_name_t className
)
1824 const OSMetaClass
* my_obj
= NULL
;
1827 return( kIOReturnBadArgument
);
1829 my_obj
= object
->getMetaClass();
1831 return (kIOReturnNotFound
);
1834 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1836 return( kIOReturnSuccess
);
1839 /* Routine io_object_get_superclass */
1840 kern_return_t
is_io_object_get_superclass(
1841 mach_port_t master_port
,
1843 io_name_t class_name
)
1845 const OSMetaClass
* my_obj
= NULL
;
1846 const OSMetaClass
* superclass
= NULL
;
1847 const OSSymbol
*my_name
= NULL
;
1848 const char *my_cstr
= NULL
;
1850 if (!obj_name
|| !class_name
)
1851 return (kIOReturnBadArgument
);
1853 if( master_port
!= master_device_port
)
1854 return( kIOReturnNotPrivileged
);
1856 my_name
= OSSymbol::withCString(obj_name
);
1859 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1863 superclass
= my_obj
->getSuperClass();
1867 return( kIOReturnNotFound
);
1870 my_cstr
= superclass
->getClassName();
1873 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1874 return( kIOReturnSuccess
);
1876 return (kIOReturnNotFound
);
1879 /* Routine io_object_get_bundle_identifier */
1880 kern_return_t
is_io_object_get_bundle_identifier(
1881 mach_port_t master_port
,
1883 io_name_t bundle_name
)
1885 const OSMetaClass
* my_obj
= NULL
;
1886 const OSSymbol
*my_name
= NULL
;
1887 const OSSymbol
*identifier
= NULL
;
1888 const char *my_cstr
= NULL
;
1890 if (!obj_name
|| !bundle_name
)
1891 return (kIOReturnBadArgument
);
1893 if( master_port
!= master_device_port
)
1894 return( kIOReturnNotPrivileged
);
1896 my_name
= OSSymbol::withCString(obj_name
);
1899 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1904 identifier
= my_obj
->getKmodName();
1907 return( kIOReturnNotFound
);
1910 my_cstr
= identifier
->getCStringNoCopy();
1912 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1913 return( kIOReturnSuccess
);
1916 return (kIOReturnBadArgument
);
1919 /* Routine io_object_conforms_to */
1920 kern_return_t
is_io_object_conforms_to(
1922 io_name_t className
,
1923 boolean_t
*conforms
)
1926 return( kIOReturnBadArgument
);
1928 *conforms
= (0 != object
->metaCast( className
));
1930 return( kIOReturnSuccess
);
1933 /* Routine io_object_get_retain_count */
1934 kern_return_t
is_io_object_get_retain_count(
1936 uint32_t *retainCount
)
1939 return( kIOReturnBadArgument
);
1941 *retainCount
= object
->getRetainCount();
1942 return( kIOReturnSuccess
);
1945 /* Routine io_iterator_next */
1946 kern_return_t
is_io_iterator_next(
1947 io_object_t iterator
,
1948 io_object_t
*object
)
1953 CHECK( OSIterator
, iterator
, iter
);
1955 obj
= iter
->getNextObject();
1959 ret
= kIOReturnSuccess
;
1961 ret
= kIOReturnNoDevice
;
1966 /* Routine io_iterator_reset */
1967 kern_return_t
is_io_iterator_reset(
1968 io_object_t iterator
)
1970 CHECK( OSIterator
, iterator
, iter
);
1974 return( kIOReturnSuccess
);
1977 /* Routine io_iterator_is_valid */
1978 kern_return_t
is_io_iterator_is_valid(
1979 io_object_t iterator
,
1980 boolean_t
*is_valid
)
1982 CHECK( OSIterator
, iterator
, iter
);
1984 *is_valid
= iter
->isValid();
1986 return( kIOReturnSuccess
);
1990 static kern_return_t
internal_io_service_match_property_table(
1991 io_service_t _service
,
1992 const char * matching
,
1993 mach_msg_type_number_t matching_size
,
1996 CHECK( IOService
, _service
, service
);
2000 OSDictionary
* dict
;
2002 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
2003 : OSUnserializeXML(matching
);
2004 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2005 *matches
= service
->passiveMatch( dict
);
2006 kr
= kIOReturnSuccess
;
2008 kr
= kIOReturnBadArgument
;
2016 /* Routine io_service_match_property_table */
2017 kern_return_t
is_io_service_match_property_table(
2018 io_service_t service
,
2019 io_string_t matching
,
2020 boolean_t
*matches
)
2022 return (internal_io_service_match_property_table(service
, matching
, 0, matches
));
2026 /* Routine io_service_match_property_table_ool */
2027 kern_return_t
is_io_service_match_property_table_ool(
2028 io_object_t service
,
2029 io_buf_ptr_t matching
,
2030 mach_msg_type_number_t matchingCnt
,
2031 kern_return_t
*result
,
2032 boolean_t
*matches
)
2036 vm_map_offset_t map_data
;
2038 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2039 data
= CAST_DOWN(vm_offset_t
, map_data
);
2041 if( KERN_SUCCESS
== kr
) {
2042 // must return success after vm_map_copyout() succeeds
2043 *result
= internal_io_service_match_property_table(service
,
2044 (const char *)data
, matchingCnt
, matches
);
2045 vm_deallocate( kernel_map
, data
, matchingCnt
);
2051 /* Routine io_service_match_property_table_bin */
2052 kern_return_t
is_io_service_match_property_table_bin(
2053 io_object_t service
,
2054 io_struct_inband_t matching
,
2055 mach_msg_type_number_t matchingCnt
,
2058 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
2061 static kern_return_t
internal_io_service_get_matching_services(
2062 mach_port_t master_port
,
2063 const char * matching
,
2064 mach_msg_type_number_t matching_size
,
2065 io_iterator_t
*existing
)
2069 OSDictionary
* dict
;
2071 if( master_port
!= master_device_port
)
2072 return( kIOReturnNotPrivileged
);
2074 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
2075 : OSUnserializeXML(matching
);
2076 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2077 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2078 kr
= kIOReturnSuccess
;
2080 kr
= kIOReturnBadArgument
;
2088 /* Routine io_service_get_matching_services */
2089 kern_return_t
is_io_service_get_matching_services(
2090 mach_port_t master_port
,
2091 io_string_t matching
,
2092 io_iterator_t
*existing
)
2094 return (internal_io_service_get_matching_services(master_port
, matching
, 0, existing
));
2097 /* Routine io_service_get_matching_services_ool */
2098 kern_return_t
is_io_service_get_matching_services_ool(
2099 mach_port_t master_port
,
2100 io_buf_ptr_t matching
,
2101 mach_msg_type_number_t matchingCnt
,
2102 kern_return_t
*result
,
2103 io_object_t
*existing
)
2107 vm_map_offset_t map_data
;
2109 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2110 data
= CAST_DOWN(vm_offset_t
, map_data
);
2112 if( KERN_SUCCESS
== kr
) {
2113 // must return success after vm_map_copyout() succeeds
2114 // and mig will copy out objects on success
2116 *result
= internal_io_service_get_matching_services(master_port
,
2117 (const char *) data
, matchingCnt
, existing
);
2118 vm_deallocate( kernel_map
, data
, matchingCnt
);
2124 /* Routine io_service_get_matching_services_bin */
2125 kern_return_t
is_io_service_get_matching_services_bin(
2126 mach_port_t master_port
,
2127 io_struct_inband_t matching
,
2128 mach_msg_type_number_t matchingCnt
,
2129 io_object_t
*existing
)
2131 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
2135 static kern_return_t
internal_io_service_get_matching_service(
2136 mach_port_t master_port
,
2137 const char * matching
,
2138 mach_msg_type_number_t matching_size
,
2139 io_service_t
*service
)
2143 OSDictionary
* dict
;
2145 if( master_port
!= master_device_port
)
2146 return( kIOReturnNotPrivileged
);
2148 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
2149 : OSUnserializeXML(matching
);
2150 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2151 *service
= IOService::copyMatchingService( dict
);
2152 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2154 kr
= kIOReturnBadArgument
;
2162 /* Routine io_service_get_matching_service */
2163 kern_return_t
is_io_service_get_matching_service(
2164 mach_port_t master_port
,
2165 io_string_t matching
,
2166 io_service_t
*service
)
2168 return (internal_io_service_get_matching_service(master_port
, matching
, 0, service
));
2171 /* Routine io_service_get_matching_services_ool */
2172 kern_return_t
is_io_service_get_matching_service_ool(
2173 mach_port_t master_port
,
2174 io_buf_ptr_t matching
,
2175 mach_msg_type_number_t matchingCnt
,
2176 kern_return_t
*result
,
2177 io_object_t
*service
)
2181 vm_map_offset_t map_data
;
2183 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2184 data
= CAST_DOWN(vm_offset_t
, map_data
);
2186 if( KERN_SUCCESS
== kr
) {
2187 // must return success after vm_map_copyout() succeeds
2188 // and mig will copy out objects on success
2190 *result
= internal_io_service_get_matching_service(master_port
,
2191 (const char *) data
, matchingCnt
, service
);
2192 vm_deallocate( kernel_map
, data
, matchingCnt
);
2198 /* Routine io_service_get_matching_service_bin */
2199 kern_return_t
is_io_service_get_matching_service_bin(
2200 mach_port_t master_port
,
2201 io_struct_inband_t matching
,
2202 mach_msg_type_number_t matchingCnt
,
2203 io_object_t
*service
)
2205 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
2208 static kern_return_t
internal_io_service_add_notification(
2209 mach_port_t master_port
,
2210 io_name_t notification_type
,
2211 const char * matching
,
2212 size_t matching_size
,
2215 vm_size_t referenceSize
,
2217 io_object_t
* notification
)
2219 IOServiceUserNotification
* userNotify
= 0;
2220 IONotifier
* notify
= 0;
2221 const OSSymbol
* sym
;
2222 OSDictionary
* dict
;
2224 unsigned long int userMsgType
;
2226 if( master_port
!= master_device_port
)
2227 return( kIOReturnNotPrivileged
);
2230 err
= kIOReturnNoResources
;
2232 if( !(sym
= OSSymbol::withCString( notification_type
)))
2233 err
= kIOReturnNoResources
;
2237 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2241 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
));
2245 err
= kIOReturnBadArgument
;
2249 if( (sym
== gIOPublishNotification
)
2250 || (sym
== gIOFirstPublishNotification
))
2251 userMsgType
= kIOServicePublishNotificationType
;
2252 else if( (sym
== gIOMatchedNotification
)
2253 || (sym
== gIOFirstMatchNotification
))
2254 userMsgType
= kIOServiceMatchedNotificationType
;
2255 else if( sym
== gIOTerminatedNotification
)
2256 userMsgType
= kIOServiceTerminatedNotificationType
;
2258 userMsgType
= kLastIOKitNotificationType
;
2260 userNotify
= new IOServiceUserNotification
;
2262 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
2263 reference
, referenceSize
, client64
)) {
2264 iokit_release_port_send(port
);
2265 userNotify
->release();
2271 notify
= IOService::addMatchingNotification( sym
, dict
,
2272 &userNotify
->_handler
, userNotify
);
2274 *notification
= userNotify
;
2275 userNotify
->setNotification( notify
);
2276 err
= kIOReturnSuccess
;
2278 err
= kIOReturnUnsupported
;
2291 /* Routine io_service_add_notification */
2292 kern_return_t
is_io_service_add_notification(
2293 mach_port_t master_port
,
2294 io_name_t notification_type
,
2295 io_string_t matching
,
2297 io_async_ref_t reference
,
2298 mach_msg_type_number_t referenceCnt
,
2299 io_object_t
* notification
)
2301 return (internal_io_service_add_notification(master_port
, notification_type
,
2302 matching
, 0, port
, &reference
[0], sizeof(io_async_ref_t
),
2303 false, notification
));
2306 /* Routine io_service_add_notification_64 */
2307 kern_return_t
is_io_service_add_notification_64(
2308 mach_port_t master_port
,
2309 io_name_t notification_type
,
2310 io_string_t matching
,
2311 mach_port_t wake_port
,
2312 io_async_ref64_t reference
,
2313 mach_msg_type_number_t referenceCnt
,
2314 io_object_t
*notification
)
2316 return (internal_io_service_add_notification(master_port
, notification_type
,
2317 matching
, 0, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2318 true, notification
));
2321 /* Routine io_service_add_notification_bin */
2322 kern_return_t is_io_service_add_notification_bin
2324 mach_port_t master_port
,
2325 io_name_t notification_type
,
2326 io_struct_inband_t matching
,
2327 mach_msg_type_number_t matchingCnt
,
2328 mach_port_t wake_port
,
2329 io_async_ref_t reference
,
2330 mach_msg_type_number_t referenceCnt
,
2331 io_object_t
*notification
)
2333 return (internal_io_service_add_notification(master_port
, notification_type
,
2334 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2335 false, notification
));
2338 /* Routine io_service_add_notification_bin_64 */
2339 kern_return_t is_io_service_add_notification_bin_64
2341 mach_port_t master_port
,
2342 io_name_t notification_type
,
2343 io_struct_inband_t matching
,
2344 mach_msg_type_number_t matchingCnt
,
2345 mach_port_t wake_port
,
2346 io_async_ref64_t reference
,
2347 mach_msg_type_number_t referenceCnt
,
2348 io_object_t
*notification
)
2350 return (internal_io_service_add_notification(master_port
, notification_type
,
2351 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2352 true, notification
));
2355 static kern_return_t
internal_io_service_add_notification_ool(
2356 mach_port_t master_port
,
2357 io_name_t notification_type
,
2358 io_buf_ptr_t matching
,
2359 mach_msg_type_number_t matchingCnt
,
2360 mach_port_t wake_port
,
2362 vm_size_t referenceSize
,
2364 kern_return_t
*result
,
2365 io_object_t
*notification
)
2369 vm_map_offset_t map_data
;
2371 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2372 data
= CAST_DOWN(vm_offset_t
, map_data
);
2374 if( KERN_SUCCESS
== kr
) {
2375 // must return success after vm_map_copyout() succeeds
2376 // and mig will copy out objects on success
2378 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2379 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2380 vm_deallocate( kernel_map
, data
, matchingCnt
);
2386 /* Routine io_service_add_notification_ool */
2387 kern_return_t
is_io_service_add_notification_ool(
2388 mach_port_t master_port
,
2389 io_name_t notification_type
,
2390 io_buf_ptr_t matching
,
2391 mach_msg_type_number_t matchingCnt
,
2392 mach_port_t wake_port
,
2393 io_async_ref_t reference
,
2394 mach_msg_type_number_t referenceCnt
,
2395 kern_return_t
*result
,
2396 io_object_t
*notification
)
2398 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2399 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2400 false, result
, notification
));
2403 /* Routine io_service_add_notification_ool_64 */
2404 kern_return_t
is_io_service_add_notification_ool_64(
2405 mach_port_t master_port
,
2406 io_name_t notification_type
,
2407 io_buf_ptr_t matching
,
2408 mach_msg_type_number_t matchingCnt
,
2409 mach_port_t wake_port
,
2410 io_async_ref64_t reference
,
2411 mach_msg_type_number_t referenceCnt
,
2412 kern_return_t
*result
,
2413 io_object_t
*notification
)
2415 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2416 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2417 true, result
, notification
));
2420 /* Routine io_service_add_notification_old */
2421 kern_return_t
is_io_service_add_notification_old(
2422 mach_port_t master_port
,
2423 io_name_t notification_type
,
2424 io_string_t matching
,
2426 // for binary compatibility reasons, this must be natural_t for ILP32
2428 io_object_t
* notification
)
2430 return( is_io_service_add_notification( master_port
, notification_type
,
2431 matching
, port
, &ref
, 1, notification
));
2435 static kern_return_t
internal_io_service_add_interest_notification(
2436 io_object_t _service
,
2437 io_name_t type_of_interest
,
2440 vm_size_t referenceSize
,
2442 io_object_t
* notification
)
2445 IOServiceMessageUserNotification
* userNotify
= 0;
2446 IONotifier
* notify
= 0;
2447 const OSSymbol
* sym
;
2450 CHECK( IOService
, _service
, service
);
2452 err
= kIOReturnNoResources
;
2453 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2455 userNotify
= new IOServiceMessageUserNotification
;
2457 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2458 reference
, referenceSize
,
2459 kIOUserNotifyMaxMessageSize
,
2461 iokit_release_port_send(port
);
2462 userNotify
->release();
2468 notify
= service
->registerInterest( sym
,
2469 &userNotify
->_handler
, userNotify
);
2471 *notification
= userNotify
;
2472 userNotify
->setNotification( notify
);
2473 err
= kIOReturnSuccess
;
2475 err
= kIOReturnUnsupported
;
2484 /* Routine io_service_add_message_notification */
2485 kern_return_t
is_io_service_add_interest_notification(
2486 io_object_t service
,
2487 io_name_t type_of_interest
,
2489 io_async_ref_t reference
,
2490 mach_msg_type_number_t referenceCnt
,
2491 io_object_t
* notification
)
2493 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2494 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2497 /* Routine io_service_add_interest_notification_64 */
2498 kern_return_t
is_io_service_add_interest_notification_64(
2499 io_object_t service
,
2500 io_name_t type_of_interest
,
2501 mach_port_t wake_port
,
2502 io_async_ref64_t reference
,
2503 mach_msg_type_number_t referenceCnt
,
2504 io_object_t
*notification
)
2506 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2507 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2511 /* Routine io_service_acknowledge_notification */
2512 kern_return_t
is_io_service_acknowledge_notification(
2513 io_object_t _service
,
2514 natural_t notify_ref
,
2515 natural_t response
)
2517 CHECK( IOService
, _service
, service
);
2519 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2520 (IOOptionBits
) response
));
2524 /* Routine io_connect_get_semaphore */
2525 kern_return_t
is_io_connect_get_notification_semaphore(
2526 io_connect_t connection
,
2527 natural_t notification_type
,
2528 semaphore_t
*semaphore
)
2530 CHECK( IOUserClient
, connection
, client
);
2532 IOStatisticsClientCall();
2533 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2537 /* Routine io_registry_get_root_entry */
2538 kern_return_t
is_io_registry_get_root_entry(
2539 mach_port_t master_port
,
2542 IORegistryEntry
* entry
;
2544 if( master_port
!= master_device_port
)
2545 return( kIOReturnNotPrivileged
);
2547 entry
= IORegistryEntry::getRegistryRoot();
2552 return( kIOReturnSuccess
);
2555 /* Routine io_registry_create_iterator */
2556 kern_return_t
is_io_registry_create_iterator(
2557 mach_port_t master_port
,
2560 io_object_t
*iterator
)
2562 if( master_port
!= master_device_port
)
2563 return( kIOReturnNotPrivileged
);
2565 *iterator
= IOUserIterator::withIterator(
2566 IORegistryIterator::iterateOver(
2567 IORegistryEntry::getPlane( plane
), options
));
2569 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2572 /* Routine io_registry_entry_create_iterator */
2573 kern_return_t
is_io_registry_entry_create_iterator(
2574 io_object_t registry_entry
,
2577 io_object_t
*iterator
)
2579 CHECK( IORegistryEntry
, registry_entry
, entry
);
2581 *iterator
= IOUserIterator::withIterator(
2582 IORegistryIterator::iterateOver( entry
,
2583 IORegistryEntry::getPlane( plane
), options
));
2585 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2588 /* Routine io_registry_iterator_enter */
2589 kern_return_t
is_io_registry_iterator_enter_entry(
2590 io_object_t iterator
)
2592 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2594 IOLockLock(oIter
->lock
);
2596 IOLockUnlock(oIter
->lock
);
2598 return( kIOReturnSuccess
);
2601 /* Routine io_registry_iterator_exit */
2602 kern_return_t
is_io_registry_iterator_exit_entry(
2603 io_object_t iterator
)
2607 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2609 IOLockLock(oIter
->lock
);
2610 didIt
= iter
->exitEntry();
2611 IOLockUnlock(oIter
->lock
);
2613 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2616 /* Routine io_registry_entry_from_path */
2617 kern_return_t
is_io_registry_entry_from_path(
2618 mach_port_t master_port
,
2620 io_object_t
*registry_entry
)
2622 IORegistryEntry
* entry
;
2624 if( master_port
!= master_device_port
)
2625 return( kIOReturnNotPrivileged
);
2627 entry
= IORegistryEntry::fromPath( path
);
2629 *registry_entry
= entry
;
2631 return( kIOReturnSuccess
);
2635 /* Routine io_registry_entry_from_path */
2636 kern_return_t
is_io_registry_entry_from_path_ool(
2637 mach_port_t master_port
,
2638 io_string_inband_t path
,
2639 io_buf_ptr_t path_ool
,
2640 mach_msg_type_number_t path_oolCnt
,
2641 kern_return_t
*result
,
2642 io_object_t
*registry_entry
)
2644 IORegistryEntry
* entry
;
2645 vm_map_offset_t map_data
;
2650 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2654 res
= err
= KERN_SUCCESS
;
2655 if (path
[0]) cpath
= path
;
2658 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2659 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2661 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2662 if (KERN_SUCCESS
== err
)
2664 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2665 cpath
= CAST_DOWN(const char *, map_data
);
2666 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2670 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2672 entry
= IORegistryEntry::fromPath(cpath
);
2673 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2676 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2678 if (KERN_SUCCESS
!= err
) res
= err
;
2679 *registry_entry
= entry
;
2686 /* Routine io_registry_entry_in_plane */
2687 kern_return_t
is_io_registry_entry_in_plane(
2688 io_object_t registry_entry
,
2690 boolean_t
*inPlane
)
2692 CHECK( IORegistryEntry
, registry_entry
, entry
);
2694 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2696 return( kIOReturnSuccess
);
2700 /* Routine io_registry_entry_get_path */
2701 kern_return_t
is_io_registry_entry_get_path(
2702 io_object_t registry_entry
,
2707 CHECK( IORegistryEntry
, registry_entry
, entry
);
2709 length
= sizeof( io_string_t
);
2710 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2711 return( kIOReturnSuccess
);
2713 return( kIOReturnBadArgument
);
2716 /* Routine io_registry_entry_get_path */
2717 kern_return_t
is_io_registry_entry_get_path_ool(
2718 io_object_t registry_entry
,
2720 io_string_inband_t path
,
2721 io_buf_ptr_t
*path_ool
,
2722 mach_msg_type_number_t
*path_oolCnt
)
2724 enum { kMaxPath
= 16384 };
2729 CHECK( IORegistryEntry
, registry_entry
, entry
);
2733 length
= sizeof(io_string_inband_t
);
2734 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2738 buf
= IONew(char, length
);
2739 if (!buf
) err
= kIOReturnNoMemory
;
2740 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2743 *path_oolCnt
= length
;
2744 err
= copyoutkdata(buf
, length
, path_ool
);
2746 if (buf
) IODelete(buf
, char, kMaxPath
);
2753 /* Routine io_registry_entry_get_name */
2754 kern_return_t
is_io_registry_entry_get_name(
2755 io_object_t registry_entry
,
2758 CHECK( IORegistryEntry
, registry_entry
, entry
);
2760 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2762 return( kIOReturnSuccess
);
2765 /* Routine io_registry_entry_get_name_in_plane */
2766 kern_return_t
is_io_registry_entry_get_name_in_plane(
2767 io_object_t registry_entry
,
2768 io_name_t planeName
,
2771 const IORegistryPlane
* plane
;
2772 CHECK( IORegistryEntry
, registry_entry
, entry
);
2775 plane
= IORegistryEntry::getPlane( planeName
);
2779 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2781 return( kIOReturnSuccess
);
2784 /* Routine io_registry_entry_get_location_in_plane */
2785 kern_return_t
is_io_registry_entry_get_location_in_plane(
2786 io_object_t registry_entry
,
2787 io_name_t planeName
,
2788 io_name_t location
)
2790 const IORegistryPlane
* plane
;
2791 CHECK( IORegistryEntry
, registry_entry
, entry
);
2794 plane
= IORegistryEntry::getPlane( planeName
);
2798 const char * cstr
= entry
->getLocation( plane
);
2801 strncpy( location
, cstr
, sizeof( io_name_t
));
2802 return( kIOReturnSuccess
);
2804 return( kIOReturnNotFound
);
2807 /* Routine io_registry_entry_get_registry_entry_id */
2808 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2809 io_object_t registry_entry
,
2810 uint64_t *entry_id
)
2812 CHECK( IORegistryEntry
, registry_entry
, entry
);
2814 *entry_id
= entry
->getRegistryEntryID();
2816 return (kIOReturnSuccess
);
2819 /* Routine io_registry_entry_get_property */
2820 kern_return_t
is_io_registry_entry_get_property_bytes(
2821 io_object_t registry_entry
,
2822 io_name_t property_name
,
2823 io_struct_inband_t buf
,
2824 mach_msg_type_number_t
*dataCnt
)
2832 unsigned int len
= 0;
2833 const void * bytes
= 0;
2834 IOReturn ret
= kIOReturnSuccess
;
2836 CHECK( IORegistryEntry
, registry_entry
, entry
);
2839 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2840 return kIOReturnNotPermitted
;
2843 obj
= entry
->copyProperty(property_name
);
2845 return( kIOReturnNoResources
);
2847 // One day OSData will be a common container base class
2849 if( (data
= OSDynamicCast( OSData
, obj
))) {
2850 len
= data
->getLength();
2851 bytes
= data
->getBytesNoCopy();
2853 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2854 len
= str
->getLength() + 1;
2855 bytes
= str
->getCStringNoCopy();
2857 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2858 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2859 bytes
= boo
->isTrue() ? "Yes" : "No";
2861 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2862 offsetBytes
= off
->unsigned64BitValue();
2863 len
= off
->numberOfBytes();
2864 bytes
= &offsetBytes
;
2865 #ifdef __BIG_ENDIAN__
2866 bytes
= (const void *)
2867 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2871 ret
= kIOReturnBadArgument
;
2875 ret
= kIOReturnIPCError
;
2878 bcopy( bytes
, buf
, len
);
2887 /* Routine io_registry_entry_get_property */
2888 kern_return_t
is_io_registry_entry_get_property(
2889 io_object_t registry_entry
,
2890 io_name_t property_name
,
2891 io_buf_ptr_t
*properties
,
2892 mach_msg_type_number_t
*propertiesCnt
)
2898 CHECK( IORegistryEntry
, registry_entry
, entry
);
2901 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2902 return kIOReturnNotPermitted
;
2905 obj
= entry
->copyProperty(property_name
);
2907 return( kIOReturnNotFound
);
2909 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2912 return( kIOReturnNoMemory
);
2915 if( obj
->serialize( s
)) {
2916 len
= s
->getLength();
2917 *propertiesCnt
= len
;
2918 err
= copyoutkdata( s
->text(), len
, properties
);
2921 err
= kIOReturnUnsupported
;
2929 /* Routine io_registry_entry_get_property_recursively */
2930 kern_return_t
is_io_registry_entry_get_property_recursively(
2931 io_object_t registry_entry
,
2933 io_name_t property_name
,
2935 io_buf_ptr_t
*properties
,
2936 mach_msg_type_number_t
*propertiesCnt
)
2942 CHECK( IORegistryEntry
, registry_entry
, entry
);
2945 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2946 return kIOReturnNotPermitted
;
2949 obj
= entry
->copyProperty( property_name
,
2950 IORegistryEntry::getPlane( plane
), options
);
2952 return( kIOReturnNotFound
);
2954 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2957 return( kIOReturnNoMemory
);
2960 if( obj
->serialize( s
)) {
2961 len
= s
->getLength();
2962 *propertiesCnt
= len
;
2963 err
= copyoutkdata( s
->text(), len
, properties
);
2966 err
= kIOReturnUnsupported
;
2976 static kern_return_t
2977 filteredProperties(IORegistryEntry
*entry
, OSDictionary
*properties
, OSDictionary
**filteredp
)
2979 kern_return_t err
= 0;
2980 OSDictionary
*filtered
= NULL
;
2981 OSCollectionIterator
*iter
= NULL
;
2984 kauth_cred_t cred
= kauth_cred_get();
2986 if (properties
== NULL
)
2987 return kIOReturnUnsupported
;
2989 if ((iter
= OSCollectionIterator::withCollection(properties
)) == NULL
||
2990 (filtered
= OSDictionary::withCapacity(properties
->getCapacity())) == NULL
) {
2991 err
= kIOReturnNoMemory
;
2995 while ((p
= iter
->getNextObject()) != NULL
) {
2996 if ((key
= OSDynamicCast(OSSymbol
, p
)) == NULL
||
2997 mac_iokit_check_get_property(cred
, entry
, key
->getCStringNoCopy()) != 0)
2999 filtered
->setObject(key
, properties
->getObject(key
));
3005 *filteredp
= filtered
;
3011 /* Routine io_registry_entry_get_properties */
3012 kern_return_t
is_io_registry_entry_get_properties(
3013 io_object_t registry_entry
,
3014 io_buf_ptr_t
*properties
,
3015 mach_msg_type_number_t
*propertiesCnt
)
3017 kern_return_t err
= 0;
3020 CHECK( IORegistryEntry
, registry_entry
, entry
);
3022 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3024 return( kIOReturnNoMemory
);
3026 if (!entry
->serializeProperties(s
))
3027 err
= kIOReturnUnsupported
;
3030 if (!err
&& mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
3031 OSObject
*propobj
= OSUnserializeXML(s
->text(), s
->getLength());
3032 OSDictionary
*filteredprops
= NULL
;
3033 err
= filteredProperties(entry
, OSDynamicCast(OSDictionary
, propobj
), &filteredprops
);
3034 if (propobj
) propobj
->release();
3038 if (!filteredprops
->serialize(s
))
3039 err
= kIOReturnUnsupported
;
3041 if (filteredprops
!= NULL
)
3042 filteredprops
->release();
3044 #endif /* CONFIG_MACF */
3047 len
= s
->getLength();
3048 *propertiesCnt
= len
;
3049 err
= copyoutkdata( s
->text(), len
, properties
);
3058 struct GetPropertiesEditorRef
3061 IORegistryEntry
* entry
;
3062 OSCollection
* root
;
3065 static const OSMetaClassBase
*
3066 GetPropertiesEditor(void * reference
,
3068 OSCollection
* container
,
3069 const OSSymbol
* name
,
3070 const OSMetaClassBase
* value
)
3072 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
3074 if (!ref
->root
) ref
->root
= container
;
3075 if (ref
->root
== container
)
3077 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
3082 if (value
) value
->retain();
3086 #endif /* CONFIG_MACF */
3088 /* Routine io_registry_entry_get_properties */
3089 kern_return_t
is_io_registry_entry_get_properties_bin(
3090 io_object_t registry_entry
,
3091 io_buf_ptr_t
*properties
,
3092 mach_msg_type_number_t
*propertiesCnt
)
3094 kern_return_t err
= kIOReturnSuccess
;
3097 OSSerialize::Editor editor
= 0;
3100 CHECK(IORegistryEntry
, registry_entry
, entry
);
3103 GetPropertiesEditorRef ref
;
3104 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
3106 editor
= &GetPropertiesEditor
;
3108 ref
.cred
= kauth_cred_get();
3114 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3115 if (!s
) return (kIOReturnNoMemory
);
3117 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
3119 if (kIOReturnSuccess
== err
)
3121 len
= s
->getLength();
3122 *propertiesCnt
= len
;
3123 err
= copyoutkdata(s
->text(), len
, properties
);
3130 /* Routine io_registry_entry_get_property_bin */
3131 kern_return_t
is_io_registry_entry_get_property_bin(
3132 io_object_t registry_entry
,
3134 io_name_t property_name
,
3136 io_buf_ptr_t
*properties
,
3137 mach_msg_type_number_t
*propertiesCnt
)
3142 const OSSymbol
* sym
;
3144 CHECK( IORegistryEntry
, registry_entry
, entry
);
3147 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3148 return kIOReturnNotPermitted
;
3151 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
3153 obj
= entry
->copyProperty(property_name
,
3154 IORegistryEntry::getPlane(plane
), options
);
3158 obj
= entry
->copyProperty(property_name
);
3162 return( kIOReturnNotFound
);
3164 sym
= OSSymbol::withCString(property_name
);
3167 if (gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
3171 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3174 return( kIOReturnNoMemory
);
3177 if( obj
->serialize( s
)) {
3178 len
= s
->getLength();
3179 *propertiesCnt
= len
;
3180 err
= copyoutkdata( s
->text(), len
, properties
);
3182 } else err
= kIOReturnUnsupported
;
3191 /* Routine io_registry_entry_set_properties */
3192 kern_return_t is_io_registry_entry_set_properties
3194 io_object_t registry_entry
,
3195 io_buf_ptr_t properties
,
3196 mach_msg_type_number_t propertiesCnt
,
3197 kern_return_t
* result
)
3203 vm_map_offset_t map_data
;
3205 CHECK( IORegistryEntry
, registry_entry
, entry
);
3207 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
3208 return( kIOReturnMessageTooLarge
);
3210 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3211 data
= CAST_DOWN(vm_offset_t
, map_data
);
3213 if( KERN_SUCCESS
== err
) {
3215 // must return success after vm_map_copyout() succeeds
3216 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3217 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3220 res
= kIOReturnBadArgument
;
3222 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3223 registry_entry
, obj
))
3225 res
= kIOReturnNotPermitted
;
3230 res
= entry
->setProperties( obj
);
3242 /* Routine io_registry_entry_get_child_iterator */
3243 kern_return_t
is_io_registry_entry_get_child_iterator(
3244 io_object_t registry_entry
,
3246 io_object_t
*iterator
)
3248 CHECK( IORegistryEntry
, registry_entry
, entry
);
3250 *iterator
= entry
->getChildIterator(
3251 IORegistryEntry::getPlane( plane
));
3253 return( kIOReturnSuccess
);
3256 /* Routine io_registry_entry_get_parent_iterator */
3257 kern_return_t
is_io_registry_entry_get_parent_iterator(
3258 io_object_t registry_entry
,
3260 io_object_t
*iterator
)
3262 CHECK( IORegistryEntry
, registry_entry
, entry
);
3264 *iterator
= entry
->getParentIterator(
3265 IORegistryEntry::getPlane( plane
));
3267 return( kIOReturnSuccess
);
3270 /* Routine io_service_get_busy_state */
3271 kern_return_t
is_io_service_get_busy_state(
3272 io_object_t _service
,
3273 uint32_t *busyState
)
3275 CHECK( IOService
, _service
, service
);
3277 *busyState
= service
->getBusyState();
3279 return( kIOReturnSuccess
);
3282 /* Routine io_service_get_state */
3283 kern_return_t
is_io_service_get_state(
3284 io_object_t _service
,
3286 uint32_t *busy_state
,
3287 uint64_t *accumulated_busy_time
)
3289 CHECK( IOService
, _service
, service
);
3291 *state
= service
->getState();
3292 *busy_state
= service
->getBusyState();
3293 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3295 return( kIOReturnSuccess
);
3298 /* Routine io_service_wait_quiet */
3299 kern_return_t
is_io_service_wait_quiet(
3300 io_object_t _service
,
3301 mach_timespec_t wait_time
)
3305 CHECK( IOService
, _service
, service
);
3307 timeoutNS
= wait_time
.tv_sec
;
3308 timeoutNS
*= kSecondScale
;
3309 timeoutNS
+= wait_time
.tv_nsec
;
3311 return( service
->waitQuiet(timeoutNS
) );
3314 /* Routine io_service_request_probe */
3315 kern_return_t
is_io_service_request_probe(
3316 io_object_t _service
,
3319 CHECK( IOService
, _service
, service
);
3321 return( service
->requestProbe( options
));
3324 /* Routine io_service_get_authorization_id */
3325 kern_return_t
is_io_service_get_authorization_id(
3326 io_object_t _service
,
3327 uint64_t *authorization_id
)
3331 CHECK( IOService
, _service
, service
);
3333 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3334 kIOClientPrivilegeAdministrator
);
3335 if( kIOReturnSuccess
!= kr
)
3338 *authorization_id
= service
->getAuthorizationID();
3343 /* Routine io_service_set_authorization_id */
3344 kern_return_t
is_io_service_set_authorization_id(
3345 io_object_t _service
,
3346 uint64_t authorization_id
)
3348 CHECK( IOService
, _service
, service
);
3350 return( service
->setAuthorizationID( authorization_id
) );
3353 /* Routine io_service_open_ndr */
3354 kern_return_t
is_io_service_open_extended(
3355 io_object_t _service
,
3357 uint32_t connect_type
,
3359 io_buf_ptr_t properties
,
3360 mach_msg_type_number_t propertiesCnt
,
3361 kern_return_t
* result
,
3362 io_object_t
*connection
)
3364 IOUserClient
* client
= 0;
3365 kern_return_t err
= KERN_SUCCESS
;
3366 IOReturn res
= kIOReturnSuccess
;
3367 OSDictionary
* propertiesDict
= 0;
3369 bool disallowAccess
;
3371 CHECK( IOService
, _service
, service
);
3373 if (!owningTask
) return (kIOReturnBadArgument
);
3374 assert(owningTask
== current_task());
3375 if (owningTask
!= current_task()) return (kIOReturnBadArgument
);
3383 vm_map_offset_t map_data
;
3385 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3386 return( kIOReturnMessageTooLarge
);
3388 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3390 data
= CAST_DOWN(vm_offset_t
, map_data
);
3391 if (KERN_SUCCESS
== err
)
3393 // must return success after vm_map_copyout() succeeds
3394 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3395 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3396 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3397 if (!propertiesDict
)
3399 res
= kIOReturnBadArgument
;
3404 if (kIOReturnSuccess
!= res
)
3408 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3411 if (!propertiesDict
)
3412 propertiesDict
= OSDictionary::withCapacity(4);
3413 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3417 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3422 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3423 connect_type
, propertiesDict
, &client
);
3426 propertiesDict
->release();
3428 if (res
== kIOReturnSuccess
)
3430 assert( OSDynamicCast(IOUserClient
, client
) );
3432 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3433 client
->closed
= false;
3435 disallowAccess
= (crossEndian
3436 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3437 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3438 if (disallowAccess
) res
= kIOReturnUnsupported
;
3440 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3441 res
= kIOReturnNotPermitted
;
3444 if (kIOReturnSuccess
== res
) res
= client
->registerOwner(owningTask
);
3446 if (kIOReturnSuccess
!= res
)
3448 IOStatisticsClientCall();
3449 client
->clientClose();
3454 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3457 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3458 creatorName
->release();
3460 client
->setTerminateDefer(service
, false);
3465 *connection
= client
;
3471 /* Routine io_service_close */
3472 kern_return_t
is_io_service_close(
3473 io_object_t connection
)
3476 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3477 return( kIOReturnSuccess
);
3479 CHECK( IOUserClient
, connection
, client
);
3481 IOStatisticsClientCall();
3483 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
))
3485 client
->clientClose();
3489 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3490 client
->getRegistryEntryID(), client
->getName());
3493 return( kIOReturnSuccess
);
3496 /* Routine io_connect_get_service */
3497 kern_return_t
is_io_connect_get_service(
3498 io_object_t connection
,
3499 io_object_t
*service
)
3501 IOService
* theService
;
3503 CHECK( IOUserClient
, connection
, client
);
3505 theService
= client
->getService();
3507 theService
->retain();
3509 *service
= theService
;
3511 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3514 /* Routine io_connect_set_notification_port */
3515 kern_return_t
is_io_connect_set_notification_port(
3516 io_object_t connection
,
3517 uint32_t notification_type
,
3521 CHECK( IOUserClient
, connection
, client
);
3523 IOStatisticsClientCall();
3524 return( client
->registerNotificationPort( port
, notification_type
,
3525 (io_user_reference_t
) reference
));
3528 /* Routine io_connect_set_notification_port */
3529 kern_return_t
is_io_connect_set_notification_port_64(
3530 io_object_t connection
,
3531 uint32_t notification_type
,
3533 io_user_reference_t reference
)
3535 CHECK( IOUserClient
, connection
, client
);
3537 IOStatisticsClientCall();
3538 return( client
->registerNotificationPort( port
, notification_type
,
3542 /* Routine io_connect_map_memory_into_task */
3543 kern_return_t is_io_connect_map_memory_into_task
3545 io_connect_t connection
,
3546 uint32_t memory_type
,
3548 mach_vm_address_t
*address
,
3549 mach_vm_size_t
*size
,
3556 CHECK( IOUserClient
, connection
, client
);
3558 if (!into_task
) return (kIOReturnBadArgument
);
3560 IOStatisticsClientCall();
3561 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3564 *address
= map
->getAddress();
3566 *size
= map
->getSize();
3568 if( client
->sharedInstance
3569 || (into_task
!= current_task())) {
3570 // push a name out to the task owning the map,
3571 // so we can clean up maps
3572 mach_port_name_t name __unused
=
3573 IOMachPort::makeSendRightForTask(
3574 into_task
, map
, IKOT_IOKIT_OBJECT
);
3577 // keep it with the user client
3578 IOLockLock( gIOObjectPortLock
);
3579 if( 0 == client
->mappings
)
3580 client
->mappings
= OSSet::withCapacity(2);
3581 if( client
->mappings
)
3582 client
->mappings
->setObject( map
);
3583 IOLockUnlock( gIOObjectPortLock
);
3586 err
= kIOReturnSuccess
;
3589 err
= kIOReturnBadArgument
;
3594 /* Routine is_io_connect_map_memory */
3595 kern_return_t
is_io_connect_map_memory(
3596 io_object_t connect
,
3604 mach_vm_address_t address
;
3605 mach_vm_size_t size
;
3607 address
= SCALAR64(*mapAddr
);
3608 size
= SCALAR64(*mapSize
);
3610 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3612 *mapAddr
= SCALAR32(address
);
3613 *mapSize
= SCALAR32(size
);
3620 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3623 IOMemoryMap
* map
= 0;
3625 IOLockLock(gIOObjectPortLock
);
3627 iter
= OSCollectionIterator::withCollection(mappings
);
3630 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3632 if(mem
== map
->getMemoryDescriptor())
3635 mappings
->removeObject(map
);
3642 IOLockUnlock(gIOObjectPortLock
);
3649 /* Routine io_connect_unmap_memory_from_task */
3650 kern_return_t is_io_connect_unmap_memory_from_task
3652 io_connect_t connection
,
3653 uint32_t memory_type
,
3655 mach_vm_address_t address
)
3658 IOOptionBits options
= 0;
3659 IOMemoryDescriptor
* memory
;
3662 CHECK( IOUserClient
, connection
, client
);
3664 if (!from_task
) return (kIOReturnBadArgument
);
3666 IOStatisticsClientCall();
3667 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3669 if( memory
&& (kIOReturnSuccess
== err
)) {
3671 options
= (options
& ~kIOMapUserOptionsMask
)
3672 | kIOMapAnywhere
| kIOMapReference
;
3674 map
= memory
->createMappingInTask( from_task
, address
, options
);
3678 IOLockLock( gIOObjectPortLock
);
3679 if( client
->mappings
)
3680 client
->mappings
->removeObject( map
);
3681 IOLockUnlock( gIOObjectPortLock
);
3683 mach_port_name_t name
= 0;
3684 if (from_task
!= current_task())
3685 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3688 map
->userClientUnmap();
3689 err
= iokit_mod_send_right( from_task
, name
, -2 );
3690 err
= kIOReturnSuccess
;
3693 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3694 if (from_task
== current_task())
3698 err
= kIOReturnBadArgument
;
3704 kern_return_t
is_io_connect_unmap_memory(
3705 io_object_t connect
,
3711 mach_vm_address_t address
;
3713 address
= SCALAR64(mapAddr
);
3715 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3721 /* Routine io_connect_add_client */
3722 kern_return_t
is_io_connect_add_client(
3723 io_object_t connection
,
3724 io_object_t connect_to
)
3726 CHECK( IOUserClient
, connection
, client
);
3727 CHECK( IOUserClient
, connect_to
, to
);
3729 IOStatisticsClientCall();
3730 return( client
->connectClient( to
) );
3734 /* Routine io_connect_set_properties */
3735 kern_return_t
is_io_connect_set_properties(
3736 io_object_t connection
,
3737 io_buf_ptr_t properties
,
3738 mach_msg_type_number_t propertiesCnt
,
3739 kern_return_t
* result
)
3741 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3744 /* Routine io_user_client_method */
3745 kern_return_t is_io_connect_method_var_output
3747 io_connect_t connection
,
3749 io_scalar_inband64_t scalar_input
,
3750 mach_msg_type_number_t scalar_inputCnt
,
3751 io_struct_inband_t inband_input
,
3752 mach_msg_type_number_t inband_inputCnt
,
3753 mach_vm_address_t ool_input
,
3754 mach_vm_size_t ool_input_size
,
3755 io_struct_inband_t inband_output
,
3756 mach_msg_type_number_t
*inband_outputCnt
,
3757 io_scalar_inband64_t scalar_output
,
3758 mach_msg_type_number_t
*scalar_outputCnt
,
3759 io_buf_ptr_t
*var_output
,
3760 mach_msg_type_number_t
*var_outputCnt
3763 CHECK( IOUserClient
, connection
, client
);
3765 IOExternalMethodArguments args
;
3767 IOMemoryDescriptor
* inputMD
= 0;
3768 OSObject
* structureVariableOutputData
= 0;
3770 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3771 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3773 args
.selector
= selector
;
3775 args
.asyncWakePort
= MACH_PORT_NULL
;
3776 args
.asyncReference
= 0;
3777 args
.asyncReferenceCount
= 0;
3778 args
.structureVariableOutputData
= &structureVariableOutputData
;
3780 args
.scalarInput
= scalar_input
;
3781 args
.scalarInputCount
= scalar_inputCnt
;
3782 args
.structureInput
= inband_input
;
3783 args
.structureInputSize
= inband_inputCnt
;
3786 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3787 kIODirectionOut
, current_task());
3789 args
.structureInputDescriptor
= inputMD
;
3791 args
.scalarOutput
= scalar_output
;
3792 args
.scalarOutputCount
= *scalar_outputCnt
;
3793 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3794 args
.structureOutput
= inband_output
;
3795 args
.structureOutputSize
= *inband_outputCnt
;
3796 args
.structureOutputDescriptor
= NULL
;
3797 args
.structureOutputDescriptorSize
= 0;
3799 IOStatisticsClientCall();
3800 ret
= client
->externalMethod( selector
, &args
);
3802 *scalar_outputCnt
= args
.scalarOutputCount
;
3803 *inband_outputCnt
= args
.structureOutputSize
;
3805 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3807 OSSerialize
* serialize
;
3811 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3813 len
= serialize
->getLength();
3814 *var_outputCnt
= len
;
3815 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3817 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3819 len
= data
->getLength();
3820 *var_outputCnt
= len
;
3821 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3825 ret
= kIOReturnUnderrun
;
3831 if (structureVariableOutputData
)
3832 structureVariableOutputData
->release();
3837 /* Routine io_user_client_method */
3838 kern_return_t is_io_connect_method
3840 io_connect_t connection
,
3842 io_scalar_inband64_t scalar_input
,
3843 mach_msg_type_number_t scalar_inputCnt
,
3844 io_struct_inband_t inband_input
,
3845 mach_msg_type_number_t inband_inputCnt
,
3846 mach_vm_address_t ool_input
,
3847 mach_vm_size_t ool_input_size
,
3848 io_struct_inband_t inband_output
,
3849 mach_msg_type_number_t
*inband_outputCnt
,
3850 io_scalar_inband64_t scalar_output
,
3851 mach_msg_type_number_t
*scalar_outputCnt
,
3852 mach_vm_address_t ool_output
,
3853 mach_vm_size_t
*ool_output_size
3856 CHECK( IOUserClient
, connection
, client
);
3858 IOExternalMethodArguments args
;
3860 IOMemoryDescriptor
* inputMD
= 0;
3861 IOMemoryDescriptor
* outputMD
= 0;
3863 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3864 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3866 args
.selector
= selector
;
3868 args
.asyncWakePort
= MACH_PORT_NULL
;
3869 args
.asyncReference
= 0;
3870 args
.asyncReferenceCount
= 0;
3871 args
.structureVariableOutputData
= 0;
3873 args
.scalarInput
= scalar_input
;
3874 args
.scalarInputCount
= scalar_inputCnt
;
3875 args
.structureInput
= inband_input
;
3876 args
.structureInputSize
= inband_inputCnt
;
3879 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3880 kIODirectionOut
, current_task());
3882 args
.structureInputDescriptor
= inputMD
;
3884 args
.scalarOutput
= scalar_output
;
3885 args
.scalarOutputCount
= *scalar_outputCnt
;
3886 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3887 args
.structureOutput
= inband_output
;
3888 args
.structureOutputSize
= *inband_outputCnt
;
3890 if (ool_output
&& ool_output_size
)
3892 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3893 kIODirectionIn
, current_task());
3896 args
.structureOutputDescriptor
= outputMD
;
3897 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3899 IOStatisticsClientCall();
3900 ret
= client
->externalMethod( selector
, &args
);
3902 *scalar_outputCnt
= args
.scalarOutputCount
;
3903 *inband_outputCnt
= args
.structureOutputSize
;
3904 *ool_output_size
= args
.structureOutputDescriptorSize
;
3909 outputMD
->release();
3914 /* Routine io_async_user_client_method */
3915 kern_return_t is_io_connect_async_method
3917 io_connect_t connection
,
3918 mach_port_t wake_port
,
3919 io_async_ref64_t reference
,
3920 mach_msg_type_number_t referenceCnt
,
3922 io_scalar_inband64_t scalar_input
,
3923 mach_msg_type_number_t scalar_inputCnt
,
3924 io_struct_inband_t inband_input
,
3925 mach_msg_type_number_t inband_inputCnt
,
3926 mach_vm_address_t ool_input
,
3927 mach_vm_size_t ool_input_size
,
3928 io_struct_inband_t inband_output
,
3929 mach_msg_type_number_t
*inband_outputCnt
,
3930 io_scalar_inband64_t scalar_output
,
3931 mach_msg_type_number_t
*scalar_outputCnt
,
3932 mach_vm_address_t ool_output
,
3933 mach_vm_size_t
* ool_output_size
3936 CHECK( IOUserClient
, connection
, client
);
3938 IOExternalMethodArguments args
;
3940 IOMemoryDescriptor
* inputMD
= 0;
3941 IOMemoryDescriptor
* outputMD
= 0;
3943 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3944 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3946 reference
[0] = (io_user_reference_t
) wake_port
;
3947 if (vm_map_is_64bit(get_task_map(current_task())))
3948 reference
[0] |= kIOUCAsync64Flag
;
3950 args
.selector
= selector
;
3952 args
.asyncWakePort
= wake_port
;
3953 args
.asyncReference
= reference
;
3954 args
.asyncReferenceCount
= referenceCnt
;
3956 args
.scalarInput
= scalar_input
;
3957 args
.scalarInputCount
= scalar_inputCnt
;
3958 args
.structureInput
= inband_input
;
3959 args
.structureInputSize
= inband_inputCnt
;
3962 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3963 kIODirectionOut
, current_task());
3965 args
.structureInputDescriptor
= inputMD
;
3967 args
.scalarOutput
= scalar_output
;
3968 args
.scalarOutputCount
= *scalar_outputCnt
;
3969 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3970 args
.structureOutput
= inband_output
;
3971 args
.structureOutputSize
= *inband_outputCnt
;
3975 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3976 kIODirectionIn
, current_task());
3979 args
.structureOutputDescriptor
= outputMD
;
3980 args
.structureOutputDescriptorSize
= *ool_output_size
;
3982 IOStatisticsClientCall();
3983 ret
= client
->externalMethod( selector
, &args
);
3985 *inband_outputCnt
= args
.structureOutputSize
;
3986 *ool_output_size
= args
.structureOutputDescriptorSize
;
3991 outputMD
->release();
3996 /* Routine io_connect_method_scalarI_scalarO */
3997 kern_return_t
is_io_connect_method_scalarI_scalarO(
3998 io_object_t connect
,
4000 io_scalar_inband_t input
,
4001 mach_msg_type_number_t inputCount
,
4002 io_scalar_inband_t output
,
4003 mach_msg_type_number_t
* outputCount
)
4007 io_scalar_inband64_t _input
;
4008 io_scalar_inband64_t _output
;
4010 mach_msg_type_number_t struct_outputCnt
= 0;
4011 mach_vm_size_t ool_output_size
= 0;
4013 bzero(&_output
[0], sizeof(_output
));
4014 for (i
= 0; i
< inputCount
; i
++)
4015 _input
[i
] = SCALAR64(input
[i
]);
4017 err
= is_io_connect_method(connect
, index
,
4021 NULL
, &struct_outputCnt
,
4022 _output
, outputCount
,
4023 0, &ool_output_size
);
4025 for (i
= 0; i
< *outputCount
; i
++)
4026 output
[i
] = SCALAR32(_output
[i
]);
4031 kern_return_t
shim_io_connect_method_scalarI_scalarO(
4032 IOExternalMethod
* method
,
4034 const io_user_scalar_t
* input
,
4035 mach_msg_type_number_t inputCount
,
4036 io_user_scalar_t
* output
,
4037 mach_msg_type_number_t
* outputCount
)
4040 io_scalar_inband_t _output
;
4042 err
= kIOReturnBadArgument
;
4044 bzero(&_output
[0], sizeof(_output
));
4047 if( inputCount
!= method
->count0
)
4049 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4052 if( *outputCount
!= method
->count1
)
4054 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4058 func
= method
->func
;
4060 switch( inputCount
) {
4063 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4064 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4067 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4068 ARG32(input
[3]), ARG32(input
[4]),
4072 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4074 &_output
[0], &_output
[1] );
4077 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4078 &_output
[0], &_output
[1], &_output
[2] );
4081 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4082 &_output
[0], &_output
[1], &_output
[2],
4086 err
= (object
->*func
)( ARG32(input
[0]),
4087 &_output
[0], &_output
[1], &_output
[2],
4088 &_output
[3], &_output
[4] );
4091 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
4092 &_output
[3], &_output
[4], &_output
[5] );
4096 IOLog("%s: Bad method table\n", object
->getName());
4102 for (i
= 0; i
< *outputCount
; i
++)
4103 output
[i
] = SCALAR32(_output
[i
]);
4108 /* Routine io_async_method_scalarI_scalarO */
4109 kern_return_t
is_io_async_method_scalarI_scalarO(
4110 io_object_t connect
,
4111 mach_port_t wake_port
,
4112 io_async_ref_t reference
,
4113 mach_msg_type_number_t referenceCnt
,
4115 io_scalar_inband_t input
,
4116 mach_msg_type_number_t inputCount
,
4117 io_scalar_inband_t output
,
4118 mach_msg_type_number_t
* outputCount
)
4122 io_scalar_inband64_t _input
;
4123 io_scalar_inband64_t _output
;
4124 io_async_ref64_t _reference
;
4126 bzero(&_output
[0], sizeof(_output
));
4127 for (i
= 0; i
< referenceCnt
; i
++)
4128 _reference
[i
] = REF64(reference
[i
]);
4130 mach_msg_type_number_t struct_outputCnt
= 0;
4131 mach_vm_size_t ool_output_size
= 0;
4133 for (i
= 0; i
< inputCount
; i
++)
4134 _input
[i
] = SCALAR64(input
[i
]);
4136 err
= is_io_connect_async_method(connect
,
4137 wake_port
, _reference
, referenceCnt
,
4142 NULL
, &struct_outputCnt
,
4143 _output
, outputCount
,
4144 0, &ool_output_size
);
4146 for (i
= 0; i
< *outputCount
; i
++)
4147 output
[i
] = SCALAR32(_output
[i
]);
4151 /* Routine io_async_method_scalarI_structureO */
4152 kern_return_t
is_io_async_method_scalarI_structureO(
4153 io_object_t connect
,
4154 mach_port_t wake_port
,
4155 io_async_ref_t reference
,
4156 mach_msg_type_number_t referenceCnt
,
4158 io_scalar_inband_t input
,
4159 mach_msg_type_number_t inputCount
,
4160 io_struct_inband_t output
,
4161 mach_msg_type_number_t
* outputCount
)
4164 io_scalar_inband64_t _input
;
4165 io_async_ref64_t _reference
;
4167 for (i
= 0; i
< referenceCnt
; i
++)
4168 _reference
[i
] = REF64(reference
[i
]);
4170 mach_msg_type_number_t scalar_outputCnt
= 0;
4171 mach_vm_size_t ool_output_size
= 0;
4173 for (i
= 0; i
< inputCount
; i
++)
4174 _input
[i
] = SCALAR64(input
[i
]);
4176 return (is_io_connect_async_method(connect
,
4177 wake_port
, _reference
, referenceCnt
,
4182 output
, outputCount
,
4183 NULL
, &scalar_outputCnt
,
4184 0, &ool_output_size
));
4187 /* Routine io_async_method_scalarI_structureI */
4188 kern_return_t
is_io_async_method_scalarI_structureI(
4189 io_connect_t connect
,
4190 mach_port_t wake_port
,
4191 io_async_ref_t reference
,
4192 mach_msg_type_number_t referenceCnt
,
4194 io_scalar_inband_t input
,
4195 mach_msg_type_number_t inputCount
,
4196 io_struct_inband_t inputStruct
,
4197 mach_msg_type_number_t inputStructCount
)
4200 io_scalar_inband64_t _input
;
4201 io_async_ref64_t _reference
;
4203 for (i
= 0; i
< referenceCnt
; i
++)
4204 _reference
[i
] = REF64(reference
[i
]);
4206 mach_msg_type_number_t scalar_outputCnt
= 0;
4207 mach_msg_type_number_t inband_outputCnt
= 0;
4208 mach_vm_size_t ool_output_size
= 0;
4210 for (i
= 0; i
< inputCount
; i
++)
4211 _input
[i
] = SCALAR64(input
[i
]);
4213 return (is_io_connect_async_method(connect
,
4214 wake_port
, _reference
, referenceCnt
,
4217 inputStruct
, inputStructCount
,
4219 NULL
, &inband_outputCnt
,
4220 NULL
, &scalar_outputCnt
,
4221 0, &ool_output_size
));
4224 /* Routine io_async_method_structureI_structureO */
4225 kern_return_t
is_io_async_method_structureI_structureO(
4226 io_object_t connect
,
4227 mach_port_t wake_port
,
4228 io_async_ref_t reference
,
4229 mach_msg_type_number_t referenceCnt
,
4231 io_struct_inband_t input
,
4232 mach_msg_type_number_t inputCount
,
4233 io_struct_inband_t output
,
4234 mach_msg_type_number_t
* outputCount
)
4237 mach_msg_type_number_t scalar_outputCnt
= 0;
4238 mach_vm_size_t ool_output_size
= 0;
4239 io_async_ref64_t _reference
;
4241 for (i
= 0; i
< referenceCnt
; i
++)
4242 _reference
[i
] = REF64(reference
[i
]);
4244 return (is_io_connect_async_method(connect
,
4245 wake_port
, _reference
, referenceCnt
,
4250 output
, outputCount
,
4251 NULL
, &scalar_outputCnt
,
4252 0, &ool_output_size
));
4256 kern_return_t
shim_io_async_method_scalarI_scalarO(
4257 IOExternalAsyncMethod
* method
,
4259 mach_port_t asyncWakePort
,
4260 io_user_reference_t
* asyncReference
,
4261 uint32_t asyncReferenceCount
,
4262 const io_user_scalar_t
* input
,
4263 mach_msg_type_number_t inputCount
,
4264 io_user_scalar_t
* output
,
4265 mach_msg_type_number_t
* outputCount
)
4269 io_scalar_inband_t _output
;
4271 io_async_ref_t reference
;
4273 bzero(&_output
[0], sizeof(_output
));
4274 for (i
= 0; i
< asyncReferenceCount
; i
++)
4275 reference
[i
] = REF32(asyncReference
[i
]);
4277 err
= kIOReturnBadArgument
;
4281 if( inputCount
!= method
->count0
)
4283 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4286 if( *outputCount
!= method
->count1
)
4288 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4292 func
= method
->func
;
4294 switch( inputCount
) {
4297 err
= (object
->*func
)( reference
,
4298 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4299 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4302 err
= (object
->*func
)( reference
,
4303 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4304 ARG32(input
[3]), ARG32(input
[4]),
4308 err
= (object
->*func
)( reference
,
4309 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4311 &_output
[0], &_output
[1] );
4314 err
= (object
->*func
)( reference
,
4315 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4316 &_output
[0], &_output
[1], &_output
[2] );
4319 err
= (object
->*func
)( reference
,
4320 ARG32(input
[0]), ARG32(input
[1]),
4321 &_output
[0], &_output
[1], &_output
[2],
4325 err
= (object
->*func
)( reference
,
4327 &_output
[0], &_output
[1], &_output
[2],
4328 &_output
[3], &_output
[4] );
4331 err
= (object
->*func
)( reference
,
4332 &_output
[0], &_output
[1], &_output
[2],
4333 &_output
[3], &_output
[4], &_output
[5] );
4337 IOLog("%s: Bad method table\n", object
->getName());
4342 for (i
= 0; i
< *outputCount
; i
++)
4343 output
[i
] = SCALAR32(_output
[i
]);
4349 /* Routine io_connect_method_scalarI_structureO */
4350 kern_return_t
is_io_connect_method_scalarI_structureO(
4351 io_object_t connect
,
4353 io_scalar_inband_t input
,
4354 mach_msg_type_number_t inputCount
,
4355 io_struct_inband_t output
,
4356 mach_msg_type_number_t
* outputCount
)
4359 io_scalar_inband64_t _input
;
4361 mach_msg_type_number_t scalar_outputCnt
= 0;
4362 mach_vm_size_t ool_output_size
= 0;
4364 for (i
= 0; i
< inputCount
; i
++)
4365 _input
[i
] = SCALAR64(input
[i
]);
4367 return (is_io_connect_method(connect
, index
,
4371 output
, outputCount
,
4372 NULL
, &scalar_outputCnt
,
4373 0, &ool_output_size
));
4376 kern_return_t
shim_io_connect_method_scalarI_structureO(
4378 IOExternalMethod
* method
,
4380 const io_user_scalar_t
* input
,
4381 mach_msg_type_number_t inputCount
,
4382 io_struct_inband_t output
,
4383 IOByteCount
* outputCount
)
4388 err
= kIOReturnBadArgument
;
4391 if( inputCount
!= method
->count0
)
4393 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4396 if( (kIOUCVariableStructureSize
!= method
->count1
)
4397 && (*outputCount
!= method
->count1
))
4399 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4403 func
= method
->func
;
4405 switch( inputCount
) {
4408 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4409 ARG32(input
[3]), ARG32(input
[4]),
4413 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4415 output
, (void *)outputCount
);
4418 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4419 output
, (void *)outputCount
, 0 );
4422 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4423 output
, (void *)outputCount
, 0, 0 );
4426 err
= (object
->*func
)( ARG32(input
[0]),
4427 output
, (void *)outputCount
, 0, 0, 0 );
4430 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4434 IOLog("%s: Bad method table\n", object
->getName());
4443 kern_return_t
shim_io_async_method_scalarI_structureO(
4444 IOExternalAsyncMethod
* method
,
4446 mach_port_t asyncWakePort
,
4447 io_user_reference_t
* asyncReference
,
4448 uint32_t asyncReferenceCount
,
4449 const io_user_scalar_t
* input
,
4450 mach_msg_type_number_t inputCount
,
4451 io_struct_inband_t output
,
4452 mach_msg_type_number_t
* outputCount
)
4457 io_async_ref_t reference
;
4459 for (i
= 0; i
< asyncReferenceCount
; i
++)
4460 reference
[i
] = REF32(asyncReference
[i
]);
4462 err
= kIOReturnBadArgument
;
4464 if( inputCount
!= method
->count0
)
4466 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4469 if( (kIOUCVariableStructureSize
!= method
->count1
)
4470 && (*outputCount
!= method
->count1
))
4472 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4476 func
= method
->func
;
4478 switch( inputCount
) {
4481 err
= (object
->*func
)( reference
,
4482 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4483 ARG32(input
[3]), ARG32(input
[4]),
4487 err
= (object
->*func
)( reference
,
4488 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4490 output
, (void *)outputCount
);
4493 err
= (object
->*func
)( reference
,
4494 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4495 output
, (void *)outputCount
, 0 );
4498 err
= (object
->*func
)( reference
,
4499 ARG32(input
[0]), ARG32(input
[1]),
4500 output
, (void *)outputCount
, 0, 0 );
4503 err
= (object
->*func
)( reference
,
4505 output
, (void *)outputCount
, 0, 0, 0 );
4508 err
= (object
->*func
)( reference
,
4509 output
, (void *)outputCount
, 0, 0, 0, 0 );
4513 IOLog("%s: Bad method table\n", object
->getName());
4521 /* Routine io_connect_method_scalarI_structureI */
4522 kern_return_t
is_io_connect_method_scalarI_structureI(
4523 io_connect_t connect
,
4525 io_scalar_inband_t input
,
4526 mach_msg_type_number_t inputCount
,
4527 io_struct_inband_t inputStruct
,
4528 mach_msg_type_number_t inputStructCount
)
4531 io_scalar_inband64_t _input
;
4533 mach_msg_type_number_t scalar_outputCnt
= 0;
4534 mach_msg_type_number_t inband_outputCnt
= 0;
4535 mach_vm_size_t ool_output_size
= 0;
4537 for (i
= 0; i
< inputCount
; i
++)
4538 _input
[i
] = SCALAR64(input
[i
]);
4540 return (is_io_connect_method(connect
, index
,
4542 inputStruct
, inputStructCount
,
4544 NULL
, &inband_outputCnt
,
4545 NULL
, &scalar_outputCnt
,
4546 0, &ool_output_size
));
4549 kern_return_t
shim_io_connect_method_scalarI_structureI(
4550 IOExternalMethod
* method
,
4552 const io_user_scalar_t
* input
,
4553 mach_msg_type_number_t inputCount
,
4554 io_struct_inband_t inputStruct
,
4555 mach_msg_type_number_t inputStructCount
)
4558 IOReturn err
= kIOReturnBadArgument
;
4562 if (inputCount
!= method
->count0
)
4564 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4567 if( (kIOUCVariableStructureSize
!= method
->count1
)
4568 && (inputStructCount
!= method
->count1
))
4570 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4574 func
= method
->func
;
4576 switch( inputCount
) {
4579 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4580 ARG32(input
[3]), ARG32(input
[4]),
4584 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4586 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4589 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4590 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4594 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4595 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4599 err
= (object
->*func
)( ARG32(input
[0]),
4600 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4604 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4609 IOLog("%s: Bad method table\n", object
->getName());
4617 kern_return_t
shim_io_async_method_scalarI_structureI(
4618 IOExternalAsyncMethod
* method
,
4620 mach_port_t asyncWakePort
,
4621 io_user_reference_t
* asyncReference
,
4622 uint32_t asyncReferenceCount
,
4623 const io_user_scalar_t
* input
,
4624 mach_msg_type_number_t inputCount
,
4625 io_struct_inband_t inputStruct
,
4626 mach_msg_type_number_t inputStructCount
)
4630 IOReturn err
= kIOReturnBadArgument
;
4631 io_async_ref_t reference
;
4633 for (i
= 0; i
< asyncReferenceCount
; i
++)
4634 reference
[i
] = REF32(asyncReference
[i
]);
4638 if (inputCount
!= method
->count0
)
4640 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4643 if( (kIOUCVariableStructureSize
!= method
->count1
)
4644 && (inputStructCount
!= method
->count1
))
4646 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4650 func
= method
->func
;
4652 switch( inputCount
) {
4655 err
= (object
->*func
)( reference
,
4656 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4657 ARG32(input
[3]), ARG32(input
[4]),
4661 err
= (object
->*func
)( reference
,
4662 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4664 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4667 err
= (object
->*func
)( reference
,
4668 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4669 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4673 err
= (object
->*func
)( reference
,
4674 ARG32(input
[0]), ARG32(input
[1]),
4675 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4679 err
= (object
->*func
)( reference
,
4681 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4685 err
= (object
->*func
)( reference
,
4686 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4691 IOLog("%s: Bad method table\n", object
->getName());
4699 /* Routine io_connect_method_structureI_structureO */
4700 kern_return_t
is_io_connect_method_structureI_structureO(
4701 io_object_t connect
,
4703 io_struct_inband_t input
,
4704 mach_msg_type_number_t inputCount
,
4705 io_struct_inband_t output
,
4706 mach_msg_type_number_t
* outputCount
)
4708 mach_msg_type_number_t scalar_outputCnt
= 0;
4709 mach_vm_size_t ool_output_size
= 0;
4711 return (is_io_connect_method(connect
, index
,
4715 output
, outputCount
,
4716 NULL
, &scalar_outputCnt
,
4717 0, &ool_output_size
));
4720 kern_return_t
shim_io_connect_method_structureI_structureO(
4721 IOExternalMethod
* method
,
4723 io_struct_inband_t input
,
4724 mach_msg_type_number_t inputCount
,
4725 io_struct_inband_t output
,
4726 IOByteCount
* outputCount
)
4729 IOReturn err
= kIOReturnBadArgument
;
4733 if( (kIOUCVariableStructureSize
!= method
->count0
)
4734 && (inputCount
!= method
->count0
))
4736 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4739 if( (kIOUCVariableStructureSize
!= method
->count1
)
4740 && (*outputCount
!= method
->count1
))
4742 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4746 func
= method
->func
;
4748 if( method
->count1
) {
4749 if( method
->count0
) {
4750 err
= (object
->*func
)( input
, output
,
4751 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4753 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4756 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4765 kern_return_t
shim_io_async_method_structureI_structureO(
4766 IOExternalAsyncMethod
* method
,
4768 mach_port_t asyncWakePort
,
4769 io_user_reference_t
* asyncReference
,
4770 uint32_t asyncReferenceCount
,
4771 io_struct_inband_t input
,
4772 mach_msg_type_number_t inputCount
,
4773 io_struct_inband_t output
,
4774 mach_msg_type_number_t
* outputCount
)
4779 io_async_ref_t reference
;
4781 for (i
= 0; i
< asyncReferenceCount
; i
++)
4782 reference
[i
] = REF32(asyncReference
[i
]);
4784 err
= kIOReturnBadArgument
;
4787 if( (kIOUCVariableStructureSize
!= method
->count0
)
4788 && (inputCount
!= method
->count0
))
4790 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4793 if( (kIOUCVariableStructureSize
!= method
->count1
)
4794 && (*outputCount
!= method
->count1
))
4796 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4800 func
= method
->func
;
4802 if( method
->count1
) {
4803 if( method
->count0
) {
4804 err
= (object
->*func
)( reference
,
4806 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4808 err
= (object
->*func
)( reference
,
4809 output
, outputCount
, 0, 0, 0, 0 );
4812 err
= (object
->*func
)( reference
,
4813 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4821 /* Routine io_catalog_send_data */
4822 kern_return_t
is_io_catalog_send_data(
4823 mach_port_t master_port
,
4825 io_buf_ptr_t inData
,
4826 mach_msg_type_number_t inDataCount
,
4827 kern_return_t
* result
)
4831 kern_return_t kr
= kIOReturnError
;
4833 //printf("io_catalog_send_data called. flag: %d\n", flag);
4835 if( master_port
!= master_device_port
)
4836 return kIOReturnNotPrivileged
;
4838 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4839 flag
!= kIOCatalogKextdActive
&&
4840 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4841 ( !inData
|| !inDataCount
) )
4843 return kIOReturnBadArgument
;
4847 vm_map_offset_t map_data
;
4849 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4850 return( kIOReturnMessageTooLarge
);
4852 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4853 data
= CAST_DOWN(vm_offset_t
, map_data
);
4855 if( kr
!= KERN_SUCCESS
)
4858 // must return success after vm_map_copyout() succeeds
4861 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4862 vm_deallocate( kernel_map
, data
, inDataCount
);
4864 *result
= kIOReturnNoMemory
;
4865 return( KERN_SUCCESS
);
4871 case kIOCatalogResetDrivers
:
4872 case kIOCatalogResetDriversNoMatch
: {
4875 array
= OSDynamicCast(OSArray
, obj
);
4877 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4878 flag
== kIOCatalogResetDrivers
) ) {
4880 kr
= kIOReturnError
;
4883 kr
= kIOReturnBadArgument
;
4888 case kIOCatalogAddDrivers
:
4889 case kIOCatalogAddDriversNoMatch
: {
4892 array
= OSDynamicCast(OSArray
, obj
);
4894 if ( !gIOCatalogue
->addDrivers( array
,
4895 flag
== kIOCatalogAddDrivers
) ) {
4896 kr
= kIOReturnError
;
4900 kr
= kIOReturnBadArgument
;
4905 case kIOCatalogRemoveDrivers
:
4906 case kIOCatalogRemoveDriversNoMatch
: {
4907 OSDictionary
* dict
;
4909 dict
= OSDynamicCast(OSDictionary
, obj
);
4911 if ( !gIOCatalogue
->removeDrivers( dict
,
4912 flag
== kIOCatalogRemoveDrivers
) ) {
4913 kr
= kIOReturnError
;
4917 kr
= kIOReturnBadArgument
;
4922 case kIOCatalogStartMatching
: {
4923 OSDictionary
* dict
;
4925 dict
= OSDynamicCast(OSDictionary
, obj
);
4927 if ( !gIOCatalogue
->startMatching( dict
) ) {
4928 kr
= kIOReturnError
;
4932 kr
= kIOReturnBadArgument
;
4937 case kIOCatalogRemoveKernelLinker
:
4938 kr
= KERN_NOT_SUPPORTED
;
4941 case kIOCatalogKextdActive
:
4943 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
4944 OSKext::setKextdActive();
4946 /* Dump all nonloaded startup extensions; kextd will now send them
4949 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4951 kr
= kIOReturnSuccess
;
4954 case kIOCatalogKextdFinishedLaunching
: {
4956 static bool clearedBusy
= false;
4959 IOService
* serviceRoot
= IOService::getServiceRoot();
4961 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
4962 serviceRoot
->adjustBusy(-1);
4967 kr
= kIOReturnSuccess
;
4972 kr
= kIOReturnBadArgument
;
4976 if (obj
) obj
->release();
4979 return( KERN_SUCCESS
);
4982 /* Routine io_catalog_terminate */
4983 kern_return_t
is_io_catalog_terminate(
4984 mach_port_t master_port
,
4990 if( master_port
!= master_device_port
)
4991 return kIOReturnNotPrivileged
;
4993 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
4994 kIOClientPrivilegeAdministrator
);
4995 if( kIOReturnSuccess
!= kr
)
4999 #if !defined(SECURE_KERNEL)
5000 case kIOCatalogServiceTerminate
:
5002 IOService
* service
;
5004 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
5005 kIORegistryIterateRecursively
);
5007 return kIOReturnNoMemory
;
5011 while( (service
= (IOService
*)iter
->getNextObject()) ) {
5012 if( service
->metaCast(name
)) {
5013 if ( !service
->terminate( kIOServiceRequired
5014 | kIOServiceSynchronous
) ) {
5015 kr
= kIOReturnUnsupported
;
5020 } while( !service
&& !iter
->isValid());
5024 case kIOCatalogModuleUnload
:
5025 case kIOCatalogModuleTerminate
:
5026 kr
= gIOCatalogue
->terminateDriversForModule(name
,
5027 flag
== kIOCatalogModuleUnload
);
5032 kr
= kIOReturnBadArgument
;
5039 /* Routine io_catalog_get_data */
5040 kern_return_t
is_io_catalog_get_data(
5041 mach_port_t master_port
,
5043 io_buf_ptr_t
*outData
,
5044 mach_msg_type_number_t
*outDataCount
)
5046 kern_return_t kr
= kIOReturnSuccess
;
5049 if( master_port
!= master_device_port
)
5050 return kIOReturnNotPrivileged
;
5052 //printf("io_catalog_get_data called. flag: %d\n", flag);
5054 s
= OSSerialize::withCapacity(4096);
5056 return kIOReturnNoMemory
;
5058 kr
= gIOCatalogue
->serializeData(flag
, s
);
5060 if ( kr
== kIOReturnSuccess
) {
5065 size
= s
->getLength();
5066 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
5067 if ( kr
== kIOReturnSuccess
) {
5068 bcopy(s
->text(), (void *)data
, size
);
5069 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
5070 (vm_map_size_t
)size
, true, ©
);
5071 *outData
= (char *)copy
;
5072 *outDataCount
= size
;
5081 /* Routine io_catalog_get_gen_count */
5082 kern_return_t
is_io_catalog_get_gen_count(
5083 mach_port_t master_port
,
5086 if( master_port
!= master_device_port
)
5087 return kIOReturnNotPrivileged
;
5089 //printf("io_catalog_get_gen_count called.\n");
5092 return kIOReturnBadArgument
;
5094 *genCount
= gIOCatalogue
->getGenerationCount();
5096 return kIOReturnSuccess
;
5099 /* Routine io_catalog_module_loaded.
5100 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
5102 kern_return_t
is_io_catalog_module_loaded(
5103 mach_port_t master_port
,
5106 if( master_port
!= master_device_port
)
5107 return kIOReturnNotPrivileged
;
5109 //printf("io_catalog_module_loaded called. name %s\n", name);
5112 return kIOReturnBadArgument
;
5114 gIOCatalogue
->moduleHasLoaded(name
);
5116 return kIOReturnSuccess
;
5119 kern_return_t
is_io_catalog_reset(
5120 mach_port_t master_port
,
5123 if( master_port
!= master_device_port
)
5124 return kIOReturnNotPrivileged
;
5127 case kIOCatalogResetDefault
:
5128 gIOCatalogue
->reset();
5132 return kIOReturnBadArgument
;
5135 return kIOReturnSuccess
;
5138 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5140 kern_return_t result
= kIOReturnBadArgument
;
5141 IOUserClient
*userClient
;
5143 if ((userClient
= OSDynamicCast(IOUserClient
,
5144 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
5145 IOExternalTrap
*trap
;
5146 IOService
*target
= NULL
;
5148 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5150 if (trap
&& target
) {
5156 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5160 iokit_remove_connect_reference(userClient
);
5168 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5169 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5173 IOByteCount structureOutputSize
;
5178 count
= dispatch
->checkScalarInputCount
;
5179 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
5181 return (kIOReturnBadArgument
);
5184 count
= dispatch
->checkStructureInputSize
;
5185 if ((kIOUCVariableStructureSize
!= count
)
5186 && (count
!= ((args
->structureInputDescriptor
)
5187 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
5189 return (kIOReturnBadArgument
);
5192 count
= dispatch
->checkScalarOutputCount
;
5193 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
5195 return (kIOReturnBadArgument
);
5198 count
= dispatch
->checkStructureOutputSize
;
5199 if ((kIOUCVariableStructureSize
!= count
)
5200 && (count
!= ((args
->structureOutputDescriptor
)
5201 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
5203 return (kIOReturnBadArgument
);
5206 if (dispatch
->function
)
5207 err
= (*dispatch
->function
)(target
, reference
, args
);
5209 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5215 // pre-Leopard API's don't do ool structs
5216 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
5218 err
= kIOReturnIPCError
;
5222 structureOutputSize
= args
->structureOutputSize
;
5224 if (args
->asyncWakePort
)
5226 IOExternalAsyncMethod
* method
;
5228 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
5229 return (kIOReturnUnsupported
);
5231 if (kIOUCForegroundOnly
& method
->flags
)
5233 if (task_is_gpu_denied(current_task()))
5234 return (kIOReturnNotPermitted
);
5237 switch (method
->flags
& kIOUCTypeMask
)
5239 case kIOUCScalarIStructI
:
5240 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5241 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5242 args
->scalarInput
, args
->scalarInputCount
,
5243 (char *)args
->structureInput
, args
->structureInputSize
);
5246 case kIOUCScalarIScalarO
:
5247 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5248 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5249 args
->scalarInput
, args
->scalarInputCount
,
5250 args
->scalarOutput
, &args
->scalarOutputCount
);
5253 case kIOUCScalarIStructO
:
5254 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5255 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5256 args
->scalarInput
, args
->scalarInputCount
,
5257 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5261 case kIOUCStructIStructO
:
5262 err
= shim_io_async_method_structureI_structureO( method
, object
,
5263 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5264 (char *)args
->structureInput
, args
->structureInputSize
,
5265 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5269 err
= kIOReturnBadArgument
;
5275 IOExternalMethod
* method
;
5277 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
5278 return (kIOReturnUnsupported
);
5280 if (kIOUCForegroundOnly
& method
->flags
)
5282 if (task_is_gpu_denied(current_task()))
5283 return (kIOReturnNotPermitted
);
5286 switch (method
->flags
& kIOUCTypeMask
)
5288 case kIOUCScalarIStructI
:
5289 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5290 args
->scalarInput
, args
->scalarInputCount
,
5291 (char *) args
->structureInput
, args
->structureInputSize
);
5294 case kIOUCScalarIScalarO
:
5295 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5296 args
->scalarInput
, args
->scalarInputCount
,
5297 args
->scalarOutput
, &args
->scalarOutputCount
);
5300 case kIOUCScalarIStructO
:
5301 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5302 args
->scalarInput
, args
->scalarInputCount
,
5303 (char *) args
->structureOutput
, &structureOutputSize
);
5307 case kIOUCStructIStructO
:
5308 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5309 (char *) args
->structureInput
, args
->structureInputSize
,
5310 (char *) args
->structureOutput
, &structureOutputSize
);
5314 err
= kIOReturnBadArgument
;
5319 args
->structureOutputSize
= structureOutputSize
;
5325 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5326 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5328 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5329 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5331 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5332 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5333 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5334 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5335 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5336 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5337 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5338 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5339 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5340 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5341 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5342 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5343 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5344 OSMetaClassDefineReservedUnused(IOUserClient
, 15);