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 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
855 const char * privilegeName
)
858 security_token_t token
;
859 mach_msg_type_number_t count
;
864 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
865 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
866 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
868 task
= (task_t
)securityToken
;
870 count
= TASK_SECURITY_TOKEN_COUNT
;
871 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
873 if (KERN_SUCCESS
!= kr
)
875 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
876 sizeof(kIOClientPrivilegeAdministrator
))) {
877 if (0 != token
.val
[0])
878 kr
= kIOReturnNotPrivileged
;
879 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
880 sizeof(kIOClientPrivilegeLocalUser
))) {
881 user
= CopyConsoleUser(token
.val
[0]);
885 kr
= kIOReturnNotPrivileged
;
886 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
887 sizeof(kIOClientPrivilegeConsoleUser
))) {
888 user
= CopyConsoleUser(token
.val
[0]);
890 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
891 kr
= kIOReturnNotPrivileged
;
892 else if ( secureConsole
) {
893 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
894 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
895 kr
= kIOReturnNotPrivileged
;
900 kr
= kIOReturnNotPrivileged
;
902 kr
= kIOReturnUnsupported
;
907 bool IOUserClient::init()
909 if( getPropertyTable())
912 return super::init();
915 bool IOUserClient::init(OSDictionary
* dictionary
)
917 if( getPropertyTable())
920 return super::init(dictionary
);
923 bool IOUserClient::initWithTask(task_t owningTask
,
927 if( getPropertyTable())
930 return super::init();
933 bool IOUserClient::initWithTask(task_t owningTask
,
936 OSDictionary
* properties
)
940 ok
= super::init( properties
);
941 ok
&= initWithTask( owningTask
, securityID
, type
);
946 void IOUserClient::free()
954 IOReturn
IOUserClient::clientDied( void )
956 return( clientClose());
959 IOReturn
IOUserClient::clientClose( void )
961 return( kIOReturnUnsupported
);
964 IOService
* IOUserClient::getService( void )
969 IOReturn
IOUserClient::registerNotificationPort(
970 mach_port_t
/* port */,
974 return( kIOReturnUnsupported
);
977 IOReturn
IOUserClient::registerNotificationPort(
980 io_user_reference_t refCon
)
982 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
985 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
986 semaphore_t
* semaphore
)
988 return( kIOReturnUnsupported
);
991 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
993 return( kIOReturnUnsupported
);
996 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
997 IOOptionBits
* options
,
998 IOMemoryDescriptor
** memory
)
1000 return( kIOReturnUnsupported
);
1004 IOMemoryMap
* IOUserClient::mapClientMemory(
1007 IOOptionBits mapFlags
,
1008 IOVirtualAddress atAddress
)
1014 IOMemoryMap
* IOUserClient::mapClientMemory64(
1017 IOOptionBits mapFlags
,
1018 mach_vm_address_t atAddress
)
1021 IOOptionBits options
= 0;
1022 IOMemoryDescriptor
* memory
;
1023 IOMemoryMap
* map
= 0;
1025 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1027 if( memory
&& (kIOReturnSuccess
== err
)) {
1029 options
= (options
& ~kIOMapUserOptionsMask
)
1030 | (mapFlags
& kIOMapUserOptionsMask
);
1031 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1038 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1039 OSObject
*obj
, io_object_t
*clientObj
)
1041 mach_port_name_t name
;
1043 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1046 *(mach_port_name_t
*)clientObj
= name
;
1047 return kIOReturnSuccess
;
1050 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1055 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1060 IOExternalMethod
* IOUserClient::
1061 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1063 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1066 *targetP
= (IOService
*) method
->object
;
1071 IOExternalAsyncMethod
* IOUserClient::
1072 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1074 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1077 *targetP
= (IOService
*) method
->object
;
1082 IOExternalTrap
* IOUserClient::
1083 getExternalTrapForIndex(UInt32 index
)
1088 IOExternalTrap
* IOUserClient::
1089 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1091 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1094 *targetP
= trap
->object
;
1100 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1103 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1105 if (MACH_PORT_NULL
!= port
)
1106 iokit_release_port_send(port
);
1108 return (kIOReturnSuccess
);
1111 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1113 if (MACH_PORT_NULL
!= port
)
1114 iokit_release_port_send(port
);
1116 return (kIOReturnSuccess
);
1119 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1120 IOReturn result
, void *args
[], UInt32 numArgs
)
1122 OSAsyncReference64 reference64
;
1123 io_user_reference_t args64
[kMaxAsyncArgs
];
1126 if (numArgs
> kMaxAsyncArgs
)
1127 return kIOReturnMessageTooLarge
;
1129 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1130 reference64
[idx
] = REF64(reference
[idx
]);
1132 for (idx
= 0; idx
< numArgs
; idx
++)
1133 args64
[idx
] = REF64(args
[idx
]);
1135 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1138 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1139 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1143 mach_msg_header_t msgHdr
;
1148 OSNotificationHeader notifyHdr
;
1149 IOAsyncCompletionContent asyncContent
;
1150 uint32_t args
[kMaxAsyncArgs
];
1154 OSNotificationHeader64 notifyHdr
;
1155 IOAsyncCompletionContent asyncContent
;
1156 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1161 mach_port_t replyPort
;
1164 // If no reply port, do nothing.
1165 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1166 if (replyPort
== MACH_PORT_NULL
)
1167 return kIOReturnSuccess
;
1169 if (numArgs
> kMaxAsyncArgs
)
1170 return kIOReturnMessageTooLarge
;
1172 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1174 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1175 replyMsg
.msgHdr
.msgh_local_port
= 0;
1176 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1177 if (kIOUCAsync64Flag
& reference
[0])
1179 replyMsg
.msgHdr
.msgh_size
=
1180 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1181 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1182 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1183 + numArgs
* sizeof(io_user_reference_t
);
1184 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1185 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1187 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1189 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1195 replyMsg
.msgHdr
.msgh_size
=
1196 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1197 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1199 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1200 + numArgs
* sizeof(uint32_t);
1201 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1203 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1204 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1206 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1208 for (idx
= 0; idx
< numArgs
; idx
++)
1209 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1212 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1213 replyMsg
.msgHdr
.msgh_size
);
1214 if( KERN_SUCCESS
!= kr
)
1215 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1220 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1224 #define CHECK(cls,obj,out) \
1226 if( !(out = OSDynamicCast( cls, obj))) \
1227 return( kIOReturnBadArgument )
1229 /* Routine io_object_get_class */
1230 kern_return_t
is_io_object_get_class(
1232 io_name_t className
)
1234 const OSMetaClass
* my_obj
= NULL
;
1237 return( kIOReturnBadArgument
);
1239 my_obj
= object
->getMetaClass();
1241 return (kIOReturnNotFound
);
1244 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1245 return( kIOReturnSuccess
);
1248 /* Routine io_object_get_superclass */
1249 kern_return_t
is_io_object_get_superclass(
1250 mach_port_t master_port
,
1252 io_name_t class_name
)
1254 const OSMetaClass
* my_obj
= NULL
;
1255 const OSMetaClass
* superclass
= NULL
;
1256 const OSSymbol
*my_name
= NULL
;
1257 const char *my_cstr
= NULL
;
1259 if (!obj_name
|| !class_name
)
1260 return (kIOReturnBadArgument
);
1262 if( master_port
!= master_device_port
)
1263 return( kIOReturnNotPrivileged
);
1265 my_name
= OSSymbol::withCString(obj_name
);
1268 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1272 superclass
= my_obj
->getSuperClass();
1276 return( kIOReturnNotFound
);
1279 my_cstr
= superclass
->getClassName();
1282 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1283 return( kIOReturnSuccess
);
1285 return (kIOReturnNotFound
);
1288 /* Routine io_object_get_bundle_identifier */
1289 kern_return_t
is_io_object_get_bundle_identifier(
1290 mach_port_t master_port
,
1292 io_name_t bundle_name
)
1294 const OSMetaClass
* my_obj
= NULL
;
1295 const OSSymbol
*my_name
= NULL
;
1296 const OSSymbol
*identifier
= NULL
;
1297 const char *my_cstr
= NULL
;
1299 if (!obj_name
|| !bundle_name
)
1300 return (kIOReturnBadArgument
);
1302 if( master_port
!= master_device_port
)
1303 return( kIOReturnNotPrivileged
);
1305 my_name
= OSSymbol::withCString(obj_name
);
1308 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1313 identifier
= my_obj
->getKmodName();
1316 return( kIOReturnNotFound
);
1319 my_cstr
= identifier
->getCStringNoCopy();
1321 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1322 return( kIOReturnSuccess
);
1325 return (kIOReturnBadArgument
);
1328 /* Routine io_object_conforms_to */
1329 kern_return_t
is_io_object_conforms_to(
1331 io_name_t className
,
1332 boolean_t
*conforms
)
1335 return( kIOReturnBadArgument
);
1337 *conforms
= (0 != object
->metaCast( className
));
1338 return( kIOReturnSuccess
);
1341 /* Routine io_object_get_retain_count */
1342 kern_return_t
is_io_object_get_retain_count(
1344 uint32_t *retainCount
)
1347 return( kIOReturnBadArgument
);
1349 *retainCount
= object
->getRetainCount();
1350 return( kIOReturnSuccess
);
1353 /* Routine io_iterator_next */
1354 kern_return_t
is_io_iterator_next(
1355 io_object_t iterator
,
1356 io_object_t
*object
)
1360 CHECK( OSIterator
, iterator
, iter
);
1362 obj
= iter
->getNextObject();
1366 return( kIOReturnSuccess
);
1368 return( kIOReturnNoDevice
);
1371 /* Routine io_iterator_reset */
1372 kern_return_t
is_io_iterator_reset(
1373 io_object_t iterator
)
1375 CHECK( OSIterator
, iterator
, iter
);
1379 return( kIOReturnSuccess
);
1382 /* Routine io_iterator_is_valid */
1383 kern_return_t
is_io_iterator_is_valid(
1384 io_object_t iterator
,
1385 boolean_t
*is_valid
)
1387 CHECK( OSIterator
, iterator
, iter
);
1389 *is_valid
= iter
->isValid();
1391 return( kIOReturnSuccess
);
1394 /* Routine io_service_match_property_table */
1395 kern_return_t
is_io_service_match_property_table(
1396 io_service_t _service
,
1397 io_string_t matching
,
1398 boolean_t
*matches
)
1400 CHECK( IOService
, _service
, service
);
1404 OSDictionary
* dict
;
1406 obj
= OSUnserializeXML( matching
);
1408 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1409 *matches
= service
->passiveMatch( dict
);
1410 kr
= kIOReturnSuccess
;
1412 kr
= kIOReturnBadArgument
;
1420 /* Routine io_service_match_property_table_ool */
1421 kern_return_t
is_io_service_match_property_table_ool(
1422 io_object_t service
,
1423 io_buf_ptr_t matching
,
1424 mach_msg_type_number_t matchingCnt
,
1425 kern_return_t
*result
,
1426 boolean_t
*matches
)
1430 vm_map_offset_t map_data
;
1432 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1433 data
= CAST_DOWN(vm_offset_t
, map_data
);
1435 if( KERN_SUCCESS
== kr
) {
1436 // must return success after vm_map_copyout() succeeds
1437 *result
= is_io_service_match_property_table( service
,
1438 (char *) data
, matches
);
1439 vm_deallocate( kernel_map
, data
, matchingCnt
);
1445 /* Routine io_service_get_matching_services */
1446 kern_return_t
is_io_service_get_matching_services(
1447 mach_port_t master_port
,
1448 io_string_t matching
,
1449 io_iterator_t
*existing
)
1453 OSDictionary
* dict
;
1455 if( master_port
!= master_device_port
)
1456 return( kIOReturnNotPrivileged
);
1458 obj
= OSUnserializeXML( matching
);
1460 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1461 *existing
= IOService::getMatchingServices( dict
);
1462 kr
= kIOReturnSuccess
;
1464 kr
= kIOReturnBadArgument
;
1472 /* Routine io_service_get_matching_services_ool */
1473 kern_return_t
is_io_service_get_matching_services_ool(
1474 mach_port_t master_port
,
1475 io_buf_ptr_t matching
,
1476 mach_msg_type_number_t matchingCnt
,
1477 kern_return_t
*result
,
1478 io_object_t
*existing
)
1482 vm_map_offset_t map_data
;
1484 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1485 data
= CAST_DOWN(vm_offset_t
, map_data
);
1487 if( KERN_SUCCESS
== kr
) {
1488 // must return success after vm_map_copyout() succeeds
1489 *result
= is_io_service_get_matching_services( master_port
,
1490 (char *) data
, existing
);
1491 vm_deallocate( kernel_map
, data
, matchingCnt
);
1497 static kern_return_t
internal_io_service_add_notification(
1498 mach_port_t master_port
,
1499 io_name_t notification_type
,
1500 io_string_t matching
,
1503 vm_size_t referenceSize
,
1505 io_object_t
* notification
)
1507 IOServiceUserNotification
* userNotify
= 0;
1508 IONotifier
* notify
= 0;
1509 const OSSymbol
* sym
;
1510 OSDictionary
* dict
;
1512 unsigned long int userMsgType
;
1515 if( master_port
!= master_device_port
)
1516 return( kIOReturnNotPrivileged
);
1519 err
= kIOReturnNoResources
;
1521 if( !(sym
= OSSymbol::withCString( notification_type
)))
1522 err
= kIOReturnNoResources
;
1524 if( !(dict
= OSDynamicCast( OSDictionary
,
1525 OSUnserializeXML( matching
)))) {
1526 err
= kIOReturnBadArgument
;
1530 if( (sym
== gIOPublishNotification
)
1531 || (sym
== gIOFirstPublishNotification
))
1532 userMsgType
= kIOServicePublishNotificationType
;
1533 else if( (sym
== gIOMatchedNotification
)
1534 || (sym
== gIOFirstMatchNotification
))
1535 userMsgType
= kIOServiceMatchedNotificationType
;
1536 else if( sym
== gIOTerminatedNotification
)
1537 userMsgType
= kIOServiceTerminatedNotificationType
;
1539 userMsgType
= kLastIOKitNotificationType
;
1541 userNotify
= new IOServiceUserNotification
;
1543 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1544 reference
, referenceSize
, client64
)) {
1545 userNotify
->release();
1551 notify
= IOService::addMatchingNotification( sym
, dict
,
1552 &userNotify
->_handler
, userNotify
);
1554 *notification
= userNotify
;
1555 userNotify
->setNotification( notify
);
1556 err
= kIOReturnSuccess
;
1558 err
= kIOReturnUnsupported
;
1571 /* Routine io_service_add_notification */
1572 kern_return_t
is_io_service_add_notification(
1573 mach_port_t master_port
,
1574 io_name_t notification_type
,
1575 io_string_t matching
,
1577 io_async_ref_t reference
,
1578 mach_msg_type_number_t referenceCnt
,
1579 io_object_t
* notification
)
1581 return (internal_io_service_add_notification(master_port
, notification_type
,
1582 matching
, port
, &reference
[0], sizeof(io_async_ref_t
),
1583 false, notification
));
1586 /* Routine io_service_add_notification_64 */
1587 kern_return_t
is_io_service_add_notification_64(
1588 mach_port_t master_port
,
1589 io_name_t notification_type
,
1590 io_string_t matching
,
1591 mach_port_t wake_port
,
1592 io_async_ref64_t reference
,
1593 mach_msg_type_number_t referenceCnt
,
1594 io_object_t
*notification
)
1596 return (internal_io_service_add_notification(master_port
, notification_type
,
1597 matching
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1598 true, notification
));
1602 static kern_return_t
internal_io_service_add_notification_ool(
1603 mach_port_t master_port
,
1604 io_name_t notification_type
,
1605 io_buf_ptr_t matching
,
1606 mach_msg_type_number_t matchingCnt
,
1607 mach_port_t wake_port
,
1609 vm_size_t referenceSize
,
1611 kern_return_t
*result
,
1612 io_object_t
*notification
)
1616 vm_map_offset_t map_data
;
1618 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1619 data
= CAST_DOWN(vm_offset_t
, map_data
);
1621 if( KERN_SUCCESS
== kr
) {
1622 // must return success after vm_map_copyout() succeeds
1623 *result
= internal_io_service_add_notification( master_port
, notification_type
,
1624 (char *) data
, wake_port
, reference
, referenceSize
, client64
, notification
);
1625 vm_deallocate( kernel_map
, data
, matchingCnt
);
1631 /* Routine io_service_add_notification_ool */
1632 kern_return_t
is_io_service_add_notification_ool(
1633 mach_port_t master_port
,
1634 io_name_t notification_type
,
1635 io_buf_ptr_t matching
,
1636 mach_msg_type_number_t matchingCnt
,
1637 mach_port_t wake_port
,
1638 io_async_ref_t reference
,
1639 mach_msg_type_number_t referenceCnt
,
1640 kern_return_t
*result
,
1641 io_object_t
*notification
)
1643 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1644 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
1645 false, result
, notification
));
1648 /* Routine io_service_add_notification_ool_64 */
1649 kern_return_t
is_io_service_add_notification_ool_64(
1650 mach_port_t master_port
,
1651 io_name_t notification_type
,
1652 io_buf_ptr_t matching
,
1653 mach_msg_type_number_t matchingCnt
,
1654 mach_port_t wake_port
,
1655 io_async_ref64_t reference
,
1656 mach_msg_type_number_t referenceCnt
,
1657 kern_return_t
*result
,
1658 io_object_t
*notification
)
1660 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1661 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1662 true, result
, notification
));
1665 /* Routine io_service_add_notification_old */
1666 kern_return_t
is_io_service_add_notification_old(
1667 mach_port_t master_port
,
1668 io_name_t notification_type
,
1669 io_string_t matching
,
1671 // for binary compatibility reasons, this must be natural_t for ILP32
1673 io_object_t
* notification
)
1675 return( is_io_service_add_notification( master_port
, notification_type
,
1676 matching
, port
, &ref
, 1, notification
));
1680 static kern_return_t
internal_io_service_add_interest_notification(
1681 io_object_t _service
,
1682 io_name_t type_of_interest
,
1685 vm_size_t referenceSize
,
1687 io_object_t
* notification
)
1690 IOServiceMessageUserNotification
* userNotify
= 0;
1691 IONotifier
* notify
= 0;
1692 const OSSymbol
* sym
;
1695 CHECK( IOService
, _service
, service
);
1697 err
= kIOReturnNoResources
;
1698 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1700 userNotify
= new IOServiceMessageUserNotification
;
1702 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1703 reference
, referenceSize
,
1704 kIOUserNotifyMaxMessageSize
,
1706 userNotify
->release();
1712 notify
= service
->registerInterest( sym
,
1713 &userNotify
->_handler
, userNotify
);
1715 *notification
= userNotify
;
1716 userNotify
->setNotification( notify
);
1717 err
= kIOReturnSuccess
;
1719 err
= kIOReturnUnsupported
;
1728 /* Routine io_service_add_message_notification */
1729 kern_return_t
is_io_service_add_interest_notification(
1730 io_object_t service
,
1731 io_name_t type_of_interest
,
1733 io_async_ref_t reference
,
1734 mach_msg_type_number_t referenceCnt
,
1735 io_object_t
* notification
)
1737 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1738 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
1741 /* Routine io_service_add_interest_notification_64 */
1742 kern_return_t
is_io_service_add_interest_notification_64(
1743 io_object_t service
,
1744 io_name_t type_of_interest
,
1745 mach_port_t wake_port
,
1746 io_async_ref64_t reference
,
1747 mach_msg_type_number_t referenceCnt
,
1748 io_object_t
*notification
)
1750 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1751 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
1755 /* Routine io_service_acknowledge_notification */
1756 kern_return_t
is_io_service_acknowledge_notification(
1757 io_object_t _service
,
1758 natural_t notify_ref
,
1759 natural_t response
)
1761 CHECK( IOService
, _service
, service
);
1763 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1764 (IOOptionBits
) response
));
1768 /* Routine io_connect_get_semaphore */
1769 kern_return_t
is_io_connect_get_notification_semaphore(
1770 io_connect_t connection
,
1771 natural_t notification_type
,
1772 semaphore_t
*semaphore
)
1774 CHECK( IOUserClient
, connection
, client
);
1776 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1780 /* Routine io_registry_get_root_entry */
1781 kern_return_t
is_io_registry_get_root_entry(
1782 mach_port_t master_port
,
1785 IORegistryEntry
* entry
;
1787 if( master_port
!= master_device_port
)
1788 return( kIOReturnNotPrivileged
);
1790 entry
= IORegistryEntry::getRegistryRoot();
1795 return( kIOReturnSuccess
);
1798 /* Routine io_registry_create_iterator */
1799 kern_return_t
is_io_registry_create_iterator(
1800 mach_port_t master_port
,
1803 io_object_t
*iterator
)
1805 if( master_port
!= master_device_port
)
1806 return( kIOReturnNotPrivileged
);
1808 *iterator
= IORegistryIterator::iterateOver(
1809 IORegistryEntry::getPlane( plane
), options
);
1811 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1814 /* Routine io_registry_entry_create_iterator */
1815 kern_return_t
is_io_registry_entry_create_iterator(
1816 io_object_t registry_entry
,
1819 io_object_t
*iterator
)
1821 CHECK( IORegistryEntry
, registry_entry
, entry
);
1823 *iterator
= IORegistryIterator::iterateOver( entry
,
1824 IORegistryEntry::getPlane( plane
), options
);
1826 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1829 /* Routine io_registry_iterator_enter */
1830 kern_return_t
is_io_registry_iterator_enter_entry(
1831 io_object_t iterator
)
1833 CHECK( IORegistryIterator
, iterator
, iter
);
1837 return( kIOReturnSuccess
);
1840 /* Routine io_registry_iterator_exit */
1841 kern_return_t
is_io_registry_iterator_exit_entry(
1842 io_object_t iterator
)
1846 CHECK( IORegistryIterator
, iterator
, iter
);
1848 didIt
= iter
->exitEntry();
1850 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1853 /* Routine io_registry_entry_from_path */
1854 kern_return_t
is_io_registry_entry_from_path(
1855 mach_port_t master_port
,
1857 io_object_t
*registry_entry
)
1859 IORegistryEntry
* entry
;
1861 if( master_port
!= master_device_port
)
1862 return( kIOReturnNotPrivileged
);
1864 entry
= IORegistryEntry::fromPath( path
);
1866 *registry_entry
= entry
;
1868 return( kIOReturnSuccess
);
1871 /* Routine io_registry_entry_in_plane */
1872 kern_return_t
is_io_registry_entry_in_plane(
1873 io_object_t registry_entry
,
1875 boolean_t
*inPlane
)
1877 CHECK( IORegistryEntry
, registry_entry
, entry
);
1879 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1881 return( kIOReturnSuccess
);
1885 /* Routine io_registry_entry_get_path */
1886 kern_return_t
is_io_registry_entry_get_path(
1887 io_object_t registry_entry
,
1892 CHECK( IORegistryEntry
, registry_entry
, entry
);
1894 length
= sizeof( io_string_t
);
1895 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1896 return( kIOReturnSuccess
);
1898 return( kIOReturnBadArgument
);
1902 /* Routine io_registry_entry_get_name */
1903 kern_return_t
is_io_registry_entry_get_name(
1904 io_object_t registry_entry
,
1907 CHECK( IORegistryEntry
, registry_entry
, entry
);
1909 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1911 return( kIOReturnSuccess
);
1914 /* Routine io_registry_entry_get_name_in_plane */
1915 kern_return_t
is_io_registry_entry_get_name_in_plane(
1916 io_object_t registry_entry
,
1917 io_name_t planeName
,
1920 const IORegistryPlane
* plane
;
1921 CHECK( IORegistryEntry
, registry_entry
, entry
);
1924 plane
= IORegistryEntry::getPlane( planeName
);
1928 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1930 return( kIOReturnSuccess
);
1933 /* Routine io_registry_entry_get_location_in_plane */
1934 kern_return_t
is_io_registry_entry_get_location_in_plane(
1935 io_object_t registry_entry
,
1936 io_name_t planeName
,
1937 io_name_t location
)
1939 const IORegistryPlane
* plane
;
1940 CHECK( IORegistryEntry
, registry_entry
, entry
);
1943 plane
= IORegistryEntry::getPlane( planeName
);
1947 const char * cstr
= entry
->getLocation( plane
);
1950 strncpy( location
, cstr
, sizeof( io_name_t
));
1951 return( kIOReturnSuccess
);
1953 return( kIOReturnNotFound
);
1956 /* Routine io_registry_entry_get_registry_entry_id */
1957 kern_return_t
is_io_registry_entry_get_registry_entry_id(
1958 io_object_t registry_entry
,
1959 uint64_t *entry_id
)
1961 CHECK( IORegistryEntry
, registry_entry
, entry
);
1963 *entry_id
= entry
->getRegistryEntryID();
1965 return (kIOReturnSuccess
);
1968 // Create a vm_map_copy_t or kalloc'ed data for memory
1969 // to be copied out. ipc will free after the copyout.
1971 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1972 io_buf_ptr_t
* buf
)
1977 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1978 false /* src_destroy */, ©
);
1980 assert( err
== KERN_SUCCESS
);
1981 if( err
== KERN_SUCCESS
)
1982 *buf
= (char *) copy
;
1987 /* Routine io_registry_entry_get_property */
1988 kern_return_t
is_io_registry_entry_get_property_bytes(
1989 io_object_t registry_entry
,
1990 io_name_t property_name
,
1991 io_struct_inband_t buf
,
1992 mach_msg_type_number_t
*dataCnt
)
2000 unsigned int len
= 0;
2001 const void * bytes
= 0;
2002 IOReturn ret
= kIOReturnSuccess
;
2004 CHECK( IORegistryEntry
, registry_entry
, entry
);
2006 obj
= entry
->copyProperty(property_name
);
2008 return( kIOReturnNoResources
);
2010 // One day OSData will be a common container base class
2012 if( (data
= OSDynamicCast( OSData
, obj
))) {
2013 len
= data
->getLength();
2014 bytes
= data
->getBytesNoCopy();
2016 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2017 len
= str
->getLength() + 1;
2018 bytes
= str
->getCStringNoCopy();
2020 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2021 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2022 bytes
= boo
->isTrue() ? "Yes" : "No";
2024 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2025 offsetBytes
= off
->unsigned64BitValue();
2026 len
= off
->numberOfBytes();
2027 bytes
= &offsetBytes
;
2028 #ifdef __BIG_ENDIAN__
2029 bytes
= (const void *)
2030 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2034 ret
= kIOReturnBadArgument
;
2038 ret
= kIOReturnIPCError
;
2041 bcopy( bytes
, buf
, len
);
2050 /* Routine io_registry_entry_get_property */
2051 kern_return_t
is_io_registry_entry_get_property(
2052 io_object_t registry_entry
,
2053 io_name_t property_name
,
2054 io_buf_ptr_t
*properties
,
2055 mach_msg_type_number_t
*propertiesCnt
)
2061 CHECK( IORegistryEntry
, registry_entry
, entry
);
2063 obj
= entry
->copyProperty(property_name
);
2065 return( kIOReturnNotFound
);
2067 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2070 return( kIOReturnNoMemory
);
2074 if( obj
->serialize( s
)) {
2075 len
= s
->getLength();
2076 *propertiesCnt
= len
;
2077 err
= copyoutkdata( s
->text(), len
, properties
);
2080 err
= kIOReturnUnsupported
;
2088 /* Routine io_registry_entry_get_property_recursively */
2089 kern_return_t
is_io_registry_entry_get_property_recursively(
2090 io_object_t registry_entry
,
2092 io_name_t property_name
,
2094 io_buf_ptr_t
*properties
,
2095 mach_msg_type_number_t
*propertiesCnt
)
2101 CHECK( IORegistryEntry
, registry_entry
, entry
);
2103 obj
= entry
->copyProperty( property_name
,
2104 IORegistryEntry::getPlane( plane
), options
);
2106 return( kIOReturnNotFound
);
2108 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2111 return( kIOReturnNoMemory
);
2116 if( obj
->serialize( s
)) {
2117 len
= s
->getLength();
2118 *propertiesCnt
= len
;
2119 err
= copyoutkdata( s
->text(), len
, properties
);
2122 err
= kIOReturnUnsupported
;
2130 /* Routine io_registry_entry_get_properties */
2131 kern_return_t
is_io_registry_entry_get_properties(
2132 io_object_t registry_entry
,
2133 io_buf_ptr_t
*properties
,
2134 mach_msg_type_number_t
*propertiesCnt
)
2139 CHECK( IORegistryEntry
, registry_entry
, entry
);
2141 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2143 return( kIOReturnNoMemory
);
2147 if( entry
->serializeProperties( s
)) {
2148 len
= s
->getLength();
2149 *propertiesCnt
= len
;
2150 err
= copyoutkdata( s
->text(), len
, properties
);
2153 err
= kIOReturnUnsupported
;
2160 /* Routine io_registry_entry_set_properties */
2161 kern_return_t is_io_registry_entry_set_properties
2163 io_object_t registry_entry
,
2164 io_buf_ptr_t properties
,
2165 mach_msg_type_number_t propertiesCnt
,
2166 kern_return_t
* result
)
2172 vm_map_offset_t map_data
;
2174 CHECK( IORegistryEntry
, registry_entry
, entry
);
2176 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2177 data
= CAST_DOWN(vm_offset_t
, map_data
);
2179 if( KERN_SUCCESS
== err
) {
2181 // must return success after vm_map_copyout() succeeds
2182 obj
= OSUnserializeXML( (const char *) data
);
2183 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2186 res
= entry
->setProperties( obj
);
2189 res
= kIOReturnBadArgument
;
2197 /* Routine io_registry_entry_get_child_iterator */
2198 kern_return_t
is_io_registry_entry_get_child_iterator(
2199 io_object_t registry_entry
,
2201 io_object_t
*iterator
)
2203 CHECK( IORegistryEntry
, registry_entry
, entry
);
2205 *iterator
= entry
->getChildIterator(
2206 IORegistryEntry::getPlane( plane
));
2208 return( kIOReturnSuccess
);
2211 /* Routine io_registry_entry_get_parent_iterator */
2212 kern_return_t
is_io_registry_entry_get_parent_iterator(
2213 io_object_t registry_entry
,
2215 io_object_t
*iterator
)
2217 CHECK( IORegistryEntry
, registry_entry
, entry
);
2219 *iterator
= entry
->getParentIterator(
2220 IORegistryEntry::getPlane( plane
));
2222 return( kIOReturnSuccess
);
2225 /* Routine io_service_get_busy_state */
2226 kern_return_t
is_io_service_get_busy_state(
2227 io_object_t _service
,
2228 uint32_t *busyState
)
2230 CHECK( IOService
, _service
, service
);
2232 *busyState
= service
->getBusyState();
2234 return( kIOReturnSuccess
);
2237 /* Routine io_service_get_state */
2238 kern_return_t
is_io_service_get_state(
2239 io_object_t _service
,
2241 uint32_t *busy_state
,
2242 uint64_t *accumulated_busy_time
)
2244 CHECK( IOService
, _service
, service
);
2246 *state
= service
->getState();
2247 *busy_state
= service
->getBusyState();
2248 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
2250 return( kIOReturnSuccess
);
2253 /* Routine io_service_wait_quiet */
2254 kern_return_t
is_io_service_wait_quiet(
2255 io_object_t _service
,
2256 mach_timespec_t wait_time
)
2260 CHECK( IOService
, _service
, service
);
2262 timeoutNS
= wait_time
.tv_sec
;
2263 timeoutNS
*= kSecondScale
;
2264 timeoutNS
+= wait_time
.tv_nsec
;
2266 return( service
->waitQuiet(timeoutNS
) );
2269 /* Routine io_service_request_probe */
2270 kern_return_t
is_io_service_request_probe(
2271 io_object_t _service
,
2274 CHECK( IOService
, _service
, service
);
2276 return( service
->requestProbe( options
));
2280 /* Routine io_service_open */
2281 kern_return_t
is_io_service_open(
2282 io_object_t _service
,
2284 uint32_t connect_type
,
2285 io_object_t
*connection
)
2287 IOUserClient
* client
;
2290 CHECK( IOService
, _service
, service
);
2292 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
2293 connect_type
, 0, &client
);
2295 if( err
== kIOReturnSuccess
) {
2296 assert( OSDynamicCast(IOUserClient
, client
) );
2297 *connection
= client
;
2303 /* Routine io_service_open_ndr */
2304 kern_return_t
is_io_service_open_extended(
2305 io_object_t _service
,
2307 uint32_t connect_type
,
2309 io_buf_ptr_t properties
,
2310 mach_msg_type_number_t propertiesCnt
,
2311 kern_return_t
* result
,
2312 io_object_t
*connection
)
2314 IOUserClient
* client
= 0;
2315 kern_return_t err
= KERN_SUCCESS
;
2316 IOReturn res
= kIOReturnSuccess
;
2317 OSDictionary
* propertiesDict
= 0;
2319 bool disallowAccess
;
2321 CHECK( IOService
, _service
, service
);
2329 vm_map_offset_t map_data
;
2331 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2333 data
= CAST_DOWN(vm_offset_t
, map_data
);
2334 if (KERN_SUCCESS
== err
)
2336 // must return success after vm_map_copyout() succeeds
2337 obj
= OSUnserializeXML( (const char *) data
);
2338 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2339 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
2340 if (!propertiesDict
)
2342 res
= kIOReturnBadArgument
;
2347 if (kIOReturnSuccess
!= res
)
2351 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
2354 if (!propertiesDict
)
2355 propertiesDict
= OSDictionary::withCapacity(4);
2356 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
2360 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
2365 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
2366 connect_type
, propertiesDict
, &client
);
2369 propertiesDict
->release();
2371 if (res
== kIOReturnSuccess
)
2373 assert( OSDynamicCast(IOUserClient
, client
) );
2375 disallowAccess
= (crossEndian
2376 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
2377 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
2381 client
->clientClose();
2384 res
= kIOReturnUnsupported
;
2387 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
2388 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
2391 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
2392 creatorName
->release();
2398 *connection
= client
;
2404 /* Routine io_service_close */
2405 kern_return_t
is_io_service_close(
2406 io_object_t connection
)
2409 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2410 return( kIOReturnSuccess
);
2412 CHECK( IOUserClient
, connection
, client
);
2414 client
->clientClose();
2416 return( kIOReturnSuccess
);
2419 /* Routine io_connect_get_service */
2420 kern_return_t
is_io_connect_get_service(
2421 io_object_t connection
,
2422 io_object_t
*service
)
2424 IOService
* theService
;
2426 CHECK( IOUserClient
, connection
, client
);
2428 theService
= client
->getService();
2430 theService
->retain();
2432 *service
= theService
;
2434 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2437 /* Routine io_connect_set_notification_port */
2438 kern_return_t
is_io_connect_set_notification_port(
2439 io_object_t connection
,
2440 uint32_t notification_type
,
2444 CHECK( IOUserClient
, connection
, client
);
2446 return( client
->registerNotificationPort( port
, notification_type
,
2447 (io_user_reference_t
) reference
));
2450 /* Routine io_connect_set_notification_port */
2451 kern_return_t
is_io_connect_set_notification_port_64(
2452 io_object_t connection
,
2453 uint32_t notification_type
,
2455 io_user_reference_t reference
)
2457 CHECK( IOUserClient
, connection
, client
);
2459 return( client
->registerNotificationPort( port
, notification_type
,
2463 /* Routine io_connect_map_memory_into_task */
2464 kern_return_t is_io_connect_map_memory_into_task
2466 io_connect_t connection
,
2467 uint32_t memory_type
,
2469 mach_vm_address_t
*address
,
2470 mach_vm_size_t
*size
,
2477 CHECK( IOUserClient
, connection
, client
);
2479 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
2482 *address
= map
->getAddress();
2484 *size
= map
->getSize();
2486 if( client
->sharedInstance
2487 || (into_task
!= current_task())) {
2488 // push a name out to the task owning the map,
2489 // so we can clean up maps
2490 mach_port_name_t name __unused
=
2491 IOMachPort::makeSendRightForTask(
2492 into_task
, map
, IKOT_IOKIT_OBJECT
);
2496 // keep it with the user client
2497 IOLockLock( gIOObjectPortLock
);
2498 if( 0 == client
->mappings
)
2499 client
->mappings
= OSSet::withCapacity(2);
2500 if( client
->mappings
)
2501 client
->mappings
->setObject( map
);
2502 IOLockUnlock( gIOObjectPortLock
);
2505 err
= kIOReturnSuccess
;
2508 err
= kIOReturnBadArgument
;
2513 /* Routine is_io_connect_map_memory */
2514 kern_return_t
is_io_connect_map_memory(
2515 io_object_t connect
,
2518 vm_address_t
* mapAddr
,
2519 vm_size_t
* mapSize
,
2523 mach_vm_address_t address
;
2524 mach_vm_size_t size
;
2526 address
= SCALAR64(*mapAddr
);
2527 size
= SCALAR64(*mapSize
);
2529 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
2531 *mapAddr
= SCALAR32(address
);
2532 *mapSize
= SCALAR32(size
);
2537 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2540 IOMemoryMap
* map
= 0;
2542 IOLockLock(gIOObjectPortLock
);
2544 iter
= OSCollectionIterator::withCollection(mappings
);
2547 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2549 if(mem
== map
->getMemoryDescriptor())
2552 mappings
->removeObject(map
);
2559 IOLockUnlock(gIOObjectPortLock
);
2564 /* Routine io_connect_unmap_memory_from_task */
2565 kern_return_t is_io_connect_unmap_memory_from_task
2567 io_connect_t connection
,
2568 uint32_t memory_type
,
2570 mach_vm_address_t address
)
2573 IOOptionBits options
= 0;
2574 IOMemoryDescriptor
* memory
;
2577 CHECK( IOUserClient
, connection
, client
);
2579 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
2581 if( memory
&& (kIOReturnSuccess
== err
)) {
2583 options
= (options
& ~kIOMapUserOptionsMask
)
2584 | kIOMapAnywhere
| kIOMapReference
;
2586 map
= memory
->createMappingInTask( from_task
, address
, options
);
2590 IOLockLock( gIOObjectPortLock
);
2591 if( client
->mappings
)
2592 client
->mappings
->removeObject( map
);
2593 IOLockUnlock( gIOObjectPortLock
);
2595 mach_port_name_t name
= 0;
2596 if (from_task
!= current_task())
2597 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
2600 map
->userClientUnmap();
2601 err
= iokit_mod_send_right( from_task
, name
, -2 );
2602 err
= kIOReturnSuccess
;
2605 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2606 if (from_task
== current_task())
2610 err
= kIOReturnBadArgument
;
2616 kern_return_t
is_io_connect_unmap_memory(
2617 io_object_t connect
,
2620 vm_address_t mapAddr
)
2623 mach_vm_address_t address
;
2625 address
= SCALAR64(mapAddr
);
2627 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
2633 /* Routine io_connect_add_client */
2634 kern_return_t
is_io_connect_add_client(
2635 io_object_t connection
,
2636 io_object_t connect_to
)
2638 CHECK( IOUserClient
, connection
, client
);
2639 CHECK( IOUserClient
, connect_to
, to
);
2641 return( client
->connectClient( to
) );
2645 /* Routine io_connect_set_properties */
2646 kern_return_t
is_io_connect_set_properties(
2647 io_object_t connection
,
2648 io_buf_ptr_t properties
,
2649 mach_msg_type_number_t propertiesCnt
,
2650 kern_return_t
* result
)
2652 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2656 /* Routine io_user_client_method */
2657 kern_return_t is_io_connect_method
2659 io_connect_t connection
,
2661 io_scalar_inband64_t scalar_input
,
2662 mach_msg_type_number_t scalar_inputCnt
,
2663 io_struct_inband_t inband_input
,
2664 mach_msg_type_number_t inband_inputCnt
,
2665 mach_vm_address_t ool_input
,
2666 mach_vm_size_t ool_input_size
,
2667 io_scalar_inband64_t scalar_output
,
2668 mach_msg_type_number_t
*scalar_outputCnt
,
2669 io_struct_inband_t inband_output
,
2670 mach_msg_type_number_t
*inband_outputCnt
,
2671 mach_vm_address_t ool_output
,
2672 mach_vm_size_t
* ool_output_size
2675 CHECK( IOUserClient
, connection
, client
);
2677 IOExternalMethodArguments args
;
2679 IOMemoryDescriptor
* inputMD
= 0;
2680 IOMemoryDescriptor
* outputMD
= 0;
2682 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
2683 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
2685 args
.selector
= selector
;
2687 args
.asyncWakePort
= MACH_PORT_NULL
;
2688 args
.asyncReference
= 0;
2689 args
.asyncReferenceCount
= 0;
2691 args
.scalarInput
= scalar_input
;
2692 args
.scalarInputCount
= scalar_inputCnt
;
2693 args
.structureInput
= inband_input
;
2694 args
.structureInputSize
= inband_inputCnt
;
2697 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
2698 kIODirectionOut
, current_task());
2700 args
.structureInputDescriptor
= inputMD
;
2702 args
.scalarOutput
= scalar_output
;
2703 args
.scalarOutputCount
= *scalar_outputCnt
;
2704 args
.structureOutput
= inband_output
;
2705 args
.structureOutputSize
= *inband_outputCnt
;
2709 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
2710 kIODirectionIn
, current_task());
2713 args
.structureOutputDescriptor
= outputMD
;
2714 args
.structureOutputDescriptorSize
= *ool_output_size
;
2716 ret
= client
->externalMethod( selector
, &args
);
2718 *scalar_outputCnt
= args
.scalarOutputCount
;
2719 *inband_outputCnt
= args
.structureOutputSize
;
2720 *ool_output_size
= args
.structureOutputDescriptorSize
;
2725 outputMD
->release();
2730 /* Routine io_async_user_client_method */
2731 kern_return_t is_io_connect_async_method
2733 io_connect_t connection
,
2734 mach_port_t wake_port
,
2735 io_async_ref64_t reference
,
2736 mach_msg_type_number_t referenceCnt
,
2738 io_scalar_inband64_t scalar_input
,
2739 mach_msg_type_number_t scalar_inputCnt
,
2740 io_struct_inband_t inband_input
,
2741 mach_msg_type_number_t inband_inputCnt
,
2742 mach_vm_address_t ool_input
,
2743 mach_vm_size_t ool_input_size
,
2744 io_scalar_inband64_t scalar_output
,
2745 mach_msg_type_number_t
*scalar_outputCnt
,
2746 io_struct_inband_t inband_output
,
2747 mach_msg_type_number_t
*inband_outputCnt
,
2748 mach_vm_address_t ool_output
,
2749 mach_vm_size_t
* ool_output_size
2752 CHECK( IOUserClient
, connection
, client
);
2754 IOExternalMethodArguments args
;
2756 IOMemoryDescriptor
* inputMD
= 0;
2757 IOMemoryDescriptor
* outputMD
= 0;
2759 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
2760 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
2762 reference
[0] = (io_user_reference_t
) wake_port
;
2763 if (vm_map_is_64bit(get_task_map(current_task())))
2764 reference
[0] |= kIOUCAsync64Flag
;
2766 args
.selector
= selector
;
2768 args
.asyncWakePort
= wake_port
;
2769 args
.asyncReference
= reference
;
2770 args
.asyncReferenceCount
= referenceCnt
;
2772 args
.scalarInput
= scalar_input
;
2773 args
.scalarInputCount
= scalar_inputCnt
;
2774 args
.structureInput
= inband_input
;
2775 args
.structureInputSize
= inband_inputCnt
;
2778 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
2779 kIODirectionOut
, current_task());
2781 args
.structureInputDescriptor
= inputMD
;
2783 args
.scalarOutput
= scalar_output
;
2784 args
.scalarOutputCount
= *scalar_outputCnt
;
2785 args
.structureOutput
= inband_output
;
2786 args
.structureOutputSize
= *inband_outputCnt
;
2790 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
2791 kIODirectionIn
, current_task());
2794 args
.structureOutputDescriptor
= outputMD
;
2795 args
.structureOutputDescriptorSize
= *ool_output_size
;
2797 ret
= client
->externalMethod( selector
, &args
);
2799 *inband_outputCnt
= args
.structureOutputSize
;
2800 *ool_output_size
= args
.structureOutputDescriptorSize
;
2805 outputMD
->release();
2810 /* Routine io_connect_method_scalarI_scalarO */
2811 kern_return_t
is_io_connect_method_scalarI_scalarO(
2812 io_object_t connect
,
2814 io_scalar_inband_t input
,
2815 mach_msg_type_number_t inputCount
,
2816 io_scalar_inband_t output
,
2817 mach_msg_type_number_t
* outputCount
)
2821 io_scalar_inband64_t _input
;
2822 io_scalar_inband64_t _output
;
2824 mach_msg_type_number_t struct_outputCnt
= 0;
2825 mach_vm_size_t ool_output_size
= 0;
2827 for (i
= 0; i
< inputCount
; i
++)
2828 _input
[i
] = SCALAR64(input
[i
]);
2830 err
= is_io_connect_method(connect
, index
,
2834 _output
, outputCount
,
2835 NULL
, &struct_outputCnt
,
2836 0, &ool_output_size
);
2838 for (i
= 0; i
< *outputCount
; i
++)
2839 output
[i
] = SCALAR32(_output
[i
]);
2844 kern_return_t
shim_io_connect_method_scalarI_scalarO(
2845 IOExternalMethod
* method
,
2847 const io_user_scalar_t
* input
,
2848 mach_msg_type_number_t inputCount
,
2849 io_user_scalar_t
* output
,
2850 mach_msg_type_number_t
* outputCount
)
2853 io_scalar_inband_t _output
;
2855 err
= kIOReturnBadArgument
;
2859 if( inputCount
!= method
->count0
)
2861 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
2864 if( *outputCount
!= method
->count1
)
2866 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
2870 func
= method
->func
;
2872 switch( inputCount
) {
2875 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2876 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
2879 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2880 ARG32(input
[3]), ARG32(input
[4]),
2884 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2886 &_output
[0], &_output
[1] );
2889 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2890 &_output
[0], &_output
[1], &_output
[2] );
2893 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
2894 &_output
[0], &_output
[1], &_output
[2],
2898 err
= (object
->*func
)( ARG32(input
[0]),
2899 &_output
[0], &_output
[1], &_output
[2],
2900 &_output
[3], &_output
[4] );
2903 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
2904 &_output
[3], &_output
[4], &_output
[5] );
2908 IOLog("%s: Bad method table\n", object
->getName());
2914 for (i
= 0; i
< *outputCount
; i
++)
2915 output
[i
] = SCALAR32(_output
[i
]);
2920 /* Routine io_async_method_scalarI_scalarO */
2921 kern_return_t
is_io_async_method_scalarI_scalarO(
2922 io_object_t connect
,
2923 mach_port_t wake_port
,
2924 io_async_ref_t reference
,
2925 mach_msg_type_number_t referenceCnt
,
2927 io_scalar_inband_t input
,
2928 mach_msg_type_number_t inputCount
,
2929 io_scalar_inband_t output
,
2930 mach_msg_type_number_t
* outputCount
)
2934 io_scalar_inband64_t _input
;
2935 io_scalar_inband64_t _output
;
2936 io_async_ref64_t _reference
;
2938 for (i
= 0; i
< referenceCnt
; i
++)
2939 _reference
[i
] = REF64(reference
[i
]);
2941 mach_msg_type_number_t struct_outputCnt
= 0;
2942 mach_vm_size_t ool_output_size
= 0;
2944 for (i
= 0; i
< inputCount
; i
++)
2945 _input
[i
] = SCALAR64(input
[i
]);
2947 err
= is_io_connect_async_method(connect
,
2948 wake_port
, _reference
, referenceCnt
,
2953 _output
, outputCount
,
2954 NULL
, &struct_outputCnt
,
2955 0, &ool_output_size
);
2957 for (i
= 0; i
< *outputCount
; i
++)
2958 output
[i
] = SCALAR32(_output
[i
]);
2962 /* Routine io_async_method_scalarI_structureO */
2963 kern_return_t
is_io_async_method_scalarI_structureO(
2964 io_object_t connect
,
2965 mach_port_t wake_port
,
2966 io_async_ref_t reference
,
2967 mach_msg_type_number_t referenceCnt
,
2969 io_scalar_inband_t input
,
2970 mach_msg_type_number_t inputCount
,
2971 io_struct_inband_t output
,
2972 mach_msg_type_number_t
* outputCount
)
2975 io_scalar_inband64_t _input
;
2976 io_async_ref64_t _reference
;
2978 for (i
= 0; i
< referenceCnt
; i
++)
2979 _reference
[i
] = REF64(reference
[i
]);
2981 mach_msg_type_number_t scalar_outputCnt
= 0;
2982 mach_vm_size_t ool_output_size
= 0;
2984 for (i
= 0; i
< inputCount
; i
++)
2985 _input
[i
] = SCALAR64(input
[i
]);
2987 return (is_io_connect_async_method(connect
,
2988 wake_port
, _reference
, referenceCnt
,
2993 NULL
, &scalar_outputCnt
,
2994 output
, outputCount
,
2995 0, &ool_output_size
));
2998 /* Routine io_async_method_scalarI_structureI */
2999 kern_return_t
is_io_async_method_scalarI_structureI(
3000 io_connect_t connect
,
3001 mach_port_t wake_port
,
3002 io_async_ref_t reference
,
3003 mach_msg_type_number_t referenceCnt
,
3005 io_scalar_inband_t input
,
3006 mach_msg_type_number_t inputCount
,
3007 io_struct_inband_t inputStruct
,
3008 mach_msg_type_number_t inputStructCount
)
3011 io_scalar_inband64_t _input
;
3012 io_async_ref64_t _reference
;
3014 for (i
= 0; i
< referenceCnt
; i
++)
3015 _reference
[i
] = REF64(reference
[i
]);
3017 mach_msg_type_number_t scalar_outputCnt
= 0;
3018 mach_msg_type_number_t inband_outputCnt
= 0;
3019 mach_vm_size_t ool_output_size
= 0;
3021 for (i
= 0; i
< inputCount
; i
++)
3022 _input
[i
] = SCALAR64(input
[i
]);
3024 return (is_io_connect_async_method(connect
,
3025 wake_port
, _reference
, referenceCnt
,
3028 inputStruct
, inputStructCount
,
3030 NULL
, &scalar_outputCnt
,
3031 NULL
, &inband_outputCnt
,
3032 0, &ool_output_size
));
3035 /* Routine io_async_method_structureI_structureO */
3036 kern_return_t
is_io_async_method_structureI_structureO(
3037 io_object_t connect
,
3038 mach_port_t wake_port
,
3039 io_async_ref_t reference
,
3040 mach_msg_type_number_t referenceCnt
,
3042 io_struct_inband_t input
,
3043 mach_msg_type_number_t inputCount
,
3044 io_struct_inband_t output
,
3045 mach_msg_type_number_t
* outputCount
)
3048 mach_msg_type_number_t scalar_outputCnt
= 0;
3049 mach_vm_size_t ool_output_size
= 0;
3050 io_async_ref64_t _reference
;
3052 for (i
= 0; i
< referenceCnt
; i
++)
3053 _reference
[i
] = REF64(reference
[i
]);
3055 return (is_io_connect_async_method(connect
,
3056 wake_port
, _reference
, referenceCnt
,
3061 NULL
, &scalar_outputCnt
,
3062 output
, outputCount
,
3063 0, &ool_output_size
));
3067 kern_return_t
shim_io_async_method_scalarI_scalarO(
3068 IOExternalAsyncMethod
* method
,
3070 mach_port_t asyncWakePort
,
3071 io_user_reference_t
* asyncReference
,
3072 uint32_t asyncReferenceCount
,
3073 const io_user_scalar_t
* input
,
3074 mach_msg_type_number_t inputCount
,
3075 io_user_scalar_t
* output
,
3076 mach_msg_type_number_t
* outputCount
)
3080 io_scalar_inband_t _output
;
3082 io_async_ref_t reference
;
3084 for (i
= 0; i
< asyncReferenceCount
; i
++)
3085 reference
[i
] = REF32(asyncReference
[i
]);
3087 err
= kIOReturnBadArgument
;
3091 if( inputCount
!= method
->count0
)
3093 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3096 if( *outputCount
!= method
->count1
)
3098 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3102 func
= method
->func
;
3104 switch( inputCount
) {
3107 err
= (object
->*func
)( reference
,
3108 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3109 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3112 err
= (object
->*func
)( reference
,
3113 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3114 ARG32(input
[3]), ARG32(input
[4]),
3118 err
= (object
->*func
)( reference
,
3119 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3121 &_output
[0], &_output
[1] );
3124 err
= (object
->*func
)( reference
,
3125 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3126 &_output
[0], &_output
[1], &_output
[2] );
3129 err
= (object
->*func
)( reference
,
3130 ARG32(input
[0]), ARG32(input
[1]),
3131 &_output
[0], &_output
[1], &_output
[2],
3135 err
= (object
->*func
)( reference
,
3137 &_output
[0], &_output
[1], &_output
[2],
3138 &_output
[3], &_output
[4] );
3141 err
= (object
->*func
)( reference
,
3142 &_output
[0], &_output
[1], &_output
[2],
3143 &_output
[3], &_output
[4], &_output
[5] );
3147 IOLog("%s: Bad method table\n", object
->getName());
3152 for (i
= 0; i
< *outputCount
; i
++)
3153 output
[i
] = SCALAR32(_output
[i
]);
3159 /* Routine io_connect_method_scalarI_structureO */
3160 kern_return_t
is_io_connect_method_scalarI_structureO(
3161 io_object_t connect
,
3163 io_scalar_inband_t input
,
3164 mach_msg_type_number_t inputCount
,
3165 io_struct_inband_t output
,
3166 mach_msg_type_number_t
* outputCount
)
3169 io_scalar_inband64_t _input
;
3171 mach_msg_type_number_t scalar_outputCnt
= 0;
3172 mach_vm_size_t ool_output_size
= 0;
3174 for (i
= 0; i
< inputCount
; i
++)
3175 _input
[i
] = SCALAR64(input
[i
]);
3177 return (is_io_connect_method(connect
, index
,
3181 NULL
, &scalar_outputCnt
,
3182 output
, outputCount
,
3183 0, &ool_output_size
));
3186 kern_return_t
shim_io_connect_method_scalarI_structureO(
3188 IOExternalMethod
* method
,
3190 const io_user_scalar_t
* input
,
3191 mach_msg_type_number_t inputCount
,
3192 io_struct_inband_t output
,
3193 IOByteCount
* outputCount
)
3198 err
= kIOReturnBadArgument
;
3201 if( inputCount
!= method
->count0
)
3203 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3206 if( (kIOUCVariableStructureSize
!= method
->count1
)
3207 && (*outputCount
!= method
->count1
))
3209 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3213 func
= method
->func
;
3215 switch( inputCount
) {
3218 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3219 ARG32(input
[3]), ARG32(input
[4]),
3223 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3225 output
, (void *)outputCount
);
3228 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3229 output
, (void *)outputCount
, 0 );
3232 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3233 output
, (void *)outputCount
, 0, 0 );
3236 err
= (object
->*func
)( ARG32(input
[0]),
3237 output
, (void *)outputCount
, 0, 0, 0 );
3240 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
3244 IOLog("%s: Bad method table\n", object
->getName());
3253 kern_return_t
shim_io_async_method_scalarI_structureO(
3254 IOExternalAsyncMethod
* method
,
3256 mach_port_t asyncWakePort
,
3257 io_user_reference_t
* asyncReference
,
3258 uint32_t asyncReferenceCount
,
3259 const io_user_scalar_t
* input
,
3260 mach_msg_type_number_t inputCount
,
3261 io_struct_inband_t output
,
3262 mach_msg_type_number_t
* outputCount
)
3267 io_async_ref_t reference
;
3269 for (i
= 0; i
< asyncReferenceCount
; i
++)
3270 reference
[i
] = REF32(asyncReference
[i
]);
3272 err
= kIOReturnBadArgument
;
3274 if( inputCount
!= method
->count0
)
3276 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3279 if( (kIOUCVariableStructureSize
!= method
->count1
)
3280 && (*outputCount
!= method
->count1
))
3282 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3286 func
= method
->func
;
3288 switch( inputCount
) {
3291 err
= (object
->*func
)( reference
,
3292 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3293 ARG32(input
[3]), ARG32(input
[4]),
3297 err
= (object
->*func
)( reference
,
3298 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3300 output
, (void *)outputCount
);
3303 err
= (object
->*func
)( reference
,
3304 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3305 output
, (void *)outputCount
, 0 );
3308 err
= (object
->*func
)( reference
,
3309 ARG32(input
[0]), ARG32(input
[1]),
3310 output
, (void *)outputCount
, 0, 0 );
3313 err
= (object
->*func
)( reference
,
3315 output
, (void *)outputCount
, 0, 0, 0 );
3318 err
= (object
->*func
)( reference
,
3319 output
, (void *)outputCount
, 0, 0, 0, 0 );
3323 IOLog("%s: Bad method table\n", object
->getName());
3331 /* Routine io_connect_method_scalarI_structureI */
3332 kern_return_t
is_io_connect_method_scalarI_structureI(
3333 io_connect_t connect
,
3335 io_scalar_inband_t input
,
3336 mach_msg_type_number_t inputCount
,
3337 io_struct_inband_t inputStruct
,
3338 mach_msg_type_number_t inputStructCount
)
3341 io_scalar_inband64_t _input
;
3343 mach_msg_type_number_t scalar_outputCnt
= 0;
3344 mach_msg_type_number_t inband_outputCnt
= 0;
3345 mach_vm_size_t ool_output_size
= 0;
3347 for (i
= 0; i
< inputCount
; i
++)
3348 _input
[i
] = SCALAR64(input
[i
]);
3350 return (is_io_connect_method(connect
, index
,
3352 inputStruct
, inputStructCount
,
3354 NULL
, &scalar_outputCnt
,
3355 NULL
, &inband_outputCnt
,
3356 0, &ool_output_size
));
3359 kern_return_t
shim_io_connect_method_scalarI_structureI(
3360 IOExternalMethod
* method
,
3362 const io_user_scalar_t
* input
,
3363 mach_msg_type_number_t inputCount
,
3364 io_struct_inband_t inputStruct
,
3365 mach_msg_type_number_t inputStructCount
)
3368 IOReturn err
= kIOReturnBadArgument
;
3372 if( (kIOUCVariableStructureSize
!= method
->count0
)
3373 && (inputCount
!= method
->count0
))
3375 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3378 if( (kIOUCVariableStructureSize
!= method
->count1
)
3379 && (inputStructCount
!= method
->count1
))
3381 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3385 func
= method
->func
;
3387 switch( inputCount
) {
3390 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3391 ARG32(input
[3]), ARG32(input
[4]),
3395 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
3397 inputStruct
, (void *)inputStructCount
);
3400 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3401 inputStruct
, (void *)inputStructCount
,
3405 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3406 inputStruct
, (void *)inputStructCount
,
3410 err
= (object
->*func
)( ARG32(input
[0]),
3411 inputStruct
, (void *)inputStructCount
,
3415 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
3420 IOLog("%s: Bad method table\n", object
->getName());
3428 kern_return_t
shim_io_async_method_scalarI_structureI(
3429 IOExternalAsyncMethod
* method
,
3431 mach_port_t asyncWakePort
,
3432 io_user_reference_t
* asyncReference
,
3433 uint32_t asyncReferenceCount
,
3434 const io_user_scalar_t
* input
,
3435 mach_msg_type_number_t inputCount
,
3436 io_struct_inband_t inputStruct
,
3437 mach_msg_type_number_t inputStructCount
)
3441 IOReturn err
= kIOReturnBadArgument
;
3442 io_async_ref_t reference
;
3444 for (i
= 0; i
< asyncReferenceCount
; i
++)
3445 reference
[i
] = REF32(asyncReference
[i
]);
3449 if( (kIOUCVariableStructureSize
!= method
->count0
)
3450 && (inputCount
!= method
->count0
))
3452 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3455 if( (kIOUCVariableStructureSize
!= method
->count1
)
3456 && (inputStructCount
!= method
->count1
))
3458 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3462 func
= method
->func
;
3464 switch( inputCount
) {
3467 err
= (object
->*func
)( reference
,
3468 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3469 ARG32(input
[3]), ARG32(input
[4]),
3473 err
= (object
->*func
)( reference
,
3474 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3476 inputStruct
, (void *)inputStructCount
);
3479 err
= (object
->*func
)( reference
,
3480 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3481 inputStruct
, (void *)inputStructCount
,
3485 err
= (object
->*func
)( reference
,
3486 ARG32(input
[0]), ARG32(input
[1]),
3487 inputStruct
, (void *)inputStructCount
,
3491 err
= (object
->*func
)( reference
,
3493 inputStruct
, (void *)inputStructCount
,
3497 err
= (object
->*func
)( reference
,
3498 inputStruct
, (void *)inputStructCount
,
3503 IOLog("%s: Bad method table\n", object
->getName());
3511 /* Routine io_connect_method_structureI_structureO */
3512 kern_return_t
is_io_connect_method_structureI_structureO(
3513 io_object_t connect
,
3515 io_struct_inband_t input
,
3516 mach_msg_type_number_t inputCount
,
3517 io_struct_inband_t output
,
3518 mach_msg_type_number_t
* outputCount
)
3520 mach_msg_type_number_t scalar_outputCnt
= 0;
3521 mach_vm_size_t ool_output_size
= 0;
3523 return (is_io_connect_method(connect
, index
,
3527 NULL
, &scalar_outputCnt
,
3528 output
, outputCount
,
3529 0, &ool_output_size
));
3532 kern_return_t
shim_io_connect_method_structureI_structureO(
3533 IOExternalMethod
* method
,
3535 io_struct_inband_t input
,
3536 mach_msg_type_number_t inputCount
,
3537 io_struct_inband_t output
,
3538 IOByteCount
* outputCount
)
3541 IOReturn err
= kIOReturnBadArgument
;
3545 if( (kIOUCVariableStructureSize
!= method
->count0
)
3546 && (inputCount
!= method
->count0
))
3548 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3551 if( (kIOUCVariableStructureSize
!= method
->count1
)
3552 && (*outputCount
!= method
->count1
))
3554 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3558 func
= method
->func
;
3560 if( method
->count1
) {
3561 if( method
->count0
) {
3562 err
= (object
->*func
)( input
, output
,
3563 (void *)inputCount
, outputCount
, 0, 0 );
3565 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
3568 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
3577 kern_return_t
shim_io_async_method_structureI_structureO(
3578 IOExternalAsyncMethod
* method
,
3580 mach_port_t asyncWakePort
,
3581 io_user_reference_t
* asyncReference
,
3582 uint32_t asyncReferenceCount
,
3583 io_struct_inband_t input
,
3584 mach_msg_type_number_t inputCount
,
3585 io_struct_inband_t output
,
3586 mach_msg_type_number_t
* outputCount
)
3591 io_async_ref_t reference
;
3593 for (i
= 0; i
< asyncReferenceCount
; i
++)
3594 reference
[i
] = REF32(asyncReference
[i
]);
3596 err
= kIOReturnBadArgument
;
3599 if( (kIOUCVariableStructureSize
!= method
->count0
)
3600 && (inputCount
!= method
->count0
))
3602 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3605 if( (kIOUCVariableStructureSize
!= method
->count1
)
3606 && (*outputCount
!= method
->count1
))
3608 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3612 func
= method
->func
;
3614 if( method
->count1
) {
3615 if( method
->count0
) {
3616 err
= (object
->*func
)( reference
,
3618 (void *)inputCount
, outputCount
, 0, 0 );
3620 err
= (object
->*func
)( reference
,
3621 output
, outputCount
, 0, 0, 0, 0 );
3624 err
= (object
->*func
)( reference
,
3625 input
, (void *)inputCount
, 0, 0, 0, 0 );
3633 /* Routine io_make_matching */
3634 kern_return_t
is_io_make_matching(
3635 mach_port_t master_port
,
3638 io_struct_inband_t input
,
3639 mach_msg_type_number_t inputCount
,
3640 io_string_t matching
)
3643 IOReturn err
= kIOReturnSuccess
;
3644 OSDictionary
* dict
;
3646 if( master_port
!= master_device_port
)
3647 return( kIOReturnNotPrivileged
);
3651 case kIOServiceMatching
:
3652 dict
= IOService::serviceMatching( gIOServiceKey
);
3655 case kIOBSDNameMatching
:
3656 dict
= IOBSDNameMatching( (const char *) input
);
3659 case kIOOFPathMatching
:
3660 dict
= IOOFPathMatching( (const char *) input
,
3661 matching
, sizeof( io_string_t
));
3669 return( kIOReturnUnsupported
);
3672 s
= OSSerialize::withCapacity(4096);
3674 err
= kIOReturnNoMemory
;
3678 if( !dict
->serialize( s
)) {
3679 err
= kIOReturnUnsupported
;
3683 if( s
->getLength() > sizeof( io_string_t
)) {
3684 err
= kIOReturnNoMemory
;
3687 strlcpy(matching
, s
->text(), sizeof(io_string_t
));
3699 /* Routine io_catalog_send_data */
3700 kern_return_t
is_io_catalog_send_data(
3701 mach_port_t master_port
,
3703 io_buf_ptr_t inData
,
3704 mach_msg_type_number_t inDataCount
,
3705 kern_return_t
* result
)
3709 kern_return_t kr
= kIOReturnError
;
3711 //printf("io_catalog_send_data called. flag: %d\n", flag);
3713 if( master_port
!= master_device_port
)
3714 return kIOReturnNotPrivileged
;
3716 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
3717 flag
!= kIOCatalogKextdActive
&&
3718 flag
!= kIOCatalogKextdFinishedLaunching
) &&
3719 ( !inData
|| !inDataCount
) )
3721 return kIOReturnBadArgument
;
3725 vm_map_offset_t map_data
;
3727 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
3728 data
= CAST_DOWN(vm_offset_t
, map_data
);
3730 if( kr
!= KERN_SUCCESS
)
3733 // must return success after vm_map_copyout() succeeds
3736 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
3737 vm_deallocate( kernel_map
, data
, inDataCount
);
3739 *result
= kIOReturnNoMemory
;
3740 return( KERN_SUCCESS
);
3746 case kIOCatalogAddDrivers
:
3747 case kIOCatalogAddDriversNoMatch
: {
3750 array
= OSDynamicCast(OSArray
, obj
);
3752 if ( !gIOCatalogue
->addDrivers( array
,
3753 flag
== kIOCatalogAddDrivers
) ) {
3754 kr
= kIOReturnError
;
3758 kr
= kIOReturnBadArgument
;
3763 case kIOCatalogRemoveDrivers
:
3764 case kIOCatalogRemoveDriversNoMatch
: {
3765 OSDictionary
* dict
;
3767 dict
= OSDynamicCast(OSDictionary
, obj
);
3769 if ( !gIOCatalogue
->removeDrivers( dict
,
3770 flag
== kIOCatalogRemoveDrivers
) ) {
3771 kr
= kIOReturnError
;
3775 kr
= kIOReturnBadArgument
;
3780 case kIOCatalogStartMatching
: {
3781 OSDictionary
* dict
;
3783 dict
= OSDynamicCast(OSDictionary
, obj
);
3785 if ( !gIOCatalogue
->startMatching( dict
) ) {
3786 kr
= kIOReturnError
;
3790 kr
= kIOReturnBadArgument
;
3795 case kIOCatalogRemoveKernelLinker
:
3796 kr
= KERN_NOT_SUPPORTED
;
3799 case kIOCatalogKextdActive
:
3801 OSKext::setKextdActive();
3803 /* Dump all nonloaded startup extensions; kextd will now send them
3806 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
3808 kr
= kIOReturnSuccess
;
3811 case kIOCatalogKextdFinishedLaunching
: {
3813 static bool clearedBusy
= false;
3816 IOService
* serviceRoot
= IOService::getServiceRoot();
3818 serviceRoot
->adjustBusy(-1);
3823 kr
= kIOReturnSuccess
;
3828 kr
= kIOReturnBadArgument
;
3832 if (obj
) obj
->release();
3835 return( KERN_SUCCESS
);
3838 /* Routine io_catalog_terminate */
3839 kern_return_t
is_io_catalog_terminate(
3840 mach_port_t master_port
,
3846 if( master_port
!= master_device_port
)
3847 return kIOReturnNotPrivileged
;
3849 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3850 kIOClientPrivilegeAdministrator
);
3851 if( kIOReturnSuccess
!= kr
)
3855 case kIOCatalogServiceTerminate
:
3857 IOService
* service
;
3859 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
3860 kIORegistryIterateRecursively
);
3862 return kIOReturnNoMemory
;
3866 while( (service
= (IOService
*)iter
->getNextObject()) ) {
3867 if( service
->metaCast(name
)) {
3868 if ( !service
->terminate( kIOServiceRequired
3869 | kIOServiceSynchronous
) ) {
3870 kr
= kIOReturnUnsupported
;
3875 } while( !service
&& !iter
->isValid());
3879 case kIOCatalogModuleUnload
:
3880 case kIOCatalogModuleTerminate
:
3881 kr
= gIOCatalogue
->terminateDriversForModule(name
,
3882 flag
== kIOCatalogModuleUnload
);
3886 kr
= kIOReturnBadArgument
;
3893 /* Routine io_catalog_get_data */
3894 kern_return_t
is_io_catalog_get_data(
3895 mach_port_t master_port
,
3897 io_buf_ptr_t
*outData
,
3898 mach_msg_type_number_t
*outDataCount
)
3900 kern_return_t kr
= kIOReturnSuccess
;
3903 if( master_port
!= master_device_port
)
3904 return kIOReturnNotPrivileged
;
3906 //printf("io_catalog_get_data called. flag: %d\n", flag);
3908 s
= OSSerialize::withCapacity(4096);
3910 return kIOReturnNoMemory
;
3914 kr
= gIOCatalogue
->serializeData(flag
, s
);
3916 if ( kr
== kIOReturnSuccess
) {
3921 size
= s
->getLength();
3922 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
3923 if ( kr
== kIOReturnSuccess
) {
3924 bcopy(s
->text(), (void *)data
, size
);
3925 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
3926 (vm_map_size_t
)size
, true, ©
);
3927 *outData
= (char *)copy
;
3928 *outDataCount
= size
;
3937 /* Routine io_catalog_get_gen_count */
3938 kern_return_t
is_io_catalog_get_gen_count(
3939 mach_port_t master_port
,
3942 if( master_port
!= master_device_port
)
3943 return kIOReturnNotPrivileged
;
3945 //printf("io_catalog_get_gen_count called.\n");
3948 return kIOReturnBadArgument
;
3950 *genCount
= gIOCatalogue
->getGenerationCount();
3952 return kIOReturnSuccess
;
3955 /* Routine io_catalog_module_loaded.
3956 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
3958 kern_return_t
is_io_catalog_module_loaded(
3959 mach_port_t master_port
,
3962 if( master_port
!= master_device_port
)
3963 return kIOReturnNotPrivileged
;
3965 //printf("io_catalog_module_loaded called. name %s\n", name);
3968 return kIOReturnBadArgument
;
3970 gIOCatalogue
->moduleHasLoaded(name
);
3972 return kIOReturnSuccess
;
3975 kern_return_t
is_io_catalog_reset(
3976 mach_port_t master_port
,
3979 if( master_port
!= master_device_port
)
3980 return kIOReturnNotPrivileged
;
3983 case kIOCatalogResetDefault
:
3984 gIOCatalogue
->reset();
3988 return kIOReturnBadArgument
;
3991 return kIOReturnSuccess
;
3994 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
3996 kern_return_t result
= kIOReturnBadArgument
;
3997 IOUserClient
*userClient
;
3999 if ((userClient
= OSDynamicCast(IOUserClient
,
4000 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
4001 IOExternalTrap
*trap
;
4002 IOService
*target
= NULL
;
4004 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
4006 if (trap
&& target
) {
4012 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
4016 userClient
->release();
4022 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
4023 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
4027 IOByteCount structureOutputSize
;
4032 count
= dispatch
->checkScalarInputCount
;
4033 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
4035 return (kIOReturnBadArgument
);
4038 count
= dispatch
->checkStructureInputSize
;
4039 if ((kIOUCVariableStructureSize
!= count
)
4040 && (count
!= ((args
->structureInputDescriptor
)
4041 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
4043 return (kIOReturnBadArgument
);
4046 count
= dispatch
->checkScalarOutputCount
;
4047 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
4049 return (kIOReturnBadArgument
);
4052 count
= dispatch
->checkStructureOutputSize
;
4053 if ((kIOUCVariableStructureSize
!= count
)
4054 && (count
!= ((args
->structureOutputDescriptor
)
4055 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
4057 return (kIOReturnBadArgument
);
4060 if (dispatch
->function
)
4061 err
= (*dispatch
->function
)(target
, reference
, args
);
4063 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
4069 // pre-Leopard API's don't do ool structs
4070 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
4072 err
= kIOReturnIPCError
;
4076 structureOutputSize
= args
->structureOutputSize
;
4078 if (args
->asyncWakePort
)
4080 IOExternalAsyncMethod
* method
;
4082 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) )
4083 return (kIOReturnUnsupported
);
4085 switch (method
->flags
& kIOUCTypeMask
)
4087 case kIOUCScalarIStructI
:
4088 err
= shim_io_async_method_scalarI_structureI( method
, object
,
4089 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4090 args
->scalarInput
, args
->scalarInputCount
,
4091 (char *)args
->structureInput
, args
->structureInputSize
);
4094 case kIOUCScalarIScalarO
:
4095 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
4096 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4097 args
->scalarInput
, args
->scalarInputCount
,
4098 args
->scalarOutput
, &args
->scalarOutputCount
);
4101 case kIOUCScalarIStructO
:
4102 err
= shim_io_async_method_scalarI_structureO( method
, object
,
4103 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4104 args
->scalarInput
, args
->scalarInputCount
,
4105 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4109 case kIOUCStructIStructO
:
4110 err
= shim_io_async_method_structureI_structureO( method
, object
,
4111 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4112 (char *)args
->structureInput
, args
->structureInputSize
,
4113 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4117 err
= kIOReturnBadArgument
;
4123 IOExternalMethod
* method
;
4125 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) )
4126 return (kIOReturnUnsupported
);
4128 switch (method
->flags
& kIOUCTypeMask
)
4130 case kIOUCScalarIStructI
:
4131 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
4132 args
->scalarInput
, args
->scalarInputCount
,
4133 (char *) args
->structureInput
, args
->structureInputSize
);
4136 case kIOUCScalarIScalarO
:
4137 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
4138 args
->scalarInput
, args
->scalarInputCount
,
4139 args
->scalarOutput
, &args
->scalarOutputCount
);
4142 case kIOUCScalarIStructO
:
4143 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
4144 args
->scalarInput
, args
->scalarInputCount
,
4145 (char *) args
->structureOutput
, &structureOutputSize
);
4149 case kIOUCStructIStructO
:
4150 err
= shim_io_connect_method_structureI_structureO( method
, object
,
4151 (char *) args
->structureInput
, args
->structureInputSize
,
4152 (char *) args
->structureOutput
, &structureOutputSize
);
4156 err
= kIOReturnBadArgument
;
4161 args
->structureOutputSize
= structureOutputSize
;
4170 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
4171 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
4173 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
4174 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
4176 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
4177 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
4178 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
4179 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
4180 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
4181 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
4182 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
4183 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
4184 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
4185 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
4186 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
4187 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
4188 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
4189 OSMetaClassDefineReservedUnused(IOUserClient
, 15);