2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
27 * 14 Aug 98 sdouglas created.
28 * 08 Dec 98 sdouglas cpp.
31 #include <IOKit/IOKitServer.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>
39 #include <IOKit/assert.h>
41 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 // definitions we should get from osfmk
45 //typedef struct ipc_port * ipc_port_t;
46 typedef natural_t ipc_kobject_type_t
;
48 #define IKOT_IOKIT_SPARE 27
49 #define IKOT_IOKIT_CONNECT 29
50 #define IKOT_IOKIT_OBJECT 30
54 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
55 ipc_kobject_type_t type
);
57 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
59 extern mach_port_name_t
iokit_make_send_right( task_t task
,
60 io_object_t obj
, ipc_kobject_type_t type
);
62 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
64 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
66 extern ipc_port_t master_device_port
;
68 extern void iokit_retain_port( ipc_port_t port
);
69 extern void iokit_release_port( ipc_port_t port
);
71 #include <vm/vm_map.h>
76 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
78 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
80 class IOMachPort
: public OSObject
82 OSDeclareDefaultStructors(IOMachPort
)
88 static IOMachPort
* portForObject( OSObject
* obj
,
89 ipc_kobject_type_t type
);
90 static bool noMoreSendersForObject( OSObject
* obj
,
91 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
92 static void releasePortForObject( OSObject
* obj
,
93 ipc_kobject_type_t type
);
94 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
96 static mach_port_name_t
makeSendRightForTask( task_t task
,
97 io_object_t obj
, ipc_kobject_type_t type
);
102 #define super OSObject
103 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
105 static IOLock
* gIOObjectPortLock
;
107 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
109 // not in dictForType() for debugging ease
110 static OSDictionary
* gIOObjectPorts
;
111 static OSDictionary
* gIOConnectPorts
;
113 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
115 OSDictionary
** dict
;
117 if( IKOT_IOKIT_OBJECT
== type
)
118 dict
= &gIOObjectPorts
;
119 else if( IKOT_IOKIT_CONNECT
== type
)
120 dict
= &gIOConnectPorts
;
125 *dict
= OSDictionary::withCapacity( 1 );
130 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
131 ipc_kobject_type_t type
)
133 IOMachPort
* inst
= 0;
136 IOTakeLock( gIOObjectPortLock
);
140 dict
= dictForType( type
);
144 if( (inst
= (IOMachPort
*)
145 dict
->getObject( (const OSSymbol
*) obj
))) {
151 inst
= new IOMachPort
;
152 if( inst
&& !inst
->init()) {
157 inst
->port
= iokit_alloc_object_port( obj
, type
);
160 dict
->setObject( (const OSSymbol
*) obj
, inst
);
170 IOUnlock( gIOObjectPortLock
);
175 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
176 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
179 IOMachPort
* machPort
;
180 bool destroyed
= true;
182 IOTakeLock( gIOObjectPortLock
);
184 if( (dict
= dictForType( type
))) {
187 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
189 destroyed
= (machPort
->mscount
== *mscount
);
191 dict
->removeObject( (const OSSymbol
*) obj
);
193 *mscount
= machPort
->mscount
;
198 IOUnlock( gIOObjectPortLock
);
203 void IOMachPort::releasePortForObject( OSObject
* obj
,
204 ipc_kobject_type_t type
)
208 IOTakeLock( gIOObjectPortLock
);
210 if( (dict
= dictForType( type
))) {
212 dict
->removeObject( (const OSSymbol
*) obj
);
216 IOUnlock( gIOObjectPortLock
);
219 void IOUserClient::destroyUserReferences( OSObject
* obj
)
221 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
222 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_CONNECT
);
225 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
226 io_object_t obj
, ipc_kobject_type_t type
)
228 return( iokit_make_send_right( task
, obj
, type
));
231 void IOMachPort::free( void )
234 iokit_destroy_object_port( port
);
238 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
242 // functions called from osfmk/device/iokit_rpc.c
245 iokit_add_reference( io_object_t obj
)
252 iokit_remove_reference( io_object_t obj
)
259 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
261 IOMachPort
* machPort
;
264 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
266 port
= machPort
->port
;
268 iokit_retain_port( port
);
279 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
280 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
282 IOUserClient
* client
;
285 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
286 return( kIOReturnNotReady
);
288 if( (IKOT_IOKIT_CONNECT
== type
)
289 && (client
= OSDynamicCast( IOUserClient
, obj
)))
290 client
->clientDied();
291 else if( (IKOT_IOKIT_OBJECT
== type
)
292 && (map
= OSDynamicCast( IOMemoryMap
, obj
)))
295 return( kIOReturnSuccess
);
300 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
302 class IOUserNotification
: public OSIterator
304 OSDeclareDefaultStructors(IOUserNotification
)
307 mach_msg_header_t msgHdr
;
308 OSNotificationHeader notifyHeader
;
313 IONotifier
* holdNotify
;
318 virtual bool init( mach_port_t port
, natural_t type
,
319 OSAsyncReference reference
,
320 vm_size_t messageSize
);
323 virtual void setNotification( IONotifier
* obj
);
325 virtual void reset();
326 virtual bool isValid();
329 class IOServiceUserNotification
: public IOUserNotification
331 OSDeclareDefaultStructors(IOServiceUserNotification
)
333 enum { kMaxOutstanding
= 256 };
336 OSObject
* lastEntry
;
341 virtual bool init( mach_port_t port
, natural_t type
,
342 OSAsyncReference reference
);
345 static bool _handler( void * target
,
346 void * ref
, IOService
* newService
);
347 virtual bool handler( void * ref
, IOService
* newService
);
349 virtual OSObject
* getNextObject();
352 class IOServiceMessageUserNotification
: public IOUserNotification
354 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
358 virtual bool init( mach_port_t port
, natural_t type
,
359 OSAsyncReference reference
, vm_size_t extraSize
);
362 static IOReturn
_handler( void * target
, void * ref
,
363 UInt32 messageType
, IOService
* provider
,
364 void * messageArgument
, vm_size_t argSize
);
365 virtual IOReturn
handler( void * ref
,
366 UInt32 messageType
, IOService
* provider
,
367 void * messageArgument
, vm_size_t argSize
);
369 virtual OSObject
* getNextObject();
372 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
375 #define super OSIterator
376 OSDefineMetaClass( IOUserNotification
, OSIterator
)
377 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
379 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
381 bool IOUserNotification::init( mach_port_t port
, natural_t type
,
382 OSAsyncReference reference
, vm_size_t extraSize
)
387 lock
= IOLockAlloc();
391 msgSize
= sizeof( PingMsg
) + extraSize
;
392 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
396 bzero( pingMsg
, msgSize
);
398 pingMsg
->msgHdr
.msgh_remote_port
= port
;
399 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
400 MACH_MSG_TYPE_COPY_SEND
,
401 MACH_MSG_TYPE_MAKE_SEND
);
402 pingMsg
->msgHdr
.msgh_size
= msgSize
;
403 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
405 pingMsg
->notifyHeader
.size
= extraSize
;
406 pingMsg
->notifyHeader
.type
= type
;
407 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
412 void IOUserNotification::free( void )
415 holdNotify
->remove();
416 // can't be in handler now
419 IOFree( pingMsg
, msgSize
);
428 void IOUserNotification::setNotification( IONotifier
* notify
)
431 holdNotify
->remove();
436 void IOUserNotification::reset()
441 bool IOUserNotification::isValid()
446 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
449 #define super IOUserNotification
450 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
452 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
454 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
455 OSAsyncReference reference
)
457 newSet
= OSArray::withCapacity( 1 );
461 return( super::init( port
, type
, reference
, 0) );
464 void IOServiceUserNotification::free( void )
467 lastEntry
->release();
475 bool IOServiceUserNotification::_handler( void * target
,
476 void * ref
, IOService
* newService
)
478 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
481 bool IOServiceUserNotification::handler( void * /* ref */,
482 IOService
* newService
)
486 ipc_port_t port
= NULL
;
487 bool sendPing
= false;
491 count
= newSet
->getCount();
492 if( count
< kMaxOutstanding
) {
494 newSet
->setObject( newService
);
495 if( (sendPing
= (armed
&& (0 == count
))))
502 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
503 pingMsg
->msgHdr
.msgh_local_port
= port
;
505 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
507 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
508 pingMsg
->msgHdr
.msgh_size
);
510 iokit_release_port( port
);
512 if( KERN_SUCCESS
!= kr
)
513 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
519 OSObject
* IOServiceUserNotification::getNextObject()
527 lastEntry
->release();
529 count
= newSet
->getCount();
531 result
= newSet
->getObject( count
- 1 );
533 newSet
->removeObject( count
- 1);
545 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
547 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
549 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
551 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
552 OSAsyncReference reference
, vm_size_t extraSize
)
554 return( super::init( port
, type
, reference
,
555 sizeof(IOServiceInterestContent
) + extraSize
) );
558 void IOServiceMessageUserNotification::free( void )
563 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
564 UInt32 messageType
, IOService
* provider
,
565 void * argument
, vm_size_t argSize
)
567 return( ((IOServiceMessageUserNotification
*) target
)->handler(
568 ref
, messageType
, provider
, argument
, argSize
));
571 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
572 UInt32 messageType
, IOService
* provider
,
573 void * messageArgument
, vm_size_t argSize
)
577 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
578 pingMsg
->notifyHeader
.content
;
580 data
->messageType
= messageType
;
582 argSize
= sizeof( messageArgument
);
583 data
->messageArgument
[0] = messageArgument
;
585 if( argSize
> kIOUserNotifyMaxMessageSize
)
586 argSize
= kIOUserNotifyMaxMessageSize
;
587 bcopy( messageArgument
, data
->messageArgument
, argSize
);
589 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
590 + sizeof( IOServiceInterestContent
)
591 - sizeof( data
->messageArgument
)
594 if( (port
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
) ))
595 pingMsg
->msgHdr
.msgh_local_port
= port
;
597 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
599 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
600 pingMsg
->msgHdr
.msgh_size
);
603 iokit_release_port( port
);
605 if( KERN_SUCCESS
!= kr
)
606 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
608 return( kIOReturnSuccess
);
611 OSObject
* IOServiceMessageUserNotification::getNextObject()
616 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
619 #define super IOService
620 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
622 void IOUserClient::initialize( void )
624 gIOObjectPortLock
= IOLockAlloc();
626 assert( gIOObjectPortLock
);
629 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
630 mach_port_t wakePort
,
631 void *callback
, void *refcon
)
633 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
634 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
635 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
638 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
639 const char * privilegeName
)
642 security_token_t token
;
643 mach_msg_type_number_t count
;
645 if( 0 != strcmp( privilegeName
, kIOClientPrivilegeAdministrator
))
646 return( kIOReturnUnsupported
);
648 count
= TASK_SECURITY_TOKEN_COUNT
;
649 kr
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
,
650 (task_info_t
) &token
, &count
);
651 if( (kr
== kIOReturnSuccess
)
652 && (0 != token
.val
[0]))
653 kr
= kIOReturnNotPrivileged
;
658 bool IOUserClient::initWithTask(task_t owningTask
,
662 if( getPropertyTable())
665 return super::init();
668 bool IOUserClient::initWithTask(task_t owningTask
,
671 OSDictionary
* properties
)
675 ok
= super::init( properties
);
676 ok
&= initWithTask( owningTask
, securityID
, type
);
681 void IOUserClient::free()
689 IOReturn
IOUserClient::clientDied( void )
691 return( clientClose());
694 IOReturn
IOUserClient::clientClose( void )
696 return( kIOReturnUnsupported
);
699 IOService
* IOUserClient::getService( void )
704 IOReturn
IOUserClient::registerNotificationPort(
705 mach_port_t
/* port */,
709 return( kIOReturnUnsupported
);
712 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
713 semaphore_t
* semaphore
)
715 return( kIOReturnUnsupported
);
718 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
720 return( kIOReturnUnsupported
);
723 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
724 IOOptionBits
* options
,
725 IOMemoryDescriptor
** memory
)
727 return( kIOReturnUnsupported
);
730 IOMemoryMap
* IOUserClient::mapClientMemory(
733 IOOptionBits mapFlags
,
734 IOVirtualAddress atAddress
)
737 IOOptionBits options
= 0;
738 IOMemoryDescriptor
* memory
;
739 IOMemoryMap
* map
= 0;
741 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
743 if( memory
&& (kIOReturnSuccess
== err
)) {
745 options
= (options
& ~kIOMapUserOptionsMask
)
746 | (mapFlags
& kIOMapUserOptionsMask
);
747 map
= memory
->map( task
, atAddress
, options
);
754 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
755 OSObject
*obj
, io_object_t
*clientObj
)
757 mach_port_name_t name
;
759 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
762 *(mach_port_name_t
*)clientObj
= name
;
763 return kIOReturnSuccess
;
766 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
771 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
776 IOExternalMethod
* IOUserClient::
777 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
779 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
782 *targetP
= (IOService
*) method
->object
;
787 IOExternalAsyncMethod
* IOUserClient::
788 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
790 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
793 *targetP
= (IOService
*) method
->object
;
798 IOExternalTrap
* IOUserClient::
799 getExternalTrapForIndex(UInt32 index
)
804 IOExternalTrap
* IOUserClient::
805 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
807 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
810 *targetP
= trap
->object
;
816 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
817 IOReturn result
, void *args
[], UInt32 numArgs
)
820 mach_msg_header_t msgHdr
;
821 OSNotificationHeader notifyHdr
;
822 IOAsyncCompletionContent asyncContent
;
823 void * args
[kMaxAsyncArgs
];
826 mach_port_t replyPort
;
829 // If no reply port, do nothing.
830 replyPort
= (mach_port_t
) reference
[0];
831 if(replyPort
== MACH_PORT_NULL
)
832 return kIOReturnSuccess
;
834 if(numArgs
> kMaxAsyncArgs
)
835 return kIOReturnMessageTooLarge
;
836 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
,0);
837 replyMsg
.msgHdr
.msgh_size
=
838 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
839 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
840 replyMsg
.msgHdr
.msgh_local_port
= 0;
841 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
843 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
844 + numArgs
*sizeof(void *);
845 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
846 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
848 replyMsg
.asyncContent
.result
= result
;
850 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
851 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
852 replyMsg
.msgHdr
.msgh_size
);
853 if( KERN_SUCCESS
!= kr
)
854 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
858 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
862 #define CHECK(cls,obj,out) \
864 if( !(out = OSDynamicCast( cls, obj))) \
865 return( kIOReturnBadArgument )
867 /* Routine io_object_get_class */
868 kern_return_t
is_io_object_get_class(
870 io_name_t className
)
873 return( kIOReturnBadArgument
);
875 strcpy( className
, object
->getMetaClass()->getClassName());
876 return( kIOReturnSuccess
);
879 /* Routine io_object_conforms_to */
880 kern_return_t
is_io_object_conforms_to(
883 boolean_t
*conforms
)
886 return( kIOReturnBadArgument
);
888 *conforms
= (0 != object
->metaCast( className
));
889 return( kIOReturnSuccess
);
892 /* Routine io_object_get_retain_count */
893 kern_return_t
is_io_object_get_retain_count(
898 return( kIOReturnBadArgument
);
900 *retainCount
= object
->getRetainCount();
901 return( kIOReturnSuccess
);
904 /* Routine io_iterator_next */
905 kern_return_t
is_io_iterator_next(
906 io_object_t iterator
,
907 io_object_t
*object
)
911 CHECK( OSIterator
, iterator
, iter
);
913 obj
= iter
->getNextObject();
917 return( kIOReturnSuccess
);
919 return( kIOReturnNoDevice
);
922 /* Routine io_iterator_reset */
923 kern_return_t
is_io_iterator_reset(
924 io_object_t iterator
)
926 CHECK( OSIterator
, iterator
, iter
);
930 return( kIOReturnSuccess
);
933 /* Routine io_iterator_is_valid */
934 kern_return_t
is_io_iterator_is_valid(
935 io_object_t iterator
,
936 boolean_t
*is_valid
)
938 CHECK( OSIterator
, iterator
, iter
);
940 *is_valid
= iter
->isValid();
942 return( kIOReturnSuccess
);
945 /* Routine io_service_match_property_table */
946 kern_return_t
is_io_service_match_property_table(
947 io_service_t _service
,
948 io_string_t matching
,
951 CHECK( IOService
, _service
, service
);
957 obj
= OSUnserializeXML( matching
);
959 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
960 *matches
= service
->passiveMatch( dict
);
961 kr
= kIOReturnSuccess
;
963 kr
= kIOReturnBadArgument
;
971 /* Routine io_service_get_matching_services */
972 kern_return_t
is_io_service_get_matching_services(
973 mach_port_t master_port
,
974 io_string_t matching
,
975 io_iterator_t
*existing
)
981 if( master_port
!= master_device_port
)
982 return( kIOReturnNotPrivileged
);
984 obj
= OSUnserializeXML( matching
);
986 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
987 *existing
= IOService::getMatchingServices( dict
);
988 kr
= kIOReturnSuccess
;
990 kr
= kIOReturnBadArgument
;
998 /* Routine io_service_add_notification */
999 kern_return_t
is_io_service_add_notification(
1000 mach_port_t master_port
,
1001 io_name_t notification_type
,
1002 io_string_t matching
,
1004 io_async_ref_t reference
,
1005 mach_msg_type_number_t referenceCnt
,
1006 io_object_t
* notification
)
1009 IOServiceUserNotification
* userNotify
= 0;
1010 IONotifier
* notify
= 0;
1011 const OSSymbol
* sym
;
1012 OSDictionary
* dict
;
1014 unsigned long int userMsgType
;
1017 if( master_port
!= master_device_port
)
1018 return( kIOReturnNotPrivileged
);
1021 err
= kIOReturnNoResources
;
1023 if( !(sym
= OSSymbol::withCString( notification_type
)))
1024 err
= kIOReturnNoResources
;
1026 if( !(dict
= OSDynamicCast( OSDictionary
,
1027 OSUnserializeXML( matching
)))) {
1028 err
= kIOReturnBadArgument
;
1032 if( (sym
== gIOPublishNotification
)
1033 || (sym
== gIOFirstPublishNotification
))
1034 userMsgType
= kIOServicePublishNotificationType
;
1035 else if( (sym
== gIOMatchedNotification
)
1036 || (sym
== gIOFirstMatchNotification
))
1037 userMsgType
= kIOServiceMatchedNotificationType
;
1038 else if( sym
== gIOTerminatedNotification
)
1039 userMsgType
= kIOServiceTerminatedNotificationType
;
1041 userMsgType
= kLastIOKitNotificationType
;
1043 userNotify
= new IOServiceUserNotification
;
1045 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1047 userNotify
->release();
1053 notify
= IOService::addNotification( sym
, dict
,
1054 &userNotify
->_handler
, userNotify
);
1057 *notification
= userNotify
;
1058 userNotify
->setNotification( notify
);
1059 err
= kIOReturnSuccess
;
1061 err
= kIOReturnUnsupported
;
1073 /* Routine io_service_add_notification_old */
1074 kern_return_t
is_io_service_add_notification_old(
1075 mach_port_t master_port
,
1076 io_name_t notification_type
,
1077 io_string_t matching
,
1080 io_object_t
* notification
)
1082 return( is_io_service_add_notification( master_port
, notification_type
,
1083 matching
, port
, &ref
, 1, notification
));
1086 /* Routine io_service_add_message_notification */
1087 kern_return_t
is_io_service_add_interest_notification(
1088 io_object_t _service
,
1089 io_name_t type_of_interest
,
1091 io_async_ref_t reference
,
1092 mach_msg_type_number_t referenceCnt
,
1093 io_object_t
* notification
)
1096 IOServiceMessageUserNotification
* userNotify
= 0;
1097 IONotifier
* notify
= 0;
1098 const OSSymbol
* sym
;
1101 CHECK( IOService
, _service
, service
);
1103 err
= kIOReturnNoResources
;
1104 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1106 userNotify
= new IOServiceMessageUserNotification
;
1108 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1109 reference
, kIOUserNotifyMaxMessageSize
)) {
1110 userNotify
->release();
1116 notify
= service
->registerInterest( sym
,
1117 &userNotify
->_handler
, userNotify
);
1119 *notification
= userNotify
;
1120 userNotify
->setNotification( notify
);
1121 err
= kIOReturnSuccess
;
1123 err
= kIOReturnUnsupported
;
1130 /* Routine io_service_acknowledge_notification */
1131 kern_return_t
is_io_service_acknowledge_notification(
1132 io_object_t _service
,
1133 natural_t notify_ref
,
1134 natural_t response
)
1136 CHECK( IOService
, _service
, service
);
1138 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1139 (IOOptionBits
) response
));
1143 /* Routine io_connect_get_semaphore */
1144 kern_return_t
is_io_connect_get_notification_semaphore(
1145 io_connect_t connection
,
1146 natural_t notification_type
,
1147 semaphore_t
*semaphore
)
1149 CHECK( IOUserClient
, connection
, client
);
1151 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1155 /* Routine io_registry_get_root_entry */
1156 kern_return_t
is_io_registry_get_root_entry(
1157 mach_port_t master_port
,
1160 IORegistryEntry
* entry
;
1162 if( master_port
!= master_device_port
)
1163 return( kIOReturnNotPrivileged
);
1165 entry
= IORegistryEntry::getRegistryRoot();
1170 return( kIOReturnSuccess
);
1173 /* Routine io_registry_create_iterator */
1174 kern_return_t
is_io_registry_create_iterator(
1175 mach_port_t master_port
,
1178 io_object_t
*iterator
)
1180 if( master_port
!= master_device_port
)
1181 return( kIOReturnNotPrivileged
);
1183 *iterator
= IORegistryIterator::iterateOver(
1184 IORegistryEntry::getPlane( plane
), options
);
1186 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1189 /* Routine io_registry_entry_create_iterator */
1190 kern_return_t
is_io_registry_entry_create_iterator(
1191 io_object_t registry_entry
,
1194 io_object_t
*iterator
)
1196 CHECK( IORegistryEntry
, registry_entry
, entry
);
1198 *iterator
= IORegistryIterator::iterateOver( entry
,
1199 IORegistryEntry::getPlane( plane
), options
);
1201 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1204 /* Routine io_registry_iterator_enter */
1205 kern_return_t
is_io_registry_iterator_enter_entry(
1206 io_object_t iterator
)
1208 CHECK( IORegistryIterator
, iterator
, iter
);
1212 return( kIOReturnSuccess
);
1215 /* Routine io_registry_iterator_exit */
1216 kern_return_t
is_io_registry_iterator_exit_entry(
1217 io_object_t iterator
)
1221 CHECK( IORegistryIterator
, iterator
, iter
);
1223 didIt
= iter
->exitEntry();
1225 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1228 /* Routine io_registry_entry_from_path */
1229 kern_return_t
is_io_registry_entry_from_path(
1230 mach_port_t master_port
,
1232 io_object_t
*registry_entry
)
1234 IORegistryEntry
* entry
;
1236 if( master_port
!= master_device_port
)
1237 return( kIOReturnNotPrivileged
);
1239 entry
= IORegistryEntry::fromPath( path
);
1241 *registry_entry
= entry
;
1243 return( kIOReturnSuccess
);
1246 /* Routine io_registry_entry_in_plane */
1247 kern_return_t
is_io_registry_entry_in_plane(
1248 io_object_t registry_entry
,
1250 boolean_t
*inPlane
)
1252 CHECK( IORegistryEntry
, registry_entry
, entry
);
1254 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1256 return( kIOReturnSuccess
);
1260 /* Routine io_registry_entry_get_path */
1261 kern_return_t
is_io_registry_entry_get_path(
1262 io_object_t registry_entry
,
1267 CHECK( IORegistryEntry
, registry_entry
, entry
);
1269 length
= sizeof( io_string_t
);
1270 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1271 return( kIOReturnSuccess
);
1273 return( kIOReturnBadArgument
);
1277 /* Routine io_registry_entry_get_name */
1278 kern_return_t
is_io_registry_entry_get_name(
1279 io_object_t registry_entry
,
1282 CHECK( IORegistryEntry
, registry_entry
, entry
);
1284 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1286 return( kIOReturnSuccess
);
1289 /* Routine io_registry_entry_get_name_in_plane */
1290 kern_return_t
is_io_registry_entry_get_name_in_plane(
1291 io_object_t registry_entry
,
1292 io_name_t planeName
,
1295 const IORegistryPlane
* plane
;
1296 CHECK( IORegistryEntry
, registry_entry
, entry
);
1299 plane
= IORegistryEntry::getPlane( planeName
);
1303 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1305 return( kIOReturnSuccess
);
1308 /* Routine io_registry_entry_get_location_in_plane */
1309 kern_return_t
is_io_registry_entry_get_location_in_plane(
1310 io_object_t registry_entry
,
1311 io_name_t planeName
,
1312 io_name_t location
)
1314 const IORegistryPlane
* plane
;
1315 CHECK( IORegistryEntry
, registry_entry
, entry
);
1318 plane
= IORegistryEntry::getPlane( planeName
);
1322 const char * cstr
= entry
->getLocation( plane
);
1325 strncpy( location
, cstr
, sizeof( io_name_t
));
1326 return( kIOReturnSuccess
);
1328 return( kIOReturnNotFound
);
1331 // Create a vm_map_copy_t or kalloc'ed data for memory
1332 // to be copied out. ipc will free after the copyout.
1334 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1335 io_buf_ptr_t
* buf
)
1340 err
= vm_map_copyin( kernel_map
, (vm_offset_t
) data
, len
,
1341 false /* src_destroy */, ©
);
1343 assert( err
== KERN_SUCCESS
);
1344 if( err
== KERN_SUCCESS
)
1345 *buf
= (char *) copy
;
1350 /* Routine io_registry_entry_get_property */
1351 kern_return_t
is_io_registry_entry_get_property_bytes(
1352 io_object_t registry_entry
,
1353 io_name_t property_name
,
1354 io_scalar_inband_t buf
,
1355 mach_msg_type_number_t
*dataCnt
)
1363 unsigned int len
= 0;
1364 const void * bytes
= 0;
1365 IOReturn ret
= kIOReturnSuccess
;
1367 CHECK( IORegistryEntry
, registry_entry
, entry
);
1369 obj
= entry
->copyProperty(property_name
);
1371 return( kIOReturnNoResources
);
1373 // One day OSData will be a common container base class
1375 if( (data
= OSDynamicCast( OSData
, obj
))) {
1376 len
= data
->getLength();
1377 bytes
= data
->getBytesNoCopy();
1379 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1380 len
= str
->getLength() + 1;
1381 bytes
= str
->getCStringNoCopy();
1383 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1384 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1385 bytes
= boo
->isTrue() ? "Yes" : "No";
1387 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1388 offsetBytes
= off
->unsigned64BitValue();
1389 len
= off
->numberOfBytes();
1390 bytes
= &offsetBytes
;
1392 bytes
= (const void *)
1393 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1397 ret
= kIOReturnBadArgument
;
1401 ret
= kIOReturnIPCError
;
1404 bcopy( bytes
, buf
, len
);
1412 /* Routine io_registry_entry_get_property */
1413 kern_return_t
is_io_registry_entry_get_property(
1414 io_object_t registry_entry
,
1415 io_name_t property_name
,
1416 io_buf_ptr_t
*properties
,
1417 mach_msg_type_number_t
*propertiesCnt
)
1423 CHECK( IORegistryEntry
, registry_entry
, entry
);
1425 obj
= entry
->copyProperty(property_name
);
1427 return( kIOReturnNotFound
);
1429 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1432 return( kIOReturnNoMemory
);
1436 if( obj
->serialize( s
)) {
1437 len
= s
->getLength();
1438 *propertiesCnt
= len
;
1439 err
= copyoutkdata( s
->text(), len
, properties
);
1442 err
= kIOReturnUnsupported
;
1450 /* Routine io_registry_entry_get_property_recursively */
1451 kern_return_t
is_io_registry_entry_get_property_recursively(
1452 io_object_t registry_entry
,
1454 io_name_t property_name
,
1456 io_buf_ptr_t
*properties
,
1457 mach_msg_type_number_t
*propertiesCnt
)
1463 CHECK( IORegistryEntry
, registry_entry
, entry
);
1465 obj
= entry
->copyProperty( property_name
,
1466 IORegistryEntry::getPlane( plane
), options
);
1468 return( kIOReturnNotFound
);
1470 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1473 return( kIOReturnNoMemory
);
1478 if( obj
->serialize( s
)) {
1479 len
= s
->getLength();
1480 *propertiesCnt
= len
;
1481 err
= copyoutkdata( s
->text(), len
, properties
);
1484 err
= kIOReturnUnsupported
;
1492 /* Routine io_registry_entry_get_properties */
1493 kern_return_t
is_io_registry_entry_get_properties(
1494 io_object_t registry_entry
,
1495 io_buf_ptr_t
*properties
,
1496 mach_msg_type_number_t
*propertiesCnt
)
1501 CHECK( IORegistryEntry
, registry_entry
, entry
);
1503 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1505 return( kIOReturnNoMemory
);
1509 if( entry
->serializeProperties( s
)) {
1510 len
= s
->getLength();
1511 *propertiesCnt
= len
;
1512 err
= copyoutkdata( s
->text(), len
, properties
);
1515 err
= kIOReturnUnsupported
;
1522 /* Routine io_registry_entry_set_properties */
1523 kern_return_t is_io_registry_entry_set_properties
1525 io_object_t registry_entry
,
1526 io_buf_ptr_t properties
,
1527 mach_msg_type_number_t propertiesCnt
,
1535 CHECK( IORegistryEntry
, registry_entry
, entry
);
1537 err
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
) properties
);
1539 if( KERN_SUCCESS
== err
) {
1541 // must return success after vm_map_copyout() succeeds
1542 obj
= OSUnserializeXML( (const char *) data
);
1543 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1546 res
= entry
->setProperties( obj
);
1549 res
= kIOReturnBadArgument
;
1557 /* Routine io_registry_entry_get_child_iterator */
1558 kern_return_t
is_io_registry_entry_get_child_iterator(
1559 io_object_t registry_entry
,
1561 io_object_t
*iterator
)
1563 CHECK( IORegistryEntry
, registry_entry
, entry
);
1565 *iterator
= entry
->getChildIterator(
1566 IORegistryEntry::getPlane( plane
));
1568 return( kIOReturnSuccess
);
1571 /* Routine io_registry_entry_get_parent_iterator */
1572 kern_return_t
is_io_registry_entry_get_parent_iterator(
1573 io_object_t registry_entry
,
1575 io_object_t
*iterator
)
1577 CHECK( IORegistryEntry
, registry_entry
, entry
);
1579 *iterator
= entry
->getParentIterator(
1580 IORegistryEntry::getPlane( plane
));
1582 return( kIOReturnSuccess
);
1585 /* Routine io_service_get_busy_state */
1586 kern_return_t
is_io_service_get_busy_state(
1587 io_object_t _service
,
1590 CHECK( IOService
, _service
, service
);
1592 *busyState
= service
->getBusyState();
1594 return( kIOReturnSuccess
);
1597 /* Routine io_service_wait_quiet */
1598 kern_return_t
is_io_service_wait_quiet(
1599 io_object_t _service
,
1600 mach_timespec_t wait_time
)
1602 CHECK( IOService
, _service
, service
);
1604 return( service
->waitQuiet( &wait_time
));
1607 /* Routine io_service_request_probe */
1608 kern_return_t
is_io_service_request_probe(
1609 io_object_t _service
,
1612 CHECK( IOService
, _service
, service
);
1614 return( service
->requestProbe( options
));
1618 /* Routine io_service_open */
1619 kern_return_t
is_io_service_open(
1620 io_object_t _service
,
1623 io_object_t
*connection
)
1625 IOUserClient
* client
;
1628 CHECK( IOService
, _service
, service
);
1630 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1631 connect_type
, &client
);
1633 if( err
== kIOReturnSuccess
) {
1634 assert( OSDynamicCast(IOUserClient
, client
) );
1635 *connection
= client
;
1641 /* Routine io_service_close */
1642 kern_return_t
is_io_service_close(
1643 io_object_t connection
)
1645 CHECK( IOUserClient
, connection
, client
);
1647 client
->clientClose();
1649 return( kIOReturnSuccess
);
1652 /* Routine io_connect_get_service */
1653 kern_return_t
is_io_connect_get_service(
1654 io_object_t connection
,
1655 io_object_t
*service
)
1657 IOService
* theService
;
1659 CHECK( IOUserClient
, connection
, client
);
1661 theService
= client
->getService();
1663 theService
->retain();
1665 *service
= theService
;
1667 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
1670 /* Routine io_connect_set_notification_port */
1671 kern_return_t
is_io_connect_set_notification_port(
1672 io_object_t connection
,
1673 int notification_type
,
1677 CHECK( IOUserClient
, connection
, client
);
1679 return( client
->registerNotificationPort( port
, notification_type
,
1683 kern_return_t
is_io_connect_map_memory(
1684 io_object_t connect
,
1687 vm_address_t
* mapAddr
,
1688 vm_size_t
* mapSize
,
1694 CHECK( IOUserClient
, connect
, client
);
1696 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
1699 *mapAddr
= map
->getVirtualAddress();
1701 *mapSize
= map
->getLength();
1703 if( task
!= current_task()) {
1704 // push a name out to the task owning the map,
1705 // so we can clean up maps
1706 mach_port_name_t name
= IOMachPort::makeSendRightForTask(
1707 task
, map
, IKOT_IOKIT_OBJECT
);
1711 // keep it with the user client
1712 IOLockLock( gIOObjectPortLock
);
1713 if( 0 == client
->mappings
)
1714 client
->mappings
= OSSet::withCapacity(2);
1715 if( client
->mappings
)
1716 client
->mappings
->setObject( map
);
1717 IOLockUnlock( gIOObjectPortLock
);
1720 err
= kIOReturnSuccess
;
1723 err
= kIOReturnBadArgument
;
1728 kern_return_t
is_io_connect_unmap_memory(
1729 io_object_t connect
,
1732 vm_address_t mapAddr
)
1735 IOOptionBits options
= 0;
1736 IOMemoryDescriptor
* memory
;
1739 CHECK( IOUserClient
, connect
, client
);
1741 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1743 if( memory
&& (kIOReturnSuccess
== err
)) {
1745 options
= (options
& ~kIOMapUserOptionsMask
)
1746 | kIOMapAnywhere
| kIOMapReference
;
1748 map
= memory
->map( task
, mapAddr
, options
);
1751 IOLockLock( gIOObjectPortLock
);
1752 if( client
->mappings
)
1753 client
->mappings
->removeObject( map
);
1754 IOLockUnlock( gIOObjectPortLock
);
1755 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
1758 err
= kIOReturnBadArgument
;
1765 /* Routine io_connect_add_client */
1766 kern_return_t
is_io_connect_add_client(
1767 io_object_t connection
,
1768 io_object_t connect_to
)
1770 CHECK( IOUserClient
, connection
, client
);
1771 CHECK( IOUserClient
, connect_to
, to
);
1773 return( client
->connectClient( to
) );
1777 /* Routine io_connect_set_properties */
1778 kern_return_t
is_io_connect_set_properties(
1779 io_object_t connection
,
1780 io_buf_ptr_t properties
,
1781 mach_msg_type_number_t propertiesCnt
,
1784 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
1788 /* Routine io_connect_method_scalarI_scalarO */
1789 kern_return_t
is_io_connect_method_scalarI_scalarO(
1790 io_object_t connect
,
1793 IOByteCount inputCount
,
1795 IOByteCount
* outputCount
)
1798 IOExternalMethod
* method
;
1802 CHECK( IOUserClient
, connect
, client
);
1803 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
1805 err
= kIOReturnBadArgument
;
1806 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
1808 if( inputCount
!= method
->count0
)
1810 if( *outputCount
!= method
->count1
)
1813 func
= method
->func
;
1815 switch( inputCount
) {
1818 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1819 input
[3], input
[4], input
[5] );
1822 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1827 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1829 &output
[0], &output
[1] );
1832 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1833 &output
[0], &output
[1], &output
[2] );
1836 err
= (object
->*func
)( input
[0], input
[1],
1837 &output
[0], &output
[1], &output
[2],
1841 err
= (object
->*func
)( input
[0],
1842 &output
[0], &output
[1], &output
[2],
1843 &output
[3], &output
[4] );
1846 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
1847 &output
[3], &output
[4], &output
[5] );
1851 IOLog("%s: Bad method table\n", client
->getName());
1856 err
= kIOReturnUnsupported
;
1861 /* Routine io_connect_method_scalarI_structureO */
1862 kern_return_t
is_io_connect_method_scalarI_structureO(
1863 io_object_t connect
,
1866 IOByteCount inputCount
,
1868 IOByteCount
* outputCount
)
1871 IOExternalMethod
* method
;
1875 CHECK( IOUserClient
, connect
, client
);
1877 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1879 err
= kIOReturnBadArgument
;
1880 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
1882 if( inputCount
!= method
->count0
)
1884 if( (0xffffffff != method
->count1
)
1885 && (*outputCount
!= method
->count1
))
1888 func
= method
->func
;
1890 switch( inputCount
) {
1893 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1898 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1900 output
, (void *)outputCount
);
1903 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1904 output
, (void *)outputCount
, 0 );
1907 err
= (object
->*func
)( input
[0], input
[1],
1908 output
, (void *)outputCount
, 0, 0 );
1911 err
= (object
->*func
)( input
[0],
1912 output
, (void *)outputCount
, 0, 0, 0 );
1915 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
1919 IOLog("%s: Bad method table\n", client
->getName());
1924 err
= kIOReturnUnsupported
;
1929 /* Routine io_connect_method_scalarI_structureI */
1930 kern_return_t
is_io_connect_method_scalarI_structureI(
1931 io_connect_t connect
,
1934 IOByteCount inputCount
,
1935 UInt8
* inputStruct
,
1936 IOByteCount inputStructCount
)
1939 IOExternalMethod
* method
;
1943 CHECK( IOUserClient
, connect
, client
);
1945 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1947 err
= kIOReturnBadArgument
;
1948 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
1950 if( (0xffffffff != method
->count0
)
1951 && (inputCount
!= method
->count0
))
1953 if( (0xffffffff != method
->count1
)
1954 && (inputStructCount
!= method
->count1
))
1957 func
= method
->func
;
1959 switch( inputCount
) {
1962 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1967 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1969 inputStruct
, (void *)inputStructCount
);
1972 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1973 inputStruct
, (void *)inputStructCount
,
1977 err
= (object
->*func
)( input
[0], input
[1],
1978 inputStruct
, (void *)inputStructCount
,
1982 err
= (object
->*func
)( input
[0],
1983 inputStruct
, (void *)inputStructCount
,
1987 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
1992 IOLog("%s: Bad method table\n", client
->getName());
1997 err
= kIOReturnUnsupported
;
2002 /* Routine io_connect_method_structureI_structureO */
2003 kern_return_t
is_io_connect_method_structureI_structureO(
2004 io_object_t connect
,
2007 IOByteCount inputCount
,
2009 IOByteCount
* outputCount
)
2012 IOExternalMethod
* method
;
2016 CHECK( IOUserClient
, connect
, client
);
2018 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2020 err
= kIOReturnBadArgument
;
2021 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2023 if( (0xffffffff != method
->count0
)
2024 && (inputCount
!= method
->count0
))
2026 if( (0xffffffff != method
->count1
)
2027 && (*outputCount
!= method
->count1
))
2030 func
= method
->func
;
2032 if( method
->count1
) {
2033 if( method
->count0
) {
2034 err
= (object
->*func
)( input
, output
,
2035 (void *)inputCount
, outputCount
, 0, 0 );
2037 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2040 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2046 err
= kIOReturnUnsupported
;
2051 kern_return_t
is_io_async_method_scalarI_scalarO(
2052 io_object_t connect
,
2053 mach_port_t wakePort
,
2054 io_async_ref_t reference
,
2055 mach_msg_type_number_t referenceCnt
,
2058 IOByteCount inputCount
,
2060 IOByteCount
* outputCount
)
2063 IOExternalAsyncMethod
*method
;
2067 CHECK( IOUserClient
, connect
, client
);
2068 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2070 err
= kIOReturnBadArgument
;
2071 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2073 if( inputCount
!= method
->count0
)
2075 if( *outputCount
!= method
->count1
)
2078 reference
[0] = (natural_t
) wakePort
;
2079 func
= method
->func
;
2081 switch( inputCount
) {
2084 err
= (object
->*func
)( reference
,
2085 input
[0], input
[1], input
[2],
2086 input
[3], input
[4], input
[5] );
2089 err
= (object
->*func
)( reference
,
2090 input
[0], input
[1], input
[2],
2095 err
= (object
->*func
)( reference
,
2096 input
[0], input
[1], input
[2],
2098 &output
[0], &output
[1] );
2101 err
= (object
->*func
)( reference
,
2102 input
[0], input
[1], input
[2],
2103 &output
[0], &output
[1], &output
[2] );
2106 err
= (object
->*func
)( reference
,
2108 &output
[0], &output
[1], &output
[2],
2112 err
= (object
->*func
)( reference
,
2114 &output
[0], &output
[1], &output
[2],
2115 &output
[3], &output
[4] );
2118 err
= (object
->*func
)( reference
,
2119 &output
[0], &output
[1], &output
[2],
2120 &output
[3], &output
[4], &output
[5] );
2124 IOLog("%s: Bad method table\n", client
->getName());
2129 err
= kIOReturnUnsupported
;
2134 kern_return_t
is_io_async_method_scalarI_structureO(
2135 io_object_t connect
,
2136 mach_port_t wakePort
,
2137 io_async_ref_t reference
,
2138 mach_msg_type_number_t referenceCnt
,
2141 IOByteCount inputCount
,
2143 IOByteCount
* outputCount
)
2146 IOExternalAsyncMethod
*method
;
2150 CHECK( IOUserClient
, connect
, client
);
2152 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2154 err
= kIOReturnBadArgument
;
2155 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2157 if( inputCount
!= method
->count0
)
2159 if( (0xffffffff != method
->count1
)
2160 && (*outputCount
!= method
->count1
))
2163 reference
[0] = (natural_t
) wakePort
;
2164 func
= method
->func
;
2166 switch( inputCount
) {
2169 err
= (object
->*func
)( reference
,
2170 input
[0], input
[1], input
[2],
2175 err
= (object
->*func
)( reference
,
2176 input
[0], input
[1], input
[2],
2178 output
, (void *)outputCount
);
2181 err
= (object
->*func
)( reference
,
2182 input
[0], input
[1], input
[2],
2183 output
, (void *)outputCount
, 0 );
2186 err
= (object
->*func
)( reference
,
2188 output
, (void *)outputCount
, 0, 0 );
2191 err
= (object
->*func
)( reference
,
2193 output
, (void *)outputCount
, 0, 0, 0 );
2196 err
= (object
->*func
)( reference
,
2197 output
, (void *)outputCount
, 0, 0, 0, 0 );
2201 IOLog("%s: Bad method table\n", client
->getName());
2206 err
= kIOReturnUnsupported
;
2211 kern_return_t
is_io_async_method_scalarI_structureI(
2212 io_connect_t connect
,
2213 mach_port_t wakePort
,
2214 io_async_ref_t reference
,
2215 mach_msg_type_number_t referenceCnt
,
2218 IOByteCount inputCount
,
2219 UInt8
* inputStruct
,
2220 IOByteCount inputStructCount
)
2223 IOExternalAsyncMethod
*method
;
2227 CHECK( IOUserClient
, connect
, client
);
2229 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2231 err
= kIOReturnBadArgument
;
2232 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2234 if( (0xffffffff != method
->count0
)
2235 && (inputCount
!= method
->count0
))
2237 if( (0xffffffff != method
->count1
)
2238 && (inputStructCount
!= method
->count1
))
2241 reference
[0] = (natural_t
) wakePort
;
2242 func
= method
->func
;
2244 switch( inputCount
) {
2247 err
= (object
->*func
)( reference
,
2248 input
[0], input
[1], input
[2],
2253 err
= (object
->*func
)( reference
,
2254 input
[0], input
[1], input
[2],
2256 inputStruct
, (void *)inputStructCount
);
2259 err
= (object
->*func
)( reference
,
2260 input
[0], input
[1], input
[2],
2261 inputStruct
, (void *)inputStructCount
,
2265 err
= (object
->*func
)( reference
,
2267 inputStruct
, (void *)inputStructCount
,
2271 err
= (object
->*func
)( reference
,
2273 inputStruct
, (void *)inputStructCount
,
2277 err
= (object
->*func
)( reference
,
2278 inputStruct
, (void *)inputStructCount
,
2283 IOLog("%s: Bad method table\n", client
->getName());
2288 err
= kIOReturnUnsupported
;
2293 kern_return_t
is_io_async_method_structureI_structureO(
2294 io_object_t connect
,
2295 mach_port_t wakePort
,
2296 io_async_ref_t reference
,
2297 mach_msg_type_number_t referenceCnt
,
2300 IOByteCount inputCount
,
2302 IOByteCount
* outputCount
)
2305 IOExternalAsyncMethod
*method
;
2309 CHECK( IOUserClient
, connect
, client
);
2311 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2313 err
= kIOReturnBadArgument
;
2314 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2316 if( (0xffffffff != method
->count0
)
2317 && (inputCount
!= method
->count0
))
2319 if( (0xffffffff != method
->count1
)
2320 && (*outputCount
!= method
->count1
))
2323 reference
[0] = (natural_t
) wakePort
;
2324 func
= method
->func
;
2326 if( method
->count1
) {
2327 if( method
->count0
) {
2328 err
= (object
->*func
)( reference
,
2330 (void *)inputCount
, outputCount
, 0, 0 );
2332 err
= (object
->*func
)( reference
,
2333 output
, outputCount
, 0, 0, 0, 0 );
2336 err
= (object
->*func
)( reference
,
2337 input
, (void *)inputCount
, 0, 0, 0, 0 );
2343 err
= kIOReturnUnsupported
;
2347 /* Routine io_make_matching */
2348 kern_return_t
is_io_make_matching(
2349 mach_port_t master_port
,
2351 IOOptionBits options
,
2353 IOByteCount inputCount
,
2354 io_string_t matching
)
2357 IOReturn err
= kIOReturnSuccess
;
2358 OSDictionary
* dict
;
2360 if( master_port
!= master_device_port
)
2361 return( kIOReturnNotPrivileged
);
2365 case kIOServiceMatching
:
2366 dict
= IOService::serviceMatching( gIOServiceKey
);
2369 case kIOBSDNameMatching
:
2370 dict
= IOBSDNameMatching( (const char *) input
);
2373 case kIOOFPathMatching
:
2374 dict
= IOOFPathMatching( (const char *) input
,
2375 matching
, sizeof( io_string_t
));
2383 return( kIOReturnUnsupported
);
2386 s
= OSSerialize::withCapacity(4096);
2388 err
= kIOReturnNoMemory
;
2392 if( !dict
->serialize( s
)) {
2393 err
= kIOReturnUnsupported
;
2397 if( s
->getLength() > sizeof( io_string_t
)) {
2398 err
= kIOReturnNoMemory
;
2401 strcpy( matching
, s
->text());
2413 /* Routine io_catalog_send_data */
2414 kern_return_t
is_io_catalog_send_data(
2415 mach_port_t master_port
,
2417 io_buf_ptr_t inData
,
2418 mach_msg_type_number_t inDataCount
,
2423 kern_return_t kr
= kIOReturnError
;
2425 //printf("io_catalog_send_data called. flag: %d\n", flag);
2427 if( master_port
!= master_device_port
)
2428 return kIOReturnNotPrivileged
;
2430 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2431 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2432 return kIOReturnBadArgument
;
2435 kr
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
)inData
);
2436 if( kr
!= KERN_SUCCESS
)
2439 // must return success after vm_map_copyout() succeeds
2442 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2443 vm_deallocate( kernel_map
, data
, inDataCount
);
2445 *result
= kIOReturnNoMemory
;
2446 return( KERN_SUCCESS
);
2452 case kIOCatalogAddDrivers
:
2453 case kIOCatalogAddDriversNoMatch
: {
2456 array
= OSDynamicCast(OSArray
, obj
);
2458 if ( !gIOCatalogue
->addDrivers( array
,
2459 flag
== kIOCatalogAddDrivers
) ) {
2460 kr
= kIOReturnError
;
2464 kr
= kIOReturnBadArgument
;
2469 case kIOCatalogRemoveDrivers
:
2470 case kIOCatalogRemoveDriversNoMatch
: {
2471 OSDictionary
* dict
;
2473 dict
= OSDynamicCast(OSDictionary
, obj
);
2475 if ( !gIOCatalogue
->removeDrivers( dict
,
2476 flag
== kIOCatalogRemoveDrivers
) ) {
2477 kr
= kIOReturnError
;
2481 kr
= kIOReturnBadArgument
;
2486 case kIOCatalogStartMatching
: {
2487 OSDictionary
* dict
;
2489 dict
= OSDynamicCast(OSDictionary
, obj
);
2491 if ( !gIOCatalogue
->startMatching( dict
) ) {
2492 kr
= kIOReturnError
;
2496 kr
= kIOReturnBadArgument
;
2501 case kIOCatalogRemoveKernelLinker
: {
2502 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
2503 kr
= kIOReturnError
;
2505 kr
= kIOReturnSuccess
;
2511 kr
= kIOReturnBadArgument
;
2515 if (obj
) obj
->release();
2518 return( KERN_SUCCESS
);
2521 /* Routine io_catalog_terminate */
2522 kern_return_t
is_io_catalog_terminate(
2523 mach_port_t master_port
,
2529 if( master_port
!= master_device_port
)
2530 return kIOReturnNotPrivileged
;
2532 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
2533 kIOClientPrivilegeAdministrator
);
2534 if( kIOReturnSuccess
!= kr
)
2538 case kIOCatalogServiceTerminate
:
2540 IOService
* service
;
2542 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
2543 kIORegistryIterateRecursively
);
2545 return kIOReturnNoMemory
;
2549 while( (service
= (IOService
*)iter
->getNextObject()) ) {
2550 if( service
->metaCast(name
)) {
2551 if ( !service
->terminate( kIOServiceRequired
2552 | kIOServiceSynchronous
) ) {
2553 kr
= kIOReturnUnsupported
;
2558 } while( !service
&& !iter
->isValid());
2562 case kIOCatalogModuleUnload
:
2563 case kIOCatalogModuleTerminate
:
2564 kr
= gIOCatalogue
->terminateDriversForModule(name
,
2565 flag
== kIOCatalogModuleUnload
);
2569 kr
= kIOReturnBadArgument
;
2576 /* Routine io_catalog_get_data */
2577 kern_return_t
is_io_catalog_get_data(
2578 mach_port_t master_port
,
2580 io_buf_ptr_t
*outData
,
2581 mach_msg_type_number_t
*outDataCount
)
2583 kern_return_t kr
= kIOReturnSuccess
;
2586 if( master_port
!= master_device_port
)
2587 return kIOReturnNotPrivileged
;
2589 //printf("io_catalog_get_data called. flag: %d\n", flag);
2591 s
= OSSerialize::withCapacity(4096);
2593 return kIOReturnNoMemory
;
2597 case kIOCatalogGetContents
:
2598 if ( !gIOCatalogue
->serialize(s
) ) {
2599 kr
= kIOReturnNoMemory
;
2604 kr
= kIOReturnBadArgument
;
2608 if ( kr
== kIOReturnSuccess
) {
2613 size
= s
->getLength();
2614 kr
= vm_allocate(kernel_map
, &data
, size
, true);
2615 if ( kr
== kIOReturnSuccess
) {
2616 bcopy(s
->text(), (void *)data
, size
);
2617 kr
= vm_map_copyin(kernel_map
, data
, size
, true, ©
);
2618 *outData
= (char *)copy
;
2619 *outDataCount
= size
;
2628 /* Routine io_catalog_get_gen_count */
2629 kern_return_t
is_io_catalog_get_gen_count(
2630 mach_port_t master_port
,
2633 if( master_port
!= master_device_port
)
2634 return kIOReturnNotPrivileged
;
2636 //printf("io_catalog_get_gen_count called.\n");
2639 return kIOReturnBadArgument
;
2641 *genCount
= gIOCatalogue
->getGenerationCount();
2643 return kIOReturnSuccess
;
2646 /* Routine io_catalog_module_loaded */
2647 kern_return_t
is_io_catalog_module_loaded(
2648 mach_port_t master_port
,
2651 if( master_port
!= master_device_port
)
2652 return kIOReturnNotPrivileged
;
2654 //printf("io_catalog_module_loaded called. name %s\n", name);
2657 return kIOReturnBadArgument
;
2659 gIOCatalogue
->moduleHasLoaded(name
);
2661 return kIOReturnSuccess
;
2664 kern_return_t
is_io_catalog_reset(
2665 mach_port_t master_port
,
2668 if( master_port
!= master_device_port
)
2669 return kIOReturnNotPrivileged
;
2672 case kIOCatalogResetDefault
:
2673 gIOCatalogue
->reset();
2677 return kIOReturnBadArgument
;
2680 return kIOReturnSuccess
;
2683 kern_return_t
iokit_user_client_trap(io_object_t userClientRef
, UInt32 index
,
2684 void *p1
, void *p2
, void *p3
,
2685 void *p4
, void *p5
, void *p6
)
2687 kern_return_t result
= kIOReturnBadArgument
;
2688 IOUserClient
*userClient
;
2690 if ((userClient
= OSDynamicCast(IOUserClient
,
2691 iokit_lookup_connect_ref_current_task(userClientRef
)))) {
2692 IOExternalTrap
*trap
;
2693 IOService
*target
= NULL
;
2695 trap
= userClient
->getTargetAndTrapForIndex(&target
, index
);
2697 if (trap
&& target
) {
2703 result
= (target
->*func
)(p1
, p2
, p3
, p4
, p5
, p6
);
2707 userClient
->release();
2715 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
2716 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
2717 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
2718 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
2719 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
2720 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
2721 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
2722 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
2723 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
2724 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
2725 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
2726 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
2727 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
2728 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
2729 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
2730 OSMetaClassDefineReservedUnused(IOUserClient
, 15);