2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 #include <IOKit/IOKitServer.h>
25 #include <IOKit/IOUserClient.h>
26 #include <IOKit/IOService.h>
27 #include <IOKit/IORegistryEntry.h>
28 #include <IOKit/IOCatalogue.h>
29 #include <IOKit/IOMemoryDescriptor.h>
30 #include <IOKit/IOLib.h>
32 #include <IOKit/assert.h>
34 #include "IOServicePrivate.h"
36 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
38 // definitions we should get from osfmk
40 //typedef struct ipc_port * ipc_port_t;
41 typedef natural_t ipc_kobject_type_t
;
43 #define IKOT_IOKIT_SPARE 27
44 #define IKOT_IOKIT_CONNECT 29
45 #define IKOT_IOKIT_OBJECT 30
49 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
50 ipc_kobject_type_t type
);
52 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
54 extern mach_port_name_t
iokit_make_send_right( task_t task
,
55 io_object_t obj
, ipc_kobject_type_t type
);
57 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
59 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
61 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
63 extern ipc_port_t master_device_port
;
65 extern void iokit_retain_port( ipc_port_t port
);
66 extern void iokit_release_port( ipc_port_t port
);
68 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
70 #include <mach/mach_traps.h>
71 #include <vm/vm_map.h>
76 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
78 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
80 class IOMachPort
: public OSObject
82 OSDeclareDefaultStructors(IOMachPort
)
89 static IOMachPort
* portForObject( OSObject
* obj
,
90 ipc_kobject_type_t type
);
91 static bool noMoreSendersForObject( OSObject
* obj
,
92 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
93 static void releasePortForObject( OSObject
* obj
,
94 ipc_kobject_type_t type
);
95 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
97 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
99 static mach_port_name_t
makeSendRightForTask( task_t task
,
100 io_object_t obj
, ipc_kobject_type_t type
);
105 #define super OSObject
106 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
108 static IOLock
* gIOObjectPortLock
;
110 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
112 // not in dictForType() for debugging ease
113 static OSDictionary
* gIOObjectPorts
;
114 static OSDictionary
* gIOConnectPorts
;
116 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
118 OSDictionary
** dict
;
120 if( IKOT_IOKIT_OBJECT
== type
)
121 dict
= &gIOObjectPorts
;
122 else if( IKOT_IOKIT_CONNECT
== type
)
123 dict
= &gIOConnectPorts
;
128 *dict
= OSDictionary::withCapacity( 1 );
133 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
134 ipc_kobject_type_t type
)
136 IOMachPort
* inst
= 0;
139 IOTakeLock( gIOObjectPortLock
);
143 dict
= dictForType( type
);
147 if( (inst
= (IOMachPort
*)
148 dict
->getObject( (const OSSymbol
*) obj
))) {
154 inst
= new IOMachPort
;
155 if( inst
&& !inst
->init()) {
160 inst
->port
= iokit_alloc_object_port( obj
, type
);
163 dict
->setObject( (const OSSymbol
*) obj
, inst
);
173 IOUnlock( gIOObjectPortLock
);
178 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
179 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
182 IOMachPort
* machPort
;
183 bool destroyed
= true;
185 IOTakeLock( gIOObjectPortLock
);
187 if( (dict
= dictForType( type
))) {
190 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
192 destroyed
= (machPort
->mscount
== *mscount
);
194 dict
->removeObject( (const OSSymbol
*) obj
);
196 *mscount
= machPort
->mscount
;
201 IOUnlock( gIOObjectPortLock
);
206 void IOMachPort::releasePortForObject( OSObject
* obj
,
207 ipc_kobject_type_t type
)
210 IOMachPort
* machPort
;
212 IOTakeLock( gIOObjectPortLock
);
214 if( (dict
= dictForType( type
))) {
216 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
217 if( machPort
&& !machPort
->holdDestroy
)
218 dict
->removeObject( (const OSSymbol
*) obj
);
222 IOUnlock( gIOObjectPortLock
);
225 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
228 IOMachPort
* machPort
;
230 IOLockLock( gIOObjectPortLock
);
232 if( (dict
= dictForType( type
))) {
233 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
235 machPort
->holdDestroy
= true;
238 IOLockUnlock( gIOObjectPortLock
);
241 void IOUserClient::destroyUserReferences( OSObject
* obj
)
243 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
246 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
250 IOTakeLock( gIOObjectPortLock
);
253 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
256 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
260 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
262 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
263 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
265 uc
->mappings
->release();
268 dict
->removeObject( (const OSSymbol
*) obj
);
272 IOUnlock( gIOObjectPortLock
);
275 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
276 io_object_t obj
, ipc_kobject_type_t type
)
278 return( iokit_make_send_right( task
, obj
, type
));
281 void IOMachPort::free( void )
284 iokit_destroy_object_port( port
);
288 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
290 class IOUserNotification
: public OSIterator
292 OSDeclareDefaultStructors(IOUserNotification
)
294 IONotifier
* holdNotify
;
299 virtual bool init( void );
302 virtual void setNotification( IONotifier
* obj
);
304 virtual void reset();
305 virtual bool isValid();
308 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
312 // functions called from osfmk/device/iokit_rpc.c
315 iokit_add_reference( io_object_t obj
)
322 iokit_remove_reference( io_object_t obj
)
329 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
331 IOMachPort
* machPort
;
334 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
336 port
= machPort
->port
;
338 iokit_retain_port( port
);
349 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
350 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
352 IOUserClient
* client
;
354 IOUserNotification
* notify
;
356 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
357 return( kIOReturnNotReady
);
359 if( IKOT_IOKIT_CONNECT
== type
)
361 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
362 client
->clientDied();
364 else if( IKOT_IOKIT_OBJECT
== type
)
366 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
368 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
369 notify
->setNotification( 0 );
372 return( kIOReturnSuccess
);
377 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
379 class IOServiceUserNotification
: public IOUserNotification
381 OSDeclareDefaultStructors(IOServiceUserNotification
)
384 mach_msg_header_t msgHdr
;
385 OSNotificationHeader notifyHeader
;
388 enum { kMaxOutstanding
= 1024 };
393 OSObject
* lastEntry
;
398 virtual bool init( mach_port_t port
, natural_t type
,
399 OSAsyncReference reference
);
402 static bool _handler( void * target
,
403 void * ref
, IOService
* newService
);
404 virtual bool handler( void * ref
, IOService
* newService
);
406 virtual OSObject
* getNextObject();
409 class IOServiceMessageUserNotification
: public IOUserNotification
411 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
414 mach_msg_header_t msgHdr
;
415 mach_msg_body_t msgBody
;
416 mach_msg_port_descriptor_t ports
[1];
417 OSNotificationHeader notifyHeader
;
425 virtual bool init( mach_port_t port
, natural_t type
,
426 OSAsyncReference reference
, vm_size_t extraSize
);
429 static IOReturn
_handler( void * target
, void * ref
,
430 UInt32 messageType
, IOService
* provider
,
431 void * messageArgument
, vm_size_t argSize
);
432 virtual IOReturn
handler( void * ref
,
433 UInt32 messageType
, IOService
* provider
,
434 void * messageArgument
, vm_size_t argSize
);
436 virtual OSObject
* getNextObject();
439 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
442 #define super OSIterator
443 OSDefineMetaClass( IOUserNotification
, OSIterator
)
444 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
446 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
448 bool IOUserNotification::init( void )
453 lock
= IOLockAlloc();
460 void IOUserNotification::free( void )
463 holdNotify
->remove();
464 // can't be in handler now
473 void IOUserNotification::setNotification( IONotifier
* notify
)
475 IONotifier
* previousNotify
;
477 IOLockLock( gIOObjectPortLock
);
479 previousNotify
= holdNotify
;
482 IOLockUnlock( gIOObjectPortLock
);
485 previousNotify
->remove();
488 void IOUserNotification::reset()
493 bool IOUserNotification::isValid()
498 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
501 #define super IOUserNotification
502 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
504 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
506 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
507 OSAsyncReference reference
)
509 newSet
= OSArray::withCapacity( 1 );
513 msgSize
= sizeof( PingMsg
) + 0;
514 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
518 bzero( pingMsg
, msgSize
);
520 pingMsg
->msgHdr
.msgh_remote_port
= port
;
521 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
522 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
523 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
524 pingMsg
->msgHdr
.msgh_size
= msgSize
;
525 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
527 pingMsg
->notifyHeader
.size
= 0;
528 pingMsg
->notifyHeader
.type
= type
;
529 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
531 return( super::init() );
534 void IOServiceUserNotification::free( void )
539 OSObject
* _lastEntry
;
543 _lastEntry
= lastEntry
;
548 if( _pingMsg
&& _msgSize
)
549 IOFree( _pingMsg
, _msgSize
);
552 _lastEntry
->release();
558 bool IOServiceUserNotification::_handler( void * target
,
559 void * ref
, IOService
* newService
)
561 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
564 bool IOServiceUserNotification::handler( void * ref
,
565 IOService
* newService
)
569 ipc_port_t port
= NULL
;
570 bool sendPing
= false;
574 count
= newSet
->getCount();
575 if( count
< kMaxOutstanding
) {
577 newSet
->setObject( newService
);
578 if( (sendPing
= (armed
&& (0 == count
))))
584 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
585 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
588 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
589 pingMsg
->msgHdr
.msgh_local_port
= port
;
591 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
593 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
594 pingMsg
->msgHdr
.msgh_size
);
596 iokit_release_port( port
);
598 if( KERN_SUCCESS
!= kr
)
599 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
605 OSObject
* IOServiceUserNotification::getNextObject()
613 lastEntry
->release();
615 count
= newSet
->getCount();
617 result
= newSet
->getObject( count
- 1 );
619 newSet
->removeObject( count
- 1);
631 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
633 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
635 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
637 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
638 OSAsyncReference reference
, vm_size_t extraSize
)
641 extraSize
+= sizeof(IOServiceInterestContent
);
642 msgSize
= sizeof( PingMsg
) + extraSize
;
643 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
647 bzero( pingMsg
, msgSize
);
649 pingMsg
->msgHdr
.msgh_remote_port
= port
;
650 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
652 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
653 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
654 pingMsg
->msgHdr
.msgh_size
= msgSize
;
655 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
657 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
659 pingMsg
->ports
[0].name
= 0;
660 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
661 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
663 pingMsg
->notifyHeader
.size
= extraSize
;
664 pingMsg
->notifyHeader
.type
= type
;
665 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
667 return( super::init() );
670 void IOServiceMessageUserNotification::free( void )
680 if( _pingMsg
&& _msgSize
)
681 IOFree( _pingMsg
, _msgSize
);
684 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
685 UInt32 messageType
, IOService
* provider
,
686 void * argument
, vm_size_t argSize
)
688 return( ((IOServiceMessageUserNotification
*) target
)->handler(
689 ref
, messageType
, provider
, argument
, argSize
));
692 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
693 UInt32 messageType
, IOService
* provider
,
694 void * messageArgument
, vm_size_t argSize
)
697 ipc_port_t thisPort
, providerPort
;
698 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
699 pingMsg
->notifyHeader
.content
;
701 data
->messageType
= messageType
;
703 argSize
= sizeof( messageArgument
);
704 data
->messageArgument
[0] = messageArgument
;
706 if( argSize
> kIOUserNotifyMaxMessageSize
)
707 argSize
= kIOUserNotifyMaxMessageSize
;
708 bcopy( messageArgument
, data
->messageArgument
, argSize
);
710 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
711 + sizeof( IOServiceInterestContent
)
712 - sizeof( data
->messageArgument
)
715 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
716 pingMsg
->ports
[0].name
= providerPort
;
717 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
718 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
719 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
720 pingMsg
->msgHdr
.msgh_size
);
722 iokit_release_port( thisPort
);
724 iokit_release_port( providerPort
);
726 if( KERN_SUCCESS
!= kr
)
727 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
729 return( kIOReturnSuccess
);
732 OSObject
* IOServiceMessageUserNotification::getNextObject()
737 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
740 #define super IOService
741 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
743 void IOUserClient::initialize( void )
745 gIOObjectPortLock
= IOLockAlloc();
747 assert( gIOObjectPortLock
);
750 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
751 mach_port_t wakePort
,
752 void *callback
, void *refcon
)
754 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
755 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
756 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
759 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
760 const char * privilegeName
)
763 security_token_t token
;
764 mach_msg_type_number_t count
;
766 count
= TASK_SECURITY_TOKEN_COUNT
;
767 kr
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
,
768 (task_info_t
) &token
, &count
);
770 if (KERN_SUCCESS
!= kr
)
772 else if (!strcmp(privilegeName
, kIOClientPrivilegeAdministrator
))
774 if (0 != token
.val
[0])
775 kr
= kIOReturnNotPrivileged
;
777 else if (!strcmp(privilegeName
, kIOClientPrivilegeLocalUser
))
780 OSDictionary
* user
= 0;
782 if ((array
= OSDynamicCast(OSArray
,
783 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
785 for (unsigned int idx
= 0;
786 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
790 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
791 && (token
.val
[0] == num
->unsigned32BitValue()))
797 kr
= kIOReturnNotPrivileged
;
800 kr
= kIOReturnUnsupported
;
805 bool IOUserClient::init()
807 if( getPropertyTable())
810 return super::init();
813 bool IOUserClient::init(OSDictionary
* dictionary
)
815 if( getPropertyTable())
818 return super::init(dictionary
);
821 bool IOUserClient::initWithTask(task_t owningTask
,
825 if( getPropertyTable())
828 return super::init();
831 bool IOUserClient::initWithTask(task_t owningTask
,
834 OSDictionary
* properties
)
838 ok
= super::init( properties
);
839 ok
&= initWithTask( owningTask
, securityID
, type
);
844 void IOUserClient::free()
852 IOReturn
IOUserClient::clientDied( void )
854 return( clientClose());
857 IOReturn
IOUserClient::clientClose( void )
859 return( kIOReturnUnsupported
);
862 IOService
* IOUserClient::getService( void )
867 IOReturn
IOUserClient::registerNotificationPort(
868 mach_port_t
/* port */,
872 return( kIOReturnUnsupported
);
875 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
876 semaphore_t
* semaphore
)
878 return( kIOReturnUnsupported
);
881 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
883 return( kIOReturnUnsupported
);
886 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
887 IOOptionBits
* options
,
888 IOMemoryDescriptor
** memory
)
890 return( kIOReturnUnsupported
);
893 IOMemoryMap
* IOUserClient::mapClientMemory(
896 IOOptionBits mapFlags
,
897 IOVirtualAddress atAddress
)
900 IOOptionBits options
= 0;
901 IOMemoryDescriptor
* memory
;
902 IOMemoryMap
* map
= 0;
904 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
906 if( memory
&& (kIOReturnSuccess
== err
)) {
908 options
= (options
& ~kIOMapUserOptionsMask
)
909 | (mapFlags
& kIOMapUserOptionsMask
);
910 map
= memory
->map( task
, atAddress
, options
);
917 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
918 OSObject
*obj
, io_object_t
*clientObj
)
920 mach_port_name_t name
;
922 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
925 *(mach_port_name_t
*)clientObj
= name
;
926 return kIOReturnSuccess
;
929 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
934 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
939 IOExternalMethod
* IOUserClient::
940 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
942 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
945 *targetP
= (IOService
*) method
->object
;
950 IOExternalAsyncMethod
* IOUserClient::
951 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
953 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
956 *targetP
= (IOService
*) method
->object
;
961 IOExternalTrap
* IOUserClient::
962 getExternalTrapForIndex(UInt32 index
)
967 IOExternalTrap
* IOUserClient::
968 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
970 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
973 *targetP
= trap
->object
;
979 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
980 IOReturn result
, void *args
[], UInt32 numArgs
)
983 mach_msg_header_t msgHdr
;
984 OSNotificationHeader notifyHdr
;
985 IOAsyncCompletionContent asyncContent
;
986 void * args
[kMaxAsyncArgs
];
989 mach_port_t replyPort
;
992 // If no reply port, do nothing.
993 replyPort
= (mach_port_t
) reference
[0];
994 if(replyPort
== MACH_PORT_NULL
)
995 return kIOReturnSuccess
;
997 if(numArgs
> kMaxAsyncArgs
)
998 return kIOReturnMessageTooLarge
;
999 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1001 replyMsg
.msgHdr
.msgh_size
=
1002 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
1003 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1004 replyMsg
.msgHdr
.msgh_local_port
= 0;
1005 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1007 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1008 + numArgs
*sizeof(void *);
1009 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1010 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
1012 replyMsg
.asyncContent
.result
= result
;
1014 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
1015 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
1016 replyMsg
.msgHdr
.msgh_size
);
1017 if( KERN_SUCCESS
!= kr
)
1018 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
1022 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1026 #define CHECK(cls,obj,out) \
1028 if( !(out = OSDynamicCast( cls, obj))) \
1029 return( kIOReturnBadArgument )
1031 /* Routine io_object_get_class */
1032 kern_return_t
is_io_object_get_class(
1034 io_name_t className
)
1036 const OSMetaClass
* my_obj
= NULL
;
1039 return( kIOReturnBadArgument
);
1041 my_obj
= object
->getMetaClass();
1043 return (kIOReturnNotFound
);
1046 strcpy( className
, my_obj
->getClassName());
1047 return( kIOReturnSuccess
);
1050 /* Routine io_object_get_superclass */
1051 kern_return_t
is_io_object_get_superclass(
1052 mach_port_t master_port
,
1054 io_name_t class_name
)
1056 const OSMetaClass
* my_obj
= NULL
;
1057 const OSMetaClass
* superclass
= NULL
;
1058 const OSSymbol
*my_name
= NULL
;
1059 const char *my_cstr
= NULL
;
1061 if (!obj_name
|| !class_name
)
1062 return (kIOReturnBadArgument
);
1064 if( master_port
!= master_device_port
)
1065 return( kIOReturnNotPrivileged
);
1067 my_name
= OSSymbol::withCString(obj_name
);
1070 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1074 superclass
= my_obj
->getSuperClass();
1078 return( kIOReturnNotFound
);
1081 my_cstr
= superclass
->getClassName();
1084 strncpy(class_name
, my_cstr
, sizeof(io_name_t
)-1);
1085 return( kIOReturnSuccess
);
1087 return (kIOReturnNotFound
);
1090 /* Routine io_object_get_bundle_identifier */
1091 kern_return_t
is_io_object_get_bundle_identifier(
1092 mach_port_t master_port
,
1094 io_name_t bundle_name
)
1096 const OSMetaClass
* my_obj
= NULL
;
1097 const OSSymbol
*my_name
= NULL
;
1098 const OSSymbol
*identifier
= NULL
;
1099 const char *my_cstr
= NULL
;
1101 if (!obj_name
|| !bundle_name
)
1102 return (kIOReturnBadArgument
);
1104 if( master_port
!= master_device_port
)
1105 return( kIOReturnNotPrivileged
);
1107 my_name
= OSSymbol::withCString(obj_name
);
1110 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1115 identifier
= my_obj
->getKmodName();
1118 return( kIOReturnNotFound
);
1121 my_cstr
= identifier
->getCStringNoCopy();
1123 strncpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
)-1);
1124 return( kIOReturnSuccess
);
1127 return (kIOReturnBadArgument
);
1130 /* Routine io_object_conforms_to */
1131 kern_return_t
is_io_object_conforms_to(
1133 io_name_t className
,
1134 boolean_t
*conforms
)
1137 return( kIOReturnBadArgument
);
1139 *conforms
= (0 != object
->metaCast( className
));
1140 return( kIOReturnSuccess
);
1143 /* Routine io_object_get_retain_count */
1144 kern_return_t
is_io_object_get_retain_count(
1149 return( kIOReturnBadArgument
);
1151 *retainCount
= object
->getRetainCount();
1152 return( kIOReturnSuccess
);
1155 /* Routine io_iterator_next */
1156 kern_return_t
is_io_iterator_next(
1157 io_object_t iterator
,
1158 io_object_t
*object
)
1162 CHECK( OSIterator
, iterator
, iter
);
1164 obj
= iter
->getNextObject();
1168 return( kIOReturnSuccess
);
1170 return( kIOReturnNoDevice
);
1173 /* Routine io_iterator_reset */
1174 kern_return_t
is_io_iterator_reset(
1175 io_object_t iterator
)
1177 CHECK( OSIterator
, iterator
, iter
);
1181 return( kIOReturnSuccess
);
1184 /* Routine io_iterator_is_valid */
1185 kern_return_t
is_io_iterator_is_valid(
1186 io_object_t iterator
,
1187 boolean_t
*is_valid
)
1189 CHECK( OSIterator
, iterator
, iter
);
1191 *is_valid
= iter
->isValid();
1193 return( kIOReturnSuccess
);
1196 /* Routine io_service_match_property_table */
1197 kern_return_t
is_io_service_match_property_table(
1198 io_service_t _service
,
1199 io_string_t matching
,
1200 boolean_t
*matches
)
1202 CHECK( IOService
, _service
, service
);
1206 OSDictionary
* dict
;
1208 obj
= OSUnserializeXML( matching
);
1210 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1211 *matches
= service
->passiveMatch( dict
);
1212 kr
= kIOReturnSuccess
;
1214 kr
= kIOReturnBadArgument
;
1222 /* Routine io_service_match_property_table_ool */
1223 kern_return_t
is_io_service_match_property_table_ool(
1224 io_object_t service
,
1225 io_buf_ptr_t matching
,
1226 mach_msg_type_number_t matchingCnt
,
1228 boolean_t
*matches
)
1232 vm_map_offset_t map_data
;
1234 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1235 data
= CAST_DOWN(vm_offset_t
, map_data
);
1237 if( KERN_SUCCESS
== kr
) {
1238 // must return success after vm_map_copyout() succeeds
1239 *result
= is_io_service_match_property_table( service
,
1240 (char *) data
, matches
);
1241 vm_deallocate( kernel_map
, data
, matchingCnt
);
1247 /* Routine io_service_get_matching_services */
1248 kern_return_t
is_io_service_get_matching_services(
1249 mach_port_t master_port
,
1250 io_string_t matching
,
1251 io_iterator_t
*existing
)
1255 OSDictionary
* dict
;
1257 if( master_port
!= master_device_port
)
1258 return( kIOReturnNotPrivileged
);
1260 obj
= OSUnserializeXML( matching
);
1262 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1263 *existing
= IOService::getMatchingServices( dict
);
1264 kr
= kIOReturnSuccess
;
1266 kr
= kIOReturnBadArgument
;
1274 /* Routine io_service_get_matching_services_ool */
1275 kern_return_t
is_io_service_get_matching_services_ool(
1276 mach_port_t master_port
,
1277 io_buf_ptr_t matching
,
1278 mach_msg_type_number_t matchingCnt
,
1280 io_object_t
*existing
)
1284 vm_map_offset_t map_data
;
1286 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1287 data
= CAST_DOWN(vm_offset_t
, map_data
);
1289 if( KERN_SUCCESS
== kr
) {
1290 // must return success after vm_map_copyout() succeeds
1291 *result
= is_io_service_get_matching_services( master_port
,
1292 (char *) data
, existing
);
1293 vm_deallocate( kernel_map
, data
, matchingCnt
);
1299 /* Routine io_service_add_notification */
1300 kern_return_t
is_io_service_add_notification(
1301 mach_port_t master_port
,
1302 io_name_t notification_type
,
1303 io_string_t matching
,
1305 io_async_ref_t reference
,
1306 mach_msg_type_number_t referenceCnt
,
1307 io_object_t
* notification
)
1309 IOServiceUserNotification
* userNotify
= 0;
1310 IONotifier
* notify
= 0;
1311 const OSSymbol
* sym
;
1312 OSDictionary
* dict
;
1314 unsigned long int userMsgType
;
1317 if( master_port
!= master_device_port
)
1318 return( kIOReturnNotPrivileged
);
1321 err
= kIOReturnNoResources
;
1323 if( !(sym
= OSSymbol::withCString( notification_type
)))
1324 err
= kIOReturnNoResources
;
1326 if( !(dict
= OSDynamicCast( OSDictionary
,
1327 OSUnserializeXML( matching
)))) {
1328 err
= kIOReturnBadArgument
;
1332 if( (sym
== gIOPublishNotification
)
1333 || (sym
== gIOFirstPublishNotification
))
1334 userMsgType
= kIOServicePublishNotificationType
;
1335 else if( (sym
== gIOMatchedNotification
)
1336 || (sym
== gIOFirstMatchNotification
))
1337 userMsgType
= kIOServiceMatchedNotificationType
;
1338 else if( sym
== gIOTerminatedNotification
)
1339 userMsgType
= kIOServiceTerminatedNotificationType
;
1341 userMsgType
= kLastIOKitNotificationType
;
1343 userNotify
= new IOServiceUserNotification
;
1345 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1347 userNotify
->release();
1353 notify
= IOService::addNotification( sym
, dict
,
1354 &userNotify
->_handler
, userNotify
);
1357 *notification
= userNotify
;
1358 userNotify
->setNotification( notify
);
1359 err
= kIOReturnSuccess
;
1361 err
= kIOReturnUnsupported
;
1373 /* Routine io_service_add_notification_ool */
1374 kern_return_t
is_io_service_add_notification_ool(
1375 mach_port_t master_port
,
1376 io_name_t notification_type
,
1377 io_buf_ptr_t matching
,
1378 mach_msg_type_number_t matchingCnt
,
1379 mach_port_t wake_port
,
1380 io_async_ref_t reference
,
1381 mach_msg_type_number_t referenceCnt
,
1383 io_object_t
*notification
)
1387 vm_map_offset_t map_data
;
1389 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1390 data
= CAST_DOWN(vm_offset_t
, map_data
);
1392 if( KERN_SUCCESS
== kr
) {
1393 // must return success after vm_map_copyout() succeeds
1394 *result
= is_io_service_add_notification( master_port
, notification_type
,
1395 (char *) data
, wake_port
, reference
, referenceCnt
, notification
);
1396 vm_deallocate( kernel_map
, data
, matchingCnt
);
1403 /* Routine io_service_add_notification_old */
1404 kern_return_t
is_io_service_add_notification_old(
1405 mach_port_t master_port
,
1406 io_name_t notification_type
,
1407 io_string_t matching
,
1410 io_object_t
* notification
)
1412 return( is_io_service_add_notification( master_port
, notification_type
,
1413 matching
, port
, &ref
, 1, notification
));
1416 /* Routine io_service_add_message_notification */
1417 kern_return_t
is_io_service_add_interest_notification(
1418 io_object_t _service
,
1419 io_name_t type_of_interest
,
1421 io_async_ref_t reference
,
1422 mach_msg_type_number_t referenceCnt
,
1423 io_object_t
* notification
)
1426 IOServiceMessageUserNotification
* userNotify
= 0;
1427 IONotifier
* notify
= 0;
1428 const OSSymbol
* sym
;
1431 CHECK( IOService
, _service
, service
);
1433 err
= kIOReturnNoResources
;
1434 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1436 userNotify
= new IOServiceMessageUserNotification
;
1438 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1439 reference
, kIOUserNotifyMaxMessageSize
)) {
1440 userNotify
->release();
1446 notify
= service
->registerInterest( sym
,
1447 &userNotify
->_handler
, userNotify
);
1449 *notification
= userNotify
;
1450 userNotify
->setNotification( notify
);
1451 err
= kIOReturnSuccess
;
1453 err
= kIOReturnUnsupported
;
1462 /* Routine io_service_acknowledge_notification */
1463 kern_return_t
is_io_service_acknowledge_notification(
1464 io_object_t _service
,
1465 natural_t notify_ref
,
1466 natural_t response
)
1468 CHECK( IOService
, _service
, service
);
1470 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1471 (IOOptionBits
) response
));
1475 /* Routine io_connect_get_semaphore */
1476 kern_return_t
is_io_connect_get_notification_semaphore(
1477 io_connect_t connection
,
1478 natural_t notification_type
,
1479 semaphore_t
*semaphore
)
1481 CHECK( IOUserClient
, connection
, client
);
1483 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1487 /* Routine io_registry_get_root_entry */
1488 kern_return_t
is_io_registry_get_root_entry(
1489 mach_port_t master_port
,
1492 IORegistryEntry
* entry
;
1494 if( master_port
!= master_device_port
)
1495 return( kIOReturnNotPrivileged
);
1497 entry
= IORegistryEntry::getRegistryRoot();
1502 return( kIOReturnSuccess
);
1505 /* Routine io_registry_create_iterator */
1506 kern_return_t
is_io_registry_create_iterator(
1507 mach_port_t master_port
,
1510 io_object_t
*iterator
)
1512 if( master_port
!= master_device_port
)
1513 return( kIOReturnNotPrivileged
);
1515 *iterator
= IORegistryIterator::iterateOver(
1516 IORegistryEntry::getPlane( plane
), options
);
1518 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1521 /* Routine io_registry_entry_create_iterator */
1522 kern_return_t
is_io_registry_entry_create_iterator(
1523 io_object_t registry_entry
,
1526 io_object_t
*iterator
)
1528 CHECK( IORegistryEntry
, registry_entry
, entry
);
1530 *iterator
= IORegistryIterator::iterateOver( entry
,
1531 IORegistryEntry::getPlane( plane
), options
);
1533 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1536 /* Routine io_registry_iterator_enter */
1537 kern_return_t
is_io_registry_iterator_enter_entry(
1538 io_object_t iterator
)
1540 CHECK( IORegistryIterator
, iterator
, iter
);
1544 return( kIOReturnSuccess
);
1547 /* Routine io_registry_iterator_exit */
1548 kern_return_t
is_io_registry_iterator_exit_entry(
1549 io_object_t iterator
)
1553 CHECK( IORegistryIterator
, iterator
, iter
);
1555 didIt
= iter
->exitEntry();
1557 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1560 /* Routine io_registry_entry_from_path */
1561 kern_return_t
is_io_registry_entry_from_path(
1562 mach_port_t master_port
,
1564 io_object_t
*registry_entry
)
1566 IORegistryEntry
* entry
;
1568 if( master_port
!= master_device_port
)
1569 return( kIOReturnNotPrivileged
);
1571 entry
= IORegistryEntry::fromPath( path
);
1573 *registry_entry
= entry
;
1575 return( kIOReturnSuccess
);
1578 /* Routine io_registry_entry_in_plane */
1579 kern_return_t
is_io_registry_entry_in_plane(
1580 io_object_t registry_entry
,
1582 boolean_t
*inPlane
)
1584 CHECK( IORegistryEntry
, registry_entry
, entry
);
1586 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1588 return( kIOReturnSuccess
);
1592 /* Routine io_registry_entry_get_path */
1593 kern_return_t
is_io_registry_entry_get_path(
1594 io_object_t registry_entry
,
1599 CHECK( IORegistryEntry
, registry_entry
, entry
);
1601 length
= sizeof( io_string_t
);
1602 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1603 return( kIOReturnSuccess
);
1605 return( kIOReturnBadArgument
);
1609 /* Routine io_registry_entry_get_name */
1610 kern_return_t
is_io_registry_entry_get_name(
1611 io_object_t registry_entry
,
1614 CHECK( IORegistryEntry
, registry_entry
, entry
);
1616 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1618 return( kIOReturnSuccess
);
1621 /* Routine io_registry_entry_get_name_in_plane */
1622 kern_return_t
is_io_registry_entry_get_name_in_plane(
1623 io_object_t registry_entry
,
1624 io_name_t planeName
,
1627 const IORegistryPlane
* plane
;
1628 CHECK( IORegistryEntry
, registry_entry
, entry
);
1631 plane
= IORegistryEntry::getPlane( planeName
);
1635 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1637 return( kIOReturnSuccess
);
1640 /* Routine io_registry_entry_get_location_in_plane */
1641 kern_return_t
is_io_registry_entry_get_location_in_plane(
1642 io_object_t registry_entry
,
1643 io_name_t planeName
,
1644 io_name_t location
)
1646 const IORegistryPlane
* plane
;
1647 CHECK( IORegistryEntry
, registry_entry
, entry
);
1650 plane
= IORegistryEntry::getPlane( planeName
);
1654 const char * cstr
= entry
->getLocation( plane
);
1657 strncpy( location
, cstr
, sizeof( io_name_t
));
1658 return( kIOReturnSuccess
);
1660 return( kIOReturnNotFound
);
1663 // Create a vm_map_copy_t or kalloc'ed data for memory
1664 // to be copied out. ipc will free after the copyout.
1666 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1667 io_buf_ptr_t
* buf
)
1672 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1673 false /* src_destroy */, ©
);
1675 assert( err
== KERN_SUCCESS
);
1676 if( err
== KERN_SUCCESS
)
1677 *buf
= (char *) copy
;
1682 /* Routine io_registry_entry_get_property */
1683 kern_return_t
is_io_registry_entry_get_property_bytes(
1684 io_object_t registry_entry
,
1685 io_name_t property_name
,
1686 io_scalar_inband_t buf
,
1687 mach_msg_type_number_t
*dataCnt
)
1695 unsigned int len
= 0;
1696 const void * bytes
= 0;
1697 IOReturn ret
= kIOReturnSuccess
;
1699 CHECK( IORegistryEntry
, registry_entry
, entry
);
1701 obj
= entry
->copyProperty(property_name
);
1703 return( kIOReturnNoResources
);
1705 // One day OSData will be a common container base class
1707 if( (data
= OSDynamicCast( OSData
, obj
))) {
1708 len
= data
->getLength();
1709 bytes
= data
->getBytesNoCopy();
1711 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1712 len
= str
->getLength() + 1;
1713 bytes
= str
->getCStringNoCopy();
1715 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1716 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1717 bytes
= boo
->isTrue() ? "Yes" : "No";
1719 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1720 offsetBytes
= off
->unsigned64BitValue();
1721 len
= off
->numberOfBytes();
1722 bytes
= &offsetBytes
;
1723 #ifdef __BIG_ENDIAN__
1724 bytes
= (const void *)
1725 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1729 ret
= kIOReturnBadArgument
;
1733 ret
= kIOReturnIPCError
;
1736 bcopy( bytes
, buf
, len
);
1745 /* Routine io_registry_entry_get_property */
1746 kern_return_t
is_io_registry_entry_get_property(
1747 io_object_t registry_entry
,
1748 io_name_t property_name
,
1749 io_buf_ptr_t
*properties
,
1750 mach_msg_type_number_t
*propertiesCnt
)
1756 CHECK( IORegistryEntry
, registry_entry
, entry
);
1758 obj
= entry
->copyProperty(property_name
);
1760 return( kIOReturnNotFound
);
1762 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1765 return( kIOReturnNoMemory
);
1769 if( obj
->serialize( s
)) {
1770 len
= s
->getLength();
1771 *propertiesCnt
= len
;
1772 err
= copyoutkdata( s
->text(), len
, properties
);
1775 err
= kIOReturnUnsupported
;
1783 /* Routine io_registry_entry_get_property_recursively */
1784 kern_return_t
is_io_registry_entry_get_property_recursively(
1785 io_object_t registry_entry
,
1787 io_name_t property_name
,
1789 io_buf_ptr_t
*properties
,
1790 mach_msg_type_number_t
*propertiesCnt
)
1796 CHECK( IORegistryEntry
, registry_entry
, entry
);
1798 obj
= entry
->copyProperty( property_name
,
1799 IORegistryEntry::getPlane( plane
), options
);
1801 return( kIOReturnNotFound
);
1803 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1806 return( kIOReturnNoMemory
);
1811 if( obj
->serialize( s
)) {
1812 len
= s
->getLength();
1813 *propertiesCnt
= len
;
1814 err
= copyoutkdata( s
->text(), len
, properties
);
1817 err
= kIOReturnUnsupported
;
1825 /* Routine io_registry_entry_get_properties */
1826 kern_return_t
is_io_registry_entry_get_properties(
1827 io_object_t registry_entry
,
1828 io_buf_ptr_t
*properties
,
1829 mach_msg_type_number_t
*propertiesCnt
)
1834 CHECK( IORegistryEntry
, registry_entry
, entry
);
1836 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1838 return( kIOReturnNoMemory
);
1842 if( entry
->serializeProperties( s
)) {
1843 len
= s
->getLength();
1844 *propertiesCnt
= len
;
1845 err
= copyoutkdata( s
->text(), len
, properties
);
1848 err
= kIOReturnUnsupported
;
1855 /* Routine io_registry_entry_set_properties */
1856 kern_return_t is_io_registry_entry_set_properties
1858 io_object_t registry_entry
,
1859 io_buf_ptr_t properties
,
1860 mach_msg_type_number_t propertiesCnt
,
1867 vm_map_offset_t map_data
;
1869 CHECK( IORegistryEntry
, registry_entry
, entry
);
1871 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
1872 data
= CAST_DOWN(vm_offset_t
, map_data
);
1874 if( KERN_SUCCESS
== err
) {
1876 // must return success after vm_map_copyout() succeeds
1877 obj
= OSUnserializeXML( (const char *) data
);
1878 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1881 res
= entry
->setProperties( obj
);
1884 res
= kIOReturnBadArgument
;
1892 /* Routine io_registry_entry_get_child_iterator */
1893 kern_return_t
is_io_registry_entry_get_child_iterator(
1894 io_object_t registry_entry
,
1896 io_object_t
*iterator
)
1898 CHECK( IORegistryEntry
, registry_entry
, entry
);
1900 *iterator
= entry
->getChildIterator(
1901 IORegistryEntry::getPlane( plane
));
1903 return( kIOReturnSuccess
);
1906 /* Routine io_registry_entry_get_parent_iterator */
1907 kern_return_t
is_io_registry_entry_get_parent_iterator(
1908 io_object_t registry_entry
,
1910 io_object_t
*iterator
)
1912 CHECK( IORegistryEntry
, registry_entry
, entry
);
1914 *iterator
= entry
->getParentIterator(
1915 IORegistryEntry::getPlane( plane
));
1917 return( kIOReturnSuccess
);
1920 /* Routine io_service_get_busy_state */
1921 kern_return_t
is_io_service_get_busy_state(
1922 io_object_t _service
,
1925 CHECK( IOService
, _service
, service
);
1927 *busyState
= service
->getBusyState();
1929 return( kIOReturnSuccess
);
1932 /* Routine io_service_get_state */
1933 kern_return_t
is_io_service_get_state(
1934 io_object_t _service
,
1937 CHECK( IOService
, _service
, service
);
1939 *state
= service
->getState();
1941 return( kIOReturnSuccess
);
1944 /* Routine io_service_wait_quiet */
1945 kern_return_t
is_io_service_wait_quiet(
1946 io_object_t _service
,
1947 mach_timespec_t wait_time
)
1949 CHECK( IOService
, _service
, service
);
1951 return( service
->waitQuiet( &wait_time
));
1954 /* Routine io_service_request_probe */
1955 kern_return_t
is_io_service_request_probe(
1956 io_object_t _service
,
1959 CHECK( IOService
, _service
, service
);
1961 return( service
->requestProbe( options
));
1965 /* Routine io_service_open */
1966 kern_return_t
is_io_service_open(
1967 io_object_t _service
,
1970 io_object_t
*connection
)
1972 IOUserClient
* client
;
1975 CHECK( IOService
, _service
, service
);
1977 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1978 connect_type
, 0, &client
);
1980 if( err
== kIOReturnSuccess
) {
1981 assert( OSDynamicCast(IOUserClient
, client
) );
1982 *connection
= client
;
1988 /* Routine io_service_open_ndr */
1989 kern_return_t
is_io_service_open_extended(
1990 io_object_t _service
,
1994 io_buf_ptr_t properties
,
1995 mach_msg_type_number_t propertiesCnt
,
1997 io_object_t
*connection
)
1999 IOUserClient
* client
= 0;
2000 kern_return_t err
= KERN_SUCCESS
;
2001 IOReturn res
= kIOReturnSuccess
;
2002 OSDictionary
* propertiesDict
= 0;
2004 bool disallowAccess
;
2006 CHECK( IOService
, _service
, service
);
2014 vm_map_offset_t map_data
;
2016 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2018 data
= CAST_DOWN(vm_offset_t
, map_data
);
2019 if (KERN_SUCCESS
== err
)
2021 // must return success after vm_map_copyout() succeeds
2022 obj
= OSUnserializeXML( (const char *) data
);
2023 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2024 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
2025 if (!propertiesDict
)
2027 res
= kIOReturnBadArgument
;
2032 if (kIOReturnSuccess
!= res
)
2036 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
2039 if (!propertiesDict
)
2040 propertiesDict
= OSDictionary::withCapacity(4);
2041 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
2045 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
2050 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
2051 connect_type
, propertiesDict
, &client
);
2054 propertiesDict
->release();
2056 if (res
== kIOReturnSuccess
)
2058 assert( OSDynamicCast(IOUserClient
, client
) );
2060 disallowAccess
= (crossEndian
2061 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
2062 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
2066 client
->clientClose();
2069 res
= kIOReturnUnsupported
;
2072 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
2077 *connection
= client
;
2083 /* Routine io_service_close */
2084 kern_return_t
is_io_service_close(
2085 io_object_t connection
)
2088 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2089 return( kIOReturnSuccess
);
2091 CHECK( IOUserClient
, connection
, client
);
2093 client
->clientClose();
2095 return( kIOReturnSuccess
);
2098 /* Routine io_connect_get_service */
2099 kern_return_t
is_io_connect_get_service(
2100 io_object_t connection
,
2101 io_object_t
*service
)
2103 IOService
* theService
;
2105 CHECK( IOUserClient
, connection
, client
);
2107 theService
= client
->getService();
2109 theService
->retain();
2111 *service
= theService
;
2113 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2116 /* Routine io_connect_set_notification_port */
2117 kern_return_t
is_io_connect_set_notification_port(
2118 io_object_t connection
,
2119 int notification_type
,
2123 CHECK( IOUserClient
, connection
, client
);
2125 return( client
->registerNotificationPort( port
, notification_type
,
2129 kern_return_t
is_io_connect_map_memory(
2130 io_object_t connect
,
2133 vm_address_t
* mapAddr
,
2134 vm_size_t
* mapSize
,
2140 CHECK( IOUserClient
, connect
, client
);
2142 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
2145 *mapAddr
= map
->getVirtualAddress();
2147 *mapSize
= map
->getLength();
2149 if( client
->sharedInstance
2150 || (task
!= current_task())) {
2151 // push a name out to the task owning the map,
2152 // so we can clean up maps
2154 mach_port_name_t name
=
2156 IOMachPort::makeSendRightForTask(
2157 task
, map
, IKOT_IOKIT_OBJECT
);
2161 // keep it with the user client
2162 IOLockLock( gIOObjectPortLock
);
2163 if( 0 == client
->mappings
)
2164 client
->mappings
= OSSet::withCapacity(2);
2165 if( client
->mappings
)
2166 client
->mappings
->setObject( map
);
2167 IOLockUnlock( gIOObjectPortLock
);
2170 err
= kIOReturnSuccess
;
2173 err
= kIOReturnBadArgument
;
2178 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2181 IOMemoryMap
* map
= 0;
2183 IOLockLock(gIOObjectPortLock
);
2185 iter
= OSCollectionIterator::withCollection(mappings
);
2188 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2190 if(mem
== map
->getMemoryDescriptor())
2193 mappings
->removeObject(map
);
2200 IOLockUnlock(gIOObjectPortLock
);
2205 kern_return_t
is_io_connect_unmap_memory(
2206 io_object_t connect
,
2209 vm_address_t mapAddr
)
2212 IOOptionBits options
= 0;
2213 IOMemoryDescriptor
* memory
;
2216 CHECK( IOUserClient
, connect
, client
);
2218 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
2220 if( memory
&& (kIOReturnSuccess
== err
)) {
2222 options
= (options
& ~kIOMapUserOptionsMask
)
2223 | kIOMapAnywhere
| kIOMapReference
;
2225 map
= memory
->map( task
, mapAddr
, options
);
2229 IOLockLock( gIOObjectPortLock
);
2230 if( client
->mappings
)
2231 client
->mappings
->removeObject( map
);
2232 IOLockUnlock( gIOObjectPortLock
);
2234 mach_port_name_t name
= 0;
2235 if (task
!= current_task())
2236 name
= IOMachPort::makeSendRightForTask( task
, map
, IKOT_IOKIT_OBJECT
);
2240 err
= iokit_mod_send_right( task
, name
, -2 );
2241 err
= kIOReturnSuccess
;
2244 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2245 if (task
== current_task())
2249 err
= kIOReturnBadArgument
;
2256 /* Routine io_connect_add_client */
2257 kern_return_t
is_io_connect_add_client(
2258 io_object_t connection
,
2259 io_object_t connect_to
)
2261 CHECK( IOUserClient
, connection
, client
);
2262 CHECK( IOUserClient
, connect_to
, to
);
2264 return( client
->connectClient( to
) );
2268 /* Routine io_connect_set_properties */
2269 kern_return_t
is_io_connect_set_properties(
2270 io_object_t connection
,
2271 io_buf_ptr_t properties
,
2272 mach_msg_type_number_t propertiesCnt
,
2275 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2279 /* Routine io_connect_method_scalarI_scalarO */
2280 kern_return_t
is_io_connect_method_scalarI_scalarO(
2281 io_object_t connect
,
2284 IOByteCount inputCount
,
2286 IOByteCount
* outputCount
)
2289 IOExternalMethod
* method
;
2293 CHECK( IOUserClient
, connect
, client
);
2294 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
2296 err
= kIOReturnBadArgument
;
2297 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2299 if( inputCount
!= method
->count0
)
2301 if( *outputCount
!= method
->count1
)
2304 func
= method
->func
;
2306 switch( inputCount
) {
2309 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2310 input
[3], input
[4], input
[5] );
2313 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2318 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2320 &output
[0], &output
[1] );
2323 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2324 &output
[0], &output
[1], &output
[2] );
2327 err
= (object
->*func
)( input
[0], input
[1],
2328 &output
[0], &output
[1], &output
[2],
2332 err
= (object
->*func
)( input
[0],
2333 &output
[0], &output
[1], &output
[2],
2334 &output
[3], &output
[4] );
2337 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
2338 &output
[3], &output
[4], &output
[5] );
2342 IOLog("%s: Bad method table\n", client
->getName());
2347 err
= kIOReturnUnsupported
;
2352 /* Routine io_connect_method_scalarI_structureO */
2353 kern_return_t
is_io_connect_method_scalarI_structureO(
2354 io_object_t connect
,
2357 IOByteCount inputCount
,
2359 IOByteCount
* outputCount
)
2362 IOExternalMethod
* method
;
2366 CHECK( IOUserClient
, connect
, client
);
2368 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2370 err
= kIOReturnBadArgument
;
2371 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2373 if( inputCount
!= method
->count0
)
2375 if( (0xffffffff != method
->count1
)
2376 && (*outputCount
!= method
->count1
))
2379 func
= method
->func
;
2381 switch( inputCount
) {
2384 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2389 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2391 output
, (void *)outputCount
);
2394 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2395 output
, (void *)outputCount
, 0 );
2398 err
= (object
->*func
)( input
[0], input
[1],
2399 output
, (void *)outputCount
, 0, 0 );
2402 err
= (object
->*func
)( input
[0],
2403 output
, (void *)outputCount
, 0, 0, 0 );
2406 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
2410 IOLog("%s: Bad method table\n", client
->getName());
2415 err
= kIOReturnUnsupported
;
2420 /* Routine io_connect_method_scalarI_structureI */
2421 kern_return_t
is_io_connect_method_scalarI_structureI(
2422 io_connect_t connect
,
2425 IOByteCount inputCount
,
2426 UInt8
* inputStruct
,
2427 IOByteCount inputStructCount
)
2430 IOExternalMethod
* method
;
2434 CHECK( IOUserClient
, connect
, client
);
2436 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2438 err
= kIOReturnBadArgument
;
2439 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2441 if( (0xffffffff != method
->count0
)
2442 && (inputCount
!= method
->count0
))
2444 if( (0xffffffff != method
->count1
)
2445 && (inputStructCount
!= method
->count1
))
2448 func
= method
->func
;
2450 switch( inputCount
) {
2453 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2458 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2460 inputStruct
, (void *)inputStructCount
);
2463 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2464 inputStruct
, (void *)inputStructCount
,
2468 err
= (object
->*func
)( input
[0], input
[1],
2469 inputStruct
, (void *)inputStructCount
,
2473 err
= (object
->*func
)( input
[0],
2474 inputStruct
, (void *)inputStructCount
,
2478 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
2483 IOLog("%s: Bad method table\n", client
->getName());
2488 err
= kIOReturnUnsupported
;
2493 /* Routine io_connect_method_structureI_structureO */
2494 kern_return_t
is_io_connect_method_structureI_structureO(
2495 io_object_t connect
,
2498 IOByteCount inputCount
,
2500 IOByteCount
* outputCount
)
2503 IOExternalMethod
* method
;
2507 CHECK( IOUserClient
, connect
, client
);
2509 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2511 err
= kIOReturnBadArgument
;
2512 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2514 if( (0xffffffff != method
->count0
)
2515 && (inputCount
!= method
->count0
))
2517 if( (0xffffffff != method
->count1
)
2518 && (*outputCount
!= method
->count1
))
2521 func
= method
->func
;
2523 if( method
->count1
) {
2524 if( method
->count0
) {
2525 err
= (object
->*func
)( input
, output
,
2526 (void *)inputCount
, outputCount
, 0, 0 );
2528 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2531 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2537 err
= kIOReturnUnsupported
;
2542 kern_return_t
is_io_async_method_scalarI_scalarO(
2543 io_object_t connect
,
2544 mach_port_t wakePort
,
2545 io_async_ref_t reference
,
2546 mach_msg_type_number_t referenceCnt
,
2549 IOByteCount inputCount
,
2551 IOByteCount
* outputCount
)
2554 IOExternalAsyncMethod
*method
;
2558 CHECK( IOUserClient
, connect
, client
);
2559 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2561 err
= kIOReturnBadArgument
;
2562 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2564 if( inputCount
!= method
->count0
)
2566 if( *outputCount
!= method
->count1
)
2569 reference
[0] = (natural_t
) wakePort
;
2570 func
= method
->func
;
2572 switch( inputCount
) {
2575 err
= (object
->*func
)( reference
,
2576 input
[0], input
[1], input
[2],
2577 input
[3], input
[4], input
[5] );
2580 err
= (object
->*func
)( reference
,
2581 input
[0], input
[1], input
[2],
2586 err
= (object
->*func
)( reference
,
2587 input
[0], input
[1], input
[2],
2589 &output
[0], &output
[1] );
2592 err
= (object
->*func
)( reference
,
2593 input
[0], input
[1], input
[2],
2594 &output
[0], &output
[1], &output
[2] );
2597 err
= (object
->*func
)( reference
,
2599 &output
[0], &output
[1], &output
[2],
2603 err
= (object
->*func
)( reference
,
2605 &output
[0], &output
[1], &output
[2],
2606 &output
[3], &output
[4] );
2609 err
= (object
->*func
)( reference
,
2610 &output
[0], &output
[1], &output
[2],
2611 &output
[3], &output
[4], &output
[5] );
2615 IOLog("%s: Bad method table\n", client
->getName());
2620 err
= kIOReturnUnsupported
;
2625 kern_return_t
is_io_async_method_scalarI_structureO(
2626 io_object_t connect
,
2627 mach_port_t wakePort
,
2628 io_async_ref_t reference
,
2629 mach_msg_type_number_t referenceCnt
,
2632 IOByteCount inputCount
,
2634 IOByteCount
* outputCount
)
2637 IOExternalAsyncMethod
*method
;
2641 CHECK( IOUserClient
, connect
, client
);
2643 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2645 err
= kIOReturnBadArgument
;
2646 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2648 if( inputCount
!= method
->count0
)
2650 if( (0xffffffff != method
->count1
)
2651 && (*outputCount
!= method
->count1
))
2654 reference
[0] = (natural_t
) wakePort
;
2655 func
= method
->func
;
2657 switch( inputCount
) {
2660 err
= (object
->*func
)( reference
,
2661 input
[0], input
[1], input
[2],
2666 err
= (object
->*func
)( reference
,
2667 input
[0], input
[1], input
[2],
2669 output
, (void *)outputCount
);
2672 err
= (object
->*func
)( reference
,
2673 input
[0], input
[1], input
[2],
2674 output
, (void *)outputCount
, 0 );
2677 err
= (object
->*func
)( reference
,
2679 output
, (void *)outputCount
, 0, 0 );
2682 err
= (object
->*func
)( reference
,
2684 output
, (void *)outputCount
, 0, 0, 0 );
2687 err
= (object
->*func
)( reference
,
2688 output
, (void *)outputCount
, 0, 0, 0, 0 );
2692 IOLog("%s: Bad method table\n", client
->getName());
2697 err
= kIOReturnUnsupported
;
2702 kern_return_t
is_io_async_method_scalarI_structureI(
2703 io_connect_t connect
,
2704 mach_port_t wakePort
,
2705 io_async_ref_t reference
,
2706 mach_msg_type_number_t referenceCnt
,
2709 IOByteCount inputCount
,
2710 UInt8
* inputStruct
,
2711 IOByteCount inputStructCount
)
2714 IOExternalAsyncMethod
*method
;
2718 CHECK( IOUserClient
, connect
, client
);
2720 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2722 err
= kIOReturnBadArgument
;
2723 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2725 if( (0xffffffff != method
->count0
)
2726 && (inputCount
!= method
->count0
))
2728 if( (0xffffffff != method
->count1
)
2729 && (inputStructCount
!= method
->count1
))
2732 reference
[0] = (natural_t
) wakePort
;
2733 func
= method
->func
;
2735 switch( inputCount
) {
2738 err
= (object
->*func
)( reference
,
2739 input
[0], input
[1], input
[2],
2744 err
= (object
->*func
)( reference
,
2745 input
[0], input
[1], input
[2],
2747 inputStruct
, (void *)inputStructCount
);
2750 err
= (object
->*func
)( reference
,
2751 input
[0], input
[1], input
[2],
2752 inputStruct
, (void *)inputStructCount
,
2756 err
= (object
->*func
)( reference
,
2758 inputStruct
, (void *)inputStructCount
,
2762 err
= (object
->*func
)( reference
,
2764 inputStruct
, (void *)inputStructCount
,
2768 err
= (object
->*func
)( reference
,
2769 inputStruct
, (void *)inputStructCount
,
2774 IOLog("%s: Bad method table\n", client
->getName());
2779 err
= kIOReturnUnsupported
;
2784 kern_return_t
is_io_async_method_structureI_structureO(
2785 io_object_t connect
,
2786 mach_port_t wakePort
,
2787 io_async_ref_t reference
,
2788 mach_msg_type_number_t referenceCnt
,
2791 IOByteCount inputCount
,
2793 IOByteCount
* outputCount
)
2796 IOExternalAsyncMethod
*method
;
2800 CHECK( IOUserClient
, connect
, client
);
2802 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2804 err
= kIOReturnBadArgument
;
2805 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2807 if( (0xffffffff != method
->count0
)
2808 && (inputCount
!= method
->count0
))
2810 if( (0xffffffff != method
->count1
)
2811 && (*outputCount
!= method
->count1
))
2814 reference
[0] = (natural_t
) wakePort
;
2815 func
= method
->func
;
2817 if( method
->count1
) {
2818 if( method
->count0
) {
2819 err
= (object
->*func
)( reference
,
2821 (void *)inputCount
, outputCount
, 0, 0 );
2823 err
= (object
->*func
)( reference
,
2824 output
, outputCount
, 0, 0, 0, 0 );
2827 err
= (object
->*func
)( reference
,
2828 input
, (void *)inputCount
, 0, 0, 0, 0 );
2834 err
= kIOReturnUnsupported
;
2838 /* Routine io_make_matching */
2839 kern_return_t
is_io_make_matching(
2840 mach_port_t master_port
,
2842 IOOptionBits options
,
2844 IOByteCount inputCount
,
2845 io_string_t matching
)
2848 IOReturn err
= kIOReturnSuccess
;
2849 OSDictionary
* dict
;
2851 if( master_port
!= master_device_port
)
2852 return( kIOReturnNotPrivileged
);
2856 case kIOServiceMatching
:
2857 dict
= IOService::serviceMatching( gIOServiceKey
);
2860 case kIOBSDNameMatching
:
2861 dict
= IOBSDNameMatching( (const char *) input
);
2864 case kIOOFPathMatching
:
2865 dict
= IOOFPathMatching( (const char *) input
,
2866 matching
, sizeof( io_string_t
));
2874 return( kIOReturnUnsupported
);
2877 s
= OSSerialize::withCapacity(4096);
2879 err
= kIOReturnNoMemory
;
2883 if( !dict
->serialize( s
)) {
2884 err
= kIOReturnUnsupported
;
2888 if( s
->getLength() > sizeof( io_string_t
)) {
2889 err
= kIOReturnNoMemory
;
2892 strcpy( matching
, s
->text());
2904 /* Routine io_catalog_send_data */
2905 kern_return_t
is_io_catalog_send_data(
2906 mach_port_t master_port
,
2908 io_buf_ptr_t inData
,
2909 mach_msg_type_number_t inDataCount
,
2914 kern_return_t kr
= kIOReturnError
;
2916 //printf("io_catalog_send_data called. flag: %d\n", flag);
2918 if( master_port
!= master_device_port
)
2919 return kIOReturnNotPrivileged
;
2921 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2922 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2923 return kIOReturnBadArgument
;
2926 vm_map_offset_t map_data
;
2928 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
2929 data
= CAST_DOWN(vm_offset_t
, map_data
);
2931 if( kr
!= KERN_SUCCESS
)
2934 // must return success after vm_map_copyout() succeeds
2937 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2938 vm_deallocate( kernel_map
, data
, inDataCount
);
2940 *result
= kIOReturnNoMemory
;
2941 return( KERN_SUCCESS
);
2947 case kIOCatalogAddDrivers
:
2948 case kIOCatalogAddDriversNoMatch
: {
2951 array
= OSDynamicCast(OSArray
, obj
);
2953 if ( !gIOCatalogue
->addDrivers( array
,
2954 flag
== kIOCatalogAddDrivers
) ) {
2955 kr
= kIOReturnError
;
2959 kr
= kIOReturnBadArgument
;
2964 case kIOCatalogRemoveDrivers
:
2965 case kIOCatalogRemoveDriversNoMatch
: {
2966 OSDictionary
* dict
;
2968 dict
= OSDynamicCast(OSDictionary
, obj
);
2970 if ( !gIOCatalogue
->removeDrivers( dict
,
2971 flag
== kIOCatalogRemoveDrivers
) ) {
2972 kr
= kIOReturnError
;
2976 kr
= kIOReturnBadArgument
;
2981 case kIOCatalogStartMatching
: {
2982 OSDictionary
* dict
;
2984 dict
= OSDynamicCast(OSDictionary
, obj
);
2986 if ( !gIOCatalogue
->startMatching( dict
) ) {
2987 kr
= kIOReturnError
;
2991 kr
= kIOReturnBadArgument
;
2996 case kIOCatalogRemoveKernelLinker
: {
2997 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
2998 kr
= kIOReturnError
;
3000 kr
= kIOReturnSuccess
;
3006 kr
= kIOReturnBadArgument
;
3010 if (obj
) obj
->release();
3013 return( KERN_SUCCESS
);
3016 /* Routine io_catalog_terminate */
3017 kern_return_t
is_io_catalog_terminate(
3018 mach_port_t master_port
,
3024 if( master_port
!= master_device_port
)
3025 return kIOReturnNotPrivileged
;
3027 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3028 kIOClientPrivilegeAdministrator
);
3029 if( kIOReturnSuccess
!= kr
)
3033 case kIOCatalogServiceTerminate
:
3035 IOService
* service
;
3037 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
3038 kIORegistryIterateRecursively
);
3040 return kIOReturnNoMemory
;
3044 while( (service
= (IOService
*)iter
->getNextObject()) ) {
3045 if( service
->metaCast(name
)) {
3046 if ( !service
->terminate( kIOServiceRequired
3047 | kIOServiceSynchronous
) ) {
3048 kr
= kIOReturnUnsupported
;
3053 } while( !service
&& !iter
->isValid());
3057 case kIOCatalogModuleUnload
:
3058 case kIOCatalogModuleTerminate
:
3059 kr
= gIOCatalogue
->terminateDriversForModule(name
,
3060 flag
== kIOCatalogModuleUnload
);
3064 kr
= kIOReturnBadArgument
;
3071 /* Routine io_catalog_get_data */
3072 kern_return_t
is_io_catalog_get_data(
3073 mach_port_t master_port
,
3075 io_buf_ptr_t
*outData
,
3076 mach_msg_type_number_t
*outDataCount
)
3078 kern_return_t kr
= kIOReturnSuccess
;
3081 if( master_port
!= master_device_port
)
3082 return kIOReturnNotPrivileged
;
3084 //printf("io_catalog_get_data called. flag: %d\n", flag);
3086 s
= OSSerialize::withCapacity(4096);
3088 return kIOReturnNoMemory
;
3092 kr
= gIOCatalogue
->serializeData(flag
, s
);
3094 if ( kr
== kIOReturnSuccess
) {
3099 size
= s
->getLength();
3100 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
3101 if ( kr
== kIOReturnSuccess
) {
3102 bcopy(s
->text(), (void *)data
, size
);
3103 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
3104 (vm_map_size_t
)size
, true, ©
);
3105 *outData
= (char *)copy
;
3106 *outDataCount
= size
;
3115 /* Routine io_catalog_get_gen_count */
3116 kern_return_t
is_io_catalog_get_gen_count(
3117 mach_port_t master_port
,
3120 if( master_port
!= master_device_port
)
3121 return kIOReturnNotPrivileged
;
3123 //printf("io_catalog_get_gen_count called.\n");
3126 return kIOReturnBadArgument
;
3128 *genCount
= gIOCatalogue
->getGenerationCount();
3130 return kIOReturnSuccess
;
3133 /* Routine io_catalog_module_loaded */
3134 kern_return_t
is_io_catalog_module_loaded(
3135 mach_port_t master_port
,
3138 if( master_port
!= master_device_port
)
3139 return kIOReturnNotPrivileged
;
3141 //printf("io_catalog_module_loaded called. name %s\n", name);
3144 return kIOReturnBadArgument
;
3146 gIOCatalogue
->moduleHasLoaded(name
);
3148 return kIOReturnSuccess
;
3151 kern_return_t
is_io_catalog_reset(
3152 mach_port_t master_port
,
3155 if( master_port
!= master_device_port
)
3156 return kIOReturnNotPrivileged
;
3159 case kIOCatalogResetDefault
:
3160 gIOCatalogue
->reset();
3164 return kIOReturnBadArgument
;
3167 return kIOReturnSuccess
;
3170 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
3172 kern_return_t result
= kIOReturnBadArgument
;
3173 IOUserClient
*userClient
;
3175 if ((userClient
= OSDynamicCast(IOUserClient
,
3176 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
3177 IOExternalTrap
*trap
;
3178 IOService
*target
= NULL
;
3180 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
3182 if (trap
&& target
) {
3188 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
3192 userClient
->release();
3200 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
3201 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
3202 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
3203 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
3204 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
3205 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
3206 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
3207 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
3208 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
3209 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
3210 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
3211 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
3212 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
3213 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
3214 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
3215 OSMetaClassDefineReservedUnused(IOUserClient
, 15);