2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <IOKit/IOKitServer.h>
26 #include <IOKit/IOUserClient.h>
27 #include <IOKit/IOService.h>
28 #include <IOKit/IOService.h>
29 #include <IOKit/IORegistryEntry.h>
30 #include <IOKit/IOCatalogue.h>
31 #include <IOKit/IOMemoryDescriptor.h>
32 #include <IOKit/IOLib.h>
34 #include <IOKit/assert.h>
36 #include "IOServicePrivate.h"
38 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40 // definitions we should get from osfmk
42 //typedef struct ipc_port * ipc_port_t;
43 typedef natural_t ipc_kobject_type_t
;
45 #define IKOT_IOKIT_SPARE 27
46 #define IKOT_IOKIT_CONNECT 29
47 #define IKOT_IOKIT_OBJECT 30
51 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
52 ipc_kobject_type_t type
);
54 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
56 extern mach_port_name_t
iokit_make_send_right( task_t task
,
57 io_object_t obj
, ipc_kobject_type_t type
);
59 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
61 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
63 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
65 extern ipc_port_t master_device_port
;
67 extern void iokit_retain_port( ipc_port_t port
);
68 extern void iokit_release_port( ipc_port_t port
);
70 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
72 #include <mach/mach_traps.h>
73 #include <vm/vm_map.h>
78 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
82 class IOMachPort
: public OSObject
84 OSDeclareDefaultStructors(IOMachPort
)
91 static IOMachPort
* portForObject( OSObject
* obj
,
92 ipc_kobject_type_t type
);
93 static bool noMoreSendersForObject( OSObject
* obj
,
94 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
95 static void releasePortForObject( OSObject
* obj
,
96 ipc_kobject_type_t type
);
97 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
99 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
101 static mach_port_name_t
makeSendRightForTask( task_t task
,
102 io_object_t obj
, ipc_kobject_type_t type
);
107 #define super OSObject
108 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
110 static IOLock
* gIOObjectPortLock
;
112 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
114 // not in dictForType() for debugging ease
115 static OSDictionary
* gIOObjectPorts
;
116 static OSDictionary
* gIOConnectPorts
;
118 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
120 OSDictionary
** dict
;
122 if( IKOT_IOKIT_OBJECT
== type
)
123 dict
= &gIOObjectPorts
;
124 else if( IKOT_IOKIT_CONNECT
== type
)
125 dict
= &gIOConnectPorts
;
130 *dict
= OSDictionary::withCapacity( 1 );
135 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
136 ipc_kobject_type_t type
)
138 IOMachPort
* inst
= 0;
141 IOTakeLock( gIOObjectPortLock
);
145 dict
= dictForType( type
);
149 if( (inst
= (IOMachPort
*)
150 dict
->getObject( (const OSSymbol
*) obj
))) {
156 inst
= new IOMachPort
;
157 if( inst
&& !inst
->init()) {
162 inst
->port
= iokit_alloc_object_port( obj
, type
);
165 dict
->setObject( (const OSSymbol
*) obj
, inst
);
175 IOUnlock( gIOObjectPortLock
);
180 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
181 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
184 IOMachPort
* machPort
;
185 bool destroyed
= true;
187 IOTakeLock( gIOObjectPortLock
);
189 if( (dict
= dictForType( type
))) {
192 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
194 destroyed
= (machPort
->mscount
== *mscount
);
196 dict
->removeObject( (const OSSymbol
*) obj
);
198 *mscount
= machPort
->mscount
;
203 IOUnlock( gIOObjectPortLock
);
208 void IOMachPort::releasePortForObject( OSObject
* obj
,
209 ipc_kobject_type_t type
)
212 IOMachPort
* machPort
;
214 IOTakeLock( gIOObjectPortLock
);
216 if( (dict
= dictForType( type
))) {
218 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
219 if( machPort
&& !machPort
->holdDestroy
)
220 dict
->removeObject( (const OSSymbol
*) obj
);
224 IOUnlock( gIOObjectPortLock
);
227 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
230 IOMachPort
* machPort
;
232 IOLockLock( gIOObjectPortLock
);
234 if( (dict
= dictForType( type
))) {
235 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
237 machPort
->holdDestroy
= true;
240 IOLockUnlock( gIOObjectPortLock
);
243 void IOUserClient::destroyUserReferences( OSObject
* obj
)
245 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
248 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
252 IOTakeLock( gIOObjectPortLock
);
255 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
258 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
262 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
264 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
265 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
267 uc
->mappings
->release();
270 dict
->removeObject( (const OSSymbol
*) obj
);
274 IOUnlock( gIOObjectPortLock
);
277 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
278 io_object_t obj
, ipc_kobject_type_t type
)
280 return( iokit_make_send_right( task
, obj
, type
));
283 void IOMachPort::free( void )
286 iokit_destroy_object_port( port
);
290 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
292 class IOUserNotification
: public OSIterator
294 OSDeclareDefaultStructors(IOUserNotification
)
296 IONotifier
* holdNotify
;
301 virtual bool init( void );
304 virtual void setNotification( IONotifier
* obj
);
306 virtual void reset();
307 virtual bool isValid();
310 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
314 // functions called from osfmk/device/iokit_rpc.c
317 iokit_add_reference( io_object_t obj
)
324 iokit_remove_reference( io_object_t obj
)
331 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
333 IOMachPort
* machPort
;
336 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
338 port
= machPort
->port
;
340 iokit_retain_port( port
);
351 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
352 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
354 IOUserClient
* client
;
356 IOUserNotification
* notify
;
358 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
359 return( kIOReturnNotReady
);
361 if( IKOT_IOKIT_CONNECT
== type
)
363 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
364 client
->clientDied();
366 else if( IKOT_IOKIT_OBJECT
== type
)
368 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
370 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
371 notify
->setNotification( 0 );
374 return( kIOReturnSuccess
);
379 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
381 class IOServiceUserNotification
: public IOUserNotification
383 OSDeclareDefaultStructors(IOServiceUserNotification
)
386 mach_msg_header_t msgHdr
;
387 OSNotificationHeader notifyHeader
;
390 enum { kMaxOutstanding
= 1024 };
395 OSObject
* lastEntry
;
400 virtual bool init( mach_port_t port
, natural_t type
,
401 OSAsyncReference reference
);
404 static bool _handler( void * target
,
405 void * ref
, IOService
* newService
);
406 virtual bool handler( void * ref
, IOService
* newService
);
408 virtual OSObject
* getNextObject();
411 class IOServiceMessageUserNotification
: public IOUserNotification
413 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
416 mach_msg_header_t msgHdr
;
417 mach_msg_body_t msgBody
;
418 mach_msg_port_descriptor_t ports
[1];
419 OSNotificationHeader notifyHeader
;
427 virtual bool init( mach_port_t port
, natural_t type
,
428 OSAsyncReference reference
, vm_size_t extraSize
);
431 static IOReturn
_handler( void * target
, void * ref
,
432 UInt32 messageType
, IOService
* provider
,
433 void * messageArgument
, vm_size_t argSize
);
434 virtual IOReturn
handler( void * ref
,
435 UInt32 messageType
, IOService
* provider
,
436 void * messageArgument
, vm_size_t argSize
);
438 virtual OSObject
* getNextObject();
441 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
444 #define super OSIterator
445 OSDefineMetaClass( IOUserNotification
, OSIterator
)
446 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
448 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
450 bool IOUserNotification::init( void )
455 lock
= IOLockAlloc();
462 void IOUserNotification::free( void )
465 holdNotify
->remove();
466 // can't be in handler now
475 void IOUserNotification::setNotification( IONotifier
* notify
)
477 IONotifier
* previousNotify
;
479 IOLockLock( gIOObjectPortLock
);
481 previousNotify
= holdNotify
;
484 IOLockUnlock( gIOObjectPortLock
);
487 previousNotify
->remove();
490 void IOUserNotification::reset()
495 bool IOUserNotification::isValid()
500 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
503 #define super IOUserNotification
504 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
506 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
508 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
509 OSAsyncReference reference
)
511 newSet
= OSArray::withCapacity( 1 );
515 msgSize
= sizeof( PingMsg
) + 0;
516 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
520 bzero( pingMsg
, msgSize
);
522 pingMsg
->msgHdr
.msgh_remote_port
= port
;
523 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
524 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
525 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
526 pingMsg
->msgHdr
.msgh_size
= msgSize
;
527 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
529 pingMsg
->notifyHeader
.size
= 0;
530 pingMsg
->notifyHeader
.type
= type
;
531 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
533 return( super::init() );
536 void IOServiceUserNotification::free( void )
541 OSObject
* _lastEntry
;
545 _lastEntry
= lastEntry
;
550 if( _pingMsg
&& _msgSize
)
551 IOFree( _pingMsg
, _msgSize
);
554 _lastEntry
->release();
560 bool IOServiceUserNotification::_handler( void * target
,
561 void * ref
, IOService
* newService
)
563 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
566 bool IOServiceUserNotification::handler( void * ref
,
567 IOService
* newService
)
571 ipc_port_t port
= NULL
;
572 bool sendPing
= false;
576 count
= newSet
->getCount();
577 if( count
< kMaxOutstanding
) {
579 newSet
->setObject( newService
);
580 if( (sendPing
= (armed
&& (0 == count
))))
586 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
587 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
590 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
591 pingMsg
->msgHdr
.msgh_local_port
= port
;
593 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
595 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
596 pingMsg
->msgHdr
.msgh_size
);
598 iokit_release_port( port
);
600 if( KERN_SUCCESS
!= kr
)
601 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
607 OSObject
* IOServiceUserNotification::getNextObject()
615 lastEntry
->release();
617 count
= newSet
->getCount();
619 result
= newSet
->getObject( count
- 1 );
621 newSet
->removeObject( count
- 1);
633 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
635 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
637 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
639 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
640 OSAsyncReference reference
, vm_size_t extraSize
)
643 extraSize
+= sizeof(IOServiceInterestContent
);
644 msgSize
= sizeof( PingMsg
) + extraSize
;
645 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
649 bzero( pingMsg
, msgSize
);
651 pingMsg
->msgHdr
.msgh_remote_port
= port
;
652 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
654 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
655 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
656 pingMsg
->msgHdr
.msgh_size
= msgSize
;
657 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
659 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
661 pingMsg
->ports
[0].name
= 0;
662 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
663 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
665 pingMsg
->notifyHeader
.size
= extraSize
;
666 pingMsg
->notifyHeader
.type
= type
;
667 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
669 return( super::init() );
672 void IOServiceMessageUserNotification::free( void )
682 if( _pingMsg
&& _msgSize
)
683 IOFree( _pingMsg
, _msgSize
);
686 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
687 UInt32 messageType
, IOService
* provider
,
688 void * argument
, vm_size_t argSize
)
690 return( ((IOServiceMessageUserNotification
*) target
)->handler(
691 ref
, messageType
, provider
, argument
, argSize
));
694 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
695 UInt32 messageType
, IOService
* provider
,
696 void * messageArgument
, vm_size_t argSize
)
699 ipc_port_t thisPort
, providerPort
;
700 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
701 pingMsg
->notifyHeader
.content
;
703 data
->messageType
= messageType
;
705 argSize
= sizeof( messageArgument
);
706 data
->messageArgument
[0] = messageArgument
;
708 if( argSize
> kIOUserNotifyMaxMessageSize
)
709 argSize
= kIOUserNotifyMaxMessageSize
;
710 bcopy( messageArgument
, data
->messageArgument
, argSize
);
712 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
713 + sizeof( IOServiceInterestContent
)
714 - sizeof( data
->messageArgument
)
717 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
718 pingMsg
->ports
[0].name
= providerPort
;
719 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
720 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
721 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
722 pingMsg
->msgHdr
.msgh_size
);
724 iokit_release_port( thisPort
);
726 iokit_release_port( providerPort
);
728 if( KERN_SUCCESS
!= kr
)
729 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
731 return( kIOReturnSuccess
);
734 OSObject
* IOServiceMessageUserNotification::getNextObject()
739 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
742 #define super IOService
743 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
745 void IOUserClient::initialize( void )
747 gIOObjectPortLock
= IOLockAlloc();
749 assert( gIOObjectPortLock
);
752 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
753 mach_port_t wakePort
,
754 void *callback
, void *refcon
)
756 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
757 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
758 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
761 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
762 const char * privilegeName
)
765 security_token_t token
;
766 mach_msg_type_number_t count
;
768 count
= TASK_SECURITY_TOKEN_COUNT
;
769 kr
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
,
770 (task_info_t
) &token
, &count
);
772 if (KERN_SUCCESS
!= kr
)
774 else if (!strcmp(privilegeName
, kIOClientPrivilegeAdministrator
))
776 if (0 != token
.val
[0])
777 kr
= kIOReturnNotPrivileged
;
779 else if (!strcmp(privilegeName
, kIOClientPrivilegeLocalUser
))
782 OSDictionary
* user
= 0;
784 if ((array
= OSDynamicCast(OSArray
,
785 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
787 for (unsigned int idx
= 0;
788 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
792 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
793 && (token
.val
[0] == num
->unsigned32BitValue()))
799 kr
= kIOReturnNotPrivileged
;
802 kr
= kIOReturnUnsupported
;
807 bool IOUserClient::initWithTask(task_t owningTask
,
811 if( getPropertyTable())
814 return super::init();
817 bool IOUserClient::initWithTask(task_t owningTask
,
820 OSDictionary
* properties
)
824 ok
= super::init( properties
);
825 ok
&= initWithTask( owningTask
, securityID
, type
);
830 void IOUserClient::free()
838 IOReturn
IOUserClient::clientDied( void )
840 return( clientClose());
843 IOReturn
IOUserClient::clientClose( void )
845 return( kIOReturnUnsupported
);
848 IOService
* IOUserClient::getService( void )
853 IOReturn
IOUserClient::registerNotificationPort(
854 mach_port_t
/* port */,
858 return( kIOReturnUnsupported
);
861 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
862 semaphore_t
* semaphore
)
864 return( kIOReturnUnsupported
);
867 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
869 return( kIOReturnUnsupported
);
872 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
873 IOOptionBits
* options
,
874 IOMemoryDescriptor
** memory
)
876 return( kIOReturnUnsupported
);
879 IOMemoryMap
* IOUserClient::mapClientMemory(
882 IOOptionBits mapFlags
,
883 IOVirtualAddress atAddress
)
886 IOOptionBits options
= 0;
887 IOMemoryDescriptor
* memory
;
888 IOMemoryMap
* map
= 0;
890 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
892 if( memory
&& (kIOReturnSuccess
== err
)) {
894 options
= (options
& ~kIOMapUserOptionsMask
)
895 | (mapFlags
& kIOMapUserOptionsMask
);
896 map
= memory
->map( task
, atAddress
, options
);
903 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
904 OSObject
*obj
, io_object_t
*clientObj
)
906 mach_port_name_t name
;
908 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
911 *(mach_port_name_t
*)clientObj
= name
;
912 return kIOReturnSuccess
;
915 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
920 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
925 IOExternalMethod
* IOUserClient::
926 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
928 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
931 *targetP
= (IOService
*) method
->object
;
936 IOExternalAsyncMethod
* IOUserClient::
937 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
939 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
942 *targetP
= (IOService
*) method
->object
;
947 IOExternalTrap
* IOUserClient::
948 getExternalTrapForIndex(UInt32 index
)
953 IOExternalTrap
* IOUserClient::
954 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
956 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
959 *targetP
= trap
->object
;
965 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
966 IOReturn result
, void *args
[], UInt32 numArgs
)
969 mach_msg_header_t msgHdr
;
970 OSNotificationHeader notifyHdr
;
971 IOAsyncCompletionContent asyncContent
;
972 void * args
[kMaxAsyncArgs
];
975 mach_port_t replyPort
;
978 // If no reply port, do nothing.
979 replyPort
= (mach_port_t
) reference
[0];
980 if(replyPort
== MACH_PORT_NULL
)
981 return kIOReturnSuccess
;
983 if(numArgs
> kMaxAsyncArgs
)
984 return kIOReturnMessageTooLarge
;
985 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
987 replyMsg
.msgHdr
.msgh_size
=
988 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
989 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
990 replyMsg
.msgHdr
.msgh_local_port
= 0;
991 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
993 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
994 + numArgs
*sizeof(void *);
995 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
996 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
998 replyMsg
.asyncContent
.result
= result
;
1000 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
1001 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
1002 replyMsg
.msgHdr
.msgh_size
);
1003 if( KERN_SUCCESS
!= kr
)
1004 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
1008 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1012 #define CHECK(cls,obj,out) \
1014 if( !(out = OSDynamicCast( cls, obj))) \
1015 return( kIOReturnBadArgument )
1017 /* Routine io_object_get_class */
1018 kern_return_t
is_io_object_get_class(
1020 io_name_t className
)
1022 const OSMetaClass
* my_obj
= NULL
;
1025 return( kIOReturnBadArgument
);
1027 my_obj
= object
->getMetaClass();
1029 return (kIOReturnNotFound
);
1032 strcpy( className
, my_obj
->getClassName());
1033 return( kIOReturnSuccess
);
1036 /* Routine io_object_get_superclass */
1037 kern_return_t
is_io_object_get_superclass(
1038 mach_port_t master_port
,
1040 io_name_t class_name
)
1042 const OSMetaClass
* my_obj
= NULL
;
1043 const OSMetaClass
* superclass
= NULL
;
1044 const OSSymbol
*my_name
= NULL
;
1045 const char *my_cstr
= NULL
;
1047 if (!obj_name
|| !class_name
)
1048 return (kIOReturnBadArgument
);
1050 if( master_port
!= master_device_port
)
1051 return( kIOReturnNotPrivileged
);
1053 my_name
= OSSymbol::withCString(obj_name
);
1056 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1060 superclass
= my_obj
->getSuperClass();
1064 return( kIOReturnNotFound
);
1067 my_cstr
= superclass
->getClassName();
1070 strncpy(class_name
, my_cstr
, sizeof(io_name_t
)-1);
1071 return( kIOReturnSuccess
);
1073 return (kIOReturnNotFound
);
1076 /* Routine io_object_get_bundle_identifier */
1077 kern_return_t
is_io_object_get_bundle_identifier(
1078 mach_port_t master_port
,
1080 io_name_t bundle_name
)
1082 const OSMetaClass
* my_obj
= NULL
;
1083 const OSSymbol
*my_name
= NULL
;
1084 const OSSymbol
*identifier
= NULL
;
1085 const char *my_cstr
= NULL
;
1087 if (!obj_name
|| !bundle_name
)
1088 return (kIOReturnBadArgument
);
1090 if( master_port
!= master_device_port
)
1091 return( kIOReturnNotPrivileged
);
1093 my_name
= OSSymbol::withCString(obj_name
);
1096 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1101 identifier
= my_obj
->getKmodName();
1104 return( kIOReturnNotFound
);
1107 my_cstr
= identifier
->getCStringNoCopy();
1109 strncpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
)-1);
1110 return( kIOReturnSuccess
);
1113 return (kIOReturnBadArgument
);
1116 /* Routine io_object_conforms_to */
1117 kern_return_t
is_io_object_conforms_to(
1119 io_name_t className
,
1120 boolean_t
*conforms
)
1123 return( kIOReturnBadArgument
);
1125 *conforms
= (0 != object
->metaCast( className
));
1126 return( kIOReturnSuccess
);
1129 /* Routine io_object_get_retain_count */
1130 kern_return_t
is_io_object_get_retain_count(
1135 return( kIOReturnBadArgument
);
1137 *retainCount
= object
->getRetainCount();
1138 return( kIOReturnSuccess
);
1141 /* Routine io_iterator_next */
1142 kern_return_t
is_io_iterator_next(
1143 io_object_t iterator
,
1144 io_object_t
*object
)
1148 CHECK( OSIterator
, iterator
, iter
);
1150 obj
= iter
->getNextObject();
1154 return( kIOReturnSuccess
);
1156 return( kIOReturnNoDevice
);
1159 /* Routine io_iterator_reset */
1160 kern_return_t
is_io_iterator_reset(
1161 io_object_t iterator
)
1163 CHECK( OSIterator
, iterator
, iter
);
1167 return( kIOReturnSuccess
);
1170 /* Routine io_iterator_is_valid */
1171 kern_return_t
is_io_iterator_is_valid(
1172 io_object_t iterator
,
1173 boolean_t
*is_valid
)
1175 CHECK( OSIterator
, iterator
, iter
);
1177 *is_valid
= iter
->isValid();
1179 return( kIOReturnSuccess
);
1182 /* Routine io_service_match_property_table */
1183 kern_return_t
is_io_service_match_property_table(
1184 io_service_t _service
,
1185 io_string_t matching
,
1186 boolean_t
*matches
)
1188 CHECK( IOService
, _service
, service
);
1192 OSDictionary
* dict
;
1194 obj
= OSUnserializeXML( matching
);
1196 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1197 *matches
= service
->passiveMatch( dict
);
1198 kr
= kIOReturnSuccess
;
1200 kr
= kIOReturnBadArgument
;
1208 /* Routine io_service_match_property_table_ool */
1209 kern_return_t
is_io_service_match_property_table_ool(
1210 io_object_t service
,
1211 io_buf_ptr_t matching
,
1212 mach_msg_type_number_t matchingCnt
,
1214 boolean_t
*matches
)
1218 vm_map_offset_t map_data
;
1220 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1221 data
= CAST_DOWN(vm_offset_t
, map_data
);
1223 if( KERN_SUCCESS
== kr
) {
1224 // must return success after vm_map_copyout() succeeds
1225 *result
= is_io_service_match_property_table( service
,
1226 (char *) data
, matches
);
1227 vm_deallocate( kernel_map
, data
, matchingCnt
);
1233 /* Routine io_service_get_matching_services */
1234 kern_return_t
is_io_service_get_matching_services(
1235 mach_port_t master_port
,
1236 io_string_t matching
,
1237 io_iterator_t
*existing
)
1241 OSDictionary
* dict
;
1243 if( master_port
!= master_device_port
)
1244 return( kIOReturnNotPrivileged
);
1246 obj
= OSUnserializeXML( matching
);
1248 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1249 *existing
= IOService::getMatchingServices( dict
);
1250 kr
= kIOReturnSuccess
;
1252 kr
= kIOReturnBadArgument
;
1260 /* Routine io_service_get_matching_services_ool */
1261 kern_return_t
is_io_service_get_matching_services_ool(
1262 mach_port_t master_port
,
1263 io_buf_ptr_t matching
,
1264 mach_msg_type_number_t matchingCnt
,
1266 io_object_t
*existing
)
1270 vm_map_offset_t map_data
;
1272 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1273 data
= CAST_DOWN(vm_offset_t
, map_data
);
1275 if( KERN_SUCCESS
== kr
) {
1276 // must return success after vm_map_copyout() succeeds
1277 *result
= is_io_service_get_matching_services( master_port
,
1278 (char *) data
, existing
);
1279 vm_deallocate( kernel_map
, data
, matchingCnt
);
1285 /* Routine io_service_add_notification */
1286 kern_return_t
is_io_service_add_notification(
1287 mach_port_t master_port
,
1288 io_name_t notification_type
,
1289 io_string_t matching
,
1291 io_async_ref_t reference
,
1292 mach_msg_type_number_t referenceCnt
,
1293 io_object_t
* notification
)
1295 IOServiceUserNotification
* userNotify
= 0;
1296 IONotifier
* notify
= 0;
1297 const OSSymbol
* sym
;
1298 OSDictionary
* dict
;
1300 unsigned long int userMsgType
;
1303 if( master_port
!= master_device_port
)
1304 return( kIOReturnNotPrivileged
);
1307 err
= kIOReturnNoResources
;
1309 if( !(sym
= OSSymbol::withCString( notification_type
)))
1310 err
= kIOReturnNoResources
;
1312 if( !(dict
= OSDynamicCast( OSDictionary
,
1313 OSUnserializeXML( matching
)))) {
1314 err
= kIOReturnBadArgument
;
1318 if( (sym
== gIOPublishNotification
)
1319 || (sym
== gIOFirstPublishNotification
))
1320 userMsgType
= kIOServicePublishNotificationType
;
1321 else if( (sym
== gIOMatchedNotification
)
1322 || (sym
== gIOFirstMatchNotification
))
1323 userMsgType
= kIOServiceMatchedNotificationType
;
1324 else if( sym
== gIOTerminatedNotification
)
1325 userMsgType
= kIOServiceTerminatedNotificationType
;
1327 userMsgType
= kLastIOKitNotificationType
;
1329 userNotify
= new IOServiceUserNotification
;
1331 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1333 userNotify
->release();
1339 notify
= IOService::addNotification( sym
, dict
,
1340 &userNotify
->_handler
, userNotify
);
1343 *notification
= userNotify
;
1344 userNotify
->setNotification( notify
);
1345 err
= kIOReturnSuccess
;
1347 err
= kIOReturnUnsupported
;
1359 /* Routine io_service_add_notification_ool */
1360 kern_return_t
is_io_service_add_notification_ool(
1361 mach_port_t master_port
,
1362 io_name_t notification_type
,
1363 io_buf_ptr_t matching
,
1364 mach_msg_type_number_t matchingCnt
,
1365 mach_port_t wake_port
,
1366 io_async_ref_t reference
,
1367 mach_msg_type_number_t referenceCnt
,
1369 io_object_t
*notification
)
1373 vm_map_offset_t map_data
;
1375 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1376 data
= CAST_DOWN(vm_offset_t
, map_data
);
1378 if( KERN_SUCCESS
== kr
) {
1379 // must return success after vm_map_copyout() succeeds
1380 *result
= is_io_service_add_notification( master_port
, notification_type
,
1381 (char *) data
, wake_port
, reference
, referenceCnt
, notification
);
1382 vm_deallocate( kernel_map
, data
, matchingCnt
);
1389 /* Routine io_service_add_notification_old */
1390 kern_return_t
is_io_service_add_notification_old(
1391 mach_port_t master_port
,
1392 io_name_t notification_type
,
1393 io_string_t matching
,
1396 io_object_t
* notification
)
1398 return( is_io_service_add_notification( master_port
, notification_type
,
1399 matching
, port
, &ref
, 1, notification
));
1402 /* Routine io_service_add_message_notification */
1403 kern_return_t
is_io_service_add_interest_notification(
1404 io_object_t _service
,
1405 io_name_t type_of_interest
,
1407 io_async_ref_t reference
,
1408 mach_msg_type_number_t referenceCnt
,
1409 io_object_t
* notification
)
1412 IOServiceMessageUserNotification
* userNotify
= 0;
1413 IONotifier
* notify
= 0;
1414 const OSSymbol
* sym
;
1417 CHECK( IOService
, _service
, service
);
1419 err
= kIOReturnNoResources
;
1420 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1422 userNotify
= new IOServiceMessageUserNotification
;
1424 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1425 reference
, kIOUserNotifyMaxMessageSize
)) {
1426 userNotify
->release();
1432 notify
= service
->registerInterest( sym
,
1433 &userNotify
->_handler
, userNotify
);
1435 *notification
= userNotify
;
1436 userNotify
->setNotification( notify
);
1437 err
= kIOReturnSuccess
;
1439 err
= kIOReturnUnsupported
;
1448 /* Routine io_service_acknowledge_notification */
1449 kern_return_t
is_io_service_acknowledge_notification(
1450 io_object_t _service
,
1451 natural_t notify_ref
,
1452 natural_t response
)
1454 CHECK( IOService
, _service
, service
);
1456 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1457 (IOOptionBits
) response
));
1461 /* Routine io_connect_get_semaphore */
1462 kern_return_t
is_io_connect_get_notification_semaphore(
1463 io_connect_t connection
,
1464 natural_t notification_type
,
1465 semaphore_t
*semaphore
)
1467 CHECK( IOUserClient
, connection
, client
);
1469 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1473 /* Routine io_registry_get_root_entry */
1474 kern_return_t
is_io_registry_get_root_entry(
1475 mach_port_t master_port
,
1478 IORegistryEntry
* entry
;
1480 if( master_port
!= master_device_port
)
1481 return( kIOReturnNotPrivileged
);
1483 entry
= IORegistryEntry::getRegistryRoot();
1488 return( kIOReturnSuccess
);
1491 /* Routine io_registry_create_iterator */
1492 kern_return_t
is_io_registry_create_iterator(
1493 mach_port_t master_port
,
1496 io_object_t
*iterator
)
1498 if( master_port
!= master_device_port
)
1499 return( kIOReturnNotPrivileged
);
1501 *iterator
= IORegistryIterator::iterateOver(
1502 IORegistryEntry::getPlane( plane
), options
);
1504 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1507 /* Routine io_registry_entry_create_iterator */
1508 kern_return_t
is_io_registry_entry_create_iterator(
1509 io_object_t registry_entry
,
1512 io_object_t
*iterator
)
1514 CHECK( IORegistryEntry
, registry_entry
, entry
);
1516 *iterator
= IORegistryIterator::iterateOver( entry
,
1517 IORegistryEntry::getPlane( plane
), options
);
1519 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1522 /* Routine io_registry_iterator_enter */
1523 kern_return_t
is_io_registry_iterator_enter_entry(
1524 io_object_t iterator
)
1526 CHECK( IORegistryIterator
, iterator
, iter
);
1530 return( kIOReturnSuccess
);
1533 /* Routine io_registry_iterator_exit */
1534 kern_return_t
is_io_registry_iterator_exit_entry(
1535 io_object_t iterator
)
1539 CHECK( IORegistryIterator
, iterator
, iter
);
1541 didIt
= iter
->exitEntry();
1543 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1546 /* Routine io_registry_entry_from_path */
1547 kern_return_t
is_io_registry_entry_from_path(
1548 mach_port_t master_port
,
1550 io_object_t
*registry_entry
)
1552 IORegistryEntry
* entry
;
1554 if( master_port
!= master_device_port
)
1555 return( kIOReturnNotPrivileged
);
1557 entry
= IORegistryEntry::fromPath( path
);
1559 *registry_entry
= entry
;
1561 return( kIOReturnSuccess
);
1564 /* Routine io_registry_entry_in_plane */
1565 kern_return_t
is_io_registry_entry_in_plane(
1566 io_object_t registry_entry
,
1568 boolean_t
*inPlane
)
1570 CHECK( IORegistryEntry
, registry_entry
, entry
);
1572 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1574 return( kIOReturnSuccess
);
1578 /* Routine io_registry_entry_get_path */
1579 kern_return_t
is_io_registry_entry_get_path(
1580 io_object_t registry_entry
,
1585 CHECK( IORegistryEntry
, registry_entry
, entry
);
1587 length
= sizeof( io_string_t
);
1588 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1589 return( kIOReturnSuccess
);
1591 return( kIOReturnBadArgument
);
1595 /* Routine io_registry_entry_get_name */
1596 kern_return_t
is_io_registry_entry_get_name(
1597 io_object_t registry_entry
,
1600 CHECK( IORegistryEntry
, registry_entry
, entry
);
1602 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1604 return( kIOReturnSuccess
);
1607 /* Routine io_registry_entry_get_name_in_plane */
1608 kern_return_t
is_io_registry_entry_get_name_in_plane(
1609 io_object_t registry_entry
,
1610 io_name_t planeName
,
1613 const IORegistryPlane
* plane
;
1614 CHECK( IORegistryEntry
, registry_entry
, entry
);
1617 plane
= IORegistryEntry::getPlane( planeName
);
1621 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1623 return( kIOReturnSuccess
);
1626 /* Routine io_registry_entry_get_location_in_plane */
1627 kern_return_t
is_io_registry_entry_get_location_in_plane(
1628 io_object_t registry_entry
,
1629 io_name_t planeName
,
1630 io_name_t location
)
1632 const IORegistryPlane
* plane
;
1633 CHECK( IORegistryEntry
, registry_entry
, entry
);
1636 plane
= IORegistryEntry::getPlane( planeName
);
1640 const char * cstr
= entry
->getLocation( plane
);
1643 strncpy( location
, cstr
, sizeof( io_name_t
));
1644 return( kIOReturnSuccess
);
1646 return( kIOReturnNotFound
);
1649 // Create a vm_map_copy_t or kalloc'ed data for memory
1650 // to be copied out. ipc will free after the copyout.
1652 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1653 io_buf_ptr_t
* buf
)
1658 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1659 false /* src_destroy */, ©
);
1661 assert( err
== KERN_SUCCESS
);
1662 if( err
== KERN_SUCCESS
)
1663 *buf
= (char *) copy
;
1668 /* Routine io_registry_entry_get_property */
1669 kern_return_t
is_io_registry_entry_get_property_bytes(
1670 io_object_t registry_entry
,
1671 io_name_t property_name
,
1672 io_scalar_inband_t buf
,
1673 mach_msg_type_number_t
*dataCnt
)
1681 unsigned int len
= 0;
1682 const void * bytes
= 0;
1683 IOReturn ret
= kIOReturnSuccess
;
1685 CHECK( IORegistryEntry
, registry_entry
, entry
);
1687 obj
= entry
->copyProperty(property_name
);
1689 return( kIOReturnNoResources
);
1691 // One day OSData will be a common container base class
1693 if( (data
= OSDynamicCast( OSData
, obj
))) {
1694 len
= data
->getLength();
1695 bytes
= data
->getBytesNoCopy();
1697 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1698 len
= str
->getLength() + 1;
1699 bytes
= str
->getCStringNoCopy();
1701 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1702 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1703 bytes
= boo
->isTrue() ? "Yes" : "No";
1705 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1706 offsetBytes
= off
->unsigned64BitValue();
1707 len
= off
->numberOfBytes();
1708 bytes
= &offsetBytes
;
1709 #ifdef __BIG_ENDIAN__
1710 bytes
= (const void *)
1711 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1715 ret
= kIOReturnBadArgument
;
1719 ret
= kIOReturnIPCError
;
1722 bcopy( bytes
, buf
, len
);
1730 /* Routine io_registry_entry_get_property */
1731 kern_return_t
is_io_registry_entry_get_property(
1732 io_object_t registry_entry
,
1733 io_name_t property_name
,
1734 io_buf_ptr_t
*properties
,
1735 mach_msg_type_number_t
*propertiesCnt
)
1741 CHECK( IORegistryEntry
, registry_entry
, entry
);
1743 obj
= entry
->copyProperty(property_name
);
1745 return( kIOReturnNotFound
);
1747 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1750 return( kIOReturnNoMemory
);
1754 if( obj
->serialize( s
)) {
1755 len
= s
->getLength();
1756 *propertiesCnt
= len
;
1757 err
= copyoutkdata( s
->text(), len
, properties
);
1760 err
= kIOReturnUnsupported
;
1768 /* Routine io_registry_entry_get_property_recursively */
1769 kern_return_t
is_io_registry_entry_get_property_recursively(
1770 io_object_t registry_entry
,
1772 io_name_t property_name
,
1774 io_buf_ptr_t
*properties
,
1775 mach_msg_type_number_t
*propertiesCnt
)
1781 CHECK( IORegistryEntry
, registry_entry
, entry
);
1783 obj
= entry
->copyProperty( property_name
,
1784 IORegistryEntry::getPlane( plane
), options
);
1786 return( kIOReturnNotFound
);
1788 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1791 return( kIOReturnNoMemory
);
1796 if( obj
->serialize( s
)) {
1797 len
= s
->getLength();
1798 *propertiesCnt
= len
;
1799 err
= copyoutkdata( s
->text(), len
, properties
);
1802 err
= kIOReturnUnsupported
;
1810 /* Routine io_registry_entry_get_properties */
1811 kern_return_t
is_io_registry_entry_get_properties(
1812 io_object_t registry_entry
,
1813 io_buf_ptr_t
*properties
,
1814 mach_msg_type_number_t
*propertiesCnt
)
1819 CHECK( IORegistryEntry
, registry_entry
, entry
);
1821 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1823 return( kIOReturnNoMemory
);
1827 if( entry
->serializeProperties( s
)) {
1828 len
= s
->getLength();
1829 *propertiesCnt
= len
;
1830 err
= copyoutkdata( s
->text(), len
, properties
);
1833 err
= kIOReturnUnsupported
;
1840 /* Routine io_registry_entry_set_properties */
1841 kern_return_t is_io_registry_entry_set_properties
1843 io_object_t registry_entry
,
1844 io_buf_ptr_t properties
,
1845 mach_msg_type_number_t propertiesCnt
,
1852 vm_map_offset_t map_data
;
1854 CHECK( IORegistryEntry
, registry_entry
, entry
);
1856 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
1857 data
= CAST_DOWN(vm_offset_t
, map_data
);
1859 if( KERN_SUCCESS
== err
) {
1861 // must return success after vm_map_copyout() succeeds
1862 obj
= OSUnserializeXML( (const char *) data
);
1863 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1866 res
= entry
->setProperties( obj
);
1869 res
= kIOReturnBadArgument
;
1877 /* Routine io_registry_entry_get_child_iterator */
1878 kern_return_t
is_io_registry_entry_get_child_iterator(
1879 io_object_t registry_entry
,
1881 io_object_t
*iterator
)
1883 CHECK( IORegistryEntry
, registry_entry
, entry
);
1885 *iterator
= entry
->getChildIterator(
1886 IORegistryEntry::getPlane( plane
));
1888 return( kIOReturnSuccess
);
1891 /* Routine io_registry_entry_get_parent_iterator */
1892 kern_return_t
is_io_registry_entry_get_parent_iterator(
1893 io_object_t registry_entry
,
1895 io_object_t
*iterator
)
1897 CHECK( IORegistryEntry
, registry_entry
, entry
);
1899 *iterator
= entry
->getParentIterator(
1900 IORegistryEntry::getPlane( plane
));
1902 return( kIOReturnSuccess
);
1905 /* Routine io_service_get_busy_state */
1906 kern_return_t
is_io_service_get_busy_state(
1907 io_object_t _service
,
1910 CHECK( IOService
, _service
, service
);
1912 *busyState
= service
->getBusyState();
1914 return( kIOReturnSuccess
);
1917 /* Routine io_service_get_state */
1918 kern_return_t
is_io_service_get_state(
1919 io_object_t _service
,
1922 CHECK( IOService
, _service
, service
);
1924 *state
= service
->getState();
1926 return( kIOReturnSuccess
);
1929 /* Routine io_service_wait_quiet */
1930 kern_return_t
is_io_service_wait_quiet(
1931 io_object_t _service
,
1932 mach_timespec_t wait_time
)
1934 CHECK( IOService
, _service
, service
);
1936 return( service
->waitQuiet( &wait_time
));
1939 /* Routine io_service_request_probe */
1940 kern_return_t
is_io_service_request_probe(
1941 io_object_t _service
,
1944 CHECK( IOService
, _service
, service
);
1946 return( service
->requestProbe( options
));
1950 /* Routine io_service_open */
1951 kern_return_t
is_io_service_open(
1952 io_object_t _service
,
1955 io_object_t
*connection
)
1957 IOUserClient
* client
;
1960 CHECK( IOService
, _service
, service
);
1962 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1963 connect_type
, &client
);
1965 if( err
== kIOReturnSuccess
) {
1966 assert( OSDynamicCast(IOUserClient
, client
) );
1967 *connection
= client
;
1973 /* Routine io_service_close */
1974 kern_return_t
is_io_service_close(
1975 io_object_t connection
)
1978 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
1979 return( kIOReturnSuccess
);
1981 CHECK( IOUserClient
, connection
, client
);
1983 client
->clientClose();
1985 return( kIOReturnSuccess
);
1988 /* Routine io_connect_get_service */
1989 kern_return_t
is_io_connect_get_service(
1990 io_object_t connection
,
1991 io_object_t
*service
)
1993 IOService
* theService
;
1995 CHECK( IOUserClient
, connection
, client
);
1997 theService
= client
->getService();
1999 theService
->retain();
2001 *service
= theService
;
2003 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2006 /* Routine io_connect_set_notification_port */
2007 kern_return_t
is_io_connect_set_notification_port(
2008 io_object_t connection
,
2009 int notification_type
,
2013 CHECK( IOUserClient
, connection
, client
);
2015 return( client
->registerNotificationPort( port
, notification_type
,
2019 kern_return_t
is_io_connect_map_memory(
2020 io_object_t connect
,
2023 vm_address_t
* mapAddr
,
2024 vm_size_t
* mapSize
,
2030 CHECK( IOUserClient
, connect
, client
);
2032 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
2035 *mapAddr
= map
->getVirtualAddress();
2037 *mapSize
= map
->getLength();
2039 if( task
!= current_task()) {
2040 // push a name out to the task owning the map,
2041 // so we can clean up maps
2043 mach_port_name_t name
=
2045 IOMachPort::makeSendRightForTask(
2046 task
, map
, IKOT_IOKIT_OBJECT
);
2050 // keep it with the user client
2051 IOLockLock( gIOObjectPortLock
);
2052 if( 0 == client
->mappings
)
2053 client
->mappings
= OSSet::withCapacity(2);
2054 if( client
->mappings
)
2055 client
->mappings
->setObject( map
);
2056 IOLockUnlock( gIOObjectPortLock
);
2059 err
= kIOReturnSuccess
;
2062 err
= kIOReturnBadArgument
;
2067 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2070 IOMemoryMap
* map
= 0;
2072 IOLockLock(gIOObjectPortLock
);
2074 iter
= OSCollectionIterator::withCollection(mappings
);
2077 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2079 if(mem
== map
->getMemoryDescriptor())
2082 mappings
->removeObject(map
);
2089 IOLockUnlock(gIOObjectPortLock
);
2094 kern_return_t
is_io_connect_unmap_memory(
2095 io_object_t connect
,
2098 vm_address_t mapAddr
)
2101 IOOptionBits options
= 0;
2102 IOMemoryDescriptor
* memory
;
2105 CHECK( IOUserClient
, connect
, client
);
2107 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
2109 if( memory
&& (kIOReturnSuccess
== err
)) {
2111 options
= (options
& ~kIOMapUserOptionsMask
)
2112 | kIOMapAnywhere
| kIOMapReference
;
2114 map
= memory
->map( task
, mapAddr
, options
);
2118 IOLockLock( gIOObjectPortLock
);
2119 if( client
->mappings
)
2120 client
->mappings
->removeObject( map
);
2121 IOLockUnlock( gIOObjectPortLock
);
2123 mach_port_name_t name
= 0;
2124 if (task
!= current_task())
2125 name
= IOMachPort::makeSendRightForTask( task
, map
, IKOT_IOKIT_OBJECT
);
2129 err
= iokit_mod_send_right( task
, name
, -2 );
2130 err
= kIOReturnSuccess
;
2133 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2134 if (task
== current_task())
2138 err
= kIOReturnBadArgument
;
2145 /* Routine io_connect_add_client */
2146 kern_return_t
is_io_connect_add_client(
2147 io_object_t connection
,
2148 io_object_t connect_to
)
2150 CHECK( IOUserClient
, connection
, client
);
2151 CHECK( IOUserClient
, connect_to
, to
);
2153 return( client
->connectClient( to
) );
2157 /* Routine io_connect_set_properties */
2158 kern_return_t
is_io_connect_set_properties(
2159 io_object_t connection
,
2160 io_buf_ptr_t properties
,
2161 mach_msg_type_number_t propertiesCnt
,
2164 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2168 /* Routine io_connect_method_scalarI_scalarO */
2169 kern_return_t
is_io_connect_method_scalarI_scalarO(
2170 io_object_t connect
,
2173 IOByteCount inputCount
,
2175 IOByteCount
* outputCount
)
2178 IOExternalMethod
* method
;
2182 CHECK( IOUserClient
, connect
, client
);
2183 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
2185 err
= kIOReturnBadArgument
;
2186 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2188 if( inputCount
!= method
->count0
)
2190 if( *outputCount
!= method
->count1
)
2193 func
= method
->func
;
2195 switch( inputCount
) {
2198 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2199 input
[3], input
[4], input
[5] );
2202 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2207 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2209 &output
[0], &output
[1] );
2212 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2213 &output
[0], &output
[1], &output
[2] );
2216 err
= (object
->*func
)( input
[0], input
[1],
2217 &output
[0], &output
[1], &output
[2],
2221 err
= (object
->*func
)( input
[0],
2222 &output
[0], &output
[1], &output
[2],
2223 &output
[3], &output
[4] );
2226 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
2227 &output
[3], &output
[4], &output
[5] );
2231 IOLog("%s: Bad method table\n", client
->getName());
2236 err
= kIOReturnUnsupported
;
2241 /* Routine io_connect_method_scalarI_structureO */
2242 kern_return_t
is_io_connect_method_scalarI_structureO(
2243 io_object_t connect
,
2246 IOByteCount inputCount
,
2248 IOByteCount
* outputCount
)
2251 IOExternalMethod
* method
;
2255 CHECK( IOUserClient
, connect
, client
);
2257 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2259 err
= kIOReturnBadArgument
;
2260 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2262 if( inputCount
!= method
->count0
)
2264 if( (0xffffffff != method
->count1
)
2265 && (*outputCount
!= method
->count1
))
2268 func
= method
->func
;
2270 switch( inputCount
) {
2273 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2278 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2280 output
, (void *)outputCount
);
2283 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2284 output
, (void *)outputCount
, 0 );
2287 err
= (object
->*func
)( input
[0], input
[1],
2288 output
, (void *)outputCount
, 0, 0 );
2291 err
= (object
->*func
)( input
[0],
2292 output
, (void *)outputCount
, 0, 0, 0 );
2295 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
2299 IOLog("%s: Bad method table\n", client
->getName());
2304 err
= kIOReturnUnsupported
;
2309 /* Routine io_connect_method_scalarI_structureI */
2310 kern_return_t
is_io_connect_method_scalarI_structureI(
2311 io_connect_t connect
,
2314 IOByteCount inputCount
,
2315 UInt8
* inputStruct
,
2316 IOByteCount inputStructCount
)
2319 IOExternalMethod
* method
;
2323 CHECK( IOUserClient
, connect
, client
);
2325 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2327 err
= kIOReturnBadArgument
;
2328 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2330 if( (0xffffffff != method
->count0
)
2331 && (inputCount
!= method
->count0
))
2333 if( (0xffffffff != method
->count1
)
2334 && (inputStructCount
!= method
->count1
))
2337 func
= method
->func
;
2339 switch( inputCount
) {
2342 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2347 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2349 inputStruct
, (void *)inputStructCount
);
2352 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2353 inputStruct
, (void *)inputStructCount
,
2357 err
= (object
->*func
)( input
[0], input
[1],
2358 inputStruct
, (void *)inputStructCount
,
2362 err
= (object
->*func
)( input
[0],
2363 inputStruct
, (void *)inputStructCount
,
2367 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
2372 IOLog("%s: Bad method table\n", client
->getName());
2377 err
= kIOReturnUnsupported
;
2382 /* Routine io_connect_method_structureI_structureO */
2383 kern_return_t
is_io_connect_method_structureI_structureO(
2384 io_object_t connect
,
2387 IOByteCount inputCount
,
2389 IOByteCount
* outputCount
)
2392 IOExternalMethod
* method
;
2396 CHECK( IOUserClient
, connect
, client
);
2398 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2400 err
= kIOReturnBadArgument
;
2401 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2403 if( (0xffffffff != method
->count0
)
2404 && (inputCount
!= method
->count0
))
2406 if( (0xffffffff != method
->count1
)
2407 && (*outputCount
!= method
->count1
))
2410 func
= method
->func
;
2412 if( method
->count1
) {
2413 if( method
->count0
) {
2414 err
= (object
->*func
)( input
, output
,
2415 (void *)inputCount
, outputCount
, 0, 0 );
2417 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2420 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2426 err
= kIOReturnUnsupported
;
2431 kern_return_t
is_io_async_method_scalarI_scalarO(
2432 io_object_t connect
,
2433 mach_port_t wakePort
,
2434 io_async_ref_t reference
,
2435 mach_msg_type_number_t referenceCnt
,
2438 IOByteCount inputCount
,
2440 IOByteCount
* outputCount
)
2443 IOExternalAsyncMethod
*method
;
2447 CHECK( IOUserClient
, connect
, client
);
2448 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2450 err
= kIOReturnBadArgument
;
2451 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2453 if( inputCount
!= method
->count0
)
2455 if( *outputCount
!= method
->count1
)
2458 reference
[0] = (natural_t
) wakePort
;
2459 func
= method
->func
;
2461 switch( inputCount
) {
2464 err
= (object
->*func
)( reference
,
2465 input
[0], input
[1], input
[2],
2466 input
[3], input
[4], input
[5] );
2469 err
= (object
->*func
)( reference
,
2470 input
[0], input
[1], input
[2],
2475 err
= (object
->*func
)( reference
,
2476 input
[0], input
[1], input
[2],
2478 &output
[0], &output
[1] );
2481 err
= (object
->*func
)( reference
,
2482 input
[0], input
[1], input
[2],
2483 &output
[0], &output
[1], &output
[2] );
2486 err
= (object
->*func
)( reference
,
2488 &output
[0], &output
[1], &output
[2],
2492 err
= (object
->*func
)( reference
,
2494 &output
[0], &output
[1], &output
[2],
2495 &output
[3], &output
[4] );
2498 err
= (object
->*func
)( reference
,
2499 &output
[0], &output
[1], &output
[2],
2500 &output
[3], &output
[4], &output
[5] );
2504 IOLog("%s: Bad method table\n", client
->getName());
2509 err
= kIOReturnUnsupported
;
2514 kern_return_t
is_io_async_method_scalarI_structureO(
2515 io_object_t connect
,
2516 mach_port_t wakePort
,
2517 io_async_ref_t reference
,
2518 mach_msg_type_number_t referenceCnt
,
2521 IOByteCount inputCount
,
2523 IOByteCount
* outputCount
)
2526 IOExternalAsyncMethod
*method
;
2530 CHECK( IOUserClient
, connect
, client
);
2532 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2534 err
= kIOReturnBadArgument
;
2535 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2537 if( inputCount
!= method
->count0
)
2539 if( (0xffffffff != method
->count1
)
2540 && (*outputCount
!= method
->count1
))
2543 reference
[0] = (natural_t
) wakePort
;
2544 func
= method
->func
;
2546 switch( inputCount
) {
2549 err
= (object
->*func
)( reference
,
2550 input
[0], input
[1], input
[2],
2555 err
= (object
->*func
)( reference
,
2556 input
[0], input
[1], input
[2],
2558 output
, (void *)outputCount
);
2561 err
= (object
->*func
)( reference
,
2562 input
[0], input
[1], input
[2],
2563 output
, (void *)outputCount
, 0 );
2566 err
= (object
->*func
)( reference
,
2568 output
, (void *)outputCount
, 0, 0 );
2571 err
= (object
->*func
)( reference
,
2573 output
, (void *)outputCount
, 0, 0, 0 );
2576 err
= (object
->*func
)( reference
,
2577 output
, (void *)outputCount
, 0, 0, 0, 0 );
2581 IOLog("%s: Bad method table\n", client
->getName());
2586 err
= kIOReturnUnsupported
;
2591 kern_return_t
is_io_async_method_scalarI_structureI(
2592 io_connect_t connect
,
2593 mach_port_t wakePort
,
2594 io_async_ref_t reference
,
2595 mach_msg_type_number_t referenceCnt
,
2598 IOByteCount inputCount
,
2599 UInt8
* inputStruct
,
2600 IOByteCount inputStructCount
)
2603 IOExternalAsyncMethod
*method
;
2607 CHECK( IOUserClient
, connect
, client
);
2609 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2611 err
= kIOReturnBadArgument
;
2612 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2614 if( (0xffffffff != method
->count0
)
2615 && (inputCount
!= method
->count0
))
2617 if( (0xffffffff != method
->count1
)
2618 && (inputStructCount
!= method
->count1
))
2621 reference
[0] = (natural_t
) wakePort
;
2622 func
= method
->func
;
2624 switch( inputCount
) {
2627 err
= (object
->*func
)( reference
,
2628 input
[0], input
[1], input
[2],
2633 err
= (object
->*func
)( reference
,
2634 input
[0], input
[1], input
[2],
2636 inputStruct
, (void *)inputStructCount
);
2639 err
= (object
->*func
)( reference
,
2640 input
[0], input
[1], input
[2],
2641 inputStruct
, (void *)inputStructCount
,
2645 err
= (object
->*func
)( reference
,
2647 inputStruct
, (void *)inputStructCount
,
2651 err
= (object
->*func
)( reference
,
2653 inputStruct
, (void *)inputStructCount
,
2657 err
= (object
->*func
)( reference
,
2658 inputStruct
, (void *)inputStructCount
,
2663 IOLog("%s: Bad method table\n", client
->getName());
2668 err
= kIOReturnUnsupported
;
2673 kern_return_t
is_io_async_method_structureI_structureO(
2674 io_object_t connect
,
2675 mach_port_t wakePort
,
2676 io_async_ref_t reference
,
2677 mach_msg_type_number_t referenceCnt
,
2680 IOByteCount inputCount
,
2682 IOByteCount
* outputCount
)
2685 IOExternalAsyncMethod
*method
;
2689 CHECK( IOUserClient
, connect
, client
);
2691 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2693 err
= kIOReturnBadArgument
;
2694 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2696 if( (0xffffffff != method
->count0
)
2697 && (inputCount
!= method
->count0
))
2699 if( (0xffffffff != method
->count1
)
2700 && (*outputCount
!= method
->count1
))
2703 reference
[0] = (natural_t
) wakePort
;
2704 func
= method
->func
;
2706 if( method
->count1
) {
2707 if( method
->count0
) {
2708 err
= (object
->*func
)( reference
,
2710 (void *)inputCount
, outputCount
, 0, 0 );
2712 err
= (object
->*func
)( reference
,
2713 output
, outputCount
, 0, 0, 0, 0 );
2716 err
= (object
->*func
)( reference
,
2717 input
, (void *)inputCount
, 0, 0, 0, 0 );
2723 err
= kIOReturnUnsupported
;
2727 /* Routine io_make_matching */
2728 kern_return_t
is_io_make_matching(
2729 mach_port_t master_port
,
2731 IOOptionBits options
,
2733 IOByteCount inputCount
,
2734 io_string_t matching
)
2737 IOReturn err
= kIOReturnSuccess
;
2738 OSDictionary
* dict
;
2740 if( master_port
!= master_device_port
)
2741 return( kIOReturnNotPrivileged
);
2745 case kIOServiceMatching
:
2746 dict
= IOService::serviceMatching( gIOServiceKey
);
2749 case kIOBSDNameMatching
:
2750 dict
= IOBSDNameMatching( (const char *) input
);
2753 case kIOOFPathMatching
:
2754 dict
= IOOFPathMatching( (const char *) input
,
2755 matching
, sizeof( io_string_t
));
2763 return( kIOReturnUnsupported
);
2766 s
= OSSerialize::withCapacity(4096);
2768 err
= kIOReturnNoMemory
;
2772 if( !dict
->serialize( s
)) {
2773 err
= kIOReturnUnsupported
;
2777 if( s
->getLength() > sizeof( io_string_t
)) {
2778 err
= kIOReturnNoMemory
;
2781 strcpy( matching
, s
->text());
2793 /* Routine io_catalog_send_data */
2794 kern_return_t
is_io_catalog_send_data(
2795 mach_port_t master_port
,
2797 io_buf_ptr_t inData
,
2798 mach_msg_type_number_t inDataCount
,
2803 kern_return_t kr
= kIOReturnError
;
2805 //printf("io_catalog_send_data called. flag: %d\n", flag);
2807 if( master_port
!= master_device_port
)
2808 return kIOReturnNotPrivileged
;
2810 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2811 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2812 return kIOReturnBadArgument
;
2815 vm_map_offset_t map_data
;
2817 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
2818 data
= CAST_DOWN(vm_offset_t
, map_data
);
2820 if( kr
!= KERN_SUCCESS
)
2823 // must return success after vm_map_copyout() succeeds
2826 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2827 vm_deallocate( kernel_map
, data
, inDataCount
);
2829 *result
= kIOReturnNoMemory
;
2830 return( KERN_SUCCESS
);
2836 case kIOCatalogAddDrivers
:
2837 case kIOCatalogAddDriversNoMatch
: {
2840 array
= OSDynamicCast(OSArray
, obj
);
2842 if ( !gIOCatalogue
->addDrivers( array
,
2843 flag
== kIOCatalogAddDrivers
) ) {
2844 kr
= kIOReturnError
;
2848 kr
= kIOReturnBadArgument
;
2853 case kIOCatalogRemoveDrivers
:
2854 case kIOCatalogRemoveDriversNoMatch
: {
2855 OSDictionary
* dict
;
2857 dict
= OSDynamicCast(OSDictionary
, obj
);
2859 if ( !gIOCatalogue
->removeDrivers( dict
,
2860 flag
== kIOCatalogRemoveDrivers
) ) {
2861 kr
= kIOReturnError
;
2865 kr
= kIOReturnBadArgument
;
2870 case kIOCatalogStartMatching
: {
2871 OSDictionary
* dict
;
2873 dict
= OSDynamicCast(OSDictionary
, obj
);
2875 if ( !gIOCatalogue
->startMatching( dict
) ) {
2876 kr
= kIOReturnError
;
2880 kr
= kIOReturnBadArgument
;
2885 case kIOCatalogRemoveKernelLinker
: {
2886 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
2887 kr
= kIOReturnError
;
2889 kr
= kIOReturnSuccess
;
2895 kr
= kIOReturnBadArgument
;
2899 if (obj
) obj
->release();
2902 return( KERN_SUCCESS
);
2905 /* Routine io_catalog_terminate */
2906 kern_return_t
is_io_catalog_terminate(
2907 mach_port_t master_port
,
2913 if( master_port
!= master_device_port
)
2914 return kIOReturnNotPrivileged
;
2916 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
2917 kIOClientPrivilegeAdministrator
);
2918 if( kIOReturnSuccess
!= kr
)
2922 case kIOCatalogServiceTerminate
:
2924 IOService
* service
;
2926 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
2927 kIORegistryIterateRecursively
);
2929 return kIOReturnNoMemory
;
2933 while( (service
= (IOService
*)iter
->getNextObject()) ) {
2934 if( service
->metaCast(name
)) {
2935 if ( !service
->terminate( kIOServiceRequired
2936 | kIOServiceSynchronous
) ) {
2937 kr
= kIOReturnUnsupported
;
2942 } while( !service
&& !iter
->isValid());
2946 case kIOCatalogModuleUnload
:
2947 case kIOCatalogModuleTerminate
:
2948 kr
= gIOCatalogue
->terminateDriversForModule(name
,
2949 flag
== kIOCatalogModuleUnload
);
2953 kr
= kIOReturnBadArgument
;
2960 /* Routine io_catalog_get_data */
2961 kern_return_t
is_io_catalog_get_data(
2962 mach_port_t master_port
,
2964 io_buf_ptr_t
*outData
,
2965 mach_msg_type_number_t
*outDataCount
)
2967 kern_return_t kr
= kIOReturnSuccess
;
2970 if( master_port
!= master_device_port
)
2971 return kIOReturnNotPrivileged
;
2973 //printf("io_catalog_get_data called. flag: %d\n", flag);
2975 s
= OSSerialize::withCapacity(4096);
2977 return kIOReturnNoMemory
;
2981 kr
= gIOCatalogue
->serializeData(flag
, s
);
2983 if ( kr
== kIOReturnSuccess
) {
2988 size
= s
->getLength();
2989 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
2990 if ( kr
== kIOReturnSuccess
) {
2991 bcopy(s
->text(), (void *)data
, size
);
2992 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
2993 (vm_map_size_t
)size
, true, ©
);
2994 *outData
= (char *)copy
;
2995 *outDataCount
= size
;
3004 /* Routine io_catalog_get_gen_count */
3005 kern_return_t
is_io_catalog_get_gen_count(
3006 mach_port_t master_port
,
3009 if( master_port
!= master_device_port
)
3010 return kIOReturnNotPrivileged
;
3012 //printf("io_catalog_get_gen_count called.\n");
3015 return kIOReturnBadArgument
;
3017 *genCount
= gIOCatalogue
->getGenerationCount();
3019 return kIOReturnSuccess
;
3022 /* Routine io_catalog_module_loaded */
3023 kern_return_t
is_io_catalog_module_loaded(
3024 mach_port_t master_port
,
3027 if( master_port
!= master_device_port
)
3028 return kIOReturnNotPrivileged
;
3030 //printf("io_catalog_module_loaded called. name %s\n", name);
3033 return kIOReturnBadArgument
;
3035 gIOCatalogue
->moduleHasLoaded(name
);
3037 return kIOReturnSuccess
;
3040 kern_return_t
is_io_catalog_reset(
3041 mach_port_t master_port
,
3044 if( master_port
!= master_device_port
)
3045 return kIOReturnNotPrivileged
;
3048 case kIOCatalogResetDefault
:
3049 gIOCatalogue
->reset();
3053 return kIOReturnBadArgument
;
3056 return kIOReturnSuccess
;
3059 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
3061 kern_return_t result
= kIOReturnBadArgument
;
3062 IOUserClient
*userClient
;
3064 if ((userClient
= OSDynamicCast(IOUserClient
,
3065 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
3066 IOExternalTrap
*trap
;
3067 IOService
*target
= NULL
;
3069 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
3071 if (trap
&& target
) {
3077 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
3081 userClient
->release();
3089 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
3090 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
3091 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
3092 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
3093 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
3094 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
3095 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
3096 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
3097 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
3098 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
3099 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
3100 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
3101 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
3102 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
3103 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
3104 OSMetaClassDefineReservedUnused(IOUserClient
, 15);