2 * Copyright (c) 1998-2008 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 <libkern/OSDebug.h>
43 #include <IOKit/assert.h>
45 #include "IOServicePrivate.h"
46 #include "IOKitKernelInternal.h"
48 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
49 #define SCALAR32(x) ((uint32_t )x)
50 #define ARG32(x) ((void *)SCALAR32(x))
51 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
52 #define REF32(x) ((int)(x))
56 kIOUCAsync0Flags
= 3ULL,
57 kIOUCAsync64Flag
= 1ULL
60 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
62 // definitions we should get from osfmk
64 //typedef struct ipc_port * ipc_port_t;
65 typedef natural_t ipc_kobject_type_t
;
67 #define IKOT_IOKIT_SPARE 27
68 #define IKOT_IOKIT_CONNECT 29
69 #define IKOT_IOKIT_OBJECT 30
73 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
74 ipc_kobject_type_t type
);
76 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
78 extern mach_port_name_t
iokit_make_send_right( task_t task
,
79 io_object_t obj
, ipc_kobject_type_t type
);
81 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
83 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
85 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
87 extern ipc_port_t master_device_port
;
89 extern void iokit_retain_port( ipc_port_t port
);
90 extern void iokit_release_port( ipc_port_t port
);
91 extern void iokit_release_port_send( ipc_port_t port
);
93 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
95 #include <mach/mach_traps.h>
96 #include <vm/vm_map.h>
101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
105 class IOMachPort
: public OSObject
107 OSDeclareDefaultStructors(IOMachPort
)
114 static IOMachPort
* portForObject( OSObject
* obj
,
115 ipc_kobject_type_t type
);
116 static bool noMoreSendersForObject( OSObject
* obj
,
117 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
118 static void releasePortForObject( OSObject
* obj
,
119 ipc_kobject_type_t type
);
120 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
122 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
124 static mach_port_name_t
makeSendRightForTask( task_t task
,
125 io_object_t obj
, ipc_kobject_type_t type
);
130 #define super OSObject
131 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
133 static IOLock
* gIOObjectPortLock
;
135 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
137 // not in dictForType() for debugging ease
138 static OSDictionary
* gIOObjectPorts
;
139 static OSDictionary
* gIOConnectPorts
;
141 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
143 OSDictionary
** dict
;
145 if( IKOT_IOKIT_OBJECT
== type
)
146 dict
= &gIOObjectPorts
;
147 else if( IKOT_IOKIT_CONNECT
== type
)
148 dict
= &gIOConnectPorts
;
153 *dict
= OSDictionary::withCapacity( 1 );
158 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
159 ipc_kobject_type_t type
)
161 IOMachPort
* inst
= 0;
164 IOTakeLock( gIOObjectPortLock
);
168 dict
= dictForType( type
);
172 if( (inst
= (IOMachPort
*)
173 dict
->getObject( (const OSSymbol
*) obj
))) {
179 inst
= new IOMachPort
;
180 if( inst
&& !inst
->init()) {
185 inst
->port
= iokit_alloc_object_port( obj
, type
);
188 dict
->setObject( (const OSSymbol
*) obj
, inst
);
198 IOUnlock( gIOObjectPortLock
);
203 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
204 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
207 IOMachPort
* machPort
;
208 bool destroyed
= true;
210 IOTakeLock( gIOObjectPortLock
);
212 if( (dict
= dictForType( type
))) {
215 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
217 destroyed
= (machPort
->mscount
<= *mscount
);
219 dict
->removeObject( (const OSSymbol
*) obj
);
221 *mscount
= machPort
->mscount
;
226 IOUnlock( gIOObjectPortLock
);
231 void IOMachPort::releasePortForObject( OSObject
* obj
,
232 ipc_kobject_type_t type
)
235 IOMachPort
* machPort
;
237 IOTakeLock( gIOObjectPortLock
);
239 if( (dict
= dictForType( type
))) {
241 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
242 if( machPort
&& !machPort
->holdDestroy
)
243 dict
->removeObject( (const OSSymbol
*) obj
);
247 IOUnlock( gIOObjectPortLock
);
250 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
253 IOMachPort
* machPort
;
255 IOLockLock( gIOObjectPortLock
);
257 if( (dict
= dictForType( type
))) {
258 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
260 machPort
->holdDestroy
= true;
263 IOLockUnlock( gIOObjectPortLock
);
266 void IOUserClient::destroyUserReferences( OSObject
* obj
)
268 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
271 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
275 IOTakeLock( gIOObjectPortLock
);
278 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
281 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
285 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
287 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
288 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
290 uc
->mappings
->release();
293 dict
->removeObject( (const OSSymbol
*) obj
);
297 IOUnlock( gIOObjectPortLock
);
300 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
301 io_object_t obj
, ipc_kobject_type_t type
)
303 return( iokit_make_send_right( task
, obj
, type
));
306 void IOMachPort::free( void )
309 iokit_destroy_object_port( port
);
313 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
315 class IOUserNotification
: public OSIterator
317 OSDeclareDefaultStructors(IOUserNotification
)
319 IONotifier
* holdNotify
;
324 virtual bool init( void );
327 virtual void setNotification( IONotifier
* obj
);
329 virtual void reset();
330 virtual bool isValid();
333 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
337 // functions called from osfmk/device/iokit_rpc.c
340 iokit_add_reference( io_object_t obj
)
347 iokit_remove_reference( io_object_t obj
)
354 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
356 IOMachPort
* machPort
;
359 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
361 port
= machPort
->port
;
363 iokit_retain_port( port
);
374 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
375 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
377 IOUserClient
* client
;
379 IOUserNotification
* notify
;
381 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
382 return( kIOReturnNotReady
);
384 if( IKOT_IOKIT_CONNECT
== type
)
386 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
387 client
->clientDied();
389 else if( IKOT_IOKIT_OBJECT
== type
)
391 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
393 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
394 notify
->setNotification( 0 );
397 return( kIOReturnSuccess
);
402 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
404 class IOServiceUserNotification
: public IOUserNotification
406 OSDeclareDefaultStructors(IOServiceUserNotification
)
409 mach_msg_header_t msgHdr
;
410 OSNotificationHeader64 notifyHeader
;
413 enum { kMaxOutstanding
= 1024 };
418 OSObject
* lastEntry
;
423 virtual bool init( mach_port_t port
, natural_t type
,
424 void * reference
, vm_size_t referenceSize
,
428 static bool _handler( void * target
,
429 void * ref
, IOService
* newService
, IONotifier
* notifier
);
430 virtual bool handler( void * ref
, IOService
* newService
);
432 virtual OSObject
* getNextObject();
435 class IOServiceMessageUserNotification
: public IOUserNotification
437 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
440 mach_msg_header_t msgHdr
;
441 mach_msg_body_t msgBody
;
442 mach_msg_port_descriptor_t ports
[1];
443 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
453 virtual bool init( mach_port_t port
, natural_t type
,
454 void * reference
, vm_size_t referenceSize
,
460 static IOReturn
_handler( void * target
, void * ref
,
461 UInt32 messageType
, IOService
* provider
,
462 void * messageArgument
, vm_size_t argSize
);
463 virtual IOReturn
handler( void * ref
,
464 UInt32 messageType
, IOService
* provider
,
465 void * messageArgument
, vm_size_t argSize
);
467 virtual OSObject
* getNextObject();
470 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
473 #define super OSIterator
474 OSDefineMetaClass( IOUserNotification
, OSIterator
)
475 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
477 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
479 bool IOUserNotification::init( void )
484 lock
= IOLockAlloc();
491 void IOUserNotification::free( void )
494 holdNotify
->remove();
495 // can't be in handler now
504 void IOUserNotification::setNotification( IONotifier
* notify
)
506 IONotifier
* previousNotify
;
508 IOLockLock( gIOObjectPortLock
);
510 previousNotify
= holdNotify
;
513 IOLockUnlock( gIOObjectPortLock
);
516 previousNotify
->remove();
519 void IOUserNotification::reset()
524 bool IOUserNotification::isValid()
529 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
532 #define super IOUserNotification
533 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
535 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
537 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
538 void * reference
, vm_size_t referenceSize
,
541 newSet
= OSArray::withCapacity( 1 );
545 if (referenceSize
> sizeof(OSAsyncReference64
))
548 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
549 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
553 bzero( pingMsg
, msgSize
);
555 pingMsg
->msgHdr
.msgh_remote_port
= port
;
556 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
557 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
558 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
559 pingMsg
->msgHdr
.msgh_size
= msgSize
;
560 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
562 pingMsg
->notifyHeader
.size
= 0;
563 pingMsg
->notifyHeader
.type
= type
;
564 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
566 return( super::init() );
569 void IOServiceUserNotification::free( void )
574 OSObject
* _lastEntry
;
578 _lastEntry
= lastEntry
;
583 if( _pingMsg
&& _msgSize
)
584 IOFree( _pingMsg
, _msgSize
);
587 _lastEntry
->release();
593 bool IOServiceUserNotification::_handler( void * target
,
594 void * ref
, IOService
* newService
, IONotifier
* notifier
)
596 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
599 bool IOServiceUserNotification::handler( void * ref
,
600 IOService
* newService
)
604 ipc_port_t port
= NULL
;
605 bool sendPing
= false;
609 count
= newSet
->getCount();
610 if( count
< kMaxOutstanding
) {
612 newSet
->setObject( newService
);
613 if( (sendPing
= (armed
&& (0 == count
))))
619 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
620 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
623 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
624 pingMsg
->msgHdr
.msgh_local_port
= port
;
626 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
628 kr
= mach_msg_send_from_kernel_proper( &pingMsg
->msgHdr
,
629 pingMsg
->msgHdr
.msgh_size
);
631 iokit_release_port( port
);
633 if( KERN_SUCCESS
!= kr
)
634 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
640 OSObject
* IOServiceUserNotification::getNextObject()
648 lastEntry
->release();
650 count
= newSet
->getCount();
652 result
= newSet
->getObject( count
- 1 );
654 newSet
->removeObject( count
- 1);
666 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
668 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
670 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
672 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
673 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
677 if (referenceSize
> sizeof(OSAsyncReference64
))
680 clientIs64
= client64
;
682 owningPID
= proc_selfpid();
684 extraSize
+= sizeof(IOServiceInterestContent64
);
685 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
+ extraSize
;
686 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
690 bzero( pingMsg
, msgSize
);
692 pingMsg
->msgHdr
.msgh_remote_port
= port
;
693 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
695 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
696 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
697 pingMsg
->msgHdr
.msgh_size
= msgSize
;
698 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
700 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
702 pingMsg
->ports
[0].name
= 0;
703 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
704 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
706 pingMsg
->notifyHeader
.size
= extraSize
;
707 pingMsg
->notifyHeader
.type
= type
;
708 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
710 return( super::init() );
713 void IOServiceMessageUserNotification::free( void )
723 if( _pingMsg
&& _msgSize
)
724 IOFree( _pingMsg
, _msgSize
);
727 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
728 UInt32 messageType
, IOService
* provider
,
729 void * argument
, vm_size_t argSize
)
731 return( ((IOServiceMessageUserNotification
*) target
)->handler(
732 ref
, messageType
, provider
, argument
, argSize
));
735 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
736 UInt32 messageType
, IOService
* provider
,
737 void * messageArgument
, vm_size_t argSize
)
740 ipc_port_t thisPort
, providerPort
;
741 IOServiceInterestContent64
* data
= (IOServiceInterestContent64
*)
742 ((((uint8_t *) pingMsg
) + msgSize
) - pingMsg
->notifyHeader
.size
);
743 // == pingMsg->notifyHeader.content;
745 if (kIOMessageCopyClientID
== messageType
)
747 *((void **) messageArgument
) = IOCopyLogNameForPID(owningPID
);
748 return (kIOReturnSuccess
);
751 data
->messageType
= messageType
;
755 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
757 argSize
= sizeof(data
->messageArgument
[0]);
760 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
761 argSize
= sizeof(uint32_t);
766 if( argSize
> kIOUserNotifyMaxMessageSize
)
767 argSize
= kIOUserNotifyMaxMessageSize
;
768 bcopy( messageArgument
, data
->messageArgument
, argSize
);
770 pingMsg
->msgHdr
.msgh_size
= msgSize
- pingMsg
->notifyHeader
.size
771 + sizeof( IOServiceInterestContent64
)
772 - sizeof( data
->messageArgument
)
775 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
776 pingMsg
->ports
[0].name
= providerPort
;
777 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
778 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
779 kr
= mach_msg_send_from_kernel_proper( &pingMsg
->msgHdr
,
780 pingMsg
->msgHdr
.msgh_size
);
782 iokit_release_port( thisPort
);
784 iokit_release_port( providerPort
);
786 if( KERN_SUCCESS
!= kr
)
787 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
789 return( kIOReturnSuccess
);
792 OSObject
* IOServiceMessageUserNotification::getNextObject()
797 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
800 #define super IOService
801 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
803 void IOUserClient::initialize( void )
805 gIOObjectPortLock
= IOLockAlloc();
807 assert( gIOObjectPortLock
);
810 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
811 mach_port_t wakePort
,
812 void *callback
, void *refcon
)
814 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
815 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
816 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
817 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
820 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
821 mach_port_t wakePort
,
822 mach_vm_address_t callback
, io_user_reference_t refcon
)
824 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
825 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
826 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
827 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
830 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
833 OSDictionary
* user
= 0;
835 if ((array
= OSDynamicCast(OSArray
,
836 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
838 for (unsigned int idx
= 0;
839 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
843 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
844 && (uid
== num
->unsigned32BitValue())) {
854 static bool IOUCIsBackgroundTask(task_t task
, bool * isBg
)
857 task_category_policy_data_t info
;
858 mach_msg_type_number_t count
= TASK_CATEGORY_POLICY_COUNT
;
859 boolean_t get_default
= false;
861 kr
= task_policy_get(current_task(),
862 TASK_CATEGORY_POLICY
,
863 (task_policy_t
) &info
,
867 *isBg
= ((KERN_SUCCESS
== kr
) && (info
.role
== TASK_THROTTLE_APPLICATION
));
871 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
872 const char * privilegeName
)
875 security_token_t token
;
876 mach_msg_type_number_t count
;
882 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
883 sizeof(kIOClientPrivilegeForeground
)))
886 kern_return_t kr
= IOUCIsBackgroundTask(current_task(), &isBg
);
888 if (KERN_SUCCESS
!= kr
)
890 return (isBg
? kIOReturnNotPrivileged
: kIOReturnSuccess
);
893 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
894 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
895 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
897 task
= (task_t
)securityToken
;
899 count
= TASK_SECURITY_TOKEN_COUNT
;
900 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
902 if (KERN_SUCCESS
!= kr
)
904 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
905 sizeof(kIOClientPrivilegeAdministrator
))) {
906 if (0 != token
.val
[0])
907 kr
= kIOReturnNotPrivileged
;
908 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
909 sizeof(kIOClientPrivilegeLocalUser
))) {
910 user
= CopyConsoleUser(token
.val
[0]);
914 kr
= kIOReturnNotPrivileged
;
915 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
916 sizeof(kIOClientPrivilegeConsoleUser
))) {
917 user
= CopyConsoleUser(token
.val
[0]);
919 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
920 kr
= kIOReturnNotPrivileged
;
921 else if ( secureConsole
) {
922 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
923 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
924 kr
= kIOReturnNotPrivileged
;
929 kr
= kIOReturnNotPrivileged
;
931 kr
= kIOReturnUnsupported
;
936 bool IOUserClient::init()
938 if( getPropertyTable())
941 return super::init();
944 bool IOUserClient::init(OSDictionary
* dictionary
)
946 if( getPropertyTable())
949 return super::init(dictionary
);
952 bool IOUserClient::initWithTask(task_t owningTask
,
956 if( getPropertyTable())
959 return super::init();
962 bool IOUserClient::initWithTask(task_t owningTask
,
965 OSDictionary
* properties
)
969 ok
= super::init( properties
);
970 ok
&= initWithTask( owningTask
, securityID
, type
);
975 void IOUserClient::free()
983 IOReturn
IOUserClient::clientDied( void )
985 return( clientClose());
988 IOReturn
IOUserClient::clientClose( void )
990 return( kIOReturnUnsupported
);
993 IOService
* IOUserClient::getService( void )
998 IOReturn
IOUserClient::registerNotificationPort(
999 mach_port_t
/* port */,
1001 UInt32
/* refCon */)
1003 return( kIOReturnUnsupported
);
1006 IOReturn
IOUserClient::registerNotificationPort(
1009 io_user_reference_t refCon
)
1011 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1014 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1015 semaphore_t
* semaphore
)
1017 return( kIOReturnUnsupported
);
1020 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1022 return( kIOReturnUnsupported
);
1025 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1026 IOOptionBits
* options
,
1027 IOMemoryDescriptor
** memory
)
1029 return( kIOReturnUnsupported
);
1033 IOMemoryMap
* IOUserClient::mapClientMemory(
1036 IOOptionBits mapFlags
,
1037 IOVirtualAddress atAddress
)
1043 IOMemoryMap
* IOUserClient::mapClientMemory64(
1046 IOOptionBits mapFlags
,
1047 mach_vm_address_t atAddress
)
1050 IOOptionBits options
= 0;
1051 IOMemoryDescriptor
* memory
;
1052 IOMemoryMap
* map
= 0;
1054 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1056 if( memory
&& (kIOReturnSuccess
== err
)) {
1058 options
= (options
& ~kIOMapUserOptionsMask
)
1059 | (mapFlags
& kIOMapUserOptionsMask
);
1060 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1067 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1068 OSObject
*obj
, io_object_t
*clientObj
)
1070 mach_port_name_t name
;
1072 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1075 *(mach_port_name_t
*)clientObj
= name
;
1076 return kIOReturnSuccess
;
1079 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1084 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1089 IOExternalMethod
* IOUserClient::
1090 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1092 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1095 *targetP
= (IOService
*) method
->object
;
1100 IOExternalAsyncMethod
* IOUserClient::
1101 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1103 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1106 *targetP
= (IOService
*) method
->object
;
1111 IOExternalTrap
* IOUserClient::
1112 getExternalTrapForIndex(UInt32 index
)
1117 IOExternalTrap
* IOUserClient::
1118 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1120 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1123 *targetP
= trap
->object
;
1129 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1132 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1134 if (MACH_PORT_NULL
!= port
)
1135 iokit_release_port_send(port
);
1137 return (kIOReturnSuccess
);
1140 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1142 if (MACH_PORT_NULL
!= port
)
1143 iokit_release_port_send(port
);
1145 return (kIOReturnSuccess
);
1148 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1149 IOReturn result
, void *args
[], UInt32 numArgs
)
1151 OSAsyncReference64 reference64
;
1152 io_user_reference_t args64
[kMaxAsyncArgs
];
1155 if (numArgs
> kMaxAsyncArgs
)
1156 return kIOReturnMessageTooLarge
;
1158 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1159 reference64
[idx
] = REF64(reference
[idx
]);
1161 for (idx
= 0; idx
< numArgs
; idx
++)
1162 args64
[idx
] = REF64(args
[idx
]);
1164 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1167 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1168 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1172 mach_msg_header_t msgHdr
;
1177 OSNotificationHeader notifyHdr
;
1178 IOAsyncCompletionContent asyncContent
;
1179 uint32_t args
[kMaxAsyncArgs
];
1183 OSNotificationHeader64 notifyHdr
;
1184 IOAsyncCompletionContent asyncContent
;
1185 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1190 mach_port_t replyPort
;
1193 // If no reply port, do nothing.
1194 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1195 if (replyPort
== MACH_PORT_NULL
)
1196 return kIOReturnSuccess
;
1198 if (numArgs
> kMaxAsyncArgs
)
1199 return kIOReturnMessageTooLarge
;
1201 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1203 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1204 replyMsg
.msgHdr
.msgh_local_port
= 0;
1205 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1206 if (kIOUCAsync64Flag
& reference
[0])
1208 replyMsg
.msgHdr
.msgh_size
=
1209 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1210 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1211 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1212 + numArgs
* sizeof(io_user_reference_t
);
1213 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1214 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1216 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1218 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1224 replyMsg
.msgHdr
.msgh_size
=
1225 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1226 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1228 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1229 + numArgs
* sizeof(uint32_t);
1230 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1232 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1233 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1235 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1237 for (idx
= 0; idx
< numArgs
; idx
++)
1238 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1241 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1242 replyMsg
.msgHdr
.msgh_size
);
1243 if( KERN_SUCCESS
!= kr
)
1244 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1249 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1253 #define CHECK(cls,obj,out) \
1255 if( !(out = OSDynamicCast( cls, obj))) \
1256 return( kIOReturnBadArgument )
1258 /* Routine io_object_get_class */
1259 kern_return_t
is_io_object_get_class(
1261 io_name_t className
)
1263 const OSMetaClass
* my_obj
= NULL
;
1266 return( kIOReturnBadArgument
);
1268 my_obj
= object
->getMetaClass();
1270 return (kIOReturnNotFound
);
1273 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1274 return( kIOReturnSuccess
);
1277 /* Routine io_object_get_superclass */
1278 kern_return_t
is_io_object_get_superclass(
1279 mach_port_t master_port
,
1281 io_name_t class_name
)
1283 const OSMetaClass
* my_obj
= NULL
;
1284 const OSMetaClass
* superclass
= NULL
;
1285 const OSSymbol
*my_name
= NULL
;
1286 const char *my_cstr
= NULL
;
1288 if (!obj_name
|| !class_name
)
1289 return (kIOReturnBadArgument
);
1291 if( master_port
!= master_device_port
)
1292 return( kIOReturnNotPrivileged
);
1294 my_name
= OSSymbol::withCString(obj_name
);
1297 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1301 superclass
= my_obj
->getSuperClass();
1305 return( kIOReturnNotFound
);
1308 my_cstr
= superclass
->getClassName();
1311 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1312 return( kIOReturnSuccess
);
1314 return (kIOReturnNotFound
);
1317 /* Routine io_object_get_bundle_identifier */
1318 kern_return_t
is_io_object_get_bundle_identifier(
1319 mach_port_t master_port
,
1321 io_name_t bundle_name
)
1323 const OSMetaClass
* my_obj
= NULL
;
1324 const OSSymbol
*my_name
= NULL
;
1325 const OSSymbol
*identifier
= NULL
;
1326 const char *my_cstr
= NULL
;
1328 if (!obj_name
|| !bundle_name
)
1329 return (kIOReturnBadArgument
);
1331 if( master_port
!= master_device_port
)
1332 return( kIOReturnNotPrivileged
);
1334 my_name
= OSSymbol::withCString(obj_name
);
1337 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1342 identifier
= my_obj
->getKmodName();
1345 return( kIOReturnNotFound
);
1348 my_cstr
= identifier
->getCStringNoCopy();
1350 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1351 return( kIOReturnSuccess
);
1354 return (kIOReturnBadArgument
);
1357 /* Routine io_object_conforms_to */
1358 kern_return_t
is_io_object_conforms_to(
1360 io_name_t className
,
1361 boolean_t
*conforms
)
1364 return( kIOReturnBadArgument
);
1366 *conforms
= (0 != object
->metaCast( className
));
1367 return( kIOReturnSuccess
);
1370 /* Routine io_object_get_retain_count */
1371 kern_return_t
is_io_object_get_retain_count(
1373 uint32_t *retainCount
)
1376 return( kIOReturnBadArgument
);
1378 *retainCount
= object
->getRetainCount();
1379 return( kIOReturnSuccess
);
1382 /* Routine io_iterator_next */
1383 kern_return_t
is_io_iterator_next(
1384 io_object_t iterator
,
1385 io_object_t
*object
)
1389 CHECK( OSIterator
, iterator
, iter
);
1391 obj
= iter
->getNextObject();
1395 return( kIOReturnSuccess
);
1397 return( kIOReturnNoDevice
);
1400 /* Routine io_iterator_reset */
1401 kern_return_t
is_io_iterator_reset(
1402 io_object_t iterator
)
1404 CHECK( OSIterator
, iterator
, iter
);
1408 return( kIOReturnSuccess
);
1411 /* Routine io_iterator_is_valid */
1412 kern_return_t
is_io_iterator_is_valid(
1413 io_object_t iterator
,
1414 boolean_t
*is_valid
)
1416 CHECK( OSIterator
, iterator
, iter
);
1418 *is_valid
= iter
->isValid();
1420 return( kIOReturnSuccess
);
1423 /* Routine io_service_match_property_table */
1424 kern_return_t
is_io_service_match_property_table(
1425 io_service_t _service
,
1426 io_string_t matching
,
1427 boolean_t
*matches
)
1429 CHECK( IOService
, _service
, service
);
1433 OSDictionary
* dict
;
1435 obj
= OSUnserializeXML( matching
);
1437 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1438 *matches
= service
->passiveMatch( dict
);
1439 kr
= kIOReturnSuccess
;
1441 kr
= kIOReturnBadArgument
;
1449 /* Routine io_service_match_property_table_ool */
1450 kern_return_t
is_io_service_match_property_table_ool(
1451 io_object_t service
,
1452 io_buf_ptr_t matching
,
1453 mach_msg_type_number_t matchingCnt
,
1454 kern_return_t
*result
,
1455 boolean_t
*matches
)
1459 vm_map_offset_t map_data
;
1461 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1462 data
= CAST_DOWN(vm_offset_t
, map_data
);
1464 if( KERN_SUCCESS
== kr
) {
1465 // must return success after vm_map_copyout() succeeds
1466 *result
= is_io_service_match_property_table( service
,
1467 (char *) data
, matches
);
1468 vm_deallocate( kernel_map
, data
, matchingCnt
);
1474 /* Routine io_service_get_matching_services */
1475 kern_return_t
is_io_service_get_matching_services(
1476 mach_port_t master_port
,
1477 io_string_t matching
,
1478 io_iterator_t
*existing
)
1482 OSDictionary
* dict
;
1484 if( master_port
!= master_device_port
)
1485 return( kIOReturnNotPrivileged
);
1487 obj
= OSUnserializeXML( matching
);
1489 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1490 *existing
= IOService::getMatchingServices( dict
);
1491 kr
= kIOReturnSuccess
;
1493 kr
= kIOReturnBadArgument
;
1501 /* Routine io_service_get_matching_services_ool */
1502 kern_return_t
is_io_service_get_matching_services_ool(
1503 mach_port_t master_port
,
1504 io_buf_ptr_t matching
,
1505 mach_msg_type_number_t matchingCnt
,
1506 kern_return_t
*result
,
1507 io_object_t
*existing
)
1511 vm_map_offset_t map_data
;
1513 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1514 data
= CAST_DOWN(vm_offset_t
, map_data
);
1516 if( KERN_SUCCESS
== kr
) {
1517 // must return success after vm_map_copyout() succeeds
1518 *result
= is_io_service_get_matching_services( master_port
,
1519 (char *) data
, existing
);
1520 vm_deallocate( kernel_map
, data
, matchingCnt
);
1526 static kern_return_t
internal_io_service_add_notification(
1527 mach_port_t master_port
,
1528 io_name_t notification_type
,
1529 io_string_t matching
,
1532 vm_size_t referenceSize
,
1534 io_object_t
* notification
)
1536 IOServiceUserNotification
* userNotify
= 0;
1537 IONotifier
* notify
= 0;
1538 const OSSymbol
* sym
;
1539 OSDictionary
* dict
;
1541 unsigned long int userMsgType
;
1544 if( master_port
!= master_device_port
)
1545 return( kIOReturnNotPrivileged
);
1548 err
= kIOReturnNoResources
;
1550 if( !(sym
= OSSymbol::withCString( notification_type
)))
1551 err
= kIOReturnNoResources
;
1553 if( !(dict
= OSDynamicCast( OSDictionary
,
1554 OSUnserializeXML( matching
)))) {
1555 err
= kIOReturnBadArgument
;
1559 if( (sym
== gIOPublishNotification
)
1560 || (sym
== gIOFirstPublishNotification
))
1561 userMsgType
= kIOServicePublishNotificationType
;
1562 else if( (sym
== gIOMatchedNotification
)
1563 || (sym
== gIOFirstMatchNotification
))
1564 userMsgType
= kIOServiceMatchedNotificationType
;
1565 else if( sym
== gIOTerminatedNotification
)
1566 userMsgType
= kIOServiceTerminatedNotificationType
;
1568 userMsgType
= kLastIOKitNotificationType
;
1570 userNotify
= new IOServiceUserNotification
;
1572 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1573 reference
, referenceSize
, client64
)) {
1574 userNotify
->release();
1580 notify
= IOService::addMatchingNotification( sym
, dict
,
1581 &userNotify
->_handler
, userNotify
);
1583 *notification
= userNotify
;
1584 userNotify
->setNotification( notify
);
1585 err
= kIOReturnSuccess
;
1587 err
= kIOReturnUnsupported
;
1600 /* Routine io_service_add_notification */
1601 kern_return_t
is_io_service_add_notification(
1602 mach_port_t master_port
,
1603 io_name_t notification_type
,
1604 io_string_t matching
,
1606 io_async_ref_t reference
,
1607 mach_msg_type_number_t referenceCnt
,
1608 io_object_t
* notification
)
1610 return (internal_io_service_add_notification(master_port
, notification_type
,
1611 matching
, port
, &reference
[0], sizeof(io_async_ref_t
),
1612 false, notification
));
1615 /* Routine io_service_add_notification_64 */
1616 kern_return_t
is_io_service_add_notification_64(
1617 mach_port_t master_port
,
1618 io_name_t notification_type
,
1619 io_string_t matching
,
1620 mach_port_t wake_port
,
1621 io_async_ref64_t reference
,
1622 mach_msg_type_number_t referenceCnt
,
1623 io_object_t
*notification
)
1625 return (internal_io_service_add_notification(master_port
, notification_type
,
1626 matching
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1627 true, notification
));
1631 static kern_return_t
internal_io_service_add_notification_ool(
1632 mach_port_t master_port
,
1633 io_name_t notification_type
,
1634 io_buf_ptr_t matching
,
1635 mach_msg_type_number_t matchingCnt
,
1636 mach_port_t wake_port
,
1638 vm_size_t referenceSize
,
1640 kern_return_t
*result
,
1641 io_object_t
*notification
)
1645 vm_map_offset_t map_data
;
1647 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1648 data
= CAST_DOWN(vm_offset_t
, map_data
);
1650 if( KERN_SUCCESS
== kr
) {
1651 // must return success after vm_map_copyout() succeeds
1652 *result
= internal_io_service_add_notification( master_port
, notification_type
,
1653 (char *) data
, wake_port
, reference
, referenceSize
, client64
, notification
);
1654 vm_deallocate( kernel_map
, data
, matchingCnt
);
1660 /* Routine io_service_add_notification_ool */
1661 kern_return_t
is_io_service_add_notification_ool(
1662 mach_port_t master_port
,
1663 io_name_t notification_type
,
1664 io_buf_ptr_t matching
,
1665 mach_msg_type_number_t matchingCnt
,
1666 mach_port_t wake_port
,
1667 io_async_ref_t reference
,
1668 mach_msg_type_number_t referenceCnt
,
1669 kern_return_t
*result
,
1670 io_object_t
*notification
)
1672 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1673 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
1674 false, result
, notification
));
1677 /* Routine io_service_add_notification_ool_64 */
1678 kern_return_t
is_io_service_add_notification_ool_64(
1679 mach_port_t master_port
,
1680 io_name_t notification_type
,
1681 io_buf_ptr_t matching
,
1682 mach_msg_type_number_t matchingCnt
,
1683 mach_port_t wake_port
,
1684 io_async_ref64_t reference
,
1685 mach_msg_type_number_t referenceCnt
,
1686 kern_return_t
*result
,
1687 io_object_t
*notification
)
1689 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1690 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1691 true, result
, notification
));
1694 /* Routine io_service_add_notification_old */
1695 kern_return_t
is_io_service_add_notification_old(
1696 mach_port_t master_port
,
1697 io_name_t notification_type
,
1698 io_string_t matching
,
1700 // for binary compatibility reasons, this must be natural_t for ILP32
1702 io_object_t
* notification
)
1704 return( is_io_service_add_notification( master_port
, notification_type
,
1705 matching
, port
, &ref
, 1, notification
));
1709 static kern_return_t
internal_io_service_add_interest_notification(
1710 io_object_t _service
,
1711 io_name_t type_of_interest
,
1714 vm_size_t referenceSize
,
1716 io_object_t
* notification
)
1719 IOServiceMessageUserNotification
* userNotify
= 0;
1720 IONotifier
* notify
= 0;
1721 const OSSymbol
* sym
;
1724 CHECK( IOService
, _service
, service
);
1726 err
= kIOReturnNoResources
;
1727 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1729 userNotify
= new IOServiceMessageUserNotification
;
1731 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1732 reference
, referenceSize
,
1733 kIOUserNotifyMaxMessageSize
,
1735 userNotify
->release();
1741 notify
= service
->registerInterest( sym
,
1742 &userNotify
->_handler
, userNotify
);
1744 *notification
= userNotify
;
1745 userNotify
->setNotification( notify
);
1746 err
= kIOReturnSuccess
;
1748 err
= kIOReturnUnsupported
;
1757 /* Routine io_service_add_message_notification */
1758 kern_return_t
is_io_service_add_interest_notification(
1759 io_object_t service
,
1760 io_name_t type_of_interest
,
1762 io_async_ref_t reference
,
1763 mach_msg_type_number_t referenceCnt
,
1764 io_object_t
* notification
)
1766 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1767 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
1770 /* Routine io_service_add_interest_notification_64 */
1771 kern_return_t
is_io_service_add_interest_notification_64(
1772 io_object_t service
,
1773 io_name_t type_of_interest
,
1774 mach_port_t wake_port
,
1775 io_async_ref64_t reference
,
1776 mach_msg_type_number_t referenceCnt
,
1777 io_object_t
*notification
)
1779 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1780 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
1784 /* Routine io_service_acknowledge_notification */
1785 kern_return_t
is_io_service_acknowledge_notification(
1786 io_object_t _service
,
1787 natural_t notify_ref
,
1788 natural_t response
)
1790 CHECK( IOService
, _service
, service
);
1792 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1793 (IOOptionBits
) response
));
1797 /* Routine io_connect_get_semaphore */
1798 kern_return_t
is_io_connect_get_notification_semaphore(
1799 io_connect_t connection
,
1800 natural_t notification_type
,
1801 semaphore_t
*semaphore
)
1803 CHECK( IOUserClient
, connection
, client
);
1805 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1809 /* Routine io_registry_get_root_entry */
1810 kern_return_t
is_io_registry_get_root_entry(
1811 mach_port_t master_port
,
1814 IORegistryEntry
* entry
;
1816 if( master_port
!= master_device_port
)
1817 return( kIOReturnNotPrivileged
);
1819 entry
= IORegistryEntry::getRegistryRoot();
1824 return( kIOReturnSuccess
);
1827 /* Routine io_registry_create_iterator */
1828 kern_return_t
is_io_registry_create_iterator(
1829 mach_port_t master_port
,
1832 io_object_t
*iterator
)
1834 if( master_port
!= master_device_port
)
1835 return( kIOReturnNotPrivileged
);
1837 *iterator
= IORegistryIterator::iterateOver(
1838 IORegistryEntry::getPlane( plane
), options
);
1840 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1843 /* Routine io_registry_entry_create_iterator */
1844 kern_return_t
is_io_registry_entry_create_iterator(
1845 io_object_t registry_entry
,
1848 io_object_t
*iterator
)
1850 CHECK( IORegistryEntry
, registry_entry
, entry
);
1852 *iterator
= IORegistryIterator::iterateOver( entry
,
1853 IORegistryEntry::getPlane( plane
), options
);
1855 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1858 /* Routine io_registry_iterator_enter */
1859 kern_return_t
is_io_registry_iterator_enter_entry(
1860 io_object_t iterator
)
1862 CHECK( IORegistryIterator
, iterator
, iter
);
1866 return( kIOReturnSuccess
);
1869 /* Routine io_registry_iterator_exit */
1870 kern_return_t
is_io_registry_iterator_exit_entry(
1871 io_object_t iterator
)
1875 CHECK( IORegistryIterator
, iterator
, iter
);
1877 didIt
= iter
->exitEntry();
1879 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1882 /* Routine io_registry_entry_from_path */
1883 kern_return_t
is_io_registry_entry_from_path(
1884 mach_port_t master_port
,
1886 io_object_t
*registry_entry
)
1888 IORegistryEntry
* entry
;
1890 if( master_port
!= master_device_port
)
1891 return( kIOReturnNotPrivileged
);
1893 entry
= IORegistryEntry::fromPath( path
);
1895 *registry_entry
= entry
;
1897 return( kIOReturnSuccess
);
1900 /* Routine io_registry_entry_in_plane */
1901 kern_return_t
is_io_registry_entry_in_plane(
1902 io_object_t registry_entry
,
1904 boolean_t
*inPlane
)
1906 CHECK( IORegistryEntry
, registry_entry
, entry
);
1908 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1910 return( kIOReturnSuccess
);
1914 /* Routine io_registry_entry_get_path */
1915 kern_return_t
is_io_registry_entry_get_path(
1916 io_object_t registry_entry
,
1921 CHECK( IORegistryEntry
, registry_entry
, entry
);
1923 length
= sizeof( io_string_t
);
1924 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1925 return( kIOReturnSuccess
);
1927 return( kIOReturnBadArgument
);
1931 /* Routine io_registry_entry_get_name */
1932 kern_return_t
is_io_registry_entry_get_name(
1933 io_object_t registry_entry
,
1936 CHECK( IORegistryEntry
, registry_entry
, entry
);
1938 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1940 return( kIOReturnSuccess
);
1943 /* Routine io_registry_entry_get_name_in_plane */
1944 kern_return_t
is_io_registry_entry_get_name_in_plane(
1945 io_object_t registry_entry
,
1946 io_name_t planeName
,
1949 const IORegistryPlane
* plane
;
1950 CHECK( IORegistryEntry
, registry_entry
, entry
);
1953 plane
= IORegistryEntry::getPlane( planeName
);
1957 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1959 return( kIOReturnSuccess
);
1962 /* Routine io_registry_entry_get_location_in_plane */
1963 kern_return_t
is_io_registry_entry_get_location_in_plane(
1964 io_object_t registry_entry
,
1965 io_name_t planeName
,
1966 io_name_t location
)
1968 const IORegistryPlane
* plane
;
1969 CHECK( IORegistryEntry
, registry_entry
, entry
);
1972 plane
= IORegistryEntry::getPlane( planeName
);
1976 const char * cstr
= entry
->getLocation( plane
);
1979 strncpy( location
, cstr
, sizeof( io_name_t
));
1980 return( kIOReturnSuccess
);
1982 return( kIOReturnNotFound
);
1985 /* Routine io_registry_entry_get_registry_entry_id */
1986 kern_return_t
is_io_registry_entry_get_registry_entry_id(
1987 io_object_t registry_entry
,
1988 uint64_t *entry_id
)
1990 CHECK( IORegistryEntry
, registry_entry
, entry
);
1992 *entry_id
= entry
->getRegistryEntryID();
1994 return (kIOReturnSuccess
);
1997 // Create a vm_map_copy_t or kalloc'ed data for memory
1998 // to be copied out. ipc will free after the copyout.
2000 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
2001 io_buf_ptr_t
* buf
)
2006 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
2007 false /* src_destroy */, ©
);
2009 assert( err
== KERN_SUCCESS
);
2010 if( err
== KERN_SUCCESS
)
2011 *buf
= (char *) copy
;
2016 /* Routine io_registry_entry_get_property */
2017 kern_return_t
is_io_registry_entry_get_property_bytes(
2018 io_object_t registry_entry
,
2019 io_name_t property_name
,
2020 io_struct_inband_t buf
,
2021 mach_msg_type_number_t
*dataCnt
)
2029 unsigned int len
= 0;
2030 const void * bytes
= 0;
2031 IOReturn ret
= kIOReturnSuccess
;
2033 CHECK( IORegistryEntry
, registry_entry
, entry
);
2035 obj
= entry
->copyProperty(property_name
);
2037 return( kIOReturnNoResources
);
2039 // One day OSData will be a common container base class
2041 if( (data
= OSDynamicCast( OSData
, obj
))) {
2042 len
= data
->getLength();
2043 bytes
= data
->getBytesNoCopy();
2045 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2046 len
= str
->getLength() + 1;
2047 bytes
= str
->getCStringNoCopy();
2049 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2050 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2051 bytes
= boo
->isTrue() ? "Yes" : "No";
2053 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2054 offsetBytes
= off
->unsigned64BitValue();
2055 len
= off
->numberOfBytes();
2056 bytes
= &offsetBytes
;
2057 #ifdef __BIG_ENDIAN__
2058 bytes
= (const void *)
2059 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2063 ret
= kIOReturnBadArgument
;
2067 ret
= kIOReturnIPCError
;
2070 bcopy( bytes
, buf
, len
);
2079 /* Routine io_registry_entry_get_property */
2080 kern_return_t
is_io_registry_entry_get_property(
2081 io_object_t registry_entry
,
2082 io_name_t property_name
,
2083 io_buf_ptr_t
*properties
,
2084 mach_msg_type_number_t
*propertiesCnt
)
2090 CHECK( IORegistryEntry
, registry_entry
, entry
);
2092 obj
= entry
->copyProperty(property_name
);
2094 return( kIOReturnNotFound
);
2096 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2099 return( kIOReturnNoMemory
);
2103 if( obj
->serialize( s
)) {
2104 len
= s
->getLength();
2105 *propertiesCnt
= len
;
2106 err
= copyoutkdata( s
->text(), len
, properties
);
2109 err
= kIOReturnUnsupported
;
2117 /* Routine io_registry_entry_get_property_recursively */
2118 kern_return_t
is_io_registry_entry_get_property_recursively(
2119 io_object_t registry_entry
,
2121 io_name_t property_name
,
2123 io_buf_ptr_t
*properties
,
2124 mach_msg_type_number_t
*propertiesCnt
)
2130 CHECK( IORegistryEntry
, registry_entry
, entry
);
2132 obj
= entry
->copyProperty( property_name
,
2133 IORegistryEntry::getPlane( plane
), options
);
2135 return( kIOReturnNotFound
);
2137 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2140 return( kIOReturnNoMemory
);
2145 if( obj
->serialize( s
)) {
2146 len
= s
->getLength();
2147 *propertiesCnt
= len
;
2148 err
= copyoutkdata( s
->text(), len
, properties
);
2151 err
= kIOReturnUnsupported
;
2159 /* Routine io_registry_entry_get_properties */
2160 kern_return_t
is_io_registry_entry_get_properties(
2161 io_object_t registry_entry
,
2162 io_buf_ptr_t
*properties
,
2163 mach_msg_type_number_t
*propertiesCnt
)
2168 CHECK( IORegistryEntry
, registry_entry
, entry
);
2170 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2172 return( kIOReturnNoMemory
);
2176 if( entry
->serializeProperties( s
)) {
2177 len
= s
->getLength();
2178 *propertiesCnt
= len
;
2179 err
= copyoutkdata( s
->text(), len
, properties
);
2182 err
= kIOReturnUnsupported
;
2189 /* Routine io_registry_entry_set_properties */
2190 kern_return_t is_io_registry_entry_set_properties
2192 io_object_t registry_entry
,
2193 io_buf_ptr_t properties
,
2194 mach_msg_type_number_t propertiesCnt
,
2195 kern_return_t
* result
)
2201 vm_map_offset_t map_data
;
2203 CHECK( IORegistryEntry
, registry_entry
, entry
);
2205 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2206 data
= CAST_DOWN(vm_offset_t
, map_data
);
2208 if( KERN_SUCCESS
== err
) {
2210 // must return success after vm_map_copyout() succeeds
2211 obj
= OSUnserializeXML( (const char *) data
);
2212 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2215 res
= entry
->setProperties( obj
);
2218 res
= kIOReturnBadArgument
;
2226 /* Routine io_registry_entry_get_child_iterator */
2227 kern_return_t
is_io_registry_entry_get_child_iterator(
2228 io_object_t registry_entry
,
2230 io_object_t
*iterator
)
2232 CHECK( IORegistryEntry
, registry_entry
, entry
);
2234 *iterator
= entry
->getChildIterator(
2235 IORegistryEntry::getPlane( plane
));
2237 return( kIOReturnSuccess
);
2240 /* Routine io_registry_entry_get_parent_iterator */
2241 kern_return_t
is_io_registry_entry_get_parent_iterator(
2242 io_object_t registry_entry
,
2244 io_object_t
*iterator
)
2246 CHECK( IORegistryEntry
, registry_entry
, entry
);
2248 *iterator
= entry
->getParentIterator(
2249 IORegistryEntry::getPlane( plane
));
2251 return( kIOReturnSuccess
);
2254 /* Routine io_service_get_busy_state */
2255 kern_return_t
is_io_service_get_busy_state(
2256 io_object_t _service
,
2257 uint32_t *busyState
)
2259 CHECK( IOService
, _service
, service
);
2261 *busyState
= service
->getBusyState();
2263 return( kIOReturnSuccess
);
2266 /* Routine io_service_get_state */
2267 kern_return_t
is_io_service_get_state(
2268 io_object_t _service
,
2270 uint32_t *busy_state
,
2271 uint64_t *accumulated_busy_time
)
2273 CHECK( IOService
, _service
, service
);
2275 *state
= service
->getState();
2276 *busy_state
= service
->getBusyState();
2277 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
2279 return( kIOReturnSuccess
);
2282 /* Routine io_service_wait_quiet */
2283 kern_return_t
is_io_service_wait_quiet(
2284 io_object_t _service
,
2285 mach_timespec_t wait_time
)
2289 CHECK( IOService
, _service
, service
);
2291 timeoutNS
= wait_time
.tv_sec
;
2292 timeoutNS
*= kSecondScale
;
2293 timeoutNS
+= wait_time
.tv_nsec
;
2295 return( service
->waitQuiet(timeoutNS
) );
2298 /* Routine io_service_request_probe */
2299 kern_return_t
is_io_service_request_probe(
2300 io_object_t _service
,
2303 CHECK( IOService
, _service
, service
);
2305 return( service
->requestProbe( options
));
2309 /* Routine io_service_open */
2310 kern_return_t
is_io_service_open(
2311 io_object_t _service
,
2313 uint32_t connect_type
,
2314 io_object_t
*connection
)
2316 IOUserClient
* client
;
2319 CHECK( IOService
, _service
, service
);
2321 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
2322 connect_type
, 0, &client
);
2324 if( err
== kIOReturnSuccess
) {
2325 assert( OSDynamicCast(IOUserClient
, client
) );
2326 *connection
= client
;
2332 /* Routine io_service_open_ndr */
2333 kern_return_t
is_io_service_open_extended(
2334 io_object_t _service
,
2336 uint32_t connect_type
,
2338 io_buf_ptr_t properties
,
2339 mach_msg_type_number_t propertiesCnt
,
2340 kern_return_t
* result
,
2341 io_object_t
*connection
)
2343 IOUserClient
* client
= 0;
2344 kern_return_t err
= KERN_SUCCESS
;
2345 IOReturn res
= kIOReturnSuccess
;
2346 OSDictionary
* propertiesDict
= 0;
2348 bool disallowAccess
;
2350 CHECK( IOService
, _service
, service
);
2358 vm_map_offset_t map_data
;
2360 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2362 data
= CAST_DOWN(vm_offset_t
, map_data
);
2363 if (KERN_SUCCESS
== err
)
2365 // must return success after vm_map_copyout() succeeds
2366 obj
= OSUnserializeXML( (const char *) data
);
2367 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2368 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
2369 if (!propertiesDict
)
2371 res
= kIOReturnBadArgument
;
2376 if (kIOReturnSuccess
!= res
)
2380 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
2383 if (!propertiesDict
)
2384 propertiesDict
= OSDictionary::withCapacity(4);
2385 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
2389 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
2394 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
2395 connect_type
, propertiesDict
, &client
);
2398 propertiesDict
->release();
2400 if (res
== kIOReturnSuccess
)
2402 assert( OSDynamicCast(IOUserClient
, client
) );
2404 disallowAccess
= (crossEndian
2405 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
2406 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
2410 client
->clientClose();
2413 res
= kIOReturnUnsupported
;
2416 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
2417 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
2420 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
2421 creatorName
->release();
2427 *connection
= client
;
2433 /* Routine io_service_close */
2434 kern_return_t
is_io_service_close(
2435 io_object_t connection
)
2438 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2439 return( kIOReturnSuccess
);
2441 CHECK( IOUserClient
, connection
, client
);
2443 client
->clientClose();
2445 return( kIOReturnSuccess
);
2448 /* Routine io_connect_get_service */
2449 kern_return_t
is_io_connect_get_service(
2450 io_object_t connection
,
2451 io_object_t
*service
)
2453 IOService
* theService
;
2455 CHECK( IOUserClient
, connection
, client
);
2457 theService
= client
->getService();
2459 theService
->retain();
2461 *service
= theService
;
2463 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2466 /* Routine io_connect_set_notification_port */
2467 kern_return_t
is_io_connect_set_notification_port(
2468 io_object_t connection
,
2469 uint32_t notification_type
,
2473 CHECK( IOUserClient
, connection
, client
);
2475 return( client
->registerNotificationPort( port
, notification_type
,
2476 (io_user_reference_t
) reference
));
2479 /* Routine io_connect_set_notification_port */
2480 kern_return_t
is_io_connect_set_notification_port_64(
2481 io_object_t connection
,
2482 uint32_t notification_type
,
2484 io_user_reference_t reference
)
2486 CHECK( IOUserClient
, connection
, client
);
2488 return( client
->registerNotificationPort( port
, notification_type
,
2492 /* Routine io_connect_map_memory_into_task */
2493 kern_return_t is_io_connect_map_memory_into_task
2495 io_connect_t connection
,
2496 uint32_t memory_type
,
2498 mach_vm_address_t
*address
,
2499 mach_vm_size_t
*size
,
2506 CHECK( IOUserClient
, connection
, client
);
2508 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
2511 *address
= map
->getAddress();
2513 *size
= map
->getSize();
2515 if( client
->sharedInstance
2516 || (into_task
!= current_task())) {
2517 // push a name out to the task owning the map,
2518 // so we can clean up maps
2519 mach_port_name_t name __unused
=
2520 IOMachPort::makeSendRightForTask(
2521 into_task
, map
, IKOT_IOKIT_OBJECT
);
2525 // keep it with the user client
2526 IOLockLock( gIOObjectPortLock
);
2527 if( 0 == client
->mappings
)
2528 client
->mappings
= OSSet::withCapacity(2);
2529 if( client
->mappings
)
2530 client
->mappings
->setObject( map
);
2531 IOLockUnlock( gIOObjectPortLock
);
2534 err
= kIOReturnSuccess
;
2537 err
= kIOReturnBadArgument
;
2542 /* Routine is_io_connect_map_memory */
2543 kern_return_t
is_io_connect_map_memory(
2544 io_object_t connect
,
2547 vm_address_t
* mapAddr
,
2548 vm_size_t
* mapSize
,
2552 mach_vm_address_t address
;
2553 mach_vm_size_t size
;
2555 address
= SCALAR64(*mapAddr
);
2556 size
= SCALAR64(*mapSize
);
2558 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
2560 *mapAddr
= SCALAR32(address
);
2561 *mapSize
= SCALAR32(size
);
2566 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2569 IOMemoryMap
* map
= 0;
2571 IOLockLock(gIOObjectPortLock
);
2573 iter
= OSCollectionIterator::withCollection(mappings
);
2576 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2578 if(mem
== map
->getMemoryDescriptor())
2581 mappings
->removeObject(map
);
2588 IOLockUnlock(gIOObjectPortLock
);
2593 /* Routine io_connect_unmap_memory_from_task */
2594 kern_return_t is_io_connect_unmap_memory_from_task
2596 io_connect_t connection
,
2597 uint32_t memory_type
,
2599 mach_vm_address_t address
)
2602 IOOptionBits options
= 0;
2603 IOMemoryDescriptor
* memory
;
2606 CHECK( IOUserClient
, connection
, client
);
2608 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
2610 if( memory
&& (kIOReturnSuccess
== err
)) {
2612 options
= (options
& ~kIOMapUserOptionsMask
)
2613 | kIOMapAnywhere
| kIOMapReference
;
2615 map
= memory
->createMappingInTask( from_task
, address
, options
);
2619 IOLockLock( gIOObjectPortLock
);
2620 if( client
->mappings
)
2621 client
->mappings
->removeObject( map
);
2622 IOLockUnlock( gIOObjectPortLock
);
2624 mach_port_name_t name
= 0;
2625 if (from_task
!= current_task())
2626 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
2629 map
->userClientUnmap();
2630 err
= iokit_mod_send_right( from_task
, name
, -2 );
2631 err
= kIOReturnSuccess
;
2634 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2635 if (from_task
== current_task())
2639 err
= kIOReturnBadArgument
;
2645 kern_return_t
is_io_connect_unmap_memory(
2646 io_object_t connect
,
2649 vm_address_t mapAddr
)
2652 mach_vm_address_t address
;
2654 address
= SCALAR64(mapAddr
);
2656 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
2662 /* Routine io_connect_add_client */
2663 kern_return_t
is_io_connect_add_client(
2664 io_object_t connection
,
2665 io_object_t connect_to
)
2667 CHECK( IOUserClient
, connection
, client
);
2668 CHECK( IOUserClient
, connect_to
, to
);
2670 return( client
->connectClient( to
) );
2674 /* Routine io_connect_set_properties */
2675 kern_return_t
is_io_connect_set_properties(
2676 io_object_t connection
,
2677 io_buf_ptr_t properties
,
2678 mach_msg_type_number_t propertiesCnt
,
2679 kern_return_t
* result
)
2681 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2685 /* Routine io_user_client_method */
2686 kern_return_t is_io_connect_method
2688 io_connect_t connection
,
2690 io_scalar_inband64_t scalar_input
,
2691 mach_msg_type_number_t scalar_inputCnt
,
2692 io_struct_inband_t inband_input
,
2693 mach_msg_type_number_t inband_inputCnt
,
2694 mach_vm_address_t ool_input
,
2695 mach_vm_size_t ool_input_size
,
2696 io_scalar_inband64_t scalar_output
,
2697 mach_msg_type_number_t
*scalar_outputCnt
,
2698 io_struct_inband_t inband_output
,
2699 mach_msg_type_number_t
*inband_outputCnt
,
2700 mach_vm_address_t ool_output
,
2701 mach_vm_size_t
* ool_output_size
2704 CHECK( IOUserClient
, connection
, client
);
2706 IOExternalMethodArguments args
;
2708 IOMemoryDescriptor
* inputMD
= 0;
2709 IOMemoryDescriptor
* outputMD
= 0;
2711 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
2712 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
2714 args
.selector
= selector
;
2716 args
.asyncWakePort
= MACH_PORT_NULL
;
2717 args
.asyncReference
= 0;
2718 args
.asyncReferenceCount
= 0;
2720 args
.scalarInput
= scalar_input
;
2721 args
.scalarInputCount
= scalar_inputCnt
;
2722 args
.structureInput
= inband_input
;
2723 args
.structureInputSize
= inband_inputCnt
;
2726 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
2727 kIODirectionOut
, current_task());
2729 args
.structureInputDescriptor
= inputMD
;
2731 args
.scalarOutput
= scalar_output
;
2732 args
.scalarOutputCount
= *scalar_outputCnt
;
2733 args
.structureOutput
= inband_output
;
2734 args
.structureOutputSize
= *inband_outputCnt
;
2738 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
2739 kIODirectionIn
, current_task());
2742 args
.structureOutputDescriptor
= outputMD
;
2743 args
.structureOutputDescriptorSize
= *ool_output_size
;
2745 ret
= client
->externalMethod( selector
, &args
);
2747 *scalar_outputCnt
= args
.scalarOutputCount
;
2748 *inband_outputCnt
= args
.structureOutputSize
;
2749 *ool_output_size
= args
.structureOutputDescriptorSize
;
2754 outputMD
->release();
2759 /* Routine io_async_user_client_method */
2760 kern_return_t is_io_connect_async_method
2762 io_connect_t connection
,
2763 mach_port_t wake_port
,
2764 io_async_ref64_t reference
,
2765 mach_msg_type_number_t referenceCnt
,
2767 io_scalar_inband64_t scalar_input
,
2768 mach_msg_type_number_t scalar_inputCnt
,
2769 io_struct_inband_t inband_input
,
2770 mach_msg_type_number_t inband_inputCnt
,
2771 mach_vm_address_t ool_input
,
2772 mach_vm_size_t ool_input_size
,
2773 io_scalar_inband64_t scalar_output
,
2774 mach_msg_type_number_t
*scalar_outputCnt
,
2775 io_struct_inband_t inband_output
,
2776 mach_msg_type_number_t
*inband_outputCnt
,
2777 mach_vm_address_t ool_output
,
2778 mach_vm_size_t
* ool_output_size
2781 CHECK( IOUserClient
, connection
, client
);
2783 IOExternalMethodArguments args
;
2785 IOMemoryDescriptor
* inputMD
= 0;
2786 IOMemoryDescriptor
* outputMD
= 0;
2788 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
2789 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
2791 reference
[0] = (io_user_reference_t
) wake_port
;
2792 if (vm_map_is_64bit(get_task_map(current_task())))
2793 reference
[0] |= kIOUCAsync64Flag
;
2795 args
.selector
= selector
;
2797 args
.asyncWakePort
= wake_port
;
2798 args
.asyncReference
= reference
;
2799 args
.asyncReferenceCount
= referenceCnt
;
2801 args
.scalarInput
= scalar_input
;
2802 args
.scalarInputCount
= scalar_inputCnt
;
2803 args
.structureInput
= inband_input
;
2804 args
.structureInputSize
= inband_inputCnt
;
2807 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
2808 kIODirectionOut
, current_task());
2810 args
.structureInputDescriptor
= inputMD
;
2812 args
.scalarOutput
= scalar_output
;
2813 args
.scalarOutputCount
= *scalar_outputCnt
;
2814 args
.structureOutput
= inband_output
;
2815 args
.structureOutputSize
= *inband_outputCnt
;
2819 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
2820 kIODirectionIn
, current_task());
2823 args
.structureOutputDescriptor
= outputMD
;
2824 args
.structureOutputDescriptorSize
= *ool_output_size
;
2826 ret
= client
->externalMethod( selector
, &args
);
2828 *inband_outputCnt
= args
.structureOutputSize
;
2829 *ool_output_size
= args
.structureOutputDescriptorSize
;
2834 outputMD
->release();
2839 /* Routine io_connect_method_scalarI_scalarO */
2840 kern_return_t
is_io_connect_method_scalarI_scalarO(
2841 io_object_t connect
,
2843 io_scalar_inband_t input
,
2844 mach_msg_type_number_t inputCount
,
2845 io_scalar_inband_t output
,
2846 mach_msg_type_number_t
* outputCount
)
2850 io_scalar_inband64_t _input
;
2851 io_scalar_inband64_t _output
;
2853 mach_msg_type_number_t struct_outputCnt
= 0;
2854 mach_vm_size_t ool_output_size
= 0;
2856 for (i
= 0; i
< inputCount
; i
++)
2857 _input
[i
] = SCALAR64(input
[i
]);
2859 err
= is_io_connect_method(connect
, index
,
2863 _output
, outputCount
,
2864 NULL
, &struct_outputCnt
,
2865 0, &ool_output_size
);
2867 for (i
= 0; i
< *outputCount
; i
++)
2868 output
[i
] = SCALAR32(_output
[i
]);
2873 kern_return_t
shim_io_connect_method_scalarI_scalarO(
2874 IOExternalMethod
* method
,
2876 const io_user_scalar_t
* input
,
2877 mach_msg_type_number_t inputCount
,
2878 io_user_scalar_t
* output
,
2879 mach_msg_type_number_t
* outputCount
)
2882 io_scalar_inband_t _output
;
2884 err
= kIOReturnBadArgument
;
2888 if( inputCount
!= method
->count0
)
2890 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
2893 if( *outputCount
!= method
->count1
)
2895 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
2899 func
= method
->func
;
2901 switch( inputCount
) {
2904 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2905 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
2908 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2909 ARG32(input
[3]), ARG32(input
[4]),
2913 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2915 &_output
[0], &_output
[1] );
2918 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2919 &_output
[0], &_output
[1], &_output
[2] );
2922 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
2923 &_output
[0], &_output
[1], &_output
[2],
2927 err
= (object
->*func
)( ARG32(input
[0]),
2928 &_output
[0], &_output
[1], &_output
[2],
2929 &_output
[3], &_output
[4] );
2932 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
2933 &_output
[3], &_output
[4], &_output
[5] );
2937 IOLog("%s: Bad method table\n", object
->getName());
2943 for (i
= 0; i
< *outputCount
; i
++)
2944 output
[i
] = SCALAR32(_output
[i
]);
2949 /* Routine io_async_method_scalarI_scalarO */
2950 kern_return_t
is_io_async_method_scalarI_scalarO(
2951 io_object_t connect
,
2952 mach_port_t wake_port
,
2953 io_async_ref_t reference
,
2954 mach_msg_type_number_t referenceCnt
,
2956 io_scalar_inband_t input
,
2957 mach_msg_type_number_t inputCount
,
2958 io_scalar_inband_t output
,
2959 mach_msg_type_number_t
* outputCount
)
2963 io_scalar_inband64_t _input
;
2964 io_scalar_inband64_t _output
;
2965 io_async_ref64_t _reference
;
2967 for (i
= 0; i
< referenceCnt
; i
++)
2968 _reference
[i
] = REF64(reference
[i
]);
2970 mach_msg_type_number_t struct_outputCnt
= 0;
2971 mach_vm_size_t ool_output_size
= 0;
2973 for (i
= 0; i
< inputCount
; i
++)
2974 _input
[i
] = SCALAR64(input
[i
]);
2976 err
= is_io_connect_async_method(connect
,
2977 wake_port
, _reference
, referenceCnt
,
2982 _output
, outputCount
,
2983 NULL
, &struct_outputCnt
,
2984 0, &ool_output_size
);
2986 for (i
= 0; i
< *outputCount
; i
++)
2987 output
[i
] = SCALAR32(_output
[i
]);
2991 /* Routine io_async_method_scalarI_structureO */
2992 kern_return_t
is_io_async_method_scalarI_structureO(
2993 io_object_t connect
,
2994 mach_port_t wake_port
,
2995 io_async_ref_t reference
,
2996 mach_msg_type_number_t referenceCnt
,
2998 io_scalar_inband_t input
,
2999 mach_msg_type_number_t inputCount
,
3000 io_struct_inband_t output
,
3001 mach_msg_type_number_t
* outputCount
)
3004 io_scalar_inband64_t _input
;
3005 io_async_ref64_t _reference
;
3007 for (i
= 0; i
< referenceCnt
; i
++)
3008 _reference
[i
] = REF64(reference
[i
]);
3010 mach_msg_type_number_t scalar_outputCnt
= 0;
3011 mach_vm_size_t ool_output_size
= 0;
3013 for (i
= 0; i
< inputCount
; i
++)
3014 _input
[i
] = SCALAR64(input
[i
]);
3016 return (is_io_connect_async_method(connect
,
3017 wake_port
, _reference
, referenceCnt
,
3022 NULL
, &scalar_outputCnt
,
3023 output
, outputCount
,
3024 0, &ool_output_size
));
3027 /* Routine io_async_method_scalarI_structureI */
3028 kern_return_t
is_io_async_method_scalarI_structureI(
3029 io_connect_t connect
,
3030 mach_port_t wake_port
,
3031 io_async_ref_t reference
,
3032 mach_msg_type_number_t referenceCnt
,
3034 io_scalar_inband_t input
,
3035 mach_msg_type_number_t inputCount
,
3036 io_struct_inband_t inputStruct
,
3037 mach_msg_type_number_t inputStructCount
)
3040 io_scalar_inband64_t _input
;
3041 io_async_ref64_t _reference
;
3043 for (i
= 0; i
< referenceCnt
; i
++)
3044 _reference
[i
] = REF64(reference
[i
]);
3046 mach_msg_type_number_t scalar_outputCnt
= 0;
3047 mach_msg_type_number_t inband_outputCnt
= 0;
3048 mach_vm_size_t ool_output_size
= 0;
3050 for (i
= 0; i
< inputCount
; i
++)
3051 _input
[i
] = SCALAR64(input
[i
]);
3053 return (is_io_connect_async_method(connect
,
3054 wake_port
, _reference
, referenceCnt
,
3057 inputStruct
, inputStructCount
,
3059 NULL
, &scalar_outputCnt
,
3060 NULL
, &inband_outputCnt
,
3061 0, &ool_output_size
));
3064 /* Routine io_async_method_structureI_structureO */
3065 kern_return_t
is_io_async_method_structureI_structureO(
3066 io_object_t connect
,
3067 mach_port_t wake_port
,
3068 io_async_ref_t reference
,
3069 mach_msg_type_number_t referenceCnt
,
3071 io_struct_inband_t input
,
3072 mach_msg_type_number_t inputCount
,
3073 io_struct_inband_t output
,
3074 mach_msg_type_number_t
* outputCount
)
3077 mach_msg_type_number_t scalar_outputCnt
= 0;
3078 mach_vm_size_t ool_output_size
= 0;
3079 io_async_ref64_t _reference
;
3081 for (i
= 0; i
< referenceCnt
; i
++)
3082 _reference
[i
] = REF64(reference
[i
]);
3084 return (is_io_connect_async_method(connect
,
3085 wake_port
, _reference
, referenceCnt
,
3090 NULL
, &scalar_outputCnt
,
3091 output
, outputCount
,
3092 0, &ool_output_size
));
3096 kern_return_t
shim_io_async_method_scalarI_scalarO(
3097 IOExternalAsyncMethod
* method
,
3099 mach_port_t asyncWakePort
,
3100 io_user_reference_t
* asyncReference
,
3101 uint32_t asyncReferenceCount
,
3102 const io_user_scalar_t
* input
,
3103 mach_msg_type_number_t inputCount
,
3104 io_user_scalar_t
* output
,
3105 mach_msg_type_number_t
* outputCount
)
3109 io_scalar_inband_t _output
;
3111 io_async_ref_t reference
;
3113 for (i
= 0; i
< asyncReferenceCount
; i
++)
3114 reference
[i
] = REF32(asyncReference
[i
]);
3116 err
= kIOReturnBadArgument
;
3120 if( inputCount
!= method
->count0
)
3122 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3125 if( *outputCount
!= method
->count1
)
3127 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3131 func
= method
->func
;
3133 switch( inputCount
) {
3136 err
= (object
->*func
)( reference
,
3137 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3138 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3141 err
= (object
->*func
)( reference
,
3142 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3143 ARG32(input
[3]), ARG32(input
[4]),
3147 err
= (object
->*func
)( reference
,
3148 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3150 &_output
[0], &_output
[1] );
3153 err
= (object
->*func
)( reference
,
3154 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3155 &_output
[0], &_output
[1], &_output
[2] );
3158 err
= (object
->*func
)( reference
,
3159 ARG32(input
[0]), ARG32(input
[1]),
3160 &_output
[0], &_output
[1], &_output
[2],
3164 err
= (object
->*func
)( reference
,
3166 &_output
[0], &_output
[1], &_output
[2],
3167 &_output
[3], &_output
[4] );
3170 err
= (object
->*func
)( reference
,
3171 &_output
[0], &_output
[1], &_output
[2],
3172 &_output
[3], &_output
[4], &_output
[5] );
3176 IOLog("%s: Bad method table\n", object
->getName());
3181 for (i
= 0; i
< *outputCount
; i
++)
3182 output
[i
] = SCALAR32(_output
[i
]);
3188 /* Routine io_connect_method_scalarI_structureO */
3189 kern_return_t
is_io_connect_method_scalarI_structureO(
3190 io_object_t connect
,
3192 io_scalar_inband_t input
,
3193 mach_msg_type_number_t inputCount
,
3194 io_struct_inband_t output
,
3195 mach_msg_type_number_t
* outputCount
)
3198 io_scalar_inband64_t _input
;
3200 mach_msg_type_number_t scalar_outputCnt
= 0;
3201 mach_vm_size_t ool_output_size
= 0;
3203 for (i
= 0; i
< inputCount
; i
++)
3204 _input
[i
] = SCALAR64(input
[i
]);
3206 return (is_io_connect_method(connect
, index
,
3210 NULL
, &scalar_outputCnt
,
3211 output
, outputCount
,
3212 0, &ool_output_size
));
3215 kern_return_t
shim_io_connect_method_scalarI_structureO(
3217 IOExternalMethod
* method
,
3219 const io_user_scalar_t
* input
,
3220 mach_msg_type_number_t inputCount
,
3221 io_struct_inband_t output
,
3222 IOByteCount
* outputCount
)
3227 err
= kIOReturnBadArgument
;
3230 if( inputCount
!= method
->count0
)
3232 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3235 if( (kIOUCVariableStructureSize
!= method
->count1
)
3236 && (*outputCount
!= method
->count1
))
3238 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3242 func
= method
->func
;
3244 switch( inputCount
) {
3247 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3248 ARG32(input
[3]), ARG32(input
[4]),
3252 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3254 output
, (void *)outputCount
);
3257 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3258 output
, (void *)outputCount
, 0 );
3261 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3262 output
, (void *)outputCount
, 0, 0 );
3265 err
= (object
->*func
)( ARG32(input
[0]),
3266 output
, (void *)outputCount
, 0, 0, 0 );
3269 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
3273 IOLog("%s: Bad method table\n", object
->getName());
3282 kern_return_t
shim_io_async_method_scalarI_structureO(
3283 IOExternalAsyncMethod
* method
,
3285 mach_port_t asyncWakePort
,
3286 io_user_reference_t
* asyncReference
,
3287 uint32_t asyncReferenceCount
,
3288 const io_user_scalar_t
* input
,
3289 mach_msg_type_number_t inputCount
,
3290 io_struct_inband_t output
,
3291 mach_msg_type_number_t
* outputCount
)
3296 io_async_ref_t reference
;
3298 for (i
= 0; i
< asyncReferenceCount
; i
++)
3299 reference
[i
] = REF32(asyncReference
[i
]);
3301 err
= kIOReturnBadArgument
;
3303 if( inputCount
!= method
->count0
)
3305 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3308 if( (kIOUCVariableStructureSize
!= method
->count1
)
3309 && (*outputCount
!= method
->count1
))
3311 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3315 func
= method
->func
;
3317 switch( inputCount
) {
3320 err
= (object
->*func
)( reference
,
3321 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3322 ARG32(input
[3]), ARG32(input
[4]),
3326 err
= (object
->*func
)( reference
,
3327 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3329 output
, (void *)outputCount
);
3332 err
= (object
->*func
)( reference
,
3333 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3334 output
, (void *)outputCount
, 0 );
3337 err
= (object
->*func
)( reference
,
3338 ARG32(input
[0]), ARG32(input
[1]),
3339 output
, (void *)outputCount
, 0, 0 );
3342 err
= (object
->*func
)( reference
,
3344 output
, (void *)outputCount
, 0, 0, 0 );
3347 err
= (object
->*func
)( reference
,
3348 output
, (void *)outputCount
, 0, 0, 0, 0 );
3352 IOLog("%s: Bad method table\n", object
->getName());
3360 /* Routine io_connect_method_scalarI_structureI */
3361 kern_return_t
is_io_connect_method_scalarI_structureI(
3362 io_connect_t connect
,
3364 io_scalar_inband_t input
,
3365 mach_msg_type_number_t inputCount
,
3366 io_struct_inband_t inputStruct
,
3367 mach_msg_type_number_t inputStructCount
)
3370 io_scalar_inband64_t _input
;
3372 mach_msg_type_number_t scalar_outputCnt
= 0;
3373 mach_msg_type_number_t inband_outputCnt
= 0;
3374 mach_vm_size_t ool_output_size
= 0;
3376 for (i
= 0; i
< inputCount
; i
++)
3377 _input
[i
] = SCALAR64(input
[i
]);
3379 return (is_io_connect_method(connect
, index
,
3381 inputStruct
, inputStructCount
,
3383 NULL
, &scalar_outputCnt
,
3384 NULL
, &inband_outputCnt
,
3385 0, &ool_output_size
));
3388 kern_return_t
shim_io_connect_method_scalarI_structureI(
3389 IOExternalMethod
* method
,
3391 const io_user_scalar_t
* input
,
3392 mach_msg_type_number_t inputCount
,
3393 io_struct_inband_t inputStruct
,
3394 mach_msg_type_number_t inputStructCount
)
3397 IOReturn err
= kIOReturnBadArgument
;
3401 if( (kIOUCVariableStructureSize
!= method
->count0
)
3402 && (inputCount
!= method
->count0
))
3404 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3407 if( (kIOUCVariableStructureSize
!= method
->count1
)
3408 && (inputStructCount
!= method
->count1
))
3410 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3414 func
= method
->func
;
3416 switch( inputCount
) {
3419 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3420 ARG32(input
[3]), ARG32(input
[4]),
3424 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
3426 inputStruct
, (void *)inputStructCount
);
3429 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3430 inputStruct
, (void *)inputStructCount
,
3434 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3435 inputStruct
, (void *)inputStructCount
,
3439 err
= (object
->*func
)( ARG32(input
[0]),
3440 inputStruct
, (void *)inputStructCount
,
3444 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
3449 IOLog("%s: Bad method table\n", object
->getName());
3457 kern_return_t
shim_io_async_method_scalarI_structureI(
3458 IOExternalAsyncMethod
* method
,
3460 mach_port_t asyncWakePort
,
3461 io_user_reference_t
* asyncReference
,
3462 uint32_t asyncReferenceCount
,
3463 const io_user_scalar_t
* input
,
3464 mach_msg_type_number_t inputCount
,
3465 io_struct_inband_t inputStruct
,
3466 mach_msg_type_number_t inputStructCount
)
3470 IOReturn err
= kIOReturnBadArgument
;
3471 io_async_ref_t reference
;
3473 for (i
= 0; i
< asyncReferenceCount
; i
++)
3474 reference
[i
] = REF32(asyncReference
[i
]);
3478 if( (kIOUCVariableStructureSize
!= method
->count0
)
3479 && (inputCount
!= method
->count0
))
3481 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3484 if( (kIOUCVariableStructureSize
!= method
->count1
)
3485 && (inputStructCount
!= method
->count1
))
3487 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3491 func
= method
->func
;
3493 switch( inputCount
) {
3496 err
= (object
->*func
)( reference
,
3497 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3498 ARG32(input
[3]), ARG32(input
[4]),
3502 err
= (object
->*func
)( reference
,
3503 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3505 inputStruct
, (void *)inputStructCount
);
3508 err
= (object
->*func
)( reference
,
3509 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3510 inputStruct
, (void *)inputStructCount
,
3514 err
= (object
->*func
)( reference
,
3515 ARG32(input
[0]), ARG32(input
[1]),
3516 inputStruct
, (void *)inputStructCount
,
3520 err
= (object
->*func
)( reference
,
3522 inputStruct
, (void *)inputStructCount
,
3526 err
= (object
->*func
)( reference
,
3527 inputStruct
, (void *)inputStructCount
,
3532 IOLog("%s: Bad method table\n", object
->getName());
3540 /* Routine io_connect_method_structureI_structureO */
3541 kern_return_t
is_io_connect_method_structureI_structureO(
3542 io_object_t connect
,
3544 io_struct_inband_t input
,
3545 mach_msg_type_number_t inputCount
,
3546 io_struct_inband_t output
,
3547 mach_msg_type_number_t
* outputCount
)
3549 mach_msg_type_number_t scalar_outputCnt
= 0;
3550 mach_vm_size_t ool_output_size
= 0;
3552 return (is_io_connect_method(connect
, index
,
3556 NULL
, &scalar_outputCnt
,
3557 output
, outputCount
,
3558 0, &ool_output_size
));
3561 kern_return_t
shim_io_connect_method_structureI_structureO(
3562 IOExternalMethod
* method
,
3564 io_struct_inband_t input
,
3565 mach_msg_type_number_t inputCount
,
3566 io_struct_inband_t output
,
3567 IOByteCount
* outputCount
)
3570 IOReturn err
= kIOReturnBadArgument
;
3574 if( (kIOUCVariableStructureSize
!= method
->count0
)
3575 && (inputCount
!= method
->count0
))
3577 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3580 if( (kIOUCVariableStructureSize
!= method
->count1
)
3581 && (*outputCount
!= method
->count1
))
3583 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3587 func
= method
->func
;
3589 if( method
->count1
) {
3590 if( method
->count0
) {
3591 err
= (object
->*func
)( input
, output
,
3592 (void *)inputCount
, outputCount
, 0, 0 );
3594 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
3597 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
3606 kern_return_t
shim_io_async_method_structureI_structureO(
3607 IOExternalAsyncMethod
* method
,
3609 mach_port_t asyncWakePort
,
3610 io_user_reference_t
* asyncReference
,
3611 uint32_t asyncReferenceCount
,
3612 io_struct_inband_t input
,
3613 mach_msg_type_number_t inputCount
,
3614 io_struct_inband_t output
,
3615 mach_msg_type_number_t
* outputCount
)
3620 io_async_ref_t reference
;
3622 for (i
= 0; i
< asyncReferenceCount
; i
++)
3623 reference
[i
] = REF32(asyncReference
[i
]);
3625 err
= kIOReturnBadArgument
;
3628 if( (kIOUCVariableStructureSize
!= method
->count0
)
3629 && (inputCount
!= method
->count0
))
3631 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3634 if( (kIOUCVariableStructureSize
!= method
->count1
)
3635 && (*outputCount
!= method
->count1
))
3637 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3641 func
= method
->func
;
3643 if( method
->count1
) {
3644 if( method
->count0
) {
3645 err
= (object
->*func
)( reference
,
3647 (void *)inputCount
, outputCount
, 0, 0 );
3649 err
= (object
->*func
)( reference
,
3650 output
, outputCount
, 0, 0, 0, 0 );
3653 err
= (object
->*func
)( reference
,
3654 input
, (void *)inputCount
, 0, 0, 0, 0 );
3662 /* Routine io_make_matching */
3663 kern_return_t
is_io_make_matching(
3664 mach_port_t master_port
,
3667 io_struct_inband_t input
,
3668 mach_msg_type_number_t inputCount
,
3669 io_string_t matching
)
3672 IOReturn err
= kIOReturnSuccess
;
3673 OSDictionary
* dict
;
3675 if( master_port
!= master_device_port
)
3676 return( kIOReturnNotPrivileged
);
3680 case kIOServiceMatching
:
3681 dict
= IOService::serviceMatching( gIOServiceKey
);
3684 case kIOBSDNameMatching
:
3685 dict
= IOBSDNameMatching( (const char *) input
);
3688 case kIOOFPathMatching
:
3689 dict
= IOOFPathMatching( (const char *) input
,
3690 matching
, sizeof( io_string_t
));
3698 return( kIOReturnUnsupported
);
3701 s
= OSSerialize::withCapacity(4096);
3703 err
= kIOReturnNoMemory
;
3707 if( !dict
->serialize( s
)) {
3708 err
= kIOReturnUnsupported
;
3712 if( s
->getLength() > sizeof( io_string_t
)) {
3713 err
= kIOReturnNoMemory
;
3716 strlcpy(matching
, s
->text(), sizeof(io_string_t
));
3728 /* Routine io_catalog_send_data */
3729 kern_return_t
is_io_catalog_send_data(
3730 mach_port_t master_port
,
3732 io_buf_ptr_t inData
,
3733 mach_msg_type_number_t inDataCount
,
3734 kern_return_t
* result
)
3738 kern_return_t kr
= kIOReturnError
;
3740 //printf("io_catalog_send_data called. flag: %d\n", flag);
3742 if( master_port
!= master_device_port
)
3743 return kIOReturnNotPrivileged
;
3745 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
3746 flag
!= kIOCatalogKextdActive
&&
3747 flag
!= kIOCatalogKextdFinishedLaunching
) &&
3748 ( !inData
|| !inDataCount
) )
3750 return kIOReturnBadArgument
;
3754 vm_map_offset_t map_data
;
3756 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
3757 data
= CAST_DOWN(vm_offset_t
, map_data
);
3759 if( kr
!= KERN_SUCCESS
)
3762 // must return success after vm_map_copyout() succeeds
3765 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
3766 vm_deallocate( kernel_map
, data
, inDataCount
);
3768 *result
= kIOReturnNoMemory
;
3769 return( KERN_SUCCESS
);
3775 case kIOCatalogAddDrivers
:
3776 case kIOCatalogAddDriversNoMatch
: {
3779 array
= OSDynamicCast(OSArray
, obj
);
3781 if ( !gIOCatalogue
->addDrivers( array
,
3782 flag
== kIOCatalogAddDrivers
) ) {
3783 kr
= kIOReturnError
;
3787 kr
= kIOReturnBadArgument
;
3792 case kIOCatalogRemoveDrivers
:
3793 case kIOCatalogRemoveDriversNoMatch
: {
3794 OSDictionary
* dict
;
3796 dict
= OSDynamicCast(OSDictionary
, obj
);
3798 if ( !gIOCatalogue
->removeDrivers( dict
,
3799 flag
== kIOCatalogRemoveDrivers
) ) {
3800 kr
= kIOReturnError
;
3804 kr
= kIOReturnBadArgument
;
3809 case kIOCatalogStartMatching
: {
3810 OSDictionary
* dict
;
3812 dict
= OSDynamicCast(OSDictionary
, obj
);
3814 if ( !gIOCatalogue
->startMatching( dict
) ) {
3815 kr
= kIOReturnError
;
3819 kr
= kIOReturnBadArgument
;
3824 case kIOCatalogRemoveKernelLinker
:
3825 kr
= KERN_NOT_SUPPORTED
;
3828 case kIOCatalogKextdActive
:
3830 OSKext::setKextdActive();
3832 /* Dump all nonloaded startup extensions; kextd will now send them
3835 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
3837 kr
= kIOReturnSuccess
;
3840 case kIOCatalogKextdFinishedLaunching
: {
3842 static bool clearedBusy
= false;
3845 IOService
* serviceRoot
= IOService::getServiceRoot();
3847 serviceRoot
->adjustBusy(-1);
3852 kr
= kIOReturnSuccess
;
3857 kr
= kIOReturnBadArgument
;
3861 if (obj
) obj
->release();
3864 return( KERN_SUCCESS
);
3867 /* Routine io_catalog_terminate */
3868 kern_return_t
is_io_catalog_terminate(
3869 mach_port_t master_port
,
3875 if( master_port
!= master_device_port
)
3876 return kIOReturnNotPrivileged
;
3878 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3879 kIOClientPrivilegeAdministrator
);
3880 if( kIOReturnSuccess
!= kr
)
3884 case kIOCatalogServiceTerminate
:
3886 IOService
* service
;
3888 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
3889 kIORegistryIterateRecursively
);
3891 return kIOReturnNoMemory
;
3895 while( (service
= (IOService
*)iter
->getNextObject()) ) {
3896 if( service
->metaCast(name
)) {
3897 if ( !service
->terminate( kIOServiceRequired
3898 | kIOServiceSynchronous
) ) {
3899 kr
= kIOReturnUnsupported
;
3904 } while( !service
&& !iter
->isValid());
3908 case kIOCatalogModuleUnload
:
3909 case kIOCatalogModuleTerminate
:
3910 kr
= gIOCatalogue
->terminateDriversForModule(name
,
3911 flag
== kIOCatalogModuleUnload
);
3915 kr
= kIOReturnBadArgument
;
3922 /* Routine io_catalog_get_data */
3923 kern_return_t
is_io_catalog_get_data(
3924 mach_port_t master_port
,
3926 io_buf_ptr_t
*outData
,
3927 mach_msg_type_number_t
*outDataCount
)
3929 kern_return_t kr
= kIOReturnSuccess
;
3932 if( master_port
!= master_device_port
)
3933 return kIOReturnNotPrivileged
;
3935 //printf("io_catalog_get_data called. flag: %d\n", flag);
3937 s
= OSSerialize::withCapacity(4096);
3939 return kIOReturnNoMemory
;
3943 kr
= gIOCatalogue
->serializeData(flag
, s
);
3945 if ( kr
== kIOReturnSuccess
) {
3950 size
= s
->getLength();
3951 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
3952 if ( kr
== kIOReturnSuccess
) {
3953 bcopy(s
->text(), (void *)data
, size
);
3954 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
3955 (vm_map_size_t
)size
, true, ©
);
3956 *outData
= (char *)copy
;
3957 *outDataCount
= size
;
3966 /* Routine io_catalog_get_gen_count */
3967 kern_return_t
is_io_catalog_get_gen_count(
3968 mach_port_t master_port
,
3971 if( master_port
!= master_device_port
)
3972 return kIOReturnNotPrivileged
;
3974 //printf("io_catalog_get_gen_count called.\n");
3977 return kIOReturnBadArgument
;
3979 *genCount
= gIOCatalogue
->getGenerationCount();
3981 return kIOReturnSuccess
;
3984 /* Routine io_catalog_module_loaded.
3985 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
3987 kern_return_t
is_io_catalog_module_loaded(
3988 mach_port_t master_port
,
3991 if( master_port
!= master_device_port
)
3992 return kIOReturnNotPrivileged
;
3994 //printf("io_catalog_module_loaded called. name %s\n", name);
3997 return kIOReturnBadArgument
;
3999 gIOCatalogue
->moduleHasLoaded(name
);
4001 return kIOReturnSuccess
;
4004 kern_return_t
is_io_catalog_reset(
4005 mach_port_t master_port
,
4008 if( master_port
!= master_device_port
)
4009 return kIOReturnNotPrivileged
;
4012 case kIOCatalogResetDefault
:
4013 gIOCatalogue
->reset();
4017 return kIOReturnBadArgument
;
4020 return kIOReturnSuccess
;
4023 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
4025 kern_return_t result
= kIOReturnBadArgument
;
4026 IOUserClient
*userClient
;
4028 if ((userClient
= OSDynamicCast(IOUserClient
,
4029 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
4030 IOExternalTrap
*trap
;
4031 IOService
*target
= NULL
;
4033 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
4035 if (trap
&& target
) {
4041 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
4045 userClient
->release();
4051 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
4052 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
4056 IOByteCount structureOutputSize
;
4061 count
= dispatch
->checkScalarInputCount
;
4062 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
4064 return (kIOReturnBadArgument
);
4067 count
= dispatch
->checkStructureInputSize
;
4068 if ((kIOUCVariableStructureSize
!= count
)
4069 && (count
!= ((args
->structureInputDescriptor
)
4070 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
4072 return (kIOReturnBadArgument
);
4075 count
= dispatch
->checkScalarOutputCount
;
4076 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
4078 return (kIOReturnBadArgument
);
4081 count
= dispatch
->checkStructureOutputSize
;
4082 if ((kIOUCVariableStructureSize
!= count
)
4083 && (count
!= ((args
->structureOutputDescriptor
)
4084 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
4086 return (kIOReturnBadArgument
);
4089 if (dispatch
->function
)
4090 err
= (*dispatch
->function
)(target
, reference
, args
);
4092 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
4098 // pre-Leopard API's don't do ool structs
4099 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
4101 err
= kIOReturnIPCError
;
4105 structureOutputSize
= args
->structureOutputSize
;
4107 if (args
->asyncWakePort
)
4109 IOExternalAsyncMethod
* method
;
4111 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) )
4112 return (kIOReturnUnsupported
);
4114 if (kIOUCForegroundOnly
& method
->flags
)
4117 kern_return_t kr
= IOUCIsBackgroundTask(current_task(), &isBg
);
4119 if ((KERN_SUCCESS
== kr
) && isBg
)
4120 return (kIOReturnNotPermitted
);
4123 switch (method
->flags
& kIOUCTypeMask
)
4125 case kIOUCScalarIStructI
:
4126 err
= shim_io_async_method_scalarI_structureI( method
, object
,
4127 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4128 args
->scalarInput
, args
->scalarInputCount
,
4129 (char *)args
->structureInput
, args
->structureInputSize
);
4132 case kIOUCScalarIScalarO
:
4133 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
4134 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4135 args
->scalarInput
, args
->scalarInputCount
,
4136 args
->scalarOutput
, &args
->scalarOutputCount
);
4139 case kIOUCScalarIStructO
:
4140 err
= shim_io_async_method_scalarI_structureO( method
, object
,
4141 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4142 args
->scalarInput
, args
->scalarInputCount
,
4143 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4147 case kIOUCStructIStructO
:
4148 err
= shim_io_async_method_structureI_structureO( method
, object
,
4149 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4150 (char *)args
->structureInput
, args
->structureInputSize
,
4151 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4155 err
= kIOReturnBadArgument
;
4161 IOExternalMethod
* method
;
4163 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) )
4164 return (kIOReturnUnsupported
);
4166 if (kIOUCForegroundOnly
& method
->flags
)
4169 kern_return_t kr
= IOUCIsBackgroundTask(current_task(), &isBg
);
4171 if ((KERN_SUCCESS
== kr
) && isBg
)
4172 return (kIOReturnNotPermitted
);
4175 switch (method
->flags
& kIOUCTypeMask
)
4177 case kIOUCScalarIStructI
:
4178 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
4179 args
->scalarInput
, args
->scalarInputCount
,
4180 (char *) args
->structureInput
, args
->structureInputSize
);
4183 case kIOUCScalarIScalarO
:
4184 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
4185 args
->scalarInput
, args
->scalarInputCount
,
4186 args
->scalarOutput
, &args
->scalarOutputCount
);
4189 case kIOUCScalarIStructO
:
4190 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
4191 args
->scalarInput
, args
->scalarInputCount
,
4192 (char *) args
->structureOutput
, &structureOutputSize
);
4196 case kIOUCStructIStructO
:
4197 err
= shim_io_connect_method_structureI_structureO( method
, object
,
4198 (char *) args
->structureInput
, args
->structureInputSize
,
4199 (char *) args
->structureOutput
, &structureOutputSize
);
4203 err
= kIOReturnBadArgument
;
4208 args
->structureOutputSize
= structureOutputSize
;
4217 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
4218 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
4220 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
4221 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
4223 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
4224 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
4225 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
4226 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
4227 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
4228 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
4229 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
4230 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
4231 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
4232 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
4233 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
4234 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
4235 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
4236 OSMetaClassDefineReservedUnused(IOUserClient
, 15);