2 * Copyright (c) 1998-2012 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>
50 #include <security/mac_framework.h>
52 #include <sys/kauth.h>
56 #endif /* CONFIG_MACF */
58 #include <IOKit/assert.h>
60 #include "IOServicePrivate.h"
61 #include "IOKitKernelInternal.h"
63 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
64 #define SCALAR32(x) ((uint32_t )x)
65 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
66 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
67 #define REF32(x) ((int)(x))
71 kIOUCAsync0Flags
= 3ULL,
72 kIOUCAsync64Flag
= 1ULL
77 #define IOStatisticsRegisterCounter() \
79 reserved->counter = IOStatistics::registerUserClient(this); \
82 #define IOStatisticsUnregisterCounter() \
85 IOStatistics::unregisterUserClient(reserved->counter); \
88 #define IOStatisticsClientCall() \
90 IOStatistics::countUserClientCall(client); \
95 #define IOStatisticsRegisterCounter()
96 #define IOStatisticsUnregisterCounter()
97 #define IOStatisticsClientCall()
99 #endif /* IOKITSTATS */
101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103 // definitions we should get from osfmk
105 //typedef struct ipc_port * ipc_port_t;
106 typedef natural_t ipc_kobject_type_t
;
108 #define IKOT_IOKIT_SPARE 27
109 #define IKOT_IOKIT_CONNECT 29
110 #define IKOT_IOKIT_OBJECT 30
114 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
115 ipc_kobject_type_t type
);
117 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
119 extern mach_port_name_t
iokit_make_send_right( task_t task
,
120 io_object_t obj
, ipc_kobject_type_t type
);
122 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
124 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
126 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
128 extern ipc_port_t master_device_port
;
130 extern void iokit_retain_port( ipc_port_t port
);
131 extern void iokit_release_port( ipc_port_t port
);
132 extern void iokit_release_port_send( ipc_port_t port
);
134 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
136 #include <mach/mach_traps.h>
137 #include <vm/vm_map.h>
142 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
144 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
146 class IOMachPort
: public OSObject
148 OSDeclareDefaultStructors(IOMachPort
)
155 static IOMachPort
* portForObject( OSObject
* obj
,
156 ipc_kobject_type_t type
);
157 static bool noMoreSendersForObject( OSObject
* obj
,
158 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
159 static void releasePortForObject( OSObject
* obj
,
160 ipc_kobject_type_t type
);
161 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
163 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
165 static mach_port_name_t
makeSendRightForTask( task_t task
,
166 io_object_t obj
, ipc_kobject_type_t type
);
171 #define super OSObject
172 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
174 static IOLock
* gIOObjectPortLock
;
176 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
178 // not in dictForType() for debugging ease
179 static OSDictionary
* gIOObjectPorts
;
180 static OSDictionary
* gIOConnectPorts
;
182 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
184 OSDictionary
** dict
;
186 if( IKOT_IOKIT_OBJECT
== type
)
187 dict
= &gIOObjectPorts
;
188 else if( IKOT_IOKIT_CONNECT
== type
)
189 dict
= &gIOConnectPorts
;
194 *dict
= OSDictionary::withCapacity( 1 );
199 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
200 ipc_kobject_type_t type
)
202 IOMachPort
* inst
= 0;
205 IOTakeLock( gIOObjectPortLock
);
209 dict
= dictForType( type
);
213 if( (inst
= (IOMachPort
*)
214 dict
->getObject( (const OSSymbol
*) obj
))) {
220 inst
= new IOMachPort
;
221 if( inst
&& !inst
->init()) {
226 inst
->port
= iokit_alloc_object_port( obj
, type
);
229 dict
->setObject( (const OSSymbol
*) obj
, inst
);
239 IOUnlock( gIOObjectPortLock
);
244 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
245 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
248 IOMachPort
* machPort
;
249 bool destroyed
= true;
251 IOTakeLock( gIOObjectPortLock
);
253 if( (dict
= dictForType( type
))) {
256 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
258 destroyed
= (machPort
->mscount
<= *mscount
);
260 dict
->removeObject( (const OSSymbol
*) obj
);
262 *mscount
= machPort
->mscount
;
267 IOUnlock( gIOObjectPortLock
);
272 void IOMachPort::releasePortForObject( OSObject
* obj
,
273 ipc_kobject_type_t type
)
276 IOMachPort
* machPort
;
278 IOTakeLock( gIOObjectPortLock
);
280 if( (dict
= dictForType( type
))) {
282 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
283 if( machPort
&& !machPort
->holdDestroy
)
284 dict
->removeObject( (const OSSymbol
*) obj
);
288 IOUnlock( gIOObjectPortLock
);
291 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
294 IOMachPort
* machPort
;
296 IOLockLock( gIOObjectPortLock
);
298 if( (dict
= dictForType( type
))) {
299 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
301 machPort
->holdDestroy
= true;
304 IOLockUnlock( gIOObjectPortLock
);
307 void IOUserClient::destroyUserReferences( OSObject
* obj
)
309 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
312 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
316 IOTakeLock( gIOObjectPortLock
);
319 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
322 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
326 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
328 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
329 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
331 uc
->mappings
->release();
334 dict
->removeObject( (const OSSymbol
*) obj
);
338 IOUnlock( gIOObjectPortLock
);
341 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
342 io_object_t obj
, ipc_kobject_type_t type
)
344 return( iokit_make_send_right( task
, obj
, type
));
347 void IOMachPort::free( void )
350 iokit_destroy_object_port( port
);
354 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
356 class IOUserNotification
: public OSIterator
358 OSDeclareDefaultStructors(IOUserNotification
)
360 IONotifier
* holdNotify
;
365 virtual bool init( void );
368 virtual void setNotification( IONotifier
* obj
);
370 virtual void reset();
371 virtual bool isValid();
374 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
378 // functions called from osfmk/device/iokit_rpc.c
381 iokit_add_reference( io_object_t obj
)
388 iokit_remove_reference( io_object_t obj
)
395 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
397 IOMachPort
* machPort
;
400 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
402 port
= machPort
->port
;
404 iokit_retain_port( port
);
415 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
416 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
418 IOUserClient
* client
;
420 IOUserNotification
* notify
;
422 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
423 return( kIOReturnNotReady
);
425 if( IKOT_IOKIT_CONNECT
== type
)
427 if( (client
= OSDynamicCast( IOUserClient
, obj
))) {
428 IOStatisticsClientCall();
429 client
->clientDied();
432 else if( IKOT_IOKIT_OBJECT
== type
)
434 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
436 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
437 notify
->setNotification( 0 );
440 return( kIOReturnSuccess
);
445 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
447 class IOServiceUserNotification
: public IOUserNotification
449 OSDeclareDefaultStructors(IOServiceUserNotification
)
452 mach_msg_header_t msgHdr
;
453 OSNotificationHeader64 notifyHeader
;
456 enum { kMaxOutstanding
= 1024 };
461 OSObject
* lastEntry
;
466 virtual bool init( mach_port_t port
, natural_t type
,
467 void * reference
, vm_size_t referenceSize
,
471 static bool _handler( void * target
,
472 void * ref
, IOService
* newService
, IONotifier
* notifier
);
473 virtual bool handler( void * ref
, IOService
* newService
);
475 virtual OSObject
* getNextObject();
478 class IOServiceMessageUserNotification
: public IOUserNotification
480 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
483 mach_msg_header_t msgHdr
;
484 mach_msg_body_t msgBody
;
485 mach_msg_port_descriptor_t ports
[1];
486 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
496 virtual bool init( mach_port_t port
, natural_t type
,
497 void * reference
, vm_size_t referenceSize
,
503 static IOReturn
_handler( void * target
, void * ref
,
504 UInt32 messageType
, IOService
* provider
,
505 void * messageArgument
, vm_size_t argSize
);
506 virtual IOReturn
handler( void * ref
,
507 UInt32 messageType
, IOService
* provider
,
508 void * messageArgument
, vm_size_t argSize
);
510 virtual OSObject
* getNextObject();
513 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
516 #define super OSIterator
517 OSDefineMetaClass( IOUserNotification
, OSIterator
)
518 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
520 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
522 bool IOUserNotification::init( void )
527 lock
= IOLockAlloc();
534 void IOUserNotification::free( void )
537 holdNotify
->remove();
538 // can't be in handler now
547 void IOUserNotification::setNotification( IONotifier
* notify
)
549 IONotifier
* previousNotify
;
551 IOLockLock( gIOObjectPortLock
);
553 previousNotify
= holdNotify
;
556 IOLockUnlock( gIOObjectPortLock
);
559 previousNotify
->remove();
562 void IOUserNotification::reset()
567 bool IOUserNotification::isValid()
572 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
575 #define super IOUserNotification
576 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
578 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
580 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
581 void * reference
, vm_size_t referenceSize
,
587 newSet
= OSArray::withCapacity( 1 );
591 if (referenceSize
> sizeof(OSAsyncReference64
))
594 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
595 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
599 bzero( pingMsg
, msgSize
);
601 pingMsg
->msgHdr
.msgh_remote_port
= port
;
602 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
603 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
604 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
605 pingMsg
->msgHdr
.msgh_size
= msgSize
;
606 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
608 pingMsg
->notifyHeader
.size
= 0;
609 pingMsg
->notifyHeader
.type
= type
;
610 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
615 void IOServiceUserNotification::free( void )
620 OSObject
* _lastEntry
;
624 _lastEntry
= lastEntry
;
629 if( _pingMsg
&& _msgSize
) {
630 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
631 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
633 IOFree(_pingMsg
, _msgSize
);
637 _lastEntry
->release();
643 bool IOServiceUserNotification::_handler( void * target
,
644 void * ref
, IOService
* newService
, IONotifier
* notifier
)
646 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
649 bool IOServiceUserNotification::handler( void * ref
,
650 IOService
* newService
)
654 ipc_port_t port
= NULL
;
655 bool sendPing
= false;
659 count
= newSet
->getCount();
660 if( count
< kMaxOutstanding
) {
662 newSet
->setObject( newService
);
663 if( (sendPing
= (armed
&& (0 == count
))))
669 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
670 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
673 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
674 pingMsg
->msgHdr
.msgh_local_port
= port
;
676 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
678 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
679 pingMsg
->msgHdr
.msgh_size
,
680 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
683 iokit_release_port( port
);
685 if( KERN_SUCCESS
!= kr
)
686 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
692 OSObject
* IOServiceUserNotification::getNextObject()
700 lastEntry
->release();
702 count
= newSet
->getCount();
704 result
= newSet
->getObject( count
- 1 );
706 newSet
->removeObject( count
- 1);
718 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
720 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
722 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
724 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
725 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
731 if (referenceSize
> sizeof(OSAsyncReference64
))
734 clientIs64
= client64
;
736 owningPID
= proc_selfpid();
738 extraSize
+= sizeof(IOServiceInterestContent64
);
739 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
+ extraSize
;
740 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
744 bzero( pingMsg
, msgSize
);
746 pingMsg
->msgHdr
.msgh_remote_port
= port
;
747 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
749 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
750 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
751 pingMsg
->msgHdr
.msgh_size
= msgSize
;
752 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
754 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
756 pingMsg
->ports
[0].name
= 0;
757 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
758 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
760 pingMsg
->notifyHeader
.size
= extraSize
;
761 pingMsg
->notifyHeader
.type
= type
;
762 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
767 void IOServiceMessageUserNotification::free( void )
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 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
786 UInt32 messageType
, IOService
* provider
,
787 void * argument
, vm_size_t argSize
)
789 return( ((IOServiceMessageUserNotification
*) target
)->handler(
790 ref
, messageType
, provider
, argument
, argSize
));
793 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
794 UInt32 messageType
, IOService
* provider
,
795 void * messageArgument
, vm_size_t argSize
)
798 ipc_port_t thisPort
, providerPort
;
799 IOServiceInterestContent64
* data
= (IOServiceInterestContent64
*)
800 ((((uint8_t *) pingMsg
) + msgSize
) - pingMsg
->notifyHeader
.size
);
801 // == pingMsg->notifyHeader.content;
803 if (kIOMessageCopyClientID
== messageType
)
805 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
806 return (kIOReturnSuccess
);
809 data
->messageType
= messageType
;
813 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
815 argSize
= sizeof(data
->messageArgument
[0]);
818 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
819 argSize
= sizeof(uint32_t);
824 if( argSize
> kIOUserNotifyMaxMessageSize
)
825 argSize
= kIOUserNotifyMaxMessageSize
;
826 bcopy( messageArgument
, data
->messageArgument
, argSize
);
828 pingMsg
->msgHdr
.msgh_size
= msgSize
- pingMsg
->notifyHeader
.size
829 + sizeof( IOServiceInterestContent64
)
830 - sizeof( data
->messageArgument
)
833 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
834 pingMsg
->ports
[0].name
= providerPort
;
835 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
836 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
837 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
838 pingMsg
->msgHdr
.msgh_size
,
839 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
842 iokit_release_port( thisPort
);
844 iokit_release_port( providerPort
);
846 if( KERN_SUCCESS
!= kr
)
847 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
849 return( kIOReturnSuccess
);
852 OSObject
* IOServiceMessageUserNotification::getNextObject()
857 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
860 #define super IOService
861 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
863 void IOUserClient::initialize( void )
865 gIOObjectPortLock
= IOLockAlloc();
867 assert( gIOObjectPortLock
);
870 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
871 mach_port_t wakePort
,
872 void *callback
, void *refcon
)
874 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
875 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
876 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
877 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
880 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
881 mach_port_t wakePort
,
882 mach_vm_address_t callback
, io_user_reference_t refcon
)
884 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
885 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
886 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
887 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
890 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
891 mach_port_t wakePort
,
892 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
894 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
895 if (vm_map_is_64bit(get_task_map(task
))) {
896 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
900 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
903 OSDictionary
* user
= 0;
905 if ((array
= OSDynamicCast(OSArray
,
906 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
908 for (unsigned int idx
= 0;
909 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
913 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
914 && (uid
== num
->unsigned32BitValue())) {
924 static OSDictionary
* CopyUserOnConsole(void)
927 OSDictionary
* user
= 0;
929 if ((array
= OSDynamicCast(OSArray
,
930 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
932 for (unsigned int idx
= 0;
933 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
936 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
947 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
948 const char * privilegeName
)
951 security_token_t token
;
952 mach_msg_type_number_t count
;
958 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
959 sizeof(kIOClientPrivilegeForeground
)))
961 /* is graphics access denied for current task? */
962 if (proc_get_effective_task_policy(current_task(), TASK_POLICY_GPU_DENY
) != 0)
963 return (kIOReturnNotPrivileged
);
965 return (kIOReturnSuccess
);
968 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
969 sizeof(kIOClientPrivilegeConsoleSession
)))
974 task
= (task_t
) securityToken
;
976 task
= current_task();
977 p
= (proc_t
) get_bsdtask_info(task
);
978 kr
= kIOReturnNotPrivileged
;
980 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
982 user
= CopyUserOnConsole();
986 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
987 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
989 kr
= kIOReturnSuccess
;
993 kauth_cred_unref(&cred
);
998 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
999 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1000 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1002 task
= (task_t
)securityToken
;
1004 count
= TASK_SECURITY_TOKEN_COUNT
;
1005 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1007 if (KERN_SUCCESS
!= kr
)
1009 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1010 sizeof(kIOClientPrivilegeAdministrator
))) {
1011 if (0 != token
.val
[0])
1012 kr
= kIOReturnNotPrivileged
;
1013 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1014 sizeof(kIOClientPrivilegeLocalUser
))) {
1015 user
= CopyConsoleUser(token
.val
[0]);
1019 kr
= kIOReturnNotPrivileged
;
1020 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1021 sizeof(kIOClientPrivilegeConsoleUser
))) {
1022 user
= CopyConsoleUser(token
.val
[0]);
1024 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1025 kr
= kIOReturnNotPrivileged
;
1026 else if ( secureConsole
) {
1027 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1028 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1029 kr
= kIOReturnNotPrivileged
;
1034 kr
= kIOReturnNotPrivileged
;
1036 kr
= kIOReturnUnsupported
;
1041 bool IOUserClient::init()
1043 if (getPropertyTable() || super::init())
1049 bool IOUserClient::init(OSDictionary
* dictionary
)
1051 if (getPropertyTable() || super::init(dictionary
))
1057 bool IOUserClient::initWithTask(task_t owningTask
,
1061 if (getPropertyTable() || super::init())
1067 bool IOUserClient::initWithTask(task_t owningTask
,
1070 OSDictionary
* properties
)
1074 ok
= super::init( properties
);
1075 ok
&= initWithTask( owningTask
, securityID
, type
);
1080 bool IOUserClient::reserve()
1083 reserved
= IONew(ExpansionData
, 1);
1088 setTerminateDefer(NULL
, true);
1089 IOStatisticsRegisterCounter();
1094 void IOUserClient::free()
1097 mappings
->release();
1099 IOStatisticsUnregisterCounter();
1102 IODelete(reserved
, ExpansionData
, 1);
1107 IOReturn
IOUserClient::clientDied( void )
1109 return( clientClose());
1112 IOReturn
IOUserClient::clientClose( void )
1114 return( kIOReturnUnsupported
);
1117 IOService
* IOUserClient::getService( void )
1122 IOReturn
IOUserClient::registerNotificationPort(
1123 mach_port_t
/* port */,
1125 UInt32
/* refCon */)
1127 return( kIOReturnUnsupported
);
1130 IOReturn
IOUserClient::registerNotificationPort(
1133 io_user_reference_t refCon
)
1135 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1138 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1139 semaphore_t
* semaphore
)
1141 return( kIOReturnUnsupported
);
1144 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1146 return( kIOReturnUnsupported
);
1149 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1150 IOOptionBits
* options
,
1151 IOMemoryDescriptor
** memory
)
1153 return( kIOReturnUnsupported
);
1157 IOMemoryMap
* IOUserClient::mapClientMemory(
1160 IOOptionBits mapFlags
,
1161 IOVirtualAddress atAddress
)
1167 IOMemoryMap
* IOUserClient::mapClientMemory64(
1170 IOOptionBits mapFlags
,
1171 mach_vm_address_t atAddress
)
1174 IOOptionBits options
= 0;
1175 IOMemoryDescriptor
* memory
;
1176 IOMemoryMap
* map
= 0;
1178 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1180 if( memory
&& (kIOReturnSuccess
== err
)) {
1182 options
= (options
& ~kIOMapUserOptionsMask
)
1183 | (mapFlags
& kIOMapUserOptionsMask
);
1184 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1191 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1192 OSObject
*obj
, io_object_t
*clientObj
)
1194 mach_port_name_t name
;
1196 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1198 *(mach_port_name_t
*)clientObj
= name
;
1199 return kIOReturnSuccess
;
1202 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1207 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1212 IOExternalMethod
* IOUserClient::
1213 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1215 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1218 *targetP
= (IOService
*) method
->object
;
1223 IOExternalAsyncMethod
* IOUserClient::
1224 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1226 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1229 *targetP
= (IOService
*) method
->object
;
1234 IOExternalTrap
* IOUserClient::
1235 getExternalTrapForIndex(UInt32 index
)
1240 IOExternalTrap
* IOUserClient::
1241 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1243 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1246 *targetP
= trap
->object
;
1252 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1255 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1257 if (MACH_PORT_NULL
!= port
)
1258 iokit_release_port_send(port
);
1260 return (kIOReturnSuccess
);
1263 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1265 if (MACH_PORT_NULL
!= port
)
1266 iokit_release_port_send(port
);
1268 return (kIOReturnSuccess
);
1271 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1272 IOReturn result
, void *args
[], UInt32 numArgs
)
1274 OSAsyncReference64 reference64
;
1275 io_user_reference_t args64
[kMaxAsyncArgs
];
1278 if (numArgs
> kMaxAsyncArgs
)
1279 return kIOReturnMessageTooLarge
;
1281 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1282 reference64
[idx
] = REF64(reference
[idx
]);
1284 for (idx
= 0; idx
< numArgs
; idx
++)
1285 args64
[idx
] = REF64(args
[idx
]);
1287 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1290 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1291 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1293 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1296 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1297 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1299 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1302 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1303 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1307 mach_msg_header_t msgHdr
;
1312 OSNotificationHeader notifyHdr
;
1313 IOAsyncCompletionContent asyncContent
;
1314 uint32_t args
[kMaxAsyncArgs
];
1318 OSNotificationHeader64 notifyHdr
;
1319 IOAsyncCompletionContent asyncContent
;
1320 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1325 mach_port_t replyPort
;
1328 // If no reply port, do nothing.
1329 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1330 if (replyPort
== MACH_PORT_NULL
)
1331 return kIOReturnSuccess
;
1333 if (numArgs
> kMaxAsyncArgs
)
1334 return kIOReturnMessageTooLarge
;
1336 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1338 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1339 replyMsg
.msgHdr
.msgh_local_port
= 0;
1340 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1341 if (kIOUCAsync64Flag
& reference
[0])
1343 replyMsg
.msgHdr
.msgh_size
=
1344 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1345 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1346 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1347 + numArgs
* sizeof(io_user_reference_t
);
1348 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1349 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1351 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1353 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1359 replyMsg
.msgHdr
.msgh_size
=
1360 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1361 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1363 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1364 + numArgs
* sizeof(uint32_t);
1365 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1367 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1368 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1370 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1372 for (idx
= 0; idx
< numArgs
; idx
++)
1373 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1376 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1377 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1378 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1380 /* Fail on full queue. */
1381 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1382 replyMsg
.msgHdr
.msgh_size
);
1384 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
))
1385 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1390 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1394 #define CHECK(cls,obj,out) \
1396 if( !(out = OSDynamicCast( cls, obj))) \
1397 return( kIOReturnBadArgument )
1399 /* Routine io_object_get_class */
1400 kern_return_t
is_io_object_get_class(
1402 io_name_t className
)
1404 const OSMetaClass
* my_obj
= NULL
;
1407 return( kIOReturnBadArgument
);
1409 my_obj
= object
->getMetaClass();
1411 return (kIOReturnNotFound
);
1414 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1415 return( kIOReturnSuccess
);
1418 /* Routine io_object_get_superclass */
1419 kern_return_t
is_io_object_get_superclass(
1420 mach_port_t master_port
,
1422 io_name_t class_name
)
1424 const OSMetaClass
* my_obj
= NULL
;
1425 const OSMetaClass
* superclass
= NULL
;
1426 const OSSymbol
*my_name
= NULL
;
1427 const char *my_cstr
= NULL
;
1429 if (!obj_name
|| !class_name
)
1430 return (kIOReturnBadArgument
);
1432 if( master_port
!= master_device_port
)
1433 return( kIOReturnNotPrivileged
);
1435 my_name
= OSSymbol::withCString(obj_name
);
1438 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1442 superclass
= my_obj
->getSuperClass();
1446 return( kIOReturnNotFound
);
1449 my_cstr
= superclass
->getClassName();
1452 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1453 return( kIOReturnSuccess
);
1455 return (kIOReturnNotFound
);
1458 /* Routine io_object_get_bundle_identifier */
1459 kern_return_t
is_io_object_get_bundle_identifier(
1460 mach_port_t master_port
,
1462 io_name_t bundle_name
)
1464 const OSMetaClass
* my_obj
= NULL
;
1465 const OSSymbol
*my_name
= NULL
;
1466 const OSSymbol
*identifier
= NULL
;
1467 const char *my_cstr
= NULL
;
1469 if (!obj_name
|| !bundle_name
)
1470 return (kIOReturnBadArgument
);
1472 if( master_port
!= master_device_port
)
1473 return( kIOReturnNotPrivileged
);
1475 my_name
= OSSymbol::withCString(obj_name
);
1478 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1483 identifier
= my_obj
->getKmodName();
1486 return( kIOReturnNotFound
);
1489 my_cstr
= identifier
->getCStringNoCopy();
1491 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1492 return( kIOReturnSuccess
);
1495 return (kIOReturnBadArgument
);
1498 /* Routine io_object_conforms_to */
1499 kern_return_t
is_io_object_conforms_to(
1501 io_name_t className
,
1502 boolean_t
*conforms
)
1505 return( kIOReturnBadArgument
);
1507 *conforms
= (0 != object
->metaCast( className
));
1508 return( kIOReturnSuccess
);
1511 /* Routine io_object_get_retain_count */
1512 kern_return_t
is_io_object_get_retain_count(
1514 uint32_t *retainCount
)
1517 return( kIOReturnBadArgument
);
1519 *retainCount
= object
->getRetainCount();
1520 return( kIOReturnSuccess
);
1523 /* Routine io_iterator_next */
1524 kern_return_t
is_io_iterator_next(
1525 io_object_t iterator
,
1526 io_object_t
*object
)
1530 CHECK( OSIterator
, iterator
, iter
);
1532 obj
= iter
->getNextObject();
1536 return( kIOReturnSuccess
);
1538 return( kIOReturnNoDevice
);
1541 /* Routine io_iterator_reset */
1542 kern_return_t
is_io_iterator_reset(
1543 io_object_t iterator
)
1545 CHECK( OSIterator
, iterator
, iter
);
1549 return( kIOReturnSuccess
);
1552 /* Routine io_iterator_is_valid */
1553 kern_return_t
is_io_iterator_is_valid(
1554 io_object_t iterator
,
1555 boolean_t
*is_valid
)
1557 CHECK( OSIterator
, iterator
, iter
);
1559 *is_valid
= iter
->isValid();
1561 return( kIOReturnSuccess
);
1564 /* Routine io_service_match_property_table */
1565 kern_return_t
is_io_service_match_property_table(
1566 io_service_t _service
,
1567 io_string_t matching
,
1568 boolean_t
*matches
)
1570 CHECK( IOService
, _service
, service
);
1574 OSDictionary
* dict
;
1576 obj
= OSUnserializeXML( matching
);
1578 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1579 *matches
= service
->passiveMatch( dict
);
1580 kr
= kIOReturnSuccess
;
1582 kr
= kIOReturnBadArgument
;
1590 /* Routine io_service_match_property_table_ool */
1591 kern_return_t
is_io_service_match_property_table_ool(
1592 io_object_t service
,
1593 io_buf_ptr_t matching
,
1594 mach_msg_type_number_t matchingCnt
,
1595 kern_return_t
*result
,
1596 boolean_t
*matches
)
1600 vm_map_offset_t map_data
;
1602 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1603 data
= CAST_DOWN(vm_offset_t
, map_data
);
1605 if( KERN_SUCCESS
== kr
) {
1606 // must return success after vm_map_copyout() succeeds
1607 *result
= is_io_service_match_property_table( service
,
1608 (char *) data
, matches
);
1609 vm_deallocate( kernel_map
, data
, matchingCnt
);
1615 /* Routine io_service_get_matching_services */
1616 kern_return_t
is_io_service_get_matching_services(
1617 mach_port_t master_port
,
1618 io_string_t matching
,
1619 io_iterator_t
*existing
)
1623 OSDictionary
* dict
;
1625 if( master_port
!= master_device_port
)
1626 return( kIOReturnNotPrivileged
);
1628 obj
= OSUnserializeXML( matching
);
1630 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1631 *existing
= IOService::getMatchingServices( dict
);
1632 kr
= kIOReturnSuccess
;
1634 kr
= kIOReturnBadArgument
;
1642 /* Routine io_service_get_matching_services_ool */
1643 kern_return_t
is_io_service_get_matching_services_ool(
1644 mach_port_t master_port
,
1645 io_buf_ptr_t matching
,
1646 mach_msg_type_number_t matchingCnt
,
1647 kern_return_t
*result
,
1648 io_object_t
*existing
)
1652 vm_map_offset_t map_data
;
1654 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1655 data
= CAST_DOWN(vm_offset_t
, map_data
);
1657 if( KERN_SUCCESS
== kr
) {
1658 // must return success after vm_map_copyout() succeeds
1659 *result
= is_io_service_get_matching_services( master_port
,
1660 (char *) data
, existing
);
1661 vm_deallocate( kernel_map
, data
, matchingCnt
);
1668 /* Routine io_service_get_matching_service */
1669 kern_return_t
is_io_service_get_matching_service(
1670 mach_port_t master_port
,
1671 io_string_t matching
,
1672 io_service_t
*service
)
1676 OSDictionary
* dict
;
1678 if( master_port
!= master_device_port
)
1679 return( kIOReturnNotPrivileged
);
1681 obj
= OSUnserializeXML( matching
);
1683 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1684 *service
= IOService::copyMatchingService( dict
);
1685 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
1687 kr
= kIOReturnBadArgument
;
1695 /* Routine io_service_get_matching_services_ool */
1696 kern_return_t
is_io_service_get_matching_service_ool(
1697 mach_port_t master_port
,
1698 io_buf_ptr_t matching
,
1699 mach_msg_type_number_t matchingCnt
,
1700 kern_return_t
*result
,
1701 io_object_t
*service
)
1705 vm_map_offset_t map_data
;
1707 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1708 data
= CAST_DOWN(vm_offset_t
, map_data
);
1710 if( KERN_SUCCESS
== kr
) {
1711 // must return success after vm_map_copyout() succeeds
1712 *result
= is_io_service_get_matching_service( master_port
,
1713 (char *) data
, service
);
1714 vm_deallocate( kernel_map
, data
, matchingCnt
);
1721 static kern_return_t
internal_io_service_add_notification(
1722 mach_port_t master_port
,
1723 io_name_t notification_type
,
1724 io_string_t matching
,
1727 vm_size_t referenceSize
,
1729 io_object_t
* notification
)
1731 IOServiceUserNotification
* userNotify
= 0;
1732 IONotifier
* notify
= 0;
1733 const OSSymbol
* sym
;
1734 OSDictionary
* dict
;
1736 unsigned long int userMsgType
;
1739 if( master_port
!= master_device_port
)
1740 return( kIOReturnNotPrivileged
);
1743 err
= kIOReturnNoResources
;
1745 if( !(sym
= OSSymbol::withCString( notification_type
)))
1746 err
= kIOReturnNoResources
;
1748 if( !(dict
= OSDynamicCast( OSDictionary
,
1749 OSUnserializeXML( matching
)))) {
1750 err
= kIOReturnBadArgument
;
1754 if( (sym
== gIOPublishNotification
)
1755 || (sym
== gIOFirstPublishNotification
))
1756 userMsgType
= kIOServicePublishNotificationType
;
1757 else if( (sym
== gIOMatchedNotification
)
1758 || (sym
== gIOFirstMatchNotification
))
1759 userMsgType
= kIOServiceMatchedNotificationType
;
1760 else if( sym
== gIOTerminatedNotification
)
1761 userMsgType
= kIOServiceTerminatedNotificationType
;
1763 userMsgType
= kLastIOKitNotificationType
;
1765 userNotify
= new IOServiceUserNotification
;
1767 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1768 reference
, referenceSize
, client64
)) {
1769 iokit_release_port_send(port
);
1770 userNotify
->release();
1776 notify
= IOService::addMatchingNotification( sym
, dict
,
1777 &userNotify
->_handler
, userNotify
);
1779 *notification
= userNotify
;
1780 userNotify
->setNotification( notify
);
1781 err
= kIOReturnSuccess
;
1783 err
= kIOReturnUnsupported
;
1796 /* Routine io_service_add_notification */
1797 kern_return_t
is_io_service_add_notification(
1798 mach_port_t master_port
,
1799 io_name_t notification_type
,
1800 io_string_t matching
,
1802 io_async_ref_t reference
,
1803 mach_msg_type_number_t referenceCnt
,
1804 io_object_t
* notification
)
1806 return (internal_io_service_add_notification(master_port
, notification_type
,
1807 matching
, port
, &reference
[0], sizeof(io_async_ref_t
),
1808 false, notification
));
1811 /* Routine io_service_add_notification_64 */
1812 kern_return_t
is_io_service_add_notification_64(
1813 mach_port_t master_port
,
1814 io_name_t notification_type
,
1815 io_string_t matching
,
1816 mach_port_t wake_port
,
1817 io_async_ref64_t reference
,
1818 mach_msg_type_number_t referenceCnt
,
1819 io_object_t
*notification
)
1821 return (internal_io_service_add_notification(master_port
, notification_type
,
1822 matching
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1823 true, notification
));
1827 static kern_return_t
internal_io_service_add_notification_ool(
1828 mach_port_t master_port
,
1829 io_name_t notification_type
,
1830 io_buf_ptr_t matching
,
1831 mach_msg_type_number_t matchingCnt
,
1832 mach_port_t wake_port
,
1834 vm_size_t referenceSize
,
1836 kern_return_t
*result
,
1837 io_object_t
*notification
)
1841 vm_map_offset_t map_data
;
1843 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1844 data
= CAST_DOWN(vm_offset_t
, map_data
);
1846 if( KERN_SUCCESS
== kr
) {
1847 // must return success after vm_map_copyout() succeeds
1848 *result
= internal_io_service_add_notification( master_port
, notification_type
,
1849 (char *) data
, wake_port
, reference
, referenceSize
, client64
, notification
);
1850 vm_deallocate( kernel_map
, data
, matchingCnt
);
1856 /* Routine io_service_add_notification_ool */
1857 kern_return_t
is_io_service_add_notification_ool(
1858 mach_port_t master_port
,
1859 io_name_t notification_type
,
1860 io_buf_ptr_t matching
,
1861 mach_msg_type_number_t matchingCnt
,
1862 mach_port_t wake_port
,
1863 io_async_ref_t reference
,
1864 mach_msg_type_number_t referenceCnt
,
1865 kern_return_t
*result
,
1866 io_object_t
*notification
)
1868 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1869 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
1870 false, result
, notification
));
1873 /* Routine io_service_add_notification_ool_64 */
1874 kern_return_t
is_io_service_add_notification_ool_64(
1875 mach_port_t master_port
,
1876 io_name_t notification_type
,
1877 io_buf_ptr_t matching
,
1878 mach_msg_type_number_t matchingCnt
,
1879 mach_port_t wake_port
,
1880 io_async_ref64_t reference
,
1881 mach_msg_type_number_t referenceCnt
,
1882 kern_return_t
*result
,
1883 io_object_t
*notification
)
1885 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1886 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1887 true, result
, notification
));
1890 /* Routine io_service_add_notification_old */
1891 kern_return_t
is_io_service_add_notification_old(
1892 mach_port_t master_port
,
1893 io_name_t notification_type
,
1894 io_string_t matching
,
1896 // for binary compatibility reasons, this must be natural_t for ILP32
1898 io_object_t
* notification
)
1900 return( is_io_service_add_notification( master_port
, notification_type
,
1901 matching
, port
, &ref
, 1, notification
));
1905 static kern_return_t
internal_io_service_add_interest_notification(
1906 io_object_t _service
,
1907 io_name_t type_of_interest
,
1910 vm_size_t referenceSize
,
1912 io_object_t
* notification
)
1915 IOServiceMessageUserNotification
* userNotify
= 0;
1916 IONotifier
* notify
= 0;
1917 const OSSymbol
* sym
;
1920 CHECK( IOService
, _service
, service
);
1922 err
= kIOReturnNoResources
;
1923 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1925 userNotify
= new IOServiceMessageUserNotification
;
1927 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1928 reference
, referenceSize
,
1929 kIOUserNotifyMaxMessageSize
,
1931 iokit_release_port_send(port
);
1932 userNotify
->release();
1938 notify
= service
->registerInterest( sym
,
1939 &userNotify
->_handler
, userNotify
);
1941 *notification
= userNotify
;
1942 userNotify
->setNotification( notify
);
1943 err
= kIOReturnSuccess
;
1945 err
= kIOReturnUnsupported
;
1954 /* Routine io_service_add_message_notification */
1955 kern_return_t
is_io_service_add_interest_notification(
1956 io_object_t service
,
1957 io_name_t type_of_interest
,
1959 io_async_ref_t reference
,
1960 mach_msg_type_number_t referenceCnt
,
1961 io_object_t
* notification
)
1963 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1964 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
1967 /* Routine io_service_add_interest_notification_64 */
1968 kern_return_t
is_io_service_add_interest_notification_64(
1969 io_object_t service
,
1970 io_name_t type_of_interest
,
1971 mach_port_t wake_port
,
1972 io_async_ref64_t reference
,
1973 mach_msg_type_number_t referenceCnt
,
1974 io_object_t
*notification
)
1976 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1977 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
1981 /* Routine io_service_acknowledge_notification */
1982 kern_return_t
is_io_service_acknowledge_notification(
1983 io_object_t _service
,
1984 natural_t notify_ref
,
1985 natural_t response
)
1987 CHECK( IOService
, _service
, service
);
1989 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
1990 (IOOptionBits
) response
));
1994 /* Routine io_connect_get_semaphore */
1995 kern_return_t
is_io_connect_get_notification_semaphore(
1996 io_connect_t connection
,
1997 natural_t notification_type
,
1998 semaphore_t
*semaphore
)
2000 CHECK( IOUserClient
, connection
, client
);
2002 IOStatisticsClientCall();
2003 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2007 /* Routine io_registry_get_root_entry */
2008 kern_return_t
is_io_registry_get_root_entry(
2009 mach_port_t master_port
,
2012 IORegistryEntry
* entry
;
2014 if( master_port
!= master_device_port
)
2015 return( kIOReturnNotPrivileged
);
2017 entry
= IORegistryEntry::getRegistryRoot();
2022 return( kIOReturnSuccess
);
2025 /* Routine io_registry_create_iterator */
2026 kern_return_t
is_io_registry_create_iterator(
2027 mach_port_t master_port
,
2030 io_object_t
*iterator
)
2032 if( master_port
!= master_device_port
)
2033 return( kIOReturnNotPrivileged
);
2035 *iterator
= IORegistryIterator::iterateOver(
2036 IORegistryEntry::getPlane( plane
), options
);
2038 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2041 /* Routine io_registry_entry_create_iterator */
2042 kern_return_t
is_io_registry_entry_create_iterator(
2043 io_object_t registry_entry
,
2046 io_object_t
*iterator
)
2048 CHECK( IORegistryEntry
, registry_entry
, entry
);
2050 *iterator
= IORegistryIterator::iterateOver( entry
,
2051 IORegistryEntry::getPlane( plane
), options
);
2053 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2056 /* Routine io_registry_iterator_enter */
2057 kern_return_t
is_io_registry_iterator_enter_entry(
2058 io_object_t iterator
)
2060 CHECK( IORegistryIterator
, iterator
, iter
);
2064 return( kIOReturnSuccess
);
2067 /* Routine io_registry_iterator_exit */
2068 kern_return_t
is_io_registry_iterator_exit_entry(
2069 io_object_t iterator
)
2073 CHECK( IORegistryIterator
, iterator
, iter
);
2075 didIt
= iter
->exitEntry();
2077 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2080 /* Routine io_registry_entry_from_path */
2081 kern_return_t
is_io_registry_entry_from_path(
2082 mach_port_t master_port
,
2084 io_object_t
*registry_entry
)
2086 IORegistryEntry
* entry
;
2088 if( master_port
!= master_device_port
)
2089 return( kIOReturnNotPrivileged
);
2091 entry
= IORegistryEntry::fromPath( path
);
2093 *registry_entry
= entry
;
2095 return( kIOReturnSuccess
);
2098 /* Routine io_registry_entry_in_plane */
2099 kern_return_t
is_io_registry_entry_in_plane(
2100 io_object_t registry_entry
,
2102 boolean_t
*inPlane
)
2104 CHECK( IORegistryEntry
, registry_entry
, entry
);
2106 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2108 return( kIOReturnSuccess
);
2112 /* Routine io_registry_entry_get_path */
2113 kern_return_t
is_io_registry_entry_get_path(
2114 io_object_t registry_entry
,
2119 CHECK( IORegistryEntry
, registry_entry
, entry
);
2121 length
= sizeof( io_string_t
);
2122 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2123 return( kIOReturnSuccess
);
2125 return( kIOReturnBadArgument
);
2129 /* Routine io_registry_entry_get_name */
2130 kern_return_t
is_io_registry_entry_get_name(
2131 io_object_t registry_entry
,
2134 CHECK( IORegistryEntry
, registry_entry
, entry
);
2136 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2138 return( kIOReturnSuccess
);
2141 /* Routine io_registry_entry_get_name_in_plane */
2142 kern_return_t
is_io_registry_entry_get_name_in_plane(
2143 io_object_t registry_entry
,
2144 io_name_t planeName
,
2147 const IORegistryPlane
* plane
;
2148 CHECK( IORegistryEntry
, registry_entry
, entry
);
2151 plane
= IORegistryEntry::getPlane( planeName
);
2155 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2157 return( kIOReturnSuccess
);
2160 /* Routine io_registry_entry_get_location_in_plane */
2161 kern_return_t
is_io_registry_entry_get_location_in_plane(
2162 io_object_t registry_entry
,
2163 io_name_t planeName
,
2164 io_name_t location
)
2166 const IORegistryPlane
* plane
;
2167 CHECK( IORegistryEntry
, registry_entry
, entry
);
2170 plane
= IORegistryEntry::getPlane( planeName
);
2174 const char * cstr
= entry
->getLocation( plane
);
2177 strncpy( location
, cstr
, sizeof( io_name_t
));
2178 return( kIOReturnSuccess
);
2180 return( kIOReturnNotFound
);
2183 /* Routine io_registry_entry_get_registry_entry_id */
2184 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2185 io_object_t registry_entry
,
2186 uint64_t *entry_id
)
2188 CHECK( IORegistryEntry
, registry_entry
, entry
);
2190 *entry_id
= entry
->getRegistryEntryID();
2192 return (kIOReturnSuccess
);
2195 // Create a vm_map_copy_t or kalloc'ed data for memory
2196 // to be copied out. ipc will free after the copyout.
2198 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
2199 io_buf_ptr_t
* buf
)
2204 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
2205 false /* src_destroy */, ©
);
2207 assert( err
== KERN_SUCCESS
);
2208 if( err
== KERN_SUCCESS
)
2209 *buf
= (char *) copy
;
2214 /* Routine io_registry_entry_get_property */
2215 kern_return_t
is_io_registry_entry_get_property_bytes(
2216 io_object_t registry_entry
,
2217 io_name_t property_name
,
2218 io_struct_inband_t buf
,
2219 mach_msg_type_number_t
*dataCnt
)
2227 unsigned int len
= 0;
2228 const void * bytes
= 0;
2229 IOReturn ret
= kIOReturnSuccess
;
2231 CHECK( IORegistryEntry
, registry_entry
, entry
);
2233 obj
= entry
->copyProperty(property_name
);
2235 return( kIOReturnNoResources
);
2237 // One day OSData will be a common container base class
2239 if( (data
= OSDynamicCast( OSData
, obj
))) {
2240 len
= data
->getLength();
2241 bytes
= data
->getBytesNoCopy();
2243 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2244 len
= str
->getLength() + 1;
2245 bytes
= str
->getCStringNoCopy();
2247 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2248 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2249 bytes
= boo
->isTrue() ? "Yes" : "No";
2251 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2252 offsetBytes
= off
->unsigned64BitValue();
2253 len
= off
->numberOfBytes();
2254 bytes
= &offsetBytes
;
2255 #ifdef __BIG_ENDIAN__
2256 bytes
= (const void *)
2257 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2261 ret
= kIOReturnBadArgument
;
2265 ret
= kIOReturnIPCError
;
2268 bcopy( bytes
, buf
, len
);
2277 /* Routine io_registry_entry_get_property */
2278 kern_return_t
is_io_registry_entry_get_property(
2279 io_object_t registry_entry
,
2280 io_name_t property_name
,
2281 io_buf_ptr_t
*properties
,
2282 mach_msg_type_number_t
*propertiesCnt
)
2288 CHECK( IORegistryEntry
, registry_entry
, entry
);
2290 obj
= entry
->copyProperty(property_name
);
2292 return( kIOReturnNotFound
);
2294 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2297 return( kIOReturnNoMemory
);
2301 if( obj
->serialize( s
)) {
2302 len
= s
->getLength();
2303 *propertiesCnt
= len
;
2304 err
= copyoutkdata( s
->text(), len
, properties
);
2307 err
= kIOReturnUnsupported
;
2315 /* Routine io_registry_entry_get_property_recursively */
2316 kern_return_t
is_io_registry_entry_get_property_recursively(
2317 io_object_t registry_entry
,
2319 io_name_t property_name
,
2321 io_buf_ptr_t
*properties
,
2322 mach_msg_type_number_t
*propertiesCnt
)
2328 CHECK( IORegistryEntry
, registry_entry
, entry
);
2330 obj
= entry
->copyProperty( property_name
,
2331 IORegistryEntry::getPlane( plane
), options
);
2333 return( kIOReturnNotFound
);
2335 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2338 return( kIOReturnNoMemory
);
2343 if( obj
->serialize( s
)) {
2344 len
= s
->getLength();
2345 *propertiesCnt
= len
;
2346 err
= copyoutkdata( s
->text(), len
, properties
);
2349 err
= kIOReturnUnsupported
;
2357 /* Routine io_registry_entry_get_properties */
2358 kern_return_t
is_io_registry_entry_get_properties(
2359 io_object_t registry_entry
,
2360 io_buf_ptr_t
*properties
,
2361 mach_msg_type_number_t
*propertiesCnt
)
2366 CHECK( IORegistryEntry
, registry_entry
, entry
);
2368 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2370 return( kIOReturnNoMemory
);
2374 if( entry
->serializeProperties( s
)) {
2375 len
= s
->getLength();
2376 *propertiesCnt
= len
;
2377 err
= copyoutkdata( s
->text(), len
, properties
);
2380 err
= kIOReturnUnsupported
;
2387 /* Routine io_registry_entry_set_properties */
2388 kern_return_t is_io_registry_entry_set_properties
2390 io_object_t registry_entry
,
2391 io_buf_ptr_t properties
,
2392 mach_msg_type_number_t propertiesCnt
,
2393 kern_return_t
* result
)
2399 vm_map_offset_t map_data
;
2401 CHECK( IORegistryEntry
, registry_entry
, entry
);
2403 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
2404 return( kIOReturnMessageTooLarge
);
2406 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2407 data
= CAST_DOWN(vm_offset_t
, map_data
);
2409 if( KERN_SUCCESS
== err
) {
2411 // must return success after vm_map_copyout() succeeds
2412 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
2413 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2416 res
= kIOReturnBadArgument
;
2418 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
2419 registry_entry
, obj
))
2420 res
= kIOReturnNotPermitted
;
2423 res
= entry
->setProperties( obj
);
2433 /* Routine io_registry_entry_get_child_iterator */
2434 kern_return_t
is_io_registry_entry_get_child_iterator(
2435 io_object_t registry_entry
,
2437 io_object_t
*iterator
)
2439 CHECK( IORegistryEntry
, registry_entry
, entry
);
2441 *iterator
= entry
->getChildIterator(
2442 IORegistryEntry::getPlane( plane
));
2444 return( kIOReturnSuccess
);
2447 /* Routine io_registry_entry_get_parent_iterator */
2448 kern_return_t
is_io_registry_entry_get_parent_iterator(
2449 io_object_t registry_entry
,
2451 io_object_t
*iterator
)
2453 CHECK( IORegistryEntry
, registry_entry
, entry
);
2455 *iterator
= entry
->getParentIterator(
2456 IORegistryEntry::getPlane( plane
));
2458 return( kIOReturnSuccess
);
2461 /* Routine io_service_get_busy_state */
2462 kern_return_t
is_io_service_get_busy_state(
2463 io_object_t _service
,
2464 uint32_t *busyState
)
2466 CHECK( IOService
, _service
, service
);
2468 *busyState
= service
->getBusyState();
2470 return( kIOReturnSuccess
);
2473 /* Routine io_service_get_state */
2474 kern_return_t
is_io_service_get_state(
2475 io_object_t _service
,
2477 uint32_t *busy_state
,
2478 uint64_t *accumulated_busy_time
)
2480 CHECK( IOService
, _service
, service
);
2482 *state
= service
->getState();
2483 *busy_state
= service
->getBusyState();
2484 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
2486 return( kIOReturnSuccess
);
2489 /* Routine io_service_wait_quiet */
2490 kern_return_t
is_io_service_wait_quiet(
2491 io_object_t _service
,
2492 mach_timespec_t wait_time
)
2496 CHECK( IOService
, _service
, service
);
2498 timeoutNS
= wait_time
.tv_sec
;
2499 timeoutNS
*= kSecondScale
;
2500 timeoutNS
+= wait_time
.tv_nsec
;
2502 return( service
->waitQuiet(timeoutNS
) );
2505 /* Routine io_service_request_probe */
2506 kern_return_t
is_io_service_request_probe(
2507 io_object_t _service
,
2510 CHECK( IOService
, _service
, service
);
2512 return( service
->requestProbe( options
));
2515 /* Routine io_service_open_ndr */
2516 kern_return_t
is_io_service_open_extended(
2517 io_object_t _service
,
2519 uint32_t connect_type
,
2521 io_buf_ptr_t properties
,
2522 mach_msg_type_number_t propertiesCnt
,
2523 kern_return_t
* result
,
2524 io_object_t
*connection
)
2526 IOUserClient
* client
= 0;
2527 kern_return_t err
= KERN_SUCCESS
;
2528 IOReturn res
= kIOReturnSuccess
;
2529 OSDictionary
* propertiesDict
= 0;
2531 bool disallowAccess
;
2533 CHECK( IOService
, _service
, service
);
2541 vm_map_offset_t map_data
;
2543 if( propertiesCnt
> sizeof(io_struct_inband_t
))
2544 return( kIOReturnMessageTooLarge
);
2546 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2548 data
= CAST_DOWN(vm_offset_t
, map_data
);
2549 if (KERN_SUCCESS
== err
)
2551 // must return success after vm_map_copyout() succeeds
2552 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
2553 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2554 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
2555 if (!propertiesDict
)
2557 res
= kIOReturnBadArgument
;
2562 if (kIOReturnSuccess
!= res
)
2566 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
2569 if (!propertiesDict
)
2570 propertiesDict
= OSDictionary::withCapacity(4);
2571 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
2575 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
2580 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
2581 connect_type
, propertiesDict
, &client
);
2584 propertiesDict
->release();
2586 if (res
== kIOReturnSuccess
)
2588 assert( OSDynamicCast(IOUserClient
, client
) );
2590 disallowAccess
= (crossEndian
2591 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
2592 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
2593 if (disallowAccess
) res
= kIOReturnUnsupported
;
2595 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
2596 res
= kIOReturnNotPermitted
;
2598 if (kIOReturnSuccess
!= res
)
2600 IOStatisticsClientCall();
2601 client
->clientClose();
2606 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
2607 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
2610 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
2611 creatorName
->release();
2613 client
->setTerminateDefer(service
, false);
2618 *connection
= client
;
2624 /* Routine io_service_close */
2625 kern_return_t
is_io_service_close(
2626 io_object_t connection
)
2629 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2630 return( kIOReturnSuccess
);
2632 CHECK( IOUserClient
, connection
, client
);
2634 IOStatisticsClientCall();
2635 client
->clientClose();
2637 return( kIOReturnSuccess
);
2640 /* Routine io_connect_get_service */
2641 kern_return_t
is_io_connect_get_service(
2642 io_object_t connection
,
2643 io_object_t
*service
)
2645 IOService
* theService
;
2647 CHECK( IOUserClient
, connection
, client
);
2649 theService
= client
->getService();
2651 theService
->retain();
2653 *service
= theService
;
2655 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2658 /* Routine io_connect_set_notification_port */
2659 kern_return_t
is_io_connect_set_notification_port(
2660 io_object_t connection
,
2661 uint32_t notification_type
,
2665 CHECK( IOUserClient
, connection
, client
);
2667 IOStatisticsClientCall();
2668 return( client
->registerNotificationPort( port
, notification_type
,
2669 (io_user_reference_t
) reference
));
2672 /* Routine io_connect_set_notification_port */
2673 kern_return_t
is_io_connect_set_notification_port_64(
2674 io_object_t connection
,
2675 uint32_t notification_type
,
2677 io_user_reference_t reference
)
2679 CHECK( IOUserClient
, connection
, client
);
2681 IOStatisticsClientCall();
2682 return( client
->registerNotificationPort( port
, notification_type
,
2686 /* Routine io_connect_map_memory_into_task */
2687 kern_return_t is_io_connect_map_memory_into_task
2689 io_connect_t connection
,
2690 uint32_t memory_type
,
2692 mach_vm_address_t
*address
,
2693 mach_vm_size_t
*size
,
2700 CHECK( IOUserClient
, connection
, client
);
2702 IOStatisticsClientCall();
2703 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
2706 *address
= map
->getAddress();
2708 *size
= map
->getSize();
2710 if( client
->sharedInstance
2711 || (into_task
!= current_task())) {
2712 // push a name out to the task owning the map,
2713 // so we can clean up maps
2714 mach_port_name_t name __unused
=
2715 IOMachPort::makeSendRightForTask(
2716 into_task
, map
, IKOT_IOKIT_OBJECT
);
2719 // keep it with the user client
2720 IOLockLock( gIOObjectPortLock
);
2721 if( 0 == client
->mappings
)
2722 client
->mappings
= OSSet::withCapacity(2);
2723 if( client
->mappings
)
2724 client
->mappings
->setObject( map
);
2725 IOLockUnlock( gIOObjectPortLock
);
2728 err
= kIOReturnSuccess
;
2731 err
= kIOReturnBadArgument
;
2736 /* Routine is_io_connect_map_memory */
2737 kern_return_t
is_io_connect_map_memory(
2738 io_object_t connect
,
2741 vm_address_t
* mapAddr
,
2742 vm_size_t
* mapSize
,
2746 mach_vm_address_t address
;
2747 mach_vm_size_t size
;
2749 address
= SCALAR64(*mapAddr
);
2750 size
= SCALAR64(*mapSize
);
2752 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
2754 *mapAddr
= SCALAR32(address
);
2755 *mapSize
= SCALAR32(size
);
2762 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2765 IOMemoryMap
* map
= 0;
2767 IOLockLock(gIOObjectPortLock
);
2769 iter
= OSCollectionIterator::withCollection(mappings
);
2772 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2774 if(mem
== map
->getMemoryDescriptor())
2777 mappings
->removeObject(map
);
2784 IOLockUnlock(gIOObjectPortLock
);
2791 /* Routine io_connect_unmap_memory_from_task */
2792 kern_return_t is_io_connect_unmap_memory_from_task
2794 io_connect_t connection
,
2795 uint32_t memory_type
,
2797 mach_vm_address_t address
)
2800 IOOptionBits options
= 0;
2801 IOMemoryDescriptor
* memory
;
2804 CHECK( IOUserClient
, connection
, client
);
2806 IOStatisticsClientCall();
2807 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
2809 if( memory
&& (kIOReturnSuccess
== err
)) {
2811 options
= (options
& ~kIOMapUserOptionsMask
)
2812 | kIOMapAnywhere
| kIOMapReference
;
2814 map
= memory
->createMappingInTask( from_task
, address
, options
);
2818 IOLockLock( gIOObjectPortLock
);
2819 if( client
->mappings
)
2820 client
->mappings
->removeObject( map
);
2821 IOLockUnlock( gIOObjectPortLock
);
2823 mach_port_name_t name
= 0;
2824 if (from_task
!= current_task())
2825 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
2828 map
->userClientUnmap();
2829 err
= iokit_mod_send_right( from_task
, name
, -2 );
2830 err
= kIOReturnSuccess
;
2833 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2834 if (from_task
== current_task())
2838 err
= kIOReturnBadArgument
;
2844 kern_return_t
is_io_connect_unmap_memory(
2845 io_object_t connect
,
2848 vm_address_t mapAddr
)
2851 mach_vm_address_t address
;
2853 address
= SCALAR64(mapAddr
);
2855 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
2861 /* Routine io_connect_add_client */
2862 kern_return_t
is_io_connect_add_client(
2863 io_object_t connection
,
2864 io_object_t connect_to
)
2866 CHECK( IOUserClient
, connection
, client
);
2867 CHECK( IOUserClient
, connect_to
, to
);
2869 IOStatisticsClientCall();
2870 return( client
->connectClient( to
) );
2874 /* Routine io_connect_set_properties */
2875 kern_return_t
is_io_connect_set_properties(
2876 io_object_t connection
,
2877 io_buf_ptr_t properties
,
2878 mach_msg_type_number_t propertiesCnt
,
2879 kern_return_t
* result
)
2881 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2884 /* Routine io_user_client_method */
2885 kern_return_t is_io_connect_method_var_output
2887 io_connect_t connection
,
2889 io_scalar_inband64_t scalar_input
,
2890 mach_msg_type_number_t scalar_inputCnt
,
2891 io_struct_inband_t inband_input
,
2892 mach_msg_type_number_t inband_inputCnt
,
2893 mach_vm_address_t ool_input
,
2894 mach_vm_size_t ool_input_size
,
2895 io_struct_inband_t inband_output
,
2896 mach_msg_type_number_t
*inband_outputCnt
,
2897 io_scalar_inband64_t scalar_output
,
2898 mach_msg_type_number_t
*scalar_outputCnt
,
2899 io_buf_ptr_t
*var_output
,
2900 mach_msg_type_number_t
*var_outputCnt
2903 CHECK( IOUserClient
, connection
, client
);
2905 IOExternalMethodArguments args
;
2907 IOMemoryDescriptor
* inputMD
= 0;
2908 OSObject
* structureVariableOutputData
= 0;
2910 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
2911 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
2913 args
.selector
= selector
;
2915 args
.asyncWakePort
= MACH_PORT_NULL
;
2916 args
.asyncReference
= 0;
2917 args
.asyncReferenceCount
= 0;
2918 args
.structureVariableOutputData
= &structureVariableOutputData
;
2920 args
.scalarInput
= scalar_input
;
2921 args
.scalarInputCount
= scalar_inputCnt
;
2922 args
.structureInput
= inband_input
;
2923 args
.structureInputSize
= inband_inputCnt
;
2926 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
2927 kIODirectionOut
, current_task());
2929 args
.structureInputDescriptor
= inputMD
;
2931 args
.scalarOutput
= scalar_output
;
2932 args
.scalarOutputCount
= *scalar_outputCnt
;
2933 args
.structureOutput
= inband_output
;
2934 args
.structureOutputSize
= *inband_outputCnt
;
2935 args
.structureOutputDescriptor
= NULL
;
2936 args
.structureOutputDescriptorSize
= 0;
2938 IOStatisticsClientCall();
2939 ret
= client
->externalMethod( selector
, &args
);
2941 *scalar_outputCnt
= args
.scalarOutputCount
;
2942 *inband_outputCnt
= args
.structureOutputSize
;
2944 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
2946 OSSerialize
* serialize
;
2950 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
2952 len
= serialize
->getLength();
2953 *var_outputCnt
= len
;
2954 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
2956 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
2958 len
= data
->getLength();
2959 *var_outputCnt
= len
;
2960 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
2964 ret
= kIOReturnUnderrun
;
2970 if (structureVariableOutputData
)
2971 structureVariableOutputData
->release();
2976 /* Routine io_user_client_method */
2977 kern_return_t is_io_connect_method
2979 io_connect_t connection
,
2981 io_scalar_inband64_t scalar_input
,
2982 mach_msg_type_number_t scalar_inputCnt
,
2983 io_struct_inband_t inband_input
,
2984 mach_msg_type_number_t inband_inputCnt
,
2985 mach_vm_address_t ool_input
,
2986 mach_vm_size_t ool_input_size
,
2987 io_struct_inband_t inband_output
,
2988 mach_msg_type_number_t
*inband_outputCnt
,
2989 io_scalar_inband64_t scalar_output
,
2990 mach_msg_type_number_t
*scalar_outputCnt
,
2991 mach_vm_address_t ool_output
,
2992 mach_vm_size_t
*ool_output_size
2995 CHECK( IOUserClient
, connection
, client
);
2997 IOExternalMethodArguments args
;
2999 IOMemoryDescriptor
* inputMD
= 0;
3000 IOMemoryDescriptor
* outputMD
= 0;
3002 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3003 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3005 args
.selector
= selector
;
3007 args
.asyncWakePort
= MACH_PORT_NULL
;
3008 args
.asyncReference
= 0;
3009 args
.asyncReferenceCount
= 0;
3010 args
.structureVariableOutputData
= 0;
3012 args
.scalarInput
= scalar_input
;
3013 args
.scalarInputCount
= scalar_inputCnt
;
3014 args
.structureInput
= inband_input
;
3015 args
.structureInputSize
= inband_inputCnt
;
3018 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3019 kIODirectionOut
, current_task());
3021 args
.structureInputDescriptor
= inputMD
;
3023 args
.scalarOutput
= scalar_output
;
3024 args
.scalarOutputCount
= *scalar_outputCnt
;
3025 args
.structureOutput
= inband_output
;
3026 args
.structureOutputSize
= *inband_outputCnt
;
3028 if (ool_output
&& ool_output_size
)
3030 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3031 kIODirectionIn
, current_task());
3034 args
.structureOutputDescriptor
= outputMD
;
3035 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3037 IOStatisticsClientCall();
3038 ret
= client
->externalMethod( selector
, &args
);
3040 *scalar_outputCnt
= args
.scalarOutputCount
;
3041 *inband_outputCnt
= args
.structureOutputSize
;
3042 *ool_output_size
= args
.structureOutputDescriptorSize
;
3047 outputMD
->release();
3052 /* Routine io_async_user_client_method */
3053 kern_return_t is_io_connect_async_method
3055 io_connect_t connection
,
3056 mach_port_t wake_port
,
3057 io_async_ref64_t reference
,
3058 mach_msg_type_number_t referenceCnt
,
3060 io_scalar_inband64_t scalar_input
,
3061 mach_msg_type_number_t scalar_inputCnt
,
3062 io_struct_inband_t inband_input
,
3063 mach_msg_type_number_t inband_inputCnt
,
3064 mach_vm_address_t ool_input
,
3065 mach_vm_size_t ool_input_size
,
3066 io_struct_inband_t inband_output
,
3067 mach_msg_type_number_t
*inband_outputCnt
,
3068 io_scalar_inband64_t scalar_output
,
3069 mach_msg_type_number_t
*scalar_outputCnt
,
3070 mach_vm_address_t ool_output
,
3071 mach_vm_size_t
* ool_output_size
3074 CHECK( IOUserClient
, connection
, client
);
3076 IOExternalMethodArguments args
;
3078 IOMemoryDescriptor
* inputMD
= 0;
3079 IOMemoryDescriptor
* outputMD
= 0;
3081 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3082 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3084 reference
[0] = (io_user_reference_t
) wake_port
;
3085 if (vm_map_is_64bit(get_task_map(current_task())))
3086 reference
[0] |= kIOUCAsync64Flag
;
3088 args
.selector
= selector
;
3090 args
.asyncWakePort
= wake_port
;
3091 args
.asyncReference
= reference
;
3092 args
.asyncReferenceCount
= referenceCnt
;
3094 args
.scalarInput
= scalar_input
;
3095 args
.scalarInputCount
= scalar_inputCnt
;
3096 args
.structureInput
= inband_input
;
3097 args
.structureInputSize
= inband_inputCnt
;
3100 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3101 kIODirectionOut
, current_task());
3103 args
.structureInputDescriptor
= inputMD
;
3105 args
.scalarOutput
= scalar_output
;
3106 args
.scalarOutputCount
= *scalar_outputCnt
;
3107 args
.structureOutput
= inband_output
;
3108 args
.structureOutputSize
= *inband_outputCnt
;
3112 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3113 kIODirectionIn
, current_task());
3116 args
.structureOutputDescriptor
= outputMD
;
3117 args
.structureOutputDescriptorSize
= *ool_output_size
;
3119 IOStatisticsClientCall();
3120 ret
= client
->externalMethod( selector
, &args
);
3122 *inband_outputCnt
= args
.structureOutputSize
;
3123 *ool_output_size
= args
.structureOutputDescriptorSize
;
3128 outputMD
->release();
3133 /* Routine io_connect_method_scalarI_scalarO */
3134 kern_return_t
is_io_connect_method_scalarI_scalarO(
3135 io_object_t connect
,
3137 io_scalar_inband_t input
,
3138 mach_msg_type_number_t inputCount
,
3139 io_scalar_inband_t output
,
3140 mach_msg_type_number_t
* outputCount
)
3144 io_scalar_inband64_t _input
;
3145 io_scalar_inband64_t _output
;
3147 mach_msg_type_number_t struct_outputCnt
= 0;
3148 mach_vm_size_t ool_output_size
= 0;
3150 for (i
= 0; i
< inputCount
; i
++)
3151 _input
[i
] = SCALAR64(input
[i
]);
3153 err
= is_io_connect_method(connect
, index
,
3157 NULL
, &struct_outputCnt
,
3158 _output
, outputCount
,
3159 0, &ool_output_size
);
3161 for (i
= 0; i
< *outputCount
; i
++)
3162 output
[i
] = SCALAR32(_output
[i
]);
3167 kern_return_t
shim_io_connect_method_scalarI_scalarO(
3168 IOExternalMethod
* method
,
3170 const io_user_scalar_t
* input
,
3171 mach_msg_type_number_t inputCount
,
3172 io_user_scalar_t
* output
,
3173 mach_msg_type_number_t
* outputCount
)
3176 io_scalar_inband_t _output
;
3178 err
= kIOReturnBadArgument
;
3182 if( inputCount
!= method
->count0
)
3184 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3187 if( *outputCount
!= method
->count1
)
3189 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3193 func
= method
->func
;
3195 switch( inputCount
) {
3198 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3199 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3202 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3203 ARG32(input
[3]), ARG32(input
[4]),
3207 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3209 &_output
[0], &_output
[1] );
3212 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3213 &_output
[0], &_output
[1], &_output
[2] );
3216 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3217 &_output
[0], &_output
[1], &_output
[2],
3221 err
= (object
->*func
)( ARG32(input
[0]),
3222 &_output
[0], &_output
[1], &_output
[2],
3223 &_output
[3], &_output
[4] );
3226 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
3227 &_output
[3], &_output
[4], &_output
[5] );
3231 IOLog("%s: Bad method table\n", object
->getName());
3237 for (i
= 0; i
< *outputCount
; i
++)
3238 output
[i
] = SCALAR32(_output
[i
]);
3243 /* Routine io_async_method_scalarI_scalarO */
3244 kern_return_t
is_io_async_method_scalarI_scalarO(
3245 io_object_t connect
,
3246 mach_port_t wake_port
,
3247 io_async_ref_t reference
,
3248 mach_msg_type_number_t referenceCnt
,
3250 io_scalar_inband_t input
,
3251 mach_msg_type_number_t inputCount
,
3252 io_scalar_inband_t output
,
3253 mach_msg_type_number_t
* outputCount
)
3257 io_scalar_inband64_t _input
;
3258 io_scalar_inband64_t _output
;
3259 io_async_ref64_t _reference
;
3261 for (i
= 0; i
< referenceCnt
; i
++)
3262 _reference
[i
] = REF64(reference
[i
]);
3264 mach_msg_type_number_t struct_outputCnt
= 0;
3265 mach_vm_size_t ool_output_size
= 0;
3267 for (i
= 0; i
< inputCount
; i
++)
3268 _input
[i
] = SCALAR64(input
[i
]);
3270 err
= is_io_connect_async_method(connect
,
3271 wake_port
, _reference
, referenceCnt
,
3276 NULL
, &struct_outputCnt
,
3277 _output
, outputCount
,
3278 0, &ool_output_size
);
3280 for (i
= 0; i
< *outputCount
; i
++)
3281 output
[i
] = SCALAR32(_output
[i
]);
3285 /* Routine io_async_method_scalarI_structureO */
3286 kern_return_t
is_io_async_method_scalarI_structureO(
3287 io_object_t connect
,
3288 mach_port_t wake_port
,
3289 io_async_ref_t reference
,
3290 mach_msg_type_number_t referenceCnt
,
3292 io_scalar_inband_t input
,
3293 mach_msg_type_number_t inputCount
,
3294 io_struct_inband_t output
,
3295 mach_msg_type_number_t
* outputCount
)
3298 io_scalar_inband64_t _input
;
3299 io_async_ref64_t _reference
;
3301 for (i
= 0; i
< referenceCnt
; i
++)
3302 _reference
[i
] = REF64(reference
[i
]);
3304 mach_msg_type_number_t scalar_outputCnt
= 0;
3305 mach_vm_size_t ool_output_size
= 0;
3307 for (i
= 0; i
< inputCount
; i
++)
3308 _input
[i
] = SCALAR64(input
[i
]);
3310 return (is_io_connect_async_method(connect
,
3311 wake_port
, _reference
, referenceCnt
,
3316 output
, outputCount
,
3317 NULL
, &scalar_outputCnt
,
3318 0, &ool_output_size
));
3321 /* Routine io_async_method_scalarI_structureI */
3322 kern_return_t
is_io_async_method_scalarI_structureI(
3323 io_connect_t connect
,
3324 mach_port_t wake_port
,
3325 io_async_ref_t reference
,
3326 mach_msg_type_number_t referenceCnt
,
3328 io_scalar_inband_t input
,
3329 mach_msg_type_number_t inputCount
,
3330 io_struct_inband_t inputStruct
,
3331 mach_msg_type_number_t inputStructCount
)
3334 io_scalar_inband64_t _input
;
3335 io_async_ref64_t _reference
;
3337 for (i
= 0; i
< referenceCnt
; i
++)
3338 _reference
[i
] = REF64(reference
[i
]);
3340 mach_msg_type_number_t scalar_outputCnt
= 0;
3341 mach_msg_type_number_t inband_outputCnt
= 0;
3342 mach_vm_size_t ool_output_size
= 0;
3344 for (i
= 0; i
< inputCount
; i
++)
3345 _input
[i
] = SCALAR64(input
[i
]);
3347 return (is_io_connect_async_method(connect
,
3348 wake_port
, _reference
, referenceCnt
,
3351 inputStruct
, inputStructCount
,
3353 NULL
, &inband_outputCnt
,
3354 NULL
, &scalar_outputCnt
,
3355 0, &ool_output_size
));
3358 /* Routine io_async_method_structureI_structureO */
3359 kern_return_t
is_io_async_method_structureI_structureO(
3360 io_object_t connect
,
3361 mach_port_t wake_port
,
3362 io_async_ref_t reference
,
3363 mach_msg_type_number_t referenceCnt
,
3365 io_struct_inband_t input
,
3366 mach_msg_type_number_t inputCount
,
3367 io_struct_inband_t output
,
3368 mach_msg_type_number_t
* outputCount
)
3371 mach_msg_type_number_t scalar_outputCnt
= 0;
3372 mach_vm_size_t ool_output_size
= 0;
3373 io_async_ref64_t _reference
;
3375 for (i
= 0; i
< referenceCnt
; i
++)
3376 _reference
[i
] = REF64(reference
[i
]);
3378 return (is_io_connect_async_method(connect
,
3379 wake_port
, _reference
, referenceCnt
,
3384 output
, outputCount
,
3385 NULL
, &scalar_outputCnt
,
3386 0, &ool_output_size
));
3390 kern_return_t
shim_io_async_method_scalarI_scalarO(
3391 IOExternalAsyncMethod
* method
,
3393 mach_port_t asyncWakePort
,
3394 io_user_reference_t
* asyncReference
,
3395 uint32_t asyncReferenceCount
,
3396 const io_user_scalar_t
* input
,
3397 mach_msg_type_number_t inputCount
,
3398 io_user_scalar_t
* output
,
3399 mach_msg_type_number_t
* outputCount
)
3403 io_scalar_inband_t _output
;
3405 io_async_ref_t reference
;
3407 for (i
= 0; i
< asyncReferenceCount
; i
++)
3408 reference
[i
] = REF32(asyncReference
[i
]);
3410 err
= kIOReturnBadArgument
;
3414 if( inputCount
!= method
->count0
)
3416 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3419 if( *outputCount
!= method
->count1
)
3421 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3425 func
= method
->func
;
3427 switch( inputCount
) {
3430 err
= (object
->*func
)( reference
,
3431 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3432 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3435 err
= (object
->*func
)( reference
,
3436 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3437 ARG32(input
[3]), ARG32(input
[4]),
3441 err
= (object
->*func
)( reference
,
3442 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3444 &_output
[0], &_output
[1] );
3447 err
= (object
->*func
)( reference
,
3448 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3449 &_output
[0], &_output
[1], &_output
[2] );
3452 err
= (object
->*func
)( reference
,
3453 ARG32(input
[0]), ARG32(input
[1]),
3454 &_output
[0], &_output
[1], &_output
[2],
3458 err
= (object
->*func
)( reference
,
3460 &_output
[0], &_output
[1], &_output
[2],
3461 &_output
[3], &_output
[4] );
3464 err
= (object
->*func
)( reference
,
3465 &_output
[0], &_output
[1], &_output
[2],
3466 &_output
[3], &_output
[4], &_output
[5] );
3470 IOLog("%s: Bad method table\n", object
->getName());
3475 for (i
= 0; i
< *outputCount
; i
++)
3476 output
[i
] = SCALAR32(_output
[i
]);
3482 /* Routine io_connect_method_scalarI_structureO */
3483 kern_return_t
is_io_connect_method_scalarI_structureO(
3484 io_object_t connect
,
3486 io_scalar_inband_t input
,
3487 mach_msg_type_number_t inputCount
,
3488 io_struct_inband_t output
,
3489 mach_msg_type_number_t
* outputCount
)
3492 io_scalar_inband64_t _input
;
3494 mach_msg_type_number_t scalar_outputCnt
= 0;
3495 mach_vm_size_t ool_output_size
= 0;
3497 for (i
= 0; i
< inputCount
; i
++)
3498 _input
[i
] = SCALAR64(input
[i
]);
3500 return (is_io_connect_method(connect
, index
,
3504 output
, outputCount
,
3505 NULL
, &scalar_outputCnt
,
3506 0, &ool_output_size
));
3509 kern_return_t
shim_io_connect_method_scalarI_structureO(
3511 IOExternalMethod
* method
,
3513 const io_user_scalar_t
* input
,
3514 mach_msg_type_number_t inputCount
,
3515 io_struct_inband_t output
,
3516 IOByteCount
* outputCount
)
3521 err
= kIOReturnBadArgument
;
3524 if( inputCount
!= method
->count0
)
3526 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3529 if( (kIOUCVariableStructureSize
!= method
->count1
)
3530 && (*outputCount
!= method
->count1
))
3532 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3536 func
= method
->func
;
3538 switch( inputCount
) {
3541 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3542 ARG32(input
[3]), ARG32(input
[4]),
3546 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3548 output
, (void *)outputCount
);
3551 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3552 output
, (void *)outputCount
, 0 );
3555 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3556 output
, (void *)outputCount
, 0, 0 );
3559 err
= (object
->*func
)( ARG32(input
[0]),
3560 output
, (void *)outputCount
, 0, 0, 0 );
3563 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
3567 IOLog("%s: Bad method table\n", object
->getName());
3576 kern_return_t
shim_io_async_method_scalarI_structureO(
3577 IOExternalAsyncMethod
* method
,
3579 mach_port_t asyncWakePort
,
3580 io_user_reference_t
* asyncReference
,
3581 uint32_t asyncReferenceCount
,
3582 const io_user_scalar_t
* input
,
3583 mach_msg_type_number_t inputCount
,
3584 io_struct_inband_t output
,
3585 mach_msg_type_number_t
* outputCount
)
3590 io_async_ref_t reference
;
3592 for (i
= 0; i
< asyncReferenceCount
; i
++)
3593 reference
[i
] = REF32(asyncReference
[i
]);
3595 err
= kIOReturnBadArgument
;
3597 if( inputCount
!= method
->count0
)
3599 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3602 if( (kIOUCVariableStructureSize
!= method
->count1
)
3603 && (*outputCount
!= method
->count1
))
3605 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3609 func
= method
->func
;
3611 switch( inputCount
) {
3614 err
= (object
->*func
)( reference
,
3615 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3616 ARG32(input
[3]), ARG32(input
[4]),
3620 err
= (object
->*func
)( reference
,
3621 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3623 output
, (void *)outputCount
);
3626 err
= (object
->*func
)( reference
,
3627 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3628 output
, (void *)outputCount
, 0 );
3631 err
= (object
->*func
)( reference
,
3632 ARG32(input
[0]), ARG32(input
[1]),
3633 output
, (void *)outputCount
, 0, 0 );
3636 err
= (object
->*func
)( reference
,
3638 output
, (void *)outputCount
, 0, 0, 0 );
3641 err
= (object
->*func
)( reference
,
3642 output
, (void *)outputCount
, 0, 0, 0, 0 );
3646 IOLog("%s: Bad method table\n", object
->getName());
3654 /* Routine io_connect_method_scalarI_structureI */
3655 kern_return_t
is_io_connect_method_scalarI_structureI(
3656 io_connect_t connect
,
3658 io_scalar_inband_t input
,
3659 mach_msg_type_number_t inputCount
,
3660 io_struct_inband_t inputStruct
,
3661 mach_msg_type_number_t inputStructCount
)
3664 io_scalar_inband64_t _input
;
3666 mach_msg_type_number_t scalar_outputCnt
= 0;
3667 mach_msg_type_number_t inband_outputCnt
= 0;
3668 mach_vm_size_t ool_output_size
= 0;
3670 for (i
= 0; i
< inputCount
; i
++)
3671 _input
[i
] = SCALAR64(input
[i
]);
3673 return (is_io_connect_method(connect
, index
,
3675 inputStruct
, inputStructCount
,
3677 NULL
, &inband_outputCnt
,
3678 NULL
, &scalar_outputCnt
,
3679 0, &ool_output_size
));
3682 kern_return_t
shim_io_connect_method_scalarI_structureI(
3683 IOExternalMethod
* method
,
3685 const io_user_scalar_t
* input
,
3686 mach_msg_type_number_t inputCount
,
3687 io_struct_inband_t inputStruct
,
3688 mach_msg_type_number_t inputStructCount
)
3691 IOReturn err
= kIOReturnBadArgument
;
3695 if( (kIOUCVariableStructureSize
!= method
->count0
)
3696 && (inputCount
!= method
->count0
))
3698 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3701 if( (kIOUCVariableStructureSize
!= method
->count1
)
3702 && (inputStructCount
!= method
->count1
))
3704 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3708 func
= method
->func
;
3710 switch( inputCount
) {
3713 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3714 ARG32(input
[3]), ARG32(input
[4]),
3718 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
3720 inputStruct
, (void *)(uintptr_t)inputStructCount
);
3723 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3724 inputStruct
, (void *)(uintptr_t)inputStructCount
,
3728 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3729 inputStruct
, (void *)(uintptr_t)inputStructCount
,
3733 err
= (object
->*func
)( ARG32(input
[0]),
3734 inputStruct
, (void *)(uintptr_t)inputStructCount
,
3738 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
3743 IOLog("%s: Bad method table\n", object
->getName());
3751 kern_return_t
shim_io_async_method_scalarI_structureI(
3752 IOExternalAsyncMethod
* method
,
3754 mach_port_t asyncWakePort
,
3755 io_user_reference_t
* asyncReference
,
3756 uint32_t asyncReferenceCount
,
3757 const io_user_scalar_t
* input
,
3758 mach_msg_type_number_t inputCount
,
3759 io_struct_inband_t inputStruct
,
3760 mach_msg_type_number_t inputStructCount
)
3764 IOReturn err
= kIOReturnBadArgument
;
3765 io_async_ref_t reference
;
3767 for (i
= 0; i
< asyncReferenceCount
; i
++)
3768 reference
[i
] = REF32(asyncReference
[i
]);
3772 if( (kIOUCVariableStructureSize
!= method
->count0
)
3773 && (inputCount
!= method
->count0
))
3775 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3778 if( (kIOUCVariableStructureSize
!= method
->count1
)
3779 && (inputStructCount
!= method
->count1
))
3781 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3785 func
= method
->func
;
3787 switch( inputCount
) {
3790 err
= (object
->*func
)( reference
,
3791 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3792 ARG32(input
[3]), ARG32(input
[4]),
3796 err
= (object
->*func
)( reference
,
3797 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3799 inputStruct
, (void *)(uintptr_t)inputStructCount
);
3802 err
= (object
->*func
)( reference
,
3803 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3804 inputStruct
, (void *)(uintptr_t)inputStructCount
,
3808 err
= (object
->*func
)( reference
,
3809 ARG32(input
[0]), ARG32(input
[1]),
3810 inputStruct
, (void *)(uintptr_t)inputStructCount
,
3814 err
= (object
->*func
)( reference
,
3816 inputStruct
, (void *)(uintptr_t)inputStructCount
,
3820 err
= (object
->*func
)( reference
,
3821 inputStruct
, (void *)(uintptr_t)inputStructCount
,
3826 IOLog("%s: Bad method table\n", object
->getName());
3834 /* Routine io_connect_method_structureI_structureO */
3835 kern_return_t
is_io_connect_method_structureI_structureO(
3836 io_object_t connect
,
3838 io_struct_inband_t input
,
3839 mach_msg_type_number_t inputCount
,
3840 io_struct_inband_t output
,
3841 mach_msg_type_number_t
* outputCount
)
3843 mach_msg_type_number_t scalar_outputCnt
= 0;
3844 mach_vm_size_t ool_output_size
= 0;
3846 return (is_io_connect_method(connect
, index
,
3850 output
, outputCount
,
3851 NULL
, &scalar_outputCnt
,
3852 0, &ool_output_size
));
3855 kern_return_t
shim_io_connect_method_structureI_structureO(
3856 IOExternalMethod
* method
,
3858 io_struct_inband_t input
,
3859 mach_msg_type_number_t inputCount
,
3860 io_struct_inband_t output
,
3861 IOByteCount
* outputCount
)
3864 IOReturn err
= kIOReturnBadArgument
;
3868 if( (kIOUCVariableStructureSize
!= method
->count0
)
3869 && (inputCount
!= method
->count0
))
3871 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3874 if( (kIOUCVariableStructureSize
!= method
->count1
)
3875 && (*outputCount
!= method
->count1
))
3877 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3881 func
= method
->func
;
3883 if( method
->count1
) {
3884 if( method
->count0
) {
3885 err
= (object
->*func
)( input
, output
,
3886 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
3888 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
3891 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
3900 kern_return_t
shim_io_async_method_structureI_structureO(
3901 IOExternalAsyncMethod
* method
,
3903 mach_port_t asyncWakePort
,
3904 io_user_reference_t
* asyncReference
,
3905 uint32_t asyncReferenceCount
,
3906 io_struct_inband_t input
,
3907 mach_msg_type_number_t inputCount
,
3908 io_struct_inband_t output
,
3909 mach_msg_type_number_t
* outputCount
)
3914 io_async_ref_t reference
;
3916 for (i
= 0; i
< asyncReferenceCount
; i
++)
3917 reference
[i
] = REF32(asyncReference
[i
]);
3919 err
= kIOReturnBadArgument
;
3922 if( (kIOUCVariableStructureSize
!= method
->count0
)
3923 && (inputCount
!= method
->count0
))
3925 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3928 if( (kIOUCVariableStructureSize
!= method
->count1
)
3929 && (*outputCount
!= method
->count1
))
3931 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3935 func
= method
->func
;
3937 if( method
->count1
) {
3938 if( method
->count0
) {
3939 err
= (object
->*func
)( reference
,
3941 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
3943 err
= (object
->*func
)( reference
,
3944 output
, outputCount
, 0, 0, 0, 0 );
3947 err
= (object
->*func
)( reference
,
3948 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
3956 /* Routine io_catalog_send_data */
3957 kern_return_t
is_io_catalog_send_data(
3958 mach_port_t master_port
,
3960 io_buf_ptr_t inData
,
3961 mach_msg_type_number_t inDataCount
,
3962 kern_return_t
* result
)
3966 kern_return_t kr
= kIOReturnError
;
3968 //printf("io_catalog_send_data called. flag: %d\n", flag);
3970 if( master_port
!= master_device_port
)
3971 return kIOReturnNotPrivileged
;
3973 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
3974 flag
!= kIOCatalogKextdActive
&&
3975 flag
!= kIOCatalogKextdFinishedLaunching
) &&
3976 ( !inData
|| !inDataCount
) )
3978 return kIOReturnBadArgument
;
3982 vm_map_offset_t map_data
;
3984 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
3985 return( kIOReturnMessageTooLarge
);
3987 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
3988 data
= CAST_DOWN(vm_offset_t
, map_data
);
3990 if( kr
!= KERN_SUCCESS
)
3993 // must return success after vm_map_copyout() succeeds
3996 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
3997 vm_deallocate( kernel_map
, data
, inDataCount
);
3999 *result
= kIOReturnNoMemory
;
4000 return( KERN_SUCCESS
);
4006 case kIOCatalogResetDrivers
:
4007 case kIOCatalogResetDriversNoMatch
: {
4010 array
= OSDynamicCast(OSArray
, obj
);
4012 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4013 flag
== kIOCatalogResetDrivers
) ) {
4015 kr
= kIOReturnError
;
4018 kr
= kIOReturnBadArgument
;
4023 case kIOCatalogAddDrivers
:
4024 case kIOCatalogAddDriversNoMatch
: {
4027 array
= OSDynamicCast(OSArray
, obj
);
4029 if ( !gIOCatalogue
->addDrivers( array
,
4030 flag
== kIOCatalogAddDrivers
) ) {
4031 kr
= kIOReturnError
;
4035 kr
= kIOReturnBadArgument
;
4040 case kIOCatalogRemoveDrivers
:
4041 case kIOCatalogRemoveDriversNoMatch
: {
4042 OSDictionary
* dict
;
4044 dict
= OSDynamicCast(OSDictionary
, obj
);
4046 if ( !gIOCatalogue
->removeDrivers( dict
,
4047 flag
== kIOCatalogRemoveDrivers
) ) {
4048 kr
= kIOReturnError
;
4052 kr
= kIOReturnBadArgument
;
4057 case kIOCatalogStartMatching
: {
4058 OSDictionary
* dict
;
4060 dict
= OSDynamicCast(OSDictionary
, obj
);
4062 if ( !gIOCatalogue
->startMatching( dict
) ) {
4063 kr
= kIOReturnError
;
4067 kr
= kIOReturnBadArgument
;
4072 case kIOCatalogRemoveKernelLinker
:
4073 kr
= KERN_NOT_SUPPORTED
;
4076 case kIOCatalogKextdActive
:
4078 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
4079 OSKext::setKextdActive();
4081 /* Dump all nonloaded startup extensions; kextd will now send them
4084 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4086 kr
= kIOReturnSuccess
;
4089 case kIOCatalogKextdFinishedLaunching
: {
4091 static bool clearedBusy
= false;
4094 IOService
* serviceRoot
= IOService::getServiceRoot();
4096 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
4097 serviceRoot
->adjustBusy(-1);
4102 kr
= kIOReturnSuccess
;
4107 kr
= kIOReturnBadArgument
;
4111 if (obj
) obj
->release();
4114 return( KERN_SUCCESS
);
4117 /* Routine io_catalog_terminate */
4118 kern_return_t
is_io_catalog_terminate(
4119 mach_port_t master_port
,
4125 if( master_port
!= master_device_port
)
4126 return kIOReturnNotPrivileged
;
4128 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
4129 kIOClientPrivilegeAdministrator
);
4130 if( kIOReturnSuccess
!= kr
)
4134 #if !defined(SECURE_KERNEL)
4135 case kIOCatalogServiceTerminate
:
4137 IOService
* service
;
4139 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
4140 kIORegistryIterateRecursively
);
4142 return kIOReturnNoMemory
;
4146 while( (service
= (IOService
*)iter
->getNextObject()) ) {
4147 if( service
->metaCast(name
)) {
4148 if ( !service
->terminate( kIOServiceRequired
4149 | kIOServiceSynchronous
) ) {
4150 kr
= kIOReturnUnsupported
;
4155 } while( !service
&& !iter
->isValid());
4159 case kIOCatalogModuleUnload
:
4160 case kIOCatalogModuleTerminate
:
4161 kr
= gIOCatalogue
->terminateDriversForModule(name
,
4162 flag
== kIOCatalogModuleUnload
);
4167 kr
= kIOReturnBadArgument
;
4174 /* Routine io_catalog_get_data */
4175 kern_return_t
is_io_catalog_get_data(
4176 mach_port_t master_port
,
4178 io_buf_ptr_t
*outData
,
4179 mach_msg_type_number_t
*outDataCount
)
4181 kern_return_t kr
= kIOReturnSuccess
;
4184 if( master_port
!= master_device_port
)
4185 return kIOReturnNotPrivileged
;
4187 //printf("io_catalog_get_data called. flag: %d\n", flag);
4189 s
= OSSerialize::withCapacity(4096);
4191 return kIOReturnNoMemory
;
4195 kr
= gIOCatalogue
->serializeData(flag
, s
);
4197 if ( kr
== kIOReturnSuccess
) {
4202 size
= s
->getLength();
4203 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
4204 if ( kr
== kIOReturnSuccess
) {
4205 bcopy(s
->text(), (void *)data
, size
);
4206 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
4207 (vm_map_size_t
)size
, true, ©
);
4208 *outData
= (char *)copy
;
4209 *outDataCount
= size
;
4218 /* Routine io_catalog_get_gen_count */
4219 kern_return_t
is_io_catalog_get_gen_count(
4220 mach_port_t master_port
,
4223 if( master_port
!= master_device_port
)
4224 return kIOReturnNotPrivileged
;
4226 //printf("io_catalog_get_gen_count called.\n");
4229 return kIOReturnBadArgument
;
4231 *genCount
= gIOCatalogue
->getGenerationCount();
4233 return kIOReturnSuccess
;
4236 /* Routine io_catalog_module_loaded.
4237 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
4239 kern_return_t
is_io_catalog_module_loaded(
4240 mach_port_t master_port
,
4243 if( master_port
!= master_device_port
)
4244 return kIOReturnNotPrivileged
;
4246 //printf("io_catalog_module_loaded called. name %s\n", name);
4249 return kIOReturnBadArgument
;
4251 gIOCatalogue
->moduleHasLoaded(name
);
4253 return kIOReturnSuccess
;
4256 kern_return_t
is_io_catalog_reset(
4257 mach_port_t master_port
,
4260 if( master_port
!= master_device_port
)
4261 return kIOReturnNotPrivileged
;
4264 case kIOCatalogResetDefault
:
4265 gIOCatalogue
->reset();
4269 return kIOReturnBadArgument
;
4272 return kIOReturnSuccess
;
4275 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
4277 kern_return_t result
= kIOReturnBadArgument
;
4278 IOUserClient
*userClient
;
4280 if ((userClient
= OSDynamicCast(IOUserClient
,
4281 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
4282 IOExternalTrap
*trap
;
4283 IOService
*target
= NULL
;
4285 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
4287 if (trap
&& target
) {
4293 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
4297 userClient
->release();
4305 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
4306 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
4310 IOByteCount structureOutputSize
;
4315 count
= dispatch
->checkScalarInputCount
;
4316 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
4318 return (kIOReturnBadArgument
);
4321 count
= dispatch
->checkStructureInputSize
;
4322 if ((kIOUCVariableStructureSize
!= count
)
4323 && (count
!= ((args
->structureInputDescriptor
)
4324 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
4326 return (kIOReturnBadArgument
);
4329 count
= dispatch
->checkScalarOutputCount
;
4330 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
4332 return (kIOReturnBadArgument
);
4335 count
= dispatch
->checkStructureOutputSize
;
4336 if ((kIOUCVariableStructureSize
!= count
)
4337 && (count
!= ((args
->structureOutputDescriptor
)
4338 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
4340 return (kIOReturnBadArgument
);
4343 if (dispatch
->function
)
4344 err
= (*dispatch
->function
)(target
, reference
, args
);
4346 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
4352 // pre-Leopard API's don't do ool structs
4353 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
4355 err
= kIOReturnIPCError
;
4359 structureOutputSize
= args
->structureOutputSize
;
4361 if (args
->asyncWakePort
)
4363 IOExternalAsyncMethod
* method
;
4365 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) )
4366 return (kIOReturnUnsupported
);
4368 if (kIOUCForegroundOnly
& method
->flags
)
4370 /* is graphics access denied for current task? */
4371 if (proc_get_effective_task_policy(current_task(), TASK_POLICY_GPU_DENY
) != 0)
4372 return (kIOReturnNotPermitted
);
4375 switch (method
->flags
& kIOUCTypeMask
)
4377 case kIOUCScalarIStructI
:
4378 err
= shim_io_async_method_scalarI_structureI( method
, object
,
4379 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4380 args
->scalarInput
, args
->scalarInputCount
,
4381 (char *)args
->structureInput
, args
->structureInputSize
);
4384 case kIOUCScalarIScalarO
:
4385 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
4386 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4387 args
->scalarInput
, args
->scalarInputCount
,
4388 args
->scalarOutput
, &args
->scalarOutputCount
);
4391 case kIOUCScalarIStructO
:
4392 err
= shim_io_async_method_scalarI_structureO( method
, object
,
4393 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4394 args
->scalarInput
, args
->scalarInputCount
,
4395 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4399 case kIOUCStructIStructO
:
4400 err
= shim_io_async_method_structureI_structureO( method
, object
,
4401 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4402 (char *)args
->structureInput
, args
->structureInputSize
,
4403 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4407 err
= kIOReturnBadArgument
;
4413 IOExternalMethod
* method
;
4415 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) )
4416 return (kIOReturnUnsupported
);
4418 if (kIOUCForegroundOnly
& method
->flags
)
4420 /* is graphics access denied for current task? */
4421 if (proc_get_effective_task_policy(current_task(), TASK_POLICY_GPU_DENY
) != 0)
4422 return (kIOReturnNotPermitted
);
4426 switch (method
->flags
& kIOUCTypeMask
)
4428 case kIOUCScalarIStructI
:
4429 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
4430 args
->scalarInput
, args
->scalarInputCount
,
4431 (char *) args
->structureInput
, args
->structureInputSize
);
4434 case kIOUCScalarIScalarO
:
4435 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
4436 args
->scalarInput
, args
->scalarInputCount
,
4437 args
->scalarOutput
, &args
->scalarOutputCount
);
4440 case kIOUCScalarIStructO
:
4441 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
4442 args
->scalarInput
, args
->scalarInputCount
,
4443 (char *) args
->structureOutput
, &structureOutputSize
);
4447 case kIOUCStructIStructO
:
4448 err
= shim_io_connect_method_structureI_structureO( method
, object
,
4449 (char *) args
->structureInput
, args
->structureInputSize
,
4450 (char *) args
->structureOutput
, &structureOutputSize
);
4454 err
= kIOReturnBadArgument
;
4459 args
->structureOutputSize
= structureOutputSize
;
4466 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
4467 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
4469 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
4470 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
4472 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
4473 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
4474 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
4475 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
4476 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
4477 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
4478 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
4479 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
4480 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
4481 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
4482 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
4483 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
4484 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
4485 OSMetaClassDefineReservedUnused(IOUserClient
, 15);