2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
32 #include <IOKit/IOKitServer.h>
33 #include <IOKit/IOUserClient.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IORegistryEntry.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOMemoryDescriptor.h>
38 #include <IOKit/IOLib.h>
40 #include <IOKit/assert.h>
42 #include "IOServicePrivate.h"
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46 // definitions we should get from osfmk
48 //typedef struct ipc_port * ipc_port_t;
49 typedef natural_t ipc_kobject_type_t
;
51 #define IKOT_IOKIT_SPARE 27
52 #define IKOT_IOKIT_CONNECT 29
53 #define IKOT_IOKIT_OBJECT 30
57 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
58 ipc_kobject_type_t type
);
60 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
62 extern mach_port_name_t
iokit_make_send_right( task_t task
,
63 io_object_t obj
, ipc_kobject_type_t type
);
65 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
67 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
69 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
71 extern ipc_port_t master_device_port
;
73 extern void iokit_retain_port( ipc_port_t port
);
74 extern void iokit_release_port( ipc_port_t port
);
76 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
78 #include <mach/mach_traps.h>
79 #include <vm/vm_map.h>
84 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
86 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
88 class IOMachPort
: public OSObject
90 OSDeclareDefaultStructors(IOMachPort
)
97 static IOMachPort
* portForObject( OSObject
* obj
,
98 ipc_kobject_type_t type
);
99 static bool noMoreSendersForObject( OSObject
* obj
,
100 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
101 static void releasePortForObject( OSObject
* obj
,
102 ipc_kobject_type_t type
);
103 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
105 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
107 static mach_port_name_t
makeSendRightForTask( task_t task
,
108 io_object_t obj
, ipc_kobject_type_t type
);
113 #define super OSObject
114 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
116 static IOLock
* gIOObjectPortLock
;
118 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
120 // not in dictForType() for debugging ease
121 static OSDictionary
* gIOObjectPorts
;
122 static OSDictionary
* gIOConnectPorts
;
124 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
126 OSDictionary
** dict
;
128 if( IKOT_IOKIT_OBJECT
== type
)
129 dict
= &gIOObjectPorts
;
130 else if( IKOT_IOKIT_CONNECT
== type
)
131 dict
= &gIOConnectPorts
;
136 *dict
= OSDictionary::withCapacity( 1 );
141 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
142 ipc_kobject_type_t type
)
144 IOMachPort
* inst
= 0;
147 IOTakeLock( gIOObjectPortLock
);
151 dict
= dictForType( type
);
155 if( (inst
= (IOMachPort
*)
156 dict
->getObject( (const OSSymbol
*) obj
))) {
162 inst
= new IOMachPort
;
163 if( inst
&& !inst
->init()) {
168 inst
->port
= iokit_alloc_object_port( obj
, type
);
171 dict
->setObject( (const OSSymbol
*) obj
, inst
);
181 IOUnlock( gIOObjectPortLock
);
186 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
187 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
190 IOMachPort
* machPort
;
191 bool destroyed
= true;
193 IOTakeLock( gIOObjectPortLock
);
195 if( (dict
= dictForType( type
))) {
198 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
200 destroyed
= (machPort
->mscount
== *mscount
);
202 dict
->removeObject( (const OSSymbol
*) obj
);
204 *mscount
= machPort
->mscount
;
209 IOUnlock( gIOObjectPortLock
);
214 void IOMachPort::releasePortForObject( OSObject
* obj
,
215 ipc_kobject_type_t type
)
218 IOMachPort
* machPort
;
220 IOTakeLock( gIOObjectPortLock
);
222 if( (dict
= dictForType( type
))) {
224 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
225 if( machPort
&& !machPort
->holdDestroy
)
226 dict
->removeObject( (const OSSymbol
*) obj
);
230 IOUnlock( gIOObjectPortLock
);
233 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
236 IOMachPort
* machPort
;
238 IOLockLock( gIOObjectPortLock
);
240 if( (dict
= dictForType( type
))) {
241 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
243 machPort
->holdDestroy
= true;
246 IOLockUnlock( gIOObjectPortLock
);
249 void IOUserClient::destroyUserReferences( OSObject
* obj
)
251 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
254 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
258 IOTakeLock( gIOObjectPortLock
);
261 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
264 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
268 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
270 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
271 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
273 uc
->mappings
->release();
276 dict
->removeObject( (const OSSymbol
*) obj
);
280 IOUnlock( gIOObjectPortLock
);
283 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
284 io_object_t obj
, ipc_kobject_type_t type
)
286 return( iokit_make_send_right( task
, obj
, type
));
289 void IOMachPort::free( void )
292 iokit_destroy_object_port( port
);
296 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
298 class IOUserNotification
: public OSIterator
300 OSDeclareDefaultStructors(IOUserNotification
)
302 IONotifier
* holdNotify
;
307 virtual bool init( void );
310 virtual void setNotification( IONotifier
* obj
);
312 virtual void reset();
313 virtual bool isValid();
316 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
320 // functions called from osfmk/device/iokit_rpc.c
323 iokit_add_reference( io_object_t obj
)
330 iokit_remove_reference( io_object_t obj
)
337 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
339 IOMachPort
* machPort
;
342 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
344 port
= machPort
->port
;
346 iokit_retain_port( port
);
357 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
358 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
360 IOUserClient
* client
;
362 IOUserNotification
* notify
;
364 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
365 return( kIOReturnNotReady
);
367 if( IKOT_IOKIT_CONNECT
== type
)
369 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
370 client
->clientDied();
372 else if( IKOT_IOKIT_OBJECT
== type
)
374 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
376 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
377 notify
->setNotification( 0 );
380 return( kIOReturnSuccess
);
385 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
387 class IOServiceUserNotification
: public IOUserNotification
389 OSDeclareDefaultStructors(IOServiceUserNotification
)
392 mach_msg_header_t msgHdr
;
393 OSNotificationHeader notifyHeader
;
396 enum { kMaxOutstanding
= 1024 };
401 OSObject
* lastEntry
;
406 virtual bool init( mach_port_t port
, natural_t type
,
407 OSAsyncReference reference
);
410 static bool _handler( void * target
,
411 void * ref
, IOService
* newService
);
412 virtual bool handler( void * ref
, IOService
* newService
);
414 virtual OSObject
* getNextObject();
417 class IOServiceMessageUserNotification
: public IOUserNotification
419 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
422 mach_msg_header_t msgHdr
;
423 mach_msg_body_t msgBody
;
424 mach_msg_port_descriptor_t ports
[1];
425 OSNotificationHeader notifyHeader
;
433 virtual bool init( mach_port_t port
, natural_t type
,
434 OSAsyncReference reference
, vm_size_t extraSize
);
437 static IOReturn
_handler( void * target
, void * ref
,
438 UInt32 messageType
, IOService
* provider
,
439 void * messageArgument
, vm_size_t argSize
);
440 virtual IOReturn
handler( void * ref
,
441 UInt32 messageType
, IOService
* provider
,
442 void * messageArgument
, vm_size_t argSize
);
444 virtual OSObject
* getNextObject();
447 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
450 #define super OSIterator
451 OSDefineMetaClass( IOUserNotification
, OSIterator
)
452 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
454 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
456 bool IOUserNotification::init( void )
461 lock
= IOLockAlloc();
468 void IOUserNotification::free( void )
471 holdNotify
->remove();
472 // can't be in handler now
481 void IOUserNotification::setNotification( IONotifier
* notify
)
483 IONotifier
* previousNotify
;
485 IOLockLock( gIOObjectPortLock
);
487 previousNotify
= holdNotify
;
490 IOLockUnlock( gIOObjectPortLock
);
493 previousNotify
->remove();
496 void IOUserNotification::reset()
501 bool IOUserNotification::isValid()
506 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
509 #define super IOUserNotification
510 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
512 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
514 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
515 OSAsyncReference reference
)
517 newSet
= OSArray::withCapacity( 1 );
521 msgSize
= sizeof( PingMsg
) + 0;
522 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
526 bzero( pingMsg
, msgSize
);
528 pingMsg
->msgHdr
.msgh_remote_port
= port
;
529 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
530 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
531 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
532 pingMsg
->msgHdr
.msgh_size
= msgSize
;
533 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
535 pingMsg
->notifyHeader
.size
= 0;
536 pingMsg
->notifyHeader
.type
= type
;
537 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
539 return( super::init() );
542 void IOServiceUserNotification::free( void )
547 OSObject
* _lastEntry
;
551 _lastEntry
= lastEntry
;
556 if( _pingMsg
&& _msgSize
)
557 IOFree( _pingMsg
, _msgSize
);
560 _lastEntry
->release();
566 bool IOServiceUserNotification::_handler( void * target
,
567 void * ref
, IOService
* newService
)
569 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
572 bool IOServiceUserNotification::handler( void * ref
,
573 IOService
* newService
)
577 ipc_port_t port
= NULL
;
578 bool sendPing
= false;
582 count
= newSet
->getCount();
583 if( count
< kMaxOutstanding
) {
585 newSet
->setObject( newService
);
586 if( (sendPing
= (armed
&& (0 == count
))))
592 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
593 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
596 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
597 pingMsg
->msgHdr
.msgh_local_port
= port
;
599 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
601 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
602 pingMsg
->msgHdr
.msgh_size
);
604 iokit_release_port( port
);
606 if( KERN_SUCCESS
!= kr
)
607 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
613 OSObject
* IOServiceUserNotification::getNextObject()
621 lastEntry
->release();
623 count
= newSet
->getCount();
625 result
= newSet
->getObject( count
- 1 );
627 newSet
->removeObject( count
- 1);
639 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
641 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
643 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
645 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
646 OSAsyncReference reference
, vm_size_t extraSize
)
649 extraSize
+= sizeof(IOServiceInterestContent
);
650 msgSize
= sizeof( PingMsg
) + extraSize
;
651 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
655 bzero( pingMsg
, msgSize
);
657 pingMsg
->msgHdr
.msgh_remote_port
= port
;
658 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
660 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
661 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
662 pingMsg
->msgHdr
.msgh_size
= msgSize
;
663 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
665 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
667 pingMsg
->ports
[0].name
= 0;
668 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
669 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
671 pingMsg
->notifyHeader
.size
= extraSize
;
672 pingMsg
->notifyHeader
.type
= type
;
673 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
675 return( super::init() );
678 void IOServiceMessageUserNotification::free( void )
688 if( _pingMsg
&& _msgSize
)
689 IOFree( _pingMsg
, _msgSize
);
692 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
693 UInt32 messageType
, IOService
* provider
,
694 void * argument
, vm_size_t argSize
)
696 return( ((IOServiceMessageUserNotification
*) target
)->handler(
697 ref
, messageType
, provider
, argument
, argSize
));
700 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
701 UInt32 messageType
, IOService
* provider
,
702 void * messageArgument
, vm_size_t argSize
)
705 ipc_port_t thisPort
, providerPort
;
706 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
707 pingMsg
->notifyHeader
.content
;
709 data
->messageType
= messageType
;
711 argSize
= sizeof( messageArgument
);
712 data
->messageArgument
[0] = messageArgument
;
714 if( argSize
> kIOUserNotifyMaxMessageSize
)
715 argSize
= kIOUserNotifyMaxMessageSize
;
716 bcopy( messageArgument
, data
->messageArgument
, argSize
);
718 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
719 + sizeof( IOServiceInterestContent
)
720 - sizeof( data
->messageArgument
)
723 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
724 pingMsg
->ports
[0].name
= providerPort
;
725 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
726 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
727 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
728 pingMsg
->msgHdr
.msgh_size
);
730 iokit_release_port( thisPort
);
732 iokit_release_port( providerPort
);
734 if( KERN_SUCCESS
!= kr
)
735 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
737 return( kIOReturnSuccess
);
740 OSObject
* IOServiceMessageUserNotification::getNextObject()
745 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
748 #define super IOService
749 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
751 void IOUserClient::initialize( void )
753 gIOObjectPortLock
= IOLockAlloc();
755 assert( gIOObjectPortLock
);
758 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
759 mach_port_t wakePort
,
760 void *callback
, void *refcon
)
762 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
763 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
764 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
767 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
768 const char * privilegeName
)
771 security_token_t token
;
772 mach_msg_type_number_t count
;
774 count
= TASK_SECURITY_TOKEN_COUNT
;
775 kr
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
,
776 (task_info_t
) &token
, &count
);
778 if (KERN_SUCCESS
!= kr
)
780 else if (!strcmp(privilegeName
, kIOClientPrivilegeAdministrator
))
782 if (0 != token
.val
[0])
783 kr
= kIOReturnNotPrivileged
;
785 else if (!strcmp(privilegeName
, kIOClientPrivilegeLocalUser
))
788 OSDictionary
* user
= 0;
790 if ((array
= OSDynamicCast(OSArray
,
791 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
793 for (unsigned int idx
= 0;
794 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
798 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
799 && (token
.val
[0] == num
->unsigned32BitValue()))
805 kr
= kIOReturnNotPrivileged
;
808 kr
= kIOReturnUnsupported
;
813 bool IOUserClient::init()
815 if( getPropertyTable())
818 return super::init();
821 bool IOUserClient::init(OSDictionary
* dictionary
)
823 if( getPropertyTable())
826 return super::init(dictionary
);
829 bool IOUserClient::initWithTask(task_t owningTask
,
833 if( getPropertyTable())
836 return super::init();
839 bool IOUserClient::initWithTask(task_t owningTask
,
842 OSDictionary
* properties
)
846 ok
= super::init( properties
);
847 ok
&= initWithTask( owningTask
, securityID
, type
);
852 void IOUserClient::free()
860 IOReturn
IOUserClient::clientDied( void )
862 return( clientClose());
865 IOReturn
IOUserClient::clientClose( void )
867 return( kIOReturnUnsupported
);
870 IOService
* IOUserClient::getService( void )
875 IOReturn
IOUserClient::registerNotificationPort(
876 mach_port_t
/* port */,
880 return( kIOReturnUnsupported
);
883 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
884 semaphore_t
* semaphore
)
886 return( kIOReturnUnsupported
);
889 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
891 return( kIOReturnUnsupported
);
894 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
895 IOOptionBits
* options
,
896 IOMemoryDescriptor
** memory
)
898 return( kIOReturnUnsupported
);
901 IOMemoryMap
* IOUserClient::mapClientMemory(
904 IOOptionBits mapFlags
,
905 IOVirtualAddress atAddress
)
908 IOOptionBits options
= 0;
909 IOMemoryDescriptor
* memory
;
910 IOMemoryMap
* map
= 0;
912 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
914 if( memory
&& (kIOReturnSuccess
== err
)) {
916 options
= (options
& ~kIOMapUserOptionsMask
)
917 | (mapFlags
& kIOMapUserOptionsMask
);
918 map
= memory
->map( task
, atAddress
, options
);
925 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
926 OSObject
*obj
, io_object_t
*clientObj
)
928 mach_port_name_t name
;
930 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
933 *(mach_port_name_t
*)clientObj
= name
;
934 return kIOReturnSuccess
;
937 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
942 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
947 IOExternalMethod
* IOUserClient::
948 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
950 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
953 *targetP
= (IOService
*) method
->object
;
958 IOExternalAsyncMethod
* IOUserClient::
959 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
961 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
964 *targetP
= (IOService
*) method
->object
;
969 IOExternalTrap
* IOUserClient::
970 getExternalTrapForIndex(UInt32 index
)
975 IOExternalTrap
* IOUserClient::
976 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
978 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
981 *targetP
= trap
->object
;
987 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
988 IOReturn result
, void *args
[], UInt32 numArgs
)
991 mach_msg_header_t msgHdr
;
992 OSNotificationHeader notifyHdr
;
993 IOAsyncCompletionContent asyncContent
;
994 void * args
[kMaxAsyncArgs
];
997 mach_port_t replyPort
;
1000 // If no reply port, do nothing.
1001 replyPort
= (mach_port_t
) reference
[0];
1002 if(replyPort
== MACH_PORT_NULL
)
1003 return kIOReturnSuccess
;
1005 if(numArgs
> kMaxAsyncArgs
)
1006 return kIOReturnMessageTooLarge
;
1007 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1009 replyMsg
.msgHdr
.msgh_size
=
1010 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
1011 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1012 replyMsg
.msgHdr
.msgh_local_port
= 0;
1013 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1015 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1016 + numArgs
*sizeof(void *);
1017 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1018 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
1020 replyMsg
.asyncContent
.result
= result
;
1022 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
1023 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
1024 replyMsg
.msgHdr
.msgh_size
);
1025 if( KERN_SUCCESS
!= kr
)
1026 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
1030 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1034 #define CHECK(cls,obj,out) \
1036 if( !(out = OSDynamicCast( cls, obj))) \
1037 return( kIOReturnBadArgument )
1039 /* Routine io_object_get_class */
1040 kern_return_t
is_io_object_get_class(
1042 io_name_t className
)
1044 const OSMetaClass
* my_obj
= NULL
;
1047 return( kIOReturnBadArgument
);
1049 my_obj
= object
->getMetaClass();
1051 return (kIOReturnNotFound
);
1054 strcpy( className
, my_obj
->getClassName());
1055 return( kIOReturnSuccess
);
1058 /* Routine io_object_get_superclass */
1059 kern_return_t
is_io_object_get_superclass(
1060 mach_port_t master_port
,
1062 io_name_t class_name
)
1064 const OSMetaClass
* my_obj
= NULL
;
1065 const OSMetaClass
* superclass
= NULL
;
1066 const OSSymbol
*my_name
= NULL
;
1067 const char *my_cstr
= NULL
;
1069 if (!obj_name
|| !class_name
)
1070 return (kIOReturnBadArgument
);
1072 if( master_port
!= master_device_port
)
1073 return( kIOReturnNotPrivileged
);
1075 my_name
= OSSymbol::withCString(obj_name
);
1078 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1082 superclass
= my_obj
->getSuperClass();
1086 return( kIOReturnNotFound
);
1089 my_cstr
= superclass
->getClassName();
1092 strncpy(class_name
, my_cstr
, sizeof(io_name_t
)-1);
1093 return( kIOReturnSuccess
);
1095 return (kIOReturnNotFound
);
1098 /* Routine io_object_get_bundle_identifier */
1099 kern_return_t
is_io_object_get_bundle_identifier(
1100 mach_port_t master_port
,
1102 io_name_t bundle_name
)
1104 const OSMetaClass
* my_obj
= NULL
;
1105 const OSSymbol
*my_name
= NULL
;
1106 const OSSymbol
*identifier
= NULL
;
1107 const char *my_cstr
= NULL
;
1109 if (!obj_name
|| !bundle_name
)
1110 return (kIOReturnBadArgument
);
1112 if( master_port
!= master_device_port
)
1113 return( kIOReturnNotPrivileged
);
1115 my_name
= OSSymbol::withCString(obj_name
);
1118 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1123 identifier
= my_obj
->getKmodName();
1126 return( kIOReturnNotFound
);
1129 my_cstr
= identifier
->getCStringNoCopy();
1131 strncpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
)-1);
1132 return( kIOReturnSuccess
);
1135 return (kIOReturnBadArgument
);
1138 /* Routine io_object_conforms_to */
1139 kern_return_t
is_io_object_conforms_to(
1141 io_name_t className
,
1142 boolean_t
*conforms
)
1145 return( kIOReturnBadArgument
);
1147 *conforms
= (0 != object
->metaCast( className
));
1148 return( kIOReturnSuccess
);
1151 /* Routine io_object_get_retain_count */
1152 kern_return_t
is_io_object_get_retain_count(
1157 return( kIOReturnBadArgument
);
1159 *retainCount
= object
->getRetainCount();
1160 return( kIOReturnSuccess
);
1163 /* Routine io_iterator_next */
1164 kern_return_t
is_io_iterator_next(
1165 io_object_t iterator
,
1166 io_object_t
*object
)
1170 CHECK( OSIterator
, iterator
, iter
);
1172 obj
= iter
->getNextObject();
1176 return( kIOReturnSuccess
);
1178 return( kIOReturnNoDevice
);
1181 /* Routine io_iterator_reset */
1182 kern_return_t
is_io_iterator_reset(
1183 io_object_t iterator
)
1185 CHECK( OSIterator
, iterator
, iter
);
1189 return( kIOReturnSuccess
);
1192 /* Routine io_iterator_is_valid */
1193 kern_return_t
is_io_iterator_is_valid(
1194 io_object_t iterator
,
1195 boolean_t
*is_valid
)
1197 CHECK( OSIterator
, iterator
, iter
);
1199 *is_valid
= iter
->isValid();
1201 return( kIOReturnSuccess
);
1204 /* Routine io_service_match_property_table */
1205 kern_return_t
is_io_service_match_property_table(
1206 io_service_t _service
,
1207 io_string_t matching
,
1208 boolean_t
*matches
)
1210 CHECK( IOService
, _service
, service
);
1214 OSDictionary
* dict
;
1216 obj
= OSUnserializeXML( matching
);
1218 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1219 *matches
= service
->passiveMatch( dict
);
1220 kr
= kIOReturnSuccess
;
1222 kr
= kIOReturnBadArgument
;
1230 /* Routine io_service_match_property_table_ool */
1231 kern_return_t
is_io_service_match_property_table_ool(
1232 io_object_t service
,
1233 io_buf_ptr_t matching
,
1234 mach_msg_type_number_t matchingCnt
,
1236 boolean_t
*matches
)
1240 vm_map_offset_t map_data
;
1242 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1243 data
= CAST_DOWN(vm_offset_t
, map_data
);
1245 if( KERN_SUCCESS
== kr
) {
1246 // must return success after vm_map_copyout() succeeds
1247 *result
= is_io_service_match_property_table( service
,
1248 (char *) data
, matches
);
1249 vm_deallocate( kernel_map
, data
, matchingCnt
);
1255 /* Routine io_service_get_matching_services */
1256 kern_return_t
is_io_service_get_matching_services(
1257 mach_port_t master_port
,
1258 io_string_t matching
,
1259 io_iterator_t
*existing
)
1263 OSDictionary
* dict
;
1265 if( master_port
!= master_device_port
)
1266 return( kIOReturnNotPrivileged
);
1268 obj
= OSUnserializeXML( matching
);
1270 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1271 *existing
= IOService::getMatchingServices( dict
);
1272 kr
= kIOReturnSuccess
;
1274 kr
= kIOReturnBadArgument
;
1282 /* Routine io_service_get_matching_services_ool */
1283 kern_return_t
is_io_service_get_matching_services_ool(
1284 mach_port_t master_port
,
1285 io_buf_ptr_t matching
,
1286 mach_msg_type_number_t matchingCnt
,
1288 io_object_t
*existing
)
1292 vm_map_offset_t map_data
;
1294 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1295 data
= CAST_DOWN(vm_offset_t
, map_data
);
1297 if( KERN_SUCCESS
== kr
) {
1298 // must return success after vm_map_copyout() succeeds
1299 *result
= is_io_service_get_matching_services( master_port
,
1300 (char *) data
, existing
);
1301 vm_deallocate( kernel_map
, data
, matchingCnt
);
1307 /* Routine io_service_add_notification */
1308 kern_return_t
is_io_service_add_notification(
1309 mach_port_t master_port
,
1310 io_name_t notification_type
,
1311 io_string_t matching
,
1313 io_async_ref_t reference
,
1314 mach_msg_type_number_t referenceCnt
,
1315 io_object_t
* notification
)
1317 IOServiceUserNotification
* userNotify
= 0;
1318 IONotifier
* notify
= 0;
1319 const OSSymbol
* sym
;
1320 OSDictionary
* dict
;
1322 unsigned long int userMsgType
;
1325 if( master_port
!= master_device_port
)
1326 return( kIOReturnNotPrivileged
);
1329 err
= kIOReturnNoResources
;
1331 if( !(sym
= OSSymbol::withCString( notification_type
)))
1332 err
= kIOReturnNoResources
;
1334 if( !(dict
= OSDynamicCast( OSDictionary
,
1335 OSUnserializeXML( matching
)))) {
1336 err
= kIOReturnBadArgument
;
1340 if( (sym
== gIOPublishNotification
)
1341 || (sym
== gIOFirstPublishNotification
))
1342 userMsgType
= kIOServicePublishNotificationType
;
1343 else if( (sym
== gIOMatchedNotification
)
1344 || (sym
== gIOFirstMatchNotification
))
1345 userMsgType
= kIOServiceMatchedNotificationType
;
1346 else if( sym
== gIOTerminatedNotification
)
1347 userMsgType
= kIOServiceTerminatedNotificationType
;
1349 userMsgType
= kLastIOKitNotificationType
;
1351 userNotify
= new IOServiceUserNotification
;
1353 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1355 userNotify
->release();
1361 notify
= IOService::addNotification( sym
, dict
,
1362 &userNotify
->_handler
, userNotify
);
1365 *notification
= userNotify
;
1366 userNotify
->setNotification( notify
);
1367 err
= kIOReturnSuccess
;
1369 err
= kIOReturnUnsupported
;
1381 /* Routine io_service_add_notification_ool */
1382 kern_return_t
is_io_service_add_notification_ool(
1383 mach_port_t master_port
,
1384 io_name_t notification_type
,
1385 io_buf_ptr_t matching
,
1386 mach_msg_type_number_t matchingCnt
,
1387 mach_port_t wake_port
,
1388 io_async_ref_t reference
,
1389 mach_msg_type_number_t referenceCnt
,
1391 io_object_t
*notification
)
1395 vm_map_offset_t map_data
;
1397 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1398 data
= CAST_DOWN(vm_offset_t
, map_data
);
1400 if( KERN_SUCCESS
== kr
) {
1401 // must return success after vm_map_copyout() succeeds
1402 *result
= is_io_service_add_notification( master_port
, notification_type
,
1403 (char *) data
, wake_port
, reference
, referenceCnt
, notification
);
1404 vm_deallocate( kernel_map
, data
, matchingCnt
);
1411 /* Routine io_service_add_notification_old */
1412 kern_return_t
is_io_service_add_notification_old(
1413 mach_port_t master_port
,
1414 io_name_t notification_type
,
1415 io_string_t matching
,
1418 io_object_t
* notification
)
1420 return( is_io_service_add_notification( master_port
, notification_type
,
1421 matching
, port
, &ref
, 1, notification
));
1424 /* Routine io_service_add_message_notification */
1425 kern_return_t
is_io_service_add_interest_notification(
1426 io_object_t _service
,
1427 io_name_t type_of_interest
,
1429 io_async_ref_t reference
,
1430 mach_msg_type_number_t referenceCnt
,
1431 io_object_t
* notification
)
1434 IOServiceMessageUserNotification
* userNotify
= 0;
1435 IONotifier
* notify
= 0;
1436 const OSSymbol
* sym
;
1439 CHECK( IOService
, _service
, service
);
1441 err
= kIOReturnNoResources
;
1442 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1444 userNotify
= new IOServiceMessageUserNotification
;
1446 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1447 reference
, kIOUserNotifyMaxMessageSize
)) {
1448 userNotify
->release();
1454 notify
= service
->registerInterest( sym
,
1455 &userNotify
->_handler
, userNotify
);
1457 *notification
= userNotify
;
1458 userNotify
->setNotification( notify
);
1459 err
= kIOReturnSuccess
;
1461 err
= kIOReturnUnsupported
;
1470 /* Routine io_service_acknowledge_notification */
1471 kern_return_t
is_io_service_acknowledge_notification(
1472 io_object_t _service
,
1473 natural_t notify_ref
,
1474 natural_t response
)
1476 CHECK( IOService
, _service
, service
);
1478 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1479 (IOOptionBits
) response
));
1483 /* Routine io_connect_get_semaphore */
1484 kern_return_t
is_io_connect_get_notification_semaphore(
1485 io_connect_t connection
,
1486 natural_t notification_type
,
1487 semaphore_t
*semaphore
)
1489 CHECK( IOUserClient
, connection
, client
);
1491 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1495 /* Routine io_registry_get_root_entry */
1496 kern_return_t
is_io_registry_get_root_entry(
1497 mach_port_t master_port
,
1500 IORegistryEntry
* entry
;
1502 if( master_port
!= master_device_port
)
1503 return( kIOReturnNotPrivileged
);
1505 entry
= IORegistryEntry::getRegistryRoot();
1510 return( kIOReturnSuccess
);
1513 /* Routine io_registry_create_iterator */
1514 kern_return_t
is_io_registry_create_iterator(
1515 mach_port_t master_port
,
1518 io_object_t
*iterator
)
1520 if( master_port
!= master_device_port
)
1521 return( kIOReturnNotPrivileged
);
1523 *iterator
= IORegistryIterator::iterateOver(
1524 IORegistryEntry::getPlane( plane
), options
);
1526 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1529 /* Routine io_registry_entry_create_iterator */
1530 kern_return_t
is_io_registry_entry_create_iterator(
1531 io_object_t registry_entry
,
1534 io_object_t
*iterator
)
1536 CHECK( IORegistryEntry
, registry_entry
, entry
);
1538 *iterator
= IORegistryIterator::iterateOver( entry
,
1539 IORegistryEntry::getPlane( plane
), options
);
1541 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1544 /* Routine io_registry_iterator_enter */
1545 kern_return_t
is_io_registry_iterator_enter_entry(
1546 io_object_t iterator
)
1548 CHECK( IORegistryIterator
, iterator
, iter
);
1552 return( kIOReturnSuccess
);
1555 /* Routine io_registry_iterator_exit */
1556 kern_return_t
is_io_registry_iterator_exit_entry(
1557 io_object_t iterator
)
1561 CHECK( IORegistryIterator
, iterator
, iter
);
1563 didIt
= iter
->exitEntry();
1565 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1568 /* Routine io_registry_entry_from_path */
1569 kern_return_t
is_io_registry_entry_from_path(
1570 mach_port_t master_port
,
1572 io_object_t
*registry_entry
)
1574 IORegistryEntry
* entry
;
1576 if( master_port
!= master_device_port
)
1577 return( kIOReturnNotPrivileged
);
1579 entry
= IORegistryEntry::fromPath( path
);
1581 *registry_entry
= entry
;
1583 return( kIOReturnSuccess
);
1586 /* Routine io_registry_entry_in_plane */
1587 kern_return_t
is_io_registry_entry_in_plane(
1588 io_object_t registry_entry
,
1590 boolean_t
*inPlane
)
1592 CHECK( IORegistryEntry
, registry_entry
, entry
);
1594 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1596 return( kIOReturnSuccess
);
1600 /* Routine io_registry_entry_get_path */
1601 kern_return_t
is_io_registry_entry_get_path(
1602 io_object_t registry_entry
,
1607 CHECK( IORegistryEntry
, registry_entry
, entry
);
1609 length
= sizeof( io_string_t
);
1610 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1611 return( kIOReturnSuccess
);
1613 return( kIOReturnBadArgument
);
1617 /* Routine io_registry_entry_get_name */
1618 kern_return_t
is_io_registry_entry_get_name(
1619 io_object_t registry_entry
,
1622 CHECK( IORegistryEntry
, registry_entry
, entry
);
1624 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1626 return( kIOReturnSuccess
);
1629 /* Routine io_registry_entry_get_name_in_plane */
1630 kern_return_t
is_io_registry_entry_get_name_in_plane(
1631 io_object_t registry_entry
,
1632 io_name_t planeName
,
1635 const IORegistryPlane
* plane
;
1636 CHECK( IORegistryEntry
, registry_entry
, entry
);
1639 plane
= IORegistryEntry::getPlane( planeName
);
1643 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1645 return( kIOReturnSuccess
);
1648 /* Routine io_registry_entry_get_location_in_plane */
1649 kern_return_t
is_io_registry_entry_get_location_in_plane(
1650 io_object_t registry_entry
,
1651 io_name_t planeName
,
1652 io_name_t location
)
1654 const IORegistryPlane
* plane
;
1655 CHECK( IORegistryEntry
, registry_entry
, entry
);
1658 plane
= IORegistryEntry::getPlane( planeName
);
1662 const char * cstr
= entry
->getLocation( plane
);
1665 strncpy( location
, cstr
, sizeof( io_name_t
));
1666 return( kIOReturnSuccess
);
1668 return( kIOReturnNotFound
);
1671 // Create a vm_map_copy_t or kalloc'ed data for memory
1672 // to be copied out. ipc will free after the copyout.
1674 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1675 io_buf_ptr_t
* buf
)
1680 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1681 false /* src_destroy */, ©
);
1683 assert( err
== KERN_SUCCESS
);
1684 if( err
== KERN_SUCCESS
)
1685 *buf
= (char *) copy
;
1690 /* Routine io_registry_entry_get_property */
1691 kern_return_t
is_io_registry_entry_get_property_bytes(
1692 io_object_t registry_entry
,
1693 io_name_t property_name
,
1694 io_scalar_inband_t buf
,
1695 mach_msg_type_number_t
*dataCnt
)
1703 unsigned int len
= 0;
1704 const void * bytes
= 0;
1705 IOReturn ret
= kIOReturnSuccess
;
1707 CHECK( IORegistryEntry
, registry_entry
, entry
);
1709 obj
= entry
->copyProperty(property_name
);
1711 return( kIOReturnNoResources
);
1713 // One day OSData will be a common container base class
1715 if( (data
= OSDynamicCast( OSData
, obj
))) {
1716 len
= data
->getLength();
1717 bytes
= data
->getBytesNoCopy();
1719 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1720 len
= str
->getLength() + 1;
1721 bytes
= str
->getCStringNoCopy();
1723 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1724 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1725 bytes
= boo
->isTrue() ? "Yes" : "No";
1727 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1728 offsetBytes
= off
->unsigned64BitValue();
1729 len
= off
->numberOfBytes();
1730 bytes
= &offsetBytes
;
1731 #ifdef __BIG_ENDIAN__
1732 bytes
= (const void *)
1733 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1737 ret
= kIOReturnBadArgument
;
1741 ret
= kIOReturnIPCError
;
1744 bcopy( bytes
, buf
, len
);
1753 /* Routine io_registry_entry_get_property */
1754 kern_return_t
is_io_registry_entry_get_property(
1755 io_object_t registry_entry
,
1756 io_name_t property_name
,
1757 io_buf_ptr_t
*properties
,
1758 mach_msg_type_number_t
*propertiesCnt
)
1764 CHECK( IORegistryEntry
, registry_entry
, entry
);
1766 obj
= entry
->copyProperty(property_name
);
1768 return( kIOReturnNotFound
);
1770 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1773 return( kIOReturnNoMemory
);
1777 if( obj
->serialize( s
)) {
1778 len
= s
->getLength();
1779 *propertiesCnt
= len
;
1780 err
= copyoutkdata( s
->text(), len
, properties
);
1783 err
= kIOReturnUnsupported
;
1791 /* Routine io_registry_entry_get_property_recursively */
1792 kern_return_t
is_io_registry_entry_get_property_recursively(
1793 io_object_t registry_entry
,
1795 io_name_t property_name
,
1797 io_buf_ptr_t
*properties
,
1798 mach_msg_type_number_t
*propertiesCnt
)
1804 CHECK( IORegistryEntry
, registry_entry
, entry
);
1806 obj
= entry
->copyProperty( property_name
,
1807 IORegistryEntry::getPlane( plane
), options
);
1809 return( kIOReturnNotFound
);
1811 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1814 return( kIOReturnNoMemory
);
1819 if( obj
->serialize( s
)) {
1820 len
= s
->getLength();
1821 *propertiesCnt
= len
;
1822 err
= copyoutkdata( s
->text(), len
, properties
);
1825 err
= kIOReturnUnsupported
;
1833 /* Routine io_registry_entry_get_properties */
1834 kern_return_t
is_io_registry_entry_get_properties(
1835 io_object_t registry_entry
,
1836 io_buf_ptr_t
*properties
,
1837 mach_msg_type_number_t
*propertiesCnt
)
1842 CHECK( IORegistryEntry
, registry_entry
, entry
);
1844 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1846 return( kIOReturnNoMemory
);
1850 if( entry
->serializeProperties( s
)) {
1851 len
= s
->getLength();
1852 *propertiesCnt
= len
;
1853 err
= copyoutkdata( s
->text(), len
, properties
);
1856 err
= kIOReturnUnsupported
;
1863 /* Routine io_registry_entry_set_properties */
1864 kern_return_t is_io_registry_entry_set_properties
1866 io_object_t registry_entry
,
1867 io_buf_ptr_t properties
,
1868 mach_msg_type_number_t propertiesCnt
,
1875 vm_map_offset_t map_data
;
1877 CHECK( IORegistryEntry
, registry_entry
, entry
);
1879 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
1880 data
= CAST_DOWN(vm_offset_t
, map_data
);
1882 if( KERN_SUCCESS
== err
) {
1884 // must return success after vm_map_copyout() succeeds
1885 obj
= OSUnserializeXML( (const char *) data
);
1886 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1889 res
= entry
->setProperties( obj
);
1892 res
= kIOReturnBadArgument
;
1900 /* Routine io_registry_entry_get_child_iterator */
1901 kern_return_t
is_io_registry_entry_get_child_iterator(
1902 io_object_t registry_entry
,
1904 io_object_t
*iterator
)
1906 CHECK( IORegistryEntry
, registry_entry
, entry
);
1908 *iterator
= entry
->getChildIterator(
1909 IORegistryEntry::getPlane( plane
));
1911 return( kIOReturnSuccess
);
1914 /* Routine io_registry_entry_get_parent_iterator */
1915 kern_return_t
is_io_registry_entry_get_parent_iterator(
1916 io_object_t registry_entry
,
1918 io_object_t
*iterator
)
1920 CHECK( IORegistryEntry
, registry_entry
, entry
);
1922 *iterator
= entry
->getParentIterator(
1923 IORegistryEntry::getPlane( plane
));
1925 return( kIOReturnSuccess
);
1928 /* Routine io_service_get_busy_state */
1929 kern_return_t
is_io_service_get_busy_state(
1930 io_object_t _service
,
1933 CHECK( IOService
, _service
, service
);
1935 *busyState
= service
->getBusyState();
1937 return( kIOReturnSuccess
);
1940 /* Routine io_service_get_state */
1941 kern_return_t
is_io_service_get_state(
1942 io_object_t _service
,
1945 CHECK( IOService
, _service
, service
);
1947 *state
= service
->getState();
1949 return( kIOReturnSuccess
);
1952 /* Routine io_service_wait_quiet */
1953 kern_return_t
is_io_service_wait_quiet(
1954 io_object_t _service
,
1955 mach_timespec_t wait_time
)
1957 CHECK( IOService
, _service
, service
);
1959 return( service
->waitQuiet( &wait_time
));
1962 /* Routine io_service_request_probe */
1963 kern_return_t
is_io_service_request_probe(
1964 io_object_t _service
,
1967 CHECK( IOService
, _service
, service
);
1969 return( service
->requestProbe( options
));
1973 /* Routine io_service_open */
1974 kern_return_t
is_io_service_open(
1975 io_object_t _service
,
1978 io_object_t
*connection
)
1980 IOUserClient
* client
;
1983 CHECK( IOService
, _service
, service
);
1985 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1986 connect_type
, 0, &client
);
1988 if( err
== kIOReturnSuccess
) {
1989 assert( OSDynamicCast(IOUserClient
, client
) );
1990 *connection
= client
;
1996 /* Routine io_service_open_ndr */
1997 kern_return_t
is_io_service_open_extended(
1998 io_object_t _service
,
2002 io_buf_ptr_t properties
,
2003 mach_msg_type_number_t propertiesCnt
,
2005 io_object_t
*connection
)
2007 IOUserClient
* client
= 0;
2008 kern_return_t err
= KERN_SUCCESS
;
2009 IOReturn res
= kIOReturnSuccess
;
2010 OSDictionary
* propertiesDict
= 0;
2012 bool disallowAccess
;
2014 CHECK( IOService
, _service
, service
);
2022 vm_map_offset_t map_data
;
2024 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2026 data
= CAST_DOWN(vm_offset_t
, map_data
);
2027 if (KERN_SUCCESS
== err
)
2029 // must return success after vm_map_copyout() succeeds
2030 obj
= OSUnserializeXML( (const char *) data
);
2031 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2032 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
2033 if (!propertiesDict
)
2035 res
= kIOReturnBadArgument
;
2040 if (kIOReturnSuccess
!= res
)
2044 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
2047 if (!propertiesDict
)
2048 propertiesDict
= OSDictionary::withCapacity(4);
2049 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
2053 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
2058 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
2059 connect_type
, propertiesDict
, &client
);
2062 propertiesDict
->release();
2064 if (res
== kIOReturnSuccess
)
2066 assert( OSDynamicCast(IOUserClient
, client
) );
2068 disallowAccess
= (crossEndian
2069 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
2070 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
2074 client
->clientClose();
2077 res
= kIOReturnUnsupported
;
2080 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
2085 *connection
= client
;
2091 /* Routine io_service_close */
2092 kern_return_t
is_io_service_close(
2093 io_object_t connection
)
2096 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2097 return( kIOReturnSuccess
);
2099 CHECK( IOUserClient
, connection
, client
);
2101 client
->clientClose();
2103 return( kIOReturnSuccess
);
2106 /* Routine io_connect_get_service */
2107 kern_return_t
is_io_connect_get_service(
2108 io_object_t connection
,
2109 io_object_t
*service
)
2111 IOService
* theService
;
2113 CHECK( IOUserClient
, connection
, client
);
2115 theService
= client
->getService();
2117 theService
->retain();
2119 *service
= theService
;
2121 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2124 /* Routine io_connect_set_notification_port */
2125 kern_return_t
is_io_connect_set_notification_port(
2126 io_object_t connection
,
2127 int notification_type
,
2131 CHECK( IOUserClient
, connection
, client
);
2133 return( client
->registerNotificationPort( port
, notification_type
,
2137 kern_return_t
is_io_connect_map_memory(
2138 io_object_t connect
,
2141 vm_address_t
* mapAddr
,
2142 vm_size_t
* mapSize
,
2148 CHECK( IOUserClient
, connect
, client
);
2150 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
2153 *mapAddr
= map
->getVirtualAddress();
2155 *mapSize
= map
->getLength();
2157 if( client
->sharedInstance
2158 || (task
!= current_task())) {
2159 // push a name out to the task owning the map,
2160 // so we can clean up maps
2162 mach_port_name_t name
=
2164 IOMachPort::makeSendRightForTask(
2165 task
, map
, IKOT_IOKIT_OBJECT
);
2169 // keep it with the user client
2170 IOLockLock( gIOObjectPortLock
);
2171 if( 0 == client
->mappings
)
2172 client
->mappings
= OSSet::withCapacity(2);
2173 if( client
->mappings
)
2174 client
->mappings
->setObject( map
);
2175 IOLockUnlock( gIOObjectPortLock
);
2178 err
= kIOReturnSuccess
;
2181 err
= kIOReturnBadArgument
;
2186 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2189 IOMemoryMap
* map
= 0;
2191 IOLockLock(gIOObjectPortLock
);
2193 iter
= OSCollectionIterator::withCollection(mappings
);
2196 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2198 if(mem
== map
->getMemoryDescriptor())
2201 mappings
->removeObject(map
);
2208 IOLockUnlock(gIOObjectPortLock
);
2213 kern_return_t
is_io_connect_unmap_memory(
2214 io_object_t connect
,
2217 vm_address_t mapAddr
)
2220 IOOptionBits options
= 0;
2221 IOMemoryDescriptor
* memory
;
2224 CHECK( IOUserClient
, connect
, client
);
2226 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
2228 if( memory
&& (kIOReturnSuccess
== err
)) {
2230 options
= (options
& ~kIOMapUserOptionsMask
)
2231 | kIOMapAnywhere
| kIOMapReference
;
2233 map
= memory
->map( task
, mapAddr
, options
);
2237 IOLockLock( gIOObjectPortLock
);
2238 if( client
->mappings
)
2239 client
->mappings
->removeObject( map
);
2240 IOLockUnlock( gIOObjectPortLock
);
2242 mach_port_name_t name
= 0;
2243 if (task
!= current_task())
2244 name
= IOMachPort::makeSendRightForTask( task
, map
, IKOT_IOKIT_OBJECT
);
2248 err
= iokit_mod_send_right( task
, name
, -2 );
2249 err
= kIOReturnSuccess
;
2252 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2253 if (task
== current_task())
2257 err
= kIOReturnBadArgument
;
2264 /* Routine io_connect_add_client */
2265 kern_return_t
is_io_connect_add_client(
2266 io_object_t connection
,
2267 io_object_t connect_to
)
2269 CHECK( IOUserClient
, connection
, client
);
2270 CHECK( IOUserClient
, connect_to
, to
);
2272 return( client
->connectClient( to
) );
2276 /* Routine io_connect_set_properties */
2277 kern_return_t
is_io_connect_set_properties(
2278 io_object_t connection
,
2279 io_buf_ptr_t properties
,
2280 mach_msg_type_number_t propertiesCnt
,
2283 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2287 /* Routine io_connect_method_scalarI_scalarO */
2288 kern_return_t
is_io_connect_method_scalarI_scalarO(
2289 io_object_t connect
,
2292 IOByteCount inputCount
,
2294 IOByteCount
* outputCount
)
2297 IOExternalMethod
* method
;
2301 CHECK( IOUserClient
, connect
, client
);
2302 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
2304 err
= kIOReturnBadArgument
;
2305 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2307 if( inputCount
!= method
->count0
)
2309 if( *outputCount
!= method
->count1
)
2312 func
= method
->func
;
2314 switch( inputCount
) {
2317 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2318 input
[3], input
[4], input
[5] );
2321 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2326 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2328 &output
[0], &output
[1] );
2331 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2332 &output
[0], &output
[1], &output
[2] );
2335 err
= (object
->*func
)( input
[0], input
[1],
2336 &output
[0], &output
[1], &output
[2],
2340 err
= (object
->*func
)( input
[0],
2341 &output
[0], &output
[1], &output
[2],
2342 &output
[3], &output
[4] );
2345 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
2346 &output
[3], &output
[4], &output
[5] );
2350 IOLog("%s: Bad method table\n", client
->getName());
2355 err
= kIOReturnUnsupported
;
2360 /* Routine io_connect_method_scalarI_structureO */
2361 kern_return_t
is_io_connect_method_scalarI_structureO(
2362 io_object_t connect
,
2365 IOByteCount inputCount
,
2367 IOByteCount
* outputCount
)
2370 IOExternalMethod
* method
;
2374 CHECK( IOUserClient
, connect
, client
);
2376 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2378 err
= kIOReturnBadArgument
;
2379 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2381 if( inputCount
!= method
->count0
)
2383 if( (0xffffffff != method
->count1
)
2384 && (*outputCount
!= method
->count1
))
2387 func
= method
->func
;
2389 switch( inputCount
) {
2392 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2397 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2399 output
, (void *)outputCount
);
2402 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2403 output
, (void *)outputCount
, 0 );
2406 err
= (object
->*func
)( input
[0], input
[1],
2407 output
, (void *)outputCount
, 0, 0 );
2410 err
= (object
->*func
)( input
[0],
2411 output
, (void *)outputCount
, 0, 0, 0 );
2414 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
2418 IOLog("%s: Bad method table\n", client
->getName());
2423 err
= kIOReturnUnsupported
;
2428 /* Routine io_connect_method_scalarI_structureI */
2429 kern_return_t
is_io_connect_method_scalarI_structureI(
2430 io_connect_t connect
,
2433 IOByteCount inputCount
,
2434 UInt8
* inputStruct
,
2435 IOByteCount inputStructCount
)
2438 IOExternalMethod
* method
;
2442 CHECK( IOUserClient
, connect
, client
);
2444 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2446 err
= kIOReturnBadArgument
;
2447 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2449 if( (0xffffffff != method
->count0
)
2450 && (inputCount
!= method
->count0
))
2452 if( (0xffffffff != method
->count1
)
2453 && (inputStructCount
!= method
->count1
))
2456 func
= method
->func
;
2458 switch( inputCount
) {
2461 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2466 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2468 inputStruct
, (void *)inputStructCount
);
2471 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2472 inputStruct
, (void *)inputStructCount
,
2476 err
= (object
->*func
)( input
[0], input
[1],
2477 inputStruct
, (void *)inputStructCount
,
2481 err
= (object
->*func
)( input
[0],
2482 inputStruct
, (void *)inputStructCount
,
2486 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
2491 IOLog("%s: Bad method table\n", client
->getName());
2496 err
= kIOReturnUnsupported
;
2501 /* Routine io_connect_method_structureI_structureO */
2502 kern_return_t
is_io_connect_method_structureI_structureO(
2503 io_object_t connect
,
2506 IOByteCount inputCount
,
2508 IOByteCount
* outputCount
)
2511 IOExternalMethod
* method
;
2515 CHECK( IOUserClient
, connect
, client
);
2517 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2519 err
= kIOReturnBadArgument
;
2520 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2522 if( (0xffffffff != method
->count0
)
2523 && (inputCount
!= method
->count0
))
2525 if( (0xffffffff != method
->count1
)
2526 && (*outputCount
!= method
->count1
))
2529 func
= method
->func
;
2531 if( method
->count1
) {
2532 if( method
->count0
) {
2533 err
= (object
->*func
)( input
, output
,
2534 (void *)inputCount
, outputCount
, 0, 0 );
2536 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2539 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2545 err
= kIOReturnUnsupported
;
2550 kern_return_t
is_io_async_method_scalarI_scalarO(
2551 io_object_t connect
,
2552 mach_port_t wakePort
,
2553 io_async_ref_t reference
,
2554 mach_msg_type_number_t referenceCnt
,
2557 IOByteCount inputCount
,
2559 IOByteCount
* outputCount
)
2562 IOExternalAsyncMethod
*method
;
2566 CHECK( IOUserClient
, connect
, client
);
2567 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2569 err
= kIOReturnBadArgument
;
2570 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2572 if( inputCount
!= method
->count0
)
2574 if( *outputCount
!= method
->count1
)
2577 reference
[0] = (natural_t
) wakePort
;
2578 func
= method
->func
;
2580 switch( inputCount
) {
2583 err
= (object
->*func
)( reference
,
2584 input
[0], input
[1], input
[2],
2585 input
[3], input
[4], input
[5] );
2588 err
= (object
->*func
)( reference
,
2589 input
[0], input
[1], input
[2],
2594 err
= (object
->*func
)( reference
,
2595 input
[0], input
[1], input
[2],
2597 &output
[0], &output
[1] );
2600 err
= (object
->*func
)( reference
,
2601 input
[0], input
[1], input
[2],
2602 &output
[0], &output
[1], &output
[2] );
2605 err
= (object
->*func
)( reference
,
2607 &output
[0], &output
[1], &output
[2],
2611 err
= (object
->*func
)( reference
,
2613 &output
[0], &output
[1], &output
[2],
2614 &output
[3], &output
[4] );
2617 err
= (object
->*func
)( reference
,
2618 &output
[0], &output
[1], &output
[2],
2619 &output
[3], &output
[4], &output
[5] );
2623 IOLog("%s: Bad method table\n", client
->getName());
2628 err
= kIOReturnUnsupported
;
2633 kern_return_t
is_io_async_method_scalarI_structureO(
2634 io_object_t connect
,
2635 mach_port_t wakePort
,
2636 io_async_ref_t reference
,
2637 mach_msg_type_number_t referenceCnt
,
2640 IOByteCount inputCount
,
2642 IOByteCount
* outputCount
)
2645 IOExternalAsyncMethod
*method
;
2649 CHECK( IOUserClient
, connect
, client
);
2651 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2653 err
= kIOReturnBadArgument
;
2654 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2656 if( inputCount
!= method
->count0
)
2658 if( (0xffffffff != method
->count1
)
2659 && (*outputCount
!= method
->count1
))
2662 reference
[0] = (natural_t
) wakePort
;
2663 func
= method
->func
;
2665 switch( inputCount
) {
2668 err
= (object
->*func
)( reference
,
2669 input
[0], input
[1], input
[2],
2674 err
= (object
->*func
)( reference
,
2675 input
[0], input
[1], input
[2],
2677 output
, (void *)outputCount
);
2680 err
= (object
->*func
)( reference
,
2681 input
[0], input
[1], input
[2],
2682 output
, (void *)outputCount
, 0 );
2685 err
= (object
->*func
)( reference
,
2687 output
, (void *)outputCount
, 0, 0 );
2690 err
= (object
->*func
)( reference
,
2692 output
, (void *)outputCount
, 0, 0, 0 );
2695 err
= (object
->*func
)( reference
,
2696 output
, (void *)outputCount
, 0, 0, 0, 0 );
2700 IOLog("%s: Bad method table\n", client
->getName());
2705 err
= kIOReturnUnsupported
;
2710 kern_return_t
is_io_async_method_scalarI_structureI(
2711 io_connect_t connect
,
2712 mach_port_t wakePort
,
2713 io_async_ref_t reference
,
2714 mach_msg_type_number_t referenceCnt
,
2717 IOByteCount inputCount
,
2718 UInt8
* inputStruct
,
2719 IOByteCount inputStructCount
)
2722 IOExternalAsyncMethod
*method
;
2726 CHECK( IOUserClient
, connect
, client
);
2728 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2730 err
= kIOReturnBadArgument
;
2731 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2733 if( (0xffffffff != method
->count0
)
2734 && (inputCount
!= method
->count0
))
2736 if( (0xffffffff != method
->count1
)
2737 && (inputStructCount
!= method
->count1
))
2740 reference
[0] = (natural_t
) wakePort
;
2741 func
= method
->func
;
2743 switch( inputCount
) {
2746 err
= (object
->*func
)( reference
,
2747 input
[0], input
[1], input
[2],
2752 err
= (object
->*func
)( reference
,
2753 input
[0], input
[1], input
[2],
2755 inputStruct
, (void *)inputStructCount
);
2758 err
= (object
->*func
)( reference
,
2759 input
[0], input
[1], input
[2],
2760 inputStruct
, (void *)inputStructCount
,
2764 err
= (object
->*func
)( reference
,
2766 inputStruct
, (void *)inputStructCount
,
2770 err
= (object
->*func
)( reference
,
2772 inputStruct
, (void *)inputStructCount
,
2776 err
= (object
->*func
)( reference
,
2777 inputStruct
, (void *)inputStructCount
,
2782 IOLog("%s: Bad method table\n", client
->getName());
2787 err
= kIOReturnUnsupported
;
2792 kern_return_t
is_io_async_method_structureI_structureO(
2793 io_object_t connect
,
2794 mach_port_t wakePort
,
2795 io_async_ref_t reference
,
2796 mach_msg_type_number_t referenceCnt
,
2799 IOByteCount inputCount
,
2801 IOByteCount
* outputCount
)
2804 IOExternalAsyncMethod
*method
;
2808 CHECK( IOUserClient
, connect
, client
);
2810 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2812 err
= kIOReturnBadArgument
;
2813 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2815 if( (0xffffffff != method
->count0
)
2816 && (inputCount
!= method
->count0
))
2818 if( (0xffffffff != method
->count1
)
2819 && (*outputCount
!= method
->count1
))
2822 reference
[0] = (natural_t
) wakePort
;
2823 func
= method
->func
;
2825 if( method
->count1
) {
2826 if( method
->count0
) {
2827 err
= (object
->*func
)( reference
,
2829 (void *)inputCount
, outputCount
, 0, 0 );
2831 err
= (object
->*func
)( reference
,
2832 output
, outputCount
, 0, 0, 0, 0 );
2835 err
= (object
->*func
)( reference
,
2836 input
, (void *)inputCount
, 0, 0, 0, 0 );
2842 err
= kIOReturnUnsupported
;
2846 /* Routine io_make_matching */
2847 kern_return_t
is_io_make_matching(
2848 mach_port_t master_port
,
2850 IOOptionBits options
,
2852 IOByteCount inputCount
,
2853 io_string_t matching
)
2856 IOReturn err
= kIOReturnSuccess
;
2857 OSDictionary
* dict
;
2859 if( master_port
!= master_device_port
)
2860 return( kIOReturnNotPrivileged
);
2864 case kIOServiceMatching
:
2865 dict
= IOService::serviceMatching( gIOServiceKey
);
2868 case kIOBSDNameMatching
:
2869 dict
= IOBSDNameMatching( (const char *) input
);
2872 case kIOOFPathMatching
:
2873 dict
= IOOFPathMatching( (const char *) input
,
2874 matching
, sizeof( io_string_t
));
2882 return( kIOReturnUnsupported
);
2885 s
= OSSerialize::withCapacity(4096);
2887 err
= kIOReturnNoMemory
;
2891 if( !dict
->serialize( s
)) {
2892 err
= kIOReturnUnsupported
;
2896 if( s
->getLength() > sizeof( io_string_t
)) {
2897 err
= kIOReturnNoMemory
;
2900 strcpy( matching
, s
->text());
2912 /* Routine io_catalog_send_data */
2913 kern_return_t
is_io_catalog_send_data(
2914 mach_port_t master_port
,
2916 io_buf_ptr_t inData
,
2917 mach_msg_type_number_t inDataCount
,
2922 kern_return_t kr
= kIOReturnError
;
2924 //printf("io_catalog_send_data called. flag: %d\n", flag);
2926 if( master_port
!= master_device_port
)
2927 return kIOReturnNotPrivileged
;
2929 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2930 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2931 return kIOReturnBadArgument
;
2934 vm_map_offset_t map_data
;
2936 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
2937 data
= CAST_DOWN(vm_offset_t
, map_data
);
2939 if( kr
!= KERN_SUCCESS
)
2942 // must return success after vm_map_copyout() succeeds
2945 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2946 vm_deallocate( kernel_map
, data
, inDataCount
);
2948 *result
= kIOReturnNoMemory
;
2949 return( KERN_SUCCESS
);
2955 case kIOCatalogAddDrivers
:
2956 case kIOCatalogAddDriversNoMatch
: {
2959 array
= OSDynamicCast(OSArray
, obj
);
2961 if ( !gIOCatalogue
->addDrivers( array
,
2962 flag
== kIOCatalogAddDrivers
) ) {
2963 kr
= kIOReturnError
;
2967 kr
= kIOReturnBadArgument
;
2972 case kIOCatalogRemoveDrivers
:
2973 case kIOCatalogRemoveDriversNoMatch
: {
2974 OSDictionary
* dict
;
2976 dict
= OSDynamicCast(OSDictionary
, obj
);
2978 if ( !gIOCatalogue
->removeDrivers( dict
,
2979 flag
== kIOCatalogRemoveDrivers
) ) {
2980 kr
= kIOReturnError
;
2984 kr
= kIOReturnBadArgument
;
2989 case kIOCatalogStartMatching
: {
2990 OSDictionary
* dict
;
2992 dict
= OSDynamicCast(OSDictionary
, obj
);
2994 if ( !gIOCatalogue
->startMatching( dict
) ) {
2995 kr
= kIOReturnError
;
2999 kr
= kIOReturnBadArgument
;
3004 case kIOCatalogRemoveKernelLinker
: {
3005 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
3006 kr
= kIOReturnError
;
3008 kr
= kIOReturnSuccess
;
3014 kr
= kIOReturnBadArgument
;
3018 if (obj
) obj
->release();
3021 return( KERN_SUCCESS
);
3024 /* Routine io_catalog_terminate */
3025 kern_return_t
is_io_catalog_terminate(
3026 mach_port_t master_port
,
3032 if( master_port
!= master_device_port
)
3033 return kIOReturnNotPrivileged
;
3035 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3036 kIOClientPrivilegeAdministrator
);
3037 if( kIOReturnSuccess
!= kr
)
3041 case kIOCatalogServiceTerminate
:
3043 IOService
* service
;
3045 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
3046 kIORegistryIterateRecursively
);
3048 return kIOReturnNoMemory
;
3052 while( (service
= (IOService
*)iter
->getNextObject()) ) {
3053 if( service
->metaCast(name
)) {
3054 if ( !service
->terminate( kIOServiceRequired
3055 | kIOServiceSynchronous
) ) {
3056 kr
= kIOReturnUnsupported
;
3061 } while( !service
&& !iter
->isValid());
3065 case kIOCatalogModuleUnload
:
3066 case kIOCatalogModuleTerminate
:
3067 kr
= gIOCatalogue
->terminateDriversForModule(name
,
3068 flag
== kIOCatalogModuleUnload
);
3072 kr
= kIOReturnBadArgument
;
3079 /* Routine io_catalog_get_data */
3080 kern_return_t
is_io_catalog_get_data(
3081 mach_port_t master_port
,
3083 io_buf_ptr_t
*outData
,
3084 mach_msg_type_number_t
*outDataCount
)
3086 kern_return_t kr
= kIOReturnSuccess
;
3089 if( master_port
!= master_device_port
)
3090 return kIOReturnNotPrivileged
;
3092 //printf("io_catalog_get_data called. flag: %d\n", flag);
3094 s
= OSSerialize::withCapacity(4096);
3096 return kIOReturnNoMemory
;
3100 kr
= gIOCatalogue
->serializeData(flag
, s
);
3102 if ( kr
== kIOReturnSuccess
) {
3107 size
= s
->getLength();
3108 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
3109 if ( kr
== kIOReturnSuccess
) {
3110 bcopy(s
->text(), (void *)data
, size
);
3111 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
3112 (vm_map_size_t
)size
, true, ©
);
3113 *outData
= (char *)copy
;
3114 *outDataCount
= size
;
3123 /* Routine io_catalog_get_gen_count */
3124 kern_return_t
is_io_catalog_get_gen_count(
3125 mach_port_t master_port
,
3128 if( master_port
!= master_device_port
)
3129 return kIOReturnNotPrivileged
;
3131 //printf("io_catalog_get_gen_count called.\n");
3134 return kIOReturnBadArgument
;
3136 *genCount
= gIOCatalogue
->getGenerationCount();
3138 return kIOReturnSuccess
;
3141 /* Routine io_catalog_module_loaded */
3142 kern_return_t
is_io_catalog_module_loaded(
3143 mach_port_t master_port
,
3146 if( master_port
!= master_device_port
)
3147 return kIOReturnNotPrivileged
;
3149 //printf("io_catalog_module_loaded called. name %s\n", name);
3152 return kIOReturnBadArgument
;
3154 gIOCatalogue
->moduleHasLoaded(name
);
3156 return kIOReturnSuccess
;
3159 kern_return_t
is_io_catalog_reset(
3160 mach_port_t master_port
,
3163 if( master_port
!= master_device_port
)
3164 return kIOReturnNotPrivileged
;
3167 case kIOCatalogResetDefault
:
3168 gIOCatalogue
->reset();
3172 return kIOReturnBadArgument
;
3175 return kIOReturnSuccess
;
3178 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
3180 kern_return_t result
= kIOReturnBadArgument
;
3181 IOUserClient
*userClient
;
3183 if ((userClient
= OSDynamicCast(IOUserClient
,
3184 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
3185 IOExternalTrap
*trap
;
3186 IOService
*target
= NULL
;
3188 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
3190 if (trap
&& target
) {
3196 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
3200 userClient
->release();
3208 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
3209 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
3210 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
3211 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
3212 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
3213 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
3214 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
3215 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
3216 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
3217 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
3218 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
3219 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
3220 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
3221 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
3222 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
3223 OSMetaClassDefineReservedUnused(IOUserClient
, 15);