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
);
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 IOUserNotification
: public OSIterator
359 OSDeclareDefaultStructors(IOUserNotification
)
361 IONotifier
* holdNotify
;
366 virtual bool init( void );
369 virtual void setNotification( IONotifier
* obj
);
371 virtual void reset();
372 virtual bool isValid();
375 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
378 // functions called from osfmk/device/iokit_rpc.c
381 iokit_add_reference( io_object_t obj
)
388 iokit_remove_reference( io_object_t obj
)
395 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
397 IOMachPort
* machPort
;
400 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
402 port
= machPort
->port
;
404 iokit_retain_port( port
);
415 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
416 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
418 IOUserClient
* client
;
420 IOUserNotification
* notify
;
422 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
423 return( kIOReturnNotReady
);
425 if( IKOT_IOKIT_CONNECT
== type
)
427 if( (client
= OSDynamicCast( IOUserClient
, obj
))) {
428 IOStatisticsClientCall();
429 client
->clientDied();
432 else if( IKOT_IOKIT_OBJECT
== type
)
434 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
436 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
437 notify
->setNotification( 0 );
440 return( kIOReturnSuccess
);
445 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
447 class IOServiceUserNotification
: public IOUserNotification
449 OSDeclareDefaultStructors(IOServiceUserNotification
)
452 mach_msg_header_t msgHdr
;
453 OSNotificationHeader64 notifyHeader
;
456 enum { kMaxOutstanding
= 1024 };
461 OSObject
* lastEntry
;
466 virtual bool init( mach_port_t port
, natural_t type
,
467 void * reference
, vm_size_t referenceSize
,
471 static bool _handler( void * target
,
472 void * ref
, IOService
* newService
, IONotifier
* notifier
);
473 virtual bool handler( void * ref
, IOService
* newService
);
475 virtual OSObject
* getNextObject();
478 class IOServiceMessageUserNotification
: public IOUserNotification
480 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
483 mach_msg_header_t msgHdr
;
484 mach_msg_body_t msgBody
;
485 mach_msg_port_descriptor_t ports
[1];
486 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
496 virtual bool init( mach_port_t port
, natural_t type
,
497 void * reference
, vm_size_t referenceSize
,
503 static IOReturn
_handler( void * target
, void * ref
,
504 UInt32 messageType
, IOService
* provider
,
505 void * messageArgument
, vm_size_t argSize
);
506 virtual IOReturn
handler( void * ref
,
507 UInt32 messageType
, IOService
* provider
,
508 void * messageArgument
, vm_size_t argSize
);
510 virtual OSObject
* getNextObject();
513 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
516 #define super OSIterator
517 OSDefineMetaClass( IOUserNotification
, OSIterator
)
518 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
520 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
522 bool IOUserNotification::init( void )
527 lock
= IOLockAlloc();
534 void IOUserNotification::free( void )
537 holdNotify
->remove();
538 // can't be in handler now
547 void IOUserNotification::setNotification( IONotifier
* notify
)
549 IONotifier
* previousNotify
;
551 IOLockLock( gIOObjectPortLock
);
553 previousNotify
= holdNotify
;
556 IOLockUnlock( gIOObjectPortLock
);
559 previousNotify
->remove();
562 void IOUserNotification::reset()
567 bool IOUserNotification::isValid()
572 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
575 #define super IOUserNotification
576 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
578 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
580 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
581 void * reference
, vm_size_t referenceSize
,
587 newSet
= OSArray::withCapacity( 1 );
591 if (referenceSize
> sizeof(OSAsyncReference64
))
594 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
595 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
599 bzero( pingMsg
, msgSize
);
601 pingMsg
->msgHdr
.msgh_remote_port
= port
;
602 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
603 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
604 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
605 pingMsg
->msgHdr
.msgh_size
= msgSize
;
606 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
608 pingMsg
->notifyHeader
.size
= 0;
609 pingMsg
->notifyHeader
.type
= type
;
610 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
615 void IOServiceUserNotification::free( void )
620 OSObject
* _lastEntry
;
624 _lastEntry
= lastEntry
;
629 if( _pingMsg
&& _msgSize
) {
630 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
631 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
633 IOFree(_pingMsg
, _msgSize
);
637 _lastEntry
->release();
643 bool IOServiceUserNotification::_handler( void * target
,
644 void * ref
, IOService
* newService
, IONotifier
* notifier
)
646 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
649 bool IOServiceUserNotification::handler( void * ref
,
650 IOService
* newService
)
654 ipc_port_t port
= NULL
;
655 bool sendPing
= false;
659 count
= newSet
->getCount();
660 if( count
< kMaxOutstanding
) {
662 newSet
->setObject( newService
);
663 if( (sendPing
= (armed
&& (0 == count
))))
669 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
670 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
673 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
674 pingMsg
->msgHdr
.msgh_local_port
= port
;
676 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
678 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
679 pingMsg
->msgHdr
.msgh_size
,
680 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
683 iokit_release_port( port
);
685 if( KERN_SUCCESS
!= kr
)
686 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
692 OSObject
* IOServiceUserNotification::getNextObject()
700 lastEntry
->release();
702 count
= newSet
->getCount();
704 result
= newSet
->getObject( count
- 1 );
706 newSet
->removeObject( count
- 1);
718 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
720 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
722 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
724 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
725 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
731 if (referenceSize
> sizeof(OSAsyncReference64
))
734 clientIs64
= client64
;
736 owningPID
= proc_selfpid();
738 extraSize
+= sizeof(IOServiceInterestContent64
);
739 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
+ extraSize
;
740 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
744 bzero( pingMsg
, msgSize
);
746 pingMsg
->msgHdr
.msgh_remote_port
= port
;
747 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
749 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
750 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
751 pingMsg
->msgHdr
.msgh_size
= msgSize
;
752 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
754 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
756 pingMsg
->ports
[0].name
= 0;
757 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
758 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
760 pingMsg
->notifyHeader
.size
= extraSize
;
761 pingMsg
->notifyHeader
.type
= type
;
762 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
767 void IOServiceMessageUserNotification::free( void )
777 if( _pingMsg
&& _msgSize
) {
778 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
779 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
781 IOFree( _pingMsg
, _msgSize
);
785 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
786 UInt32 messageType
, IOService
* provider
,
787 void * argument
, vm_size_t argSize
)
789 return( ((IOServiceMessageUserNotification
*) target
)->handler(
790 ref
, messageType
, provider
, argument
, argSize
));
793 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
794 UInt32 messageType
, IOService
* provider
,
795 void * messageArgument
, vm_size_t argSize
)
798 ipc_port_t thisPort
, providerPort
;
799 IOServiceInterestContent64
* data
= (IOServiceInterestContent64
*)
800 ((((uint8_t *) pingMsg
) + msgSize
) - pingMsg
->notifyHeader
.size
);
801 // == pingMsg->notifyHeader.content;
803 if (kIOMessageCopyClientID
== messageType
)
805 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
806 return (kIOReturnSuccess
);
809 data
->messageType
= messageType
;
813 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
815 argSize
= sizeof(data
->messageArgument
[0]);
818 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
819 argSize
= sizeof(uint32_t);
824 if( argSize
> kIOUserNotifyMaxMessageSize
)
825 argSize
= kIOUserNotifyMaxMessageSize
;
826 bcopy( messageArgument
, data
->messageArgument
, argSize
);
829 // adjust message size for ipc restrictions
831 type
= pingMsg
->notifyHeader
.type
;
832 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
833 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
834 pingMsg
->notifyHeader
.type
= type
;
835 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
837 pingMsg
->msgHdr
.msgh_size
= msgSize
- pingMsg
->notifyHeader
.size
838 + sizeof( IOServiceInterestContent64
)
839 - sizeof( data
->messageArgument
)
842 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
843 pingMsg
->ports
[0].name
= providerPort
;
844 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
845 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
846 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
847 pingMsg
->msgHdr
.msgh_size
,
848 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
851 iokit_release_port( thisPort
);
853 iokit_release_port( providerPort
);
855 if( KERN_SUCCESS
!= kr
)
856 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
858 return( kIOReturnSuccess
);
861 OSObject
* IOServiceMessageUserNotification::getNextObject()
866 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
869 #define super IOService
870 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
872 void IOUserClient::initialize( void )
874 gIOObjectPortLock
= IOLockAlloc();
876 assert( gIOObjectPortLock
);
879 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
880 mach_port_t wakePort
,
881 void *callback
, void *refcon
)
883 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
884 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
885 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
886 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
889 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
890 mach_port_t wakePort
,
891 mach_vm_address_t callback
, io_user_reference_t refcon
)
893 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
894 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
895 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
896 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
899 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
900 mach_port_t wakePort
,
901 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
903 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
904 if (vm_map_is_64bit(get_task_map(task
))) {
905 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
909 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
912 OSDictionary
* user
= 0;
914 if ((array
= OSDynamicCast(OSArray
,
915 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
917 for (unsigned int idx
= 0;
918 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
922 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
923 && (uid
== num
->unsigned32BitValue())) {
933 static OSDictionary
* CopyUserOnConsole(void)
936 OSDictionary
* user
= 0;
938 if ((array
= OSDynamicCast(OSArray
,
939 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
941 for (unsigned int idx
= 0;
942 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
945 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
956 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
957 IOService
* service
)
961 p
= (proc_t
) get_bsdtask_info(task
);
964 uint64_t authorizationID
;
966 authorizationID
= proc_uniqueid(p
);
969 if (service
->getAuthorizationID() == authorizationID
)
971 return (kIOReturnSuccess
);
976 return (kIOReturnNotPermitted
);
979 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
980 const char * privilegeName
)
983 security_token_t token
;
984 mach_msg_type_number_t count
;
990 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
991 sizeof(kIOClientPrivilegeForeground
)))
993 if (task_is_gpu_denied(current_task()))
994 return (kIOReturnNotPrivileged
);
996 return (kIOReturnSuccess
);
999 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1000 sizeof(kIOClientPrivilegeConsoleSession
)))
1005 task
= (task_t
) securityToken
;
1007 task
= current_task();
1008 p
= (proc_t
) get_bsdtask_info(task
);
1009 kr
= kIOReturnNotPrivileged
;
1011 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1013 user
= CopyUserOnConsole();
1017 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1018 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1020 kr
= kIOReturnSuccess
;
1024 kauth_cred_unref(&cred
);
1029 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1030 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1031 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1033 task
= (task_t
)securityToken
;
1035 count
= TASK_SECURITY_TOKEN_COUNT
;
1036 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1038 if (KERN_SUCCESS
!= kr
)
1040 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1041 sizeof(kIOClientPrivilegeAdministrator
))) {
1042 if (0 != token
.val
[0])
1043 kr
= kIOReturnNotPrivileged
;
1044 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1045 sizeof(kIOClientPrivilegeLocalUser
))) {
1046 user
= CopyConsoleUser(token
.val
[0]);
1050 kr
= kIOReturnNotPrivileged
;
1051 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1052 sizeof(kIOClientPrivilegeConsoleUser
))) {
1053 user
= CopyConsoleUser(token
.val
[0]);
1055 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1056 kr
= kIOReturnNotPrivileged
;
1057 else if ( secureConsole
) {
1058 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1059 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1060 kr
= kIOReturnNotPrivileged
;
1065 kr
= kIOReturnNotPrivileged
;
1067 kr
= kIOReturnUnsupported
;
1072 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1073 const char * entitlement
)
1075 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1079 char procname
[MAXCOMLEN
+ 1] = "";
1081 void *entitlements_blob
= NULL
;
1082 char *entitlements_data
= NULL
;
1083 OSObject
*entitlements_obj
= NULL
;
1084 OSDictionary
*entitlements
= NULL
;
1085 OSString
*errorString
= NULL
;
1086 OSObject
*value
= NULL
;
1088 p
= (proc_t
)get_bsdtask_info(task
);
1092 proc_name(pid
, procname
, (int)sizeof(procname
));
1094 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1097 if (len
<= offsetof(CS_GenericBlob
, data
))
1101 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1102 * we'll try to parse in the kernel.
1104 len
-= offsetof(CS_GenericBlob
, data
);
1105 if (len
> MAX_ENTITLEMENTS_LEN
) {
1106 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1111 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1112 * what is stored in the entitlements blob. Copy the string and
1115 entitlements_data
= (char *)IOMalloc(len
+ 1);
1116 if (entitlements_data
== NULL
)
1118 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1119 entitlements_data
[len
] = '\0';
1121 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1122 if (errorString
!= NULL
) {
1123 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1126 if (entitlements_obj
== NULL
)
1129 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1130 if (entitlements
== NULL
)
1133 /* Fetch the entitlement value from the dictionary. */
1134 value
= entitlements
->getObject(entitlement
);
1139 if (entitlements_data
!= NULL
)
1140 IOFree(entitlements_data
, len
+ 1);
1141 if (entitlements_obj
!= NULL
)
1142 entitlements_obj
->release();
1143 if (errorString
!= NULL
)
1144 errorString
->release();
1148 bool IOUserClient::init()
1150 if (getPropertyTable() || super::init())
1156 bool IOUserClient::init(OSDictionary
* dictionary
)
1158 if (getPropertyTable() || super::init(dictionary
))
1164 bool IOUserClient::initWithTask(task_t owningTask
,
1168 if (getPropertyTable() || super::init())
1174 bool IOUserClient::initWithTask(task_t owningTask
,
1177 OSDictionary
* properties
)
1181 ok
= super::init( properties
);
1182 ok
&= initWithTask( owningTask
, securityID
, type
);
1187 bool IOUserClient::reserve()
1190 reserved
= IONew(ExpansionData
, 1);
1195 setTerminateDefer(NULL
, true);
1196 IOStatisticsRegisterCounter();
1201 void IOUserClient::free()
1204 mappings
->release();
1206 IOStatisticsUnregisterCounter();
1209 IODelete(reserved
, ExpansionData
, 1);
1214 IOReturn
IOUserClient::clientDied( void )
1216 return( clientClose());
1219 IOReturn
IOUserClient::clientClose( void )
1221 return( kIOReturnUnsupported
);
1224 IOService
* IOUserClient::getService( void )
1229 IOReturn
IOUserClient::registerNotificationPort(
1230 mach_port_t
/* port */,
1232 UInt32
/* refCon */)
1234 return( kIOReturnUnsupported
);
1237 IOReturn
IOUserClient::registerNotificationPort(
1240 io_user_reference_t refCon
)
1242 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1245 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1246 semaphore_t
* semaphore
)
1248 return( kIOReturnUnsupported
);
1251 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1253 return( kIOReturnUnsupported
);
1256 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1257 IOOptionBits
* options
,
1258 IOMemoryDescriptor
** memory
)
1260 return( kIOReturnUnsupported
);
1264 IOMemoryMap
* IOUserClient::mapClientMemory(
1267 IOOptionBits mapFlags
,
1268 IOVirtualAddress atAddress
)
1274 IOMemoryMap
* IOUserClient::mapClientMemory64(
1277 IOOptionBits mapFlags
,
1278 mach_vm_address_t atAddress
)
1281 IOOptionBits options
= 0;
1282 IOMemoryDescriptor
* memory
;
1283 IOMemoryMap
* map
= 0;
1285 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1287 if( memory
&& (kIOReturnSuccess
== err
)) {
1289 options
= (options
& ~kIOMapUserOptionsMask
)
1290 | (mapFlags
& kIOMapUserOptionsMask
);
1291 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1298 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1299 OSObject
*obj
, io_object_t
*clientObj
)
1301 mach_port_name_t name
;
1303 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1305 *(mach_port_name_t
*)clientObj
= name
;
1306 return kIOReturnSuccess
;
1309 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1314 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1319 IOExternalMethod
* IOUserClient::
1320 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1322 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1325 *targetP
= (IOService
*) method
->object
;
1330 IOExternalAsyncMethod
* IOUserClient::
1331 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1333 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1336 *targetP
= (IOService
*) method
->object
;
1341 IOExternalTrap
* IOUserClient::
1342 getExternalTrapForIndex(UInt32 index
)
1347 IOExternalTrap
* IOUserClient::
1348 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1350 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1353 *targetP
= trap
->object
;
1359 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1362 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1364 if (MACH_PORT_NULL
!= port
)
1365 iokit_release_port_send(port
);
1367 return (kIOReturnSuccess
);
1370 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1372 if (MACH_PORT_NULL
!= port
)
1373 iokit_release_port_send(port
);
1375 return (kIOReturnSuccess
);
1378 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1379 IOReturn result
, void *args
[], UInt32 numArgs
)
1381 OSAsyncReference64 reference64
;
1382 io_user_reference_t args64
[kMaxAsyncArgs
];
1385 if (numArgs
> kMaxAsyncArgs
)
1386 return kIOReturnMessageTooLarge
;
1388 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1389 reference64
[idx
] = REF64(reference
[idx
]);
1391 for (idx
= 0; idx
< numArgs
; idx
++)
1392 args64
[idx
] = REF64(args
[idx
]);
1394 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1397 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1398 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1400 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1403 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1404 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1406 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1409 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1410 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1414 mach_msg_header_t msgHdr
;
1419 OSNotificationHeader notifyHdr
;
1420 IOAsyncCompletionContent asyncContent
;
1421 uint32_t args
[kMaxAsyncArgs
];
1425 OSNotificationHeader64 notifyHdr
;
1426 IOAsyncCompletionContent asyncContent
;
1427 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1432 mach_port_t replyPort
;
1435 // If no reply port, do nothing.
1436 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1437 if (replyPort
== MACH_PORT_NULL
)
1438 return kIOReturnSuccess
;
1440 if (numArgs
> kMaxAsyncArgs
)
1441 return kIOReturnMessageTooLarge
;
1443 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1445 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1446 replyMsg
.msgHdr
.msgh_local_port
= 0;
1447 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1448 if (kIOUCAsync64Flag
& reference
[0])
1450 replyMsg
.msgHdr
.msgh_size
=
1451 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1452 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1453 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1454 + numArgs
* sizeof(io_user_reference_t
);
1455 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1456 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1458 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1460 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1466 replyMsg
.msgHdr
.msgh_size
=
1467 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1468 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1470 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1471 + numArgs
* sizeof(uint32_t);
1472 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1474 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1475 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1477 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1479 for (idx
= 0; idx
< numArgs
; idx
++)
1480 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1483 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1484 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1485 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1487 /* Fail on full queue. */
1488 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1489 replyMsg
.msgHdr
.msgh_size
);
1491 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
))
1492 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1497 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1501 #define CHECK(cls,obj,out) \
1503 if( !(out = OSDynamicCast( cls, obj))) \
1504 return( kIOReturnBadArgument )
1506 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1508 /* Routine io_server_version */
1509 kern_return_t
is_io_server_version(
1510 mach_port_t master_port
,
1513 *version
= IOKIT_SERVER_VERSION
;
1514 return (kIOReturnSuccess
);
1517 /* Routine io_object_get_class */
1518 kern_return_t
is_io_object_get_class(
1520 io_name_t className
)
1522 const OSMetaClass
* my_obj
= NULL
;
1525 return( kIOReturnBadArgument
);
1527 my_obj
= object
->getMetaClass();
1529 return (kIOReturnNotFound
);
1532 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1533 return( kIOReturnSuccess
);
1536 /* Routine io_object_get_superclass */
1537 kern_return_t
is_io_object_get_superclass(
1538 mach_port_t master_port
,
1540 io_name_t class_name
)
1542 const OSMetaClass
* my_obj
= NULL
;
1543 const OSMetaClass
* superclass
= NULL
;
1544 const OSSymbol
*my_name
= NULL
;
1545 const char *my_cstr
= NULL
;
1547 if (!obj_name
|| !class_name
)
1548 return (kIOReturnBadArgument
);
1550 if( master_port
!= master_device_port
)
1551 return( kIOReturnNotPrivileged
);
1553 my_name
= OSSymbol::withCString(obj_name
);
1556 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1560 superclass
= my_obj
->getSuperClass();
1564 return( kIOReturnNotFound
);
1567 my_cstr
= superclass
->getClassName();
1570 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1571 return( kIOReturnSuccess
);
1573 return (kIOReturnNotFound
);
1576 /* Routine io_object_get_bundle_identifier */
1577 kern_return_t
is_io_object_get_bundle_identifier(
1578 mach_port_t master_port
,
1580 io_name_t bundle_name
)
1582 const OSMetaClass
* my_obj
= NULL
;
1583 const OSSymbol
*my_name
= NULL
;
1584 const OSSymbol
*identifier
= NULL
;
1585 const char *my_cstr
= NULL
;
1587 if (!obj_name
|| !bundle_name
)
1588 return (kIOReturnBadArgument
);
1590 if( master_port
!= master_device_port
)
1591 return( kIOReturnNotPrivileged
);
1593 my_name
= OSSymbol::withCString(obj_name
);
1596 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1601 identifier
= my_obj
->getKmodName();
1604 return( kIOReturnNotFound
);
1607 my_cstr
= identifier
->getCStringNoCopy();
1609 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1610 return( kIOReturnSuccess
);
1613 return (kIOReturnBadArgument
);
1616 /* Routine io_object_conforms_to */
1617 kern_return_t
is_io_object_conforms_to(
1619 io_name_t className
,
1620 boolean_t
*conforms
)
1623 return( kIOReturnBadArgument
);
1625 *conforms
= (0 != object
->metaCast( className
));
1626 return( kIOReturnSuccess
);
1629 /* Routine io_object_get_retain_count */
1630 kern_return_t
is_io_object_get_retain_count(
1632 uint32_t *retainCount
)
1635 return( kIOReturnBadArgument
);
1637 *retainCount
= object
->getRetainCount();
1638 return( kIOReturnSuccess
);
1641 /* Routine io_iterator_next */
1642 kern_return_t
is_io_iterator_next(
1643 io_object_t iterator
,
1644 io_object_t
*object
)
1648 CHECK( OSIterator
, iterator
, iter
);
1650 obj
= iter
->getNextObject();
1654 return( kIOReturnSuccess
);
1656 return( kIOReturnNoDevice
);
1659 /* Routine io_iterator_reset */
1660 kern_return_t
is_io_iterator_reset(
1661 io_object_t iterator
)
1663 CHECK( OSIterator
, iterator
, iter
);
1667 return( kIOReturnSuccess
);
1670 /* Routine io_iterator_is_valid */
1671 kern_return_t
is_io_iterator_is_valid(
1672 io_object_t iterator
,
1673 boolean_t
*is_valid
)
1675 CHECK( OSIterator
, iterator
, iter
);
1677 *is_valid
= iter
->isValid();
1679 return( kIOReturnSuccess
);
1683 static kern_return_t
internal_io_service_match_property_table(
1684 io_service_t _service
,
1685 const char * matching
,
1686 mach_msg_type_number_t matching_size
,
1689 CHECK( IOService
, _service
, service
);
1693 OSDictionary
* dict
;
1695 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1696 : OSUnserializeXML(matching
);
1697 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1698 *matches
= service
->passiveMatch( dict
);
1699 kr
= kIOReturnSuccess
;
1701 kr
= kIOReturnBadArgument
;
1709 /* Routine io_service_match_property_table */
1710 kern_return_t
is_io_service_match_property_table(
1711 io_service_t service
,
1712 io_string_t matching
,
1713 boolean_t
*matches
)
1715 return (internal_io_service_match_property_table(service
, matching
, 0, matches
));
1719 /* Routine io_service_match_property_table_ool */
1720 kern_return_t
is_io_service_match_property_table_ool(
1721 io_object_t service
,
1722 io_buf_ptr_t matching
,
1723 mach_msg_type_number_t matchingCnt
,
1724 kern_return_t
*result
,
1725 boolean_t
*matches
)
1729 vm_map_offset_t map_data
;
1731 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1732 data
= CAST_DOWN(vm_offset_t
, map_data
);
1734 if( KERN_SUCCESS
== kr
) {
1735 // must return success after vm_map_copyout() succeeds
1736 *result
= internal_io_service_match_property_table(service
,
1737 (const char *)data
, matchingCnt
, matches
);
1738 vm_deallocate( kernel_map
, data
, matchingCnt
);
1744 /* Routine io_service_match_property_table_bin */
1745 kern_return_t
is_io_service_match_property_table_bin(
1746 io_object_t service
,
1747 io_struct_inband_t matching
,
1748 mach_msg_type_number_t matchingCnt
,
1751 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
1754 static kern_return_t
internal_io_service_get_matching_services(
1755 mach_port_t master_port
,
1756 const char * matching
,
1757 mach_msg_type_number_t matching_size
,
1758 io_iterator_t
*existing
)
1762 OSDictionary
* dict
;
1764 if( master_port
!= master_device_port
)
1765 return( kIOReturnNotPrivileged
);
1767 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1768 : OSUnserializeXML(matching
);
1769 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1770 *existing
= IOService::getMatchingServices( dict
);
1771 kr
= kIOReturnSuccess
;
1773 kr
= kIOReturnBadArgument
;
1781 /* Routine io_service_get_matching_services */
1782 kern_return_t
is_io_service_get_matching_services(
1783 mach_port_t master_port
,
1784 io_string_t matching
,
1785 io_iterator_t
*existing
)
1787 return (internal_io_service_get_matching_services(master_port
, matching
, 0, existing
));
1790 /* Routine io_service_get_matching_services_ool */
1791 kern_return_t
is_io_service_get_matching_services_ool(
1792 mach_port_t master_port
,
1793 io_buf_ptr_t matching
,
1794 mach_msg_type_number_t matchingCnt
,
1795 kern_return_t
*result
,
1796 io_object_t
*existing
)
1800 vm_map_offset_t map_data
;
1802 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1803 data
= CAST_DOWN(vm_offset_t
, map_data
);
1805 if( KERN_SUCCESS
== kr
) {
1806 // must return success after vm_map_copyout() succeeds
1807 *result
= internal_io_service_get_matching_services(master_port
,
1808 (const char *) data
, matchingCnt
, existing
);
1809 vm_deallocate( kernel_map
, data
, matchingCnt
);
1815 /* Routine io_service_get_matching_services_bin */
1816 kern_return_t
is_io_service_get_matching_services_bin(
1817 mach_port_t master_port
,
1818 io_struct_inband_t matching
,
1819 mach_msg_type_number_t matchingCnt
,
1820 io_object_t
*existing
)
1822 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
1826 static kern_return_t
internal_io_service_get_matching_service(
1827 mach_port_t master_port
,
1828 const char * matching
,
1829 mach_msg_type_number_t matching_size
,
1830 io_service_t
*service
)
1834 OSDictionary
* dict
;
1836 if( master_port
!= master_device_port
)
1837 return( kIOReturnNotPrivileged
);
1839 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1840 : OSUnserializeXML(matching
);
1841 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1842 *service
= IOService::copyMatchingService( dict
);
1843 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
1845 kr
= kIOReturnBadArgument
;
1853 /* Routine io_service_get_matching_service */
1854 kern_return_t
is_io_service_get_matching_service(
1855 mach_port_t master_port
,
1856 io_string_t matching
,
1857 io_service_t
*service
)
1859 return (internal_io_service_get_matching_service(master_port
, matching
, 0, service
));
1862 /* Routine io_service_get_matching_services_ool */
1863 kern_return_t
is_io_service_get_matching_service_ool(
1864 mach_port_t master_port
,
1865 io_buf_ptr_t matching
,
1866 mach_msg_type_number_t matchingCnt
,
1867 kern_return_t
*result
,
1868 io_object_t
*service
)
1872 vm_map_offset_t map_data
;
1874 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1875 data
= CAST_DOWN(vm_offset_t
, map_data
);
1877 if( KERN_SUCCESS
== kr
) {
1878 // must return success after vm_map_copyout() succeeds
1879 *result
= internal_io_service_get_matching_service(master_port
,
1880 (const char *) data
, matchingCnt
, service
);
1881 vm_deallocate( kernel_map
, data
, matchingCnt
);
1887 /* Routine io_service_get_matching_service_bin */
1888 kern_return_t
is_io_service_get_matching_service_bin(
1889 mach_port_t master_port
,
1890 io_struct_inband_t matching
,
1891 mach_msg_type_number_t matchingCnt
,
1892 io_object_t
*service
)
1894 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
1897 static kern_return_t
internal_io_service_add_notification(
1898 mach_port_t master_port
,
1899 io_name_t notification_type
,
1900 const char * matching
,
1901 size_t matching_size
,
1904 vm_size_t referenceSize
,
1906 io_object_t
* notification
)
1908 IOServiceUserNotification
* userNotify
= 0;
1909 IONotifier
* notify
= 0;
1910 const OSSymbol
* sym
;
1911 OSDictionary
* dict
;
1913 unsigned long int userMsgType
;
1915 if( master_port
!= master_device_port
)
1916 return( kIOReturnNotPrivileged
);
1919 err
= kIOReturnNoResources
;
1921 if( !(sym
= OSSymbol::withCString( notification_type
)))
1922 err
= kIOReturnNoResources
;
1926 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
1930 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
));
1934 err
= kIOReturnBadArgument
;
1938 if( (sym
== gIOPublishNotification
)
1939 || (sym
== gIOFirstPublishNotification
))
1940 userMsgType
= kIOServicePublishNotificationType
;
1941 else if( (sym
== gIOMatchedNotification
)
1942 || (sym
== gIOFirstMatchNotification
))
1943 userMsgType
= kIOServiceMatchedNotificationType
;
1944 else if( sym
== gIOTerminatedNotification
)
1945 userMsgType
= kIOServiceTerminatedNotificationType
;
1947 userMsgType
= kLastIOKitNotificationType
;
1949 userNotify
= new IOServiceUserNotification
;
1951 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1952 reference
, referenceSize
, client64
)) {
1953 iokit_release_port_send(port
);
1954 userNotify
->release();
1960 notify
= IOService::addMatchingNotification( sym
, dict
,
1961 &userNotify
->_handler
, userNotify
);
1963 *notification
= userNotify
;
1964 userNotify
->setNotification( notify
);
1965 err
= kIOReturnSuccess
;
1967 err
= kIOReturnUnsupported
;
1980 /* Routine io_service_add_notification */
1981 kern_return_t
is_io_service_add_notification(
1982 mach_port_t master_port
,
1983 io_name_t notification_type
,
1984 io_string_t matching
,
1986 io_async_ref_t reference
,
1987 mach_msg_type_number_t referenceCnt
,
1988 io_object_t
* notification
)
1990 return (internal_io_service_add_notification(master_port
, notification_type
,
1991 matching
, 0, port
, &reference
[0], sizeof(io_async_ref_t
),
1992 false, notification
));
1995 /* Routine io_service_add_notification_64 */
1996 kern_return_t
is_io_service_add_notification_64(
1997 mach_port_t master_port
,
1998 io_name_t notification_type
,
1999 io_string_t matching
,
2000 mach_port_t wake_port
,
2001 io_async_ref64_t reference
,
2002 mach_msg_type_number_t referenceCnt
,
2003 io_object_t
*notification
)
2005 return (internal_io_service_add_notification(master_port
, notification_type
,
2006 matching
, 0, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2007 true, notification
));
2010 /* Routine io_service_add_notification_bin */
2011 kern_return_t is_io_service_add_notification_bin
2013 mach_port_t master_port
,
2014 io_name_t notification_type
,
2015 io_struct_inband_t matching
,
2016 mach_msg_type_number_t matchingCnt
,
2017 mach_port_t wake_port
,
2018 io_async_ref_t reference
,
2019 mach_msg_type_number_t referenceCnt
,
2020 io_object_t
*notification
)
2022 return (internal_io_service_add_notification(master_port
, notification_type
,
2023 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2024 false, notification
));
2027 /* Routine io_service_add_notification_bin_64 */
2028 kern_return_t is_io_service_add_notification_bin_64
2030 mach_port_t master_port
,
2031 io_name_t notification_type
,
2032 io_struct_inband_t matching
,
2033 mach_msg_type_number_t matchingCnt
,
2034 mach_port_t wake_port
,
2035 io_async_ref64_t reference
,
2036 mach_msg_type_number_t referenceCnt
,
2037 io_object_t
*notification
)
2039 return (internal_io_service_add_notification(master_port
, notification_type
,
2040 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2041 true, notification
));
2044 static kern_return_t
internal_io_service_add_notification_ool(
2045 mach_port_t master_port
,
2046 io_name_t notification_type
,
2047 io_buf_ptr_t matching
,
2048 mach_msg_type_number_t matchingCnt
,
2049 mach_port_t wake_port
,
2051 vm_size_t referenceSize
,
2053 kern_return_t
*result
,
2054 io_object_t
*notification
)
2058 vm_map_offset_t map_data
;
2060 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2061 data
= CAST_DOWN(vm_offset_t
, map_data
);
2063 if( KERN_SUCCESS
== kr
) {
2064 // must return success after vm_map_copyout() succeeds
2065 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2066 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2067 vm_deallocate( kernel_map
, data
, matchingCnt
);
2073 /* Routine io_service_add_notification_ool */
2074 kern_return_t
is_io_service_add_notification_ool(
2075 mach_port_t master_port
,
2076 io_name_t notification_type
,
2077 io_buf_ptr_t matching
,
2078 mach_msg_type_number_t matchingCnt
,
2079 mach_port_t wake_port
,
2080 io_async_ref_t reference
,
2081 mach_msg_type_number_t referenceCnt
,
2082 kern_return_t
*result
,
2083 io_object_t
*notification
)
2085 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2086 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2087 false, result
, notification
));
2090 /* Routine io_service_add_notification_ool_64 */
2091 kern_return_t
is_io_service_add_notification_ool_64(
2092 mach_port_t master_port
,
2093 io_name_t notification_type
,
2094 io_buf_ptr_t matching
,
2095 mach_msg_type_number_t matchingCnt
,
2096 mach_port_t wake_port
,
2097 io_async_ref64_t reference
,
2098 mach_msg_type_number_t referenceCnt
,
2099 kern_return_t
*result
,
2100 io_object_t
*notification
)
2102 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2103 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2104 true, result
, notification
));
2107 /* Routine io_service_add_notification_old */
2108 kern_return_t
is_io_service_add_notification_old(
2109 mach_port_t master_port
,
2110 io_name_t notification_type
,
2111 io_string_t matching
,
2113 // for binary compatibility reasons, this must be natural_t for ILP32
2115 io_object_t
* notification
)
2117 return( is_io_service_add_notification( master_port
, notification_type
,
2118 matching
, port
, &ref
, 1, notification
));
2122 static kern_return_t
internal_io_service_add_interest_notification(
2123 io_object_t _service
,
2124 io_name_t type_of_interest
,
2127 vm_size_t referenceSize
,
2129 io_object_t
* notification
)
2132 IOServiceMessageUserNotification
* userNotify
= 0;
2133 IONotifier
* notify
= 0;
2134 const OSSymbol
* sym
;
2137 CHECK( IOService
, _service
, service
);
2139 err
= kIOReturnNoResources
;
2140 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2142 userNotify
= new IOServiceMessageUserNotification
;
2144 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2145 reference
, referenceSize
,
2146 kIOUserNotifyMaxMessageSize
,
2148 iokit_release_port_send(port
);
2149 userNotify
->release();
2155 notify
= service
->registerInterest( sym
,
2156 &userNotify
->_handler
, userNotify
);
2158 *notification
= userNotify
;
2159 userNotify
->setNotification( notify
);
2160 err
= kIOReturnSuccess
;
2162 err
= kIOReturnUnsupported
;
2171 /* Routine io_service_add_message_notification */
2172 kern_return_t
is_io_service_add_interest_notification(
2173 io_object_t service
,
2174 io_name_t type_of_interest
,
2176 io_async_ref_t reference
,
2177 mach_msg_type_number_t referenceCnt
,
2178 io_object_t
* notification
)
2180 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2181 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2184 /* Routine io_service_add_interest_notification_64 */
2185 kern_return_t
is_io_service_add_interest_notification_64(
2186 io_object_t service
,
2187 io_name_t type_of_interest
,
2188 mach_port_t wake_port
,
2189 io_async_ref64_t reference
,
2190 mach_msg_type_number_t referenceCnt
,
2191 io_object_t
*notification
)
2193 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2194 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2198 /* Routine io_service_acknowledge_notification */
2199 kern_return_t
is_io_service_acknowledge_notification(
2200 io_object_t _service
,
2201 natural_t notify_ref
,
2202 natural_t response
)
2204 CHECK( IOService
, _service
, service
);
2206 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2207 (IOOptionBits
) response
));
2211 /* Routine io_connect_get_semaphore */
2212 kern_return_t
is_io_connect_get_notification_semaphore(
2213 io_connect_t connection
,
2214 natural_t notification_type
,
2215 semaphore_t
*semaphore
)
2217 CHECK( IOUserClient
, connection
, client
);
2219 IOStatisticsClientCall();
2220 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2224 /* Routine io_registry_get_root_entry */
2225 kern_return_t
is_io_registry_get_root_entry(
2226 mach_port_t master_port
,
2229 IORegistryEntry
* entry
;
2231 if( master_port
!= master_device_port
)
2232 return( kIOReturnNotPrivileged
);
2234 entry
= IORegistryEntry::getRegistryRoot();
2239 return( kIOReturnSuccess
);
2242 /* Routine io_registry_create_iterator */
2243 kern_return_t
is_io_registry_create_iterator(
2244 mach_port_t master_port
,
2247 io_object_t
*iterator
)
2249 if( master_port
!= master_device_port
)
2250 return( kIOReturnNotPrivileged
);
2252 *iterator
= IORegistryIterator::iterateOver(
2253 IORegistryEntry::getPlane( plane
), options
);
2255 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2258 /* Routine io_registry_entry_create_iterator */
2259 kern_return_t
is_io_registry_entry_create_iterator(
2260 io_object_t registry_entry
,
2263 io_object_t
*iterator
)
2265 CHECK( IORegistryEntry
, registry_entry
, entry
);
2267 *iterator
= IORegistryIterator::iterateOver( entry
,
2268 IORegistryEntry::getPlane( plane
), options
);
2270 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2273 /* Routine io_registry_iterator_enter */
2274 kern_return_t
is_io_registry_iterator_enter_entry(
2275 io_object_t iterator
)
2277 CHECK( IORegistryIterator
, iterator
, iter
);
2281 return( kIOReturnSuccess
);
2284 /* Routine io_registry_iterator_exit */
2285 kern_return_t
is_io_registry_iterator_exit_entry(
2286 io_object_t iterator
)
2290 CHECK( IORegistryIterator
, iterator
, iter
);
2292 didIt
= iter
->exitEntry();
2294 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2297 /* Routine io_registry_entry_from_path */
2298 kern_return_t
is_io_registry_entry_from_path(
2299 mach_port_t master_port
,
2301 io_object_t
*registry_entry
)
2303 IORegistryEntry
* entry
;
2305 if( master_port
!= master_device_port
)
2306 return( kIOReturnNotPrivileged
);
2308 entry
= IORegistryEntry::fromPath( path
);
2310 *registry_entry
= entry
;
2312 return( kIOReturnSuccess
);
2315 /* Routine io_registry_entry_in_plane */
2316 kern_return_t
is_io_registry_entry_in_plane(
2317 io_object_t registry_entry
,
2319 boolean_t
*inPlane
)
2321 CHECK( IORegistryEntry
, registry_entry
, entry
);
2323 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2325 return( kIOReturnSuccess
);
2329 /* Routine io_registry_entry_get_path */
2330 kern_return_t
is_io_registry_entry_get_path(
2331 io_object_t registry_entry
,
2336 CHECK( IORegistryEntry
, registry_entry
, entry
);
2338 length
= sizeof( io_string_t
);
2339 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2340 return( kIOReturnSuccess
);
2342 return( kIOReturnBadArgument
);
2346 /* Routine io_registry_entry_get_name */
2347 kern_return_t
is_io_registry_entry_get_name(
2348 io_object_t registry_entry
,
2351 CHECK( IORegistryEntry
, registry_entry
, entry
);
2353 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2355 return( kIOReturnSuccess
);
2358 /* Routine io_registry_entry_get_name_in_plane */
2359 kern_return_t
is_io_registry_entry_get_name_in_plane(
2360 io_object_t registry_entry
,
2361 io_name_t planeName
,
2364 const IORegistryPlane
* plane
;
2365 CHECK( IORegistryEntry
, registry_entry
, entry
);
2368 plane
= IORegistryEntry::getPlane( planeName
);
2372 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2374 return( kIOReturnSuccess
);
2377 /* Routine io_registry_entry_get_location_in_plane */
2378 kern_return_t
is_io_registry_entry_get_location_in_plane(
2379 io_object_t registry_entry
,
2380 io_name_t planeName
,
2381 io_name_t location
)
2383 const IORegistryPlane
* plane
;
2384 CHECK( IORegistryEntry
, registry_entry
, entry
);
2387 plane
= IORegistryEntry::getPlane( planeName
);
2391 const char * cstr
= entry
->getLocation( plane
);
2394 strncpy( location
, cstr
, sizeof( io_name_t
));
2395 return( kIOReturnSuccess
);
2397 return( kIOReturnNotFound
);
2400 /* Routine io_registry_entry_get_registry_entry_id */
2401 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2402 io_object_t registry_entry
,
2403 uint64_t *entry_id
)
2405 CHECK( IORegistryEntry
, registry_entry
, entry
);
2407 *entry_id
= entry
->getRegistryEntryID();
2409 return (kIOReturnSuccess
);
2412 // Create a vm_map_copy_t or kalloc'ed data for memory
2413 // to be copied out. ipc will free after the copyout.
2415 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
2416 io_buf_ptr_t
* buf
)
2421 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
2422 false /* src_destroy */, ©
);
2424 assert( err
== KERN_SUCCESS
);
2425 if( err
== KERN_SUCCESS
)
2426 *buf
= (char *) copy
;
2431 /* Routine io_registry_entry_get_property */
2432 kern_return_t
is_io_registry_entry_get_property_bytes(
2433 io_object_t registry_entry
,
2434 io_name_t property_name
,
2435 io_struct_inband_t buf
,
2436 mach_msg_type_number_t
*dataCnt
)
2444 unsigned int len
= 0;
2445 const void * bytes
= 0;
2446 IOReturn ret
= kIOReturnSuccess
;
2448 CHECK( IORegistryEntry
, registry_entry
, entry
);
2451 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2452 return kIOReturnNotPermitted
;
2455 obj
= entry
->copyProperty(property_name
);
2457 return( kIOReturnNoResources
);
2459 // One day OSData will be a common container base class
2461 if( (data
= OSDynamicCast( OSData
, obj
))) {
2462 len
= data
->getLength();
2463 bytes
= data
->getBytesNoCopy();
2465 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2466 len
= str
->getLength() + 1;
2467 bytes
= str
->getCStringNoCopy();
2469 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2470 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2471 bytes
= boo
->isTrue() ? "Yes" : "No";
2473 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2474 offsetBytes
= off
->unsigned64BitValue();
2475 len
= off
->numberOfBytes();
2476 bytes
= &offsetBytes
;
2477 #ifdef __BIG_ENDIAN__
2478 bytes
= (const void *)
2479 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2483 ret
= kIOReturnBadArgument
;
2487 ret
= kIOReturnIPCError
;
2490 bcopy( bytes
, buf
, len
);
2499 /* Routine io_registry_entry_get_property */
2500 kern_return_t
is_io_registry_entry_get_property(
2501 io_object_t registry_entry
,
2502 io_name_t property_name
,
2503 io_buf_ptr_t
*properties
,
2504 mach_msg_type_number_t
*propertiesCnt
)
2510 CHECK( IORegistryEntry
, registry_entry
, entry
);
2513 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2514 return kIOReturnNotPermitted
;
2517 obj
= entry
->copyProperty(property_name
);
2519 return( kIOReturnNotFound
);
2521 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2524 return( kIOReturnNoMemory
);
2527 if( obj
->serialize( s
)) {
2528 len
= s
->getLength();
2529 *propertiesCnt
= len
;
2530 err
= copyoutkdata( s
->text(), len
, properties
);
2533 err
= kIOReturnUnsupported
;
2541 /* Routine io_registry_entry_get_property_recursively */
2542 kern_return_t
is_io_registry_entry_get_property_recursively(
2543 io_object_t registry_entry
,
2545 io_name_t property_name
,
2547 io_buf_ptr_t
*properties
,
2548 mach_msg_type_number_t
*propertiesCnt
)
2554 CHECK( IORegistryEntry
, registry_entry
, entry
);
2557 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2558 return kIOReturnNotPermitted
;
2561 obj
= entry
->copyProperty( property_name
,
2562 IORegistryEntry::getPlane( plane
), options
);
2564 return( kIOReturnNotFound
);
2566 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2569 return( kIOReturnNoMemory
);
2572 if( obj
->serialize( s
)) {
2573 len
= s
->getLength();
2574 *propertiesCnt
= len
;
2575 err
= copyoutkdata( s
->text(), len
, properties
);
2578 err
= kIOReturnUnsupported
;
2588 static kern_return_t
2589 filteredProperties(IORegistryEntry
*entry
, OSDictionary
*properties
, OSDictionary
**filteredp
)
2591 kern_return_t err
= 0;
2592 OSDictionary
*filtered
= NULL
;
2593 OSCollectionIterator
*iter
= NULL
;
2596 kauth_cred_t cred
= kauth_cred_get();
2598 if (properties
== NULL
)
2599 return kIOReturnUnsupported
;
2601 if ((iter
= OSCollectionIterator::withCollection(properties
)) == NULL
||
2602 (filtered
= OSDictionary::withCapacity(properties
->getCapacity())) == NULL
) {
2603 err
= kIOReturnNoMemory
;
2607 while ((p
= iter
->getNextObject()) != NULL
) {
2608 if ((key
= OSDynamicCast(OSSymbol
, p
)) == NULL
||
2609 mac_iokit_check_get_property(cred
, entry
, key
->getCStringNoCopy()) != 0)
2611 filtered
->setObject(key
, properties
->getObject(key
));
2617 *filteredp
= filtered
;
2623 /* Routine io_registry_entry_get_properties */
2624 kern_return_t
is_io_registry_entry_get_properties(
2625 io_object_t registry_entry
,
2626 io_buf_ptr_t
*properties
,
2627 mach_msg_type_number_t
*propertiesCnt
)
2629 kern_return_t err
= 0;
2632 CHECK( IORegistryEntry
, registry_entry
, entry
);
2634 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2636 return( kIOReturnNoMemory
);
2638 if (!entry
->serializeProperties(s
))
2639 err
= kIOReturnUnsupported
;
2642 if (!err
&& mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
2643 OSObject
*propobj
= OSUnserializeXML(s
->text(), s
->getLength());
2644 OSDictionary
*filteredprops
= NULL
;
2645 err
= filteredProperties(entry
, OSDynamicCast(OSDictionary
, propobj
), &filteredprops
);
2646 if (propobj
) propobj
->release();
2650 if (!filteredprops
->serialize(s
))
2651 err
= kIOReturnUnsupported
;
2653 if (filteredprops
!= NULL
)
2654 filteredprops
->release();
2656 #endif /* CONFIG_MACF */
2659 len
= s
->getLength();
2660 *propertiesCnt
= len
;
2661 err
= copyoutkdata( s
->text(), len
, properties
);
2670 struct GetPropertiesEditorRef
2673 IORegistryEntry
* entry
;
2674 OSCollection
* root
;
2677 static const OSMetaClassBase
*
2678 GetPropertiesEditor(void * reference
,
2680 OSCollection
* container
,
2681 const OSSymbol
* name
,
2682 const OSMetaClassBase
* value
)
2684 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
2686 if (!ref
->root
) ref
->root
= container
;
2687 if (ref
->root
== container
)
2689 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
2694 if (value
) value
->retain();
2698 #endif /* CONFIG_MACF */
2700 /* Routine io_registry_entry_get_properties */
2701 kern_return_t
is_io_registry_entry_get_properties_bin(
2702 io_object_t registry_entry
,
2703 io_buf_ptr_t
*properties
,
2704 mach_msg_type_number_t
*propertiesCnt
)
2706 kern_return_t err
= kIOReturnSuccess
;
2709 OSSerialize::Editor editor
= 0;
2712 CHECK(IORegistryEntry
, registry_entry
, entry
);
2715 GetPropertiesEditorRef ref
;
2716 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
2718 editor
= &GetPropertiesEditor
;
2720 ref
.cred
= kauth_cred_get();
2726 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
2727 if (!s
) return (kIOReturnNoMemory
);
2729 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
2731 if (kIOReturnSuccess
== err
)
2733 len
= s
->getLength();
2734 *propertiesCnt
= len
;
2735 err
= copyoutkdata(s
->text(), len
, properties
);
2742 /* Routine io_registry_entry_get_property_bin */
2743 kern_return_t
is_io_registry_entry_get_property_bin(
2744 io_object_t registry_entry
,
2746 io_name_t property_name
,
2748 io_buf_ptr_t
*properties
,
2749 mach_msg_type_number_t
*propertiesCnt
)
2754 const OSSymbol
* sym
;
2756 CHECK( IORegistryEntry
, registry_entry
, entry
);
2759 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2760 return kIOReturnNotPermitted
;
2763 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
2765 obj
= entry
->copyProperty(property_name
,
2766 IORegistryEntry::getPlane(plane
), options
);
2770 obj
= entry
->copyProperty(property_name
);
2774 return( kIOReturnNotFound
);
2776 sym
= OSSymbol::withCString(property_name
);
2779 if (gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
2783 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
2786 return( kIOReturnNoMemory
);
2789 if( obj
->serialize( s
)) {
2790 len
= s
->getLength();
2791 *propertiesCnt
= len
;
2792 err
= copyoutkdata( s
->text(), len
, properties
);
2794 } else err
= kIOReturnUnsupported
;
2802 /* Routine io_registry_entry_set_properties */
2803 kern_return_t is_io_registry_entry_set_properties
2805 io_object_t registry_entry
,
2806 io_buf_ptr_t properties
,
2807 mach_msg_type_number_t propertiesCnt
,
2808 kern_return_t
* result
)
2814 vm_map_offset_t map_data
;
2816 CHECK( IORegistryEntry
, registry_entry
, entry
);
2818 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
2819 return( kIOReturnMessageTooLarge
);
2821 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2822 data
= CAST_DOWN(vm_offset_t
, map_data
);
2824 if( KERN_SUCCESS
== err
) {
2826 // must return success after vm_map_copyout() succeeds
2827 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
2828 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2831 res
= kIOReturnBadArgument
;
2833 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
2834 registry_entry
, obj
))
2836 res
= kIOReturnNotPermitted
;
2841 res
= entry
->setProperties( obj
);
2853 /* Routine io_registry_entry_get_child_iterator */
2854 kern_return_t
is_io_registry_entry_get_child_iterator(
2855 io_object_t registry_entry
,
2857 io_object_t
*iterator
)
2859 CHECK( IORegistryEntry
, registry_entry
, entry
);
2861 *iterator
= entry
->getChildIterator(
2862 IORegistryEntry::getPlane( plane
));
2864 return( kIOReturnSuccess
);
2867 /* Routine io_registry_entry_get_parent_iterator */
2868 kern_return_t
is_io_registry_entry_get_parent_iterator(
2869 io_object_t registry_entry
,
2871 io_object_t
*iterator
)
2873 CHECK( IORegistryEntry
, registry_entry
, entry
);
2875 *iterator
= entry
->getParentIterator(
2876 IORegistryEntry::getPlane( plane
));
2878 return( kIOReturnSuccess
);
2881 /* Routine io_service_get_busy_state */
2882 kern_return_t
is_io_service_get_busy_state(
2883 io_object_t _service
,
2884 uint32_t *busyState
)
2886 CHECK( IOService
, _service
, service
);
2888 *busyState
= service
->getBusyState();
2890 return( kIOReturnSuccess
);
2893 /* Routine io_service_get_state */
2894 kern_return_t
is_io_service_get_state(
2895 io_object_t _service
,
2897 uint32_t *busy_state
,
2898 uint64_t *accumulated_busy_time
)
2900 CHECK( IOService
, _service
, service
);
2902 *state
= service
->getState();
2903 *busy_state
= service
->getBusyState();
2904 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
2906 return( kIOReturnSuccess
);
2909 /* Routine io_service_wait_quiet */
2910 kern_return_t
is_io_service_wait_quiet(
2911 io_object_t _service
,
2912 mach_timespec_t wait_time
)
2916 CHECK( IOService
, _service
, service
);
2918 timeoutNS
= wait_time
.tv_sec
;
2919 timeoutNS
*= kSecondScale
;
2920 timeoutNS
+= wait_time
.tv_nsec
;
2922 return( service
->waitQuiet(timeoutNS
) );
2925 /* Routine io_service_request_probe */
2926 kern_return_t
is_io_service_request_probe(
2927 io_object_t _service
,
2930 CHECK( IOService
, _service
, service
);
2932 return( service
->requestProbe( options
));
2935 /* Routine io_service_get_authorization_id */
2936 kern_return_t
is_io_service_get_authorization_id(
2937 io_object_t _service
,
2938 uint64_t *authorization_id
)
2942 CHECK( IOService
, _service
, service
);
2944 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
2945 kIOClientPrivilegeAdministrator
);
2946 if( kIOReturnSuccess
!= kr
)
2949 *authorization_id
= service
->getAuthorizationID();
2954 /* Routine io_service_set_authorization_id */
2955 kern_return_t
is_io_service_set_authorization_id(
2956 io_object_t _service
,
2957 uint64_t authorization_id
)
2959 CHECK( IOService
, _service
, service
);
2961 return( service
->setAuthorizationID( authorization_id
) );
2964 /* Routine io_service_open_ndr */
2965 kern_return_t
is_io_service_open_extended(
2966 io_object_t _service
,
2968 uint32_t connect_type
,
2970 io_buf_ptr_t properties
,
2971 mach_msg_type_number_t propertiesCnt
,
2972 kern_return_t
* result
,
2973 io_object_t
*connection
)
2975 IOUserClient
* client
= 0;
2976 kern_return_t err
= KERN_SUCCESS
;
2977 IOReturn res
= kIOReturnSuccess
;
2978 OSDictionary
* propertiesDict
= 0;
2980 bool disallowAccess
;
2982 CHECK( IOService
, _service
, service
);
2990 vm_map_offset_t map_data
;
2992 if( propertiesCnt
> sizeof(io_struct_inband_t
))
2993 return( kIOReturnMessageTooLarge
);
2995 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2997 data
= CAST_DOWN(vm_offset_t
, map_data
);
2998 if (KERN_SUCCESS
== err
)
3000 // must return success after vm_map_copyout() succeeds
3001 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3002 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3003 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3004 if (!propertiesDict
)
3006 res
= kIOReturnBadArgument
;
3011 if (kIOReturnSuccess
!= res
)
3015 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3018 if (!propertiesDict
)
3019 propertiesDict
= OSDictionary::withCapacity(4);
3020 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3024 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3029 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3030 connect_type
, propertiesDict
, &client
);
3033 propertiesDict
->release();
3035 if (res
== kIOReturnSuccess
)
3037 assert( OSDynamicCast(IOUserClient
, client
) );
3039 disallowAccess
= (crossEndian
3040 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3041 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3042 if (disallowAccess
) res
= kIOReturnUnsupported
;
3044 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3045 res
= kIOReturnNotPermitted
;
3047 if (kIOReturnSuccess
!= res
)
3049 IOStatisticsClientCall();
3050 client
->clientClose();
3055 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3056 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3059 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3060 creatorName
->release();
3062 client
->setTerminateDefer(service
, false);
3067 *connection
= client
;
3073 /* Routine io_service_close */
3074 kern_return_t
is_io_service_close(
3075 io_object_t connection
)
3078 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3079 return( kIOReturnSuccess
);
3081 CHECK( IOUserClient
, connection
, client
);
3083 IOStatisticsClientCall();
3084 client
->clientClose();
3086 return( kIOReturnSuccess
);
3089 /* Routine io_connect_get_service */
3090 kern_return_t
is_io_connect_get_service(
3091 io_object_t connection
,
3092 io_object_t
*service
)
3094 IOService
* theService
;
3096 CHECK( IOUserClient
, connection
, client
);
3098 theService
= client
->getService();
3100 theService
->retain();
3102 *service
= theService
;
3104 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3107 /* Routine io_connect_set_notification_port */
3108 kern_return_t
is_io_connect_set_notification_port(
3109 io_object_t connection
,
3110 uint32_t notification_type
,
3114 CHECK( IOUserClient
, connection
, client
);
3116 IOStatisticsClientCall();
3117 return( client
->registerNotificationPort( port
, notification_type
,
3118 (io_user_reference_t
) reference
));
3121 /* Routine io_connect_set_notification_port */
3122 kern_return_t
is_io_connect_set_notification_port_64(
3123 io_object_t connection
,
3124 uint32_t notification_type
,
3126 io_user_reference_t reference
)
3128 CHECK( IOUserClient
, connection
, client
);
3130 IOStatisticsClientCall();
3131 return( client
->registerNotificationPort( port
, notification_type
,
3135 /* Routine io_connect_map_memory_into_task */
3136 kern_return_t is_io_connect_map_memory_into_task
3138 io_connect_t connection
,
3139 uint32_t memory_type
,
3141 mach_vm_address_t
*address
,
3142 mach_vm_size_t
*size
,
3149 CHECK( IOUserClient
, connection
, client
);
3151 IOStatisticsClientCall();
3152 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3155 *address
= map
->getAddress();
3157 *size
= map
->getSize();
3159 if( client
->sharedInstance
3160 || (into_task
!= current_task())) {
3161 // push a name out to the task owning the map,
3162 // so we can clean up maps
3163 mach_port_name_t name __unused
=
3164 IOMachPort::makeSendRightForTask(
3165 into_task
, map
, IKOT_IOKIT_OBJECT
);
3168 // keep it with the user client
3169 IOLockLock( gIOObjectPortLock
);
3170 if( 0 == client
->mappings
)
3171 client
->mappings
= OSSet::withCapacity(2);
3172 if( client
->mappings
)
3173 client
->mappings
->setObject( map
);
3174 IOLockUnlock( gIOObjectPortLock
);
3177 err
= kIOReturnSuccess
;
3180 err
= kIOReturnBadArgument
;
3185 /* Routine is_io_connect_map_memory */
3186 kern_return_t
is_io_connect_map_memory(
3187 io_object_t connect
,
3195 mach_vm_address_t address
;
3196 mach_vm_size_t size
;
3198 address
= SCALAR64(*mapAddr
);
3199 size
= SCALAR64(*mapSize
);
3201 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3203 *mapAddr
= SCALAR32(address
);
3204 *mapSize
= SCALAR32(size
);
3211 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3214 IOMemoryMap
* map
= 0;
3216 IOLockLock(gIOObjectPortLock
);
3218 iter
= OSCollectionIterator::withCollection(mappings
);
3221 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3223 if(mem
== map
->getMemoryDescriptor())
3226 mappings
->removeObject(map
);
3233 IOLockUnlock(gIOObjectPortLock
);
3240 /* Routine io_connect_unmap_memory_from_task */
3241 kern_return_t is_io_connect_unmap_memory_from_task
3243 io_connect_t connection
,
3244 uint32_t memory_type
,
3246 mach_vm_address_t address
)
3249 IOOptionBits options
= 0;
3250 IOMemoryDescriptor
* memory
;
3253 CHECK( IOUserClient
, connection
, client
);
3255 IOStatisticsClientCall();
3256 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3258 if( memory
&& (kIOReturnSuccess
== err
)) {
3260 options
= (options
& ~kIOMapUserOptionsMask
)
3261 | kIOMapAnywhere
| kIOMapReference
;
3263 map
= memory
->createMappingInTask( from_task
, address
, options
);
3267 IOLockLock( gIOObjectPortLock
);
3268 if( client
->mappings
)
3269 client
->mappings
->removeObject( map
);
3270 IOLockUnlock( gIOObjectPortLock
);
3272 mach_port_name_t name
= 0;
3273 if (from_task
!= current_task())
3274 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3277 map
->userClientUnmap();
3278 err
= iokit_mod_send_right( from_task
, name
, -2 );
3279 err
= kIOReturnSuccess
;
3282 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3283 if (from_task
== current_task())
3287 err
= kIOReturnBadArgument
;
3293 kern_return_t
is_io_connect_unmap_memory(
3294 io_object_t connect
,
3300 mach_vm_address_t address
;
3302 address
= SCALAR64(mapAddr
);
3304 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3310 /* Routine io_connect_add_client */
3311 kern_return_t
is_io_connect_add_client(
3312 io_object_t connection
,
3313 io_object_t connect_to
)
3315 CHECK( IOUserClient
, connection
, client
);
3316 CHECK( IOUserClient
, connect_to
, to
);
3318 IOStatisticsClientCall();
3319 return( client
->connectClient( to
) );
3323 /* Routine io_connect_set_properties */
3324 kern_return_t
is_io_connect_set_properties(
3325 io_object_t connection
,
3326 io_buf_ptr_t properties
,
3327 mach_msg_type_number_t propertiesCnt
,
3328 kern_return_t
* result
)
3330 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3333 /* Routine io_user_client_method */
3334 kern_return_t is_io_connect_method_var_output
3336 io_connect_t connection
,
3338 io_scalar_inband64_t scalar_input
,
3339 mach_msg_type_number_t scalar_inputCnt
,
3340 io_struct_inband_t inband_input
,
3341 mach_msg_type_number_t inband_inputCnt
,
3342 mach_vm_address_t ool_input
,
3343 mach_vm_size_t ool_input_size
,
3344 io_struct_inband_t inband_output
,
3345 mach_msg_type_number_t
*inband_outputCnt
,
3346 io_scalar_inband64_t scalar_output
,
3347 mach_msg_type_number_t
*scalar_outputCnt
,
3348 io_buf_ptr_t
*var_output
,
3349 mach_msg_type_number_t
*var_outputCnt
3352 CHECK( IOUserClient
, connection
, client
);
3354 IOExternalMethodArguments args
;
3356 IOMemoryDescriptor
* inputMD
= 0;
3357 OSObject
* structureVariableOutputData
= 0;
3359 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3360 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3362 args
.selector
= selector
;
3364 args
.asyncWakePort
= MACH_PORT_NULL
;
3365 args
.asyncReference
= 0;
3366 args
.asyncReferenceCount
= 0;
3367 args
.structureVariableOutputData
= &structureVariableOutputData
;
3369 args
.scalarInput
= scalar_input
;
3370 args
.scalarInputCount
= scalar_inputCnt
;
3371 args
.structureInput
= inband_input
;
3372 args
.structureInputSize
= inband_inputCnt
;
3375 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3376 kIODirectionOut
, current_task());
3378 args
.structureInputDescriptor
= inputMD
;
3380 args
.scalarOutput
= scalar_output
;
3381 args
.scalarOutputCount
= *scalar_outputCnt
;
3382 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3383 args
.structureOutput
= inband_output
;
3384 args
.structureOutputSize
= *inband_outputCnt
;
3385 args
.structureOutputDescriptor
= NULL
;
3386 args
.structureOutputDescriptorSize
= 0;
3388 IOStatisticsClientCall();
3389 ret
= client
->externalMethod( selector
, &args
);
3391 *scalar_outputCnt
= args
.scalarOutputCount
;
3392 *inband_outputCnt
= args
.structureOutputSize
;
3394 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3396 OSSerialize
* serialize
;
3400 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3402 len
= serialize
->getLength();
3403 *var_outputCnt
= len
;
3404 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3406 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3408 len
= data
->getLength();
3409 *var_outputCnt
= len
;
3410 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3414 ret
= kIOReturnUnderrun
;
3420 if (structureVariableOutputData
)
3421 structureVariableOutputData
->release();
3426 /* Routine io_user_client_method */
3427 kern_return_t is_io_connect_method
3429 io_connect_t connection
,
3431 io_scalar_inband64_t scalar_input
,
3432 mach_msg_type_number_t scalar_inputCnt
,
3433 io_struct_inband_t inband_input
,
3434 mach_msg_type_number_t inband_inputCnt
,
3435 mach_vm_address_t ool_input
,
3436 mach_vm_size_t ool_input_size
,
3437 io_struct_inband_t inband_output
,
3438 mach_msg_type_number_t
*inband_outputCnt
,
3439 io_scalar_inband64_t scalar_output
,
3440 mach_msg_type_number_t
*scalar_outputCnt
,
3441 mach_vm_address_t ool_output
,
3442 mach_vm_size_t
*ool_output_size
3445 CHECK( IOUserClient
, connection
, client
);
3447 IOExternalMethodArguments args
;
3449 IOMemoryDescriptor
* inputMD
= 0;
3450 IOMemoryDescriptor
* outputMD
= 0;
3452 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3453 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3455 args
.selector
= selector
;
3457 args
.asyncWakePort
= MACH_PORT_NULL
;
3458 args
.asyncReference
= 0;
3459 args
.asyncReferenceCount
= 0;
3460 args
.structureVariableOutputData
= 0;
3462 args
.scalarInput
= scalar_input
;
3463 args
.scalarInputCount
= scalar_inputCnt
;
3464 args
.structureInput
= inband_input
;
3465 args
.structureInputSize
= inband_inputCnt
;
3468 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3469 kIODirectionOut
, current_task());
3471 args
.structureInputDescriptor
= inputMD
;
3473 args
.scalarOutput
= scalar_output
;
3474 args
.scalarOutputCount
= *scalar_outputCnt
;
3475 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3476 args
.structureOutput
= inband_output
;
3477 args
.structureOutputSize
= *inband_outputCnt
;
3479 if (ool_output
&& ool_output_size
)
3481 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3482 kIODirectionIn
, current_task());
3485 args
.structureOutputDescriptor
= outputMD
;
3486 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3488 IOStatisticsClientCall();
3489 ret
= client
->externalMethod( selector
, &args
);
3491 *scalar_outputCnt
= args
.scalarOutputCount
;
3492 *inband_outputCnt
= args
.structureOutputSize
;
3493 *ool_output_size
= args
.structureOutputDescriptorSize
;
3498 outputMD
->release();
3503 /* Routine io_async_user_client_method */
3504 kern_return_t is_io_connect_async_method
3506 io_connect_t connection
,
3507 mach_port_t wake_port
,
3508 io_async_ref64_t reference
,
3509 mach_msg_type_number_t referenceCnt
,
3511 io_scalar_inband64_t scalar_input
,
3512 mach_msg_type_number_t scalar_inputCnt
,
3513 io_struct_inband_t inband_input
,
3514 mach_msg_type_number_t inband_inputCnt
,
3515 mach_vm_address_t ool_input
,
3516 mach_vm_size_t ool_input_size
,
3517 io_struct_inband_t inband_output
,
3518 mach_msg_type_number_t
*inband_outputCnt
,
3519 io_scalar_inband64_t scalar_output
,
3520 mach_msg_type_number_t
*scalar_outputCnt
,
3521 mach_vm_address_t ool_output
,
3522 mach_vm_size_t
* ool_output_size
3525 CHECK( IOUserClient
, connection
, client
);
3527 IOExternalMethodArguments args
;
3529 IOMemoryDescriptor
* inputMD
= 0;
3530 IOMemoryDescriptor
* outputMD
= 0;
3532 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3533 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3535 reference
[0] = (io_user_reference_t
) wake_port
;
3536 if (vm_map_is_64bit(get_task_map(current_task())))
3537 reference
[0] |= kIOUCAsync64Flag
;
3539 args
.selector
= selector
;
3541 args
.asyncWakePort
= wake_port
;
3542 args
.asyncReference
= reference
;
3543 args
.asyncReferenceCount
= referenceCnt
;
3545 args
.scalarInput
= scalar_input
;
3546 args
.scalarInputCount
= scalar_inputCnt
;
3547 args
.structureInput
= inband_input
;
3548 args
.structureInputSize
= inband_inputCnt
;
3551 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3552 kIODirectionOut
, current_task());
3554 args
.structureInputDescriptor
= inputMD
;
3556 args
.scalarOutput
= scalar_output
;
3557 args
.scalarOutputCount
= *scalar_outputCnt
;
3558 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3559 args
.structureOutput
= inband_output
;
3560 args
.structureOutputSize
= *inband_outputCnt
;
3564 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3565 kIODirectionIn
, current_task());
3568 args
.structureOutputDescriptor
= outputMD
;
3569 args
.structureOutputDescriptorSize
= *ool_output_size
;
3571 IOStatisticsClientCall();
3572 ret
= client
->externalMethod( selector
, &args
);
3574 *inband_outputCnt
= args
.structureOutputSize
;
3575 *ool_output_size
= args
.structureOutputDescriptorSize
;
3580 outputMD
->release();
3585 /* Routine io_connect_method_scalarI_scalarO */
3586 kern_return_t
is_io_connect_method_scalarI_scalarO(
3587 io_object_t connect
,
3589 io_scalar_inband_t input
,
3590 mach_msg_type_number_t inputCount
,
3591 io_scalar_inband_t output
,
3592 mach_msg_type_number_t
* outputCount
)
3596 io_scalar_inband64_t _input
;
3597 io_scalar_inband64_t _output
;
3599 mach_msg_type_number_t struct_outputCnt
= 0;
3600 mach_vm_size_t ool_output_size
= 0;
3602 bzero(&_output
[0], sizeof(_output
));
3603 for (i
= 0; i
< inputCount
; i
++)
3604 _input
[i
] = SCALAR64(input
[i
]);
3606 err
= is_io_connect_method(connect
, index
,
3610 NULL
, &struct_outputCnt
,
3611 _output
, outputCount
,
3612 0, &ool_output_size
);
3614 for (i
= 0; i
< *outputCount
; i
++)
3615 output
[i
] = SCALAR32(_output
[i
]);
3620 kern_return_t
shim_io_connect_method_scalarI_scalarO(
3621 IOExternalMethod
* method
,
3623 const io_user_scalar_t
* input
,
3624 mach_msg_type_number_t inputCount
,
3625 io_user_scalar_t
* output
,
3626 mach_msg_type_number_t
* outputCount
)
3629 io_scalar_inband_t _output
;
3631 err
= kIOReturnBadArgument
;
3633 bzero(&_output
[0], sizeof(_output
));
3636 if( inputCount
!= method
->count0
)
3638 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3641 if( *outputCount
!= method
->count1
)
3643 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3647 func
= method
->func
;
3649 switch( inputCount
) {
3652 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3653 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3656 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3657 ARG32(input
[3]), ARG32(input
[4]),
3661 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3663 &_output
[0], &_output
[1] );
3666 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3667 &_output
[0], &_output
[1], &_output
[2] );
3670 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3671 &_output
[0], &_output
[1], &_output
[2],
3675 err
= (object
->*func
)( ARG32(input
[0]),
3676 &_output
[0], &_output
[1], &_output
[2],
3677 &_output
[3], &_output
[4] );
3680 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
3681 &_output
[3], &_output
[4], &_output
[5] );
3685 IOLog("%s: Bad method table\n", object
->getName());
3691 for (i
= 0; i
< *outputCount
; i
++)
3692 output
[i
] = SCALAR32(_output
[i
]);
3697 /* Routine io_async_method_scalarI_scalarO */
3698 kern_return_t
is_io_async_method_scalarI_scalarO(
3699 io_object_t connect
,
3700 mach_port_t wake_port
,
3701 io_async_ref_t reference
,
3702 mach_msg_type_number_t referenceCnt
,
3704 io_scalar_inband_t input
,
3705 mach_msg_type_number_t inputCount
,
3706 io_scalar_inband_t output
,
3707 mach_msg_type_number_t
* outputCount
)
3711 io_scalar_inband64_t _input
;
3712 io_scalar_inband64_t _output
;
3713 io_async_ref64_t _reference
;
3715 bzero(&_output
[0], sizeof(_output
));
3716 for (i
= 0; i
< referenceCnt
; i
++)
3717 _reference
[i
] = REF64(reference
[i
]);
3719 mach_msg_type_number_t struct_outputCnt
= 0;
3720 mach_vm_size_t ool_output_size
= 0;
3722 for (i
= 0; i
< inputCount
; i
++)
3723 _input
[i
] = SCALAR64(input
[i
]);
3725 err
= is_io_connect_async_method(connect
,
3726 wake_port
, _reference
, referenceCnt
,
3731 NULL
, &struct_outputCnt
,
3732 _output
, outputCount
,
3733 0, &ool_output_size
);
3735 for (i
= 0; i
< *outputCount
; i
++)
3736 output
[i
] = SCALAR32(_output
[i
]);
3740 /* Routine io_async_method_scalarI_structureO */
3741 kern_return_t
is_io_async_method_scalarI_structureO(
3742 io_object_t connect
,
3743 mach_port_t wake_port
,
3744 io_async_ref_t reference
,
3745 mach_msg_type_number_t referenceCnt
,
3747 io_scalar_inband_t input
,
3748 mach_msg_type_number_t inputCount
,
3749 io_struct_inband_t output
,
3750 mach_msg_type_number_t
* outputCount
)
3753 io_scalar_inband64_t _input
;
3754 io_async_ref64_t _reference
;
3756 for (i
= 0; i
< referenceCnt
; i
++)
3757 _reference
[i
] = REF64(reference
[i
]);
3759 mach_msg_type_number_t scalar_outputCnt
= 0;
3760 mach_vm_size_t ool_output_size
= 0;
3762 for (i
= 0; i
< inputCount
; i
++)
3763 _input
[i
] = SCALAR64(input
[i
]);
3765 return (is_io_connect_async_method(connect
,
3766 wake_port
, _reference
, referenceCnt
,
3771 output
, outputCount
,
3772 NULL
, &scalar_outputCnt
,
3773 0, &ool_output_size
));
3776 /* Routine io_async_method_scalarI_structureI */
3777 kern_return_t
is_io_async_method_scalarI_structureI(
3778 io_connect_t connect
,
3779 mach_port_t wake_port
,
3780 io_async_ref_t reference
,
3781 mach_msg_type_number_t referenceCnt
,
3783 io_scalar_inband_t input
,
3784 mach_msg_type_number_t inputCount
,
3785 io_struct_inband_t inputStruct
,
3786 mach_msg_type_number_t inputStructCount
)
3789 io_scalar_inband64_t _input
;
3790 io_async_ref64_t _reference
;
3792 for (i
= 0; i
< referenceCnt
; i
++)
3793 _reference
[i
] = REF64(reference
[i
]);
3795 mach_msg_type_number_t scalar_outputCnt
= 0;
3796 mach_msg_type_number_t inband_outputCnt
= 0;
3797 mach_vm_size_t ool_output_size
= 0;
3799 for (i
= 0; i
< inputCount
; i
++)
3800 _input
[i
] = SCALAR64(input
[i
]);
3802 return (is_io_connect_async_method(connect
,
3803 wake_port
, _reference
, referenceCnt
,
3806 inputStruct
, inputStructCount
,
3808 NULL
, &inband_outputCnt
,
3809 NULL
, &scalar_outputCnt
,
3810 0, &ool_output_size
));
3813 /* Routine io_async_method_structureI_structureO */
3814 kern_return_t
is_io_async_method_structureI_structureO(
3815 io_object_t connect
,
3816 mach_port_t wake_port
,
3817 io_async_ref_t reference
,
3818 mach_msg_type_number_t referenceCnt
,
3820 io_struct_inband_t input
,
3821 mach_msg_type_number_t inputCount
,
3822 io_struct_inband_t output
,
3823 mach_msg_type_number_t
* outputCount
)
3826 mach_msg_type_number_t scalar_outputCnt
= 0;
3827 mach_vm_size_t ool_output_size
= 0;
3828 io_async_ref64_t _reference
;
3830 for (i
= 0; i
< referenceCnt
; i
++)
3831 _reference
[i
] = REF64(reference
[i
]);
3833 return (is_io_connect_async_method(connect
,
3834 wake_port
, _reference
, referenceCnt
,
3839 output
, outputCount
,
3840 NULL
, &scalar_outputCnt
,
3841 0, &ool_output_size
));
3845 kern_return_t
shim_io_async_method_scalarI_scalarO(
3846 IOExternalAsyncMethod
* method
,
3848 mach_port_t asyncWakePort
,
3849 io_user_reference_t
* asyncReference
,
3850 uint32_t asyncReferenceCount
,
3851 const io_user_scalar_t
* input
,
3852 mach_msg_type_number_t inputCount
,
3853 io_user_scalar_t
* output
,
3854 mach_msg_type_number_t
* outputCount
)
3858 io_scalar_inband_t _output
;
3860 io_async_ref_t reference
;
3862 bzero(&_output
[0], sizeof(_output
));
3863 for (i
= 0; i
< asyncReferenceCount
; i
++)
3864 reference
[i
] = REF32(asyncReference
[i
]);
3866 err
= kIOReturnBadArgument
;
3870 if( inputCount
!= method
->count0
)
3872 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3875 if( *outputCount
!= method
->count1
)
3877 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3881 func
= method
->func
;
3883 switch( inputCount
) {
3886 err
= (object
->*func
)( reference
,
3887 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3888 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3891 err
= (object
->*func
)( reference
,
3892 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3893 ARG32(input
[3]), ARG32(input
[4]),
3897 err
= (object
->*func
)( reference
,
3898 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3900 &_output
[0], &_output
[1] );
3903 err
= (object
->*func
)( reference
,
3904 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3905 &_output
[0], &_output
[1], &_output
[2] );
3908 err
= (object
->*func
)( reference
,
3909 ARG32(input
[0]), ARG32(input
[1]),
3910 &_output
[0], &_output
[1], &_output
[2],
3914 err
= (object
->*func
)( reference
,
3916 &_output
[0], &_output
[1], &_output
[2],
3917 &_output
[3], &_output
[4] );
3920 err
= (object
->*func
)( reference
,
3921 &_output
[0], &_output
[1], &_output
[2],
3922 &_output
[3], &_output
[4], &_output
[5] );
3926 IOLog("%s: Bad method table\n", object
->getName());
3931 for (i
= 0; i
< *outputCount
; i
++)
3932 output
[i
] = SCALAR32(_output
[i
]);
3938 /* Routine io_connect_method_scalarI_structureO */
3939 kern_return_t
is_io_connect_method_scalarI_structureO(
3940 io_object_t connect
,
3942 io_scalar_inband_t input
,
3943 mach_msg_type_number_t inputCount
,
3944 io_struct_inband_t output
,
3945 mach_msg_type_number_t
* outputCount
)
3948 io_scalar_inband64_t _input
;
3950 mach_msg_type_number_t scalar_outputCnt
= 0;
3951 mach_vm_size_t ool_output_size
= 0;
3953 for (i
= 0; i
< inputCount
; i
++)
3954 _input
[i
] = SCALAR64(input
[i
]);
3956 return (is_io_connect_method(connect
, index
,
3960 output
, outputCount
,
3961 NULL
, &scalar_outputCnt
,
3962 0, &ool_output_size
));
3965 kern_return_t
shim_io_connect_method_scalarI_structureO(
3967 IOExternalMethod
* method
,
3969 const io_user_scalar_t
* input
,
3970 mach_msg_type_number_t inputCount
,
3971 io_struct_inband_t output
,
3972 IOByteCount
* outputCount
)
3977 err
= kIOReturnBadArgument
;
3980 if( inputCount
!= method
->count0
)
3982 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3985 if( (kIOUCVariableStructureSize
!= method
->count1
)
3986 && (*outputCount
!= method
->count1
))
3988 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3992 func
= method
->func
;
3994 switch( inputCount
) {
3997 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3998 ARG32(input
[3]), ARG32(input
[4]),
4002 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4004 output
, (void *)outputCount
);
4007 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4008 output
, (void *)outputCount
, 0 );
4011 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4012 output
, (void *)outputCount
, 0, 0 );
4015 err
= (object
->*func
)( ARG32(input
[0]),
4016 output
, (void *)outputCount
, 0, 0, 0 );
4019 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4023 IOLog("%s: Bad method table\n", object
->getName());
4032 kern_return_t
shim_io_async_method_scalarI_structureO(
4033 IOExternalAsyncMethod
* method
,
4035 mach_port_t asyncWakePort
,
4036 io_user_reference_t
* asyncReference
,
4037 uint32_t asyncReferenceCount
,
4038 const io_user_scalar_t
* input
,
4039 mach_msg_type_number_t inputCount
,
4040 io_struct_inband_t output
,
4041 mach_msg_type_number_t
* outputCount
)
4046 io_async_ref_t reference
;
4048 for (i
= 0; i
< asyncReferenceCount
; i
++)
4049 reference
[i
] = REF32(asyncReference
[i
]);
4051 err
= kIOReturnBadArgument
;
4053 if( inputCount
!= method
->count0
)
4055 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4058 if( (kIOUCVariableStructureSize
!= method
->count1
)
4059 && (*outputCount
!= method
->count1
))
4061 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4065 func
= method
->func
;
4067 switch( inputCount
) {
4070 err
= (object
->*func
)( reference
,
4071 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4072 ARG32(input
[3]), ARG32(input
[4]),
4076 err
= (object
->*func
)( reference
,
4077 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4079 output
, (void *)outputCount
);
4082 err
= (object
->*func
)( reference
,
4083 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4084 output
, (void *)outputCount
, 0 );
4087 err
= (object
->*func
)( reference
,
4088 ARG32(input
[0]), ARG32(input
[1]),
4089 output
, (void *)outputCount
, 0, 0 );
4092 err
= (object
->*func
)( reference
,
4094 output
, (void *)outputCount
, 0, 0, 0 );
4097 err
= (object
->*func
)( reference
,
4098 output
, (void *)outputCount
, 0, 0, 0, 0 );
4102 IOLog("%s: Bad method table\n", object
->getName());
4110 /* Routine io_connect_method_scalarI_structureI */
4111 kern_return_t
is_io_connect_method_scalarI_structureI(
4112 io_connect_t connect
,
4114 io_scalar_inband_t input
,
4115 mach_msg_type_number_t inputCount
,
4116 io_struct_inband_t inputStruct
,
4117 mach_msg_type_number_t inputStructCount
)
4120 io_scalar_inband64_t _input
;
4122 mach_msg_type_number_t scalar_outputCnt
= 0;
4123 mach_msg_type_number_t inband_outputCnt
= 0;
4124 mach_vm_size_t ool_output_size
= 0;
4126 for (i
= 0; i
< inputCount
; i
++)
4127 _input
[i
] = SCALAR64(input
[i
]);
4129 return (is_io_connect_method(connect
, index
,
4131 inputStruct
, inputStructCount
,
4133 NULL
, &inband_outputCnt
,
4134 NULL
, &scalar_outputCnt
,
4135 0, &ool_output_size
));
4138 kern_return_t
shim_io_connect_method_scalarI_structureI(
4139 IOExternalMethod
* method
,
4141 const io_user_scalar_t
* input
,
4142 mach_msg_type_number_t inputCount
,
4143 io_struct_inband_t inputStruct
,
4144 mach_msg_type_number_t inputStructCount
)
4147 IOReturn err
= kIOReturnBadArgument
;
4151 if( (kIOUCVariableStructureSize
!= method
->count0
)
4152 && (inputCount
!= method
->count0
))
4154 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4157 if( (kIOUCVariableStructureSize
!= method
->count1
)
4158 && (inputStructCount
!= method
->count1
))
4160 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4164 func
= method
->func
;
4166 switch( inputCount
) {
4169 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4170 ARG32(input
[3]), ARG32(input
[4]),
4174 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4176 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4179 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4180 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4184 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4185 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4189 err
= (object
->*func
)( ARG32(input
[0]),
4190 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4194 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4199 IOLog("%s: Bad method table\n", object
->getName());
4207 kern_return_t
shim_io_async_method_scalarI_structureI(
4208 IOExternalAsyncMethod
* method
,
4210 mach_port_t asyncWakePort
,
4211 io_user_reference_t
* asyncReference
,
4212 uint32_t asyncReferenceCount
,
4213 const io_user_scalar_t
* input
,
4214 mach_msg_type_number_t inputCount
,
4215 io_struct_inband_t inputStruct
,
4216 mach_msg_type_number_t inputStructCount
)
4220 IOReturn err
= kIOReturnBadArgument
;
4221 io_async_ref_t reference
;
4223 for (i
= 0; i
< asyncReferenceCount
; i
++)
4224 reference
[i
] = REF32(asyncReference
[i
]);
4228 if( (kIOUCVariableStructureSize
!= method
->count0
)
4229 && (inputCount
!= method
->count0
))
4231 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4234 if( (kIOUCVariableStructureSize
!= method
->count1
)
4235 && (inputStructCount
!= method
->count1
))
4237 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4241 func
= method
->func
;
4243 switch( inputCount
) {
4246 err
= (object
->*func
)( reference
,
4247 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4248 ARG32(input
[3]), ARG32(input
[4]),
4252 err
= (object
->*func
)( reference
,
4253 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4255 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4258 err
= (object
->*func
)( reference
,
4259 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4260 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4264 err
= (object
->*func
)( reference
,
4265 ARG32(input
[0]), ARG32(input
[1]),
4266 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4270 err
= (object
->*func
)( reference
,
4272 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4276 err
= (object
->*func
)( reference
,
4277 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4282 IOLog("%s: Bad method table\n", object
->getName());
4290 /* Routine io_connect_method_structureI_structureO */
4291 kern_return_t
is_io_connect_method_structureI_structureO(
4292 io_object_t connect
,
4294 io_struct_inband_t input
,
4295 mach_msg_type_number_t inputCount
,
4296 io_struct_inband_t output
,
4297 mach_msg_type_number_t
* outputCount
)
4299 mach_msg_type_number_t scalar_outputCnt
= 0;
4300 mach_vm_size_t ool_output_size
= 0;
4302 return (is_io_connect_method(connect
, index
,
4306 output
, outputCount
,
4307 NULL
, &scalar_outputCnt
,
4308 0, &ool_output_size
));
4311 kern_return_t
shim_io_connect_method_structureI_structureO(
4312 IOExternalMethod
* method
,
4314 io_struct_inband_t input
,
4315 mach_msg_type_number_t inputCount
,
4316 io_struct_inband_t output
,
4317 IOByteCount
* outputCount
)
4320 IOReturn err
= kIOReturnBadArgument
;
4324 if( (kIOUCVariableStructureSize
!= method
->count0
)
4325 && (inputCount
!= method
->count0
))
4327 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4330 if( (kIOUCVariableStructureSize
!= method
->count1
)
4331 && (*outputCount
!= method
->count1
))
4333 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4337 func
= method
->func
;
4339 if( method
->count1
) {
4340 if( method
->count0
) {
4341 err
= (object
->*func
)( input
, output
,
4342 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4344 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4347 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4356 kern_return_t
shim_io_async_method_structureI_structureO(
4357 IOExternalAsyncMethod
* method
,
4359 mach_port_t asyncWakePort
,
4360 io_user_reference_t
* asyncReference
,
4361 uint32_t asyncReferenceCount
,
4362 io_struct_inband_t input
,
4363 mach_msg_type_number_t inputCount
,
4364 io_struct_inband_t output
,
4365 mach_msg_type_number_t
* outputCount
)
4370 io_async_ref_t reference
;
4372 for (i
= 0; i
< asyncReferenceCount
; i
++)
4373 reference
[i
] = REF32(asyncReference
[i
]);
4375 err
= kIOReturnBadArgument
;
4378 if( (kIOUCVariableStructureSize
!= method
->count0
)
4379 && (inputCount
!= method
->count0
))
4381 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4384 if( (kIOUCVariableStructureSize
!= method
->count1
)
4385 && (*outputCount
!= method
->count1
))
4387 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4391 func
= method
->func
;
4393 if( method
->count1
) {
4394 if( method
->count0
) {
4395 err
= (object
->*func
)( reference
,
4397 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4399 err
= (object
->*func
)( reference
,
4400 output
, outputCount
, 0, 0, 0, 0 );
4403 err
= (object
->*func
)( reference
,
4404 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4412 /* Routine io_catalog_send_data */
4413 kern_return_t
is_io_catalog_send_data(
4414 mach_port_t master_port
,
4416 io_buf_ptr_t inData
,
4417 mach_msg_type_number_t inDataCount
,
4418 kern_return_t
* result
)
4422 kern_return_t kr
= kIOReturnError
;
4424 //printf("io_catalog_send_data called. flag: %d\n", flag);
4426 if( master_port
!= master_device_port
)
4427 return kIOReturnNotPrivileged
;
4429 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4430 flag
!= kIOCatalogKextdActive
&&
4431 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4432 ( !inData
|| !inDataCount
) )
4434 return kIOReturnBadArgument
;
4438 vm_map_offset_t map_data
;
4440 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4441 return( kIOReturnMessageTooLarge
);
4443 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4444 data
= CAST_DOWN(vm_offset_t
, map_data
);
4446 if( kr
!= KERN_SUCCESS
)
4449 // must return success after vm_map_copyout() succeeds
4452 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4453 vm_deallocate( kernel_map
, data
, inDataCount
);
4455 *result
= kIOReturnNoMemory
;
4456 return( KERN_SUCCESS
);
4462 case kIOCatalogResetDrivers
:
4463 case kIOCatalogResetDriversNoMatch
: {
4466 array
= OSDynamicCast(OSArray
, obj
);
4468 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4469 flag
== kIOCatalogResetDrivers
) ) {
4471 kr
= kIOReturnError
;
4474 kr
= kIOReturnBadArgument
;
4479 case kIOCatalogAddDrivers
:
4480 case kIOCatalogAddDriversNoMatch
: {
4483 array
= OSDynamicCast(OSArray
, obj
);
4485 if ( !gIOCatalogue
->addDrivers( array
,
4486 flag
== kIOCatalogAddDrivers
) ) {
4487 kr
= kIOReturnError
;
4491 kr
= kIOReturnBadArgument
;
4496 case kIOCatalogRemoveDrivers
:
4497 case kIOCatalogRemoveDriversNoMatch
: {
4498 OSDictionary
* dict
;
4500 dict
= OSDynamicCast(OSDictionary
, obj
);
4502 if ( !gIOCatalogue
->removeDrivers( dict
,
4503 flag
== kIOCatalogRemoveDrivers
) ) {
4504 kr
= kIOReturnError
;
4508 kr
= kIOReturnBadArgument
;
4513 case kIOCatalogStartMatching
: {
4514 OSDictionary
* dict
;
4516 dict
= OSDynamicCast(OSDictionary
, obj
);
4518 if ( !gIOCatalogue
->startMatching( dict
) ) {
4519 kr
= kIOReturnError
;
4523 kr
= kIOReturnBadArgument
;
4528 case kIOCatalogRemoveKernelLinker
:
4529 kr
= KERN_NOT_SUPPORTED
;
4532 case kIOCatalogKextdActive
:
4534 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
4535 OSKext::setKextdActive();
4537 /* Dump all nonloaded startup extensions; kextd will now send them
4540 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4542 kr
= kIOReturnSuccess
;
4545 case kIOCatalogKextdFinishedLaunching
: {
4547 static bool clearedBusy
= false;
4550 IOService
* serviceRoot
= IOService::getServiceRoot();
4552 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
4553 serviceRoot
->adjustBusy(-1);
4558 kr
= kIOReturnSuccess
;
4563 kr
= kIOReturnBadArgument
;
4567 if (obj
) obj
->release();
4570 return( KERN_SUCCESS
);
4573 /* Routine io_catalog_terminate */
4574 kern_return_t
is_io_catalog_terminate(
4575 mach_port_t master_port
,
4581 if( master_port
!= master_device_port
)
4582 return kIOReturnNotPrivileged
;
4584 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
4585 kIOClientPrivilegeAdministrator
);
4586 if( kIOReturnSuccess
!= kr
)
4590 #if !defined(SECURE_KERNEL)
4591 case kIOCatalogServiceTerminate
:
4593 IOService
* service
;
4595 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
4596 kIORegistryIterateRecursively
);
4598 return kIOReturnNoMemory
;
4602 while( (service
= (IOService
*)iter
->getNextObject()) ) {
4603 if( service
->metaCast(name
)) {
4604 if ( !service
->terminate( kIOServiceRequired
4605 | kIOServiceSynchronous
) ) {
4606 kr
= kIOReturnUnsupported
;
4611 } while( !service
&& !iter
->isValid());
4615 case kIOCatalogModuleUnload
:
4616 case kIOCatalogModuleTerminate
:
4617 kr
= gIOCatalogue
->terminateDriversForModule(name
,
4618 flag
== kIOCatalogModuleUnload
);
4623 kr
= kIOReturnBadArgument
;
4630 /* Routine io_catalog_get_data */
4631 kern_return_t
is_io_catalog_get_data(
4632 mach_port_t master_port
,
4634 io_buf_ptr_t
*outData
,
4635 mach_msg_type_number_t
*outDataCount
)
4637 kern_return_t kr
= kIOReturnSuccess
;
4640 if( master_port
!= master_device_port
)
4641 return kIOReturnNotPrivileged
;
4643 //printf("io_catalog_get_data called. flag: %d\n", flag);
4645 s
= OSSerialize::withCapacity(4096);
4647 return kIOReturnNoMemory
;
4649 kr
= gIOCatalogue
->serializeData(flag
, s
);
4651 if ( kr
== kIOReturnSuccess
) {
4656 size
= s
->getLength();
4657 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
4658 if ( kr
== kIOReturnSuccess
) {
4659 bcopy(s
->text(), (void *)data
, size
);
4660 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
4661 (vm_map_size_t
)size
, true, ©
);
4662 *outData
= (char *)copy
;
4663 *outDataCount
= size
;
4672 /* Routine io_catalog_get_gen_count */
4673 kern_return_t
is_io_catalog_get_gen_count(
4674 mach_port_t master_port
,
4677 if( master_port
!= master_device_port
)
4678 return kIOReturnNotPrivileged
;
4680 //printf("io_catalog_get_gen_count called.\n");
4683 return kIOReturnBadArgument
;
4685 *genCount
= gIOCatalogue
->getGenerationCount();
4687 return kIOReturnSuccess
;
4690 /* Routine io_catalog_module_loaded.
4691 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
4693 kern_return_t
is_io_catalog_module_loaded(
4694 mach_port_t master_port
,
4697 if( master_port
!= master_device_port
)
4698 return kIOReturnNotPrivileged
;
4700 //printf("io_catalog_module_loaded called. name %s\n", name);
4703 return kIOReturnBadArgument
;
4705 gIOCatalogue
->moduleHasLoaded(name
);
4707 return kIOReturnSuccess
;
4710 kern_return_t
is_io_catalog_reset(
4711 mach_port_t master_port
,
4714 if( master_port
!= master_device_port
)
4715 return kIOReturnNotPrivileged
;
4718 case kIOCatalogResetDefault
:
4719 gIOCatalogue
->reset();
4723 return kIOReturnBadArgument
;
4726 return kIOReturnSuccess
;
4729 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
4731 kern_return_t result
= kIOReturnBadArgument
;
4732 IOUserClient
*userClient
;
4734 if ((userClient
= OSDynamicCast(IOUserClient
,
4735 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
4736 IOExternalTrap
*trap
;
4737 IOService
*target
= NULL
;
4739 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
4741 if (trap
&& target
) {
4747 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
4751 userClient
->release();
4759 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
4760 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
4764 IOByteCount structureOutputSize
;
4769 count
= dispatch
->checkScalarInputCount
;
4770 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
4772 return (kIOReturnBadArgument
);
4775 count
= dispatch
->checkStructureInputSize
;
4776 if ((kIOUCVariableStructureSize
!= count
)
4777 && (count
!= ((args
->structureInputDescriptor
)
4778 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
4780 return (kIOReturnBadArgument
);
4783 count
= dispatch
->checkScalarOutputCount
;
4784 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
4786 return (kIOReturnBadArgument
);
4789 count
= dispatch
->checkStructureOutputSize
;
4790 if ((kIOUCVariableStructureSize
!= count
)
4791 && (count
!= ((args
->structureOutputDescriptor
)
4792 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
4794 return (kIOReturnBadArgument
);
4797 if (dispatch
->function
)
4798 err
= (*dispatch
->function
)(target
, reference
, args
);
4800 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
4806 // pre-Leopard API's don't do ool structs
4807 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
4809 err
= kIOReturnIPCError
;
4813 structureOutputSize
= args
->structureOutputSize
;
4815 if (args
->asyncWakePort
)
4817 IOExternalAsyncMethod
* method
;
4819 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) )
4820 return (kIOReturnUnsupported
);
4822 if (kIOUCForegroundOnly
& method
->flags
)
4824 if (task_is_gpu_denied(current_task()))
4825 return (kIOReturnNotPermitted
);
4828 switch (method
->flags
& kIOUCTypeMask
)
4830 case kIOUCScalarIStructI
:
4831 err
= shim_io_async_method_scalarI_structureI( method
, object
,
4832 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4833 args
->scalarInput
, args
->scalarInputCount
,
4834 (char *)args
->structureInput
, args
->structureInputSize
);
4837 case kIOUCScalarIScalarO
:
4838 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
4839 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4840 args
->scalarInput
, args
->scalarInputCount
,
4841 args
->scalarOutput
, &args
->scalarOutputCount
);
4844 case kIOUCScalarIStructO
:
4845 err
= shim_io_async_method_scalarI_structureO( method
, object
,
4846 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4847 args
->scalarInput
, args
->scalarInputCount
,
4848 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4852 case kIOUCStructIStructO
:
4853 err
= shim_io_async_method_structureI_structureO( method
, object
,
4854 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4855 (char *)args
->structureInput
, args
->structureInputSize
,
4856 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4860 err
= kIOReturnBadArgument
;
4866 IOExternalMethod
* method
;
4868 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) )
4869 return (kIOReturnUnsupported
);
4871 if (kIOUCForegroundOnly
& method
->flags
)
4873 if (task_is_gpu_denied(current_task()))
4874 return (kIOReturnNotPermitted
);
4877 switch (method
->flags
& kIOUCTypeMask
)
4879 case kIOUCScalarIStructI
:
4880 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
4881 args
->scalarInput
, args
->scalarInputCount
,
4882 (char *) args
->structureInput
, args
->structureInputSize
);
4885 case kIOUCScalarIScalarO
:
4886 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
4887 args
->scalarInput
, args
->scalarInputCount
,
4888 args
->scalarOutput
, &args
->scalarOutputCount
);
4891 case kIOUCScalarIStructO
:
4892 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
4893 args
->scalarInput
, args
->scalarInputCount
,
4894 (char *) args
->structureOutput
, &structureOutputSize
);
4898 case kIOUCStructIStructO
:
4899 err
= shim_io_connect_method_structureI_structureO( method
, object
,
4900 (char *) args
->structureInput
, args
->structureInputSize
,
4901 (char *) args
->structureOutput
, &structureOutputSize
);
4905 err
= kIOReturnBadArgument
;
4910 args
->structureOutputSize
= structureOutputSize
;
4917 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
4918 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
4920 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
4921 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
4923 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
4924 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
4925 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
4926 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
4927 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
4928 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
4929 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
4930 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
4931 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
4932 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
4933 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
4934 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
4935 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
4936 OSMetaClassDefineReservedUnused(IOUserClient
, 15);