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 #include <vm/vm_map.h>
73 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
75 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
77 class IOMachPort
: public OSObject
79 OSDeclareDefaultStructors(IOMachPort
)
84 static IOMachPort
* portForObject( OSObject
* obj
,
85 ipc_kobject_type_t type
);
86 static void releasePortForObject( OSObject
* obj
,
87 ipc_kobject_type_t type
);
88 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
90 static mach_port_name_t
makeSendRightForTask( task_t task
,
91 io_object_t obj
, ipc_kobject_type_t type
);
96 #define super OSObject
97 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
99 static IOLock
* gIOObjectPortLock
;
101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103 // not in dictForType() for debugging ease
104 static OSDictionary
* gIOObjectPorts
;
105 static OSDictionary
* gIOConnectPorts
;
107 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
109 OSDictionary
** dict
;
111 if( IKOT_IOKIT_OBJECT
== type
)
112 dict
= &gIOObjectPorts
;
113 else if( IKOT_IOKIT_CONNECT
== type
)
114 dict
= &gIOConnectPorts
;
119 *dict
= OSDictionary::withCapacity( 1 );
124 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
125 ipc_kobject_type_t type
)
127 IOMachPort
* inst
= 0;
130 IOTakeLock( gIOObjectPortLock
);
134 dict
= dictForType( type
);
138 if( (inst
= (IOMachPort
*)
139 dict
->getObject( (const OSSymbol
*) obj
)))
142 inst
= new IOMachPort
;
143 if( inst
&& !inst
->init()) {
148 inst
->port
= iokit_alloc_object_port( obj
, type
);
151 dict
->setObject( (const OSSymbol
*) obj
, inst
);
152 inst
->release(); // one more to free port => release obj
161 IOUnlock( gIOObjectPortLock
);
166 void IOMachPort::releasePortForObject( OSObject
* obj
,
167 ipc_kobject_type_t type
)
171 IOTakeLock( gIOObjectPortLock
);
173 if( (dict
= dictForType( type
))) {
175 dict
->removeObject( (const OSSymbol
*) obj
);
179 IOUnlock( gIOObjectPortLock
);
182 void IOUserClient::destroyUserReferences( OSObject
* obj
)
184 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
185 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_CONNECT
);
188 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
189 io_object_t obj
, ipc_kobject_type_t type
)
191 return( iokit_make_send_right( task
, obj
, type
));
194 void IOMachPort::free( void )
197 iokit_destroy_object_port( port
);
201 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
205 // functions called from osfmk/device/iokit_rpc.c
208 iokit_add_reference( io_object_t obj
)
215 iokit_remove_reference( io_object_t obj
)
222 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
224 IOMachPort
* machPort
;
226 if( (machPort
= IOMachPort::portForObject( obj
, type
)))
227 return( machPort
->port
);
233 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
234 ipc_kobject_type_t type
)
236 IOUserClient
* client
;
239 if( (IKOT_IOKIT_CONNECT
== type
)
240 && (client
= OSDynamicCast( IOUserClient
, obj
)))
241 client
->clientDied();
242 else if( (IKOT_IOKIT_OBJECT
== type
)
243 && (map
= OSDynamicCast( IOMemoryMap
, obj
)))
246 IOMachPort::releasePortForObject( obj
, type
);
248 return( kIOReturnSuccess
);
253 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
255 class IOUserNotification
: public OSIterator
257 OSDeclareDefaultStructors(IOUserNotification
)
260 mach_msg_header_t msgHdr
;
261 OSNotificationHeader notifyHeader
;
266 IONotifier
* holdNotify
;
271 virtual bool init( mach_port_t port
, natural_t type
,
272 OSAsyncReference reference
,
273 vm_size_t messageSize
);
276 virtual void setNotification( IONotifier
* obj
);
278 virtual void reset();
279 virtual bool isValid();
282 class IOServiceUserNotification
: public IOUserNotification
284 OSDeclareDefaultStructors(IOServiceUserNotification
)
286 enum { kMaxOutstanding
= 256 };
289 OSObject
* lastEntry
;
294 virtual bool init( mach_port_t port
, natural_t type
,
295 OSAsyncReference reference
);
298 static bool _handler( void * target
,
299 void * ref
, IOService
* newService
);
300 virtual bool handler( void * ref
, IOService
* newService
);
302 virtual OSObject
* getNextObject();
305 class IOServiceMessageUserNotification
: public IOUserNotification
307 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
311 virtual bool init( mach_port_t port
, natural_t type
,
312 OSAsyncReference reference
, vm_size_t extraSize
);
315 static IOReturn
_handler( void * target
, void * ref
,
316 UInt32 messageType
, IOService
* provider
,
317 void * messageArgument
, vm_size_t argSize
);
318 virtual IOReturn
handler( void * ref
,
319 UInt32 messageType
, IOService
* provider
,
320 void * messageArgument
, vm_size_t argSize
);
322 virtual OSObject
* getNextObject();
325 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
328 #define super OSIterator
329 OSDefineMetaClass( IOUserNotification
, OSIterator
)
330 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
332 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
334 bool IOUserNotification::init( mach_port_t port
, natural_t type
,
335 OSAsyncReference reference
, vm_size_t extraSize
)
340 lock
= IOLockAlloc();
344 msgSize
= sizeof( PingMsg
) + extraSize
;
345 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
349 bzero( pingMsg
, msgSize
);
351 pingMsg
->msgHdr
.msgh_remote_port
= port
;
352 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
353 MACH_MSG_TYPE_COPY_SEND
,
354 MACH_MSG_TYPE_COPY_SEND
);
355 pingMsg
->msgHdr
.msgh_size
= msgSize
;
356 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
358 pingMsg
->notifyHeader
.size
= extraSize
;
359 pingMsg
->notifyHeader
.type
= type
;
360 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
365 void IOUserNotification::free( void )
368 holdNotify
->remove();
369 // can't be in handler now
372 IOFree( pingMsg
, msgSize
);
381 void IOUserNotification::setNotification( IONotifier
* notify
)
384 holdNotify
->remove();
389 void IOUserNotification::reset()
394 bool IOUserNotification::isValid()
399 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
402 #define super IOUserNotification
403 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
405 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
407 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
408 OSAsyncReference reference
)
410 newSet
= OSArray::withCapacity( 1 );
414 return( super::init( port
, type
, reference
, 0) );
417 void IOServiceUserNotification::free( void )
420 lastEntry
->release();
428 bool IOServiceUserNotification::_handler( void * target
,
429 void * ref
, IOService
* newService
)
431 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
434 bool IOServiceUserNotification::handler( void * /* ref */,
435 IOService
* newService
)
439 IOMachPort
* machPort
;
440 bool sendPing
= false;
444 count
= newSet
->getCount();
445 if( count
< kMaxOutstanding
) {
447 newSet
->setObject( newService
);
448 if( (sendPing
= (armed
&& (0 == count
))))
455 if( (0 == pingMsg
->msgHdr
.msgh_local_port
)
456 && (machPort
= IOMachPort::portForObject( this, IKOT_IOKIT_OBJECT
) ))
457 pingMsg
->msgHdr
.msgh_local_port
= machPort
->port
;
459 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
460 pingMsg
->msgHdr
.msgh_size
);
461 if( KERN_SUCCESS
!= kr
)
462 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
468 OSObject
* IOServiceUserNotification::getNextObject()
476 lastEntry
->release();
478 count
= newSet
->getCount();
480 result
= newSet
->getObject( count
- 1 );
482 newSet
->removeObject( count
- 1);
494 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
496 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
498 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
500 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
501 OSAsyncReference reference
, vm_size_t extraSize
)
503 return( super::init( port
, type
, reference
,
504 sizeof(IOServiceInterestContent
) + extraSize
) );
507 void IOServiceMessageUserNotification::free( void )
512 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
513 UInt32 messageType
, IOService
* provider
,
514 void * argument
, vm_size_t argSize
)
516 return( ((IOServiceMessageUserNotification
*) target
)->handler(
517 ref
, messageType
, provider
, argument
, argSize
));
520 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
521 UInt32 messageType
, IOService
* provider
,
522 void * messageArgument
, vm_size_t argSize
)
525 IOMachPort
* machPort
;
526 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
527 pingMsg
->notifyHeader
.content
;
529 data
->messageType
= messageType
;
531 argSize
= sizeof( messageArgument
);
532 data
->messageArgument
[0] = messageArgument
;
534 if( argSize
> kIOUserNotifyMaxMessageSize
)
535 argSize
= kIOUserNotifyMaxMessageSize
;
536 bcopy( messageArgument
, data
->messageArgument
, argSize
);
538 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
539 + sizeof( IOServiceInterestContent
)
540 - sizeof( data
->messageArgument
)
543 if( (machPort
= IOMachPort::portForObject( provider
, IKOT_IOKIT_OBJECT
) ))
544 pingMsg
->msgHdr
.msgh_local_port
= machPort
->port
;
546 pingMsg
->msgHdr
.msgh_local_port
= MACH_PORT_NULL
;
548 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
549 pingMsg
->msgHdr
.msgh_size
);
550 if( KERN_SUCCESS
!= kr
)
551 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
553 return( kIOReturnSuccess
);
556 OSObject
* IOServiceMessageUserNotification::getNextObject()
561 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
564 #define super IOService
565 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
567 void IOUserClient::initialize( void )
569 gIOObjectPortLock
= IOLockAlloc();
571 assert( gIOObjectPortLock
);
574 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
575 mach_port_t wakePort
,
576 void *callback
, void *refcon
)
578 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
579 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
580 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
583 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
584 const char * privilegeName
)
587 security_token_t token
;
588 mach_msg_type_number_t count
;
590 if( 0 != strcmp( privilegeName
, kIOClientPrivilegeAdministrator
))
591 return( kIOReturnUnsupported
);
593 count
= TASK_SECURITY_TOKEN_COUNT
;
594 kr
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
,
595 (task_info_t
) &token
, &count
);
596 if( (kr
== kIOReturnSuccess
)
597 && (0 != token
.val
[0]))
598 kr
= kIOReturnNotPrivileged
;
603 bool IOUserClient::initWithTask(task_t owningTask
,
607 if( getPropertyTable())
610 return super::init();
613 bool IOUserClient::initWithTask(task_t owningTask
,
616 OSDictionary
* properties
)
620 ok
= super::init( properties
);
621 ok
&= initWithTask( owningTask
, securityID
, type
);
626 void IOUserClient::free()
634 IOReturn
IOUserClient::clientDied( void )
636 return( clientClose());
639 IOReturn
IOUserClient::clientClose( void )
641 return( kIOReturnUnsupported
);
644 IOService
* IOUserClient::getService( void )
649 IOReturn
IOUserClient::registerNotificationPort(
650 mach_port_t
/* port */,
654 return( kIOReturnUnsupported
);
657 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
658 semaphore_t
* semaphore
)
660 return( kIOReturnUnsupported
);
663 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
665 return( kIOReturnUnsupported
);
668 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
669 IOOptionBits
* options
,
670 IOMemoryDescriptor
** memory
)
672 return( kIOReturnUnsupported
);
675 IOMemoryMap
* IOUserClient::mapClientMemory(
678 IOOptionBits mapFlags
= kIOMapAnywhere
,
679 IOVirtualAddress atAddress
= 0 )
682 IOOptionBits options
= 0;
683 IOMemoryDescriptor
* memory
;
684 IOMemoryMap
* map
= 0;
686 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
688 if( memory
&& (kIOReturnSuccess
== err
)) {
690 options
= (options
& ~kIOMapUserOptionsMask
)
691 | (mapFlags
& kIOMapUserOptionsMask
);
692 map
= memory
->map( task
, atAddress
, options
);
699 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
700 OSObject
*obj
, io_object_t
*clientObj
)
702 mach_port_name_t name
;
704 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
707 *(mach_port_name_t
*)clientObj
= name
;
708 return kIOReturnSuccess
;
711 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
716 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
721 IOExternalMethod
* IOUserClient::
722 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
724 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
727 *targetP
= (IOService
*) method
->object
;
732 IOExternalAsyncMethod
* IOUserClient::
733 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
735 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
738 *targetP
= (IOService
*) method
->object
;
743 IOExternalTrap
* IOUserClient::
744 getExternalTrapForIndex(UInt32 index
)
749 IOExternalTrap
* IOUserClient::
750 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
752 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
755 *targetP
= trap
->object
;
761 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
762 IOReturn result
, void *args
[], UInt32 numArgs
)
765 mach_msg_header_t msgHdr
;
766 OSNotificationHeader notifyHdr
;
767 IOAsyncCompletionContent asyncContent
;
768 void * args
[kMaxAsyncArgs
];
771 mach_port_t replyPort
;
774 // If no reply port, do nothing.
775 replyPort
= (mach_port_t
) reference
[0];
776 if(replyPort
== MACH_PORT_NULL
)
777 return kIOReturnSuccess
;
779 if(numArgs
> kMaxAsyncArgs
)
780 return kIOReturnMessageTooLarge
;
781 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
,0);
782 replyMsg
.msgHdr
.msgh_size
=
783 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
784 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
785 replyMsg
.msgHdr
.msgh_local_port
= 0;
786 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
788 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
789 + numArgs
*sizeof(void *);
790 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
791 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
793 replyMsg
.asyncContent
.result
= result
;
795 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
796 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
797 replyMsg
.msgHdr
.msgh_size
);
798 if( KERN_SUCCESS
!= kr
)
799 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
803 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
807 #define CHECK(cls,obj,out) \
809 if( !(out = OSDynamicCast( cls, obj))) \
810 return( kIOReturnBadArgument )
812 /* Routine io_object_get_class */
813 kern_return_t
is_io_object_get_class(
815 io_name_t className
)
818 return( kIOReturnBadArgument
);
820 strcpy( className
, object
->getMetaClass()->getClassName());
821 return( kIOReturnSuccess
);
824 /* Routine io_object_conforms_to */
825 kern_return_t
is_io_object_conforms_to(
828 boolean_t
*conforms
)
831 return( kIOReturnBadArgument
);
833 *conforms
= (0 != object
->metaCast( className
));
834 return( kIOReturnSuccess
);
837 /* Routine io_object_get_retain_count */
838 kern_return_t
is_io_object_get_retain_count(
843 return( kIOReturnBadArgument
);
845 *retainCount
= object
->getRetainCount();
846 return( kIOReturnSuccess
);
849 /* Routine io_iterator_next */
850 kern_return_t
is_io_iterator_next(
851 io_object_t iterator
,
852 io_object_t
*object
)
856 CHECK( OSIterator
, iterator
, iter
);
858 obj
= iter
->getNextObject();
862 return( kIOReturnSuccess
);
864 return( kIOReturnNoDevice
);
867 /* Routine io_iterator_reset */
868 kern_return_t
is_io_iterator_reset(
869 io_object_t iterator
)
871 CHECK( OSIterator
, iterator
, iter
);
875 return( kIOReturnSuccess
);
878 /* Routine io_iterator_is_valid */
879 kern_return_t
is_io_iterator_is_valid(
880 io_object_t iterator
,
881 boolean_t
*is_valid
)
883 CHECK( OSIterator
, iterator
, iter
);
885 *is_valid
= iter
->isValid();
887 return( kIOReturnSuccess
);
890 /* Routine io_service_match_property_table */
891 kern_return_t
is_io_service_match_property_table(
892 io_service_t _service
,
893 io_string_t matching
,
896 CHECK( IOService
, _service
, service
);
902 obj
= OSUnserializeXML( matching
);
904 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
905 *matches
= service
->passiveMatch( dict
);
906 kr
= kIOReturnSuccess
;
908 kr
= kIOReturnBadArgument
;
916 /* Routine io_service_get_matching_services */
917 kern_return_t
is_io_service_get_matching_services(
918 mach_port_t master_port
,
919 io_string_t matching
,
920 io_iterator_t
*existing
)
926 if( master_port
!= master_device_port
)
927 return( kIOReturnNotPrivileged
);
929 obj
= OSUnserializeXML( matching
);
931 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
932 *existing
= IOService::getMatchingServices( dict
);
933 kr
= kIOReturnSuccess
;
935 kr
= kIOReturnBadArgument
;
943 /* Routine io_service_add_notification */
944 kern_return_t
is_io_service_add_notification(
945 mach_port_t master_port
,
946 io_name_t notification_type
,
947 io_string_t matching
,
949 io_async_ref_t reference
,
950 mach_msg_type_number_t referenceCnt
,
951 io_object_t
* notification
)
954 IOServiceUserNotification
* userNotify
= 0;
955 IONotifier
* notify
= 0;
956 const OSSymbol
* sym
;
959 unsigned long int userMsgType
;
962 if( master_port
!= master_device_port
)
963 return( kIOReturnNotPrivileged
);
966 err
= kIOReturnNoResources
;
968 if( !(sym
= OSSymbol::withCString( notification_type
)))
969 err
= kIOReturnNoResources
;
971 if( !(dict
= OSDynamicCast( OSDictionary
,
972 OSUnserializeXML( matching
)))) {
973 err
= kIOReturnBadArgument
;
977 if( (sym
== gIOPublishNotification
)
978 || (sym
== gIOFirstPublishNotification
))
979 userMsgType
= kIOServicePublishNotificationType
;
980 else if( (sym
== gIOMatchedNotification
)
981 || (sym
== gIOFirstMatchNotification
))
982 userMsgType
= kIOServiceMatchedNotificationType
;
983 else if( sym
== gIOTerminatedNotification
)
984 userMsgType
= kIOServiceTerminatedNotificationType
;
986 userMsgType
= kLastIOKitNotificationType
;
988 userNotify
= new IOServiceUserNotification
;
990 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
992 userNotify
->release();
998 notify
= IOService::addNotification( sym
, dict
,
999 &userNotify
->_handler
, userNotify
);
1002 *notification
= userNotify
;
1003 userNotify
->setNotification( notify
);
1004 err
= kIOReturnSuccess
;
1006 err
= kIOReturnUnsupported
;
1018 /* Routine io_service_add_notification_old */
1019 kern_return_t
is_io_service_add_notification_old(
1020 mach_port_t master_port
,
1021 io_name_t notification_type
,
1022 io_string_t matching
,
1025 io_object_t
* notification
)
1027 return( is_io_service_add_notification( master_port
, notification_type
,
1028 matching
, port
, &ref
, 1, notification
));
1031 /* Routine io_service_add_message_notification */
1032 kern_return_t
is_io_service_add_interest_notification(
1033 io_object_t _service
,
1034 io_name_t type_of_interest
,
1036 io_async_ref_t reference
,
1037 mach_msg_type_number_t referenceCnt
,
1038 io_object_t
* notification
)
1041 IOServiceMessageUserNotification
* userNotify
= 0;
1042 IONotifier
* notify
= 0;
1043 const OSSymbol
* sym
;
1046 CHECK( IOService
, _service
, service
);
1048 err
= kIOReturnNoResources
;
1049 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1051 userNotify
= new IOServiceMessageUserNotification
;
1053 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1054 reference
, kIOUserNotifyMaxMessageSize
)) {
1055 userNotify
->release();
1061 notify
= service
->registerInterest( sym
,
1062 &userNotify
->_handler
, userNotify
);
1064 *notification
= userNotify
;
1065 userNotify
->setNotification( notify
);
1066 err
= kIOReturnSuccess
;
1068 err
= kIOReturnUnsupported
;
1075 /* Routine io_service_acknowledge_notification */
1076 kern_return_t
is_io_service_acknowledge_notification(
1077 io_object_t _service
,
1078 natural_t notify_ref
,
1079 natural_t response
)
1081 CHECK( IOService
, _service
, service
);
1083 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1084 (IOOptionBits
) response
));
1088 /* Routine io_connect_get_semaphore */
1089 kern_return_t
is_io_connect_get_notification_semaphore(
1090 io_connect_t connection
,
1091 natural_t notification_type
,
1092 semaphore_t
*semaphore
)
1094 CHECK( IOUserClient
, connection
, client
);
1096 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1100 /* Routine io_registry_get_root_entry */
1101 kern_return_t
is_io_registry_get_root_entry(
1102 mach_port_t master_port
,
1105 IORegistryEntry
* entry
;
1107 if( master_port
!= master_device_port
)
1108 return( kIOReturnNotPrivileged
);
1110 entry
= IORegistryEntry::getRegistryRoot();
1115 return( kIOReturnSuccess
);
1118 /* Routine io_registry_create_iterator */
1119 kern_return_t
is_io_registry_create_iterator(
1120 mach_port_t master_port
,
1123 io_object_t
*iterator
)
1125 if( master_port
!= master_device_port
)
1126 return( kIOReturnNotPrivileged
);
1128 *iterator
= IORegistryIterator::iterateOver(
1129 IORegistryEntry::getPlane( plane
), options
);
1131 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1134 /* Routine io_registry_entry_create_iterator */
1135 kern_return_t
is_io_registry_entry_create_iterator(
1136 io_object_t registry_entry
,
1139 io_object_t
*iterator
)
1141 CHECK( IORegistryEntry
, registry_entry
, entry
);
1143 *iterator
= IORegistryIterator::iterateOver( entry
,
1144 IORegistryEntry::getPlane( plane
), options
);
1146 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1149 /* Routine io_registry_iterator_enter */
1150 kern_return_t
is_io_registry_iterator_enter_entry(
1151 io_object_t iterator
)
1153 CHECK( IORegistryIterator
, iterator
, iter
);
1157 return( kIOReturnSuccess
);
1160 /* Routine io_registry_iterator_exit */
1161 kern_return_t
is_io_registry_iterator_exit_entry(
1162 io_object_t iterator
)
1166 CHECK( IORegistryIterator
, iterator
, iter
);
1168 didIt
= iter
->exitEntry();
1170 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1173 /* Routine io_registry_entry_from_path */
1174 kern_return_t
is_io_registry_entry_from_path(
1175 mach_port_t master_port
,
1177 io_object_t
*registry_entry
)
1179 IORegistryEntry
* entry
;
1181 if( master_port
!= master_device_port
)
1182 return( kIOReturnNotPrivileged
);
1184 entry
= IORegistryEntry::fromPath( path
);
1186 *registry_entry
= entry
;
1188 return( kIOReturnSuccess
);
1191 /* Routine io_registry_entry_in_plane */
1192 kern_return_t
is_io_registry_entry_in_plane(
1193 io_object_t registry_entry
,
1195 boolean_t
*inPlane
)
1197 CHECK( IORegistryEntry
, registry_entry
, entry
);
1199 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1201 return( kIOReturnSuccess
);
1205 /* Routine io_registry_entry_get_path */
1206 kern_return_t
is_io_registry_entry_get_path(
1207 io_object_t registry_entry
,
1212 CHECK( IORegistryEntry
, registry_entry
, entry
);
1214 length
= sizeof( io_string_t
);
1215 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1216 return( kIOReturnSuccess
);
1218 return( kIOReturnBadArgument
);
1222 /* Routine io_registry_entry_get_name */
1223 kern_return_t
is_io_registry_entry_get_name(
1224 io_object_t registry_entry
,
1227 CHECK( IORegistryEntry
, registry_entry
, entry
);
1229 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1231 return( kIOReturnSuccess
);
1234 /* Routine io_registry_entry_get_name_in_plane */
1235 kern_return_t
is_io_registry_entry_get_name_in_plane(
1236 io_object_t registry_entry
,
1237 io_name_t planeName
,
1240 const IORegistryPlane
* plane
;
1241 CHECK( IORegistryEntry
, registry_entry
, entry
);
1244 plane
= IORegistryEntry::getPlane( planeName
);
1248 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1250 return( kIOReturnSuccess
);
1253 /* Routine io_registry_entry_get_location_in_plane */
1254 kern_return_t
is_io_registry_entry_get_location_in_plane(
1255 io_object_t registry_entry
,
1256 io_name_t planeName
,
1257 io_name_t location
)
1259 const IORegistryPlane
* plane
;
1260 CHECK( IORegistryEntry
, registry_entry
, entry
);
1263 plane
= IORegistryEntry::getPlane( planeName
);
1267 const char * cstr
= entry
->getLocation( plane
);
1270 strncpy( location
, cstr
, sizeof( io_name_t
));
1271 return( kIOReturnSuccess
);
1273 return( kIOReturnNotFound
);
1276 // Create a vm_map_copy_t or kalloc'ed data for memory
1277 // to be copied out. ipc will free after the copyout.
1279 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1280 io_buf_ptr_t
* buf
)
1285 err
= vm_map_copyin( kernel_map
, (vm_offset_t
) data
, len
,
1286 false /* src_destroy */, ©
);
1288 assert( err
== KERN_SUCCESS
);
1289 if( err
== KERN_SUCCESS
)
1290 *buf
= (char *) copy
;
1295 /* Routine io_registry_entry_get_property */
1296 kern_return_t
is_io_registry_entry_get_property_bytes(
1297 io_object_t registry_entry
,
1298 io_name_t property_name
,
1299 io_scalar_inband_t buf
,
1300 mach_msg_type_number_t
*dataCnt
)
1308 unsigned int len
= 0;
1309 const void * bytes
= 0;
1310 IOReturn ret
= kIOReturnSuccess
;
1312 CHECK( IORegistryEntry
, registry_entry
, entry
);
1316 obj
= entry
->copyProperty(property_name
);
1318 obj
= entry
->getProperty(property_name
);
1323 return( kIOReturnNoResources
);
1325 // One day OSData will be a common container base class
1327 if( (data
= OSDynamicCast( OSData
, obj
))) {
1328 len
= data
->getLength();
1329 bytes
= data
->getBytesNoCopy();
1331 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1332 len
= str
->getLength() + 1;
1333 bytes
= str
->getCStringNoCopy();
1335 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1336 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1337 bytes
= boo
->isTrue() ? "Yes" : "No";
1339 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1340 offsetBytes
= off
->unsigned64BitValue();
1341 len
= off
->numberOfBytes();
1342 bytes
= &offsetBytes
;
1344 bytes
= (const void *)
1345 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1349 ret
= kIOReturnBadArgument
;
1353 ret
= kIOReturnIPCError
;
1356 bcopy( bytes
, buf
, len
);
1364 /* Routine io_registry_entry_get_property */
1365 kern_return_t
is_io_registry_entry_get_property(
1366 io_object_t registry_entry
,
1367 io_name_t property_name
,
1368 io_buf_ptr_t
*properties
,
1369 mach_msg_type_number_t
*propertiesCnt
)
1375 CHECK( IORegistryEntry
, registry_entry
, entry
);
1379 obj
= entry
->copyProperty(property_name
);
1381 obj
= entry
->getProperty(property_name
);
1386 return( kIOReturnNotFound
);
1388 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1391 return( kIOReturnNoMemory
);
1395 if( obj
->serialize( s
)) {
1396 len
= s
->getLength();
1397 *propertiesCnt
= len
;
1398 err
= copyoutkdata( s
->text(), len
, properties
);
1401 err
= kIOReturnUnsupported
;
1409 /* Routine io_registry_entry_get_property_recursively */
1410 kern_return_t
is_io_registry_entry_get_property_recursively(
1411 io_object_t registry_entry
,
1413 io_name_t property_name
,
1415 io_buf_ptr_t
*properties
,
1416 mach_msg_type_number_t
*propertiesCnt
)
1422 CHECK( IORegistryEntry
, registry_entry
, entry
);
1425 obj
= entry
->copyProperty( property_name
,
1426 IORegistryEntry::getPlane( plane
), options
);
1428 obj
= entry
->getProperty( property_name
,
1429 IORegistryEntry::getPlane( plane
), options
);
1434 return( kIOReturnNotFound
);
1436 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1439 return( kIOReturnNoMemory
);
1444 if( obj
->serialize( s
)) {
1445 len
= s
->getLength();
1446 *propertiesCnt
= len
;
1447 err
= copyoutkdata( s
->text(), len
, properties
);
1450 err
= kIOReturnUnsupported
;
1458 /* Routine io_registry_entry_get_properties */
1459 kern_return_t
is_io_registry_entry_get_properties(
1460 io_object_t registry_entry
,
1461 io_buf_ptr_t
*properties
,
1462 mach_msg_type_number_t
*propertiesCnt
)
1467 CHECK( IORegistryEntry
, registry_entry
, entry
);
1469 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1471 return( kIOReturnNoMemory
);
1475 if( entry
->serializeProperties( s
)) {
1476 len
= s
->getLength();
1477 *propertiesCnt
= len
;
1478 err
= copyoutkdata( s
->text(), len
, properties
);
1481 err
= kIOReturnUnsupported
;
1488 /* Routine io_registry_entry_set_properties */
1489 kern_return_t is_io_registry_entry_set_properties
1491 io_object_t registry_entry
,
1492 io_buf_ptr_t properties
,
1493 mach_msg_type_number_t propertiesCnt
,
1501 CHECK( IORegistryEntry
, registry_entry
, entry
);
1503 err
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
) properties
);
1505 if( KERN_SUCCESS
== err
) {
1507 // must return success after vm_map_copyout() succeeds
1508 obj
= OSUnserializeXML( (const char *) data
);
1509 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1512 res
= entry
->setProperties( obj
);
1515 res
= kIOReturnBadArgument
;
1523 /* Routine io_registry_entry_get_child_iterator */
1524 kern_return_t
is_io_registry_entry_get_child_iterator(
1525 io_object_t registry_entry
,
1527 io_object_t
*iterator
)
1529 CHECK( IORegistryEntry
, registry_entry
, entry
);
1531 *iterator
= entry
->getChildIterator(
1532 IORegistryEntry::getPlane( plane
));
1534 return( kIOReturnSuccess
);
1537 /* Routine io_registry_entry_get_parent_iterator */
1538 kern_return_t
is_io_registry_entry_get_parent_iterator(
1539 io_object_t registry_entry
,
1541 io_object_t
*iterator
)
1543 CHECK( IORegistryEntry
, registry_entry
, entry
);
1545 *iterator
= entry
->getParentIterator(
1546 IORegistryEntry::getPlane( plane
));
1548 return( kIOReturnSuccess
);
1551 /* Routine io_service_get_busy_state */
1552 kern_return_t
is_io_service_get_busy_state(
1553 io_object_t _service
,
1556 CHECK( IOService
, _service
, service
);
1558 *busyState
= service
->getBusyState();
1560 return( kIOReturnSuccess
);
1563 /* Routine io_service_wait_quiet */
1564 kern_return_t
is_io_service_wait_quiet(
1565 io_object_t _service
,
1566 mach_timespec_t wait_time
)
1568 CHECK( IOService
, _service
, service
);
1570 return( service
->waitQuiet( &wait_time
));
1573 /* Routine io_service_request_probe */
1574 kern_return_t
is_io_service_request_probe(
1575 io_object_t _service
,
1578 CHECK( IOService
, _service
, service
);
1580 return( service
->requestProbe( options
));
1584 /* Routine io_service_open */
1585 kern_return_t
is_io_service_open(
1586 io_object_t _service
,
1589 io_object_t
*connection
)
1591 IOUserClient
* client
;
1594 CHECK( IOService
, _service
, service
);
1596 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1597 connect_type
, &client
);
1599 if( err
== kIOReturnSuccess
) {
1600 assert( OSDynamicCast(IOUserClient
, client
) );
1601 *connection
= client
;
1607 /* Routine io_service_close */
1608 kern_return_t
is_io_service_close(
1609 io_object_t connection
)
1611 CHECK( IOUserClient
, connection
, client
);
1613 client
->clientClose();
1615 return( kIOReturnSuccess
);
1618 /* Routine io_connect_get_service */
1619 kern_return_t
is_io_connect_get_service(
1620 io_object_t connection
,
1621 io_object_t
*service
)
1623 IOService
* theService
;
1625 CHECK( IOUserClient
, connection
, client
);
1627 theService
= client
->getService();
1629 theService
->retain();
1631 *service
= theService
;
1633 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
1636 /* Routine io_connect_set_notification_port */
1637 kern_return_t
is_io_connect_set_notification_port(
1638 io_object_t connection
,
1639 int notification_type
,
1643 CHECK( IOUserClient
, connection
, client
);
1645 return( client
->registerNotificationPort( port
, notification_type
,
1649 kern_return_t
is_io_connect_map_memory(
1650 io_object_t connect
,
1653 vm_address_t
* mapAddr
,
1654 vm_size_t
* mapSize
,
1660 CHECK( IOUserClient
, connect
, client
);
1662 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
1665 *mapAddr
= map
->getVirtualAddress();
1667 *mapSize
= map
->getLength();
1669 if( task
!= current_task()) {
1670 // push a name out to the task owning the map,
1671 // so we can clean up maps
1672 mach_port_name_t name
= IOMachPort::makeSendRightForTask(
1673 task
, map
, IKOT_IOKIT_OBJECT
);
1677 // keep it with the user client
1678 IOLockLock( gIOObjectPortLock
);
1679 if( 0 == client
->mappings
)
1680 client
->mappings
= OSSet::withCapacity(2);
1681 if( client
->mappings
)
1682 client
->mappings
->setObject( map
);
1683 IOLockUnlock( gIOObjectPortLock
);
1686 err
= kIOReturnSuccess
;
1689 err
= kIOReturnBadArgument
;
1694 kern_return_t
is_io_connect_unmap_memory(
1695 io_object_t connect
,
1698 vm_address_t mapAddr
)
1701 IOOptionBits options
= 0;
1702 IOMemoryDescriptor
* memory
;
1705 CHECK( IOUserClient
, connect
, client
);
1707 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1709 if( memory
&& (kIOReturnSuccess
== err
)) {
1711 options
= (options
& ~kIOMapUserOptionsMask
)
1712 | kIOMapAnywhere
| kIOMapReference
;
1714 map
= memory
->map( task
, mapAddr
, options
);
1717 IOLockLock( gIOObjectPortLock
);
1718 if( client
->mappings
)
1719 client
->mappings
->removeObject( map
);
1720 IOLockUnlock( gIOObjectPortLock
);
1721 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
1724 err
= kIOReturnBadArgument
;
1731 /* Routine io_connect_add_client */
1732 kern_return_t
is_io_connect_add_client(
1733 io_object_t connection
,
1734 io_object_t connect_to
)
1736 CHECK( IOUserClient
, connection
, client
);
1737 CHECK( IOUserClient
, connect_to
, to
);
1739 return( client
->connectClient( to
) );
1743 /* Routine io_connect_set_properties */
1744 kern_return_t
is_io_connect_set_properties(
1745 io_object_t connection
,
1746 io_buf_ptr_t properties
,
1747 mach_msg_type_number_t propertiesCnt
,
1750 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
1754 /* Routine io_connect_method_scalarI_scalarO */
1755 kern_return_t
is_io_connect_method_scalarI_scalarO(
1756 io_object_t connect
,
1759 IOByteCount inputCount
,
1761 IOByteCount
* outputCount
)
1764 IOExternalMethod
* method
;
1768 CHECK( IOUserClient
, connect
, client
);
1769 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
1771 err
= kIOReturnBadArgument
;
1772 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
1774 if( inputCount
!= method
->count0
)
1776 if( *outputCount
!= method
->count1
)
1779 func
= method
->func
;
1781 switch( inputCount
) {
1784 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1785 input
[3], input
[4], input
[5] );
1788 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1793 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1795 &output
[0], &output
[1] );
1798 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1799 &output
[0], &output
[1], &output
[2] );
1802 err
= (object
->*func
)( input
[0], input
[1],
1803 &output
[0], &output
[1], &output
[2],
1807 err
= (object
->*func
)( input
[0],
1808 &output
[0], &output
[1], &output
[2],
1809 &output
[3], &output
[4] );
1812 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
1813 &output
[3], &output
[4], &output
[5] );
1817 IOLog("%s: Bad method table\n", client
->getName());
1822 err
= kIOReturnUnsupported
;
1827 /* Routine io_connect_method_scalarI_structureO */
1828 kern_return_t
is_io_connect_method_scalarI_structureO(
1829 io_object_t connect
,
1832 IOByteCount inputCount
,
1834 IOByteCount
* outputCount
)
1837 IOExternalMethod
* method
;
1841 CHECK( IOUserClient
, connect
, client
);
1843 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1845 err
= kIOReturnBadArgument
;
1846 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
1848 if( inputCount
!= method
->count0
)
1850 if( (0xffffffff != method
->count1
)
1851 && (*outputCount
!= method
->count1
))
1854 func
= method
->func
;
1856 switch( inputCount
) {
1859 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1864 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1866 output
, (void *)outputCount
);
1869 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1870 output
, (void *)outputCount
, 0 );
1873 err
= (object
->*func
)( input
[0], input
[1],
1874 output
, (void *)outputCount
, 0, 0 );
1877 err
= (object
->*func
)( input
[0],
1878 output
, (void *)outputCount
, 0, 0, 0 );
1881 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
1885 IOLog("%s: Bad method table\n", client
->getName());
1890 err
= kIOReturnUnsupported
;
1895 /* Routine io_connect_method_scalarI_structureI */
1896 kern_return_t
is_io_connect_method_scalarI_structureI(
1897 io_connect_t connect
,
1900 IOByteCount inputCount
,
1901 UInt8
* inputStruct
,
1902 IOByteCount inputStructCount
)
1905 IOExternalMethod
* method
;
1909 CHECK( IOUserClient
, connect
, client
);
1911 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1913 err
= kIOReturnBadArgument
;
1914 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
1916 if( (0xffffffff != method
->count0
)
1917 && (inputCount
!= method
->count0
))
1919 if( (0xffffffff != method
->count1
)
1920 && (inputStructCount
!= method
->count1
))
1923 func
= method
->func
;
1925 switch( inputCount
) {
1928 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1933 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1935 inputStruct
, (void *)inputStructCount
);
1938 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1939 inputStruct
, (void *)inputStructCount
,
1943 err
= (object
->*func
)( input
[0], input
[1],
1944 inputStruct
, (void *)inputStructCount
,
1948 err
= (object
->*func
)( input
[0],
1949 inputStruct
, (void *)inputStructCount
,
1953 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
1958 IOLog("%s: Bad method table\n", client
->getName());
1963 err
= kIOReturnUnsupported
;
1968 /* Routine io_connect_method_structureI_structureO */
1969 kern_return_t
is_io_connect_method_structureI_structureO(
1970 io_object_t connect
,
1973 IOByteCount inputCount
,
1975 IOByteCount
* outputCount
)
1978 IOExternalMethod
* method
;
1982 CHECK( IOUserClient
, connect
, client
);
1984 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1986 err
= kIOReturnBadArgument
;
1987 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
1989 if( (0xffffffff != method
->count0
)
1990 && (inputCount
!= method
->count0
))
1992 if( (0xffffffff != method
->count1
)
1993 && (*outputCount
!= method
->count1
))
1996 func
= method
->func
;
1998 if( method
->count1
) {
1999 if( method
->count0
) {
2000 err
= (object
->*func
)( input
, output
,
2001 (void *)inputCount
, outputCount
, 0, 0 );
2003 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2006 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2012 err
= kIOReturnUnsupported
;
2017 kern_return_t
is_io_async_method_scalarI_scalarO(
2018 io_object_t connect
,
2019 mach_port_t wakePort
,
2020 io_async_ref_t reference
,
2021 mach_msg_type_number_t referenceCnt
,
2024 IOByteCount inputCount
,
2026 IOByteCount
* outputCount
)
2029 IOExternalAsyncMethod
*method
;
2033 CHECK( IOUserClient
, connect
, client
);
2034 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2036 err
= kIOReturnBadArgument
;
2037 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2039 if( inputCount
!= method
->count0
)
2041 if( *outputCount
!= method
->count1
)
2044 reference
[0] = (natural_t
) wakePort
;
2045 func
= method
->func
;
2047 switch( inputCount
) {
2050 err
= (object
->*func
)( reference
,
2051 input
[0], input
[1], input
[2],
2052 input
[3], input
[4], input
[5] );
2055 err
= (object
->*func
)( reference
,
2056 input
[0], input
[1], input
[2],
2061 err
= (object
->*func
)( reference
,
2062 input
[0], input
[1], input
[2],
2064 &output
[0], &output
[1] );
2067 err
= (object
->*func
)( reference
,
2068 input
[0], input
[1], input
[2],
2069 &output
[0], &output
[1], &output
[2] );
2072 err
= (object
->*func
)( reference
,
2074 &output
[0], &output
[1], &output
[2],
2078 err
= (object
->*func
)( reference
,
2080 &output
[0], &output
[1], &output
[2],
2081 &output
[3], &output
[4] );
2084 err
= (object
->*func
)( reference
,
2085 &output
[0], &output
[1], &output
[2],
2086 &output
[3], &output
[4], &output
[5] );
2090 IOLog("%s: Bad method table\n", client
->getName());
2095 err
= kIOReturnUnsupported
;
2100 kern_return_t
is_io_async_method_scalarI_structureO(
2101 io_object_t connect
,
2102 mach_port_t wakePort
,
2103 io_async_ref_t reference
,
2104 mach_msg_type_number_t referenceCnt
,
2107 IOByteCount inputCount
,
2109 IOByteCount
* outputCount
)
2112 IOExternalAsyncMethod
*method
;
2116 CHECK( IOUserClient
, connect
, client
);
2118 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2120 err
= kIOReturnBadArgument
;
2121 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2123 if( inputCount
!= method
->count0
)
2125 if( (0xffffffff != method
->count1
)
2126 && (*outputCount
!= method
->count1
))
2129 reference
[0] = (natural_t
) wakePort
;
2130 func
= method
->func
;
2132 switch( inputCount
) {
2135 err
= (object
->*func
)( reference
,
2136 input
[0], input
[1], input
[2],
2141 err
= (object
->*func
)( reference
,
2142 input
[0], input
[1], input
[2],
2144 output
, (void *)outputCount
);
2147 err
= (object
->*func
)( reference
,
2148 input
[0], input
[1], input
[2],
2149 output
, (void *)outputCount
, 0 );
2152 err
= (object
->*func
)( reference
,
2154 output
, (void *)outputCount
, 0, 0 );
2157 err
= (object
->*func
)( reference
,
2159 output
, (void *)outputCount
, 0, 0, 0 );
2162 err
= (object
->*func
)( reference
,
2163 output
, (void *)outputCount
, 0, 0, 0, 0 );
2167 IOLog("%s: Bad method table\n", client
->getName());
2172 err
= kIOReturnUnsupported
;
2177 kern_return_t
is_io_async_method_scalarI_structureI(
2178 io_connect_t connect
,
2179 mach_port_t wakePort
,
2180 io_async_ref_t reference
,
2181 mach_msg_type_number_t referenceCnt
,
2184 IOByteCount inputCount
,
2185 UInt8
* inputStruct
,
2186 IOByteCount inputStructCount
)
2189 IOExternalAsyncMethod
*method
;
2193 CHECK( IOUserClient
, connect
, client
);
2195 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2197 err
= kIOReturnBadArgument
;
2198 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2200 if( (0xffffffff != method
->count0
)
2201 && (inputCount
!= method
->count0
))
2203 if( (0xffffffff != method
->count1
)
2204 && (inputStructCount
!= method
->count1
))
2207 reference
[0] = (natural_t
) wakePort
;
2208 func
= method
->func
;
2210 switch( inputCount
) {
2213 err
= (object
->*func
)( reference
,
2214 input
[0], input
[1], input
[2],
2219 err
= (object
->*func
)( reference
,
2220 input
[0], input
[1], input
[2],
2222 inputStruct
, (void *)inputStructCount
);
2225 err
= (object
->*func
)( reference
,
2226 input
[0], input
[1], input
[2],
2227 inputStruct
, (void *)inputStructCount
,
2231 err
= (object
->*func
)( reference
,
2233 inputStruct
, (void *)inputStructCount
,
2237 err
= (object
->*func
)( reference
,
2239 inputStruct
, (void *)inputStructCount
,
2243 err
= (object
->*func
)( reference
,
2244 inputStruct
, (void *)inputStructCount
,
2249 IOLog("%s: Bad method table\n", client
->getName());
2254 err
= kIOReturnUnsupported
;
2259 kern_return_t
is_io_async_method_structureI_structureO(
2260 io_object_t connect
,
2261 mach_port_t wakePort
,
2262 io_async_ref_t reference
,
2263 mach_msg_type_number_t referenceCnt
,
2266 IOByteCount inputCount
,
2268 IOByteCount
* outputCount
)
2271 IOExternalAsyncMethod
*method
;
2275 CHECK( IOUserClient
, connect
, client
);
2277 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2279 err
= kIOReturnBadArgument
;
2280 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2282 if( (0xffffffff != method
->count0
)
2283 && (inputCount
!= method
->count0
))
2285 if( (0xffffffff != method
->count1
)
2286 && (*outputCount
!= method
->count1
))
2289 reference
[0] = (natural_t
) wakePort
;
2290 func
= method
->func
;
2292 if( method
->count1
) {
2293 if( method
->count0
) {
2294 err
= (object
->*func
)( reference
,
2296 (void *)inputCount
, outputCount
, 0, 0 );
2298 err
= (object
->*func
)( reference
,
2299 output
, outputCount
, 0, 0, 0, 0 );
2302 err
= (object
->*func
)( reference
,
2303 input
, (void *)inputCount
, 0, 0, 0, 0 );
2309 err
= kIOReturnUnsupported
;
2313 /* Routine io_make_matching */
2314 kern_return_t
is_io_make_matching(
2315 mach_port_t master_port
,
2317 IOOptionBits options
,
2319 IOByteCount inputCount
,
2320 io_string_t matching
)
2323 IOReturn err
= kIOReturnSuccess
;
2324 OSDictionary
* dict
;
2326 if( master_port
!= master_device_port
)
2327 return( kIOReturnNotPrivileged
);
2331 case kIOServiceMatching
:
2332 dict
= IOService::serviceMatching( gIOServiceKey
);
2335 case kIOBSDNameMatching
:
2336 dict
= IOBSDNameMatching( (const char *) input
);
2339 case kIOOFPathMatching
:
2340 dict
= IOOFPathMatching( (const char *) input
,
2341 matching
, sizeof( io_string_t
));
2349 return( kIOReturnUnsupported
);
2352 s
= OSSerialize::withCapacity(4096);
2354 err
= kIOReturnNoMemory
;
2358 if( !dict
->serialize( s
)) {
2359 err
= kIOReturnUnsupported
;
2363 if( s
->getLength() > sizeof( io_string_t
)) {
2364 err
= kIOReturnNoMemory
;
2367 strcpy( matching
, s
->text());
2379 /* Routine io_catalog_send_data */
2380 kern_return_t
is_io_catalog_send_data(
2381 mach_port_t master_port
,
2383 io_buf_ptr_t inData
,
2384 mach_msg_type_number_t inDataCount
,
2389 kern_return_t kr
= kIOReturnError
;
2391 //printf("io_catalog_send_data called. flag: %d\n", flag);
2393 if( master_port
!= master_device_port
)
2394 return kIOReturnNotPrivileged
;
2396 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2397 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2398 return kIOReturnBadArgument
;
2401 kr
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
)inData
);
2402 if( kr
!= KERN_SUCCESS
)
2405 // must return success after vm_map_copyout() succeeds
2408 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2409 vm_deallocate( kernel_map
, data
, inDataCount
);
2411 *result
= kIOReturnNoMemory
;
2412 return( KERN_SUCCESS
);
2418 case kIOCatalogAddDrivers
:
2419 case kIOCatalogAddDriversNoMatch
: {
2422 array
= OSDynamicCast(OSArray
, obj
);
2424 if ( !gIOCatalogue
->addDrivers( array
,
2425 flag
== kIOCatalogAddDrivers
) ) {
2426 kr
= kIOReturnError
;
2430 kr
= kIOReturnBadArgument
;
2435 case kIOCatalogRemoveDrivers
:
2436 case kIOCatalogRemoveDriversNoMatch
: {
2437 OSDictionary
* dict
;
2439 dict
= OSDynamicCast(OSDictionary
, obj
);
2441 if ( !gIOCatalogue
->removeDrivers( dict
,
2442 flag
== kIOCatalogRemoveDrivers
) ) {
2443 kr
= kIOReturnError
;
2447 kr
= kIOReturnBadArgument
;
2452 case kIOCatalogStartMatching
: {
2453 OSDictionary
* dict
;
2455 dict
= OSDynamicCast(OSDictionary
, obj
);
2457 if ( !gIOCatalogue
->startMatching( dict
) ) {
2458 kr
= kIOReturnError
;
2462 kr
= kIOReturnBadArgument
;
2467 case kIOCatalogRemoveKernelLinker
: {
2468 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
2469 kr
= kIOReturnError
;
2475 kr
= kIOReturnBadArgument
;
2479 if (obj
) obj
->release();
2482 return( KERN_SUCCESS
);
2485 /* Routine io_catalog_terminate */
2486 kern_return_t
is_io_catalog_terminate(
2487 mach_port_t master_port
,
2493 if( master_port
!= master_device_port
)
2494 return kIOReturnNotPrivileged
;
2496 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
2497 kIOClientPrivilegeAdministrator
);
2498 if( kIOReturnSuccess
!= kr
)
2502 case kIOCatalogServiceTerminate
:
2504 IOService
* service
;
2506 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
2507 kIORegistryIterateRecursively
);
2509 return kIOReturnNoMemory
;
2513 while( (service
= (IOService
*)iter
->getNextObject()) ) {
2514 if( service
->metaCast(name
)) {
2515 if ( !service
->terminate( kIOServiceRequired
2516 | kIOServiceSynchronous
) ) {
2517 kr
= kIOReturnUnsupported
;
2522 } while( !service
&& !iter
->isValid());
2526 case kIOCatalogModuleUnload
:
2527 case kIOCatalogModuleTerminate
:
2528 kr
= gIOCatalogue
->terminateDriversForModule(name
,
2529 flag
== kIOCatalogModuleUnload
);
2533 kr
= kIOReturnBadArgument
;
2540 /* Routine io_catalog_get_data */
2541 kern_return_t
is_io_catalog_get_data(
2542 mach_port_t master_port
,
2544 io_buf_ptr_t
*outData
,
2545 mach_msg_type_number_t
*outDataCount
)
2547 kern_return_t kr
= kIOReturnSuccess
;
2550 if( master_port
!= master_device_port
)
2551 return kIOReturnNotPrivileged
;
2553 //printf("io_catalog_get_data called. flag: %d\n", flag);
2555 s
= OSSerialize::withCapacity(4096);
2557 return kIOReturnNoMemory
;
2561 case kIOCatalogGetContents
:
2562 if ( !gIOCatalogue
->serialize(s
) ) {
2563 kr
= kIOReturnNoMemory
;
2568 kr
= kIOReturnBadArgument
;
2572 if ( kr
== kIOReturnSuccess
) {
2577 size
= s
->getLength();
2578 kr
= vm_allocate(kernel_map
, &data
, size
, true);
2579 if ( kr
== kIOReturnSuccess
) {
2580 bcopy(s
->text(), (void *)data
, size
);
2581 kr
= vm_map_copyin(kernel_map
, data
, size
, true, ©
);
2582 *outData
= (char *)copy
;
2583 *outDataCount
= size
;
2592 /* Routine io_catalog_get_gen_count */
2593 kern_return_t
is_io_catalog_get_gen_count(
2594 mach_port_t master_port
,
2597 if( master_port
!= master_device_port
)
2598 return kIOReturnNotPrivileged
;
2600 //printf("io_catalog_get_gen_count called.\n");
2603 return kIOReturnBadArgument
;
2605 *genCount
= gIOCatalogue
->getGenerationCount();
2607 return kIOReturnSuccess
;
2610 /* Routine io_catalog_module_loaded */
2611 kern_return_t
is_io_catalog_module_loaded(
2612 mach_port_t master_port
,
2615 if( master_port
!= master_device_port
)
2616 return kIOReturnNotPrivileged
;
2618 //printf("io_catalog_module_loaded called. name %s\n", name);
2621 return kIOReturnBadArgument
;
2623 gIOCatalogue
->moduleHasLoaded(name
);
2625 return kIOReturnSuccess
;
2628 kern_return_t
is_io_catalog_reset(
2629 mach_port_t master_port
,
2632 if( master_port
!= master_device_port
)
2633 return kIOReturnNotPrivileged
;
2636 case kIOCatalogResetDefault
:
2637 gIOCatalogue
->reset();
2641 return kIOReturnBadArgument
;
2644 return kIOReturnSuccess
;
2647 kern_return_t
iokit_user_client_trap(io_object_t userClientRef
, UInt32 index
,
2648 void *p1
, void *p2
, void *p3
,
2649 void *p4
, void *p5
, void *p6
)
2651 kern_return_t result
= kIOReturnBadArgument
;
2652 IOUserClient
*userClient
;
2654 if ((userClient
= OSDynamicCast(IOUserClient
,
2655 iokit_lookup_connect_ref_current_task(userClientRef
)))) {
2656 IOExternalTrap
*trap
;
2657 IOService
*target
= NULL
;
2659 trap
= userClient
->getTargetAndTrapForIndex(&target
, index
);
2661 if (trap
&& target
) {
2667 result
= (target
->*func
)(p1
, p2
, p3
, p4
, p5
, p6
);
2671 userClient
->release();
2679 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
2680 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
2681 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
2682 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
2683 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
2684 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
2685 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
2686 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
2687 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
2688 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
2689 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
2690 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
2691 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
2692 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
2693 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
2694 OSMetaClassDefineReservedUnused(IOUserClient
, 15);