2 * Copyright (c) 1998-2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <libkern/c++/OSKext.h>
31 #include <IOKit/IOKitServer.h>
32 #include <IOKit/IOKitKeysPrivate.h>
33 #include <IOKit/IOUserClient.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IORegistryEntry.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOMemoryDescriptor.h>
38 #include <IOKit/IOBufferMemoryDescriptor.h>
39 #include <IOKit/IOLib.h>
40 #include <IOKit/IOStatisticsPrivate.h>
41 #include <IOKit/IOTimeStamp.h>
42 #include <IOKit/system.h>
43 #include <libkern/OSDebug.h>
45 #include <sys/kauth.h>
46 #include <sys/codesign.h>
51 #include <security/mac_framework.h>
53 #include <sys/kauth.h>
57 #endif /* CONFIG_MACF */
59 #include <IOKit/assert.h>
61 #include "IOServicePrivate.h"
62 #include "IOKitKernelInternal.h"
64 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
65 #define SCALAR32(x) ((uint32_t )x)
66 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
67 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
68 #define REF32(x) ((int)(x))
72 kIOUCAsync0Flags
= 3ULL,
73 kIOUCAsync64Flag
= 1ULL
78 #define IOStatisticsRegisterCounter() \
80 reserved->counter = IOStatistics::registerUserClient(this); \
83 #define IOStatisticsUnregisterCounter() \
86 IOStatistics::unregisterUserClient(reserved->counter); \
89 #define IOStatisticsClientCall() \
91 IOStatistics::countUserClientCall(client); \
96 #define IOStatisticsRegisterCounter()
97 #define IOStatisticsUnregisterCounter()
98 #define IOStatisticsClientCall()
100 #endif /* IOKITSTATS */
102 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 // definitions we should get from osfmk
106 //typedef struct ipc_port * ipc_port_t;
107 typedef natural_t ipc_kobject_type_t
;
109 #define IKOT_IOKIT_SPARE 27
110 #define IKOT_IOKIT_CONNECT 29
111 #define IKOT_IOKIT_OBJECT 30
115 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
116 ipc_kobject_type_t type
);
118 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
120 extern mach_port_name_t
iokit_make_send_right( task_t task
,
121 io_object_t obj
, ipc_kobject_type_t type
);
123 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
125 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
127 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
129 extern ipc_port_t master_device_port
;
131 extern void iokit_retain_port( ipc_port_t port
);
132 extern void iokit_release_port( ipc_port_t port
);
133 extern void iokit_release_port_send( ipc_port_t port
);
135 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
137 #include <mach/mach_traps.h>
138 #include <vm/vm_map.h>
143 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
145 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
147 class IOMachPort
: public OSObject
149 OSDeclareDefaultStructors(IOMachPort
)
156 static IOMachPort
* portForObject( OSObject
* obj
,
157 ipc_kobject_type_t type
);
158 static bool noMoreSendersForObject( OSObject
* obj
,
159 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
160 static void releasePortForObject( OSObject
* obj
,
161 ipc_kobject_type_t type
);
162 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
164 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
166 static mach_port_name_t
makeSendRightForTask( task_t task
,
167 io_object_t obj
, ipc_kobject_type_t type
);
169 virtual void free() APPLE_KEXT_OVERRIDE
;
172 #define super OSObject
173 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
175 static IOLock
* gIOObjectPortLock
;
177 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
179 // not in dictForType() for debugging ease
180 static OSDictionary
* gIOObjectPorts
;
181 static OSDictionary
* gIOConnectPorts
;
183 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
185 OSDictionary
** dict
;
187 if( IKOT_IOKIT_OBJECT
== type
)
188 dict
= &gIOObjectPorts
;
189 else if( IKOT_IOKIT_CONNECT
== type
)
190 dict
= &gIOConnectPorts
;
195 *dict
= OSDictionary::withCapacity( 1 );
200 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
201 ipc_kobject_type_t type
)
203 IOMachPort
* inst
= 0;
206 IOTakeLock( gIOObjectPortLock
);
210 dict
= dictForType( type
);
214 if( (inst
= (IOMachPort
*)
215 dict
->getObject( (const OSSymbol
*) obj
))) {
221 inst
= new IOMachPort
;
222 if( inst
&& !inst
->init()) {
227 inst
->port
= iokit_alloc_object_port( obj
, type
);
230 dict
->setObject( (const OSSymbol
*) obj
, inst
);
240 IOUnlock( gIOObjectPortLock
);
245 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
246 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
249 IOMachPort
* machPort
;
250 bool destroyed
= true;
252 IOTakeLock( gIOObjectPortLock
);
254 if( (dict
= dictForType( type
))) {
257 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
259 destroyed
= (machPort
->mscount
<= *mscount
);
261 dict
->removeObject( (const OSSymbol
*) obj
);
263 *mscount
= machPort
->mscount
;
268 IOUnlock( gIOObjectPortLock
);
273 void IOMachPort::releasePortForObject( OSObject
* obj
,
274 ipc_kobject_type_t type
)
277 IOMachPort
* machPort
;
279 IOTakeLock( gIOObjectPortLock
);
281 if( (dict
= dictForType( type
))) {
283 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
284 if( machPort
&& !machPort
->holdDestroy
)
285 dict
->removeObject( (const OSSymbol
*) obj
);
289 IOUnlock( gIOObjectPortLock
);
292 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
295 IOMachPort
* machPort
;
297 IOLockLock( gIOObjectPortLock
);
299 if( (dict
= dictForType( type
))) {
300 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
302 machPort
->holdDestroy
= true;
305 IOLockUnlock( gIOObjectPortLock
);
308 void IOUserClient::destroyUserReferences( OSObject
* obj
)
310 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
313 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
317 IOTakeLock( gIOObjectPortLock
);
320 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
323 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
327 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
329 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
330 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
332 uc
->mappings
->release();
335 dict
->removeObject( (const OSSymbol
*) obj
);
339 IOUnlock( gIOObjectPortLock
);
342 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
343 io_object_t obj
, ipc_kobject_type_t type
)
345 return( iokit_make_send_right( task
, obj
, type
));
348 void IOMachPort::free( void )
351 iokit_destroy_object_port( port
);
355 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
357 class IOUserNotification
: public OSIterator
359 OSDeclareDefaultStructors(IOUserNotification
)
361 IONotifier
* holdNotify
;
366 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
367 virtual void free() APPLE_KEXT_OVERRIDE
;
369 virtual void setNotification( IONotifier
* obj
);
371 virtual void reset() APPLE_KEXT_OVERRIDE
;
372 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
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
,
469 virtual void free() APPLE_KEXT_OVERRIDE
;
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() APPLE_KEXT_OVERRIDE
;
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
,
501 virtual void free() APPLE_KEXT_OVERRIDE
;
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() APPLE_KEXT_OVERRIDE
;
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 // Create a vm_map_copy_t or kalloc'ed data for memory
1509 // to be copied out. ipc will free after the copyout.
1511 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1512 io_buf_ptr_t
* buf
)
1517 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1518 false /* src_destroy */, ©
);
1520 assert( err
== KERN_SUCCESS
);
1521 if( err
== KERN_SUCCESS
)
1522 *buf
= (char *) copy
;
1527 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1529 /* Routine io_server_version */
1530 kern_return_t
is_io_server_version(
1531 mach_port_t master_port
,
1534 *version
= IOKIT_SERVER_VERSION
;
1535 return (kIOReturnSuccess
);
1538 /* Routine io_object_get_class */
1539 kern_return_t
is_io_object_get_class(
1541 io_name_t className
)
1543 const OSMetaClass
* my_obj
= NULL
;
1544 const char * my_class_name
= NULL
;
1547 return( kIOReturnBadArgument
);
1549 if ( !my_class_name
) {
1550 my_obj
= object
->getMetaClass();
1552 return (kIOReturnNotFound
);
1555 my_class_name
= my_obj
->getClassName();
1558 strlcpy( className
, my_class_name
, sizeof(io_name_t
));
1560 return( kIOReturnSuccess
);
1563 /* Routine io_object_get_superclass */
1564 kern_return_t
is_io_object_get_superclass(
1565 mach_port_t master_port
,
1567 io_name_t class_name
)
1569 const OSMetaClass
* my_obj
= NULL
;
1570 const OSMetaClass
* superclass
= NULL
;
1571 const OSSymbol
*my_name
= NULL
;
1572 const char *my_cstr
= NULL
;
1574 if (!obj_name
|| !class_name
)
1575 return (kIOReturnBadArgument
);
1577 if( master_port
!= master_device_port
)
1578 return( kIOReturnNotPrivileged
);
1580 my_name
= OSSymbol::withCString(obj_name
);
1583 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1587 superclass
= my_obj
->getSuperClass();
1591 return( kIOReturnNotFound
);
1594 my_cstr
= superclass
->getClassName();
1597 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1598 return( kIOReturnSuccess
);
1600 return (kIOReturnNotFound
);
1603 /* Routine io_object_get_bundle_identifier */
1604 kern_return_t
is_io_object_get_bundle_identifier(
1605 mach_port_t master_port
,
1607 io_name_t bundle_name
)
1609 const OSMetaClass
* my_obj
= NULL
;
1610 const OSSymbol
*my_name
= NULL
;
1611 const OSSymbol
*identifier
= NULL
;
1612 const char *my_cstr
= NULL
;
1614 if (!obj_name
|| !bundle_name
)
1615 return (kIOReturnBadArgument
);
1617 if( master_port
!= master_device_port
)
1618 return( kIOReturnNotPrivileged
);
1620 my_name
= OSSymbol::withCString(obj_name
);
1623 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1628 identifier
= my_obj
->getKmodName();
1631 return( kIOReturnNotFound
);
1634 my_cstr
= identifier
->getCStringNoCopy();
1636 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1637 return( kIOReturnSuccess
);
1640 return (kIOReturnBadArgument
);
1643 /* Routine io_object_conforms_to */
1644 kern_return_t
is_io_object_conforms_to(
1646 io_name_t className
,
1647 boolean_t
*conforms
)
1650 return( kIOReturnBadArgument
);
1652 *conforms
= (0 != object
->metaCast( className
));
1654 return( kIOReturnSuccess
);
1657 /* Routine io_object_get_retain_count */
1658 kern_return_t
is_io_object_get_retain_count(
1660 uint32_t *retainCount
)
1663 return( kIOReturnBadArgument
);
1665 *retainCount
= object
->getRetainCount();
1666 return( kIOReturnSuccess
);
1669 /* Routine io_iterator_next */
1670 kern_return_t
is_io_iterator_next(
1671 io_object_t iterator
,
1672 io_object_t
*object
)
1676 CHECK( OSIterator
, iterator
, iter
);
1678 obj
= iter
->getNextObject();
1682 return( kIOReturnSuccess
);
1684 return( kIOReturnNoDevice
);
1687 /* Routine io_iterator_reset */
1688 kern_return_t
is_io_iterator_reset(
1689 io_object_t iterator
)
1691 CHECK( OSIterator
, iterator
, iter
);
1695 return( kIOReturnSuccess
);
1698 /* Routine io_iterator_is_valid */
1699 kern_return_t
is_io_iterator_is_valid(
1700 io_object_t iterator
,
1701 boolean_t
*is_valid
)
1703 CHECK( OSIterator
, iterator
, iter
);
1705 *is_valid
= iter
->isValid();
1707 return( kIOReturnSuccess
);
1711 static kern_return_t
internal_io_service_match_property_table(
1712 io_service_t _service
,
1713 const char * matching
,
1714 mach_msg_type_number_t matching_size
,
1717 CHECK( IOService
, _service
, service
);
1721 OSDictionary
* dict
;
1723 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1724 : OSUnserializeXML(matching
);
1725 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1726 *matches
= service
->passiveMatch( dict
);
1727 kr
= kIOReturnSuccess
;
1729 kr
= kIOReturnBadArgument
;
1737 /* Routine io_service_match_property_table */
1738 kern_return_t
is_io_service_match_property_table(
1739 io_service_t service
,
1740 io_string_t matching
,
1741 boolean_t
*matches
)
1743 return (internal_io_service_match_property_table(service
, matching
, 0, matches
));
1747 /* Routine io_service_match_property_table_ool */
1748 kern_return_t
is_io_service_match_property_table_ool(
1749 io_object_t service
,
1750 io_buf_ptr_t matching
,
1751 mach_msg_type_number_t matchingCnt
,
1752 kern_return_t
*result
,
1753 boolean_t
*matches
)
1757 vm_map_offset_t map_data
;
1759 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1760 data
= CAST_DOWN(vm_offset_t
, map_data
);
1762 if( KERN_SUCCESS
== kr
) {
1763 // must return success after vm_map_copyout() succeeds
1764 *result
= internal_io_service_match_property_table(service
,
1765 (const char *)data
, matchingCnt
, matches
);
1766 vm_deallocate( kernel_map
, data
, matchingCnt
);
1772 /* Routine io_service_match_property_table_bin */
1773 kern_return_t
is_io_service_match_property_table_bin(
1774 io_object_t service
,
1775 io_struct_inband_t matching
,
1776 mach_msg_type_number_t matchingCnt
,
1779 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
1782 static kern_return_t
internal_io_service_get_matching_services(
1783 mach_port_t master_port
,
1784 const char * matching
,
1785 mach_msg_type_number_t matching_size
,
1786 io_iterator_t
*existing
)
1790 OSDictionary
* dict
;
1792 if( master_port
!= master_device_port
)
1793 return( kIOReturnNotPrivileged
);
1795 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1796 : OSUnserializeXML(matching
);
1797 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1798 *existing
= IOService::getMatchingServices( dict
);
1799 kr
= kIOReturnSuccess
;
1801 kr
= kIOReturnBadArgument
;
1809 /* Routine io_service_get_matching_services */
1810 kern_return_t
is_io_service_get_matching_services(
1811 mach_port_t master_port
,
1812 io_string_t matching
,
1813 io_iterator_t
*existing
)
1815 return (internal_io_service_get_matching_services(master_port
, matching
, 0, existing
));
1818 /* Routine io_service_get_matching_services_ool */
1819 kern_return_t
is_io_service_get_matching_services_ool(
1820 mach_port_t master_port
,
1821 io_buf_ptr_t matching
,
1822 mach_msg_type_number_t matchingCnt
,
1823 kern_return_t
*result
,
1824 io_object_t
*existing
)
1828 vm_map_offset_t map_data
;
1830 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1831 data
= CAST_DOWN(vm_offset_t
, map_data
);
1833 if( KERN_SUCCESS
== kr
) {
1834 // must return success after vm_map_copyout() succeeds
1835 *result
= internal_io_service_get_matching_services(master_port
,
1836 (const char *) data
, matchingCnt
, existing
);
1837 vm_deallocate( kernel_map
, data
, matchingCnt
);
1843 /* Routine io_service_get_matching_services_bin */
1844 kern_return_t
is_io_service_get_matching_services_bin(
1845 mach_port_t master_port
,
1846 io_struct_inband_t matching
,
1847 mach_msg_type_number_t matchingCnt
,
1848 io_object_t
*existing
)
1850 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
1854 static kern_return_t
internal_io_service_get_matching_service(
1855 mach_port_t master_port
,
1856 const char * matching
,
1857 mach_msg_type_number_t matching_size
,
1858 io_service_t
*service
)
1862 OSDictionary
* dict
;
1864 if( master_port
!= master_device_port
)
1865 return( kIOReturnNotPrivileged
);
1867 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1868 : OSUnserializeXML(matching
);
1869 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1870 *service
= IOService::copyMatchingService( dict
);
1871 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
1873 kr
= kIOReturnBadArgument
;
1881 /* Routine io_service_get_matching_service */
1882 kern_return_t
is_io_service_get_matching_service(
1883 mach_port_t master_port
,
1884 io_string_t matching
,
1885 io_service_t
*service
)
1887 return (internal_io_service_get_matching_service(master_port
, matching
, 0, service
));
1890 /* Routine io_service_get_matching_services_ool */
1891 kern_return_t
is_io_service_get_matching_service_ool(
1892 mach_port_t master_port
,
1893 io_buf_ptr_t matching
,
1894 mach_msg_type_number_t matchingCnt
,
1895 kern_return_t
*result
,
1896 io_object_t
*service
)
1900 vm_map_offset_t map_data
;
1902 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1903 data
= CAST_DOWN(vm_offset_t
, map_data
);
1905 if( KERN_SUCCESS
== kr
) {
1906 // must return success after vm_map_copyout() succeeds
1907 *result
= internal_io_service_get_matching_service(master_port
,
1908 (const char *) data
, matchingCnt
, service
);
1909 vm_deallocate( kernel_map
, data
, matchingCnt
);
1915 /* Routine io_service_get_matching_service_bin */
1916 kern_return_t
is_io_service_get_matching_service_bin(
1917 mach_port_t master_port
,
1918 io_struct_inband_t matching
,
1919 mach_msg_type_number_t matchingCnt
,
1920 io_object_t
*service
)
1922 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
1925 static kern_return_t
internal_io_service_add_notification(
1926 mach_port_t master_port
,
1927 io_name_t notification_type
,
1928 const char * matching
,
1929 size_t matching_size
,
1932 vm_size_t referenceSize
,
1934 io_object_t
* notification
)
1936 IOServiceUserNotification
* userNotify
= 0;
1937 IONotifier
* notify
= 0;
1938 const OSSymbol
* sym
;
1939 OSDictionary
* dict
;
1941 unsigned long int userMsgType
;
1943 if( master_port
!= master_device_port
)
1944 return( kIOReturnNotPrivileged
);
1947 err
= kIOReturnNoResources
;
1949 if( !(sym
= OSSymbol::withCString( notification_type
)))
1950 err
= kIOReturnNoResources
;
1954 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
1958 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
));
1962 err
= kIOReturnBadArgument
;
1966 if( (sym
== gIOPublishNotification
)
1967 || (sym
== gIOFirstPublishNotification
))
1968 userMsgType
= kIOServicePublishNotificationType
;
1969 else if( (sym
== gIOMatchedNotification
)
1970 || (sym
== gIOFirstMatchNotification
))
1971 userMsgType
= kIOServiceMatchedNotificationType
;
1972 else if( sym
== gIOTerminatedNotification
)
1973 userMsgType
= kIOServiceTerminatedNotificationType
;
1975 userMsgType
= kLastIOKitNotificationType
;
1977 userNotify
= new IOServiceUserNotification
;
1979 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1980 reference
, referenceSize
, client64
)) {
1981 iokit_release_port_send(port
);
1982 userNotify
->release();
1988 notify
= IOService::addMatchingNotification( sym
, dict
,
1989 &userNotify
->_handler
, userNotify
);
1991 *notification
= userNotify
;
1992 userNotify
->setNotification( notify
);
1993 err
= kIOReturnSuccess
;
1995 err
= kIOReturnUnsupported
;
2008 /* Routine io_service_add_notification */
2009 kern_return_t
is_io_service_add_notification(
2010 mach_port_t master_port
,
2011 io_name_t notification_type
,
2012 io_string_t matching
,
2014 io_async_ref_t reference
,
2015 mach_msg_type_number_t referenceCnt
,
2016 io_object_t
* notification
)
2018 return (internal_io_service_add_notification(master_port
, notification_type
,
2019 matching
, 0, port
, &reference
[0], sizeof(io_async_ref_t
),
2020 false, notification
));
2023 /* Routine io_service_add_notification_64 */
2024 kern_return_t
is_io_service_add_notification_64(
2025 mach_port_t master_port
,
2026 io_name_t notification_type
,
2027 io_string_t matching
,
2028 mach_port_t wake_port
,
2029 io_async_ref64_t reference
,
2030 mach_msg_type_number_t referenceCnt
,
2031 io_object_t
*notification
)
2033 return (internal_io_service_add_notification(master_port
, notification_type
,
2034 matching
, 0, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2035 true, notification
));
2038 /* Routine io_service_add_notification_bin */
2039 kern_return_t is_io_service_add_notification_bin
2041 mach_port_t master_port
,
2042 io_name_t notification_type
,
2043 io_struct_inband_t matching
,
2044 mach_msg_type_number_t matchingCnt
,
2045 mach_port_t wake_port
,
2046 io_async_ref_t reference
,
2047 mach_msg_type_number_t referenceCnt
,
2048 io_object_t
*notification
)
2050 return (internal_io_service_add_notification(master_port
, notification_type
,
2051 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2052 false, notification
));
2055 /* Routine io_service_add_notification_bin_64 */
2056 kern_return_t is_io_service_add_notification_bin_64
2058 mach_port_t master_port
,
2059 io_name_t notification_type
,
2060 io_struct_inband_t matching
,
2061 mach_msg_type_number_t matchingCnt
,
2062 mach_port_t wake_port
,
2063 io_async_ref64_t reference
,
2064 mach_msg_type_number_t referenceCnt
,
2065 io_object_t
*notification
)
2067 return (internal_io_service_add_notification(master_port
, notification_type
,
2068 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2069 true, notification
));
2072 static kern_return_t
internal_io_service_add_notification_ool(
2073 mach_port_t master_port
,
2074 io_name_t notification_type
,
2075 io_buf_ptr_t matching
,
2076 mach_msg_type_number_t matchingCnt
,
2077 mach_port_t wake_port
,
2079 vm_size_t referenceSize
,
2081 kern_return_t
*result
,
2082 io_object_t
*notification
)
2086 vm_map_offset_t map_data
;
2088 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2089 data
= CAST_DOWN(vm_offset_t
, map_data
);
2091 if( KERN_SUCCESS
== kr
) {
2092 // must return success after vm_map_copyout() succeeds
2093 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2094 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2095 vm_deallocate( kernel_map
, data
, matchingCnt
);
2101 /* Routine io_service_add_notification_ool */
2102 kern_return_t
is_io_service_add_notification_ool(
2103 mach_port_t master_port
,
2104 io_name_t notification_type
,
2105 io_buf_ptr_t matching
,
2106 mach_msg_type_number_t matchingCnt
,
2107 mach_port_t wake_port
,
2108 io_async_ref_t reference
,
2109 mach_msg_type_number_t referenceCnt
,
2110 kern_return_t
*result
,
2111 io_object_t
*notification
)
2113 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2114 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2115 false, result
, notification
));
2118 /* Routine io_service_add_notification_ool_64 */
2119 kern_return_t
is_io_service_add_notification_ool_64(
2120 mach_port_t master_port
,
2121 io_name_t notification_type
,
2122 io_buf_ptr_t matching
,
2123 mach_msg_type_number_t matchingCnt
,
2124 mach_port_t wake_port
,
2125 io_async_ref64_t reference
,
2126 mach_msg_type_number_t referenceCnt
,
2127 kern_return_t
*result
,
2128 io_object_t
*notification
)
2130 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2131 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2132 true, result
, notification
));
2135 /* Routine io_service_add_notification_old */
2136 kern_return_t
is_io_service_add_notification_old(
2137 mach_port_t master_port
,
2138 io_name_t notification_type
,
2139 io_string_t matching
,
2141 // for binary compatibility reasons, this must be natural_t for ILP32
2143 io_object_t
* notification
)
2145 return( is_io_service_add_notification( master_port
, notification_type
,
2146 matching
, port
, &ref
, 1, notification
));
2150 static kern_return_t
internal_io_service_add_interest_notification(
2151 io_object_t _service
,
2152 io_name_t type_of_interest
,
2155 vm_size_t referenceSize
,
2157 io_object_t
* notification
)
2160 IOServiceMessageUserNotification
* userNotify
= 0;
2161 IONotifier
* notify
= 0;
2162 const OSSymbol
* sym
;
2165 CHECK( IOService
, _service
, service
);
2167 err
= kIOReturnNoResources
;
2168 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2170 userNotify
= new IOServiceMessageUserNotification
;
2172 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2173 reference
, referenceSize
,
2174 kIOUserNotifyMaxMessageSize
,
2176 iokit_release_port_send(port
);
2177 userNotify
->release();
2183 notify
= service
->registerInterest( sym
,
2184 &userNotify
->_handler
, userNotify
);
2186 *notification
= userNotify
;
2187 userNotify
->setNotification( notify
);
2188 err
= kIOReturnSuccess
;
2190 err
= kIOReturnUnsupported
;
2199 /* Routine io_service_add_message_notification */
2200 kern_return_t
is_io_service_add_interest_notification(
2201 io_object_t service
,
2202 io_name_t type_of_interest
,
2204 io_async_ref_t reference
,
2205 mach_msg_type_number_t referenceCnt
,
2206 io_object_t
* notification
)
2208 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2209 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2212 /* Routine io_service_add_interest_notification_64 */
2213 kern_return_t
is_io_service_add_interest_notification_64(
2214 io_object_t service
,
2215 io_name_t type_of_interest
,
2216 mach_port_t wake_port
,
2217 io_async_ref64_t reference
,
2218 mach_msg_type_number_t referenceCnt
,
2219 io_object_t
*notification
)
2221 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2222 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2226 /* Routine io_service_acknowledge_notification */
2227 kern_return_t
is_io_service_acknowledge_notification(
2228 io_object_t _service
,
2229 natural_t notify_ref
,
2230 natural_t response
)
2232 CHECK( IOService
, _service
, service
);
2234 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2235 (IOOptionBits
) response
));
2239 /* Routine io_connect_get_semaphore */
2240 kern_return_t
is_io_connect_get_notification_semaphore(
2241 io_connect_t connection
,
2242 natural_t notification_type
,
2243 semaphore_t
*semaphore
)
2245 CHECK( IOUserClient
, connection
, client
);
2247 IOStatisticsClientCall();
2248 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2252 /* Routine io_registry_get_root_entry */
2253 kern_return_t
is_io_registry_get_root_entry(
2254 mach_port_t master_port
,
2257 IORegistryEntry
* entry
;
2259 if( master_port
!= master_device_port
)
2260 return( kIOReturnNotPrivileged
);
2262 entry
= IORegistryEntry::getRegistryRoot();
2267 return( kIOReturnSuccess
);
2270 /* Routine io_registry_create_iterator */
2271 kern_return_t
is_io_registry_create_iterator(
2272 mach_port_t master_port
,
2275 io_object_t
*iterator
)
2277 if( master_port
!= master_device_port
)
2278 return( kIOReturnNotPrivileged
);
2280 *iterator
= IORegistryIterator::iterateOver(
2281 IORegistryEntry::getPlane( plane
), options
);
2283 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2286 /* Routine io_registry_entry_create_iterator */
2287 kern_return_t
is_io_registry_entry_create_iterator(
2288 io_object_t registry_entry
,
2291 io_object_t
*iterator
)
2293 CHECK( IORegistryEntry
, registry_entry
, entry
);
2295 *iterator
= IORegistryIterator::iterateOver( entry
,
2296 IORegistryEntry::getPlane( plane
), options
);
2298 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2301 /* Routine io_registry_iterator_enter */
2302 kern_return_t
is_io_registry_iterator_enter_entry(
2303 io_object_t iterator
)
2305 CHECK( IORegistryIterator
, iterator
, iter
);
2309 return( kIOReturnSuccess
);
2312 /* Routine io_registry_iterator_exit */
2313 kern_return_t
is_io_registry_iterator_exit_entry(
2314 io_object_t iterator
)
2318 CHECK( IORegistryIterator
, iterator
, iter
);
2320 didIt
= iter
->exitEntry();
2322 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2325 /* Routine io_registry_entry_from_path */
2326 kern_return_t
is_io_registry_entry_from_path(
2327 mach_port_t master_port
,
2329 io_object_t
*registry_entry
)
2331 IORegistryEntry
* entry
;
2333 if( master_port
!= master_device_port
)
2334 return( kIOReturnNotPrivileged
);
2336 entry
= IORegistryEntry::fromPath( path
);
2338 *registry_entry
= entry
;
2340 return( kIOReturnSuccess
);
2344 /* Routine io_registry_entry_from_path */
2345 kern_return_t
is_io_registry_entry_from_path_ool(
2346 mach_port_t master_port
,
2347 io_string_inband_t path
,
2348 io_buf_ptr_t path_ool
,
2349 mach_msg_type_number_t path_oolCnt
,
2350 kern_return_t
*result
,
2351 io_object_t
*registry_entry
)
2353 IORegistryEntry
* entry
;
2354 vm_map_offset_t map_data
;
2359 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2363 res
= err
= KERN_SUCCESS
;
2364 if (path
[0]) cpath
= path
;
2367 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2368 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2370 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2371 if (KERN_SUCCESS
== err
)
2373 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2374 cpath
= CAST_DOWN(const char *, map_data
);
2375 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2379 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2381 entry
= IORegistryEntry::fromPath(cpath
);
2382 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2385 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2387 if (KERN_SUCCESS
!= err
) res
= err
;
2388 *registry_entry
= entry
;
2395 /* Routine io_registry_entry_in_plane */
2396 kern_return_t
is_io_registry_entry_in_plane(
2397 io_object_t registry_entry
,
2399 boolean_t
*inPlane
)
2401 CHECK( IORegistryEntry
, registry_entry
, entry
);
2403 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2405 return( kIOReturnSuccess
);
2409 /* Routine io_registry_entry_get_path */
2410 kern_return_t
is_io_registry_entry_get_path(
2411 io_object_t registry_entry
,
2416 CHECK( IORegistryEntry
, registry_entry
, entry
);
2418 length
= sizeof( io_string_t
);
2419 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2420 return( kIOReturnSuccess
);
2422 return( kIOReturnBadArgument
);
2425 /* Routine io_registry_entry_get_path */
2426 kern_return_t
is_io_registry_entry_get_path_ool(
2427 io_object_t registry_entry
,
2429 io_string_inband_t path
,
2430 io_buf_ptr_t
*path_ool
,
2431 mach_msg_type_number_t
*path_oolCnt
)
2433 enum { kMaxPath
= 16384 };
2438 CHECK( IORegistryEntry
, registry_entry
, entry
);
2442 length
= sizeof(io_string_inband_t
);
2443 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2447 buf
= IONew(char, length
);
2448 if (!buf
) err
= kIOReturnNoMemory
;
2449 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2452 *path_oolCnt
= length
;
2453 err
= copyoutkdata(buf
, length
, path_ool
);
2455 if (buf
) IODelete(buf
, char, kMaxPath
);
2462 /* Routine io_registry_entry_get_name */
2463 kern_return_t
is_io_registry_entry_get_name(
2464 io_object_t registry_entry
,
2467 CHECK( IORegistryEntry
, registry_entry
, entry
);
2469 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2471 return( kIOReturnSuccess
);
2474 /* Routine io_registry_entry_get_name_in_plane */
2475 kern_return_t
is_io_registry_entry_get_name_in_plane(
2476 io_object_t registry_entry
,
2477 io_name_t planeName
,
2480 const IORegistryPlane
* plane
;
2481 CHECK( IORegistryEntry
, registry_entry
, entry
);
2484 plane
= IORegistryEntry::getPlane( planeName
);
2488 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2490 return( kIOReturnSuccess
);
2493 /* Routine io_registry_entry_get_location_in_plane */
2494 kern_return_t
is_io_registry_entry_get_location_in_plane(
2495 io_object_t registry_entry
,
2496 io_name_t planeName
,
2497 io_name_t location
)
2499 const IORegistryPlane
* plane
;
2500 CHECK( IORegistryEntry
, registry_entry
, entry
);
2503 plane
= IORegistryEntry::getPlane( planeName
);
2507 const char * cstr
= entry
->getLocation( plane
);
2510 strncpy( location
, cstr
, sizeof( io_name_t
));
2511 return( kIOReturnSuccess
);
2513 return( kIOReturnNotFound
);
2516 /* Routine io_registry_entry_get_registry_entry_id */
2517 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2518 io_object_t registry_entry
,
2519 uint64_t *entry_id
)
2521 CHECK( IORegistryEntry
, registry_entry
, entry
);
2523 *entry_id
= entry
->getRegistryEntryID();
2525 return (kIOReturnSuccess
);
2528 /* Routine io_registry_entry_get_property */
2529 kern_return_t
is_io_registry_entry_get_property_bytes(
2530 io_object_t registry_entry
,
2531 io_name_t property_name
,
2532 io_struct_inband_t buf
,
2533 mach_msg_type_number_t
*dataCnt
)
2541 unsigned int len
= 0;
2542 const void * bytes
= 0;
2543 IOReturn ret
= kIOReturnSuccess
;
2545 CHECK( IORegistryEntry
, registry_entry
, entry
);
2548 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2549 return kIOReturnNotPermitted
;
2552 obj
= entry
->copyProperty(property_name
);
2554 return( kIOReturnNoResources
);
2556 // One day OSData will be a common container base class
2558 if( (data
= OSDynamicCast( OSData
, obj
))) {
2559 len
= data
->getLength();
2560 bytes
= data
->getBytesNoCopy();
2562 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2563 len
= str
->getLength() + 1;
2564 bytes
= str
->getCStringNoCopy();
2566 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2567 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2568 bytes
= boo
->isTrue() ? "Yes" : "No";
2570 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2571 offsetBytes
= off
->unsigned64BitValue();
2572 len
= off
->numberOfBytes();
2573 bytes
= &offsetBytes
;
2574 #ifdef __BIG_ENDIAN__
2575 bytes
= (const void *)
2576 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2580 ret
= kIOReturnBadArgument
;
2584 ret
= kIOReturnIPCError
;
2587 bcopy( bytes
, buf
, len
);
2596 /* Routine io_registry_entry_get_property */
2597 kern_return_t
is_io_registry_entry_get_property(
2598 io_object_t registry_entry
,
2599 io_name_t property_name
,
2600 io_buf_ptr_t
*properties
,
2601 mach_msg_type_number_t
*propertiesCnt
)
2607 CHECK( IORegistryEntry
, registry_entry
, entry
);
2610 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2611 return kIOReturnNotPermitted
;
2614 obj
= entry
->copyProperty(property_name
);
2616 return( kIOReturnNotFound
);
2618 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2621 return( kIOReturnNoMemory
);
2624 if( obj
->serialize( s
)) {
2625 len
= s
->getLength();
2626 *propertiesCnt
= len
;
2627 err
= copyoutkdata( s
->text(), len
, properties
);
2630 err
= kIOReturnUnsupported
;
2638 /* Routine io_registry_entry_get_property_recursively */
2639 kern_return_t
is_io_registry_entry_get_property_recursively(
2640 io_object_t registry_entry
,
2642 io_name_t property_name
,
2644 io_buf_ptr_t
*properties
,
2645 mach_msg_type_number_t
*propertiesCnt
)
2651 CHECK( IORegistryEntry
, registry_entry
, entry
);
2654 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2655 return kIOReturnNotPermitted
;
2658 obj
= entry
->copyProperty( property_name
,
2659 IORegistryEntry::getPlane( plane
), options
);
2661 return( kIOReturnNotFound
);
2663 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2666 return( kIOReturnNoMemory
);
2669 if( obj
->serialize( s
)) {
2670 len
= s
->getLength();
2671 *propertiesCnt
= len
;
2672 err
= copyoutkdata( s
->text(), len
, properties
);
2675 err
= kIOReturnUnsupported
;
2685 static kern_return_t
2686 filteredProperties(IORegistryEntry
*entry
, OSDictionary
*properties
, OSDictionary
**filteredp
)
2688 kern_return_t err
= 0;
2689 OSDictionary
*filtered
= NULL
;
2690 OSCollectionIterator
*iter
= NULL
;
2693 kauth_cred_t cred
= kauth_cred_get();
2695 if (properties
== NULL
)
2696 return kIOReturnUnsupported
;
2698 if ((iter
= OSCollectionIterator::withCollection(properties
)) == NULL
||
2699 (filtered
= OSDictionary::withCapacity(properties
->getCapacity())) == NULL
) {
2700 err
= kIOReturnNoMemory
;
2704 while ((p
= iter
->getNextObject()) != NULL
) {
2705 if ((key
= OSDynamicCast(OSSymbol
, p
)) == NULL
||
2706 mac_iokit_check_get_property(cred
, entry
, key
->getCStringNoCopy()) != 0)
2708 filtered
->setObject(key
, properties
->getObject(key
));
2714 *filteredp
= filtered
;
2720 /* Routine io_registry_entry_get_properties */
2721 kern_return_t
is_io_registry_entry_get_properties(
2722 io_object_t registry_entry
,
2723 io_buf_ptr_t
*properties
,
2724 mach_msg_type_number_t
*propertiesCnt
)
2726 kern_return_t err
= 0;
2729 CHECK( IORegistryEntry
, registry_entry
, entry
);
2731 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2733 return( kIOReturnNoMemory
);
2735 if (!entry
->serializeProperties(s
))
2736 err
= kIOReturnUnsupported
;
2739 if (!err
&& mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
2740 OSObject
*propobj
= OSUnserializeXML(s
->text(), s
->getLength());
2741 OSDictionary
*filteredprops
= NULL
;
2742 err
= filteredProperties(entry
, OSDynamicCast(OSDictionary
, propobj
), &filteredprops
);
2743 if (propobj
) propobj
->release();
2747 if (!filteredprops
->serialize(s
))
2748 err
= kIOReturnUnsupported
;
2750 if (filteredprops
!= NULL
)
2751 filteredprops
->release();
2753 #endif /* CONFIG_MACF */
2756 len
= s
->getLength();
2757 *propertiesCnt
= len
;
2758 err
= copyoutkdata( s
->text(), len
, properties
);
2767 struct GetPropertiesEditorRef
2770 IORegistryEntry
* entry
;
2771 OSCollection
* root
;
2774 static const OSMetaClassBase
*
2775 GetPropertiesEditor(void * reference
,
2777 OSCollection
* container
,
2778 const OSSymbol
* name
,
2779 const OSMetaClassBase
* value
)
2781 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
2783 if (!ref
->root
) ref
->root
= container
;
2784 if (ref
->root
== container
)
2786 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
2791 if (value
) value
->retain();
2795 #endif /* CONFIG_MACF */
2797 /* Routine io_registry_entry_get_properties */
2798 kern_return_t
is_io_registry_entry_get_properties_bin(
2799 io_object_t registry_entry
,
2800 io_buf_ptr_t
*properties
,
2801 mach_msg_type_number_t
*propertiesCnt
)
2803 kern_return_t err
= kIOReturnSuccess
;
2806 OSSerialize::Editor editor
= 0;
2809 CHECK(IORegistryEntry
, registry_entry
, entry
);
2812 GetPropertiesEditorRef ref
;
2813 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
2815 editor
= &GetPropertiesEditor
;
2817 ref
.cred
= kauth_cred_get();
2823 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
2824 if (!s
) return (kIOReturnNoMemory
);
2826 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
2828 if (kIOReturnSuccess
== err
)
2830 len
= s
->getLength();
2831 *propertiesCnt
= len
;
2832 err
= copyoutkdata(s
->text(), len
, properties
);
2839 /* Routine io_registry_entry_get_property_bin */
2840 kern_return_t
is_io_registry_entry_get_property_bin(
2841 io_object_t registry_entry
,
2843 io_name_t property_name
,
2845 io_buf_ptr_t
*properties
,
2846 mach_msg_type_number_t
*propertiesCnt
)
2851 const OSSymbol
* sym
;
2853 CHECK( IORegistryEntry
, registry_entry
, entry
);
2856 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2857 return kIOReturnNotPermitted
;
2860 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
2862 obj
= entry
->copyProperty(property_name
,
2863 IORegistryEntry::getPlane(plane
), options
);
2867 obj
= entry
->copyProperty(property_name
);
2871 return( kIOReturnNotFound
);
2873 sym
= OSSymbol::withCString(property_name
);
2876 if (gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
2880 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
2883 return( kIOReturnNoMemory
);
2886 if( obj
->serialize( s
)) {
2887 len
= s
->getLength();
2888 *propertiesCnt
= len
;
2889 err
= copyoutkdata( s
->text(), len
, properties
);
2891 } else err
= kIOReturnUnsupported
;
2900 /* Routine io_registry_entry_set_properties */
2901 kern_return_t is_io_registry_entry_set_properties
2903 io_object_t registry_entry
,
2904 io_buf_ptr_t properties
,
2905 mach_msg_type_number_t propertiesCnt
,
2906 kern_return_t
* result
)
2912 vm_map_offset_t map_data
;
2914 CHECK( IORegistryEntry
, registry_entry
, entry
);
2916 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
2917 return( kIOReturnMessageTooLarge
);
2919 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2920 data
= CAST_DOWN(vm_offset_t
, map_data
);
2922 if( KERN_SUCCESS
== err
) {
2924 // must return success after vm_map_copyout() succeeds
2925 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
2926 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2929 res
= kIOReturnBadArgument
;
2931 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
2932 registry_entry
, obj
))
2934 res
= kIOReturnNotPermitted
;
2939 res
= entry
->setProperties( obj
);
2951 /* Routine io_registry_entry_get_child_iterator */
2952 kern_return_t
is_io_registry_entry_get_child_iterator(
2953 io_object_t registry_entry
,
2955 io_object_t
*iterator
)
2957 CHECK( IORegistryEntry
, registry_entry
, entry
);
2959 *iterator
= entry
->getChildIterator(
2960 IORegistryEntry::getPlane( plane
));
2962 return( kIOReturnSuccess
);
2965 /* Routine io_registry_entry_get_parent_iterator */
2966 kern_return_t
is_io_registry_entry_get_parent_iterator(
2967 io_object_t registry_entry
,
2969 io_object_t
*iterator
)
2971 CHECK( IORegistryEntry
, registry_entry
, entry
);
2973 *iterator
= entry
->getParentIterator(
2974 IORegistryEntry::getPlane( plane
));
2976 return( kIOReturnSuccess
);
2979 /* Routine io_service_get_busy_state */
2980 kern_return_t
is_io_service_get_busy_state(
2981 io_object_t _service
,
2982 uint32_t *busyState
)
2984 CHECK( IOService
, _service
, service
);
2986 *busyState
= service
->getBusyState();
2988 return( kIOReturnSuccess
);
2991 /* Routine io_service_get_state */
2992 kern_return_t
is_io_service_get_state(
2993 io_object_t _service
,
2995 uint32_t *busy_state
,
2996 uint64_t *accumulated_busy_time
)
2998 CHECK( IOService
, _service
, service
);
3000 *state
= service
->getState();
3001 *busy_state
= service
->getBusyState();
3002 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3004 return( kIOReturnSuccess
);
3007 /* Routine io_service_wait_quiet */
3008 kern_return_t
is_io_service_wait_quiet(
3009 io_object_t _service
,
3010 mach_timespec_t wait_time
)
3014 CHECK( IOService
, _service
, service
);
3016 timeoutNS
= wait_time
.tv_sec
;
3017 timeoutNS
*= kSecondScale
;
3018 timeoutNS
+= wait_time
.tv_nsec
;
3020 return( service
->waitQuiet(timeoutNS
) );
3023 /* Routine io_service_request_probe */
3024 kern_return_t
is_io_service_request_probe(
3025 io_object_t _service
,
3028 CHECK( IOService
, _service
, service
);
3030 return( service
->requestProbe( options
));
3033 /* Routine io_service_get_authorization_id */
3034 kern_return_t
is_io_service_get_authorization_id(
3035 io_object_t _service
,
3036 uint64_t *authorization_id
)
3040 CHECK( IOService
, _service
, service
);
3042 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3043 kIOClientPrivilegeAdministrator
);
3044 if( kIOReturnSuccess
!= kr
)
3047 *authorization_id
= service
->getAuthorizationID();
3052 /* Routine io_service_set_authorization_id */
3053 kern_return_t
is_io_service_set_authorization_id(
3054 io_object_t _service
,
3055 uint64_t authorization_id
)
3057 CHECK( IOService
, _service
, service
);
3059 return( service
->setAuthorizationID( authorization_id
) );
3062 /* Routine io_service_open_ndr */
3063 kern_return_t
is_io_service_open_extended(
3064 io_object_t _service
,
3066 uint32_t connect_type
,
3068 io_buf_ptr_t properties
,
3069 mach_msg_type_number_t propertiesCnt
,
3070 kern_return_t
* result
,
3071 io_object_t
*connection
)
3073 IOUserClient
* client
= 0;
3074 kern_return_t err
= KERN_SUCCESS
;
3075 IOReturn res
= kIOReturnSuccess
;
3076 OSDictionary
* propertiesDict
= 0;
3078 bool disallowAccess
;
3080 CHECK( IOService
, _service
, service
);
3082 if (!owningTask
) return (kIOReturnBadArgument
);
3090 vm_map_offset_t map_data
;
3092 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3093 return( kIOReturnMessageTooLarge
);
3095 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3097 data
= CAST_DOWN(vm_offset_t
, map_data
);
3098 if (KERN_SUCCESS
== err
)
3100 // must return success after vm_map_copyout() succeeds
3101 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3102 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3103 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3104 if (!propertiesDict
)
3106 res
= kIOReturnBadArgument
;
3111 if (kIOReturnSuccess
!= res
)
3115 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3118 if (!propertiesDict
)
3119 propertiesDict
= OSDictionary::withCapacity(4);
3120 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3124 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3129 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3130 connect_type
, propertiesDict
, &client
);
3133 propertiesDict
->release();
3135 if (res
== kIOReturnSuccess
)
3137 assert( OSDynamicCast(IOUserClient
, client
) );
3139 disallowAccess
= (crossEndian
3140 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3141 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3142 if (disallowAccess
) res
= kIOReturnUnsupported
;
3144 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3145 res
= kIOReturnNotPermitted
;
3147 if (kIOReturnSuccess
!= res
)
3149 IOStatisticsClientCall();
3150 client
->clientClose();
3155 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3156 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3159 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3160 creatorName
->release();
3162 client
->setTerminateDefer(service
, false);
3167 *connection
= client
;
3173 /* Routine io_service_close */
3174 kern_return_t
is_io_service_close(
3175 io_object_t connection
)
3178 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3179 return( kIOReturnSuccess
);
3181 CHECK( IOUserClient
, connection
, client
);
3183 IOStatisticsClientCall();
3184 client
->clientClose();
3186 return( kIOReturnSuccess
);
3189 /* Routine io_connect_get_service */
3190 kern_return_t
is_io_connect_get_service(
3191 io_object_t connection
,
3192 io_object_t
*service
)
3194 IOService
* theService
;
3196 CHECK( IOUserClient
, connection
, client
);
3198 theService
= client
->getService();
3200 theService
->retain();
3202 *service
= theService
;
3204 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3207 /* Routine io_connect_set_notification_port */
3208 kern_return_t
is_io_connect_set_notification_port(
3209 io_object_t connection
,
3210 uint32_t notification_type
,
3214 CHECK( IOUserClient
, connection
, client
);
3216 IOStatisticsClientCall();
3217 return( client
->registerNotificationPort( port
, notification_type
,
3218 (io_user_reference_t
) reference
));
3221 /* Routine io_connect_set_notification_port */
3222 kern_return_t
is_io_connect_set_notification_port_64(
3223 io_object_t connection
,
3224 uint32_t notification_type
,
3226 io_user_reference_t reference
)
3228 CHECK( IOUserClient
, connection
, client
);
3230 IOStatisticsClientCall();
3231 return( client
->registerNotificationPort( port
, notification_type
,
3235 /* Routine io_connect_map_memory_into_task */
3236 kern_return_t is_io_connect_map_memory_into_task
3238 io_connect_t connection
,
3239 uint32_t memory_type
,
3241 mach_vm_address_t
*address
,
3242 mach_vm_size_t
*size
,
3249 CHECK( IOUserClient
, connection
, client
);
3251 if (!into_task
) return (kIOReturnBadArgument
);
3253 IOStatisticsClientCall();
3254 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3257 *address
= map
->getAddress();
3259 *size
= map
->getSize();
3261 if( client
->sharedInstance
3262 || (into_task
!= current_task())) {
3263 // push a name out to the task owning the map,
3264 // so we can clean up maps
3265 mach_port_name_t name __unused
=
3266 IOMachPort::makeSendRightForTask(
3267 into_task
, map
, IKOT_IOKIT_OBJECT
);
3270 // keep it with the user client
3271 IOLockLock( gIOObjectPortLock
);
3272 if( 0 == client
->mappings
)
3273 client
->mappings
= OSSet::withCapacity(2);
3274 if( client
->mappings
)
3275 client
->mappings
->setObject( map
);
3276 IOLockUnlock( gIOObjectPortLock
);
3279 err
= kIOReturnSuccess
;
3282 err
= kIOReturnBadArgument
;
3287 /* Routine is_io_connect_map_memory */
3288 kern_return_t
is_io_connect_map_memory(
3289 io_object_t connect
,
3297 mach_vm_address_t address
;
3298 mach_vm_size_t size
;
3300 address
= SCALAR64(*mapAddr
);
3301 size
= SCALAR64(*mapSize
);
3303 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3305 *mapAddr
= SCALAR32(address
);
3306 *mapSize
= SCALAR32(size
);
3313 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3316 IOMemoryMap
* map
= 0;
3318 IOLockLock(gIOObjectPortLock
);
3320 iter
= OSCollectionIterator::withCollection(mappings
);
3323 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3325 if(mem
== map
->getMemoryDescriptor())
3328 mappings
->removeObject(map
);
3335 IOLockUnlock(gIOObjectPortLock
);
3342 /* Routine io_connect_unmap_memory_from_task */
3343 kern_return_t is_io_connect_unmap_memory_from_task
3345 io_connect_t connection
,
3346 uint32_t memory_type
,
3348 mach_vm_address_t address
)
3351 IOOptionBits options
= 0;
3352 IOMemoryDescriptor
* memory
;
3355 CHECK( IOUserClient
, connection
, client
);
3357 if (!from_task
) return (kIOReturnBadArgument
);
3359 IOStatisticsClientCall();
3360 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3362 if( memory
&& (kIOReturnSuccess
== err
)) {
3364 options
= (options
& ~kIOMapUserOptionsMask
)
3365 | kIOMapAnywhere
| kIOMapReference
;
3367 map
= memory
->createMappingInTask( from_task
, address
, options
);
3371 IOLockLock( gIOObjectPortLock
);
3372 if( client
->mappings
)
3373 client
->mappings
->removeObject( map
);
3374 IOLockUnlock( gIOObjectPortLock
);
3376 mach_port_name_t name
= 0;
3377 if (from_task
!= current_task())
3378 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3381 map
->userClientUnmap();
3382 err
= iokit_mod_send_right( from_task
, name
, -2 );
3383 err
= kIOReturnSuccess
;
3386 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3387 if (from_task
== current_task())
3391 err
= kIOReturnBadArgument
;
3397 kern_return_t
is_io_connect_unmap_memory(
3398 io_object_t connect
,
3404 mach_vm_address_t address
;
3406 address
= SCALAR64(mapAddr
);
3408 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3414 /* Routine io_connect_add_client */
3415 kern_return_t
is_io_connect_add_client(
3416 io_object_t connection
,
3417 io_object_t connect_to
)
3419 CHECK( IOUserClient
, connection
, client
);
3420 CHECK( IOUserClient
, connect_to
, to
);
3422 IOStatisticsClientCall();
3423 return( client
->connectClient( to
) );
3427 /* Routine io_connect_set_properties */
3428 kern_return_t
is_io_connect_set_properties(
3429 io_object_t connection
,
3430 io_buf_ptr_t properties
,
3431 mach_msg_type_number_t propertiesCnt
,
3432 kern_return_t
* result
)
3434 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3437 /* Routine io_user_client_method */
3438 kern_return_t is_io_connect_method_var_output
3440 io_connect_t connection
,
3442 io_scalar_inband64_t scalar_input
,
3443 mach_msg_type_number_t scalar_inputCnt
,
3444 io_struct_inband_t inband_input
,
3445 mach_msg_type_number_t inband_inputCnt
,
3446 mach_vm_address_t ool_input
,
3447 mach_vm_size_t ool_input_size
,
3448 io_struct_inband_t inband_output
,
3449 mach_msg_type_number_t
*inband_outputCnt
,
3450 io_scalar_inband64_t scalar_output
,
3451 mach_msg_type_number_t
*scalar_outputCnt
,
3452 io_buf_ptr_t
*var_output
,
3453 mach_msg_type_number_t
*var_outputCnt
3456 CHECK( IOUserClient
, connection
, client
);
3458 IOExternalMethodArguments args
;
3460 IOMemoryDescriptor
* inputMD
= 0;
3461 OSObject
* structureVariableOutputData
= 0;
3463 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3464 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3466 args
.selector
= selector
;
3468 args
.asyncWakePort
= MACH_PORT_NULL
;
3469 args
.asyncReference
= 0;
3470 args
.asyncReferenceCount
= 0;
3471 args
.structureVariableOutputData
= &structureVariableOutputData
;
3473 args
.scalarInput
= scalar_input
;
3474 args
.scalarInputCount
= scalar_inputCnt
;
3475 args
.structureInput
= inband_input
;
3476 args
.structureInputSize
= inband_inputCnt
;
3479 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3480 kIODirectionOut
, current_task());
3482 args
.structureInputDescriptor
= inputMD
;
3484 args
.scalarOutput
= scalar_output
;
3485 args
.scalarOutputCount
= *scalar_outputCnt
;
3486 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3487 args
.structureOutput
= inband_output
;
3488 args
.structureOutputSize
= *inband_outputCnt
;
3489 args
.structureOutputDescriptor
= NULL
;
3490 args
.structureOutputDescriptorSize
= 0;
3492 IOStatisticsClientCall();
3493 ret
= client
->externalMethod( selector
, &args
);
3495 *scalar_outputCnt
= args
.scalarOutputCount
;
3496 *inband_outputCnt
= args
.structureOutputSize
;
3498 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3500 OSSerialize
* serialize
;
3504 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3506 len
= serialize
->getLength();
3507 *var_outputCnt
= len
;
3508 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3510 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3512 len
= data
->getLength();
3513 *var_outputCnt
= len
;
3514 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3518 ret
= kIOReturnUnderrun
;
3524 if (structureVariableOutputData
)
3525 structureVariableOutputData
->release();
3530 /* Routine io_user_client_method */
3531 kern_return_t is_io_connect_method
3533 io_connect_t connection
,
3535 io_scalar_inband64_t scalar_input
,
3536 mach_msg_type_number_t scalar_inputCnt
,
3537 io_struct_inband_t inband_input
,
3538 mach_msg_type_number_t inband_inputCnt
,
3539 mach_vm_address_t ool_input
,
3540 mach_vm_size_t ool_input_size
,
3541 io_struct_inband_t inband_output
,
3542 mach_msg_type_number_t
*inband_outputCnt
,
3543 io_scalar_inband64_t scalar_output
,
3544 mach_msg_type_number_t
*scalar_outputCnt
,
3545 mach_vm_address_t ool_output
,
3546 mach_vm_size_t
*ool_output_size
3549 CHECK( IOUserClient
, connection
, client
);
3551 IOExternalMethodArguments args
;
3553 IOMemoryDescriptor
* inputMD
= 0;
3554 IOMemoryDescriptor
* outputMD
= 0;
3556 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3557 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3559 args
.selector
= selector
;
3561 args
.asyncWakePort
= MACH_PORT_NULL
;
3562 args
.asyncReference
= 0;
3563 args
.asyncReferenceCount
= 0;
3564 args
.structureVariableOutputData
= 0;
3566 args
.scalarInput
= scalar_input
;
3567 args
.scalarInputCount
= scalar_inputCnt
;
3568 args
.structureInput
= inband_input
;
3569 args
.structureInputSize
= inband_inputCnt
;
3572 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3573 kIODirectionOut
, current_task());
3575 args
.structureInputDescriptor
= inputMD
;
3577 args
.scalarOutput
= scalar_output
;
3578 args
.scalarOutputCount
= *scalar_outputCnt
;
3579 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3580 args
.structureOutput
= inband_output
;
3581 args
.structureOutputSize
= *inband_outputCnt
;
3583 if (ool_output
&& ool_output_size
)
3585 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3586 kIODirectionIn
, current_task());
3589 args
.structureOutputDescriptor
= outputMD
;
3590 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3592 IOStatisticsClientCall();
3593 ret
= client
->externalMethod( selector
, &args
);
3595 *scalar_outputCnt
= args
.scalarOutputCount
;
3596 *inband_outputCnt
= args
.structureOutputSize
;
3597 *ool_output_size
= args
.structureOutputDescriptorSize
;
3602 outputMD
->release();
3607 /* Routine io_async_user_client_method */
3608 kern_return_t is_io_connect_async_method
3610 io_connect_t connection
,
3611 mach_port_t wake_port
,
3612 io_async_ref64_t reference
,
3613 mach_msg_type_number_t referenceCnt
,
3615 io_scalar_inband64_t scalar_input
,
3616 mach_msg_type_number_t scalar_inputCnt
,
3617 io_struct_inband_t inband_input
,
3618 mach_msg_type_number_t inband_inputCnt
,
3619 mach_vm_address_t ool_input
,
3620 mach_vm_size_t ool_input_size
,
3621 io_struct_inband_t inband_output
,
3622 mach_msg_type_number_t
*inband_outputCnt
,
3623 io_scalar_inband64_t scalar_output
,
3624 mach_msg_type_number_t
*scalar_outputCnt
,
3625 mach_vm_address_t ool_output
,
3626 mach_vm_size_t
* ool_output_size
3629 CHECK( IOUserClient
, connection
, client
);
3631 IOExternalMethodArguments args
;
3633 IOMemoryDescriptor
* inputMD
= 0;
3634 IOMemoryDescriptor
* outputMD
= 0;
3636 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3637 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3639 reference
[0] = (io_user_reference_t
) wake_port
;
3640 if (vm_map_is_64bit(get_task_map(current_task())))
3641 reference
[0] |= kIOUCAsync64Flag
;
3643 args
.selector
= selector
;
3645 args
.asyncWakePort
= wake_port
;
3646 args
.asyncReference
= reference
;
3647 args
.asyncReferenceCount
= referenceCnt
;
3649 args
.scalarInput
= scalar_input
;
3650 args
.scalarInputCount
= scalar_inputCnt
;
3651 args
.structureInput
= inband_input
;
3652 args
.structureInputSize
= inband_inputCnt
;
3655 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3656 kIODirectionOut
, current_task());
3658 args
.structureInputDescriptor
= inputMD
;
3660 args
.scalarOutput
= scalar_output
;
3661 args
.scalarOutputCount
= *scalar_outputCnt
;
3662 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3663 args
.structureOutput
= inband_output
;
3664 args
.structureOutputSize
= *inband_outputCnt
;
3668 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3669 kIODirectionIn
, current_task());
3672 args
.structureOutputDescriptor
= outputMD
;
3673 args
.structureOutputDescriptorSize
= *ool_output_size
;
3675 IOStatisticsClientCall();
3676 ret
= client
->externalMethod( selector
, &args
);
3678 *inband_outputCnt
= args
.structureOutputSize
;
3679 *ool_output_size
= args
.structureOutputDescriptorSize
;
3684 outputMD
->release();
3689 /* Routine io_connect_method_scalarI_scalarO */
3690 kern_return_t
is_io_connect_method_scalarI_scalarO(
3691 io_object_t connect
,
3693 io_scalar_inband_t input
,
3694 mach_msg_type_number_t inputCount
,
3695 io_scalar_inband_t output
,
3696 mach_msg_type_number_t
* outputCount
)
3700 io_scalar_inband64_t _input
;
3701 io_scalar_inband64_t _output
;
3703 mach_msg_type_number_t struct_outputCnt
= 0;
3704 mach_vm_size_t ool_output_size
= 0;
3706 bzero(&_output
[0], sizeof(_output
));
3707 for (i
= 0; i
< inputCount
; i
++)
3708 _input
[i
] = SCALAR64(input
[i
]);
3710 err
= is_io_connect_method(connect
, index
,
3714 NULL
, &struct_outputCnt
,
3715 _output
, outputCount
,
3716 0, &ool_output_size
);
3718 for (i
= 0; i
< *outputCount
; i
++)
3719 output
[i
] = SCALAR32(_output
[i
]);
3724 kern_return_t
shim_io_connect_method_scalarI_scalarO(
3725 IOExternalMethod
* method
,
3727 const io_user_scalar_t
* input
,
3728 mach_msg_type_number_t inputCount
,
3729 io_user_scalar_t
* output
,
3730 mach_msg_type_number_t
* outputCount
)
3733 io_scalar_inband_t _output
;
3735 err
= kIOReturnBadArgument
;
3737 bzero(&_output
[0], sizeof(_output
));
3740 if( inputCount
!= method
->count0
)
3742 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3745 if( *outputCount
!= method
->count1
)
3747 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3751 func
= method
->func
;
3753 switch( inputCount
) {
3756 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3757 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3760 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3761 ARG32(input
[3]), ARG32(input
[4]),
3765 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3767 &_output
[0], &_output
[1] );
3770 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3771 &_output
[0], &_output
[1], &_output
[2] );
3774 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3775 &_output
[0], &_output
[1], &_output
[2],
3779 err
= (object
->*func
)( ARG32(input
[0]),
3780 &_output
[0], &_output
[1], &_output
[2],
3781 &_output
[3], &_output
[4] );
3784 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
3785 &_output
[3], &_output
[4], &_output
[5] );
3789 IOLog("%s: Bad method table\n", object
->getName());
3795 for (i
= 0; i
< *outputCount
; i
++)
3796 output
[i
] = SCALAR32(_output
[i
]);
3801 /* Routine io_async_method_scalarI_scalarO */
3802 kern_return_t
is_io_async_method_scalarI_scalarO(
3803 io_object_t connect
,
3804 mach_port_t wake_port
,
3805 io_async_ref_t reference
,
3806 mach_msg_type_number_t referenceCnt
,
3808 io_scalar_inband_t input
,
3809 mach_msg_type_number_t inputCount
,
3810 io_scalar_inband_t output
,
3811 mach_msg_type_number_t
* outputCount
)
3815 io_scalar_inband64_t _input
;
3816 io_scalar_inband64_t _output
;
3817 io_async_ref64_t _reference
;
3819 bzero(&_output
[0], sizeof(_output
));
3820 for (i
= 0; i
< referenceCnt
; i
++)
3821 _reference
[i
] = REF64(reference
[i
]);
3823 mach_msg_type_number_t struct_outputCnt
= 0;
3824 mach_vm_size_t ool_output_size
= 0;
3826 for (i
= 0; i
< inputCount
; i
++)
3827 _input
[i
] = SCALAR64(input
[i
]);
3829 err
= is_io_connect_async_method(connect
,
3830 wake_port
, _reference
, referenceCnt
,
3835 NULL
, &struct_outputCnt
,
3836 _output
, outputCount
,
3837 0, &ool_output_size
);
3839 for (i
= 0; i
< *outputCount
; i
++)
3840 output
[i
] = SCALAR32(_output
[i
]);
3844 /* Routine io_async_method_scalarI_structureO */
3845 kern_return_t
is_io_async_method_scalarI_structureO(
3846 io_object_t connect
,
3847 mach_port_t wake_port
,
3848 io_async_ref_t reference
,
3849 mach_msg_type_number_t referenceCnt
,
3851 io_scalar_inband_t input
,
3852 mach_msg_type_number_t inputCount
,
3853 io_struct_inband_t output
,
3854 mach_msg_type_number_t
* outputCount
)
3857 io_scalar_inband64_t _input
;
3858 io_async_ref64_t _reference
;
3860 for (i
= 0; i
< referenceCnt
; i
++)
3861 _reference
[i
] = REF64(reference
[i
]);
3863 mach_msg_type_number_t scalar_outputCnt
= 0;
3864 mach_vm_size_t ool_output_size
= 0;
3866 for (i
= 0; i
< inputCount
; i
++)
3867 _input
[i
] = SCALAR64(input
[i
]);
3869 return (is_io_connect_async_method(connect
,
3870 wake_port
, _reference
, referenceCnt
,
3875 output
, outputCount
,
3876 NULL
, &scalar_outputCnt
,
3877 0, &ool_output_size
));
3880 /* Routine io_async_method_scalarI_structureI */
3881 kern_return_t
is_io_async_method_scalarI_structureI(
3882 io_connect_t connect
,
3883 mach_port_t wake_port
,
3884 io_async_ref_t reference
,
3885 mach_msg_type_number_t referenceCnt
,
3887 io_scalar_inband_t input
,
3888 mach_msg_type_number_t inputCount
,
3889 io_struct_inband_t inputStruct
,
3890 mach_msg_type_number_t inputStructCount
)
3893 io_scalar_inband64_t _input
;
3894 io_async_ref64_t _reference
;
3896 for (i
= 0; i
< referenceCnt
; i
++)
3897 _reference
[i
] = REF64(reference
[i
]);
3899 mach_msg_type_number_t scalar_outputCnt
= 0;
3900 mach_msg_type_number_t inband_outputCnt
= 0;
3901 mach_vm_size_t ool_output_size
= 0;
3903 for (i
= 0; i
< inputCount
; i
++)
3904 _input
[i
] = SCALAR64(input
[i
]);
3906 return (is_io_connect_async_method(connect
,
3907 wake_port
, _reference
, referenceCnt
,
3910 inputStruct
, inputStructCount
,
3912 NULL
, &inband_outputCnt
,
3913 NULL
, &scalar_outputCnt
,
3914 0, &ool_output_size
));
3917 /* Routine io_async_method_structureI_structureO */
3918 kern_return_t
is_io_async_method_structureI_structureO(
3919 io_object_t connect
,
3920 mach_port_t wake_port
,
3921 io_async_ref_t reference
,
3922 mach_msg_type_number_t referenceCnt
,
3924 io_struct_inband_t input
,
3925 mach_msg_type_number_t inputCount
,
3926 io_struct_inband_t output
,
3927 mach_msg_type_number_t
* outputCount
)
3930 mach_msg_type_number_t scalar_outputCnt
= 0;
3931 mach_vm_size_t ool_output_size
= 0;
3932 io_async_ref64_t _reference
;
3934 for (i
= 0; i
< referenceCnt
; i
++)
3935 _reference
[i
] = REF64(reference
[i
]);
3937 return (is_io_connect_async_method(connect
,
3938 wake_port
, _reference
, referenceCnt
,
3943 output
, outputCount
,
3944 NULL
, &scalar_outputCnt
,
3945 0, &ool_output_size
));
3949 kern_return_t
shim_io_async_method_scalarI_scalarO(
3950 IOExternalAsyncMethod
* method
,
3952 mach_port_t asyncWakePort
,
3953 io_user_reference_t
* asyncReference
,
3954 uint32_t asyncReferenceCount
,
3955 const io_user_scalar_t
* input
,
3956 mach_msg_type_number_t inputCount
,
3957 io_user_scalar_t
* output
,
3958 mach_msg_type_number_t
* outputCount
)
3962 io_scalar_inband_t _output
;
3964 io_async_ref_t reference
;
3966 bzero(&_output
[0], sizeof(_output
));
3967 for (i
= 0; i
< asyncReferenceCount
; i
++)
3968 reference
[i
] = REF32(asyncReference
[i
]);
3970 err
= kIOReturnBadArgument
;
3974 if( inputCount
!= method
->count0
)
3976 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3979 if( *outputCount
!= method
->count1
)
3981 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3985 func
= method
->func
;
3987 switch( inputCount
) {
3990 err
= (object
->*func
)( reference
,
3991 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3992 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3995 err
= (object
->*func
)( reference
,
3996 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3997 ARG32(input
[3]), ARG32(input
[4]),
4001 err
= (object
->*func
)( reference
,
4002 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4004 &_output
[0], &_output
[1] );
4007 err
= (object
->*func
)( reference
,
4008 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4009 &_output
[0], &_output
[1], &_output
[2] );
4012 err
= (object
->*func
)( reference
,
4013 ARG32(input
[0]), ARG32(input
[1]),
4014 &_output
[0], &_output
[1], &_output
[2],
4018 err
= (object
->*func
)( reference
,
4020 &_output
[0], &_output
[1], &_output
[2],
4021 &_output
[3], &_output
[4] );
4024 err
= (object
->*func
)( reference
,
4025 &_output
[0], &_output
[1], &_output
[2],
4026 &_output
[3], &_output
[4], &_output
[5] );
4030 IOLog("%s: Bad method table\n", object
->getName());
4035 for (i
= 0; i
< *outputCount
; i
++)
4036 output
[i
] = SCALAR32(_output
[i
]);
4042 /* Routine io_connect_method_scalarI_structureO */
4043 kern_return_t
is_io_connect_method_scalarI_structureO(
4044 io_object_t connect
,
4046 io_scalar_inband_t input
,
4047 mach_msg_type_number_t inputCount
,
4048 io_struct_inband_t output
,
4049 mach_msg_type_number_t
* outputCount
)
4052 io_scalar_inband64_t _input
;
4054 mach_msg_type_number_t scalar_outputCnt
= 0;
4055 mach_vm_size_t ool_output_size
= 0;
4057 for (i
= 0; i
< inputCount
; i
++)
4058 _input
[i
] = SCALAR64(input
[i
]);
4060 return (is_io_connect_method(connect
, index
,
4064 output
, outputCount
,
4065 NULL
, &scalar_outputCnt
,
4066 0, &ool_output_size
));
4069 kern_return_t
shim_io_connect_method_scalarI_structureO(
4071 IOExternalMethod
* method
,
4073 const io_user_scalar_t
* input
,
4074 mach_msg_type_number_t inputCount
,
4075 io_struct_inband_t output
,
4076 IOByteCount
* outputCount
)
4081 err
= kIOReturnBadArgument
;
4084 if( inputCount
!= method
->count0
)
4086 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4089 if( (kIOUCVariableStructureSize
!= method
->count1
)
4090 && (*outputCount
!= method
->count1
))
4092 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4096 func
= method
->func
;
4098 switch( inputCount
) {
4101 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4102 ARG32(input
[3]), ARG32(input
[4]),
4106 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4108 output
, (void *)outputCount
);
4111 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4112 output
, (void *)outputCount
, 0 );
4115 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4116 output
, (void *)outputCount
, 0, 0 );
4119 err
= (object
->*func
)( ARG32(input
[0]),
4120 output
, (void *)outputCount
, 0, 0, 0 );
4123 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4127 IOLog("%s: Bad method table\n", object
->getName());
4136 kern_return_t
shim_io_async_method_scalarI_structureO(
4137 IOExternalAsyncMethod
* method
,
4139 mach_port_t asyncWakePort
,
4140 io_user_reference_t
* asyncReference
,
4141 uint32_t asyncReferenceCount
,
4142 const io_user_scalar_t
* input
,
4143 mach_msg_type_number_t inputCount
,
4144 io_struct_inband_t output
,
4145 mach_msg_type_number_t
* outputCount
)
4150 io_async_ref_t reference
;
4152 for (i
= 0; i
< asyncReferenceCount
; i
++)
4153 reference
[i
] = REF32(asyncReference
[i
]);
4155 err
= kIOReturnBadArgument
;
4157 if( inputCount
!= method
->count0
)
4159 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4162 if( (kIOUCVariableStructureSize
!= method
->count1
)
4163 && (*outputCount
!= method
->count1
))
4165 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4169 func
= method
->func
;
4171 switch( inputCount
) {
4174 err
= (object
->*func
)( reference
,
4175 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4176 ARG32(input
[3]), ARG32(input
[4]),
4180 err
= (object
->*func
)( reference
,
4181 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4183 output
, (void *)outputCount
);
4186 err
= (object
->*func
)( reference
,
4187 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4188 output
, (void *)outputCount
, 0 );
4191 err
= (object
->*func
)( reference
,
4192 ARG32(input
[0]), ARG32(input
[1]),
4193 output
, (void *)outputCount
, 0, 0 );
4196 err
= (object
->*func
)( reference
,
4198 output
, (void *)outputCount
, 0, 0, 0 );
4201 err
= (object
->*func
)( reference
,
4202 output
, (void *)outputCount
, 0, 0, 0, 0 );
4206 IOLog("%s: Bad method table\n", object
->getName());
4214 /* Routine io_connect_method_scalarI_structureI */
4215 kern_return_t
is_io_connect_method_scalarI_structureI(
4216 io_connect_t connect
,
4218 io_scalar_inband_t input
,
4219 mach_msg_type_number_t inputCount
,
4220 io_struct_inband_t inputStruct
,
4221 mach_msg_type_number_t inputStructCount
)
4224 io_scalar_inband64_t _input
;
4226 mach_msg_type_number_t scalar_outputCnt
= 0;
4227 mach_msg_type_number_t inband_outputCnt
= 0;
4228 mach_vm_size_t ool_output_size
= 0;
4230 for (i
= 0; i
< inputCount
; i
++)
4231 _input
[i
] = SCALAR64(input
[i
]);
4233 return (is_io_connect_method(connect
, index
,
4235 inputStruct
, inputStructCount
,
4237 NULL
, &inband_outputCnt
,
4238 NULL
, &scalar_outputCnt
,
4239 0, &ool_output_size
));
4242 kern_return_t
shim_io_connect_method_scalarI_structureI(
4243 IOExternalMethod
* method
,
4245 const io_user_scalar_t
* input
,
4246 mach_msg_type_number_t inputCount
,
4247 io_struct_inband_t inputStruct
,
4248 mach_msg_type_number_t inputStructCount
)
4251 IOReturn err
= kIOReturnBadArgument
;
4255 if (inputCount
!= method
->count0
)
4257 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4260 if( (kIOUCVariableStructureSize
!= method
->count1
)
4261 && (inputStructCount
!= method
->count1
))
4263 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4267 func
= method
->func
;
4269 switch( inputCount
) {
4272 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4273 ARG32(input
[3]), ARG32(input
[4]),
4277 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4279 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4282 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4283 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4287 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4288 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4292 err
= (object
->*func
)( ARG32(input
[0]),
4293 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4297 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4302 IOLog("%s: Bad method table\n", object
->getName());
4310 kern_return_t
shim_io_async_method_scalarI_structureI(
4311 IOExternalAsyncMethod
* method
,
4313 mach_port_t asyncWakePort
,
4314 io_user_reference_t
* asyncReference
,
4315 uint32_t asyncReferenceCount
,
4316 const io_user_scalar_t
* input
,
4317 mach_msg_type_number_t inputCount
,
4318 io_struct_inband_t inputStruct
,
4319 mach_msg_type_number_t inputStructCount
)
4323 IOReturn err
= kIOReturnBadArgument
;
4324 io_async_ref_t reference
;
4326 for (i
= 0; i
< asyncReferenceCount
; i
++)
4327 reference
[i
] = REF32(asyncReference
[i
]);
4331 if (inputCount
!= method
->count0
)
4333 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4336 if( (kIOUCVariableStructureSize
!= method
->count1
)
4337 && (inputStructCount
!= method
->count1
))
4339 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4343 func
= method
->func
;
4345 switch( inputCount
) {
4348 err
= (object
->*func
)( reference
,
4349 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4350 ARG32(input
[3]), ARG32(input
[4]),
4354 err
= (object
->*func
)( reference
,
4355 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4357 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4360 err
= (object
->*func
)( reference
,
4361 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4362 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4366 err
= (object
->*func
)( reference
,
4367 ARG32(input
[0]), ARG32(input
[1]),
4368 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4372 err
= (object
->*func
)( reference
,
4374 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4378 err
= (object
->*func
)( reference
,
4379 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4384 IOLog("%s: Bad method table\n", object
->getName());
4392 /* Routine io_connect_method_structureI_structureO */
4393 kern_return_t
is_io_connect_method_structureI_structureO(
4394 io_object_t connect
,
4396 io_struct_inband_t input
,
4397 mach_msg_type_number_t inputCount
,
4398 io_struct_inband_t output
,
4399 mach_msg_type_number_t
* outputCount
)
4401 mach_msg_type_number_t scalar_outputCnt
= 0;
4402 mach_vm_size_t ool_output_size
= 0;
4404 return (is_io_connect_method(connect
, index
,
4408 output
, outputCount
,
4409 NULL
, &scalar_outputCnt
,
4410 0, &ool_output_size
));
4413 kern_return_t
shim_io_connect_method_structureI_structureO(
4414 IOExternalMethod
* method
,
4416 io_struct_inband_t input
,
4417 mach_msg_type_number_t inputCount
,
4418 io_struct_inband_t output
,
4419 IOByteCount
* outputCount
)
4422 IOReturn err
= kIOReturnBadArgument
;
4426 if( (kIOUCVariableStructureSize
!= method
->count0
)
4427 && (inputCount
!= method
->count0
))
4429 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4432 if( (kIOUCVariableStructureSize
!= method
->count1
)
4433 && (*outputCount
!= method
->count1
))
4435 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4439 func
= method
->func
;
4441 if( method
->count1
) {
4442 if( method
->count0
) {
4443 err
= (object
->*func
)( input
, output
,
4444 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4446 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4449 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4458 kern_return_t
shim_io_async_method_structureI_structureO(
4459 IOExternalAsyncMethod
* method
,
4461 mach_port_t asyncWakePort
,
4462 io_user_reference_t
* asyncReference
,
4463 uint32_t asyncReferenceCount
,
4464 io_struct_inband_t input
,
4465 mach_msg_type_number_t inputCount
,
4466 io_struct_inband_t output
,
4467 mach_msg_type_number_t
* outputCount
)
4472 io_async_ref_t reference
;
4474 for (i
= 0; i
< asyncReferenceCount
; i
++)
4475 reference
[i
] = REF32(asyncReference
[i
]);
4477 err
= kIOReturnBadArgument
;
4480 if( (kIOUCVariableStructureSize
!= method
->count0
)
4481 && (inputCount
!= method
->count0
))
4483 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4486 if( (kIOUCVariableStructureSize
!= method
->count1
)
4487 && (*outputCount
!= method
->count1
))
4489 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4493 func
= method
->func
;
4495 if( method
->count1
) {
4496 if( method
->count0
) {
4497 err
= (object
->*func
)( reference
,
4499 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4501 err
= (object
->*func
)( reference
,
4502 output
, outputCount
, 0, 0, 0, 0 );
4505 err
= (object
->*func
)( reference
,
4506 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4514 /* Routine io_catalog_send_data */
4515 kern_return_t
is_io_catalog_send_data(
4516 mach_port_t master_port
,
4518 io_buf_ptr_t inData
,
4519 mach_msg_type_number_t inDataCount
,
4520 kern_return_t
* result
)
4524 kern_return_t kr
= kIOReturnError
;
4526 //printf("io_catalog_send_data called. flag: %d\n", flag);
4528 if( master_port
!= master_device_port
)
4529 return kIOReturnNotPrivileged
;
4531 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4532 flag
!= kIOCatalogKextdActive
&&
4533 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4534 ( !inData
|| !inDataCount
) )
4536 return kIOReturnBadArgument
;
4540 vm_map_offset_t map_data
;
4542 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4543 return( kIOReturnMessageTooLarge
);
4545 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4546 data
= CAST_DOWN(vm_offset_t
, map_data
);
4548 if( kr
!= KERN_SUCCESS
)
4551 // must return success after vm_map_copyout() succeeds
4554 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4555 vm_deallocate( kernel_map
, data
, inDataCount
);
4557 *result
= kIOReturnNoMemory
;
4558 return( KERN_SUCCESS
);
4564 case kIOCatalogResetDrivers
:
4565 case kIOCatalogResetDriversNoMatch
: {
4568 array
= OSDynamicCast(OSArray
, obj
);
4570 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4571 flag
== kIOCatalogResetDrivers
) ) {
4573 kr
= kIOReturnError
;
4576 kr
= kIOReturnBadArgument
;
4581 case kIOCatalogAddDrivers
:
4582 case kIOCatalogAddDriversNoMatch
: {
4585 array
= OSDynamicCast(OSArray
, obj
);
4587 if ( !gIOCatalogue
->addDrivers( array
,
4588 flag
== kIOCatalogAddDrivers
) ) {
4589 kr
= kIOReturnError
;
4593 kr
= kIOReturnBadArgument
;
4598 case kIOCatalogRemoveDrivers
:
4599 case kIOCatalogRemoveDriversNoMatch
: {
4600 OSDictionary
* dict
;
4602 dict
= OSDynamicCast(OSDictionary
, obj
);
4604 if ( !gIOCatalogue
->removeDrivers( dict
,
4605 flag
== kIOCatalogRemoveDrivers
) ) {
4606 kr
= kIOReturnError
;
4610 kr
= kIOReturnBadArgument
;
4615 case kIOCatalogStartMatching
: {
4616 OSDictionary
* dict
;
4618 dict
= OSDynamicCast(OSDictionary
, obj
);
4620 if ( !gIOCatalogue
->startMatching( dict
) ) {
4621 kr
= kIOReturnError
;
4625 kr
= kIOReturnBadArgument
;
4630 case kIOCatalogRemoveKernelLinker
:
4631 kr
= KERN_NOT_SUPPORTED
;
4634 case kIOCatalogKextdActive
:
4636 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
4637 OSKext::setKextdActive();
4639 /* Dump all nonloaded startup extensions; kextd will now send them
4642 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4644 kr
= kIOReturnSuccess
;
4647 case kIOCatalogKextdFinishedLaunching
: {
4649 static bool clearedBusy
= false;
4652 IOService
* serviceRoot
= IOService::getServiceRoot();
4654 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
4655 serviceRoot
->adjustBusy(-1);
4660 kr
= kIOReturnSuccess
;
4665 kr
= kIOReturnBadArgument
;
4669 if (obj
) obj
->release();
4672 return( KERN_SUCCESS
);
4675 /* Routine io_catalog_terminate */
4676 kern_return_t
is_io_catalog_terminate(
4677 mach_port_t master_port
,
4683 if( master_port
!= master_device_port
)
4684 return kIOReturnNotPrivileged
;
4686 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
4687 kIOClientPrivilegeAdministrator
);
4688 if( kIOReturnSuccess
!= kr
)
4692 #if !defined(SECURE_KERNEL)
4693 case kIOCatalogServiceTerminate
:
4695 IOService
* service
;
4697 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
4698 kIORegistryIterateRecursively
);
4700 return kIOReturnNoMemory
;
4704 while( (service
= (IOService
*)iter
->getNextObject()) ) {
4705 if( service
->metaCast(name
)) {
4706 if ( !service
->terminate( kIOServiceRequired
4707 | kIOServiceSynchronous
) ) {
4708 kr
= kIOReturnUnsupported
;
4713 } while( !service
&& !iter
->isValid());
4717 case kIOCatalogModuleUnload
:
4718 case kIOCatalogModuleTerminate
:
4719 kr
= gIOCatalogue
->terminateDriversForModule(name
,
4720 flag
== kIOCatalogModuleUnload
);
4725 kr
= kIOReturnBadArgument
;
4732 /* Routine io_catalog_get_data */
4733 kern_return_t
is_io_catalog_get_data(
4734 mach_port_t master_port
,
4736 io_buf_ptr_t
*outData
,
4737 mach_msg_type_number_t
*outDataCount
)
4739 kern_return_t kr
= kIOReturnSuccess
;
4742 if( master_port
!= master_device_port
)
4743 return kIOReturnNotPrivileged
;
4745 //printf("io_catalog_get_data called. flag: %d\n", flag);
4747 s
= OSSerialize::withCapacity(4096);
4749 return kIOReturnNoMemory
;
4751 kr
= gIOCatalogue
->serializeData(flag
, s
);
4753 if ( kr
== kIOReturnSuccess
) {
4758 size
= s
->getLength();
4759 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
4760 if ( kr
== kIOReturnSuccess
) {
4761 bcopy(s
->text(), (void *)data
, size
);
4762 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
4763 (vm_map_size_t
)size
, true, ©
);
4764 *outData
= (char *)copy
;
4765 *outDataCount
= size
;
4774 /* Routine io_catalog_get_gen_count */
4775 kern_return_t
is_io_catalog_get_gen_count(
4776 mach_port_t master_port
,
4779 if( master_port
!= master_device_port
)
4780 return kIOReturnNotPrivileged
;
4782 //printf("io_catalog_get_gen_count called.\n");
4785 return kIOReturnBadArgument
;
4787 *genCount
= gIOCatalogue
->getGenerationCount();
4789 return kIOReturnSuccess
;
4792 /* Routine io_catalog_module_loaded.
4793 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
4795 kern_return_t
is_io_catalog_module_loaded(
4796 mach_port_t master_port
,
4799 if( master_port
!= master_device_port
)
4800 return kIOReturnNotPrivileged
;
4802 //printf("io_catalog_module_loaded called. name %s\n", name);
4805 return kIOReturnBadArgument
;
4807 gIOCatalogue
->moduleHasLoaded(name
);
4809 return kIOReturnSuccess
;
4812 kern_return_t
is_io_catalog_reset(
4813 mach_port_t master_port
,
4816 if( master_port
!= master_device_port
)
4817 return kIOReturnNotPrivileged
;
4820 case kIOCatalogResetDefault
:
4821 gIOCatalogue
->reset();
4825 return kIOReturnBadArgument
;
4828 return kIOReturnSuccess
;
4831 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
4833 kern_return_t result
= kIOReturnBadArgument
;
4834 IOUserClient
*userClient
;
4836 if ((userClient
= OSDynamicCast(IOUserClient
,
4837 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
4838 IOExternalTrap
*trap
;
4839 IOService
*target
= NULL
;
4841 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
4843 if (trap
&& target
) {
4849 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
4853 userClient
->release();
4861 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
4862 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
4866 IOByteCount structureOutputSize
;
4871 count
= dispatch
->checkScalarInputCount
;
4872 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
4874 return (kIOReturnBadArgument
);
4877 count
= dispatch
->checkStructureInputSize
;
4878 if ((kIOUCVariableStructureSize
!= count
)
4879 && (count
!= ((args
->structureInputDescriptor
)
4880 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
4882 return (kIOReturnBadArgument
);
4885 count
= dispatch
->checkScalarOutputCount
;
4886 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
4888 return (kIOReturnBadArgument
);
4891 count
= dispatch
->checkStructureOutputSize
;
4892 if ((kIOUCVariableStructureSize
!= count
)
4893 && (count
!= ((args
->structureOutputDescriptor
)
4894 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
4896 return (kIOReturnBadArgument
);
4899 if (dispatch
->function
)
4900 err
= (*dispatch
->function
)(target
, reference
, args
);
4902 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
4908 // pre-Leopard API's don't do ool structs
4909 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
4911 err
= kIOReturnIPCError
;
4915 structureOutputSize
= args
->structureOutputSize
;
4917 if (args
->asyncWakePort
)
4919 IOExternalAsyncMethod
* method
;
4921 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
4922 return (kIOReturnUnsupported
);
4924 if (kIOUCForegroundOnly
& method
->flags
)
4926 if (task_is_gpu_denied(current_task()))
4927 return (kIOReturnNotPermitted
);
4930 switch (method
->flags
& kIOUCTypeMask
)
4932 case kIOUCScalarIStructI
:
4933 err
= shim_io_async_method_scalarI_structureI( method
, object
,
4934 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4935 args
->scalarInput
, args
->scalarInputCount
,
4936 (char *)args
->structureInput
, args
->structureInputSize
);
4939 case kIOUCScalarIScalarO
:
4940 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
4941 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4942 args
->scalarInput
, args
->scalarInputCount
,
4943 args
->scalarOutput
, &args
->scalarOutputCount
);
4946 case kIOUCScalarIStructO
:
4947 err
= shim_io_async_method_scalarI_structureO( method
, object
,
4948 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4949 args
->scalarInput
, args
->scalarInputCount
,
4950 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4954 case kIOUCStructIStructO
:
4955 err
= shim_io_async_method_structureI_structureO( method
, object
,
4956 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4957 (char *)args
->structureInput
, args
->structureInputSize
,
4958 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4962 err
= kIOReturnBadArgument
;
4968 IOExternalMethod
* method
;
4970 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
4971 return (kIOReturnUnsupported
);
4973 if (kIOUCForegroundOnly
& method
->flags
)
4975 if (task_is_gpu_denied(current_task()))
4976 return (kIOReturnNotPermitted
);
4979 switch (method
->flags
& kIOUCTypeMask
)
4981 case kIOUCScalarIStructI
:
4982 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
4983 args
->scalarInput
, args
->scalarInputCount
,
4984 (char *) args
->structureInput
, args
->structureInputSize
);
4987 case kIOUCScalarIScalarO
:
4988 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
4989 args
->scalarInput
, args
->scalarInputCount
,
4990 args
->scalarOutput
, &args
->scalarOutputCount
);
4993 case kIOUCScalarIStructO
:
4994 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
4995 args
->scalarInput
, args
->scalarInputCount
,
4996 (char *) args
->structureOutput
, &structureOutputSize
);
5000 case kIOUCStructIStructO
:
5001 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5002 (char *) args
->structureInput
, args
->structureInputSize
,
5003 (char *) args
->structureOutput
, &structureOutputSize
);
5007 err
= kIOReturnBadArgument
;
5012 args
->structureOutputSize
= structureOutputSize
;
5019 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5020 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5022 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5023 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5025 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5026 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5027 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5028 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5029 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5030 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5031 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5032 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5033 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5034 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5035 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5036 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5037 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5038 OSMetaClassDefineReservedUnused(IOUserClient
, 15);