2 * Copyright (c) 1998-2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <libkern/c++/OSKext.h>
31 #include <IOKit/IOKitServer.h>
32 #include <IOKit/IOKitKeysPrivate.h>
33 #include <IOKit/IOUserClient.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IORegistryEntry.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOMemoryDescriptor.h>
38 #include <IOKit/IOBufferMemoryDescriptor.h>
39 #include <IOKit/IOLib.h>
40 #include <IOKit/IOStatisticsPrivate.h>
41 #include <IOKit/IOTimeStamp.h>
42 #include <IOKit/system.h>
43 #include <libkern/OSDebug.h>
45 #include <sys/kauth.h>
46 #include <sys/codesign.h>
51 #include <security/mac_framework.h>
53 #include <sys/kauth.h>
57 #endif /* CONFIG_MACF */
59 #include <IOKit/assert.h>
61 #include "IOServicePrivate.h"
62 #include "IOKitKernelInternal.h"
64 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
65 #define SCALAR32(x) ((uint32_t )x)
66 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
67 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
68 #define REF32(x) ((int)(x))
72 kIOUCAsync0Flags
= 3ULL,
73 kIOUCAsync64Flag
= 1ULL
78 #define IOStatisticsRegisterCounter() \
80 reserved->counter = IOStatistics::registerUserClient(this); \
83 #define IOStatisticsUnregisterCounter() \
86 IOStatistics::unregisterUserClient(reserved->counter); \
89 #define IOStatisticsClientCall() \
91 IOStatistics::countUserClientCall(client); \
96 #define IOStatisticsRegisterCounter()
97 #define IOStatisticsUnregisterCounter()
98 #define IOStatisticsClientCall()
100 #endif /* IOKITSTATS */
102 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 // definitions we should get from osfmk
106 //typedef struct ipc_port * ipc_port_t;
107 typedef natural_t ipc_kobject_type_t
;
109 #define IKOT_IOKIT_SPARE 27
110 #define IKOT_IOKIT_CONNECT 29
111 #define IKOT_IOKIT_OBJECT 30
115 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
116 ipc_kobject_type_t type
);
118 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
120 extern mach_port_name_t
iokit_make_send_right( task_t task
,
121 io_object_t obj
, ipc_kobject_type_t type
);
123 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
125 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
127 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
129 extern ipc_port_t master_device_port
;
131 extern void iokit_retain_port( ipc_port_t port
);
132 extern void iokit_release_port( ipc_port_t port
);
133 extern void iokit_release_port_send( ipc_port_t port
);
135 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
137 #include <mach/mach_traps.h>
138 #include <vm/vm_map.h>
143 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
145 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
147 class IOMachPort
: public OSObject
149 OSDeclareDefaultStructors(IOMachPort
)
156 static IOMachPort
* portForObject( OSObject
* obj
,
157 ipc_kobject_type_t type
);
158 static bool noMoreSendersForObject( OSObject
* obj
,
159 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
160 static void releasePortForObject( OSObject
* obj
,
161 ipc_kobject_type_t type
);
162 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
164 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
166 static mach_port_name_t
makeSendRightForTask( task_t task
,
167 io_object_t obj
, ipc_kobject_type_t type
);
169 virtual void free() APPLE_KEXT_OVERRIDE
;
172 #define super OSObject
173 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
175 static IOLock
* gIOObjectPortLock
;
177 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
179 // not in dictForType() for debugging ease
180 static OSDictionary
* gIOObjectPorts
;
181 static OSDictionary
* gIOConnectPorts
;
183 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
185 OSDictionary
** dict
;
187 if( IKOT_IOKIT_OBJECT
== type
)
188 dict
= &gIOObjectPorts
;
189 else if( IKOT_IOKIT_CONNECT
== type
)
190 dict
= &gIOConnectPorts
;
195 *dict
= OSDictionary::withCapacity( 1 );
200 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
201 ipc_kobject_type_t type
)
203 IOMachPort
* inst
= 0;
206 IOTakeLock( gIOObjectPortLock
);
210 dict
= dictForType( type
);
214 if( (inst
= (IOMachPort
*)
215 dict
->getObject( (const OSSymbol
*) obj
))) {
221 inst
= new IOMachPort
;
222 if( inst
&& !inst
->init()) {
227 inst
->port
= iokit_alloc_object_port( obj
, type
);
230 dict
->setObject( (const OSSymbol
*) obj
, inst
);
240 IOUnlock( gIOObjectPortLock
);
245 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
246 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
249 IOMachPort
* machPort
;
250 bool destroyed
= true;
252 IOTakeLock( gIOObjectPortLock
);
254 if( (dict
= dictForType( type
))) {
257 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
259 destroyed
= (machPort
->mscount
<= *mscount
);
261 dict
->removeObject( (const OSSymbol
*) obj
);
263 *mscount
= machPort
->mscount
;
268 IOUnlock( gIOObjectPortLock
);
273 void IOMachPort::releasePortForObject( OSObject
* obj
,
274 ipc_kobject_type_t type
)
277 IOMachPort
* machPort
;
279 IOTakeLock( gIOObjectPortLock
);
281 if( (dict
= dictForType( type
))) {
283 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
284 if( machPort
&& !machPort
->holdDestroy
)
285 dict
->removeObject( (const OSSymbol
*) obj
);
289 IOUnlock( gIOObjectPortLock
);
292 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
295 IOMachPort
* machPort
;
297 IOLockLock( gIOObjectPortLock
);
299 if( (dict
= dictForType( type
))) {
300 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
302 machPort
->holdDestroy
= true;
305 IOLockUnlock( gIOObjectPortLock
);
308 void IOUserClient::destroyUserReferences( OSObject
* obj
)
310 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
313 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
317 IOTakeLock( gIOObjectPortLock
);
320 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
323 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
327 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
329 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
330 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
332 uc
->mappings
->release();
335 dict
->removeObject( (const OSSymbol
*) obj
);
339 IOUnlock( gIOObjectPortLock
);
342 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
343 io_object_t obj
, ipc_kobject_type_t type
)
345 return( iokit_make_send_right( task
, obj
, type
));
348 void IOMachPort::free( void )
351 iokit_destroy_object_port( port
);
355 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
357 class IOUserIterator
: public OSIterator
359 OSDeclareDefaultStructors(IOUserIterator
)
361 OSObject
* userIteratorObject
;
364 static IOUserIterator
* withIterator(OSIterator
* iter
);
365 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
366 virtual void free() APPLE_KEXT_OVERRIDE
;
368 virtual void reset() APPLE_KEXT_OVERRIDE
;
369 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
370 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
373 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
375 class IOUserNotification
: public IOUserIterator
377 OSDeclareDefaultStructors(IOUserNotification
)
379 #define holdNotify userIteratorObject
383 virtual void free() APPLE_KEXT_OVERRIDE
;
385 virtual void setNotification( IONotifier
* obj
);
387 virtual void reset() APPLE_KEXT_OVERRIDE
;
388 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
391 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
393 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
396 IOUserIterator::withIterator(OSIterator
* iter
)
400 if (!iter
) return (0);
402 me
= new IOUserIterator
;
403 if (me
&& !me
->init())
409 me
->userIteratorObject
= iter
;
415 IOUserIterator::init( void )
417 if (!OSObject::init()) return (false);
419 lock
= IOLockAlloc();
427 IOUserIterator::free()
429 if (userIteratorObject
) userIteratorObject
->release();
430 if (lock
) IOLockFree(lock
);
435 IOUserIterator::reset()
438 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
439 ((OSIterator
*)userIteratorObject
)->reset();
444 IOUserIterator::isValid()
449 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
450 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
457 IOUserIterator::getNextObject()
462 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
463 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
469 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
472 // functions called from osfmk/device/iokit_rpc.c
475 iokit_add_reference( io_object_t obj
)
482 iokit_remove_reference( io_object_t obj
)
489 iokit_add_connect_reference( io_object_t obj
)
495 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) OSIncrementAtomic(&uc
->__ipc
);
501 iokit_remove_connect_reference( io_object_t obj
)
504 bool finalize
= false;
508 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
510 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive())
512 IOLockLock(gIOObjectPortLock
);
513 if ((finalize
= uc
->__ipcFinal
)) uc
->__ipcFinal
= false;
514 IOLockUnlock(gIOObjectPortLock
);
516 if (finalize
) uc
->scheduleFinalize(true);
523 IOUserClient::finalizeUserReferences(OSObject
* obj
)
528 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
530 IOLockLock(gIOObjectPortLock
);
531 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) ok
= false;
532 IOLockUnlock(gIOObjectPortLock
);
538 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
540 IOMachPort
* machPort
;
543 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
545 port
= machPort
->port
;
547 iokit_retain_port( port
);
558 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
559 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
561 IOUserClient
* client
;
563 IOUserNotification
* notify
;
565 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
566 return( kIOReturnNotReady
);
568 if( IKOT_IOKIT_CONNECT
== type
)
570 if( (client
= OSDynamicCast( IOUserClient
, obj
))) {
571 IOStatisticsClientCall();
572 client
->clientDied();
575 else if( IKOT_IOKIT_OBJECT
== type
)
577 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
579 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
580 notify
->setNotification( 0 );
583 return( kIOReturnSuccess
);
588 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
590 class IOServiceUserNotification
: public IOUserNotification
592 OSDeclareDefaultStructors(IOServiceUserNotification
)
595 mach_msg_header_t msgHdr
;
596 OSNotificationHeader64 notifyHeader
;
599 enum { kMaxOutstanding
= 1024 };
604 OSObject
* lastEntry
;
609 virtual bool init( mach_port_t port
, natural_t type
,
610 void * reference
, vm_size_t referenceSize
,
612 virtual void free() APPLE_KEXT_OVERRIDE
;
614 static bool _handler( void * target
,
615 void * ref
, IOService
* newService
, IONotifier
* notifier
);
616 virtual bool handler( void * ref
, IOService
* newService
);
618 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
621 class IOServiceMessageUserNotification
: public IOUserNotification
623 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
626 mach_msg_header_t msgHdr
;
627 mach_msg_body_t msgBody
;
628 mach_msg_port_descriptor_t ports
[1];
629 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
639 virtual bool init( mach_port_t port
, natural_t type
,
640 void * reference
, vm_size_t referenceSize
,
644 virtual void free() APPLE_KEXT_OVERRIDE
;
646 static IOReturn
_handler( void * target
, void * ref
,
647 UInt32 messageType
, IOService
* provider
,
648 void * messageArgument
, vm_size_t argSize
);
649 virtual IOReturn
handler( void * ref
,
650 UInt32 messageType
, IOService
* provider
,
651 void * messageArgument
, vm_size_t argSize
);
653 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
656 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
659 #define super IOUserIterator
660 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
661 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
663 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
665 void IOUserNotification::free( void )
669 assert(OSDynamicCast(IONotifier
, holdNotify
));
670 ((IONotifier
*)holdNotify
)->remove();
673 // can't be in handler now
679 void IOUserNotification::setNotification( IONotifier
* notify
)
681 OSObject
* previousNotify
;
683 IOLockLock( gIOObjectPortLock
);
685 previousNotify
= holdNotify
;
688 IOLockUnlock( gIOObjectPortLock
);
692 assert(OSDynamicCast(IONotifier
, previousNotify
));
693 ((IONotifier
*)previousNotify
)->remove();
697 void IOUserNotification::reset()
702 bool IOUserNotification::isValid()
707 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
710 #define super IOUserNotification
711 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
713 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
715 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
716 void * reference
, vm_size_t referenceSize
,
722 newSet
= OSArray::withCapacity( 1 );
726 if (referenceSize
> sizeof(OSAsyncReference64
))
729 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
730 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
734 bzero( pingMsg
, msgSize
);
736 pingMsg
->msgHdr
.msgh_remote_port
= port
;
737 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
738 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
739 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
740 pingMsg
->msgHdr
.msgh_size
= msgSize
;
741 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
743 pingMsg
->notifyHeader
.size
= 0;
744 pingMsg
->notifyHeader
.type
= type
;
745 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
750 void IOServiceUserNotification::free( void )
755 OSObject
* _lastEntry
;
759 _lastEntry
= lastEntry
;
764 if( _pingMsg
&& _msgSize
) {
765 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
766 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
768 IOFree(_pingMsg
, _msgSize
);
772 _lastEntry
->release();
778 bool IOServiceUserNotification::_handler( void * target
,
779 void * ref
, IOService
* newService
, IONotifier
* notifier
)
781 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
784 bool IOServiceUserNotification::handler( void * ref
,
785 IOService
* newService
)
789 ipc_port_t port
= NULL
;
790 bool sendPing
= false;
794 count
= newSet
->getCount();
795 if( count
< kMaxOutstanding
) {
797 newSet
->setObject( newService
);
798 if( (sendPing
= (armed
&& (0 == count
))))
804 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
805 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
808 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
809 pingMsg
->msgHdr
.msgh_local_port
= port
;
811 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
813 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
814 pingMsg
->msgHdr
.msgh_size
,
815 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
818 iokit_release_port( port
);
820 if( KERN_SUCCESS
!= kr
)
821 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
827 OSObject
* IOServiceUserNotification::getNextObject()
835 lastEntry
->release();
837 count
= newSet
->getCount();
839 result
= newSet
->getObject( count
- 1 );
841 newSet
->removeObject( count
- 1);
853 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
855 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
857 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
859 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
860 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
866 if (referenceSize
> sizeof(OSAsyncReference64
))
869 clientIs64
= client64
;
871 owningPID
= proc_selfpid();
873 extraSize
+= sizeof(IOServiceInterestContent64
);
874 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
+ extraSize
;
875 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
879 bzero( pingMsg
, msgSize
);
881 pingMsg
->msgHdr
.msgh_remote_port
= port
;
882 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
884 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
885 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
886 pingMsg
->msgHdr
.msgh_size
= msgSize
;
887 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
889 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
891 pingMsg
->ports
[0].name
= 0;
892 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
893 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
895 pingMsg
->notifyHeader
.size
= extraSize
;
896 pingMsg
->notifyHeader
.type
= type
;
897 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
902 void IOServiceMessageUserNotification::free( void )
912 if( _pingMsg
&& _msgSize
) {
913 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
914 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
916 IOFree( _pingMsg
, _msgSize
);
920 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
921 UInt32 messageType
, IOService
* provider
,
922 void * argument
, vm_size_t argSize
)
924 return( ((IOServiceMessageUserNotification
*) target
)->handler(
925 ref
, messageType
, provider
, argument
, argSize
));
928 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
929 UInt32 messageType
, IOService
* provider
,
930 void * messageArgument
, vm_size_t argSize
)
933 ipc_port_t thisPort
, providerPort
;
934 IOServiceInterestContent64
* data
= (IOServiceInterestContent64
*)
935 ((((uint8_t *) pingMsg
) + msgSize
) - pingMsg
->notifyHeader
.size
);
936 // == pingMsg->notifyHeader.content;
938 if (kIOMessageCopyClientID
== messageType
)
940 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
941 return (kIOReturnSuccess
);
944 data
->messageType
= messageType
;
948 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
950 argSize
= sizeof(data
->messageArgument
[0]);
953 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
954 argSize
= sizeof(uint32_t);
959 if( argSize
> kIOUserNotifyMaxMessageSize
)
960 argSize
= kIOUserNotifyMaxMessageSize
;
961 bcopy( messageArgument
, data
->messageArgument
, argSize
);
964 // adjust message size for ipc restrictions
966 type
= pingMsg
->notifyHeader
.type
;
967 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
968 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
969 pingMsg
->notifyHeader
.type
= type
;
970 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
972 pingMsg
->msgHdr
.msgh_size
= msgSize
- pingMsg
->notifyHeader
.size
973 + sizeof( IOServiceInterestContent64
)
974 - sizeof( data
->messageArgument
)
977 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
978 pingMsg
->ports
[0].name
= providerPort
;
979 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
980 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
981 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
982 pingMsg
->msgHdr
.msgh_size
,
983 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
986 iokit_release_port( thisPort
);
988 iokit_release_port( providerPort
);
990 if( KERN_SUCCESS
!= kr
)
991 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
993 return( kIOReturnSuccess
);
996 OSObject
* IOServiceMessageUserNotification::getNextObject()
1001 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1004 #define super IOService
1005 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1007 void IOUserClient::initialize( void )
1009 gIOObjectPortLock
= IOLockAlloc();
1011 assert( gIOObjectPortLock
);
1014 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1015 mach_port_t wakePort
,
1016 void *callback
, void *refcon
)
1018 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1019 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1020 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1021 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1024 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1025 mach_port_t wakePort
,
1026 mach_vm_address_t callback
, io_user_reference_t refcon
)
1028 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1029 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1030 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1031 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1034 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1035 mach_port_t wakePort
,
1036 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1038 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1039 if (vm_map_is_64bit(get_task_map(task
))) {
1040 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1044 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
1047 OSDictionary
* user
= 0;
1049 if ((array
= OSDynamicCast(OSArray
,
1050 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1052 for (unsigned int idx
= 0;
1053 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1057 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1058 && (uid
== num
->unsigned32BitValue())) {
1068 static OSDictionary
* CopyUserOnConsole(void)
1071 OSDictionary
* user
= 0;
1073 if ((array
= OSDynamicCast(OSArray
,
1074 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1076 for (unsigned int idx
= 0;
1077 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1080 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
1091 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
1092 IOService
* service
)
1096 p
= (proc_t
) get_bsdtask_info(task
);
1099 uint64_t authorizationID
;
1101 authorizationID
= proc_uniqueid(p
);
1102 if (authorizationID
)
1104 if (service
->getAuthorizationID() == authorizationID
)
1106 return (kIOReturnSuccess
);
1111 return (kIOReturnNotPermitted
);
1114 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
1115 const char * privilegeName
)
1118 security_token_t token
;
1119 mach_msg_type_number_t count
;
1121 OSDictionary
* user
;
1125 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1126 sizeof(kIOClientPrivilegeForeground
)))
1128 if (task_is_gpu_denied(current_task()))
1129 return (kIOReturnNotPrivileged
);
1131 return (kIOReturnSuccess
);
1134 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1135 sizeof(kIOClientPrivilegeConsoleSession
)))
1140 task
= (task_t
) securityToken
;
1142 task
= current_task();
1143 p
= (proc_t
) get_bsdtask_info(task
);
1144 kr
= kIOReturnNotPrivileged
;
1146 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1148 user
= CopyUserOnConsole();
1152 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1153 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1155 kr
= kIOReturnSuccess
;
1159 kauth_cred_unref(&cred
);
1164 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1165 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1166 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1168 task
= (task_t
)securityToken
;
1170 count
= TASK_SECURITY_TOKEN_COUNT
;
1171 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1173 if (KERN_SUCCESS
!= kr
)
1175 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1176 sizeof(kIOClientPrivilegeAdministrator
))) {
1177 if (0 != token
.val
[0])
1178 kr
= kIOReturnNotPrivileged
;
1179 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1180 sizeof(kIOClientPrivilegeLocalUser
))) {
1181 user
= CopyConsoleUser(token
.val
[0]);
1185 kr
= kIOReturnNotPrivileged
;
1186 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1187 sizeof(kIOClientPrivilegeConsoleUser
))) {
1188 user
= CopyConsoleUser(token
.val
[0]);
1190 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1191 kr
= kIOReturnNotPrivileged
;
1192 else if ( secureConsole
) {
1193 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1194 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1195 kr
= kIOReturnNotPrivileged
;
1200 kr
= kIOReturnNotPrivileged
;
1202 kr
= kIOReturnUnsupported
;
1207 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1208 const char * entitlement
)
1210 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1214 char procname
[MAXCOMLEN
+ 1] = "";
1216 void *entitlements_blob
= NULL
;
1217 char *entitlements_data
= NULL
;
1218 OSObject
*entitlements_obj
= NULL
;
1219 OSDictionary
*entitlements
= NULL
;
1220 OSString
*errorString
= NULL
;
1221 OSObject
*value
= NULL
;
1223 p
= (proc_t
)get_bsdtask_info(task
);
1227 proc_name(pid
, procname
, (int)sizeof(procname
));
1229 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1232 if (len
<= offsetof(CS_GenericBlob
, data
))
1236 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1237 * we'll try to parse in the kernel.
1239 len
-= offsetof(CS_GenericBlob
, data
);
1240 if (len
> MAX_ENTITLEMENTS_LEN
) {
1241 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1246 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1247 * what is stored in the entitlements blob. Copy the string and
1250 entitlements_data
= (char *)IOMalloc(len
+ 1);
1251 if (entitlements_data
== NULL
)
1253 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1254 entitlements_data
[len
] = '\0';
1256 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1257 if (errorString
!= NULL
) {
1258 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1261 if (entitlements_obj
== NULL
)
1264 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1265 if (entitlements
== NULL
)
1268 /* Fetch the entitlement value from the dictionary. */
1269 value
= entitlements
->getObject(entitlement
);
1274 if (entitlements_data
!= NULL
)
1275 IOFree(entitlements_data
, len
+ 1);
1276 if (entitlements_obj
!= NULL
)
1277 entitlements_obj
->release();
1278 if (errorString
!= NULL
)
1279 errorString
->release();
1283 bool IOUserClient::init()
1285 if (getPropertyTable() || super::init())
1291 bool IOUserClient::init(OSDictionary
* dictionary
)
1293 if (getPropertyTable() || super::init(dictionary
))
1299 bool IOUserClient::initWithTask(task_t owningTask
,
1303 if (getPropertyTable() || super::init())
1309 bool IOUserClient::initWithTask(task_t owningTask
,
1312 OSDictionary
* properties
)
1316 ok
= super::init( properties
);
1317 ok
&= initWithTask( owningTask
, securityID
, type
);
1322 bool IOUserClient::reserve()
1325 reserved
= IONew(ExpansionData
, 1);
1330 setTerminateDefer(NULL
, true);
1331 IOStatisticsRegisterCounter();
1336 void IOUserClient::free()
1339 mappings
->release();
1341 IOStatisticsUnregisterCounter();
1344 IODelete(reserved
, ExpansionData
, 1);
1349 IOReturn
IOUserClient::clientDied( void )
1351 IOReturn ret
= kIOReturnNotReady
;
1353 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
))
1355 ret
= clientClose();
1361 IOReturn
IOUserClient::clientClose( void )
1363 return( kIOReturnUnsupported
);
1366 IOService
* IOUserClient::getService( void )
1371 IOReturn
IOUserClient::registerNotificationPort(
1372 mach_port_t
/* port */,
1374 UInt32
/* refCon */)
1376 return( kIOReturnUnsupported
);
1379 IOReturn
IOUserClient::registerNotificationPort(
1382 io_user_reference_t refCon
)
1384 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1387 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1388 semaphore_t
* semaphore
)
1390 return( kIOReturnUnsupported
);
1393 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1395 return( kIOReturnUnsupported
);
1398 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1399 IOOptionBits
* options
,
1400 IOMemoryDescriptor
** memory
)
1402 return( kIOReturnUnsupported
);
1406 IOMemoryMap
* IOUserClient::mapClientMemory(
1409 IOOptionBits mapFlags
,
1410 IOVirtualAddress atAddress
)
1416 IOMemoryMap
* IOUserClient::mapClientMemory64(
1419 IOOptionBits mapFlags
,
1420 mach_vm_address_t atAddress
)
1423 IOOptionBits options
= 0;
1424 IOMemoryDescriptor
* memory
;
1425 IOMemoryMap
* map
= 0;
1427 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1429 if( memory
&& (kIOReturnSuccess
== err
)) {
1431 options
= (options
& ~kIOMapUserOptionsMask
)
1432 | (mapFlags
& kIOMapUserOptionsMask
);
1433 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1440 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1441 OSObject
*obj
, io_object_t
*clientObj
)
1443 mach_port_name_t name
;
1445 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1447 *(mach_port_name_t
*)clientObj
= name
;
1448 return kIOReturnSuccess
;
1451 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1456 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1461 IOExternalMethod
* IOUserClient::
1462 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1464 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1467 *targetP
= (IOService
*) method
->object
;
1472 IOExternalAsyncMethod
* IOUserClient::
1473 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1475 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1478 *targetP
= (IOService
*) method
->object
;
1483 IOExternalTrap
* IOUserClient::
1484 getExternalTrapForIndex(UInt32 index
)
1489 IOExternalTrap
* IOUserClient::
1490 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1492 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1495 *targetP
= trap
->object
;
1501 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1504 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1506 if (MACH_PORT_NULL
!= port
)
1507 iokit_release_port_send(port
);
1509 return (kIOReturnSuccess
);
1512 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1514 if (MACH_PORT_NULL
!= port
)
1515 iokit_release_port_send(port
);
1517 return (kIOReturnSuccess
);
1520 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1521 IOReturn result
, void *args
[], UInt32 numArgs
)
1523 OSAsyncReference64 reference64
;
1524 io_user_reference_t args64
[kMaxAsyncArgs
];
1527 if (numArgs
> kMaxAsyncArgs
)
1528 return kIOReturnMessageTooLarge
;
1530 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1531 reference64
[idx
] = REF64(reference
[idx
]);
1533 for (idx
= 0; idx
< numArgs
; idx
++)
1534 args64
[idx
] = REF64(args
[idx
]);
1536 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1539 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1540 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1542 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1545 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1546 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1548 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1551 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1552 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1556 mach_msg_header_t msgHdr
;
1561 OSNotificationHeader notifyHdr
;
1562 IOAsyncCompletionContent asyncContent
;
1563 uint32_t args
[kMaxAsyncArgs
];
1567 OSNotificationHeader64 notifyHdr
;
1568 IOAsyncCompletionContent asyncContent
;
1569 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1574 mach_port_t replyPort
;
1577 // If no reply port, do nothing.
1578 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1579 if (replyPort
== MACH_PORT_NULL
)
1580 return kIOReturnSuccess
;
1582 if (numArgs
> kMaxAsyncArgs
)
1583 return kIOReturnMessageTooLarge
;
1585 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1587 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1588 replyMsg
.msgHdr
.msgh_local_port
= 0;
1589 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1590 if (kIOUCAsync64Flag
& reference
[0])
1592 replyMsg
.msgHdr
.msgh_size
=
1593 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1594 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1595 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1596 + numArgs
* sizeof(io_user_reference_t
);
1597 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1598 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1600 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1602 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1608 replyMsg
.msgHdr
.msgh_size
=
1609 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1610 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1612 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1613 + numArgs
* sizeof(uint32_t);
1614 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1616 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1617 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1619 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1621 for (idx
= 0; idx
< numArgs
; idx
++)
1622 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1625 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1626 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1627 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1629 /* Fail on full queue. */
1630 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1631 replyMsg
.msgHdr
.msgh_size
);
1633 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
))
1634 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1639 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1643 #define CHECK(cls,obj,out) \
1645 if( !(out = OSDynamicCast( cls, obj))) \
1646 return( kIOReturnBadArgument )
1648 #define CHECKLOCKED(cls,obj,out) \
1649 IOUserIterator * oIter; \
1651 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1652 return (kIOReturnBadArgument); \
1653 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
1654 return (kIOReturnBadArgument)
1656 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1658 // Create a vm_map_copy_t or kalloc'ed data for memory
1659 // to be copied out. ipc will free after the copyout.
1661 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1662 io_buf_ptr_t
* buf
)
1667 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1668 false /* src_destroy */, ©
);
1670 assert( err
== KERN_SUCCESS
);
1671 if( err
== KERN_SUCCESS
)
1672 *buf
= (char *) copy
;
1677 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1679 /* Routine io_server_version */
1680 kern_return_t
is_io_server_version(
1681 mach_port_t master_port
,
1684 *version
= IOKIT_SERVER_VERSION
;
1685 return (kIOReturnSuccess
);
1688 /* Routine io_object_get_class */
1689 kern_return_t
is_io_object_get_class(
1691 io_name_t className
)
1693 const OSMetaClass
* my_obj
= NULL
;
1696 return( kIOReturnBadArgument
);
1698 my_obj
= object
->getMetaClass();
1700 return (kIOReturnNotFound
);
1703 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1705 return( kIOReturnSuccess
);
1708 /* Routine io_object_get_superclass */
1709 kern_return_t
is_io_object_get_superclass(
1710 mach_port_t master_port
,
1712 io_name_t class_name
)
1714 const OSMetaClass
* my_obj
= NULL
;
1715 const OSMetaClass
* superclass
= NULL
;
1716 const OSSymbol
*my_name
= NULL
;
1717 const char *my_cstr
= NULL
;
1719 if (!obj_name
|| !class_name
)
1720 return (kIOReturnBadArgument
);
1722 if( master_port
!= master_device_port
)
1723 return( kIOReturnNotPrivileged
);
1725 my_name
= OSSymbol::withCString(obj_name
);
1728 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1732 superclass
= my_obj
->getSuperClass();
1736 return( kIOReturnNotFound
);
1739 my_cstr
= superclass
->getClassName();
1742 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1743 return( kIOReturnSuccess
);
1745 return (kIOReturnNotFound
);
1748 /* Routine io_object_get_bundle_identifier */
1749 kern_return_t
is_io_object_get_bundle_identifier(
1750 mach_port_t master_port
,
1752 io_name_t bundle_name
)
1754 const OSMetaClass
* my_obj
= NULL
;
1755 const OSSymbol
*my_name
= NULL
;
1756 const OSSymbol
*identifier
= NULL
;
1757 const char *my_cstr
= NULL
;
1759 if (!obj_name
|| !bundle_name
)
1760 return (kIOReturnBadArgument
);
1762 if( master_port
!= master_device_port
)
1763 return( kIOReturnNotPrivileged
);
1765 my_name
= OSSymbol::withCString(obj_name
);
1768 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1773 identifier
= my_obj
->getKmodName();
1776 return( kIOReturnNotFound
);
1779 my_cstr
= identifier
->getCStringNoCopy();
1781 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1782 return( kIOReturnSuccess
);
1785 return (kIOReturnBadArgument
);
1788 /* Routine io_object_conforms_to */
1789 kern_return_t
is_io_object_conforms_to(
1791 io_name_t className
,
1792 boolean_t
*conforms
)
1795 return( kIOReturnBadArgument
);
1797 *conforms
= (0 != object
->metaCast( className
));
1799 return( kIOReturnSuccess
);
1802 /* Routine io_object_get_retain_count */
1803 kern_return_t
is_io_object_get_retain_count(
1805 uint32_t *retainCount
)
1808 return( kIOReturnBadArgument
);
1810 *retainCount
= object
->getRetainCount();
1811 return( kIOReturnSuccess
);
1814 /* Routine io_iterator_next */
1815 kern_return_t
is_io_iterator_next(
1816 io_object_t iterator
,
1817 io_object_t
*object
)
1822 CHECK( OSIterator
, iterator
, iter
);
1824 obj
= iter
->getNextObject();
1828 ret
= kIOReturnSuccess
;
1830 ret
= kIOReturnNoDevice
;
1835 /* Routine io_iterator_reset */
1836 kern_return_t
is_io_iterator_reset(
1837 io_object_t iterator
)
1839 CHECK( OSIterator
, iterator
, iter
);
1843 return( kIOReturnSuccess
);
1846 /* Routine io_iterator_is_valid */
1847 kern_return_t
is_io_iterator_is_valid(
1848 io_object_t iterator
,
1849 boolean_t
*is_valid
)
1851 CHECK( OSIterator
, iterator
, iter
);
1853 *is_valid
= iter
->isValid();
1855 return( kIOReturnSuccess
);
1859 static kern_return_t
internal_io_service_match_property_table(
1860 io_service_t _service
,
1861 const char * matching
,
1862 mach_msg_type_number_t matching_size
,
1865 CHECK( IOService
, _service
, service
);
1869 OSDictionary
* dict
;
1871 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1872 : OSUnserializeXML(matching
);
1873 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1874 *matches
= service
->passiveMatch( dict
);
1875 kr
= kIOReturnSuccess
;
1877 kr
= kIOReturnBadArgument
;
1885 /* Routine io_service_match_property_table */
1886 kern_return_t
is_io_service_match_property_table(
1887 io_service_t service
,
1888 io_string_t matching
,
1889 boolean_t
*matches
)
1891 return (internal_io_service_match_property_table(service
, matching
, 0, matches
));
1895 /* Routine io_service_match_property_table_ool */
1896 kern_return_t
is_io_service_match_property_table_ool(
1897 io_object_t service
,
1898 io_buf_ptr_t matching
,
1899 mach_msg_type_number_t matchingCnt
,
1900 kern_return_t
*result
,
1901 boolean_t
*matches
)
1905 vm_map_offset_t map_data
;
1907 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1908 data
= CAST_DOWN(vm_offset_t
, map_data
);
1910 if( KERN_SUCCESS
== kr
) {
1911 // must return success after vm_map_copyout() succeeds
1912 *result
= internal_io_service_match_property_table(service
,
1913 (const char *)data
, matchingCnt
, matches
);
1914 vm_deallocate( kernel_map
, data
, matchingCnt
);
1920 /* Routine io_service_match_property_table_bin */
1921 kern_return_t
is_io_service_match_property_table_bin(
1922 io_object_t service
,
1923 io_struct_inband_t matching
,
1924 mach_msg_type_number_t matchingCnt
,
1927 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
1930 static kern_return_t
internal_io_service_get_matching_services(
1931 mach_port_t master_port
,
1932 const char * matching
,
1933 mach_msg_type_number_t matching_size
,
1934 io_iterator_t
*existing
)
1938 OSDictionary
* dict
;
1940 if( master_port
!= master_device_port
)
1941 return( kIOReturnNotPrivileged
);
1943 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1944 : OSUnserializeXML(matching
);
1945 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1946 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
1947 kr
= kIOReturnSuccess
;
1949 kr
= kIOReturnBadArgument
;
1957 /* Routine io_service_get_matching_services */
1958 kern_return_t
is_io_service_get_matching_services(
1959 mach_port_t master_port
,
1960 io_string_t matching
,
1961 io_iterator_t
*existing
)
1963 return (internal_io_service_get_matching_services(master_port
, matching
, 0, existing
));
1966 /* Routine io_service_get_matching_services_ool */
1967 kern_return_t
is_io_service_get_matching_services_ool(
1968 mach_port_t master_port
,
1969 io_buf_ptr_t matching
,
1970 mach_msg_type_number_t matchingCnt
,
1971 kern_return_t
*result
,
1972 io_object_t
*existing
)
1976 vm_map_offset_t map_data
;
1978 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1979 data
= CAST_DOWN(vm_offset_t
, map_data
);
1981 if( KERN_SUCCESS
== kr
) {
1982 // must return success after vm_map_copyout() succeeds
1983 // and mig will copy out objects on success
1985 *result
= internal_io_service_get_matching_services(master_port
,
1986 (const char *) data
, matchingCnt
, existing
);
1987 vm_deallocate( kernel_map
, data
, matchingCnt
);
1993 /* Routine io_service_get_matching_services_bin */
1994 kern_return_t
is_io_service_get_matching_services_bin(
1995 mach_port_t master_port
,
1996 io_struct_inband_t matching
,
1997 mach_msg_type_number_t matchingCnt
,
1998 io_object_t
*existing
)
2000 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
2004 static kern_return_t
internal_io_service_get_matching_service(
2005 mach_port_t master_port
,
2006 const char * matching
,
2007 mach_msg_type_number_t matching_size
,
2008 io_service_t
*service
)
2012 OSDictionary
* dict
;
2014 if( master_port
!= master_device_port
)
2015 return( kIOReturnNotPrivileged
);
2017 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
2018 : OSUnserializeXML(matching
);
2019 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2020 *service
= IOService::copyMatchingService( dict
);
2021 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2023 kr
= kIOReturnBadArgument
;
2031 /* Routine io_service_get_matching_service */
2032 kern_return_t
is_io_service_get_matching_service(
2033 mach_port_t master_port
,
2034 io_string_t matching
,
2035 io_service_t
*service
)
2037 return (internal_io_service_get_matching_service(master_port
, matching
, 0, service
));
2040 /* Routine io_service_get_matching_services_ool */
2041 kern_return_t
is_io_service_get_matching_service_ool(
2042 mach_port_t master_port
,
2043 io_buf_ptr_t matching
,
2044 mach_msg_type_number_t matchingCnt
,
2045 kern_return_t
*result
,
2046 io_object_t
*service
)
2050 vm_map_offset_t map_data
;
2052 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2053 data
= CAST_DOWN(vm_offset_t
, map_data
);
2055 if( KERN_SUCCESS
== kr
) {
2056 // must return success after vm_map_copyout() succeeds
2057 // and mig will copy out objects on success
2059 *result
= internal_io_service_get_matching_service(master_port
,
2060 (const char *) data
, matchingCnt
, service
);
2061 vm_deallocate( kernel_map
, data
, matchingCnt
);
2067 /* Routine io_service_get_matching_service_bin */
2068 kern_return_t
is_io_service_get_matching_service_bin(
2069 mach_port_t master_port
,
2070 io_struct_inband_t matching
,
2071 mach_msg_type_number_t matchingCnt
,
2072 io_object_t
*service
)
2074 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
2077 static kern_return_t
internal_io_service_add_notification(
2078 mach_port_t master_port
,
2079 io_name_t notification_type
,
2080 const char * matching
,
2081 size_t matching_size
,
2084 vm_size_t referenceSize
,
2086 io_object_t
* notification
)
2088 IOServiceUserNotification
* userNotify
= 0;
2089 IONotifier
* notify
= 0;
2090 const OSSymbol
* sym
;
2091 OSDictionary
* dict
;
2093 unsigned long int userMsgType
;
2095 if( master_port
!= master_device_port
)
2096 return( kIOReturnNotPrivileged
);
2099 err
= kIOReturnNoResources
;
2101 if( !(sym
= OSSymbol::withCString( notification_type
)))
2102 err
= kIOReturnNoResources
;
2106 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2110 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
));
2114 err
= kIOReturnBadArgument
;
2118 if( (sym
== gIOPublishNotification
)
2119 || (sym
== gIOFirstPublishNotification
))
2120 userMsgType
= kIOServicePublishNotificationType
;
2121 else if( (sym
== gIOMatchedNotification
)
2122 || (sym
== gIOFirstMatchNotification
))
2123 userMsgType
= kIOServiceMatchedNotificationType
;
2124 else if( sym
== gIOTerminatedNotification
)
2125 userMsgType
= kIOServiceTerminatedNotificationType
;
2127 userMsgType
= kLastIOKitNotificationType
;
2129 userNotify
= new IOServiceUserNotification
;
2131 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
2132 reference
, referenceSize
, client64
)) {
2133 iokit_release_port_send(port
);
2134 userNotify
->release();
2140 notify
= IOService::addMatchingNotification( sym
, dict
,
2141 &userNotify
->_handler
, userNotify
);
2143 *notification
= userNotify
;
2144 userNotify
->setNotification( notify
);
2145 err
= kIOReturnSuccess
;
2147 err
= kIOReturnUnsupported
;
2160 /* Routine io_service_add_notification */
2161 kern_return_t
is_io_service_add_notification(
2162 mach_port_t master_port
,
2163 io_name_t notification_type
,
2164 io_string_t matching
,
2166 io_async_ref_t reference
,
2167 mach_msg_type_number_t referenceCnt
,
2168 io_object_t
* notification
)
2170 return (internal_io_service_add_notification(master_port
, notification_type
,
2171 matching
, 0, port
, &reference
[0], sizeof(io_async_ref_t
),
2172 false, notification
));
2175 /* Routine io_service_add_notification_64 */
2176 kern_return_t
is_io_service_add_notification_64(
2177 mach_port_t master_port
,
2178 io_name_t notification_type
,
2179 io_string_t matching
,
2180 mach_port_t wake_port
,
2181 io_async_ref64_t reference
,
2182 mach_msg_type_number_t referenceCnt
,
2183 io_object_t
*notification
)
2185 return (internal_io_service_add_notification(master_port
, notification_type
,
2186 matching
, 0, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2187 true, notification
));
2190 /* Routine io_service_add_notification_bin */
2191 kern_return_t is_io_service_add_notification_bin
2193 mach_port_t master_port
,
2194 io_name_t notification_type
,
2195 io_struct_inband_t matching
,
2196 mach_msg_type_number_t matchingCnt
,
2197 mach_port_t wake_port
,
2198 io_async_ref_t reference
,
2199 mach_msg_type_number_t referenceCnt
,
2200 io_object_t
*notification
)
2202 return (internal_io_service_add_notification(master_port
, notification_type
,
2203 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2204 false, notification
));
2207 /* Routine io_service_add_notification_bin_64 */
2208 kern_return_t is_io_service_add_notification_bin_64
2210 mach_port_t master_port
,
2211 io_name_t notification_type
,
2212 io_struct_inband_t matching
,
2213 mach_msg_type_number_t matchingCnt
,
2214 mach_port_t wake_port
,
2215 io_async_ref64_t reference
,
2216 mach_msg_type_number_t referenceCnt
,
2217 io_object_t
*notification
)
2219 return (internal_io_service_add_notification(master_port
, notification_type
,
2220 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2221 true, notification
));
2224 static kern_return_t
internal_io_service_add_notification_ool(
2225 mach_port_t master_port
,
2226 io_name_t notification_type
,
2227 io_buf_ptr_t matching
,
2228 mach_msg_type_number_t matchingCnt
,
2229 mach_port_t wake_port
,
2231 vm_size_t referenceSize
,
2233 kern_return_t
*result
,
2234 io_object_t
*notification
)
2238 vm_map_offset_t map_data
;
2240 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2241 data
= CAST_DOWN(vm_offset_t
, map_data
);
2243 if( KERN_SUCCESS
== kr
) {
2244 // must return success after vm_map_copyout() succeeds
2245 // and mig will copy out objects on success
2247 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2248 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2249 vm_deallocate( kernel_map
, data
, matchingCnt
);
2255 /* Routine io_service_add_notification_ool */
2256 kern_return_t
is_io_service_add_notification_ool(
2257 mach_port_t master_port
,
2258 io_name_t notification_type
,
2259 io_buf_ptr_t matching
,
2260 mach_msg_type_number_t matchingCnt
,
2261 mach_port_t wake_port
,
2262 io_async_ref_t reference
,
2263 mach_msg_type_number_t referenceCnt
,
2264 kern_return_t
*result
,
2265 io_object_t
*notification
)
2267 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2268 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2269 false, result
, notification
));
2272 /* Routine io_service_add_notification_ool_64 */
2273 kern_return_t
is_io_service_add_notification_ool_64(
2274 mach_port_t master_port
,
2275 io_name_t notification_type
,
2276 io_buf_ptr_t matching
,
2277 mach_msg_type_number_t matchingCnt
,
2278 mach_port_t wake_port
,
2279 io_async_ref64_t reference
,
2280 mach_msg_type_number_t referenceCnt
,
2281 kern_return_t
*result
,
2282 io_object_t
*notification
)
2284 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2285 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2286 true, result
, notification
));
2289 /* Routine io_service_add_notification_old */
2290 kern_return_t
is_io_service_add_notification_old(
2291 mach_port_t master_port
,
2292 io_name_t notification_type
,
2293 io_string_t matching
,
2295 // for binary compatibility reasons, this must be natural_t for ILP32
2297 io_object_t
* notification
)
2299 return( is_io_service_add_notification( master_port
, notification_type
,
2300 matching
, port
, &ref
, 1, notification
));
2304 static kern_return_t
internal_io_service_add_interest_notification(
2305 io_object_t _service
,
2306 io_name_t type_of_interest
,
2309 vm_size_t referenceSize
,
2311 io_object_t
* notification
)
2314 IOServiceMessageUserNotification
* userNotify
= 0;
2315 IONotifier
* notify
= 0;
2316 const OSSymbol
* sym
;
2319 CHECK( IOService
, _service
, service
);
2321 err
= kIOReturnNoResources
;
2322 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2324 userNotify
= new IOServiceMessageUserNotification
;
2326 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2327 reference
, referenceSize
,
2328 kIOUserNotifyMaxMessageSize
,
2330 iokit_release_port_send(port
);
2331 userNotify
->release();
2337 notify
= service
->registerInterest( sym
,
2338 &userNotify
->_handler
, userNotify
);
2340 *notification
= userNotify
;
2341 userNotify
->setNotification( notify
);
2342 err
= kIOReturnSuccess
;
2344 err
= kIOReturnUnsupported
;
2353 /* Routine io_service_add_message_notification */
2354 kern_return_t
is_io_service_add_interest_notification(
2355 io_object_t service
,
2356 io_name_t type_of_interest
,
2358 io_async_ref_t reference
,
2359 mach_msg_type_number_t referenceCnt
,
2360 io_object_t
* notification
)
2362 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2363 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2366 /* Routine io_service_add_interest_notification_64 */
2367 kern_return_t
is_io_service_add_interest_notification_64(
2368 io_object_t service
,
2369 io_name_t type_of_interest
,
2370 mach_port_t wake_port
,
2371 io_async_ref64_t reference
,
2372 mach_msg_type_number_t referenceCnt
,
2373 io_object_t
*notification
)
2375 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2376 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2380 /* Routine io_service_acknowledge_notification */
2381 kern_return_t
is_io_service_acknowledge_notification(
2382 io_object_t _service
,
2383 natural_t notify_ref
,
2384 natural_t response
)
2386 CHECK( IOService
, _service
, service
);
2388 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2389 (IOOptionBits
) response
));
2393 /* Routine io_connect_get_semaphore */
2394 kern_return_t
is_io_connect_get_notification_semaphore(
2395 io_connect_t connection
,
2396 natural_t notification_type
,
2397 semaphore_t
*semaphore
)
2399 CHECK( IOUserClient
, connection
, client
);
2401 IOStatisticsClientCall();
2402 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2406 /* Routine io_registry_get_root_entry */
2407 kern_return_t
is_io_registry_get_root_entry(
2408 mach_port_t master_port
,
2411 IORegistryEntry
* entry
;
2413 if( master_port
!= master_device_port
)
2414 return( kIOReturnNotPrivileged
);
2416 entry
= IORegistryEntry::getRegistryRoot();
2421 return( kIOReturnSuccess
);
2424 /* Routine io_registry_create_iterator */
2425 kern_return_t
is_io_registry_create_iterator(
2426 mach_port_t master_port
,
2429 io_object_t
*iterator
)
2431 if( master_port
!= master_device_port
)
2432 return( kIOReturnNotPrivileged
);
2434 *iterator
= IOUserIterator::withIterator(
2435 IORegistryIterator::iterateOver(
2436 IORegistryEntry::getPlane( plane
), options
));
2438 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2441 /* Routine io_registry_entry_create_iterator */
2442 kern_return_t
is_io_registry_entry_create_iterator(
2443 io_object_t registry_entry
,
2446 io_object_t
*iterator
)
2448 CHECK( IORegistryEntry
, registry_entry
, entry
);
2450 *iterator
= IOUserIterator::withIterator(
2451 IORegistryIterator::iterateOver( entry
,
2452 IORegistryEntry::getPlane( plane
), options
));
2454 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2457 /* Routine io_registry_iterator_enter */
2458 kern_return_t
is_io_registry_iterator_enter_entry(
2459 io_object_t iterator
)
2461 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2463 IOLockLock(oIter
->lock
);
2465 IOLockUnlock(oIter
->lock
);
2467 return( kIOReturnSuccess
);
2470 /* Routine io_registry_iterator_exit */
2471 kern_return_t
is_io_registry_iterator_exit_entry(
2472 io_object_t iterator
)
2476 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2478 IOLockLock(oIter
->lock
);
2479 didIt
= iter
->exitEntry();
2480 IOLockUnlock(oIter
->lock
);
2482 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2485 /* Routine io_registry_entry_from_path */
2486 kern_return_t
is_io_registry_entry_from_path(
2487 mach_port_t master_port
,
2489 io_object_t
*registry_entry
)
2491 IORegistryEntry
* entry
;
2493 if( master_port
!= master_device_port
)
2494 return( kIOReturnNotPrivileged
);
2496 entry
= IORegistryEntry::fromPath( path
);
2498 *registry_entry
= entry
;
2500 return( kIOReturnSuccess
);
2504 /* Routine io_registry_entry_from_path */
2505 kern_return_t
is_io_registry_entry_from_path_ool(
2506 mach_port_t master_port
,
2507 io_string_inband_t path
,
2508 io_buf_ptr_t path_ool
,
2509 mach_msg_type_number_t path_oolCnt
,
2510 kern_return_t
*result
,
2511 io_object_t
*registry_entry
)
2513 IORegistryEntry
* entry
;
2514 vm_map_offset_t map_data
;
2519 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2523 res
= err
= KERN_SUCCESS
;
2524 if (path
[0]) cpath
= path
;
2527 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2528 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2530 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2531 if (KERN_SUCCESS
== err
)
2533 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2534 cpath
= CAST_DOWN(const char *, map_data
);
2535 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2539 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2541 entry
= IORegistryEntry::fromPath(cpath
);
2542 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2545 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2547 if (KERN_SUCCESS
!= err
) res
= err
;
2548 *registry_entry
= entry
;
2555 /* Routine io_registry_entry_in_plane */
2556 kern_return_t
is_io_registry_entry_in_plane(
2557 io_object_t registry_entry
,
2559 boolean_t
*inPlane
)
2561 CHECK( IORegistryEntry
, registry_entry
, entry
);
2563 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2565 return( kIOReturnSuccess
);
2569 /* Routine io_registry_entry_get_path */
2570 kern_return_t
is_io_registry_entry_get_path(
2571 io_object_t registry_entry
,
2576 CHECK( IORegistryEntry
, registry_entry
, entry
);
2578 length
= sizeof( io_string_t
);
2579 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2580 return( kIOReturnSuccess
);
2582 return( kIOReturnBadArgument
);
2585 /* Routine io_registry_entry_get_path */
2586 kern_return_t
is_io_registry_entry_get_path_ool(
2587 io_object_t registry_entry
,
2589 io_string_inband_t path
,
2590 io_buf_ptr_t
*path_ool
,
2591 mach_msg_type_number_t
*path_oolCnt
)
2593 enum { kMaxPath
= 16384 };
2598 CHECK( IORegistryEntry
, registry_entry
, entry
);
2602 length
= sizeof(io_string_inband_t
);
2603 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2607 buf
= IONew(char, length
);
2608 if (!buf
) err
= kIOReturnNoMemory
;
2609 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2612 *path_oolCnt
= length
;
2613 err
= copyoutkdata(buf
, length
, path_ool
);
2615 if (buf
) IODelete(buf
, char, kMaxPath
);
2622 /* Routine io_registry_entry_get_name */
2623 kern_return_t
is_io_registry_entry_get_name(
2624 io_object_t registry_entry
,
2627 CHECK( IORegistryEntry
, registry_entry
, entry
);
2629 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2631 return( kIOReturnSuccess
);
2634 /* Routine io_registry_entry_get_name_in_plane */
2635 kern_return_t
is_io_registry_entry_get_name_in_plane(
2636 io_object_t registry_entry
,
2637 io_name_t planeName
,
2640 const IORegistryPlane
* plane
;
2641 CHECK( IORegistryEntry
, registry_entry
, entry
);
2644 plane
= IORegistryEntry::getPlane( planeName
);
2648 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2650 return( kIOReturnSuccess
);
2653 /* Routine io_registry_entry_get_location_in_plane */
2654 kern_return_t
is_io_registry_entry_get_location_in_plane(
2655 io_object_t registry_entry
,
2656 io_name_t planeName
,
2657 io_name_t location
)
2659 const IORegistryPlane
* plane
;
2660 CHECK( IORegistryEntry
, registry_entry
, entry
);
2663 plane
= IORegistryEntry::getPlane( planeName
);
2667 const char * cstr
= entry
->getLocation( plane
);
2670 strncpy( location
, cstr
, sizeof( io_name_t
));
2671 return( kIOReturnSuccess
);
2673 return( kIOReturnNotFound
);
2676 /* Routine io_registry_entry_get_registry_entry_id */
2677 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2678 io_object_t registry_entry
,
2679 uint64_t *entry_id
)
2681 CHECK( IORegistryEntry
, registry_entry
, entry
);
2683 *entry_id
= entry
->getRegistryEntryID();
2685 return (kIOReturnSuccess
);
2688 /* Routine io_registry_entry_get_property */
2689 kern_return_t
is_io_registry_entry_get_property_bytes(
2690 io_object_t registry_entry
,
2691 io_name_t property_name
,
2692 io_struct_inband_t buf
,
2693 mach_msg_type_number_t
*dataCnt
)
2701 unsigned int len
= 0;
2702 const void * bytes
= 0;
2703 IOReturn ret
= kIOReturnSuccess
;
2705 CHECK( IORegistryEntry
, registry_entry
, entry
);
2708 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2709 return kIOReturnNotPermitted
;
2712 obj
= entry
->copyProperty(property_name
);
2714 return( kIOReturnNoResources
);
2716 // One day OSData will be a common container base class
2718 if( (data
= OSDynamicCast( OSData
, obj
))) {
2719 len
= data
->getLength();
2720 bytes
= data
->getBytesNoCopy();
2722 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2723 len
= str
->getLength() + 1;
2724 bytes
= str
->getCStringNoCopy();
2726 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2727 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2728 bytes
= boo
->isTrue() ? "Yes" : "No";
2730 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2731 offsetBytes
= off
->unsigned64BitValue();
2732 len
= off
->numberOfBytes();
2733 bytes
= &offsetBytes
;
2734 #ifdef __BIG_ENDIAN__
2735 bytes
= (const void *)
2736 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2740 ret
= kIOReturnBadArgument
;
2744 ret
= kIOReturnIPCError
;
2747 bcopy( bytes
, buf
, len
);
2756 /* Routine io_registry_entry_get_property */
2757 kern_return_t
is_io_registry_entry_get_property(
2758 io_object_t registry_entry
,
2759 io_name_t property_name
,
2760 io_buf_ptr_t
*properties
,
2761 mach_msg_type_number_t
*propertiesCnt
)
2767 CHECK( IORegistryEntry
, registry_entry
, entry
);
2770 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2771 return kIOReturnNotPermitted
;
2774 obj
= entry
->copyProperty(property_name
);
2776 return( kIOReturnNotFound
);
2778 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2781 return( kIOReturnNoMemory
);
2784 if( obj
->serialize( s
)) {
2785 len
= s
->getLength();
2786 *propertiesCnt
= len
;
2787 err
= copyoutkdata( s
->text(), len
, properties
);
2790 err
= kIOReturnUnsupported
;
2798 /* Routine io_registry_entry_get_property_recursively */
2799 kern_return_t
is_io_registry_entry_get_property_recursively(
2800 io_object_t registry_entry
,
2802 io_name_t property_name
,
2804 io_buf_ptr_t
*properties
,
2805 mach_msg_type_number_t
*propertiesCnt
)
2811 CHECK( IORegistryEntry
, registry_entry
, entry
);
2814 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2815 return kIOReturnNotPermitted
;
2818 obj
= entry
->copyProperty( property_name
,
2819 IORegistryEntry::getPlane( plane
), options
);
2821 return( kIOReturnNotFound
);
2823 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2826 return( kIOReturnNoMemory
);
2829 if( obj
->serialize( s
)) {
2830 len
= s
->getLength();
2831 *propertiesCnt
= len
;
2832 err
= copyoutkdata( s
->text(), len
, properties
);
2835 err
= kIOReturnUnsupported
;
2845 static kern_return_t
2846 filteredProperties(IORegistryEntry
*entry
, OSDictionary
*properties
, OSDictionary
**filteredp
)
2848 kern_return_t err
= 0;
2849 OSDictionary
*filtered
= NULL
;
2850 OSCollectionIterator
*iter
= NULL
;
2853 kauth_cred_t cred
= kauth_cred_get();
2855 if (properties
== NULL
)
2856 return kIOReturnUnsupported
;
2858 if ((iter
= OSCollectionIterator::withCollection(properties
)) == NULL
||
2859 (filtered
= OSDictionary::withCapacity(properties
->getCapacity())) == NULL
) {
2860 err
= kIOReturnNoMemory
;
2864 while ((p
= iter
->getNextObject()) != NULL
) {
2865 if ((key
= OSDynamicCast(OSSymbol
, p
)) == NULL
||
2866 mac_iokit_check_get_property(cred
, entry
, key
->getCStringNoCopy()) != 0)
2868 filtered
->setObject(key
, properties
->getObject(key
));
2874 *filteredp
= filtered
;
2880 /* Routine io_registry_entry_get_properties */
2881 kern_return_t
is_io_registry_entry_get_properties(
2882 io_object_t registry_entry
,
2883 io_buf_ptr_t
*properties
,
2884 mach_msg_type_number_t
*propertiesCnt
)
2886 kern_return_t err
= 0;
2889 CHECK( IORegistryEntry
, registry_entry
, entry
);
2891 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2893 return( kIOReturnNoMemory
);
2895 if (!entry
->serializeProperties(s
))
2896 err
= kIOReturnUnsupported
;
2899 if (!err
&& mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
2900 OSObject
*propobj
= OSUnserializeXML(s
->text(), s
->getLength());
2901 OSDictionary
*filteredprops
= NULL
;
2902 err
= filteredProperties(entry
, OSDynamicCast(OSDictionary
, propobj
), &filteredprops
);
2903 if (propobj
) propobj
->release();
2907 if (!filteredprops
->serialize(s
))
2908 err
= kIOReturnUnsupported
;
2910 if (filteredprops
!= NULL
)
2911 filteredprops
->release();
2913 #endif /* CONFIG_MACF */
2916 len
= s
->getLength();
2917 *propertiesCnt
= len
;
2918 err
= copyoutkdata( s
->text(), len
, properties
);
2927 struct GetPropertiesEditorRef
2930 IORegistryEntry
* entry
;
2931 OSCollection
* root
;
2934 static const OSMetaClassBase
*
2935 GetPropertiesEditor(void * reference
,
2937 OSCollection
* container
,
2938 const OSSymbol
* name
,
2939 const OSMetaClassBase
* value
)
2941 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
2943 if (!ref
->root
) ref
->root
= container
;
2944 if (ref
->root
== container
)
2946 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
2951 if (value
) value
->retain();
2955 #endif /* CONFIG_MACF */
2957 /* Routine io_registry_entry_get_properties */
2958 kern_return_t
is_io_registry_entry_get_properties_bin(
2959 io_object_t registry_entry
,
2960 io_buf_ptr_t
*properties
,
2961 mach_msg_type_number_t
*propertiesCnt
)
2963 kern_return_t err
= kIOReturnSuccess
;
2966 OSSerialize::Editor editor
= 0;
2969 CHECK(IORegistryEntry
, registry_entry
, entry
);
2972 GetPropertiesEditorRef ref
;
2973 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
2975 editor
= &GetPropertiesEditor
;
2977 ref
.cred
= kauth_cred_get();
2983 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
2984 if (!s
) return (kIOReturnNoMemory
);
2986 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
2988 if (kIOReturnSuccess
== err
)
2990 len
= s
->getLength();
2991 *propertiesCnt
= len
;
2992 err
= copyoutkdata(s
->text(), len
, properties
);
2999 /* Routine io_registry_entry_get_property_bin */
3000 kern_return_t
is_io_registry_entry_get_property_bin(
3001 io_object_t registry_entry
,
3003 io_name_t property_name
,
3005 io_buf_ptr_t
*properties
,
3006 mach_msg_type_number_t
*propertiesCnt
)
3011 const OSSymbol
* sym
;
3013 CHECK( IORegistryEntry
, registry_entry
, entry
);
3016 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3017 return kIOReturnNotPermitted
;
3020 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
3022 obj
= entry
->copyProperty(property_name
,
3023 IORegistryEntry::getPlane(plane
), options
);
3027 obj
= entry
->copyProperty(property_name
);
3031 return( kIOReturnNotFound
);
3033 sym
= OSSymbol::withCString(property_name
);
3036 if (gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
3040 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3043 return( kIOReturnNoMemory
);
3046 if( obj
->serialize( s
)) {
3047 len
= s
->getLength();
3048 *propertiesCnt
= len
;
3049 err
= copyoutkdata( s
->text(), len
, properties
);
3051 } else err
= kIOReturnUnsupported
;
3060 /* Routine io_registry_entry_set_properties */
3061 kern_return_t is_io_registry_entry_set_properties
3063 io_object_t registry_entry
,
3064 io_buf_ptr_t properties
,
3065 mach_msg_type_number_t propertiesCnt
,
3066 kern_return_t
* result
)
3072 vm_map_offset_t map_data
;
3074 CHECK( IORegistryEntry
, registry_entry
, entry
);
3076 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
3077 return( kIOReturnMessageTooLarge
);
3079 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3080 data
= CAST_DOWN(vm_offset_t
, map_data
);
3082 if( KERN_SUCCESS
== err
) {
3084 // must return success after vm_map_copyout() succeeds
3085 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3086 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3089 res
= kIOReturnBadArgument
;
3091 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3092 registry_entry
, obj
))
3094 res
= kIOReturnNotPermitted
;
3099 res
= entry
->setProperties( obj
);
3111 /* Routine io_registry_entry_get_child_iterator */
3112 kern_return_t
is_io_registry_entry_get_child_iterator(
3113 io_object_t registry_entry
,
3115 io_object_t
*iterator
)
3117 CHECK( IORegistryEntry
, registry_entry
, entry
);
3119 *iterator
= entry
->getChildIterator(
3120 IORegistryEntry::getPlane( plane
));
3122 return( kIOReturnSuccess
);
3125 /* Routine io_registry_entry_get_parent_iterator */
3126 kern_return_t
is_io_registry_entry_get_parent_iterator(
3127 io_object_t registry_entry
,
3129 io_object_t
*iterator
)
3131 CHECK( IORegistryEntry
, registry_entry
, entry
);
3133 *iterator
= entry
->getParentIterator(
3134 IORegistryEntry::getPlane( plane
));
3136 return( kIOReturnSuccess
);
3139 /* Routine io_service_get_busy_state */
3140 kern_return_t
is_io_service_get_busy_state(
3141 io_object_t _service
,
3142 uint32_t *busyState
)
3144 CHECK( IOService
, _service
, service
);
3146 *busyState
= service
->getBusyState();
3148 return( kIOReturnSuccess
);
3151 /* Routine io_service_get_state */
3152 kern_return_t
is_io_service_get_state(
3153 io_object_t _service
,
3155 uint32_t *busy_state
,
3156 uint64_t *accumulated_busy_time
)
3158 CHECK( IOService
, _service
, service
);
3160 *state
= service
->getState();
3161 *busy_state
= service
->getBusyState();
3162 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3164 return( kIOReturnSuccess
);
3167 /* Routine io_service_wait_quiet */
3168 kern_return_t
is_io_service_wait_quiet(
3169 io_object_t _service
,
3170 mach_timespec_t wait_time
)
3174 CHECK( IOService
, _service
, service
);
3176 timeoutNS
= wait_time
.tv_sec
;
3177 timeoutNS
*= kSecondScale
;
3178 timeoutNS
+= wait_time
.tv_nsec
;
3180 return( service
->waitQuiet(timeoutNS
) );
3183 /* Routine io_service_request_probe */
3184 kern_return_t
is_io_service_request_probe(
3185 io_object_t _service
,
3188 CHECK( IOService
, _service
, service
);
3190 return( service
->requestProbe( options
));
3193 /* Routine io_service_get_authorization_id */
3194 kern_return_t
is_io_service_get_authorization_id(
3195 io_object_t _service
,
3196 uint64_t *authorization_id
)
3200 CHECK( IOService
, _service
, service
);
3202 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3203 kIOClientPrivilegeAdministrator
);
3204 if( kIOReturnSuccess
!= kr
)
3207 *authorization_id
= service
->getAuthorizationID();
3212 /* Routine io_service_set_authorization_id */
3213 kern_return_t
is_io_service_set_authorization_id(
3214 io_object_t _service
,
3215 uint64_t authorization_id
)
3217 CHECK( IOService
, _service
, service
);
3219 return( service
->setAuthorizationID( authorization_id
) );
3222 /* Routine io_service_open_ndr */
3223 kern_return_t
is_io_service_open_extended(
3224 io_object_t _service
,
3226 uint32_t connect_type
,
3228 io_buf_ptr_t properties
,
3229 mach_msg_type_number_t propertiesCnt
,
3230 kern_return_t
* result
,
3231 io_object_t
*connection
)
3233 IOUserClient
* client
= 0;
3234 kern_return_t err
= KERN_SUCCESS
;
3235 IOReturn res
= kIOReturnSuccess
;
3236 OSDictionary
* propertiesDict
= 0;
3238 bool disallowAccess
;
3240 CHECK( IOService
, _service
, service
);
3242 if (!owningTask
) return (kIOReturnBadArgument
);
3250 vm_map_offset_t map_data
;
3252 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3253 return( kIOReturnMessageTooLarge
);
3255 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3257 data
= CAST_DOWN(vm_offset_t
, map_data
);
3258 if (KERN_SUCCESS
== err
)
3260 // must return success after vm_map_copyout() succeeds
3261 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3262 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3263 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3264 if (!propertiesDict
)
3266 res
= kIOReturnBadArgument
;
3271 if (kIOReturnSuccess
!= res
)
3275 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3278 if (!propertiesDict
)
3279 propertiesDict
= OSDictionary::withCapacity(4);
3280 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3284 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3289 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3290 connect_type
, propertiesDict
, &client
);
3293 propertiesDict
->release();
3295 if (res
== kIOReturnSuccess
)
3297 assert( OSDynamicCast(IOUserClient
, client
) );
3299 disallowAccess
= (crossEndian
3300 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3301 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3302 if (disallowAccess
) res
= kIOReturnUnsupported
;
3304 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3305 res
= kIOReturnNotPermitted
;
3307 if (kIOReturnSuccess
!= res
)
3309 IOStatisticsClientCall();
3310 client
->clientClose();
3315 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3316 client
->closed
= false;
3317 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3320 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3321 creatorName
->release();
3323 client
->setTerminateDefer(service
, false);
3328 *connection
= client
;
3334 /* Routine io_service_close */
3335 kern_return_t
is_io_service_close(
3336 io_object_t connection
)
3339 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3340 return( kIOReturnSuccess
);
3342 CHECK( IOUserClient
, connection
, client
);
3344 IOStatisticsClientCall();
3346 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
))
3348 client
->clientClose();
3352 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3353 client
->getRegistryEntryID(), client
->getName());
3356 return( kIOReturnSuccess
);
3359 /* Routine io_connect_get_service */
3360 kern_return_t
is_io_connect_get_service(
3361 io_object_t connection
,
3362 io_object_t
*service
)
3364 IOService
* theService
;
3366 CHECK( IOUserClient
, connection
, client
);
3368 theService
= client
->getService();
3370 theService
->retain();
3372 *service
= theService
;
3374 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3377 /* Routine io_connect_set_notification_port */
3378 kern_return_t
is_io_connect_set_notification_port(
3379 io_object_t connection
,
3380 uint32_t notification_type
,
3384 CHECK( IOUserClient
, connection
, client
);
3386 IOStatisticsClientCall();
3387 return( client
->registerNotificationPort( port
, notification_type
,
3388 (io_user_reference_t
) reference
));
3391 /* Routine io_connect_set_notification_port */
3392 kern_return_t
is_io_connect_set_notification_port_64(
3393 io_object_t connection
,
3394 uint32_t notification_type
,
3396 io_user_reference_t reference
)
3398 CHECK( IOUserClient
, connection
, client
);
3400 IOStatisticsClientCall();
3401 return( client
->registerNotificationPort( port
, notification_type
,
3405 /* Routine io_connect_map_memory_into_task */
3406 kern_return_t is_io_connect_map_memory_into_task
3408 io_connect_t connection
,
3409 uint32_t memory_type
,
3411 mach_vm_address_t
*address
,
3412 mach_vm_size_t
*size
,
3419 CHECK( IOUserClient
, connection
, client
);
3421 if (!into_task
) return (kIOReturnBadArgument
);
3423 IOStatisticsClientCall();
3424 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3427 *address
= map
->getAddress();
3429 *size
= map
->getSize();
3431 if( client
->sharedInstance
3432 || (into_task
!= current_task())) {
3433 // push a name out to the task owning the map,
3434 // so we can clean up maps
3435 mach_port_name_t name __unused
=
3436 IOMachPort::makeSendRightForTask(
3437 into_task
, map
, IKOT_IOKIT_OBJECT
);
3440 // keep it with the user client
3441 IOLockLock( gIOObjectPortLock
);
3442 if( 0 == client
->mappings
)
3443 client
->mappings
= OSSet::withCapacity(2);
3444 if( client
->mappings
)
3445 client
->mappings
->setObject( map
);
3446 IOLockUnlock( gIOObjectPortLock
);
3449 err
= kIOReturnSuccess
;
3452 err
= kIOReturnBadArgument
;
3457 /* Routine is_io_connect_map_memory */
3458 kern_return_t
is_io_connect_map_memory(
3459 io_object_t connect
,
3467 mach_vm_address_t address
;
3468 mach_vm_size_t size
;
3470 address
= SCALAR64(*mapAddr
);
3471 size
= SCALAR64(*mapSize
);
3473 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3475 *mapAddr
= SCALAR32(address
);
3476 *mapSize
= SCALAR32(size
);
3483 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3486 IOMemoryMap
* map
= 0;
3488 IOLockLock(gIOObjectPortLock
);
3490 iter
= OSCollectionIterator::withCollection(mappings
);
3493 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3495 if(mem
== map
->getMemoryDescriptor())
3498 mappings
->removeObject(map
);
3505 IOLockUnlock(gIOObjectPortLock
);
3512 /* Routine io_connect_unmap_memory_from_task */
3513 kern_return_t is_io_connect_unmap_memory_from_task
3515 io_connect_t connection
,
3516 uint32_t memory_type
,
3518 mach_vm_address_t address
)
3521 IOOptionBits options
= 0;
3522 IOMemoryDescriptor
* memory
;
3525 CHECK( IOUserClient
, connection
, client
);
3527 if (!from_task
) return (kIOReturnBadArgument
);
3529 IOStatisticsClientCall();
3530 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3532 if( memory
&& (kIOReturnSuccess
== err
)) {
3534 options
= (options
& ~kIOMapUserOptionsMask
)
3535 | kIOMapAnywhere
| kIOMapReference
;
3537 map
= memory
->createMappingInTask( from_task
, address
, options
);
3541 IOLockLock( gIOObjectPortLock
);
3542 if( client
->mappings
)
3543 client
->mappings
->removeObject( map
);
3544 IOLockUnlock( gIOObjectPortLock
);
3546 mach_port_name_t name
= 0;
3547 if (from_task
!= current_task())
3548 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3551 map
->userClientUnmap();
3552 err
= iokit_mod_send_right( from_task
, name
, -2 );
3553 err
= kIOReturnSuccess
;
3556 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3557 if (from_task
== current_task())
3561 err
= kIOReturnBadArgument
;
3567 kern_return_t
is_io_connect_unmap_memory(
3568 io_object_t connect
,
3574 mach_vm_address_t address
;
3576 address
= SCALAR64(mapAddr
);
3578 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3584 /* Routine io_connect_add_client */
3585 kern_return_t
is_io_connect_add_client(
3586 io_object_t connection
,
3587 io_object_t connect_to
)
3589 CHECK( IOUserClient
, connection
, client
);
3590 CHECK( IOUserClient
, connect_to
, to
);
3592 IOStatisticsClientCall();
3593 return( client
->connectClient( to
) );
3597 /* Routine io_connect_set_properties */
3598 kern_return_t
is_io_connect_set_properties(
3599 io_object_t connection
,
3600 io_buf_ptr_t properties
,
3601 mach_msg_type_number_t propertiesCnt
,
3602 kern_return_t
* result
)
3604 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3607 /* Routine io_user_client_method */
3608 kern_return_t is_io_connect_method_var_output
3610 io_connect_t connection
,
3612 io_scalar_inband64_t scalar_input
,
3613 mach_msg_type_number_t scalar_inputCnt
,
3614 io_struct_inband_t inband_input
,
3615 mach_msg_type_number_t inband_inputCnt
,
3616 mach_vm_address_t ool_input
,
3617 mach_vm_size_t ool_input_size
,
3618 io_struct_inband_t inband_output
,
3619 mach_msg_type_number_t
*inband_outputCnt
,
3620 io_scalar_inband64_t scalar_output
,
3621 mach_msg_type_number_t
*scalar_outputCnt
,
3622 io_buf_ptr_t
*var_output
,
3623 mach_msg_type_number_t
*var_outputCnt
3626 CHECK( IOUserClient
, connection
, client
);
3628 IOExternalMethodArguments args
;
3630 IOMemoryDescriptor
* inputMD
= 0;
3631 OSObject
* structureVariableOutputData
= 0;
3633 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3634 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3636 args
.selector
= selector
;
3638 args
.asyncWakePort
= MACH_PORT_NULL
;
3639 args
.asyncReference
= 0;
3640 args
.asyncReferenceCount
= 0;
3641 args
.structureVariableOutputData
= &structureVariableOutputData
;
3643 args
.scalarInput
= scalar_input
;
3644 args
.scalarInputCount
= scalar_inputCnt
;
3645 args
.structureInput
= inband_input
;
3646 args
.structureInputSize
= inband_inputCnt
;
3649 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3650 kIODirectionOut
, current_task());
3652 args
.structureInputDescriptor
= inputMD
;
3654 args
.scalarOutput
= scalar_output
;
3655 args
.scalarOutputCount
= *scalar_outputCnt
;
3656 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3657 args
.structureOutput
= inband_output
;
3658 args
.structureOutputSize
= *inband_outputCnt
;
3659 args
.structureOutputDescriptor
= NULL
;
3660 args
.structureOutputDescriptorSize
= 0;
3662 IOStatisticsClientCall();
3663 ret
= client
->externalMethod( selector
, &args
);
3665 *scalar_outputCnt
= args
.scalarOutputCount
;
3666 *inband_outputCnt
= args
.structureOutputSize
;
3668 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3670 OSSerialize
* serialize
;
3674 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3676 len
= serialize
->getLength();
3677 *var_outputCnt
= len
;
3678 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3680 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3682 len
= data
->getLength();
3683 *var_outputCnt
= len
;
3684 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3688 ret
= kIOReturnUnderrun
;
3694 if (structureVariableOutputData
)
3695 structureVariableOutputData
->release();
3700 /* Routine io_user_client_method */
3701 kern_return_t is_io_connect_method
3703 io_connect_t connection
,
3705 io_scalar_inband64_t scalar_input
,
3706 mach_msg_type_number_t scalar_inputCnt
,
3707 io_struct_inband_t inband_input
,
3708 mach_msg_type_number_t inband_inputCnt
,
3709 mach_vm_address_t ool_input
,
3710 mach_vm_size_t ool_input_size
,
3711 io_struct_inband_t inband_output
,
3712 mach_msg_type_number_t
*inband_outputCnt
,
3713 io_scalar_inband64_t scalar_output
,
3714 mach_msg_type_number_t
*scalar_outputCnt
,
3715 mach_vm_address_t ool_output
,
3716 mach_vm_size_t
*ool_output_size
3719 CHECK( IOUserClient
, connection
, client
);
3721 IOExternalMethodArguments args
;
3723 IOMemoryDescriptor
* inputMD
= 0;
3724 IOMemoryDescriptor
* outputMD
= 0;
3726 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3727 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3729 args
.selector
= selector
;
3731 args
.asyncWakePort
= MACH_PORT_NULL
;
3732 args
.asyncReference
= 0;
3733 args
.asyncReferenceCount
= 0;
3734 args
.structureVariableOutputData
= 0;
3736 args
.scalarInput
= scalar_input
;
3737 args
.scalarInputCount
= scalar_inputCnt
;
3738 args
.structureInput
= inband_input
;
3739 args
.structureInputSize
= inband_inputCnt
;
3742 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3743 kIODirectionOut
, current_task());
3745 args
.structureInputDescriptor
= inputMD
;
3747 args
.scalarOutput
= scalar_output
;
3748 args
.scalarOutputCount
= *scalar_outputCnt
;
3749 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3750 args
.structureOutput
= inband_output
;
3751 args
.structureOutputSize
= *inband_outputCnt
;
3753 if (ool_output
&& ool_output_size
)
3755 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3756 kIODirectionIn
, current_task());
3759 args
.structureOutputDescriptor
= outputMD
;
3760 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3762 IOStatisticsClientCall();
3763 ret
= client
->externalMethod( selector
, &args
);
3765 *scalar_outputCnt
= args
.scalarOutputCount
;
3766 *inband_outputCnt
= args
.structureOutputSize
;
3767 *ool_output_size
= args
.structureOutputDescriptorSize
;
3772 outputMD
->release();
3777 /* Routine io_async_user_client_method */
3778 kern_return_t is_io_connect_async_method
3780 io_connect_t connection
,
3781 mach_port_t wake_port
,
3782 io_async_ref64_t reference
,
3783 mach_msg_type_number_t referenceCnt
,
3785 io_scalar_inband64_t scalar_input
,
3786 mach_msg_type_number_t scalar_inputCnt
,
3787 io_struct_inband_t inband_input
,
3788 mach_msg_type_number_t inband_inputCnt
,
3789 mach_vm_address_t ool_input
,
3790 mach_vm_size_t ool_input_size
,
3791 io_struct_inband_t inband_output
,
3792 mach_msg_type_number_t
*inband_outputCnt
,
3793 io_scalar_inband64_t scalar_output
,
3794 mach_msg_type_number_t
*scalar_outputCnt
,
3795 mach_vm_address_t ool_output
,
3796 mach_vm_size_t
* ool_output_size
3799 CHECK( IOUserClient
, connection
, client
);
3801 IOExternalMethodArguments args
;
3803 IOMemoryDescriptor
* inputMD
= 0;
3804 IOMemoryDescriptor
* outputMD
= 0;
3806 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3807 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3809 reference
[0] = (io_user_reference_t
) wake_port
;
3810 if (vm_map_is_64bit(get_task_map(current_task())))
3811 reference
[0] |= kIOUCAsync64Flag
;
3813 args
.selector
= selector
;
3815 args
.asyncWakePort
= wake_port
;
3816 args
.asyncReference
= reference
;
3817 args
.asyncReferenceCount
= referenceCnt
;
3819 args
.scalarInput
= scalar_input
;
3820 args
.scalarInputCount
= scalar_inputCnt
;
3821 args
.structureInput
= inband_input
;
3822 args
.structureInputSize
= inband_inputCnt
;
3825 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3826 kIODirectionOut
, current_task());
3828 args
.structureInputDescriptor
= inputMD
;
3830 args
.scalarOutput
= scalar_output
;
3831 args
.scalarOutputCount
= *scalar_outputCnt
;
3832 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3833 args
.structureOutput
= inband_output
;
3834 args
.structureOutputSize
= *inband_outputCnt
;
3838 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3839 kIODirectionIn
, current_task());
3842 args
.structureOutputDescriptor
= outputMD
;
3843 args
.structureOutputDescriptorSize
= *ool_output_size
;
3845 IOStatisticsClientCall();
3846 ret
= client
->externalMethod( selector
, &args
);
3848 *inband_outputCnt
= args
.structureOutputSize
;
3849 *ool_output_size
= args
.structureOutputDescriptorSize
;
3854 outputMD
->release();
3859 /* Routine io_connect_method_scalarI_scalarO */
3860 kern_return_t
is_io_connect_method_scalarI_scalarO(
3861 io_object_t connect
,
3863 io_scalar_inband_t input
,
3864 mach_msg_type_number_t inputCount
,
3865 io_scalar_inband_t output
,
3866 mach_msg_type_number_t
* outputCount
)
3870 io_scalar_inband64_t _input
;
3871 io_scalar_inband64_t _output
;
3873 mach_msg_type_number_t struct_outputCnt
= 0;
3874 mach_vm_size_t ool_output_size
= 0;
3876 bzero(&_output
[0], sizeof(_output
));
3877 for (i
= 0; i
< inputCount
; i
++)
3878 _input
[i
] = SCALAR64(input
[i
]);
3880 err
= is_io_connect_method(connect
, index
,
3884 NULL
, &struct_outputCnt
,
3885 _output
, outputCount
,
3886 0, &ool_output_size
);
3888 for (i
= 0; i
< *outputCount
; i
++)
3889 output
[i
] = SCALAR32(_output
[i
]);
3894 kern_return_t
shim_io_connect_method_scalarI_scalarO(
3895 IOExternalMethod
* method
,
3897 const io_user_scalar_t
* input
,
3898 mach_msg_type_number_t inputCount
,
3899 io_user_scalar_t
* output
,
3900 mach_msg_type_number_t
* outputCount
)
3903 io_scalar_inband_t _output
;
3905 err
= kIOReturnBadArgument
;
3907 bzero(&_output
[0], sizeof(_output
));
3910 if( inputCount
!= method
->count0
)
3912 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3915 if( *outputCount
!= method
->count1
)
3917 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3921 func
= method
->func
;
3923 switch( inputCount
) {
3926 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3927 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3930 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3931 ARG32(input
[3]), ARG32(input
[4]),
3935 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3937 &_output
[0], &_output
[1] );
3940 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3941 &_output
[0], &_output
[1], &_output
[2] );
3944 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3945 &_output
[0], &_output
[1], &_output
[2],
3949 err
= (object
->*func
)( ARG32(input
[0]),
3950 &_output
[0], &_output
[1], &_output
[2],
3951 &_output
[3], &_output
[4] );
3954 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
3955 &_output
[3], &_output
[4], &_output
[5] );
3959 IOLog("%s: Bad method table\n", object
->getName());
3965 for (i
= 0; i
< *outputCount
; i
++)
3966 output
[i
] = SCALAR32(_output
[i
]);
3971 /* Routine io_async_method_scalarI_scalarO */
3972 kern_return_t
is_io_async_method_scalarI_scalarO(
3973 io_object_t connect
,
3974 mach_port_t wake_port
,
3975 io_async_ref_t reference
,
3976 mach_msg_type_number_t referenceCnt
,
3978 io_scalar_inband_t input
,
3979 mach_msg_type_number_t inputCount
,
3980 io_scalar_inband_t output
,
3981 mach_msg_type_number_t
* outputCount
)
3985 io_scalar_inband64_t _input
;
3986 io_scalar_inband64_t _output
;
3987 io_async_ref64_t _reference
;
3989 bzero(&_output
[0], sizeof(_output
));
3990 for (i
= 0; i
< referenceCnt
; i
++)
3991 _reference
[i
] = REF64(reference
[i
]);
3993 mach_msg_type_number_t struct_outputCnt
= 0;
3994 mach_vm_size_t ool_output_size
= 0;
3996 for (i
= 0; i
< inputCount
; i
++)
3997 _input
[i
] = SCALAR64(input
[i
]);
3999 err
= is_io_connect_async_method(connect
,
4000 wake_port
, _reference
, referenceCnt
,
4005 NULL
, &struct_outputCnt
,
4006 _output
, outputCount
,
4007 0, &ool_output_size
);
4009 for (i
= 0; i
< *outputCount
; i
++)
4010 output
[i
] = SCALAR32(_output
[i
]);
4014 /* Routine io_async_method_scalarI_structureO */
4015 kern_return_t
is_io_async_method_scalarI_structureO(
4016 io_object_t connect
,
4017 mach_port_t wake_port
,
4018 io_async_ref_t reference
,
4019 mach_msg_type_number_t referenceCnt
,
4021 io_scalar_inband_t input
,
4022 mach_msg_type_number_t inputCount
,
4023 io_struct_inband_t output
,
4024 mach_msg_type_number_t
* outputCount
)
4027 io_scalar_inband64_t _input
;
4028 io_async_ref64_t _reference
;
4030 for (i
= 0; i
< referenceCnt
; i
++)
4031 _reference
[i
] = REF64(reference
[i
]);
4033 mach_msg_type_number_t scalar_outputCnt
= 0;
4034 mach_vm_size_t ool_output_size
= 0;
4036 for (i
= 0; i
< inputCount
; i
++)
4037 _input
[i
] = SCALAR64(input
[i
]);
4039 return (is_io_connect_async_method(connect
,
4040 wake_port
, _reference
, referenceCnt
,
4045 output
, outputCount
,
4046 NULL
, &scalar_outputCnt
,
4047 0, &ool_output_size
));
4050 /* Routine io_async_method_scalarI_structureI */
4051 kern_return_t
is_io_async_method_scalarI_structureI(
4052 io_connect_t connect
,
4053 mach_port_t wake_port
,
4054 io_async_ref_t reference
,
4055 mach_msg_type_number_t referenceCnt
,
4057 io_scalar_inband_t input
,
4058 mach_msg_type_number_t inputCount
,
4059 io_struct_inband_t inputStruct
,
4060 mach_msg_type_number_t inputStructCount
)
4063 io_scalar_inband64_t _input
;
4064 io_async_ref64_t _reference
;
4066 for (i
= 0; i
< referenceCnt
; i
++)
4067 _reference
[i
] = REF64(reference
[i
]);
4069 mach_msg_type_number_t scalar_outputCnt
= 0;
4070 mach_msg_type_number_t inband_outputCnt
= 0;
4071 mach_vm_size_t ool_output_size
= 0;
4073 for (i
= 0; i
< inputCount
; i
++)
4074 _input
[i
] = SCALAR64(input
[i
]);
4076 return (is_io_connect_async_method(connect
,
4077 wake_port
, _reference
, referenceCnt
,
4080 inputStruct
, inputStructCount
,
4082 NULL
, &inband_outputCnt
,
4083 NULL
, &scalar_outputCnt
,
4084 0, &ool_output_size
));
4087 /* Routine io_async_method_structureI_structureO */
4088 kern_return_t
is_io_async_method_structureI_structureO(
4089 io_object_t connect
,
4090 mach_port_t wake_port
,
4091 io_async_ref_t reference
,
4092 mach_msg_type_number_t referenceCnt
,
4094 io_struct_inband_t input
,
4095 mach_msg_type_number_t inputCount
,
4096 io_struct_inband_t output
,
4097 mach_msg_type_number_t
* outputCount
)
4100 mach_msg_type_number_t scalar_outputCnt
= 0;
4101 mach_vm_size_t ool_output_size
= 0;
4102 io_async_ref64_t _reference
;
4104 for (i
= 0; i
< referenceCnt
; i
++)
4105 _reference
[i
] = REF64(reference
[i
]);
4107 return (is_io_connect_async_method(connect
,
4108 wake_port
, _reference
, referenceCnt
,
4113 output
, outputCount
,
4114 NULL
, &scalar_outputCnt
,
4115 0, &ool_output_size
));
4119 kern_return_t
shim_io_async_method_scalarI_scalarO(
4120 IOExternalAsyncMethod
* method
,
4122 mach_port_t asyncWakePort
,
4123 io_user_reference_t
* asyncReference
,
4124 uint32_t asyncReferenceCount
,
4125 const io_user_scalar_t
* input
,
4126 mach_msg_type_number_t inputCount
,
4127 io_user_scalar_t
* output
,
4128 mach_msg_type_number_t
* outputCount
)
4132 io_scalar_inband_t _output
;
4134 io_async_ref_t reference
;
4136 bzero(&_output
[0], sizeof(_output
));
4137 for (i
= 0; i
< asyncReferenceCount
; i
++)
4138 reference
[i
] = REF32(asyncReference
[i
]);
4140 err
= kIOReturnBadArgument
;
4144 if( inputCount
!= method
->count0
)
4146 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4149 if( *outputCount
!= method
->count1
)
4151 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4155 func
= method
->func
;
4157 switch( inputCount
) {
4160 err
= (object
->*func
)( reference
,
4161 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4162 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4165 err
= (object
->*func
)( reference
,
4166 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4167 ARG32(input
[3]), ARG32(input
[4]),
4171 err
= (object
->*func
)( reference
,
4172 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4174 &_output
[0], &_output
[1] );
4177 err
= (object
->*func
)( reference
,
4178 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4179 &_output
[0], &_output
[1], &_output
[2] );
4182 err
= (object
->*func
)( reference
,
4183 ARG32(input
[0]), ARG32(input
[1]),
4184 &_output
[0], &_output
[1], &_output
[2],
4188 err
= (object
->*func
)( reference
,
4190 &_output
[0], &_output
[1], &_output
[2],
4191 &_output
[3], &_output
[4] );
4194 err
= (object
->*func
)( reference
,
4195 &_output
[0], &_output
[1], &_output
[2],
4196 &_output
[3], &_output
[4], &_output
[5] );
4200 IOLog("%s: Bad method table\n", object
->getName());
4205 for (i
= 0; i
< *outputCount
; i
++)
4206 output
[i
] = SCALAR32(_output
[i
]);
4212 /* Routine io_connect_method_scalarI_structureO */
4213 kern_return_t
is_io_connect_method_scalarI_structureO(
4214 io_object_t connect
,
4216 io_scalar_inband_t input
,
4217 mach_msg_type_number_t inputCount
,
4218 io_struct_inband_t output
,
4219 mach_msg_type_number_t
* outputCount
)
4222 io_scalar_inband64_t _input
;
4224 mach_msg_type_number_t scalar_outputCnt
= 0;
4225 mach_vm_size_t ool_output_size
= 0;
4227 for (i
= 0; i
< inputCount
; i
++)
4228 _input
[i
] = SCALAR64(input
[i
]);
4230 return (is_io_connect_method(connect
, index
,
4234 output
, outputCount
,
4235 NULL
, &scalar_outputCnt
,
4236 0, &ool_output_size
));
4239 kern_return_t
shim_io_connect_method_scalarI_structureO(
4241 IOExternalMethod
* method
,
4243 const io_user_scalar_t
* input
,
4244 mach_msg_type_number_t inputCount
,
4245 io_struct_inband_t output
,
4246 IOByteCount
* outputCount
)
4251 err
= kIOReturnBadArgument
;
4254 if( inputCount
!= method
->count0
)
4256 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4259 if( (kIOUCVariableStructureSize
!= method
->count1
)
4260 && (*outputCount
!= method
->count1
))
4262 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4266 func
= method
->func
;
4268 switch( inputCount
) {
4271 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4272 ARG32(input
[3]), ARG32(input
[4]),
4276 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4278 output
, (void *)outputCount
);
4281 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4282 output
, (void *)outputCount
, 0 );
4285 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4286 output
, (void *)outputCount
, 0, 0 );
4289 err
= (object
->*func
)( ARG32(input
[0]),
4290 output
, (void *)outputCount
, 0, 0, 0 );
4293 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4297 IOLog("%s: Bad method table\n", object
->getName());
4306 kern_return_t
shim_io_async_method_scalarI_structureO(
4307 IOExternalAsyncMethod
* method
,
4309 mach_port_t asyncWakePort
,
4310 io_user_reference_t
* asyncReference
,
4311 uint32_t asyncReferenceCount
,
4312 const io_user_scalar_t
* input
,
4313 mach_msg_type_number_t inputCount
,
4314 io_struct_inband_t output
,
4315 mach_msg_type_number_t
* outputCount
)
4320 io_async_ref_t reference
;
4322 for (i
= 0; i
< asyncReferenceCount
; i
++)
4323 reference
[i
] = REF32(asyncReference
[i
]);
4325 err
= kIOReturnBadArgument
;
4327 if( inputCount
!= method
->count0
)
4329 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4332 if( (kIOUCVariableStructureSize
!= method
->count1
)
4333 && (*outputCount
!= method
->count1
))
4335 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4339 func
= method
->func
;
4341 switch( inputCount
) {
4344 err
= (object
->*func
)( reference
,
4345 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4346 ARG32(input
[3]), ARG32(input
[4]),
4350 err
= (object
->*func
)( reference
,
4351 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4353 output
, (void *)outputCount
);
4356 err
= (object
->*func
)( reference
,
4357 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4358 output
, (void *)outputCount
, 0 );
4361 err
= (object
->*func
)( reference
,
4362 ARG32(input
[0]), ARG32(input
[1]),
4363 output
, (void *)outputCount
, 0, 0 );
4366 err
= (object
->*func
)( reference
,
4368 output
, (void *)outputCount
, 0, 0, 0 );
4371 err
= (object
->*func
)( reference
,
4372 output
, (void *)outputCount
, 0, 0, 0, 0 );
4376 IOLog("%s: Bad method table\n", object
->getName());
4384 /* Routine io_connect_method_scalarI_structureI */
4385 kern_return_t
is_io_connect_method_scalarI_structureI(
4386 io_connect_t connect
,
4388 io_scalar_inband_t input
,
4389 mach_msg_type_number_t inputCount
,
4390 io_struct_inband_t inputStruct
,
4391 mach_msg_type_number_t inputStructCount
)
4394 io_scalar_inband64_t _input
;
4396 mach_msg_type_number_t scalar_outputCnt
= 0;
4397 mach_msg_type_number_t inband_outputCnt
= 0;
4398 mach_vm_size_t ool_output_size
= 0;
4400 for (i
= 0; i
< inputCount
; i
++)
4401 _input
[i
] = SCALAR64(input
[i
]);
4403 return (is_io_connect_method(connect
, index
,
4405 inputStruct
, inputStructCount
,
4407 NULL
, &inband_outputCnt
,
4408 NULL
, &scalar_outputCnt
,
4409 0, &ool_output_size
));
4412 kern_return_t
shim_io_connect_method_scalarI_structureI(
4413 IOExternalMethod
* method
,
4415 const io_user_scalar_t
* input
,
4416 mach_msg_type_number_t inputCount
,
4417 io_struct_inband_t inputStruct
,
4418 mach_msg_type_number_t inputStructCount
)
4421 IOReturn err
= kIOReturnBadArgument
;
4425 if (inputCount
!= method
->count0
)
4427 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4430 if( (kIOUCVariableStructureSize
!= method
->count1
)
4431 && (inputStructCount
!= method
->count1
))
4433 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4437 func
= method
->func
;
4439 switch( inputCount
) {
4442 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4443 ARG32(input
[3]), ARG32(input
[4]),
4447 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4449 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4452 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4453 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4457 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4458 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4462 err
= (object
->*func
)( ARG32(input
[0]),
4463 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4467 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4472 IOLog("%s: Bad method table\n", object
->getName());
4480 kern_return_t
shim_io_async_method_scalarI_structureI(
4481 IOExternalAsyncMethod
* method
,
4483 mach_port_t asyncWakePort
,
4484 io_user_reference_t
* asyncReference
,
4485 uint32_t asyncReferenceCount
,
4486 const io_user_scalar_t
* input
,
4487 mach_msg_type_number_t inputCount
,
4488 io_struct_inband_t inputStruct
,
4489 mach_msg_type_number_t inputStructCount
)
4493 IOReturn err
= kIOReturnBadArgument
;
4494 io_async_ref_t reference
;
4496 for (i
= 0; i
< asyncReferenceCount
; i
++)
4497 reference
[i
] = REF32(asyncReference
[i
]);
4501 if (inputCount
!= method
->count0
)
4503 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4506 if( (kIOUCVariableStructureSize
!= method
->count1
)
4507 && (inputStructCount
!= method
->count1
))
4509 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4513 func
= method
->func
;
4515 switch( inputCount
) {
4518 err
= (object
->*func
)( reference
,
4519 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4520 ARG32(input
[3]), ARG32(input
[4]),
4524 err
= (object
->*func
)( reference
,
4525 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4527 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4530 err
= (object
->*func
)( reference
,
4531 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4532 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4536 err
= (object
->*func
)( reference
,
4537 ARG32(input
[0]), ARG32(input
[1]),
4538 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4542 err
= (object
->*func
)( reference
,
4544 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4548 err
= (object
->*func
)( reference
,
4549 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4554 IOLog("%s: Bad method table\n", object
->getName());
4562 /* Routine io_connect_method_structureI_structureO */
4563 kern_return_t
is_io_connect_method_structureI_structureO(
4564 io_object_t connect
,
4566 io_struct_inband_t input
,
4567 mach_msg_type_number_t inputCount
,
4568 io_struct_inband_t output
,
4569 mach_msg_type_number_t
* outputCount
)
4571 mach_msg_type_number_t scalar_outputCnt
= 0;
4572 mach_vm_size_t ool_output_size
= 0;
4574 return (is_io_connect_method(connect
, index
,
4578 output
, outputCount
,
4579 NULL
, &scalar_outputCnt
,
4580 0, &ool_output_size
));
4583 kern_return_t
shim_io_connect_method_structureI_structureO(
4584 IOExternalMethod
* method
,
4586 io_struct_inband_t input
,
4587 mach_msg_type_number_t inputCount
,
4588 io_struct_inband_t output
,
4589 IOByteCount
* outputCount
)
4592 IOReturn err
= kIOReturnBadArgument
;
4596 if( (kIOUCVariableStructureSize
!= method
->count0
)
4597 && (inputCount
!= method
->count0
))
4599 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4602 if( (kIOUCVariableStructureSize
!= method
->count1
)
4603 && (*outputCount
!= method
->count1
))
4605 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4609 func
= method
->func
;
4611 if( method
->count1
) {
4612 if( method
->count0
) {
4613 err
= (object
->*func
)( input
, output
,
4614 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4616 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4619 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4628 kern_return_t
shim_io_async_method_structureI_structureO(
4629 IOExternalAsyncMethod
* method
,
4631 mach_port_t asyncWakePort
,
4632 io_user_reference_t
* asyncReference
,
4633 uint32_t asyncReferenceCount
,
4634 io_struct_inband_t input
,
4635 mach_msg_type_number_t inputCount
,
4636 io_struct_inband_t output
,
4637 mach_msg_type_number_t
* outputCount
)
4642 io_async_ref_t reference
;
4644 for (i
= 0; i
< asyncReferenceCount
; i
++)
4645 reference
[i
] = REF32(asyncReference
[i
]);
4647 err
= kIOReturnBadArgument
;
4650 if( (kIOUCVariableStructureSize
!= method
->count0
)
4651 && (inputCount
!= method
->count0
))
4653 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4656 if( (kIOUCVariableStructureSize
!= method
->count1
)
4657 && (*outputCount
!= method
->count1
))
4659 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4663 func
= method
->func
;
4665 if( method
->count1
) {
4666 if( method
->count0
) {
4667 err
= (object
->*func
)( reference
,
4669 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4671 err
= (object
->*func
)( reference
,
4672 output
, outputCount
, 0, 0, 0, 0 );
4675 err
= (object
->*func
)( reference
,
4676 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4684 /* Routine io_catalog_send_data */
4685 kern_return_t
is_io_catalog_send_data(
4686 mach_port_t master_port
,
4688 io_buf_ptr_t inData
,
4689 mach_msg_type_number_t inDataCount
,
4690 kern_return_t
* result
)
4694 kern_return_t kr
= kIOReturnError
;
4696 //printf("io_catalog_send_data called. flag: %d\n", flag);
4698 if( master_port
!= master_device_port
)
4699 return kIOReturnNotPrivileged
;
4701 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4702 flag
!= kIOCatalogKextdActive
&&
4703 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4704 ( !inData
|| !inDataCount
) )
4706 return kIOReturnBadArgument
;
4710 vm_map_offset_t map_data
;
4712 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4713 return( kIOReturnMessageTooLarge
);
4715 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4716 data
= CAST_DOWN(vm_offset_t
, map_data
);
4718 if( kr
!= KERN_SUCCESS
)
4721 // must return success after vm_map_copyout() succeeds
4724 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4725 vm_deallocate( kernel_map
, data
, inDataCount
);
4727 *result
= kIOReturnNoMemory
;
4728 return( KERN_SUCCESS
);
4734 case kIOCatalogResetDrivers
:
4735 case kIOCatalogResetDriversNoMatch
: {
4738 array
= OSDynamicCast(OSArray
, obj
);
4740 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4741 flag
== kIOCatalogResetDrivers
) ) {
4743 kr
= kIOReturnError
;
4746 kr
= kIOReturnBadArgument
;
4751 case kIOCatalogAddDrivers
:
4752 case kIOCatalogAddDriversNoMatch
: {
4755 array
= OSDynamicCast(OSArray
, obj
);
4757 if ( !gIOCatalogue
->addDrivers( array
,
4758 flag
== kIOCatalogAddDrivers
) ) {
4759 kr
= kIOReturnError
;
4763 kr
= kIOReturnBadArgument
;
4768 case kIOCatalogRemoveDrivers
:
4769 case kIOCatalogRemoveDriversNoMatch
: {
4770 OSDictionary
* dict
;
4772 dict
= OSDynamicCast(OSDictionary
, obj
);
4774 if ( !gIOCatalogue
->removeDrivers( dict
,
4775 flag
== kIOCatalogRemoveDrivers
) ) {
4776 kr
= kIOReturnError
;
4780 kr
= kIOReturnBadArgument
;
4785 case kIOCatalogStartMatching
: {
4786 OSDictionary
* dict
;
4788 dict
= OSDynamicCast(OSDictionary
, obj
);
4790 if ( !gIOCatalogue
->startMatching( dict
) ) {
4791 kr
= kIOReturnError
;
4795 kr
= kIOReturnBadArgument
;
4800 case kIOCatalogRemoveKernelLinker
:
4801 kr
= KERN_NOT_SUPPORTED
;
4804 case kIOCatalogKextdActive
:
4806 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
4807 OSKext::setKextdActive();
4809 /* Dump all nonloaded startup extensions; kextd will now send them
4812 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4814 kr
= kIOReturnSuccess
;
4817 case kIOCatalogKextdFinishedLaunching
: {
4819 static bool clearedBusy
= false;
4822 IOService
* serviceRoot
= IOService::getServiceRoot();
4824 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
4825 serviceRoot
->adjustBusy(-1);
4830 kr
= kIOReturnSuccess
;
4835 kr
= kIOReturnBadArgument
;
4839 if (obj
) obj
->release();
4842 return( KERN_SUCCESS
);
4845 /* Routine io_catalog_terminate */
4846 kern_return_t
is_io_catalog_terminate(
4847 mach_port_t master_port
,
4853 if( master_port
!= master_device_port
)
4854 return kIOReturnNotPrivileged
;
4856 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
4857 kIOClientPrivilegeAdministrator
);
4858 if( kIOReturnSuccess
!= kr
)
4862 #if !defined(SECURE_KERNEL)
4863 case kIOCatalogServiceTerminate
:
4865 IOService
* service
;
4867 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
4868 kIORegistryIterateRecursively
);
4870 return kIOReturnNoMemory
;
4874 while( (service
= (IOService
*)iter
->getNextObject()) ) {
4875 if( service
->metaCast(name
)) {
4876 if ( !service
->terminate( kIOServiceRequired
4877 | kIOServiceSynchronous
) ) {
4878 kr
= kIOReturnUnsupported
;
4883 } while( !service
&& !iter
->isValid());
4887 case kIOCatalogModuleUnload
:
4888 case kIOCatalogModuleTerminate
:
4889 kr
= gIOCatalogue
->terminateDriversForModule(name
,
4890 flag
== kIOCatalogModuleUnload
);
4895 kr
= kIOReturnBadArgument
;
4902 /* Routine io_catalog_get_data */
4903 kern_return_t
is_io_catalog_get_data(
4904 mach_port_t master_port
,
4906 io_buf_ptr_t
*outData
,
4907 mach_msg_type_number_t
*outDataCount
)
4909 kern_return_t kr
= kIOReturnSuccess
;
4912 if( master_port
!= master_device_port
)
4913 return kIOReturnNotPrivileged
;
4915 //printf("io_catalog_get_data called. flag: %d\n", flag);
4917 s
= OSSerialize::withCapacity(4096);
4919 return kIOReturnNoMemory
;
4921 kr
= gIOCatalogue
->serializeData(flag
, s
);
4923 if ( kr
== kIOReturnSuccess
) {
4928 size
= s
->getLength();
4929 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
4930 if ( kr
== kIOReturnSuccess
) {
4931 bcopy(s
->text(), (void *)data
, size
);
4932 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
4933 (vm_map_size_t
)size
, true, ©
);
4934 *outData
= (char *)copy
;
4935 *outDataCount
= size
;
4944 /* Routine io_catalog_get_gen_count */
4945 kern_return_t
is_io_catalog_get_gen_count(
4946 mach_port_t master_port
,
4949 if( master_port
!= master_device_port
)
4950 return kIOReturnNotPrivileged
;
4952 //printf("io_catalog_get_gen_count called.\n");
4955 return kIOReturnBadArgument
;
4957 *genCount
= gIOCatalogue
->getGenerationCount();
4959 return kIOReturnSuccess
;
4962 /* Routine io_catalog_module_loaded.
4963 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
4965 kern_return_t
is_io_catalog_module_loaded(
4966 mach_port_t master_port
,
4969 if( master_port
!= master_device_port
)
4970 return kIOReturnNotPrivileged
;
4972 //printf("io_catalog_module_loaded called. name %s\n", name);
4975 return kIOReturnBadArgument
;
4977 gIOCatalogue
->moduleHasLoaded(name
);
4979 return kIOReturnSuccess
;
4982 kern_return_t
is_io_catalog_reset(
4983 mach_port_t master_port
,
4986 if( master_port
!= master_device_port
)
4987 return kIOReturnNotPrivileged
;
4990 case kIOCatalogResetDefault
:
4991 gIOCatalogue
->reset();
4995 return kIOReturnBadArgument
;
4998 return kIOReturnSuccess
;
5001 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5003 kern_return_t result
= kIOReturnBadArgument
;
5004 IOUserClient
*userClient
;
5006 if ((userClient
= OSDynamicCast(IOUserClient
,
5007 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
5008 IOExternalTrap
*trap
;
5009 IOService
*target
= NULL
;
5011 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5013 if (trap
&& target
) {
5019 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5023 iokit_remove_connect_reference(userClient
);
5031 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5032 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5036 IOByteCount structureOutputSize
;
5041 count
= dispatch
->checkScalarInputCount
;
5042 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
5044 return (kIOReturnBadArgument
);
5047 count
= dispatch
->checkStructureInputSize
;
5048 if ((kIOUCVariableStructureSize
!= count
)
5049 && (count
!= ((args
->structureInputDescriptor
)
5050 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
5052 return (kIOReturnBadArgument
);
5055 count
= dispatch
->checkScalarOutputCount
;
5056 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
5058 return (kIOReturnBadArgument
);
5061 count
= dispatch
->checkStructureOutputSize
;
5062 if ((kIOUCVariableStructureSize
!= count
)
5063 && (count
!= ((args
->structureOutputDescriptor
)
5064 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
5066 return (kIOReturnBadArgument
);
5069 if (dispatch
->function
)
5070 err
= (*dispatch
->function
)(target
, reference
, args
);
5072 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5078 // pre-Leopard API's don't do ool structs
5079 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
5081 err
= kIOReturnIPCError
;
5085 structureOutputSize
= args
->structureOutputSize
;
5087 if (args
->asyncWakePort
)
5089 IOExternalAsyncMethod
* method
;
5091 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
5092 return (kIOReturnUnsupported
);
5094 if (kIOUCForegroundOnly
& method
->flags
)
5096 if (task_is_gpu_denied(current_task()))
5097 return (kIOReturnNotPermitted
);
5100 switch (method
->flags
& kIOUCTypeMask
)
5102 case kIOUCScalarIStructI
:
5103 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5104 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5105 args
->scalarInput
, args
->scalarInputCount
,
5106 (char *)args
->structureInput
, args
->structureInputSize
);
5109 case kIOUCScalarIScalarO
:
5110 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5111 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5112 args
->scalarInput
, args
->scalarInputCount
,
5113 args
->scalarOutput
, &args
->scalarOutputCount
);
5116 case kIOUCScalarIStructO
:
5117 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5118 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5119 args
->scalarInput
, args
->scalarInputCount
,
5120 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5124 case kIOUCStructIStructO
:
5125 err
= shim_io_async_method_structureI_structureO( method
, object
,
5126 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5127 (char *)args
->structureInput
, args
->structureInputSize
,
5128 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5132 err
= kIOReturnBadArgument
;
5138 IOExternalMethod
* method
;
5140 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
5141 return (kIOReturnUnsupported
);
5143 if (kIOUCForegroundOnly
& method
->flags
)
5145 if (task_is_gpu_denied(current_task()))
5146 return (kIOReturnNotPermitted
);
5149 switch (method
->flags
& kIOUCTypeMask
)
5151 case kIOUCScalarIStructI
:
5152 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5153 args
->scalarInput
, args
->scalarInputCount
,
5154 (char *) args
->structureInput
, args
->structureInputSize
);
5157 case kIOUCScalarIScalarO
:
5158 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5159 args
->scalarInput
, args
->scalarInputCount
,
5160 args
->scalarOutput
, &args
->scalarOutputCount
);
5163 case kIOUCScalarIStructO
:
5164 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5165 args
->scalarInput
, args
->scalarInputCount
,
5166 (char *) args
->structureOutput
, &structureOutputSize
);
5170 case kIOUCStructIStructO
:
5171 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5172 (char *) args
->structureInput
, args
->structureInputSize
,
5173 (char *) args
->structureOutput
, &structureOutputSize
);
5177 err
= kIOReturnBadArgument
;
5182 args
->structureOutputSize
= structureOutputSize
;
5188 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5189 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5191 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5192 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5194 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5195 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5196 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5197 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5198 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5199 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5200 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5201 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5202 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5203 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5204 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5205 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5206 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5207 OSMetaClassDefineReservedUnused(IOUserClient
, 15);