2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
30 * 14 Aug 98 sdouglas created.
31 * 08 Dec 98 sdouglas cpp.
34 #include <IOKit/IOKitServer.h>
35 #include <IOKit/IOUserClient.h>
36 #include <IOKit/IOService.h>
37 #include <IOKit/IORegistryEntry.h>
38 #include <IOKit/IOCatalogue.h>
39 #include <IOKit/IOMemoryDescriptor.h>
40 #include <IOKit/IOLib.h>
42 #include <IOKit/assert.h>
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46 // definitions we should get from osfmk
48 //typedef struct ipc_port * ipc_port_t;
49 typedef natural_t ipc_kobject_type_t
;
51 #define IKOT_IOKIT_SPARE 27
52 #define IKOT_IOKIT_CONNECT 29
53 #define IKOT_IOKIT_OBJECT 30
57 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
58 ipc_kobject_type_t type
);
60 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
62 extern mach_port_name_t
iokit_make_send_right( task_t task
,
63 io_object_t obj
, ipc_kobject_type_t type
);
65 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
67 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
69 extern ipc_port_t master_device_port
;
71 extern void iokit_retain_port( ipc_port_t port
);
72 extern void iokit_release_port( ipc_port_t port
);
74 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
76 #include <vm/vm_map.h>
81 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
83 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
85 class IOMachPort
: public OSObject
87 OSDeclareDefaultStructors(IOMachPort
)
93 static IOMachPort
* portForObject( OSObject
* obj
,
94 ipc_kobject_type_t type
);
95 static bool noMoreSendersForObject( OSObject
* obj
,
96 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
97 static void releasePortForObject( OSObject
* obj
,
98 ipc_kobject_type_t type
);
99 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
101 static mach_port_name_t
makeSendRightForTask( task_t task
,
102 io_object_t obj
, ipc_kobject_type_t type
);
107 #define super OSObject
108 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
110 static IOLock
* gIOObjectPortLock
;
112 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
114 // not in dictForType() for debugging ease
115 static OSDictionary
* gIOObjectPorts
;
116 static OSDictionary
* gIOConnectPorts
;
118 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
120 OSDictionary
** dict
;
122 if( IKOT_IOKIT_OBJECT
== type
)
123 dict
= &gIOObjectPorts
;
124 else if( IKOT_IOKIT_CONNECT
== type
)
125 dict
= &gIOConnectPorts
;
130 *dict
= OSDictionary::withCapacity( 1 );
135 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
136 ipc_kobject_type_t type
)
138 IOMachPort
* inst
= 0;
141 IOTakeLock( gIOObjectPortLock
);
145 dict
= dictForType( type
);
149 if( (inst
= (IOMachPort
*)
150 dict
->getObject( (const OSSymbol
*) obj
))) {
156 inst
= new IOMachPort
;
157 if( inst
&& !inst
->init()) {
162 inst
->port
= iokit_alloc_object_port( obj
, type
);
165 dict
->setObject( (const OSSymbol
*) obj
, inst
);
175 IOUnlock( gIOObjectPortLock
);
180 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
181 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
184 IOMachPort
* machPort
;
185 bool destroyed
= true;
187 IOTakeLock( gIOObjectPortLock
);
189 if( (dict
= dictForType( type
))) {
192 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
194 destroyed
= (machPort
->mscount
== *mscount
);
196 dict
->removeObject( (const OSSymbol
*) obj
);
198 *mscount
= machPort
->mscount
;
203 IOUnlock( gIOObjectPortLock
);
208 void IOMachPort::releasePortForObject( OSObject
* obj
,
209 ipc_kobject_type_t type
)
213 IOTakeLock( gIOObjectPortLock
);
215 if( (dict
= dictForType( type
))) {
217 dict
->removeObject( (const OSSymbol
*) obj
);
221 IOUnlock( gIOObjectPortLock
);
224 void IOUserClient::destroyUserReferences( OSObject
* obj
)
226 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
229 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
233 IOTakeLock( gIOObjectPortLock
);
236 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
239 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
243 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
245 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
246 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
248 uc
->mappings
->release();
251 dict
->removeObject( (const OSSymbol
*) obj
);
255 IOUnlock( gIOObjectPortLock
);
259 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
260 io_object_t obj
, ipc_kobject_type_t type
)
262 return( iokit_make_send_right( task
, obj
, type
));
265 void IOMachPort::free( void )
268 iokit_destroy_object_port( port
);
272 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
276 // functions called from osfmk/device/iokit_rpc.c
279 iokit_add_reference( io_object_t obj
)
286 iokit_remove_reference( io_object_t obj
)
293 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
295 IOMachPort
* machPort
;
298 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
300 port
= machPort
->port
;
302 iokit_retain_port( port
);
313 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
314 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
316 IOUserClient
* client
;
319 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
320 return( kIOReturnNotReady
);
322 if( (IKOT_IOKIT_CONNECT
== type
)
323 && (client
= OSDynamicCast( IOUserClient
, obj
)))
324 client
->clientDied();
325 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
328 return( kIOReturnSuccess
);
333 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
335 class IOUserNotification
: public OSIterator
337 OSDeclareDefaultStructors(IOUserNotification
)
340 mach_msg_header_t msgHdr
;
341 OSNotificationHeader notifyHeader
;
346 IONotifier
* holdNotify
;
351 virtual bool init( mach_port_t port
, natural_t type
,
352 OSAsyncReference reference
,
353 vm_size_t messageSize
);
356 virtual void setNotification( IONotifier
* obj
);
358 virtual void reset();
359 virtual bool isValid();
362 class IOServiceUserNotification
: public IOUserNotification
364 OSDeclareDefaultStructors(IOServiceUserNotification
)
366 enum { kMaxOutstanding
= 256 };
369 OSObject
* lastEntry
;
374 virtual bool init( mach_port_t port
, natural_t type
,
375 OSAsyncReference reference
);
378 static bool _handler( void * target
,
379 void * ref
, IOService
* newService
);
380 virtual bool handler( void * ref
, IOService
* newService
);
382 virtual OSObject
* getNextObject();
385 class IOServiceMessageUserNotification
: public IOUserNotification
387 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
391 virtual bool init( mach_port_t port
, natural_t type
,
392 OSAsyncReference reference
, vm_size_t extraSize
);
395 static IOReturn
_handler( void * target
, void * ref
,
396 UInt32 messageType
, IOService
* provider
,
397 void * messageArgument
, vm_size_t argSize
);
398 virtual IOReturn
handler( void * ref
,
399 UInt32 messageType
, IOService
* provider
,
400 void * messageArgument
, vm_size_t argSize
);
402 virtual OSObject
* getNextObject();
405 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
408 #define super OSIterator
409 OSDefineMetaClass( IOUserNotification
, OSIterator
)
410 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
412 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
414 bool IOUserNotification::init( mach_port_t port
, natural_t type
,
415 OSAsyncReference reference
, vm_size_t extraSize
)
420 lock
= IOLockAlloc();
424 msgSize
= sizeof( PingMsg
) + extraSize
;
425 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
429 bzero( pingMsg
, msgSize
);
431 pingMsg
->msgHdr
.msgh_remote_port
= port
;
432 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
433 MACH_MSG_TYPE_COPY_SEND
,
434 MACH_MSG_TYPE_MAKE_SEND
);
435 pingMsg
->msgHdr
.msgh_size
= msgSize
;
436 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
438 pingMsg
->notifyHeader
.size
= extraSize
;
439 pingMsg
->notifyHeader
.type
= type
;
440 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
445 void IOUserNotification::free( void )
448 holdNotify
->remove();
449 // can't be in handler now
452 IOFree( pingMsg
, msgSize
);
461 void IOUserNotification::setNotification( IONotifier
* notify
)
464 holdNotify
->remove();
469 void IOUserNotification::reset()
474 bool IOUserNotification::isValid()
479 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
482 #define super IOUserNotification
483 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
485 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
487 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
488 OSAsyncReference reference
)
490 newSet
= OSArray::withCapacity( 1 );
494 return( super::init( port
, type
, reference
, 0) );
497 void IOServiceUserNotification::free( void )
500 lastEntry
->release();
508 bool IOServiceUserNotification::_handler( void * target
,
509 void * ref
, IOService
* newService
)
511 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
514 bool IOServiceUserNotification::handler( void * /* ref */,
515 IOService
* newService
)
519 ipc_port_t port
= NULL
;
520 bool sendPing
= false;
524 count
= newSet
->getCount();
525 if( count
< kMaxOutstanding
) {
527 newSet
->setObject( newService
);
528 if( (sendPing
= (armed
&& (0 == count
))))
535 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
536 pingMsg
->msgHdr
.msgh_local_port
= port
;
538 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
540 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
541 pingMsg
->msgHdr
.msgh_size
);
543 iokit_release_port( port
);
545 if( KERN_SUCCESS
!= kr
)
546 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
552 OSObject
* IOServiceUserNotification::getNextObject()
560 lastEntry
->release();
562 count
= newSet
->getCount();
564 result
= newSet
->getObject( count
- 1 );
566 newSet
->removeObject( count
- 1);
578 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
580 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
582 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
584 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
585 OSAsyncReference reference
, vm_size_t extraSize
)
587 return( super::init( port
, type
, reference
,
588 sizeof(IOServiceInterestContent
) + extraSize
) );
591 void IOServiceMessageUserNotification::free( void )
596 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
597 UInt32 messageType
, IOService
* provider
,
598 void * argument
, vm_size_t argSize
)
600 return( ((IOServiceMessageUserNotification
*) target
)->handler(
601 ref
, messageType
, provider
, argument
, argSize
));
604 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
605 UInt32 messageType
, IOService
* provider
,
606 void * messageArgument
, vm_size_t argSize
)
610 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
611 pingMsg
->notifyHeader
.content
;
613 data
->messageType
= messageType
;
615 argSize
= sizeof( messageArgument
);
616 data
->messageArgument
[0] = messageArgument
;
618 if( argSize
> kIOUserNotifyMaxMessageSize
)
619 argSize
= kIOUserNotifyMaxMessageSize
;
620 bcopy( messageArgument
, data
->messageArgument
, argSize
);
622 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
623 + sizeof( IOServiceInterestContent
)
624 - sizeof( data
->messageArgument
)
627 if( (port
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
) ))
628 pingMsg
->msgHdr
.msgh_local_port
= port
;
630 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
632 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
633 pingMsg
->msgHdr
.msgh_size
);
636 iokit_release_port( port
);
638 if( KERN_SUCCESS
!= kr
)
639 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
641 return( kIOReturnSuccess
);
644 OSObject
* IOServiceMessageUserNotification::getNextObject()
649 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
652 #define super IOService
653 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
655 void IOUserClient::initialize( void )
657 gIOObjectPortLock
= IOLockAlloc();
659 assert( gIOObjectPortLock
);
662 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
663 mach_port_t wakePort
,
664 void *callback
, void *refcon
)
666 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
667 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
668 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
671 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
672 const char * privilegeName
)
675 security_token_t token
;
676 mach_msg_type_number_t count
;
678 if( 0 != strcmp( privilegeName
, kIOClientPrivilegeAdministrator
))
679 return( kIOReturnUnsupported
);
681 count
= TASK_SECURITY_TOKEN_COUNT
;
682 kr
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
,
683 (task_info_t
) &token
, &count
);
684 if( (kr
== kIOReturnSuccess
)
685 && (0 != token
.val
[0]))
686 kr
= kIOReturnNotPrivileged
;
691 bool IOUserClient::initWithTask(task_t owningTask
,
695 if( getPropertyTable())
698 return super::init();
701 bool IOUserClient::initWithTask(task_t owningTask
,
704 OSDictionary
* properties
)
708 ok
= super::init( properties
);
709 ok
&= initWithTask( owningTask
, securityID
, type
);
714 void IOUserClient::free()
722 IOReturn
IOUserClient::clientDied( void )
724 return( clientClose());
727 IOReturn
IOUserClient::clientClose( void )
729 return( kIOReturnUnsupported
);
732 IOService
* IOUserClient::getService( void )
737 IOReturn
IOUserClient::registerNotificationPort(
738 mach_port_t
/* port */,
742 return( kIOReturnUnsupported
);
745 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
746 semaphore_t
* semaphore
)
748 return( kIOReturnUnsupported
);
751 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
753 return( kIOReturnUnsupported
);
756 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
757 IOOptionBits
* options
,
758 IOMemoryDescriptor
** memory
)
760 return( kIOReturnUnsupported
);
763 IOMemoryMap
* IOUserClient::mapClientMemory(
766 IOOptionBits mapFlags
,
767 IOVirtualAddress atAddress
)
770 IOOptionBits options
= 0;
771 IOMemoryDescriptor
* memory
;
772 IOMemoryMap
* map
= 0;
774 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
776 if( memory
&& (kIOReturnSuccess
== err
)) {
778 options
= (options
& ~kIOMapUserOptionsMask
)
779 | (mapFlags
& kIOMapUserOptionsMask
);
780 map
= memory
->map( task
, atAddress
, options
);
787 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
788 OSObject
*obj
, io_object_t
*clientObj
)
790 mach_port_name_t name
;
792 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
795 *(mach_port_name_t
*)clientObj
= name
;
796 return kIOReturnSuccess
;
799 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
804 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
809 IOExternalMethod
* IOUserClient::
810 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
812 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
815 *targetP
= (IOService
*) method
->object
;
820 IOExternalAsyncMethod
* IOUserClient::
821 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
823 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
826 *targetP
= (IOService
*) method
->object
;
831 IOExternalTrap
* IOUserClient::
832 getExternalTrapForIndex(UInt32 index
)
837 IOExternalTrap
* IOUserClient::
838 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
840 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
843 *targetP
= trap
->object
;
849 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
850 IOReturn result
, void *args
[], UInt32 numArgs
)
853 mach_msg_header_t msgHdr
;
854 OSNotificationHeader notifyHdr
;
855 IOAsyncCompletionContent asyncContent
;
856 void * args
[kMaxAsyncArgs
];
859 mach_port_t replyPort
;
862 // If no reply port, do nothing.
863 replyPort
= (mach_port_t
) reference
[0];
864 if(replyPort
== MACH_PORT_NULL
)
865 return kIOReturnSuccess
;
867 if(numArgs
> kMaxAsyncArgs
)
868 return kIOReturnMessageTooLarge
;
869 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
,0);
870 replyMsg
.msgHdr
.msgh_size
=
871 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
872 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
873 replyMsg
.msgHdr
.msgh_local_port
= 0;
874 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
876 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
877 + numArgs
*sizeof(void *);
878 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
879 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
881 replyMsg
.asyncContent
.result
= result
;
883 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
884 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
885 replyMsg
.msgHdr
.msgh_size
);
886 if( KERN_SUCCESS
!= kr
)
887 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
891 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
895 #define CHECK(cls,obj,out) \
897 if( !(out = OSDynamicCast( cls, obj))) \
898 return( kIOReturnBadArgument )
900 /* Routine io_object_get_class */
901 kern_return_t
is_io_object_get_class(
903 io_name_t className
)
906 return( kIOReturnBadArgument
);
908 strcpy( className
, object
->getMetaClass()->getClassName());
909 return( kIOReturnSuccess
);
912 /* Routine io_object_conforms_to */
913 kern_return_t
is_io_object_conforms_to(
916 boolean_t
*conforms
)
919 return( kIOReturnBadArgument
);
921 *conforms
= (0 != object
->metaCast( className
));
922 return( kIOReturnSuccess
);
925 /* Routine io_object_get_retain_count */
926 kern_return_t
is_io_object_get_retain_count(
931 return( kIOReturnBadArgument
);
933 *retainCount
= object
->getRetainCount();
934 return( kIOReturnSuccess
);
937 /* Routine io_iterator_next */
938 kern_return_t
is_io_iterator_next(
939 io_object_t iterator
,
940 io_object_t
*object
)
944 CHECK( OSIterator
, iterator
, iter
);
946 obj
= iter
->getNextObject();
950 return( kIOReturnSuccess
);
952 return( kIOReturnNoDevice
);
955 /* Routine io_iterator_reset */
956 kern_return_t
is_io_iterator_reset(
957 io_object_t iterator
)
959 CHECK( OSIterator
, iterator
, iter
);
963 return( kIOReturnSuccess
);
966 /* Routine io_iterator_is_valid */
967 kern_return_t
is_io_iterator_is_valid(
968 io_object_t iterator
,
969 boolean_t
*is_valid
)
971 CHECK( OSIterator
, iterator
, iter
);
973 *is_valid
= iter
->isValid();
975 return( kIOReturnSuccess
);
978 /* Routine io_service_match_property_table */
979 kern_return_t
is_io_service_match_property_table(
980 io_service_t _service
,
981 io_string_t matching
,
984 CHECK( IOService
, _service
, service
);
990 obj
= OSUnserializeXML( matching
);
992 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
993 *matches
= service
->passiveMatch( dict
);
994 kr
= kIOReturnSuccess
;
996 kr
= kIOReturnBadArgument
;
1004 /* Routine io_service_get_matching_services */
1005 kern_return_t
is_io_service_get_matching_services(
1006 mach_port_t master_port
,
1007 io_string_t matching
,
1008 io_iterator_t
*existing
)
1012 OSDictionary
* dict
;
1014 if( master_port
!= master_device_port
)
1015 return( kIOReturnNotPrivileged
);
1017 obj
= OSUnserializeXML( matching
);
1019 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1020 *existing
= IOService::getMatchingServices( dict
);
1021 kr
= kIOReturnSuccess
;
1023 kr
= kIOReturnBadArgument
;
1031 /* Routine io_service_add_notification */
1032 kern_return_t
is_io_service_add_notification(
1033 mach_port_t master_port
,
1034 io_name_t notification_type
,
1035 io_string_t matching
,
1037 io_async_ref_t reference
,
1038 mach_msg_type_number_t referenceCnt
,
1039 io_object_t
* notification
)
1042 IOServiceUserNotification
* userNotify
= 0;
1043 IONotifier
* notify
= 0;
1044 const OSSymbol
* sym
;
1045 OSDictionary
* dict
;
1047 unsigned long int userMsgType
;
1050 if( master_port
!= master_device_port
)
1051 return( kIOReturnNotPrivileged
);
1054 err
= kIOReturnNoResources
;
1056 if( !(sym
= OSSymbol::withCString( notification_type
)))
1057 err
= kIOReturnNoResources
;
1059 if( !(dict
= OSDynamicCast( OSDictionary
,
1060 OSUnserializeXML( matching
)))) {
1061 err
= kIOReturnBadArgument
;
1065 if( (sym
== gIOPublishNotification
)
1066 || (sym
== gIOFirstPublishNotification
))
1067 userMsgType
= kIOServicePublishNotificationType
;
1068 else if( (sym
== gIOMatchedNotification
)
1069 || (sym
== gIOFirstMatchNotification
))
1070 userMsgType
= kIOServiceMatchedNotificationType
;
1071 else if( sym
== gIOTerminatedNotification
)
1072 userMsgType
= kIOServiceTerminatedNotificationType
;
1074 userMsgType
= kLastIOKitNotificationType
;
1076 userNotify
= new IOServiceUserNotification
;
1078 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1080 userNotify
->release();
1086 notify
= IOService::addNotification( sym
, dict
,
1087 &userNotify
->_handler
, userNotify
);
1090 *notification
= userNotify
;
1091 userNotify
->setNotification( notify
);
1092 err
= kIOReturnSuccess
;
1094 err
= kIOReturnUnsupported
;
1106 /* Routine io_service_add_notification_old */
1107 kern_return_t
is_io_service_add_notification_old(
1108 mach_port_t master_port
,
1109 io_name_t notification_type
,
1110 io_string_t matching
,
1113 io_object_t
* notification
)
1115 return( is_io_service_add_notification( master_port
, notification_type
,
1116 matching
, port
, &ref
, 1, notification
));
1119 /* Routine io_service_add_message_notification */
1120 kern_return_t
is_io_service_add_interest_notification(
1121 io_object_t _service
,
1122 io_name_t type_of_interest
,
1124 io_async_ref_t reference
,
1125 mach_msg_type_number_t referenceCnt
,
1126 io_object_t
* notification
)
1129 IOServiceMessageUserNotification
* userNotify
= 0;
1130 IONotifier
* notify
= 0;
1131 const OSSymbol
* sym
;
1134 CHECK( IOService
, _service
, service
);
1136 err
= kIOReturnNoResources
;
1137 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1139 userNotify
= new IOServiceMessageUserNotification
;
1141 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1142 reference
, kIOUserNotifyMaxMessageSize
)) {
1143 userNotify
->release();
1149 notify
= service
->registerInterest( sym
,
1150 &userNotify
->_handler
, userNotify
);
1152 *notification
= userNotify
;
1153 userNotify
->setNotification( notify
);
1154 err
= kIOReturnSuccess
;
1156 err
= kIOReturnUnsupported
;
1163 /* Routine io_service_acknowledge_notification */
1164 kern_return_t
is_io_service_acknowledge_notification(
1165 io_object_t _service
,
1166 natural_t notify_ref
,
1167 natural_t response
)
1169 CHECK( IOService
, _service
, service
);
1171 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1172 (IOOptionBits
) response
));
1176 /* Routine io_connect_get_semaphore */
1177 kern_return_t
is_io_connect_get_notification_semaphore(
1178 io_connect_t connection
,
1179 natural_t notification_type
,
1180 semaphore_t
*semaphore
)
1182 CHECK( IOUserClient
, connection
, client
);
1184 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1188 /* Routine io_registry_get_root_entry */
1189 kern_return_t
is_io_registry_get_root_entry(
1190 mach_port_t master_port
,
1193 IORegistryEntry
* entry
;
1195 if( master_port
!= master_device_port
)
1196 return( kIOReturnNotPrivileged
);
1198 entry
= IORegistryEntry::getRegistryRoot();
1203 return( kIOReturnSuccess
);
1206 /* Routine io_registry_create_iterator */
1207 kern_return_t
is_io_registry_create_iterator(
1208 mach_port_t master_port
,
1211 io_object_t
*iterator
)
1213 if( master_port
!= master_device_port
)
1214 return( kIOReturnNotPrivileged
);
1216 *iterator
= IORegistryIterator::iterateOver(
1217 IORegistryEntry::getPlane( plane
), options
);
1219 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1222 /* Routine io_registry_entry_create_iterator */
1223 kern_return_t
is_io_registry_entry_create_iterator(
1224 io_object_t registry_entry
,
1227 io_object_t
*iterator
)
1229 CHECK( IORegistryEntry
, registry_entry
, entry
);
1231 *iterator
= IORegistryIterator::iterateOver( entry
,
1232 IORegistryEntry::getPlane( plane
), options
);
1234 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1237 /* Routine io_registry_iterator_enter */
1238 kern_return_t
is_io_registry_iterator_enter_entry(
1239 io_object_t iterator
)
1241 CHECK( IORegistryIterator
, iterator
, iter
);
1245 return( kIOReturnSuccess
);
1248 /* Routine io_registry_iterator_exit */
1249 kern_return_t
is_io_registry_iterator_exit_entry(
1250 io_object_t iterator
)
1254 CHECK( IORegistryIterator
, iterator
, iter
);
1256 didIt
= iter
->exitEntry();
1258 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1261 /* Routine io_registry_entry_from_path */
1262 kern_return_t
is_io_registry_entry_from_path(
1263 mach_port_t master_port
,
1265 io_object_t
*registry_entry
)
1267 IORegistryEntry
* entry
;
1269 if( master_port
!= master_device_port
)
1270 return( kIOReturnNotPrivileged
);
1272 entry
= IORegistryEntry::fromPath( path
);
1274 *registry_entry
= entry
;
1276 return( kIOReturnSuccess
);
1279 /* Routine io_registry_entry_in_plane */
1280 kern_return_t
is_io_registry_entry_in_plane(
1281 io_object_t registry_entry
,
1283 boolean_t
*inPlane
)
1285 CHECK( IORegistryEntry
, registry_entry
, entry
);
1287 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1289 return( kIOReturnSuccess
);
1293 /* Routine io_registry_entry_get_path */
1294 kern_return_t
is_io_registry_entry_get_path(
1295 io_object_t registry_entry
,
1300 CHECK( IORegistryEntry
, registry_entry
, entry
);
1302 length
= sizeof( io_string_t
);
1303 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1304 return( kIOReturnSuccess
);
1306 return( kIOReturnBadArgument
);
1310 /* Routine io_registry_entry_get_name */
1311 kern_return_t
is_io_registry_entry_get_name(
1312 io_object_t registry_entry
,
1315 CHECK( IORegistryEntry
, registry_entry
, entry
);
1317 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1319 return( kIOReturnSuccess
);
1322 /* Routine io_registry_entry_get_name_in_plane */
1323 kern_return_t
is_io_registry_entry_get_name_in_plane(
1324 io_object_t registry_entry
,
1325 io_name_t planeName
,
1328 const IORegistryPlane
* plane
;
1329 CHECK( IORegistryEntry
, registry_entry
, entry
);
1332 plane
= IORegistryEntry::getPlane( planeName
);
1336 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1338 return( kIOReturnSuccess
);
1341 /* Routine io_registry_entry_get_location_in_plane */
1342 kern_return_t
is_io_registry_entry_get_location_in_plane(
1343 io_object_t registry_entry
,
1344 io_name_t planeName
,
1345 io_name_t location
)
1347 const IORegistryPlane
* plane
;
1348 CHECK( IORegistryEntry
, registry_entry
, entry
);
1351 plane
= IORegistryEntry::getPlane( planeName
);
1355 const char * cstr
= entry
->getLocation( plane
);
1358 strncpy( location
, cstr
, sizeof( io_name_t
));
1359 return( kIOReturnSuccess
);
1361 return( kIOReturnNotFound
);
1364 // Create a vm_map_copy_t or kalloc'ed data for memory
1365 // to be copied out. ipc will free after the copyout.
1367 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1368 io_buf_ptr_t
* buf
)
1373 err
= vm_map_copyin( kernel_map
, (vm_offset_t
) data
, len
,
1374 false /* src_destroy */, ©
);
1376 assert( err
== KERN_SUCCESS
);
1377 if( err
== KERN_SUCCESS
)
1378 *buf
= (char *) copy
;
1383 /* Routine io_registry_entry_get_property */
1384 kern_return_t
is_io_registry_entry_get_property_bytes(
1385 io_object_t registry_entry
,
1386 io_name_t property_name
,
1387 io_scalar_inband_t buf
,
1388 mach_msg_type_number_t
*dataCnt
)
1396 unsigned int len
= 0;
1397 const void * bytes
= 0;
1398 IOReturn ret
= kIOReturnSuccess
;
1400 CHECK( IORegistryEntry
, registry_entry
, entry
);
1402 obj
= entry
->copyProperty(property_name
);
1404 return( kIOReturnNoResources
);
1406 // One day OSData will be a common container base class
1408 if( (data
= OSDynamicCast( OSData
, obj
))) {
1409 len
= data
->getLength();
1410 bytes
= data
->getBytesNoCopy();
1412 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1413 len
= str
->getLength() + 1;
1414 bytes
= str
->getCStringNoCopy();
1416 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1417 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1418 bytes
= boo
->isTrue() ? "Yes" : "No";
1420 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1421 offsetBytes
= off
->unsigned64BitValue();
1422 len
= off
->numberOfBytes();
1423 bytes
= &offsetBytes
;
1425 bytes
= (const void *)
1426 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1430 ret
= kIOReturnBadArgument
;
1434 ret
= kIOReturnIPCError
;
1437 bcopy( bytes
, buf
, len
);
1445 /* Routine io_registry_entry_get_property */
1446 kern_return_t
is_io_registry_entry_get_property(
1447 io_object_t registry_entry
,
1448 io_name_t property_name
,
1449 io_buf_ptr_t
*properties
,
1450 mach_msg_type_number_t
*propertiesCnt
)
1456 CHECK( IORegistryEntry
, registry_entry
, entry
);
1458 obj
= entry
->copyProperty(property_name
);
1460 return( kIOReturnNotFound
);
1462 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1465 return( kIOReturnNoMemory
);
1469 if( obj
->serialize( s
)) {
1470 len
= s
->getLength();
1471 *propertiesCnt
= len
;
1472 err
= copyoutkdata( s
->text(), len
, properties
);
1475 err
= kIOReturnUnsupported
;
1483 /* Routine io_registry_entry_get_property_recursively */
1484 kern_return_t
is_io_registry_entry_get_property_recursively(
1485 io_object_t registry_entry
,
1487 io_name_t property_name
,
1489 io_buf_ptr_t
*properties
,
1490 mach_msg_type_number_t
*propertiesCnt
)
1496 CHECK( IORegistryEntry
, registry_entry
, entry
);
1498 obj
= entry
->copyProperty( property_name
,
1499 IORegistryEntry::getPlane( plane
), options
);
1501 return( kIOReturnNotFound
);
1503 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1506 return( kIOReturnNoMemory
);
1511 if( obj
->serialize( s
)) {
1512 len
= s
->getLength();
1513 *propertiesCnt
= len
;
1514 err
= copyoutkdata( s
->text(), len
, properties
);
1517 err
= kIOReturnUnsupported
;
1525 /* Routine io_registry_entry_get_properties */
1526 kern_return_t
is_io_registry_entry_get_properties(
1527 io_object_t registry_entry
,
1528 io_buf_ptr_t
*properties
,
1529 mach_msg_type_number_t
*propertiesCnt
)
1534 CHECK( IORegistryEntry
, registry_entry
, entry
);
1536 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1538 return( kIOReturnNoMemory
);
1542 if( entry
->serializeProperties( s
)) {
1543 len
= s
->getLength();
1544 *propertiesCnt
= len
;
1545 err
= copyoutkdata( s
->text(), len
, properties
);
1548 err
= kIOReturnUnsupported
;
1555 /* Routine io_registry_entry_set_properties */
1556 kern_return_t is_io_registry_entry_set_properties
1558 io_object_t registry_entry
,
1559 io_buf_ptr_t properties
,
1560 mach_msg_type_number_t propertiesCnt
,
1568 CHECK( IORegistryEntry
, registry_entry
, entry
);
1570 err
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
) properties
);
1572 if( KERN_SUCCESS
== err
) {
1574 // must return success after vm_map_copyout() succeeds
1575 obj
= OSUnserializeXML( (const char *) data
);
1576 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1579 res
= entry
->setProperties( obj
);
1582 res
= kIOReturnBadArgument
;
1590 /* Routine io_registry_entry_get_child_iterator */
1591 kern_return_t
is_io_registry_entry_get_child_iterator(
1592 io_object_t registry_entry
,
1594 io_object_t
*iterator
)
1596 CHECK( IORegistryEntry
, registry_entry
, entry
);
1598 *iterator
= entry
->getChildIterator(
1599 IORegistryEntry::getPlane( plane
));
1601 return( kIOReturnSuccess
);
1604 /* Routine io_registry_entry_get_parent_iterator */
1605 kern_return_t
is_io_registry_entry_get_parent_iterator(
1606 io_object_t registry_entry
,
1608 io_object_t
*iterator
)
1610 CHECK( IORegistryEntry
, registry_entry
, entry
);
1612 *iterator
= entry
->getParentIterator(
1613 IORegistryEntry::getPlane( plane
));
1615 return( kIOReturnSuccess
);
1618 /* Routine io_service_get_busy_state */
1619 kern_return_t
is_io_service_get_busy_state(
1620 io_object_t _service
,
1623 CHECK( IOService
, _service
, service
);
1625 *busyState
= service
->getBusyState();
1627 return( kIOReturnSuccess
);
1630 /* Routine io_service_wait_quiet */
1631 kern_return_t
is_io_service_wait_quiet(
1632 io_object_t _service
,
1633 mach_timespec_t wait_time
)
1635 CHECK( IOService
, _service
, service
);
1637 return( service
->waitQuiet( &wait_time
));
1640 /* Routine io_service_request_probe */
1641 kern_return_t
is_io_service_request_probe(
1642 io_object_t _service
,
1645 CHECK( IOService
, _service
, service
);
1647 return( service
->requestProbe( options
));
1651 /* Routine io_service_open */
1652 kern_return_t
is_io_service_open(
1653 io_object_t _service
,
1656 io_object_t
*connection
)
1658 IOUserClient
* client
;
1661 CHECK( IOService
, _service
, service
);
1663 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1664 connect_type
, &client
);
1666 if( err
== kIOReturnSuccess
) {
1667 assert( OSDynamicCast(IOUserClient
, client
) );
1668 *connection
= client
;
1674 /* Routine io_service_close */
1675 kern_return_t
is_io_service_close(
1676 io_object_t connection
)
1679 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
1680 return( kIOReturnSuccess
);
1682 CHECK( IOUserClient
, connection
, client
);
1684 client
->clientClose();
1686 return( kIOReturnSuccess
);
1689 /* Routine io_connect_get_service */
1690 kern_return_t
is_io_connect_get_service(
1691 io_object_t connection
,
1692 io_object_t
*service
)
1694 IOService
* theService
;
1696 CHECK( IOUserClient
, connection
, client
);
1698 theService
= client
->getService();
1700 theService
->retain();
1702 *service
= theService
;
1704 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
1707 /* Routine io_connect_set_notification_port */
1708 kern_return_t
is_io_connect_set_notification_port(
1709 io_object_t connection
,
1710 int notification_type
,
1714 CHECK( IOUserClient
, connection
, client
);
1716 return( client
->registerNotificationPort( port
, notification_type
,
1720 kern_return_t
is_io_connect_map_memory(
1721 io_object_t connect
,
1724 vm_address_t
* mapAddr
,
1725 vm_size_t
* mapSize
,
1731 CHECK( IOUserClient
, connect
, client
);
1733 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
1736 *mapAddr
= map
->getVirtualAddress();
1738 *mapSize
= map
->getLength();
1740 if( task
!= current_task()) {
1741 // push a name out to the task owning the map,
1742 // so we can clean up maps
1743 mach_port_name_t name
= IOMachPort::makeSendRightForTask(
1744 task
, map
, IKOT_IOKIT_OBJECT
);
1748 // keep it with the user client
1749 IOLockLock( gIOObjectPortLock
);
1750 if( 0 == client
->mappings
)
1751 client
->mappings
= OSSet::withCapacity(2);
1752 if( client
->mappings
)
1753 client
->mappings
->setObject( map
);
1754 IOLockUnlock( gIOObjectPortLock
);
1757 err
= kIOReturnSuccess
;
1760 err
= kIOReturnBadArgument
;
1765 kern_return_t
is_io_connect_unmap_memory(
1766 io_object_t connect
,
1769 vm_address_t mapAddr
)
1772 IOOptionBits options
= 0;
1773 IOMemoryDescriptor
* memory
;
1776 CHECK( IOUserClient
, connect
, client
);
1778 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1780 if( memory
&& (kIOReturnSuccess
== err
)) {
1782 options
= (options
& ~kIOMapUserOptionsMask
)
1783 | kIOMapAnywhere
| kIOMapReference
;
1785 map
= memory
->map( task
, mapAddr
, options
);
1788 IOLockLock( gIOObjectPortLock
);
1789 if( client
->mappings
)
1790 client
->mappings
->removeObject( map
);
1791 IOLockUnlock( gIOObjectPortLock
);
1792 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
1795 err
= kIOReturnBadArgument
;
1802 /* Routine io_connect_add_client */
1803 kern_return_t
is_io_connect_add_client(
1804 io_object_t connection
,
1805 io_object_t connect_to
)
1807 CHECK( IOUserClient
, connection
, client
);
1808 CHECK( IOUserClient
, connect_to
, to
);
1810 return( client
->connectClient( to
) );
1814 /* Routine io_connect_set_properties */
1815 kern_return_t
is_io_connect_set_properties(
1816 io_object_t connection
,
1817 io_buf_ptr_t properties
,
1818 mach_msg_type_number_t propertiesCnt
,
1821 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
1825 /* Routine io_connect_method_scalarI_scalarO */
1826 kern_return_t
is_io_connect_method_scalarI_scalarO(
1827 io_object_t connect
,
1830 IOByteCount inputCount
,
1832 IOByteCount
* outputCount
)
1835 IOExternalMethod
* method
;
1839 CHECK( IOUserClient
, connect
, client
);
1840 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
1842 err
= kIOReturnBadArgument
;
1843 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
1845 if( inputCount
!= method
->count0
)
1847 if( *outputCount
!= method
->count1
)
1850 func
= method
->func
;
1852 switch( inputCount
) {
1855 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1856 input
[3], input
[4], input
[5] );
1859 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1864 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1866 &output
[0], &output
[1] );
1869 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1870 &output
[0], &output
[1], &output
[2] );
1873 err
= (object
->*func
)( input
[0], input
[1],
1874 &output
[0], &output
[1], &output
[2],
1878 err
= (object
->*func
)( input
[0],
1879 &output
[0], &output
[1], &output
[2],
1880 &output
[3], &output
[4] );
1883 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
1884 &output
[3], &output
[4], &output
[5] );
1888 IOLog("%s: Bad method table\n", client
->getName());
1893 err
= kIOReturnUnsupported
;
1898 /* Routine io_connect_method_scalarI_structureO */
1899 kern_return_t
is_io_connect_method_scalarI_structureO(
1900 io_object_t connect
,
1903 IOByteCount inputCount
,
1905 IOByteCount
* outputCount
)
1908 IOExternalMethod
* method
;
1912 CHECK( IOUserClient
, connect
, client
);
1914 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1916 err
= kIOReturnBadArgument
;
1917 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
1919 if( inputCount
!= method
->count0
)
1921 if( (0xffffffff != method
->count1
)
1922 && (*outputCount
!= method
->count1
))
1925 func
= method
->func
;
1927 switch( inputCount
) {
1930 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1935 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1937 output
, (void *)outputCount
);
1940 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1941 output
, (void *)outputCount
, 0 );
1944 err
= (object
->*func
)( input
[0], input
[1],
1945 output
, (void *)outputCount
, 0, 0 );
1948 err
= (object
->*func
)( input
[0],
1949 output
, (void *)outputCount
, 0, 0, 0 );
1952 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
1956 IOLog("%s: Bad method table\n", client
->getName());
1961 err
= kIOReturnUnsupported
;
1966 /* Routine io_connect_method_scalarI_structureI */
1967 kern_return_t
is_io_connect_method_scalarI_structureI(
1968 io_connect_t connect
,
1971 IOByteCount inputCount
,
1972 UInt8
* inputStruct
,
1973 IOByteCount inputStructCount
)
1976 IOExternalMethod
* method
;
1980 CHECK( IOUserClient
, connect
, client
);
1982 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1984 err
= kIOReturnBadArgument
;
1985 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
1987 if( (0xffffffff != method
->count0
)
1988 && (inputCount
!= method
->count0
))
1990 if( (0xffffffff != method
->count1
)
1991 && (inputStructCount
!= method
->count1
))
1994 func
= method
->func
;
1996 switch( inputCount
) {
1999 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2004 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2006 inputStruct
, (void *)inputStructCount
);
2009 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2010 inputStruct
, (void *)inputStructCount
,
2014 err
= (object
->*func
)( input
[0], input
[1],
2015 inputStruct
, (void *)inputStructCount
,
2019 err
= (object
->*func
)( input
[0],
2020 inputStruct
, (void *)inputStructCount
,
2024 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
2029 IOLog("%s: Bad method table\n", client
->getName());
2034 err
= kIOReturnUnsupported
;
2039 /* Routine io_connect_method_structureI_structureO */
2040 kern_return_t
is_io_connect_method_structureI_structureO(
2041 io_object_t connect
,
2044 IOByteCount inputCount
,
2046 IOByteCount
* outputCount
)
2049 IOExternalMethod
* method
;
2053 CHECK( IOUserClient
, connect
, client
);
2055 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2057 err
= kIOReturnBadArgument
;
2058 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2060 if( (0xffffffff != method
->count0
)
2061 && (inputCount
!= method
->count0
))
2063 if( (0xffffffff != method
->count1
)
2064 && (*outputCount
!= method
->count1
))
2067 func
= method
->func
;
2069 if( method
->count1
) {
2070 if( method
->count0
) {
2071 err
= (object
->*func
)( input
, output
,
2072 (void *)inputCount
, outputCount
, 0, 0 );
2074 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2077 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2083 err
= kIOReturnUnsupported
;
2088 kern_return_t
is_io_async_method_scalarI_scalarO(
2089 io_object_t connect
,
2090 mach_port_t wakePort
,
2091 io_async_ref_t reference
,
2092 mach_msg_type_number_t referenceCnt
,
2095 IOByteCount inputCount
,
2097 IOByteCount
* outputCount
)
2100 IOExternalAsyncMethod
*method
;
2104 CHECK( IOUserClient
, connect
, client
);
2105 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2107 err
= kIOReturnBadArgument
;
2108 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2110 if( inputCount
!= method
->count0
)
2112 if( *outputCount
!= method
->count1
)
2115 reference
[0] = (natural_t
) wakePort
;
2116 func
= method
->func
;
2118 switch( inputCount
) {
2121 err
= (object
->*func
)( reference
,
2122 input
[0], input
[1], input
[2],
2123 input
[3], input
[4], input
[5] );
2126 err
= (object
->*func
)( reference
,
2127 input
[0], input
[1], input
[2],
2132 err
= (object
->*func
)( reference
,
2133 input
[0], input
[1], input
[2],
2135 &output
[0], &output
[1] );
2138 err
= (object
->*func
)( reference
,
2139 input
[0], input
[1], input
[2],
2140 &output
[0], &output
[1], &output
[2] );
2143 err
= (object
->*func
)( reference
,
2145 &output
[0], &output
[1], &output
[2],
2149 err
= (object
->*func
)( reference
,
2151 &output
[0], &output
[1], &output
[2],
2152 &output
[3], &output
[4] );
2155 err
= (object
->*func
)( reference
,
2156 &output
[0], &output
[1], &output
[2],
2157 &output
[3], &output
[4], &output
[5] );
2161 IOLog("%s: Bad method table\n", client
->getName());
2166 err
= kIOReturnUnsupported
;
2171 kern_return_t
is_io_async_method_scalarI_structureO(
2172 io_object_t connect
,
2173 mach_port_t wakePort
,
2174 io_async_ref_t reference
,
2175 mach_msg_type_number_t referenceCnt
,
2178 IOByteCount inputCount
,
2180 IOByteCount
* outputCount
)
2183 IOExternalAsyncMethod
*method
;
2187 CHECK( IOUserClient
, connect
, client
);
2189 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2191 err
= kIOReturnBadArgument
;
2192 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2194 if( inputCount
!= method
->count0
)
2196 if( (0xffffffff != method
->count1
)
2197 && (*outputCount
!= method
->count1
))
2200 reference
[0] = (natural_t
) wakePort
;
2201 func
= method
->func
;
2203 switch( inputCount
) {
2206 err
= (object
->*func
)( reference
,
2207 input
[0], input
[1], input
[2],
2212 err
= (object
->*func
)( reference
,
2213 input
[0], input
[1], input
[2],
2215 output
, (void *)outputCount
);
2218 err
= (object
->*func
)( reference
,
2219 input
[0], input
[1], input
[2],
2220 output
, (void *)outputCount
, 0 );
2223 err
= (object
->*func
)( reference
,
2225 output
, (void *)outputCount
, 0, 0 );
2228 err
= (object
->*func
)( reference
,
2230 output
, (void *)outputCount
, 0, 0, 0 );
2233 err
= (object
->*func
)( reference
,
2234 output
, (void *)outputCount
, 0, 0, 0, 0 );
2238 IOLog("%s: Bad method table\n", client
->getName());
2243 err
= kIOReturnUnsupported
;
2248 kern_return_t
is_io_async_method_scalarI_structureI(
2249 io_connect_t connect
,
2250 mach_port_t wakePort
,
2251 io_async_ref_t reference
,
2252 mach_msg_type_number_t referenceCnt
,
2255 IOByteCount inputCount
,
2256 UInt8
* inputStruct
,
2257 IOByteCount inputStructCount
)
2260 IOExternalAsyncMethod
*method
;
2264 CHECK( IOUserClient
, connect
, client
);
2266 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2268 err
= kIOReturnBadArgument
;
2269 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2271 if( (0xffffffff != method
->count0
)
2272 && (inputCount
!= method
->count0
))
2274 if( (0xffffffff != method
->count1
)
2275 && (inputStructCount
!= method
->count1
))
2278 reference
[0] = (natural_t
) wakePort
;
2279 func
= method
->func
;
2281 switch( inputCount
) {
2284 err
= (object
->*func
)( reference
,
2285 input
[0], input
[1], input
[2],
2290 err
= (object
->*func
)( reference
,
2291 input
[0], input
[1], input
[2],
2293 inputStruct
, (void *)inputStructCount
);
2296 err
= (object
->*func
)( reference
,
2297 input
[0], input
[1], input
[2],
2298 inputStruct
, (void *)inputStructCount
,
2302 err
= (object
->*func
)( reference
,
2304 inputStruct
, (void *)inputStructCount
,
2308 err
= (object
->*func
)( reference
,
2310 inputStruct
, (void *)inputStructCount
,
2314 err
= (object
->*func
)( reference
,
2315 inputStruct
, (void *)inputStructCount
,
2320 IOLog("%s: Bad method table\n", client
->getName());
2325 err
= kIOReturnUnsupported
;
2330 kern_return_t
is_io_async_method_structureI_structureO(
2331 io_object_t connect
,
2332 mach_port_t wakePort
,
2333 io_async_ref_t reference
,
2334 mach_msg_type_number_t referenceCnt
,
2337 IOByteCount inputCount
,
2339 IOByteCount
* outputCount
)
2342 IOExternalAsyncMethod
*method
;
2346 CHECK( IOUserClient
, connect
, client
);
2348 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2350 err
= kIOReturnBadArgument
;
2351 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2353 if( (0xffffffff != method
->count0
)
2354 && (inputCount
!= method
->count0
))
2356 if( (0xffffffff != method
->count1
)
2357 && (*outputCount
!= method
->count1
))
2360 reference
[0] = (natural_t
) wakePort
;
2361 func
= method
->func
;
2363 if( method
->count1
) {
2364 if( method
->count0
) {
2365 err
= (object
->*func
)( reference
,
2367 (void *)inputCount
, outputCount
, 0, 0 );
2369 err
= (object
->*func
)( reference
,
2370 output
, outputCount
, 0, 0, 0, 0 );
2373 err
= (object
->*func
)( reference
,
2374 input
, (void *)inputCount
, 0, 0, 0, 0 );
2380 err
= kIOReturnUnsupported
;
2384 /* Routine io_make_matching */
2385 kern_return_t
is_io_make_matching(
2386 mach_port_t master_port
,
2388 IOOptionBits options
,
2390 IOByteCount inputCount
,
2391 io_string_t matching
)
2394 IOReturn err
= kIOReturnSuccess
;
2395 OSDictionary
* dict
;
2397 if( master_port
!= master_device_port
)
2398 return( kIOReturnNotPrivileged
);
2402 case kIOServiceMatching
:
2403 dict
= IOService::serviceMatching( gIOServiceKey
);
2406 case kIOBSDNameMatching
:
2407 dict
= IOBSDNameMatching( (const char *) input
);
2410 case kIOOFPathMatching
:
2411 dict
= IOOFPathMatching( (const char *) input
,
2412 matching
, sizeof( io_string_t
));
2420 return( kIOReturnUnsupported
);
2423 s
= OSSerialize::withCapacity(4096);
2425 err
= kIOReturnNoMemory
;
2429 if( !dict
->serialize( s
)) {
2430 err
= kIOReturnUnsupported
;
2434 if( s
->getLength() > sizeof( io_string_t
)) {
2435 err
= kIOReturnNoMemory
;
2438 strcpy( matching
, s
->text());
2450 /* Routine io_catalog_send_data */
2451 kern_return_t
is_io_catalog_send_data(
2452 mach_port_t master_port
,
2454 io_buf_ptr_t inData
,
2455 mach_msg_type_number_t inDataCount
,
2460 kern_return_t kr
= kIOReturnError
;
2462 //printf("io_catalog_send_data called. flag: %d\n", flag);
2464 if( master_port
!= master_device_port
)
2465 return kIOReturnNotPrivileged
;
2467 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2468 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2469 return kIOReturnBadArgument
;
2472 kr
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
)inData
);
2473 if( kr
!= KERN_SUCCESS
)
2476 // must return success after vm_map_copyout() succeeds
2479 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2480 vm_deallocate( kernel_map
, data
, inDataCount
);
2482 *result
= kIOReturnNoMemory
;
2483 return( KERN_SUCCESS
);
2489 case kIOCatalogAddDrivers
:
2490 case kIOCatalogAddDriversNoMatch
: {
2493 array
= OSDynamicCast(OSArray
, obj
);
2495 if ( !gIOCatalogue
->addDrivers( array
,
2496 flag
== kIOCatalogAddDrivers
) ) {
2497 kr
= kIOReturnError
;
2501 kr
= kIOReturnBadArgument
;
2506 case kIOCatalogRemoveDrivers
:
2507 case kIOCatalogRemoveDriversNoMatch
: {
2508 OSDictionary
* dict
;
2510 dict
= OSDynamicCast(OSDictionary
, obj
);
2512 if ( !gIOCatalogue
->removeDrivers( dict
,
2513 flag
== kIOCatalogRemoveDrivers
) ) {
2514 kr
= kIOReturnError
;
2518 kr
= kIOReturnBadArgument
;
2523 case kIOCatalogStartMatching
: {
2524 OSDictionary
* dict
;
2526 dict
= OSDynamicCast(OSDictionary
, obj
);
2528 if ( !gIOCatalogue
->startMatching( dict
) ) {
2529 kr
= kIOReturnError
;
2533 kr
= kIOReturnBadArgument
;
2538 case kIOCatalogRemoveKernelLinker
: {
2539 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
2540 kr
= kIOReturnError
;
2542 kr
= kIOReturnSuccess
;
2548 kr
= kIOReturnBadArgument
;
2552 if (obj
) obj
->release();
2555 return( KERN_SUCCESS
);
2558 /* Routine io_catalog_terminate */
2559 kern_return_t
is_io_catalog_terminate(
2560 mach_port_t master_port
,
2566 if( master_port
!= master_device_port
)
2567 return kIOReturnNotPrivileged
;
2569 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
2570 kIOClientPrivilegeAdministrator
);
2571 if( kIOReturnSuccess
!= kr
)
2575 case kIOCatalogServiceTerminate
:
2577 IOService
* service
;
2579 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
2580 kIORegistryIterateRecursively
);
2582 return kIOReturnNoMemory
;
2586 while( (service
= (IOService
*)iter
->getNextObject()) ) {
2587 if( service
->metaCast(name
)) {
2588 if ( !service
->terminate( kIOServiceRequired
2589 | kIOServiceSynchronous
) ) {
2590 kr
= kIOReturnUnsupported
;
2595 } while( !service
&& !iter
->isValid());
2599 case kIOCatalogModuleUnload
:
2600 case kIOCatalogModuleTerminate
:
2601 kr
= gIOCatalogue
->terminateDriversForModule(name
,
2602 flag
== kIOCatalogModuleUnload
);
2606 kr
= kIOReturnBadArgument
;
2613 /* Routine io_catalog_get_data */
2614 kern_return_t
is_io_catalog_get_data(
2615 mach_port_t master_port
,
2617 io_buf_ptr_t
*outData
,
2618 mach_msg_type_number_t
*outDataCount
)
2620 kern_return_t kr
= kIOReturnSuccess
;
2623 if( master_port
!= master_device_port
)
2624 return kIOReturnNotPrivileged
;
2626 //printf("io_catalog_get_data called. flag: %d\n", flag);
2628 s
= OSSerialize::withCapacity(4096);
2630 return kIOReturnNoMemory
;
2634 case kIOCatalogGetContents
:
2635 if ( !gIOCatalogue
->serialize(s
) ) {
2636 kr
= kIOReturnNoMemory
;
2641 kr
= kIOReturnBadArgument
;
2645 if ( kr
== kIOReturnSuccess
) {
2650 size
= s
->getLength();
2651 kr
= vm_allocate(kernel_map
, &data
, size
, true);
2652 if ( kr
== kIOReturnSuccess
) {
2653 bcopy(s
->text(), (void *)data
, size
);
2654 kr
= vm_map_copyin(kernel_map
, data
, size
, true, ©
);
2655 *outData
= (char *)copy
;
2656 *outDataCount
= size
;
2665 /* Routine io_catalog_get_gen_count */
2666 kern_return_t
is_io_catalog_get_gen_count(
2667 mach_port_t master_port
,
2670 if( master_port
!= master_device_port
)
2671 return kIOReturnNotPrivileged
;
2673 //printf("io_catalog_get_gen_count called.\n");
2676 return kIOReturnBadArgument
;
2678 *genCount
= gIOCatalogue
->getGenerationCount();
2680 return kIOReturnSuccess
;
2683 /* Routine io_catalog_module_loaded */
2684 kern_return_t
is_io_catalog_module_loaded(
2685 mach_port_t master_port
,
2688 if( master_port
!= master_device_port
)
2689 return kIOReturnNotPrivileged
;
2691 //printf("io_catalog_module_loaded called. name %s\n", name);
2694 return kIOReturnBadArgument
;
2696 gIOCatalogue
->moduleHasLoaded(name
);
2698 return kIOReturnSuccess
;
2701 kern_return_t
is_io_catalog_reset(
2702 mach_port_t master_port
,
2705 if( master_port
!= master_device_port
)
2706 return kIOReturnNotPrivileged
;
2709 case kIOCatalogResetDefault
:
2710 gIOCatalogue
->reset();
2714 return kIOReturnBadArgument
;
2717 return kIOReturnSuccess
;
2720 kern_return_t
iokit_user_client_trap(io_object_t userClientRef
, UInt32 index
,
2721 void *p1
, void *p2
, void *p3
,
2722 void *p4
, void *p5
, void *p6
)
2724 kern_return_t result
= kIOReturnBadArgument
;
2725 IOUserClient
*userClient
;
2727 if ((userClient
= OSDynamicCast(IOUserClient
,
2728 iokit_lookup_connect_ref_current_task(userClientRef
)))) {
2729 IOExternalTrap
*trap
;
2730 IOService
*target
= NULL
;
2732 trap
= userClient
->getTargetAndTrapForIndex(&target
, index
);
2734 if (trap
&& target
) {
2740 result
= (target
->*func
)(p1
, p2
, p3
, p4
, p5
, p6
);
2744 userClient
->release();
2752 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
2753 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
2754 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
2755 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
2756 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
2757 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
2758 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
2759 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
2760 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
2761 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
2762 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
2763 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
2764 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
2765 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
2766 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
2767 OSMetaClassDefineReservedUnused(IOUserClient
, 15);