2 * Copyright (c) 1998-2006 Apple Computer, 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 <IOKit/IOKitServer.h>
31 #include <IOKit/IOKitKeysPrivate.h>
32 #include <IOKit/IOUserClient.h>
33 #include <IOKit/IOService.h>
34 #include <IOKit/IORegistryEntry.h>
35 #include <IOKit/IOCatalogue.h>
36 #include <IOKit/IOMemoryDescriptor.h>
37 #include <IOKit/IOLib.h>
40 #include <IOKit/assert.h>
42 #include "IOServicePrivate.h"
43 #include "IOKitKernelInternal.h"
45 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
46 #define SCALAR32(x) ((uint32_t )x)
47 #define ARG32(x) ((void *)SCALAR32(x))
48 #define REF64(x) ((io_user_reference_t)((natural_t)(x)))
49 #define REF32(x) ((int)(x))
53 kIOUCAsync0Flags
= 3ULL,
54 kIOUCAsync64Flag
= 1ULL
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59 // definitions we should get from osfmk
61 //typedef struct ipc_port * ipc_port_t;
62 typedef natural_t ipc_kobject_type_t
;
64 #define IKOT_IOKIT_SPARE 27
65 #define IKOT_IOKIT_CONNECT 29
66 #define IKOT_IOKIT_OBJECT 30
70 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
71 ipc_kobject_type_t type
);
73 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
75 extern mach_port_name_t
iokit_make_send_right( task_t task
,
76 io_object_t obj
, ipc_kobject_type_t type
);
78 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
80 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
82 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
84 extern ipc_port_t master_device_port
;
86 extern void iokit_retain_port( ipc_port_t port
);
87 extern void iokit_release_port( ipc_port_t port
);
89 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
91 #include <mach/mach_traps.h>
92 #include <vm/vm_map.h>
97 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
99 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
101 class IOMachPort
: public OSObject
103 OSDeclareDefaultStructors(IOMachPort
)
110 static IOMachPort
* portForObject( OSObject
* obj
,
111 ipc_kobject_type_t type
);
112 static bool noMoreSendersForObject( OSObject
* obj
,
113 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
114 static void releasePortForObject( OSObject
* obj
,
115 ipc_kobject_type_t type
);
116 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
118 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
120 static mach_port_name_t
makeSendRightForTask( task_t task
,
121 io_object_t obj
, ipc_kobject_type_t type
);
126 #define super OSObject
127 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
129 static IOLock
* gIOObjectPortLock
;
131 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
133 // not in dictForType() for debugging ease
134 static OSDictionary
* gIOObjectPorts
;
135 static OSDictionary
* gIOConnectPorts
;
137 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
139 OSDictionary
** dict
;
141 if( IKOT_IOKIT_OBJECT
== type
)
142 dict
= &gIOObjectPorts
;
143 else if( IKOT_IOKIT_CONNECT
== type
)
144 dict
= &gIOConnectPorts
;
149 *dict
= OSDictionary::withCapacity( 1 );
154 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
155 ipc_kobject_type_t type
)
157 IOMachPort
* inst
= 0;
160 IOTakeLock( gIOObjectPortLock
);
164 dict
= dictForType( type
);
168 if( (inst
= (IOMachPort
*)
169 dict
->getObject( (const OSSymbol
*) obj
))) {
175 inst
= new IOMachPort
;
176 if( inst
&& !inst
->init()) {
181 inst
->port
= iokit_alloc_object_port( obj
, type
);
184 dict
->setObject( (const OSSymbol
*) obj
, inst
);
194 IOUnlock( gIOObjectPortLock
);
199 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
200 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
203 IOMachPort
* machPort
;
204 bool destroyed
= true;
206 IOTakeLock( gIOObjectPortLock
);
208 if( (dict
= dictForType( type
))) {
211 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
213 destroyed
= (machPort
->mscount
== *mscount
);
215 dict
->removeObject( (const OSSymbol
*) obj
);
217 *mscount
= machPort
->mscount
;
222 IOUnlock( gIOObjectPortLock
);
227 void IOMachPort::releasePortForObject( OSObject
* obj
,
228 ipc_kobject_type_t type
)
231 IOMachPort
* machPort
;
233 IOTakeLock( gIOObjectPortLock
);
235 if( (dict
= dictForType( type
))) {
237 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
238 if( machPort
&& !machPort
->holdDestroy
)
239 dict
->removeObject( (const OSSymbol
*) obj
);
243 IOUnlock( gIOObjectPortLock
);
246 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
249 IOMachPort
* machPort
;
251 IOLockLock( gIOObjectPortLock
);
253 if( (dict
= dictForType( type
))) {
254 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
256 machPort
->holdDestroy
= true;
259 IOLockUnlock( gIOObjectPortLock
);
262 void IOUserClient::destroyUserReferences( OSObject
* obj
)
264 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
267 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
271 IOTakeLock( gIOObjectPortLock
);
274 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
277 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
281 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
283 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
284 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
286 uc
->mappings
->release();
289 dict
->removeObject( (const OSSymbol
*) obj
);
293 IOUnlock( gIOObjectPortLock
);
296 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
297 io_object_t obj
, ipc_kobject_type_t type
)
299 return( iokit_make_send_right( task
, obj
, type
));
302 void IOMachPort::free( void )
305 iokit_destroy_object_port( port
);
309 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
311 class IOUserNotification
: public OSIterator
313 OSDeclareDefaultStructors(IOUserNotification
)
315 IONotifier
* holdNotify
;
320 virtual bool init( void );
323 virtual void setNotification( IONotifier
* obj
);
325 virtual void reset();
326 virtual bool isValid();
329 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
333 // functions called from osfmk/device/iokit_rpc.c
336 iokit_add_reference( io_object_t obj
)
343 iokit_remove_reference( io_object_t obj
)
350 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
352 IOMachPort
* machPort
;
355 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
357 port
= machPort
->port
;
359 iokit_retain_port( port
);
370 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
371 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
373 IOUserClient
* client
;
375 IOUserNotification
* notify
;
377 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
378 return( kIOReturnNotReady
);
380 if( IKOT_IOKIT_CONNECT
== type
)
382 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
383 client
->clientDied();
385 else if( IKOT_IOKIT_OBJECT
== type
)
387 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
389 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
390 notify
->setNotification( 0 );
393 return( kIOReturnSuccess
);
398 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
400 class IOServiceUserNotification
: public IOUserNotification
402 OSDeclareDefaultStructors(IOServiceUserNotification
)
405 mach_msg_header_t msgHdr
;
406 OSNotificationHeader64 notifyHeader
;
409 enum { kMaxOutstanding
= 1024 };
414 OSObject
* lastEntry
;
419 virtual bool init( mach_port_t port
, natural_t type
,
420 void * reference
, vm_size_t referenceSize
,
424 static bool _handler( void * target
,
425 void * ref
, IOService
* newService
);
426 virtual bool handler( void * ref
, IOService
* newService
);
428 virtual OSObject
* getNextObject();
431 class IOServiceMessageUserNotification
: public IOUserNotification
433 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
436 mach_msg_header_t msgHdr
;
437 mach_msg_body_t msgBody
;
438 mach_msg_port_descriptor_t ports
[1];
439 OSNotificationHeader64 notifyHeader
;
449 virtual bool init( mach_port_t port
, natural_t type
,
450 void * reference
, vm_size_t referenceSize
,
456 static IOReturn
_handler( void * target
, void * ref
,
457 UInt32 messageType
, IOService
* provider
,
458 void * messageArgument
, vm_size_t argSize
);
459 virtual IOReturn
handler( void * ref
,
460 UInt32 messageType
, IOService
* provider
,
461 void * messageArgument
, vm_size_t argSize
);
463 virtual OSObject
* getNextObject();
466 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
469 #define super OSIterator
470 OSDefineMetaClass( IOUserNotification
, OSIterator
)
471 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
473 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
475 bool IOUserNotification::init( void )
480 lock
= IOLockAlloc();
487 void IOUserNotification::free( void )
490 holdNotify
->remove();
491 // can't be in handler now
500 void IOUserNotification::setNotification( IONotifier
* notify
)
502 IONotifier
* previousNotify
;
504 IOLockLock( gIOObjectPortLock
);
506 previousNotify
= holdNotify
;
509 IOLockUnlock( gIOObjectPortLock
);
512 previousNotify
->remove();
515 void IOUserNotification::reset()
520 bool IOUserNotification::isValid()
525 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
528 #define super IOUserNotification
529 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
531 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
533 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
534 void * reference
, vm_size_t referenceSize
,
537 newSet
= OSArray::withCapacity( 1 );
541 if (referenceSize
> sizeof(OSAsyncReference64
))
544 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
545 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
549 bzero( pingMsg
, msgSize
);
551 pingMsg
->msgHdr
.msgh_remote_port
= port
;
552 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
553 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
554 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
555 pingMsg
->msgHdr
.msgh_size
= msgSize
;
556 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
558 pingMsg
->notifyHeader
.size
= 0;
559 pingMsg
->notifyHeader
.type
= type
;
560 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
562 return( super::init() );
565 void IOServiceUserNotification::free( void )
570 OSObject
* _lastEntry
;
574 _lastEntry
= lastEntry
;
579 if( _pingMsg
&& _msgSize
)
580 IOFree( _pingMsg
, _msgSize
);
583 _lastEntry
->release();
589 bool IOServiceUserNotification::_handler( void * target
,
590 void * ref
, IOService
* newService
)
592 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
595 bool IOServiceUserNotification::handler( void * ref
,
596 IOService
* newService
)
600 ipc_port_t port
= NULL
;
601 bool sendPing
= false;
605 count
= newSet
->getCount();
606 if( count
< kMaxOutstanding
) {
608 newSet
->setObject( newService
);
609 if( (sendPing
= (armed
&& (0 == count
))))
615 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
616 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
619 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
620 pingMsg
->msgHdr
.msgh_local_port
= port
;
622 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
624 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
625 pingMsg
->msgHdr
.msgh_size
);
627 iokit_release_port( port
);
629 if( KERN_SUCCESS
!= kr
)
630 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
636 OSObject
* IOServiceUserNotification::getNextObject()
644 lastEntry
->release();
646 count
= newSet
->getCount();
648 result
= newSet
->getObject( count
- 1 );
650 newSet
->removeObject( count
- 1);
662 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
664 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
666 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
668 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
669 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
673 if (referenceSize
> sizeof(OSAsyncReference64
))
676 clientIs64
= client64
;
678 owningPID
= proc_selfpid();
680 extraSize
+= sizeof(IOServiceInterestContent64
);
681 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
+ extraSize
;
682 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
686 bzero( pingMsg
, msgSize
);
688 pingMsg
->msgHdr
.msgh_remote_port
= port
;
689 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
691 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
692 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
693 pingMsg
->msgHdr
.msgh_size
= msgSize
;
694 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
696 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
698 pingMsg
->ports
[0].name
= 0;
699 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
700 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
702 pingMsg
->notifyHeader
.size
= extraSize
;
703 pingMsg
->notifyHeader
.type
= type
;
704 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
706 return( super::init() );
709 void IOServiceMessageUserNotification::free( void )
719 if( _pingMsg
&& _msgSize
)
720 IOFree( _pingMsg
, _msgSize
);
723 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
724 UInt32 messageType
, IOService
* provider
,
725 void * argument
, vm_size_t argSize
)
727 return( ((IOServiceMessageUserNotification
*) target
)->handler(
728 ref
, messageType
, provider
, argument
, argSize
));
731 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
732 UInt32 messageType
, IOService
* provider
,
733 void * messageArgument
, vm_size_t argSize
)
736 ipc_port_t thisPort
, providerPort
;
737 IOServiceInterestContent64
* data
= (IOServiceInterestContent64
*)
738 ((((uint8_t *) pingMsg
) + msgSize
) - pingMsg
->notifyHeader
.size
);
739 // == pingMsg->notifyHeader.content;
741 if (kIOMessageCopyClientID
== messageType
)
743 *((void **) messageArgument
) = IOCopyLogNameForPID(owningPID
);
744 return (kIOReturnSuccess
);
747 data
->messageType
= messageType
;
751 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
753 argSize
= sizeof(data
->messageArgument
[0]);
756 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
757 argSize
= sizeof(messageArgument
);
762 if( argSize
> kIOUserNotifyMaxMessageSize
)
763 argSize
= kIOUserNotifyMaxMessageSize
;
764 bcopy( messageArgument
, data
->messageArgument
, argSize
);
766 pingMsg
->msgHdr
.msgh_size
= msgSize
- pingMsg
->notifyHeader
.size
767 + sizeof( IOServiceInterestContent64
)
768 - sizeof( data
->messageArgument
)
771 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
772 pingMsg
->ports
[0].name
= providerPort
;
773 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
774 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
775 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
776 pingMsg
->msgHdr
.msgh_size
);
778 iokit_release_port( thisPort
);
780 iokit_release_port( providerPort
);
782 if( KERN_SUCCESS
!= kr
)
783 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
785 return( kIOReturnSuccess
);
788 OSObject
* IOServiceMessageUserNotification::getNextObject()
793 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
796 #define super IOService
797 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
799 void IOUserClient::initialize( void )
801 gIOObjectPortLock
= IOLockAlloc();
803 assert( gIOObjectPortLock
);
806 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
807 mach_port_t wakePort
,
808 void *callback
, void *refcon
)
810 asyncRef
[kIOAsyncReservedIndex
] = ((natural_t
) wakePort
)
811 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
812 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
813 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
816 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
817 mach_port_t wakePort
,
818 mach_vm_address_t callback
, io_user_reference_t refcon
)
820 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
821 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
822 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
823 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
826 inline OSDictionary
* CopyConsoleUser(UInt32 uid
)
829 OSDictionary
* user
= 0;
831 if ((array
= OSDynamicCast(OSArray
,
832 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
834 for (unsigned int idx
= 0;
835 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
839 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
840 && (uid
== num
->unsigned32BitValue())) {
850 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
851 const char * privilegeName
)
854 security_token_t token
;
855 mach_msg_type_number_t count
;
860 if ((secureConsole
= !strcmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
)))
861 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
863 task
= (task_t
)securityToken
;
865 count
= TASK_SECURITY_TOKEN_COUNT
;
866 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
868 if (KERN_SUCCESS
!= kr
)
870 else if (!strcmp(privilegeName
, kIOClientPrivilegeAdministrator
)) {
871 if (0 != token
.val
[0])
872 kr
= kIOReturnNotPrivileged
;
873 } else if (!strcmp(privilegeName
, kIOClientPrivilegeLocalUser
)) {
874 user
= CopyConsoleUser(token
.val
[0]);
878 kr
= kIOReturnNotPrivileged
;
879 } else if (secureConsole
|| !strcmp(privilegeName
, kIOClientPrivilegeConsoleUser
)) {
880 user
= CopyConsoleUser(token
.val
[0]);
882 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
883 kr
= kIOReturnNotPrivileged
;
884 else if ( secureConsole
) {
885 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
886 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
887 kr
= kIOReturnNotPrivileged
;
892 kr
= kIOReturnNotPrivileged
;
894 kr
= kIOReturnUnsupported
;
899 bool IOUserClient::init()
901 if( getPropertyTable())
904 return super::init();
907 bool IOUserClient::init(OSDictionary
* dictionary
)
909 if( getPropertyTable())
912 return super::init(dictionary
);
915 bool IOUserClient::initWithTask(task_t owningTask
,
919 if( getPropertyTable())
922 return super::init();
925 bool IOUserClient::initWithTask(task_t owningTask
,
928 OSDictionary
* properties
)
932 ok
= super::init( properties
);
933 ok
&= initWithTask( owningTask
, securityID
, type
);
938 void IOUserClient::free()
946 IOReturn
IOUserClient::clientDied( void )
948 return( clientClose());
951 IOReturn
IOUserClient::clientClose( void )
953 return( kIOReturnUnsupported
);
956 IOService
* IOUserClient::getService( void )
961 IOReturn
IOUserClient::registerNotificationPort(
962 mach_port_t
/* port */,
966 return( kIOReturnUnsupported
);
969 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
970 semaphore_t
* semaphore
)
972 return( kIOReturnUnsupported
);
975 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
977 return( kIOReturnUnsupported
);
980 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
981 IOOptionBits
* options
,
982 IOMemoryDescriptor
** memory
)
984 return( kIOReturnUnsupported
);
987 IOMemoryMap
* IOUserClient::mapClientMemory(
990 IOOptionBits mapFlags
,
991 IOVirtualAddress atAddress
)
994 IOOptionBits options
= 0;
995 IOMemoryDescriptor
* memory
;
996 IOMemoryMap
* map
= 0;
998 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1000 if( memory
&& (kIOReturnSuccess
== err
)) {
1002 options
= (options
& ~kIOMapUserOptionsMask
)
1003 | (mapFlags
& kIOMapUserOptionsMask
);
1004 map
= memory
->map( task
, atAddress
, options
);
1011 IOMemoryMap
* IOUserClient::mapClientMemory64(
1014 IOOptionBits mapFlags
,
1015 mach_vm_address_t atAddress
)
1018 IOOptionBits options
= 0;
1019 IOMemoryDescriptor
* memory
;
1020 IOMemoryMap
* map
= 0;
1022 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1024 if( memory
&& (kIOReturnSuccess
== err
)) {
1026 options
= (options
& ~kIOMapUserOptionsMask
)
1027 | (mapFlags
& kIOMapUserOptionsMask
);
1028 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1035 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1036 OSObject
*obj
, io_object_t
*clientObj
)
1038 mach_port_name_t name
;
1040 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1043 *(mach_port_name_t
*)clientObj
= name
;
1044 return kIOReturnSuccess
;
1047 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1052 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1057 IOExternalMethod
* IOUserClient::
1058 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1060 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1063 *targetP
= (IOService
*) method
->object
;
1068 IOExternalAsyncMethod
* IOUserClient::
1069 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1071 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1074 *targetP
= (IOService
*) method
->object
;
1079 IOExternalTrap
* IOUserClient::
1080 getExternalTrapForIndex(UInt32 index
)
1085 IOExternalTrap
* IOUserClient::
1086 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1088 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1091 *targetP
= trap
->object
;
1097 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1098 IOReturn result
, void *args
[], UInt32 numArgs
)
1100 OSAsyncReference64 reference64
;
1101 io_user_reference_t args64
[kMaxAsyncArgs
];
1104 if (numArgs
> kMaxAsyncArgs
)
1105 return kIOReturnMessageTooLarge
;
1107 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1108 reference64
[idx
] = REF64(reference
[idx
]);
1110 for (idx
= 0; idx
< numArgs
; idx
++)
1111 args64
[idx
] = REF64(args
[idx
]);
1113 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1116 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1117 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1121 mach_msg_header_t msgHdr
;
1126 OSNotificationHeader notifyHdr
;
1127 IOAsyncCompletionContent asyncContent
;
1128 uint32_t args
[kMaxAsyncArgs
];
1132 OSNotificationHeader64 notifyHdr
;
1133 IOAsyncCompletionContent asyncContent
;
1135 io_user_reference_t args
[kMaxAsyncArgs
];
1140 mach_port_t replyPort
;
1143 // If no reply port, do nothing.
1144 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1145 if (replyPort
== MACH_PORT_NULL
)
1146 return kIOReturnSuccess
;
1148 if (numArgs
> kMaxAsyncArgs
)
1149 return kIOReturnMessageTooLarge
;
1151 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1153 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1154 replyMsg
.msgHdr
.msgh_local_port
= 0;
1155 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1156 if (kIOUCAsync64Flag
& reference
[0])
1158 replyMsg
.msgHdr
.msgh_size
=
1159 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1160 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1161 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1163 + numArgs
* sizeof(io_user_reference_t
);
1164 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1165 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1167 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1169 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1175 replyMsg
.msgHdr
.msgh_size
=
1176 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1177 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1179 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1180 + numArgs
* sizeof(uint32_t);
1181 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1183 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1184 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1186 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1188 for (idx
= 0; idx
< numArgs
; idx
++)
1189 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1192 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
1193 replyMsg
.msgHdr
.msgh_size
);
1194 if( KERN_SUCCESS
!= kr
)
1195 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
1200 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1204 #define CHECK(cls,obj,out) \
1206 if( !(out = OSDynamicCast( cls, obj))) \
1207 return( kIOReturnBadArgument )
1209 /* Routine io_object_get_class */
1210 kern_return_t
is_io_object_get_class(
1212 io_name_t className
)
1214 const OSMetaClass
* my_obj
= NULL
;
1217 return( kIOReturnBadArgument
);
1219 my_obj
= object
->getMetaClass();
1221 return (kIOReturnNotFound
);
1224 strcpy( className
, my_obj
->getClassName());
1225 return( kIOReturnSuccess
);
1228 /* Routine io_object_get_superclass */
1229 kern_return_t
is_io_object_get_superclass(
1230 mach_port_t master_port
,
1232 io_name_t class_name
)
1234 const OSMetaClass
* my_obj
= NULL
;
1235 const OSMetaClass
* superclass
= NULL
;
1236 const OSSymbol
*my_name
= NULL
;
1237 const char *my_cstr
= NULL
;
1239 if (!obj_name
|| !class_name
)
1240 return (kIOReturnBadArgument
);
1242 if( master_port
!= master_device_port
)
1243 return( kIOReturnNotPrivileged
);
1245 my_name
= OSSymbol::withCString(obj_name
);
1248 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1252 superclass
= my_obj
->getSuperClass();
1256 return( kIOReturnNotFound
);
1259 my_cstr
= superclass
->getClassName();
1262 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1263 return( kIOReturnSuccess
);
1265 return (kIOReturnNotFound
);
1268 /* Routine io_object_get_bundle_identifier */
1269 kern_return_t
is_io_object_get_bundle_identifier(
1270 mach_port_t master_port
,
1272 io_name_t bundle_name
)
1274 const OSMetaClass
* my_obj
= NULL
;
1275 const OSSymbol
*my_name
= NULL
;
1276 const OSSymbol
*identifier
= NULL
;
1277 const char *my_cstr
= NULL
;
1279 if (!obj_name
|| !bundle_name
)
1280 return (kIOReturnBadArgument
);
1282 if( master_port
!= master_device_port
)
1283 return( kIOReturnNotPrivileged
);
1285 my_name
= OSSymbol::withCString(obj_name
);
1288 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1293 identifier
= my_obj
->getKmodName();
1296 return( kIOReturnNotFound
);
1299 my_cstr
= identifier
->getCStringNoCopy();
1301 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1302 return( kIOReturnSuccess
);
1305 return (kIOReturnBadArgument
);
1308 /* Routine io_object_conforms_to */
1309 kern_return_t
is_io_object_conforms_to(
1311 io_name_t className
,
1312 boolean_t
*conforms
)
1315 return( kIOReturnBadArgument
);
1317 *conforms
= (0 != object
->metaCast( className
));
1318 return( kIOReturnSuccess
);
1321 /* Routine io_object_get_retain_count */
1322 kern_return_t
is_io_object_get_retain_count(
1324 uint32_t *retainCount
)
1327 return( kIOReturnBadArgument
);
1329 *retainCount
= object
->getRetainCount();
1330 return( kIOReturnSuccess
);
1333 /* Routine io_iterator_next */
1334 kern_return_t
is_io_iterator_next(
1335 io_object_t iterator
,
1336 io_object_t
*object
)
1340 CHECK( OSIterator
, iterator
, iter
);
1342 obj
= iter
->getNextObject();
1346 return( kIOReturnSuccess
);
1348 return( kIOReturnNoDevice
);
1351 /* Routine io_iterator_reset */
1352 kern_return_t
is_io_iterator_reset(
1353 io_object_t iterator
)
1355 CHECK( OSIterator
, iterator
, iter
);
1359 return( kIOReturnSuccess
);
1362 /* Routine io_iterator_is_valid */
1363 kern_return_t
is_io_iterator_is_valid(
1364 io_object_t iterator
,
1365 boolean_t
*is_valid
)
1367 CHECK( OSIterator
, iterator
, iter
);
1369 *is_valid
= iter
->isValid();
1371 return( kIOReturnSuccess
);
1374 /* Routine io_service_match_property_table */
1375 kern_return_t
is_io_service_match_property_table(
1376 io_service_t _service
,
1377 io_string_t matching
,
1378 boolean_t
*matches
)
1380 CHECK( IOService
, _service
, service
);
1384 OSDictionary
* dict
;
1386 obj
= OSUnserializeXML( matching
);
1388 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1389 *matches
= service
->passiveMatch( dict
);
1390 kr
= kIOReturnSuccess
;
1392 kr
= kIOReturnBadArgument
;
1400 /* Routine io_service_match_property_table_ool */
1401 kern_return_t
is_io_service_match_property_table_ool(
1402 io_object_t service
,
1403 io_buf_ptr_t matching
,
1404 mach_msg_type_number_t matchingCnt
,
1405 kern_return_t
*result
,
1406 boolean_t
*matches
)
1410 vm_map_offset_t map_data
;
1412 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1413 data
= CAST_DOWN(vm_offset_t
, map_data
);
1415 if( KERN_SUCCESS
== kr
) {
1416 // must return success after vm_map_copyout() succeeds
1417 *result
= is_io_service_match_property_table( service
,
1418 (char *) data
, matches
);
1419 vm_deallocate( kernel_map
, data
, matchingCnt
);
1425 /* Routine io_service_get_matching_services */
1426 kern_return_t
is_io_service_get_matching_services(
1427 mach_port_t master_port
,
1428 io_string_t matching
,
1429 io_iterator_t
*existing
)
1433 OSDictionary
* dict
;
1435 if( master_port
!= master_device_port
)
1436 return( kIOReturnNotPrivileged
);
1438 obj
= OSUnserializeXML( matching
);
1440 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1441 *existing
= IOService::getMatchingServices( dict
);
1442 kr
= kIOReturnSuccess
;
1444 kr
= kIOReturnBadArgument
;
1452 /* Routine io_service_get_matching_services_ool */
1453 kern_return_t
is_io_service_get_matching_services_ool(
1454 mach_port_t master_port
,
1455 io_buf_ptr_t matching
,
1456 mach_msg_type_number_t matchingCnt
,
1457 kern_return_t
*result
,
1458 io_object_t
*existing
)
1462 vm_map_offset_t map_data
;
1464 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1465 data
= CAST_DOWN(vm_offset_t
, map_data
);
1467 if( KERN_SUCCESS
== kr
) {
1468 // must return success after vm_map_copyout() succeeds
1469 *result
= is_io_service_get_matching_services( master_port
,
1470 (char *) data
, existing
);
1471 vm_deallocate( kernel_map
, data
, matchingCnt
);
1477 static kern_return_t
internal_io_service_add_notification(
1478 mach_port_t master_port
,
1479 io_name_t notification_type
,
1480 io_string_t matching
,
1483 vm_size_t referenceSize
,
1485 io_object_t
* notification
)
1487 IOServiceUserNotification
* userNotify
= 0;
1488 IONotifier
* notify
= 0;
1489 const OSSymbol
* sym
;
1490 OSDictionary
* dict
;
1492 unsigned long int userMsgType
;
1495 if( master_port
!= master_device_port
)
1496 return( kIOReturnNotPrivileged
);
1499 err
= kIOReturnNoResources
;
1501 if( !(sym
= OSSymbol::withCString( notification_type
)))
1502 err
= kIOReturnNoResources
;
1504 if( !(dict
= OSDynamicCast( OSDictionary
,
1505 OSUnserializeXML( matching
)))) {
1506 err
= kIOReturnBadArgument
;
1510 if( (sym
== gIOPublishNotification
)
1511 || (sym
== gIOFirstPublishNotification
))
1512 userMsgType
= kIOServicePublishNotificationType
;
1513 else if( (sym
== gIOMatchedNotification
)
1514 || (sym
== gIOFirstMatchNotification
))
1515 userMsgType
= kIOServiceMatchedNotificationType
;
1516 else if( sym
== gIOTerminatedNotification
)
1517 userMsgType
= kIOServiceTerminatedNotificationType
;
1519 userMsgType
= kLastIOKitNotificationType
;
1521 userNotify
= new IOServiceUserNotification
;
1523 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1524 reference
, referenceSize
, client64
)) {
1525 userNotify
->release();
1531 notify
= IOService::addNotification( sym
, dict
,
1532 &userNotify
->_handler
, userNotify
);
1535 *notification
= userNotify
;
1536 userNotify
->setNotification( notify
);
1537 err
= kIOReturnSuccess
;
1539 err
= kIOReturnUnsupported
;
1552 /* Routine io_service_add_notification */
1553 kern_return_t
is_io_service_add_notification(
1554 mach_port_t master_port
,
1555 io_name_t notification_type
,
1556 io_string_t matching
,
1558 io_async_ref_t reference
,
1559 mach_msg_type_number_t referenceCnt
,
1560 io_object_t
* notification
)
1562 return (internal_io_service_add_notification(master_port
, notification_type
,
1563 matching
, port
, &reference
[0], sizeof(io_async_ref_t
),
1564 false, notification
));
1567 /* Routine io_service_add_notification_64 */
1568 kern_return_t
is_io_service_add_notification_64(
1569 mach_port_t master_port
,
1570 io_name_t notification_type
,
1571 io_string_t matching
,
1572 mach_port_t wake_port
,
1573 io_async_ref64_t reference
,
1574 mach_msg_type_number_t referenceCnt
,
1575 io_object_t
*notification
)
1577 return (internal_io_service_add_notification(master_port
, notification_type
,
1578 matching
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1579 true, notification
));
1583 static kern_return_t
internal_io_service_add_notification_ool(
1584 mach_port_t master_port
,
1585 io_name_t notification_type
,
1586 io_buf_ptr_t matching
,
1587 mach_msg_type_number_t matchingCnt
,
1588 mach_port_t wake_port
,
1590 vm_size_t referenceSize
,
1592 kern_return_t
*result
,
1593 io_object_t
*notification
)
1597 vm_map_offset_t map_data
;
1599 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1600 data
= CAST_DOWN(vm_offset_t
, map_data
);
1602 if( KERN_SUCCESS
== kr
) {
1603 // must return success after vm_map_copyout() succeeds
1604 *result
= internal_io_service_add_notification( master_port
, notification_type
,
1605 (char *) data
, wake_port
, reference
, referenceSize
, client64
, notification
);
1606 vm_deallocate( kernel_map
, data
, matchingCnt
);
1612 /* Routine io_service_add_notification_ool */
1613 kern_return_t
is_io_service_add_notification_ool(
1614 mach_port_t master_port
,
1615 io_name_t notification_type
,
1616 io_buf_ptr_t matching
,
1617 mach_msg_type_number_t matchingCnt
,
1618 mach_port_t wake_port
,
1619 io_async_ref_t reference
,
1620 mach_msg_type_number_t referenceCnt
,
1621 kern_return_t
*result
,
1622 io_object_t
*notification
)
1624 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1625 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
1626 false, result
, notification
));
1629 /* Routine io_service_add_notification_ool_64 */
1630 kern_return_t
is_io_service_add_notification_ool_64(
1631 mach_port_t master_port
,
1632 io_name_t notification_type
,
1633 io_buf_ptr_t matching
,
1634 mach_msg_type_number_t matchingCnt
,
1635 mach_port_t wake_port
,
1636 io_async_ref64_t reference
,
1637 mach_msg_type_number_t referenceCnt
,
1638 kern_return_t
*result
,
1639 io_object_t
*notification
)
1641 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
1642 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
1643 true, result
, notification
));
1646 /* Routine io_service_add_notification_old */
1647 kern_return_t
is_io_service_add_notification_old(
1648 mach_port_t master_port
,
1649 io_name_t notification_type
,
1650 io_string_t matching
,
1653 io_object_t
* notification
)
1655 return( is_io_service_add_notification( master_port
, notification_type
,
1656 matching
, port
, &ref
, 1, notification
));
1660 static kern_return_t
internal_io_service_add_interest_notification(
1661 io_object_t _service
,
1662 io_name_t type_of_interest
,
1665 vm_size_t referenceSize
,
1667 io_object_t
* notification
)
1670 IOServiceMessageUserNotification
* userNotify
= 0;
1671 IONotifier
* notify
= 0;
1672 const OSSymbol
* sym
;
1675 CHECK( IOService
, _service
, service
);
1677 err
= kIOReturnNoResources
;
1678 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1680 userNotify
= new IOServiceMessageUserNotification
;
1682 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1683 reference
, referenceSize
,
1684 kIOUserNotifyMaxMessageSize
,
1686 userNotify
->release();
1692 notify
= service
->registerInterest( sym
,
1693 &userNotify
->_handler
, userNotify
);
1695 *notification
= userNotify
;
1696 userNotify
->setNotification( notify
);
1697 err
= kIOReturnSuccess
;
1699 err
= kIOReturnUnsupported
;
1708 /* Routine io_service_add_message_notification */
1709 kern_return_t
is_io_service_add_interest_notification(
1710 io_object_t service
,
1711 io_name_t type_of_interest
,
1713 io_async_ref_t reference
,
1714 mach_msg_type_number_t referenceCnt
,
1715 io_object_t
* notification
)
1717 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1718 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
1721 /* Routine io_service_add_interest_notification_64 */
1722 kern_return_t
is_io_service_add_interest_notification_64(
1723 io_object_t service
,
1724 io_name_t type_of_interest
,
1725 mach_port_t wake_port
,
1726 io_async_ref64_t reference
,
1727 mach_msg_type_number_t referenceCnt
,
1728 io_object_t
*notification
)
1730 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
1731 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
1735 /* Routine io_service_acknowledge_notification */
1736 kern_return_t
is_io_service_acknowledge_notification(
1737 io_object_t _service
,
1738 natural_t notify_ref
,
1739 natural_t response
)
1741 CHECK( IOService
, _service
, service
);
1743 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1744 (IOOptionBits
) response
));
1748 /* Routine io_connect_get_semaphore */
1749 kern_return_t
is_io_connect_get_notification_semaphore(
1750 io_connect_t connection
,
1751 natural_t notification_type
,
1752 semaphore_t
*semaphore
)
1754 CHECK( IOUserClient
, connection
, client
);
1756 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1760 /* Routine io_registry_get_root_entry */
1761 kern_return_t
is_io_registry_get_root_entry(
1762 mach_port_t master_port
,
1765 IORegistryEntry
* entry
;
1767 if( master_port
!= master_device_port
)
1768 return( kIOReturnNotPrivileged
);
1770 entry
= IORegistryEntry::getRegistryRoot();
1775 return( kIOReturnSuccess
);
1778 /* Routine io_registry_create_iterator */
1779 kern_return_t
is_io_registry_create_iterator(
1780 mach_port_t master_port
,
1783 io_object_t
*iterator
)
1785 if( master_port
!= master_device_port
)
1786 return( kIOReturnNotPrivileged
);
1788 *iterator
= IORegistryIterator::iterateOver(
1789 IORegistryEntry::getPlane( plane
), options
);
1791 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1794 /* Routine io_registry_entry_create_iterator */
1795 kern_return_t
is_io_registry_entry_create_iterator(
1796 io_object_t registry_entry
,
1799 io_object_t
*iterator
)
1801 CHECK( IORegistryEntry
, registry_entry
, entry
);
1803 *iterator
= IORegistryIterator::iterateOver( entry
,
1804 IORegistryEntry::getPlane( plane
), options
);
1806 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1809 /* Routine io_registry_iterator_enter */
1810 kern_return_t
is_io_registry_iterator_enter_entry(
1811 io_object_t iterator
)
1813 CHECK( IORegistryIterator
, iterator
, iter
);
1817 return( kIOReturnSuccess
);
1820 /* Routine io_registry_iterator_exit */
1821 kern_return_t
is_io_registry_iterator_exit_entry(
1822 io_object_t iterator
)
1826 CHECK( IORegistryIterator
, iterator
, iter
);
1828 didIt
= iter
->exitEntry();
1830 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1833 /* Routine io_registry_entry_from_path */
1834 kern_return_t
is_io_registry_entry_from_path(
1835 mach_port_t master_port
,
1837 io_object_t
*registry_entry
)
1839 IORegistryEntry
* entry
;
1841 if( master_port
!= master_device_port
)
1842 return( kIOReturnNotPrivileged
);
1844 entry
= IORegistryEntry::fromPath( path
);
1846 *registry_entry
= entry
;
1848 return( kIOReturnSuccess
);
1851 /* Routine io_registry_entry_in_plane */
1852 kern_return_t
is_io_registry_entry_in_plane(
1853 io_object_t registry_entry
,
1855 boolean_t
*inPlane
)
1857 CHECK( IORegistryEntry
, registry_entry
, entry
);
1859 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1861 return( kIOReturnSuccess
);
1865 /* Routine io_registry_entry_get_path */
1866 kern_return_t
is_io_registry_entry_get_path(
1867 io_object_t registry_entry
,
1872 CHECK( IORegistryEntry
, registry_entry
, entry
);
1874 length
= sizeof( io_string_t
);
1875 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1876 return( kIOReturnSuccess
);
1878 return( kIOReturnBadArgument
);
1882 /* Routine io_registry_entry_get_name */
1883 kern_return_t
is_io_registry_entry_get_name(
1884 io_object_t registry_entry
,
1887 CHECK( IORegistryEntry
, registry_entry
, entry
);
1889 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1891 return( kIOReturnSuccess
);
1894 /* Routine io_registry_entry_get_name_in_plane */
1895 kern_return_t
is_io_registry_entry_get_name_in_plane(
1896 io_object_t registry_entry
,
1897 io_name_t planeName
,
1900 const IORegistryPlane
* plane
;
1901 CHECK( IORegistryEntry
, registry_entry
, entry
);
1904 plane
= IORegistryEntry::getPlane( planeName
);
1908 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1910 return( kIOReturnSuccess
);
1913 /* Routine io_registry_entry_get_location_in_plane */
1914 kern_return_t
is_io_registry_entry_get_location_in_plane(
1915 io_object_t registry_entry
,
1916 io_name_t planeName
,
1917 io_name_t location
)
1919 const IORegistryPlane
* plane
;
1920 CHECK( IORegistryEntry
, registry_entry
, entry
);
1923 plane
= IORegistryEntry::getPlane( planeName
);
1927 const char * cstr
= entry
->getLocation( plane
);
1930 strncpy( location
, cstr
, sizeof( io_name_t
));
1931 return( kIOReturnSuccess
);
1933 return( kIOReturnNotFound
);
1936 // Create a vm_map_copy_t or kalloc'ed data for memory
1937 // to be copied out. ipc will free after the copyout.
1939 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1940 io_buf_ptr_t
* buf
)
1945 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1946 false /* src_destroy */, ©
);
1948 assert( err
== KERN_SUCCESS
);
1949 if( err
== KERN_SUCCESS
)
1950 *buf
= (char *) copy
;
1955 /* Routine io_registry_entry_get_property */
1956 kern_return_t
is_io_registry_entry_get_property_bytes(
1957 io_object_t registry_entry
,
1958 io_name_t property_name
,
1959 io_struct_inband_t buf
,
1960 mach_msg_type_number_t
*dataCnt
)
1968 unsigned int len
= 0;
1969 const void * bytes
= 0;
1970 IOReturn ret
= kIOReturnSuccess
;
1972 CHECK( IORegistryEntry
, registry_entry
, entry
);
1974 obj
= entry
->copyProperty(property_name
);
1976 return( kIOReturnNoResources
);
1978 // One day OSData will be a common container base class
1980 if( (data
= OSDynamicCast( OSData
, obj
))) {
1981 len
= data
->getLength();
1982 bytes
= data
->getBytesNoCopy();
1984 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1985 len
= str
->getLength() + 1;
1986 bytes
= str
->getCStringNoCopy();
1988 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1989 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1990 bytes
= boo
->isTrue() ? "Yes" : "No";
1992 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1993 offsetBytes
= off
->unsigned64BitValue();
1994 len
= off
->numberOfBytes();
1995 bytes
= &offsetBytes
;
1996 #ifdef __BIG_ENDIAN__
1997 bytes
= (const void *)
1998 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2002 ret
= kIOReturnBadArgument
;
2006 ret
= kIOReturnIPCError
;
2009 bcopy( bytes
, buf
, len
);
2018 /* Routine io_registry_entry_get_property */
2019 kern_return_t
is_io_registry_entry_get_property(
2020 io_object_t registry_entry
,
2021 io_name_t property_name
,
2022 io_buf_ptr_t
*properties
,
2023 mach_msg_type_number_t
*propertiesCnt
)
2029 CHECK( IORegistryEntry
, registry_entry
, entry
);
2031 obj
= entry
->copyProperty(property_name
);
2033 return( kIOReturnNotFound
);
2035 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2038 return( kIOReturnNoMemory
);
2042 if( obj
->serialize( s
)) {
2043 len
= s
->getLength();
2044 *propertiesCnt
= len
;
2045 err
= copyoutkdata( s
->text(), len
, properties
);
2048 err
= kIOReturnUnsupported
;
2056 /* Routine io_registry_entry_get_property_recursively */
2057 kern_return_t
is_io_registry_entry_get_property_recursively(
2058 io_object_t registry_entry
,
2060 io_name_t property_name
,
2062 io_buf_ptr_t
*properties
,
2063 mach_msg_type_number_t
*propertiesCnt
)
2069 CHECK( IORegistryEntry
, registry_entry
, entry
);
2071 obj
= entry
->copyProperty( property_name
,
2072 IORegistryEntry::getPlane( plane
), options
);
2074 return( kIOReturnNotFound
);
2076 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2079 return( kIOReturnNoMemory
);
2084 if( obj
->serialize( s
)) {
2085 len
= s
->getLength();
2086 *propertiesCnt
= len
;
2087 err
= copyoutkdata( s
->text(), len
, properties
);
2090 err
= kIOReturnUnsupported
;
2098 /* Routine io_registry_entry_get_properties */
2099 kern_return_t
is_io_registry_entry_get_properties(
2100 io_object_t registry_entry
,
2101 io_buf_ptr_t
*properties
,
2102 mach_msg_type_number_t
*propertiesCnt
)
2107 CHECK( IORegistryEntry
, registry_entry
, entry
);
2109 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2111 return( kIOReturnNoMemory
);
2115 if( entry
->serializeProperties( s
)) {
2116 len
= s
->getLength();
2117 *propertiesCnt
= len
;
2118 err
= copyoutkdata( s
->text(), len
, properties
);
2121 err
= kIOReturnUnsupported
;
2128 /* Routine io_registry_entry_set_properties */
2129 kern_return_t is_io_registry_entry_set_properties
2131 io_object_t registry_entry
,
2132 io_buf_ptr_t properties
,
2133 mach_msg_type_number_t propertiesCnt
,
2134 kern_return_t
* result
)
2140 vm_map_offset_t map_data
;
2142 CHECK( IORegistryEntry
, registry_entry
, entry
);
2144 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2145 data
= CAST_DOWN(vm_offset_t
, map_data
);
2147 if( KERN_SUCCESS
== err
) {
2149 // must return success after vm_map_copyout() succeeds
2150 obj
= OSUnserializeXML( (const char *) data
);
2151 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2154 res
= entry
->setProperties( obj
);
2157 res
= kIOReturnBadArgument
;
2165 /* Routine io_registry_entry_get_child_iterator */
2166 kern_return_t
is_io_registry_entry_get_child_iterator(
2167 io_object_t registry_entry
,
2169 io_object_t
*iterator
)
2171 CHECK( IORegistryEntry
, registry_entry
, entry
);
2173 *iterator
= entry
->getChildIterator(
2174 IORegistryEntry::getPlane( plane
));
2176 return( kIOReturnSuccess
);
2179 /* Routine io_registry_entry_get_parent_iterator */
2180 kern_return_t
is_io_registry_entry_get_parent_iterator(
2181 io_object_t registry_entry
,
2183 io_object_t
*iterator
)
2185 CHECK( IORegistryEntry
, registry_entry
, entry
);
2187 *iterator
= entry
->getParentIterator(
2188 IORegistryEntry::getPlane( plane
));
2190 return( kIOReturnSuccess
);
2193 /* Routine io_service_get_busy_state */
2194 kern_return_t
is_io_service_get_busy_state(
2195 io_object_t _service
,
2196 uint32_t *busyState
)
2198 CHECK( IOService
, _service
, service
);
2200 *busyState
= service
->getBusyState();
2202 return( kIOReturnSuccess
);
2205 /* Routine io_service_get_state */
2206 kern_return_t
is_io_service_get_state(
2207 io_object_t _service
,
2210 CHECK( IOService
, _service
, service
);
2212 *state
= service
->getState();
2214 return( kIOReturnSuccess
);
2217 /* Routine io_service_wait_quiet */
2218 kern_return_t
is_io_service_wait_quiet(
2219 io_object_t _service
,
2220 mach_timespec_t wait_time
)
2222 CHECK( IOService
, _service
, service
);
2224 return( service
->waitQuiet( &wait_time
));
2227 /* Routine io_service_request_probe */
2228 kern_return_t
is_io_service_request_probe(
2229 io_object_t _service
,
2232 CHECK( IOService
, _service
, service
);
2234 return( service
->requestProbe( options
));
2238 /* Routine io_service_open */
2239 kern_return_t
is_io_service_open(
2240 io_object_t _service
,
2242 uint32_t connect_type
,
2243 io_object_t
*connection
)
2245 IOUserClient
* client
;
2248 CHECK( IOService
, _service
, service
);
2250 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
2251 connect_type
, 0, &client
);
2253 if( err
== kIOReturnSuccess
) {
2254 assert( OSDynamicCast(IOUserClient
, client
) );
2255 *connection
= client
;
2261 /* Routine io_service_open_ndr */
2262 kern_return_t
is_io_service_open_extended(
2263 io_object_t _service
,
2265 uint32_t connect_type
,
2267 io_buf_ptr_t properties
,
2268 mach_msg_type_number_t propertiesCnt
,
2269 kern_return_t
* result
,
2270 io_object_t
*connection
)
2272 IOUserClient
* client
= 0;
2273 kern_return_t err
= KERN_SUCCESS
;
2274 IOReturn res
= kIOReturnSuccess
;
2275 OSDictionary
* propertiesDict
= 0;
2277 bool disallowAccess
;
2279 CHECK( IOService
, _service
, service
);
2287 vm_map_offset_t map_data
;
2289 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2291 data
= CAST_DOWN(vm_offset_t
, map_data
);
2292 if (KERN_SUCCESS
== err
)
2294 // must return success after vm_map_copyout() succeeds
2295 obj
= OSUnserializeXML( (const char *) data
);
2296 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2297 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
2298 if (!propertiesDict
)
2300 res
= kIOReturnBadArgument
;
2305 if (kIOReturnSuccess
!= res
)
2309 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
2312 if (!propertiesDict
)
2313 propertiesDict
= OSDictionary::withCapacity(4);
2314 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
2318 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
2323 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
2324 connect_type
, propertiesDict
, &client
);
2327 propertiesDict
->release();
2329 if (res
== kIOReturnSuccess
)
2331 assert( OSDynamicCast(IOUserClient
, client
) );
2333 disallowAccess
= (crossEndian
2334 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
2335 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
2339 client
->clientClose();
2342 res
= kIOReturnUnsupported
;
2345 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
2350 *connection
= client
;
2356 /* Routine io_service_close */
2357 kern_return_t
is_io_service_close(
2358 io_object_t connection
)
2361 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2362 return( kIOReturnSuccess
);
2364 CHECK( IOUserClient
, connection
, client
);
2366 client
->clientClose();
2368 return( kIOReturnSuccess
);
2371 /* Routine io_connect_get_service */
2372 kern_return_t
is_io_connect_get_service(
2373 io_object_t connection
,
2374 io_object_t
*service
)
2376 IOService
* theService
;
2378 CHECK( IOUserClient
, connection
, client
);
2380 theService
= client
->getService();
2382 theService
->retain();
2384 *service
= theService
;
2386 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2389 /* Routine io_connect_set_notification_port */
2390 kern_return_t
is_io_connect_set_notification_port(
2391 io_object_t connection
,
2392 uint32_t notification_type
,
2396 CHECK( IOUserClient
, connection
, client
);
2398 return( client
->registerNotificationPort( port
, notification_type
,
2402 /* Routine io_connect_set_notification_port */
2403 kern_return_t
is_io_connect_set_notification_port_64(
2404 io_object_t connection
,
2405 uint32_t notification_type
,
2407 io_user_reference_t reference
)
2409 CHECK( IOUserClient
, connection
, client
);
2411 return( client
->registerNotificationPort( port
, notification_type
,
2415 /* Routine io_connect_map_memory_into_task */
2416 kern_return_t is_io_connect_map_memory_into_task
2418 io_connect_t connection
,
2419 uint32_t memory_type
,
2421 mach_vm_address_t
*address
,
2422 mach_vm_size_t
*size
,
2429 CHECK( IOUserClient
, connection
, client
);
2431 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
2434 *address
= map
->getAddress();
2436 *size
= map
->getSize();
2438 if( client
->sharedInstance
2439 || (into_task
!= current_task())) {
2440 // push a name out to the task owning the map,
2441 // so we can clean up maps
2442 mach_port_name_t name __unused
=
2443 IOMachPort::makeSendRightForTask(
2444 into_task
, map
, IKOT_IOKIT_OBJECT
);
2448 // keep it with the user client
2449 IOLockLock( gIOObjectPortLock
);
2450 if( 0 == client
->mappings
)
2451 client
->mappings
= OSSet::withCapacity(2);
2452 if( client
->mappings
)
2453 client
->mappings
->setObject( map
);
2454 IOLockUnlock( gIOObjectPortLock
);
2457 err
= kIOReturnSuccess
;
2460 err
= kIOReturnBadArgument
;
2465 /* Routine is_io_connect_map_memory */
2466 kern_return_t
is_io_connect_map_memory(
2467 io_object_t connect
,
2470 vm_address_t
* mapAddr
,
2471 vm_size_t
* mapSize
,
2475 mach_vm_address_t address
;
2476 mach_vm_size_t size
;
2478 address
= SCALAR64(*mapAddr
);
2479 size
= SCALAR64(*mapSize
);
2481 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
2483 *mapAddr
= SCALAR32(address
);
2484 *mapSize
= SCALAR32(size
);
2489 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2492 IOMemoryMap
* map
= 0;
2494 IOLockLock(gIOObjectPortLock
);
2496 iter
= OSCollectionIterator::withCollection(mappings
);
2499 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2501 if(mem
== map
->getMemoryDescriptor())
2504 mappings
->removeObject(map
);
2511 IOLockUnlock(gIOObjectPortLock
);
2516 /* Routine io_connect_unmap_memory_from_task */
2517 kern_return_t is_io_connect_unmap_memory_from_task
2519 io_connect_t connection
,
2520 uint32_t memory_type
,
2522 mach_vm_address_t address
)
2525 IOOptionBits options
= 0;
2526 IOMemoryDescriptor
* memory
;
2529 CHECK( IOUserClient
, connection
, client
);
2531 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
2533 if( memory
&& (kIOReturnSuccess
== err
)) {
2535 options
= (options
& ~kIOMapUserOptionsMask
)
2536 | kIOMapAnywhere
| kIOMapReference
;
2538 map
= memory
->createMappingInTask( from_task
, address
, options
);
2542 IOLockLock( gIOObjectPortLock
);
2543 if( client
->mappings
)
2544 client
->mappings
->removeObject( map
);
2545 IOLockUnlock( gIOObjectPortLock
);
2547 mach_port_name_t name
= 0;
2548 if (from_task
!= current_task())
2549 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
2553 err
= iokit_mod_send_right( from_task
, name
, -2 );
2554 err
= kIOReturnSuccess
;
2557 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2558 if (from_task
== current_task())
2562 err
= kIOReturnBadArgument
;
2568 kern_return_t
is_io_connect_unmap_memory(
2569 io_object_t connect
,
2572 vm_address_t mapAddr
)
2575 mach_vm_address_t address
;
2577 address
= SCALAR64(mapAddr
);
2579 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
2585 /* Routine io_connect_add_client */
2586 kern_return_t
is_io_connect_add_client(
2587 io_object_t connection
,
2588 io_object_t connect_to
)
2590 CHECK( IOUserClient
, connection
, client
);
2591 CHECK( IOUserClient
, connect_to
, to
);
2593 return( client
->connectClient( to
) );
2597 /* Routine io_connect_set_properties */
2598 kern_return_t
is_io_connect_set_properties(
2599 io_object_t connection
,
2600 io_buf_ptr_t properties
,
2601 mach_msg_type_number_t propertiesCnt
,
2602 kern_return_t
* result
)
2604 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2608 /* Routine io_user_client_method */
2609 kern_return_t is_io_connect_method
2611 io_connect_t connection
,
2613 io_scalar_inband64_t scalar_input
,
2614 mach_msg_type_number_t scalar_inputCnt
,
2615 io_struct_inband_t inband_input
,
2616 mach_msg_type_number_t inband_inputCnt
,
2617 mach_vm_address_t ool_input
,
2618 mach_vm_size_t ool_input_size
,
2619 io_scalar_inband64_t scalar_output
,
2620 mach_msg_type_number_t
*scalar_outputCnt
,
2621 io_struct_inband_t inband_output
,
2622 mach_msg_type_number_t
*inband_outputCnt
,
2623 mach_vm_address_t ool_output
,
2624 mach_vm_size_t
* ool_output_size
2627 CHECK( IOUserClient
, connection
, client
);
2629 IOExternalMethodArguments args
;
2631 IOMemoryDescriptor
* inputMD
= 0;
2632 IOMemoryDescriptor
* outputMD
= 0;
2634 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
2635 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
2637 args
.selector
= selector
;
2639 args
.asyncWakePort
= MACH_PORT_NULL
;
2640 args
.asyncReference
= 0;
2641 args
.asyncReferenceCount
= 0;
2643 args
.scalarInput
= scalar_input
;
2644 args
.scalarInputCount
= scalar_inputCnt
;
2645 args
.structureInput
= inband_input
;
2646 args
.structureInputSize
= inband_inputCnt
;
2649 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
2650 kIODirectionOut
, current_task());
2652 args
.structureInputDescriptor
= inputMD
;
2654 args
.scalarOutput
= scalar_output
;
2655 args
.scalarOutputCount
= *scalar_outputCnt
;
2656 args
.structureOutput
= inband_output
;
2657 args
.structureOutputSize
= *inband_outputCnt
;
2661 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
2662 kIODirectionIn
, current_task());
2665 args
.structureOutputDescriptor
= outputMD
;
2666 args
.structureOutputDescriptorSize
= *ool_output_size
;
2668 ret
= client
->externalMethod( selector
, &args
);
2670 *scalar_outputCnt
= args
.scalarOutputCount
;
2671 *inband_outputCnt
= args
.structureOutputSize
;
2672 *ool_output_size
= args
.structureOutputDescriptorSize
;
2677 outputMD
->release();
2682 /* Routine io_async_user_client_method */
2683 kern_return_t is_io_connect_async_method
2685 io_connect_t connection
,
2686 mach_port_t wake_port
,
2687 io_async_ref64_t reference
,
2688 mach_msg_type_number_t referenceCnt
,
2690 io_scalar_inband64_t scalar_input
,
2691 mach_msg_type_number_t scalar_inputCnt
,
2692 io_struct_inband_t inband_input
,
2693 mach_msg_type_number_t inband_inputCnt
,
2694 mach_vm_address_t ool_input
,
2695 mach_vm_size_t ool_input_size
,
2696 io_scalar_inband64_t scalar_output
,
2697 mach_msg_type_number_t
*scalar_outputCnt
,
2698 io_struct_inband_t inband_output
,
2699 mach_msg_type_number_t
*inband_outputCnt
,
2700 mach_vm_address_t ool_output
,
2701 mach_vm_size_t
* ool_output_size
2704 CHECK( IOUserClient
, connection
, client
);
2706 IOExternalMethodArguments args
;
2708 IOMemoryDescriptor
* inputMD
= 0;
2709 IOMemoryDescriptor
* outputMD
= 0;
2711 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
2712 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
2714 reference
[0] = (io_user_reference_t
) wake_port
;
2715 if (vm_map_is_64bit(get_task_map(current_task())))
2716 reference
[0] |= kIOUCAsync64Flag
;
2718 args
.selector
= selector
;
2720 args
.asyncWakePort
= wake_port
;
2721 args
.asyncReference
= reference
;
2722 args
.asyncReferenceCount
= referenceCnt
;
2724 args
.scalarInput
= scalar_input
;
2725 args
.scalarInputCount
= scalar_inputCnt
;
2726 args
.structureInput
= inband_input
;
2727 args
.structureInputSize
= inband_inputCnt
;
2730 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
2731 kIODirectionOut
, current_task());
2733 args
.structureInputDescriptor
= inputMD
;
2735 args
.scalarOutput
= scalar_output
;
2736 args
.scalarOutputCount
= *scalar_outputCnt
;
2737 args
.structureOutput
= inband_output
;
2738 args
.structureOutputSize
= *inband_outputCnt
;
2742 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
2743 kIODirectionIn
, current_task());
2746 args
.structureOutputDescriptor
= outputMD
;
2747 args
.structureOutputDescriptorSize
= *ool_output_size
;
2749 ret
= client
->externalMethod( selector
, &args
);
2751 *inband_outputCnt
= args
.structureOutputSize
;
2752 *ool_output_size
= args
.structureOutputDescriptorSize
;
2757 outputMD
->release();
2762 /* Routine io_connect_method_scalarI_scalarO */
2763 kern_return_t
is_io_connect_method_scalarI_scalarO(
2764 io_object_t connect
,
2766 io_scalar_inband_t input
,
2767 mach_msg_type_number_t inputCount
,
2768 io_scalar_inband_t output
,
2769 mach_msg_type_number_t
* outputCount
)
2773 io_scalar_inband64_t _input
;
2774 io_scalar_inband64_t _output
;
2776 mach_msg_type_number_t struct_outputCnt
= 0;
2777 mach_vm_size_t ool_output_size
= 0;
2779 for (i
= 0; i
< inputCount
; i
++)
2780 _input
[i
] = SCALAR64(input
[i
]);
2782 err
= is_io_connect_method(connect
, index
,
2786 _output
, outputCount
,
2787 NULL
, &struct_outputCnt
,
2788 0, &ool_output_size
);
2790 for (i
= 0; i
< *outputCount
; i
++)
2791 output
[i
] = SCALAR32(_output
[i
]);
2796 kern_return_t
shim_io_connect_method_scalarI_scalarO(
2797 IOExternalMethod
* method
,
2799 const io_user_scalar_t
* input
,
2800 mach_msg_type_number_t inputCount
,
2801 io_user_scalar_t
* output
,
2802 mach_msg_type_number_t
* outputCount
)
2805 io_scalar_inband_t _output
;
2807 err
= kIOReturnBadArgument
;
2811 if( inputCount
!= method
->count0
)
2813 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
2816 if( *outputCount
!= method
->count1
)
2818 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
2822 func
= method
->func
;
2824 switch( inputCount
) {
2827 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2828 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
2831 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2832 ARG32(input
[3]), ARG32(input
[4]),
2836 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2838 &_output
[0], &_output
[1] );
2841 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
2842 &_output
[0], &_output
[1], &_output
[2] );
2845 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
2846 &_output
[0], &_output
[1], &_output
[2],
2850 err
= (object
->*func
)( ARG32(input
[0]),
2851 &_output
[0], &_output
[1], &_output
[2],
2852 &_output
[3], &_output
[4] );
2855 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
2856 &_output
[3], &_output
[4], &_output
[5] );
2860 IOLog("%s: Bad method table\n", object
->getName());
2866 for (i
= 0; i
< *outputCount
; i
++)
2867 output
[i
] = SCALAR32(_output
[i
]);
2872 /* Routine io_async_method_scalarI_scalarO */
2873 kern_return_t
is_io_async_method_scalarI_scalarO(
2874 io_object_t connect
,
2875 mach_port_t wake_port
,
2876 io_async_ref_t reference
,
2877 mach_msg_type_number_t referenceCnt
,
2879 io_scalar_inband_t input
,
2880 mach_msg_type_number_t inputCount
,
2881 io_scalar_inband_t output
,
2882 mach_msg_type_number_t
* outputCount
)
2886 io_scalar_inband64_t _input
;
2887 io_scalar_inband64_t _output
;
2888 io_async_ref64_t _reference
;
2890 for (i
= 0; i
< referenceCnt
; i
++)
2891 _reference
[i
] = REF64(reference
[i
]);
2893 mach_msg_type_number_t struct_outputCnt
= 0;
2894 mach_vm_size_t ool_output_size
= 0;
2896 for (i
= 0; i
< inputCount
; i
++)
2897 _input
[i
] = SCALAR64(input
[i
]);
2899 err
= is_io_connect_async_method(connect
,
2900 wake_port
, _reference
, referenceCnt
,
2905 _output
, outputCount
,
2906 NULL
, &struct_outputCnt
,
2907 0, &ool_output_size
);
2909 for (i
= 0; i
< *outputCount
; i
++)
2910 output
[i
] = SCALAR32(_output
[i
]);
2914 /* Routine io_async_method_scalarI_structureO */
2915 kern_return_t
is_io_async_method_scalarI_structureO(
2916 io_object_t connect
,
2917 mach_port_t wake_port
,
2918 io_async_ref_t reference
,
2919 mach_msg_type_number_t referenceCnt
,
2921 io_scalar_inband_t input
,
2922 mach_msg_type_number_t inputCount
,
2923 io_struct_inband_t output
,
2924 mach_msg_type_number_t
* outputCount
)
2927 io_scalar_inband64_t _input
;
2928 io_async_ref64_t _reference
;
2930 for (i
= 0; i
< referenceCnt
; i
++)
2931 _reference
[i
] = REF64(reference
[i
]);
2933 mach_msg_type_number_t scalar_outputCnt
= 0;
2934 mach_vm_size_t ool_output_size
= 0;
2936 for (i
= 0; i
< inputCount
; i
++)
2937 _input
[i
] = SCALAR64(input
[i
]);
2939 return (is_io_connect_async_method(connect
,
2940 wake_port
, _reference
, referenceCnt
,
2945 NULL
, &scalar_outputCnt
,
2946 output
, outputCount
,
2947 0, &ool_output_size
));
2950 /* Routine io_async_method_scalarI_structureI */
2951 kern_return_t
is_io_async_method_scalarI_structureI(
2952 io_connect_t connect
,
2953 mach_port_t wake_port
,
2954 io_async_ref_t reference
,
2955 mach_msg_type_number_t referenceCnt
,
2957 io_scalar_inband_t input
,
2958 mach_msg_type_number_t inputCount
,
2959 io_struct_inband_t inputStruct
,
2960 mach_msg_type_number_t inputStructCount
)
2963 io_scalar_inband64_t _input
;
2964 io_async_ref64_t _reference
;
2966 for (i
= 0; i
< referenceCnt
; i
++)
2967 _reference
[i
] = REF64(reference
[i
]);
2969 mach_msg_type_number_t scalar_outputCnt
= 0;
2970 mach_msg_type_number_t inband_outputCnt
= 0;
2971 mach_vm_size_t ool_output_size
= 0;
2973 for (i
= 0; i
< inputCount
; i
++)
2974 _input
[i
] = SCALAR64(input
[i
]);
2976 return (is_io_connect_async_method(connect
,
2977 wake_port
, _reference
, referenceCnt
,
2980 inputStruct
, inputStructCount
,
2982 NULL
, &scalar_outputCnt
,
2983 NULL
, &inband_outputCnt
,
2984 0, &ool_output_size
));
2987 /* Routine io_async_method_structureI_structureO */
2988 kern_return_t
is_io_async_method_structureI_structureO(
2989 io_object_t connect
,
2990 mach_port_t wake_port
,
2991 io_async_ref_t reference
,
2992 mach_msg_type_number_t referenceCnt
,
2994 io_struct_inband_t input
,
2995 mach_msg_type_number_t inputCount
,
2996 io_struct_inband_t output
,
2997 mach_msg_type_number_t
* outputCount
)
3000 mach_msg_type_number_t scalar_outputCnt
= 0;
3001 mach_vm_size_t ool_output_size
= 0;
3002 io_async_ref64_t _reference
;
3004 for (i
= 0; i
< referenceCnt
; i
++)
3005 _reference
[i
] = REF64(reference
[i
]);
3007 return (is_io_connect_async_method(connect
,
3008 wake_port
, _reference
, referenceCnt
,
3013 NULL
, &scalar_outputCnt
,
3014 output
, outputCount
,
3015 0, &ool_output_size
));
3019 kern_return_t
shim_io_async_method_scalarI_scalarO(
3020 IOExternalAsyncMethod
* method
,
3022 mach_port_t asyncWakePort
,
3023 io_user_reference_t
* asyncReference
,
3024 uint32_t asyncReferenceCount
,
3025 const io_user_scalar_t
* input
,
3026 mach_msg_type_number_t inputCount
,
3027 io_user_scalar_t
* output
,
3028 mach_msg_type_number_t
* outputCount
)
3032 io_scalar_inband_t _output
;
3034 io_async_ref_t reference
;
3036 for (i
= 0; i
< asyncReferenceCount
; i
++)
3037 reference
[i
] = REF32(asyncReference
[i
]);
3039 err
= kIOReturnBadArgument
;
3043 if( inputCount
!= method
->count0
)
3045 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3048 if( *outputCount
!= method
->count1
)
3050 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3054 func
= method
->func
;
3056 switch( inputCount
) {
3059 err
= (object
->*func
)( reference
,
3060 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3061 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3064 err
= (object
->*func
)( reference
,
3065 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3066 ARG32(input
[3]), ARG32(input
[4]),
3070 err
= (object
->*func
)( reference
,
3071 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3073 &_output
[0], &_output
[1] );
3076 err
= (object
->*func
)( reference
,
3077 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3078 &_output
[0], &_output
[1], &_output
[2] );
3081 err
= (object
->*func
)( reference
,
3082 ARG32(input
[0]), ARG32(input
[1]),
3083 &_output
[0], &_output
[1], &_output
[2],
3087 err
= (object
->*func
)( reference
,
3089 &_output
[0], &_output
[1], &_output
[2],
3090 &_output
[3], &_output
[4] );
3093 err
= (object
->*func
)( reference
,
3094 &_output
[0], &_output
[1], &_output
[2],
3095 &_output
[3], &_output
[4], &_output
[5] );
3099 IOLog("%s: Bad method table\n", object
->getName());
3104 for (i
= 0; i
< *outputCount
; i
++)
3105 output
[i
] = SCALAR32(_output
[i
]);
3111 /* Routine io_connect_method_scalarI_structureO */
3112 kern_return_t
is_io_connect_method_scalarI_structureO(
3113 io_object_t connect
,
3115 io_scalar_inband_t input
,
3116 mach_msg_type_number_t inputCount
,
3117 io_struct_inband_t output
,
3118 mach_msg_type_number_t
* outputCount
)
3121 io_scalar_inband64_t _input
;
3123 mach_msg_type_number_t scalar_outputCnt
= 0;
3124 mach_vm_size_t ool_output_size
= 0;
3126 for (i
= 0; i
< inputCount
; i
++)
3127 _input
[i
] = SCALAR64(input
[i
]);
3129 return (is_io_connect_method(connect
, index
,
3133 NULL
, &scalar_outputCnt
,
3134 output
, outputCount
,
3135 0, &ool_output_size
));
3138 kern_return_t
shim_io_connect_method_scalarI_structureO(
3140 IOExternalMethod
* method
,
3142 const io_user_scalar_t
* input
,
3143 mach_msg_type_number_t inputCount
,
3144 io_struct_inband_t output
,
3145 mach_msg_type_number_t
* outputCount
)
3150 err
= kIOReturnBadArgument
;
3153 if( inputCount
!= method
->count0
)
3155 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3158 if( (kIOUCVariableStructureSize
!= method
->count1
)
3159 && (*outputCount
!= method
->count1
))
3161 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3165 func
= method
->func
;
3167 switch( inputCount
) {
3170 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3171 ARG32(input
[3]), ARG32(input
[4]),
3175 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3177 output
, (void *)outputCount
);
3180 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3181 output
, (void *)outputCount
, 0 );
3184 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3185 output
, (void *)outputCount
, 0, 0 );
3188 err
= (object
->*func
)( ARG32(input
[0]),
3189 output
, (void *)outputCount
, 0, 0, 0 );
3192 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
3196 IOLog("%s: Bad method table\n", object
->getName());
3205 kern_return_t
shim_io_async_method_scalarI_structureO(
3206 IOExternalAsyncMethod
* method
,
3208 mach_port_t asyncWakePort
,
3209 io_user_reference_t
* asyncReference
,
3210 uint32_t asyncReferenceCount
,
3211 const io_user_scalar_t
* input
,
3212 mach_msg_type_number_t inputCount
,
3213 io_struct_inband_t output
,
3214 mach_msg_type_number_t
* outputCount
)
3219 io_async_ref_t reference
;
3221 for (i
= 0; i
< asyncReferenceCount
; i
++)
3222 reference
[i
] = REF32(asyncReference
[i
]);
3224 err
= kIOReturnBadArgument
;
3226 if( inputCount
!= method
->count0
)
3228 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3231 if( (kIOUCVariableStructureSize
!= method
->count1
)
3232 && (*outputCount
!= method
->count1
))
3234 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3238 func
= method
->func
;
3240 switch( inputCount
) {
3243 err
= (object
->*func
)( reference
,
3244 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3245 ARG32(input
[3]), ARG32(input
[4]),
3249 err
= (object
->*func
)( reference
,
3250 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3252 output
, (void *)outputCount
);
3255 err
= (object
->*func
)( reference
,
3256 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3257 output
, (void *)outputCount
, 0 );
3260 err
= (object
->*func
)( reference
,
3261 ARG32(input
[0]), ARG32(input
[1]),
3262 output
, (void *)outputCount
, 0, 0 );
3265 err
= (object
->*func
)( reference
,
3267 output
, (void *)outputCount
, 0, 0, 0 );
3270 err
= (object
->*func
)( reference
,
3271 output
, (void *)outputCount
, 0, 0, 0, 0 );
3275 IOLog("%s: Bad method table\n", object
->getName());
3283 /* Routine io_connect_method_scalarI_structureI */
3284 kern_return_t
is_io_connect_method_scalarI_structureI(
3285 io_connect_t connect
,
3287 io_scalar_inband_t input
,
3288 mach_msg_type_number_t inputCount
,
3289 io_struct_inband_t inputStruct
,
3290 mach_msg_type_number_t inputStructCount
)
3293 io_scalar_inband64_t _input
;
3295 mach_msg_type_number_t scalar_outputCnt
= 0;
3296 mach_msg_type_number_t inband_outputCnt
= 0;
3297 mach_vm_size_t ool_output_size
= 0;
3299 for (i
= 0; i
< inputCount
; i
++)
3300 _input
[i
] = SCALAR64(input
[i
]);
3302 return (is_io_connect_method(connect
, index
,
3304 inputStruct
, inputStructCount
,
3306 NULL
, &scalar_outputCnt
,
3307 NULL
, &inband_outputCnt
,
3308 0, &ool_output_size
));
3311 kern_return_t
shim_io_connect_method_scalarI_structureI(
3312 IOExternalMethod
* method
,
3314 const io_user_scalar_t
* input
,
3315 mach_msg_type_number_t inputCount
,
3316 io_struct_inband_t inputStruct
,
3317 mach_msg_type_number_t inputStructCount
)
3320 IOReturn err
= kIOReturnBadArgument
;
3324 if( (kIOUCVariableStructureSize
!= method
->count0
)
3325 && (inputCount
!= method
->count0
))
3327 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3330 if( (kIOUCVariableStructureSize
!= method
->count1
)
3331 && (inputStructCount
!= method
->count1
))
3333 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3337 func
= method
->func
;
3339 switch( inputCount
) {
3342 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3343 ARG32(input
[3]), ARG32(input
[4]),
3347 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
3349 inputStruct
, (void *)inputStructCount
);
3352 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3353 inputStruct
, (void *)inputStructCount
,
3357 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3358 inputStruct
, (void *)inputStructCount
,
3362 err
= (object
->*func
)( ARG32(input
[0]),
3363 inputStruct
, (void *)inputStructCount
,
3367 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
3372 IOLog("%s: Bad method table\n", object
->getName());
3380 kern_return_t
shim_io_async_method_scalarI_structureI(
3381 IOExternalAsyncMethod
* method
,
3383 mach_port_t asyncWakePort
,
3384 io_user_reference_t
* asyncReference
,
3385 uint32_t asyncReferenceCount
,
3386 const io_user_scalar_t
* input
,
3387 mach_msg_type_number_t inputCount
,
3388 io_struct_inband_t inputStruct
,
3389 mach_msg_type_number_t inputStructCount
)
3393 IOReturn err
= kIOReturnBadArgument
;
3394 io_async_ref_t reference
;
3396 for (i
= 0; i
< asyncReferenceCount
; i
++)
3397 reference
[i
] = REF32(asyncReference
[i
]);
3401 if( (kIOUCVariableStructureSize
!= method
->count0
)
3402 && (inputCount
!= method
->count0
))
3404 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3407 if( (kIOUCVariableStructureSize
!= method
->count1
)
3408 && (inputStructCount
!= method
->count1
))
3410 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3414 func
= method
->func
;
3416 switch( inputCount
) {
3419 err
= (object
->*func
)( reference
,
3420 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3421 ARG32(input
[3]), ARG32(input
[4]),
3425 err
= (object
->*func
)( reference
,
3426 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3428 inputStruct
, (void *)inputStructCount
);
3431 err
= (object
->*func
)( reference
,
3432 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3433 inputStruct
, (void *)inputStructCount
,
3437 err
= (object
->*func
)( reference
,
3438 ARG32(input
[0]), ARG32(input
[1]),
3439 inputStruct
, (void *)inputStructCount
,
3443 err
= (object
->*func
)( reference
,
3445 inputStruct
, (void *)inputStructCount
,
3449 err
= (object
->*func
)( reference
,
3450 inputStruct
, (void *)inputStructCount
,
3455 IOLog("%s: Bad method table\n", object
->getName());
3463 /* Routine io_connect_method_structureI_structureO */
3464 kern_return_t
is_io_connect_method_structureI_structureO(
3465 io_object_t connect
,
3467 io_struct_inband_t input
,
3468 mach_msg_type_number_t inputCount
,
3469 io_struct_inband_t output
,
3470 mach_msg_type_number_t
* outputCount
)
3472 mach_msg_type_number_t scalar_outputCnt
= 0;
3473 mach_vm_size_t ool_output_size
= 0;
3475 return (is_io_connect_method(connect
, index
,
3479 NULL
, &scalar_outputCnt
,
3480 output
, outputCount
,
3481 0, &ool_output_size
));
3484 kern_return_t
shim_io_connect_method_structureI_structureO(
3485 IOExternalMethod
* method
,
3487 io_struct_inband_t input
,
3488 mach_msg_type_number_t inputCount
,
3489 io_struct_inband_t output
,
3490 mach_msg_type_number_t
* outputCount
)
3493 IOReturn err
= kIOReturnBadArgument
;
3497 if( (kIOUCVariableStructureSize
!= method
->count0
)
3498 && (inputCount
!= method
->count0
))
3500 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3503 if( (kIOUCVariableStructureSize
!= method
->count1
)
3504 && (*outputCount
!= method
->count1
))
3506 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3510 func
= method
->func
;
3512 if( method
->count1
) {
3513 if( method
->count0
) {
3514 err
= (object
->*func
)( input
, output
,
3515 (void *)inputCount
, outputCount
, 0, 0 );
3517 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
3520 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
3529 kern_return_t
shim_io_async_method_structureI_structureO(
3530 IOExternalAsyncMethod
* method
,
3532 mach_port_t asyncWakePort
,
3533 io_user_reference_t
* asyncReference
,
3534 uint32_t asyncReferenceCount
,
3535 io_struct_inband_t input
,
3536 mach_msg_type_number_t inputCount
,
3537 io_struct_inband_t output
,
3538 mach_msg_type_number_t
* outputCount
)
3543 io_async_ref_t reference
;
3545 for (i
= 0; i
< asyncReferenceCount
; i
++)
3546 reference
[i
] = REF32(asyncReference
[i
]);
3548 err
= kIOReturnBadArgument
;
3551 if( (kIOUCVariableStructureSize
!= method
->count0
)
3552 && (inputCount
!= method
->count0
))
3554 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3557 if( (kIOUCVariableStructureSize
!= method
->count1
)
3558 && (*outputCount
!= method
->count1
))
3560 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3564 func
= method
->func
;
3566 if( method
->count1
) {
3567 if( method
->count0
) {
3568 err
= (object
->*func
)( reference
,
3570 (void *)inputCount
, outputCount
, 0, 0 );
3572 err
= (object
->*func
)( reference
,
3573 output
, outputCount
, 0, 0, 0, 0 );
3576 err
= (object
->*func
)( reference
,
3577 input
, (void *)inputCount
, 0, 0, 0, 0 );
3585 /* Routine io_make_matching */
3586 kern_return_t
is_io_make_matching(
3587 mach_port_t master_port
,
3590 io_struct_inband_t input
,
3591 mach_msg_type_number_t inputCount
,
3592 io_string_t matching
)
3595 IOReturn err
= kIOReturnSuccess
;
3596 OSDictionary
* dict
;
3598 if( master_port
!= master_device_port
)
3599 return( kIOReturnNotPrivileged
);
3603 case kIOServiceMatching
:
3604 dict
= IOService::serviceMatching( gIOServiceKey
);
3607 case kIOBSDNameMatching
:
3608 dict
= IOBSDNameMatching( (const char *) input
);
3611 case kIOOFPathMatching
:
3612 dict
= IOOFPathMatching( (const char *) input
,
3613 matching
, sizeof( io_string_t
));
3621 return( kIOReturnUnsupported
);
3624 s
= OSSerialize::withCapacity(4096);
3626 err
= kIOReturnNoMemory
;
3630 if( !dict
->serialize( s
)) {
3631 err
= kIOReturnUnsupported
;
3635 if( s
->getLength() > sizeof( io_string_t
)) {
3636 err
= kIOReturnNoMemory
;
3639 strcpy( matching
, s
->text());
3651 /* Routine io_catalog_send_data */
3652 kern_return_t
is_io_catalog_send_data(
3653 mach_port_t master_port
,
3655 io_buf_ptr_t inData
,
3656 mach_msg_type_number_t inDataCount
,
3657 kern_return_t
* result
)
3661 kern_return_t kr
= kIOReturnError
;
3663 //printf("io_catalog_send_data called. flag: %d\n", flag);
3665 if( master_port
!= master_device_port
)
3666 return kIOReturnNotPrivileged
;
3668 // FIXME: This is a hack. Should have own function for removeKernelLinker()
3669 if( (flag
!= kIOCatalogRemoveKernelLinker
&& flag
!= kIOCatalogKextdFinishedLaunching
) && ( !inData
|| !inDataCount
) )
3670 return kIOReturnBadArgument
;
3673 vm_map_offset_t map_data
;
3675 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
3676 data
= CAST_DOWN(vm_offset_t
, map_data
);
3678 if( kr
!= KERN_SUCCESS
)
3681 // must return success after vm_map_copyout() succeeds
3684 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
3685 vm_deallocate( kernel_map
, data
, inDataCount
);
3687 *result
= kIOReturnNoMemory
;
3688 return( KERN_SUCCESS
);
3694 case kIOCatalogAddDrivers
:
3695 case kIOCatalogAddDriversNoMatch
: {
3698 array
= OSDynamicCast(OSArray
, obj
);
3700 if ( !gIOCatalogue
->addDrivers( array
,
3701 flag
== kIOCatalogAddDrivers
) ) {
3702 kr
= kIOReturnError
;
3706 kr
= kIOReturnBadArgument
;
3711 case kIOCatalogRemoveDrivers
:
3712 case kIOCatalogRemoveDriversNoMatch
: {
3713 OSDictionary
* dict
;
3715 dict
= OSDynamicCast(OSDictionary
, obj
);
3717 if ( !gIOCatalogue
->removeDrivers( dict
,
3718 flag
== kIOCatalogRemoveDrivers
) ) {
3719 kr
= kIOReturnError
;
3723 kr
= kIOReturnBadArgument
;
3728 case kIOCatalogStartMatching
: {
3729 OSDictionary
* dict
;
3731 dict
= OSDynamicCast(OSDictionary
, obj
);
3733 if ( !gIOCatalogue
->startMatching( dict
) ) {
3734 kr
= kIOReturnError
;
3738 kr
= kIOReturnBadArgument
;
3743 case kIOCatalogRemoveKernelLinker
: {
3744 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
3745 kr
= kIOReturnError
;
3747 kr
= kIOReturnSuccess
;
3752 case kIOCatalogKextdFinishedLaunching
: {
3754 static bool clearedBusy
= false;
3756 IOService
* serviceRoot
= IOService::getServiceRoot();
3758 serviceRoot
->adjustBusy(-1);
3763 kr
= kIOReturnSuccess
;
3768 kr
= kIOReturnBadArgument
;
3772 if (obj
) obj
->release();
3775 return( KERN_SUCCESS
);
3778 /* Routine io_catalog_terminate */
3779 kern_return_t
is_io_catalog_terminate(
3780 mach_port_t master_port
,
3786 if( master_port
!= master_device_port
)
3787 return kIOReturnNotPrivileged
;
3789 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3790 kIOClientPrivilegeAdministrator
);
3791 if( kIOReturnSuccess
!= kr
)
3795 case kIOCatalogServiceTerminate
:
3797 IOService
* service
;
3799 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
3800 kIORegistryIterateRecursively
);
3802 return kIOReturnNoMemory
;
3806 while( (service
= (IOService
*)iter
->getNextObject()) ) {
3807 if( service
->metaCast(name
)) {
3808 if ( !service
->terminate( kIOServiceRequired
3809 | kIOServiceSynchronous
) ) {
3810 kr
= kIOReturnUnsupported
;
3815 } while( !service
&& !iter
->isValid());
3819 case kIOCatalogModuleUnload
:
3820 case kIOCatalogModuleTerminate
:
3821 kr
= gIOCatalogue
->terminateDriversForModule(name
,
3822 flag
== kIOCatalogModuleUnload
);
3826 kr
= kIOReturnBadArgument
;
3833 /* Routine io_catalog_get_data */
3834 kern_return_t
is_io_catalog_get_data(
3835 mach_port_t master_port
,
3837 io_buf_ptr_t
*outData
,
3838 mach_msg_type_number_t
*outDataCount
)
3840 kern_return_t kr
= kIOReturnSuccess
;
3843 if( master_port
!= master_device_port
)
3844 return kIOReturnNotPrivileged
;
3846 //printf("io_catalog_get_data called. flag: %d\n", flag);
3848 s
= OSSerialize::withCapacity(4096);
3850 return kIOReturnNoMemory
;
3854 kr
= gIOCatalogue
->serializeData(flag
, s
);
3856 if ( kr
== kIOReturnSuccess
) {
3861 size
= s
->getLength();
3862 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
3863 if ( kr
== kIOReturnSuccess
) {
3864 bcopy(s
->text(), (void *)data
, size
);
3865 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
3866 (vm_map_size_t
)size
, true, ©
);
3867 *outData
= (char *)copy
;
3868 *outDataCount
= size
;
3877 /* Routine io_catalog_get_gen_count */
3878 kern_return_t
is_io_catalog_get_gen_count(
3879 mach_port_t master_port
,
3882 if( master_port
!= master_device_port
)
3883 return kIOReturnNotPrivileged
;
3885 //printf("io_catalog_get_gen_count called.\n");
3888 return kIOReturnBadArgument
;
3890 *genCount
= gIOCatalogue
->getGenerationCount();
3892 return kIOReturnSuccess
;
3895 /* Routine io_catalog_module_loaded */
3896 kern_return_t
is_io_catalog_module_loaded(
3897 mach_port_t master_port
,
3900 if( master_port
!= master_device_port
)
3901 return kIOReturnNotPrivileged
;
3903 //printf("io_catalog_module_loaded called. name %s\n", name);
3906 return kIOReturnBadArgument
;
3908 gIOCatalogue
->moduleHasLoaded(name
);
3910 return kIOReturnSuccess
;
3913 kern_return_t
is_io_catalog_reset(
3914 mach_port_t master_port
,
3917 if( master_port
!= master_device_port
)
3918 return kIOReturnNotPrivileged
;
3921 case kIOCatalogResetDefault
:
3922 gIOCatalogue
->reset();
3926 return kIOReturnBadArgument
;
3929 return kIOReturnSuccess
;
3932 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
3934 kern_return_t result
= kIOReturnBadArgument
;
3935 IOUserClient
*userClient
;
3937 if ((userClient
= OSDynamicCast(IOUserClient
,
3938 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
3939 IOExternalTrap
*trap
;
3940 IOService
*target
= NULL
;
3942 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
3944 if (trap
&& target
) {
3950 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
3954 userClient
->release();
3960 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
3961 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
3969 count
= dispatch
->checkScalarInputCount
;
3970 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
3972 return (kIOReturnBadArgument
);
3975 count
= dispatch
->checkStructureInputSize
;
3976 if ((kIOUCVariableStructureSize
!= count
)
3977 && (count
!= ((args
->structureInputDescriptor
)
3978 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
3980 return (kIOReturnBadArgument
);
3983 count
= dispatch
->checkScalarOutputCount
;
3984 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
3986 return (kIOReturnBadArgument
);
3989 count
= dispatch
->checkStructureOutputSize
;
3990 if ((kIOUCVariableStructureSize
!= count
)
3991 && (count
!= ((args
->structureOutputDescriptor
)
3992 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
3994 return (kIOReturnBadArgument
);
3997 if (dispatch
->function
)
3998 err
= (*dispatch
->function
)(target
, reference
, args
);
4000 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
4005 // pre-Leopard API's don't do ool structs
4006 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
4008 err
= kIOReturnIPCError
;
4012 if (args
->asyncWakePort
)
4014 IOExternalAsyncMethod
* method
;
4016 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) )
4017 return (kIOReturnUnsupported
);
4019 switch (method
->flags
& kIOUCTypeMask
)
4021 case kIOUCScalarIStructI
:
4022 err
= shim_io_async_method_scalarI_structureI( method
, object
,
4023 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4024 args
->scalarInput
, args
->scalarInputCount
,
4025 (char *)args
->structureInput
, args
->structureInputSize
);
4028 case kIOUCScalarIScalarO
:
4029 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
4030 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4031 args
->scalarInput
, args
->scalarInputCount
,
4032 args
->scalarOutput
, &args
->scalarOutputCount
);
4035 case kIOUCScalarIStructO
:
4036 err
= shim_io_async_method_scalarI_structureO( method
, object
,
4037 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4038 args
->scalarInput
, args
->scalarInputCount
,
4039 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4043 case kIOUCStructIStructO
:
4044 err
= shim_io_async_method_structureI_structureO( method
, object
,
4045 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
4046 (char *)args
->structureInput
, args
->structureInputSize
,
4047 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4051 err
= kIOReturnBadArgument
;
4057 IOExternalMethod
* method
;
4059 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) )
4060 return (kIOReturnUnsupported
);
4062 switch (method
->flags
& kIOUCTypeMask
)
4064 case kIOUCScalarIStructI
:
4065 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
4066 args
->scalarInput
, args
->scalarInputCount
,
4067 (char *)args
->structureInput
, args
->structureInputSize
);
4070 case kIOUCScalarIScalarO
:
4071 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
4072 args
->scalarInput
, args
->scalarInputCount
,
4073 args
->scalarOutput
, &args
->scalarOutputCount
);
4076 case kIOUCScalarIStructO
:
4077 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
4078 args
->scalarInput
, args
->scalarInputCount
,
4079 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4083 case kIOUCStructIStructO
:
4084 err
= shim_io_connect_method_structureI_structureO( method
, object
,
4085 (char *)args
->structureInput
, args
->structureInputSize
,
4086 (char *) args
->structureOutput
, &args
->structureOutputSize
);
4090 err
= kIOReturnBadArgument
;
4100 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
4101 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
4102 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
4103 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
4104 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
4105 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
4106 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
4107 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
4108 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
4109 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
4110 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
4111 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
4112 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
4113 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
4114 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
4115 OSMetaClassDefineReservedUnused(IOUserClient
, 15);