2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <IOKit/IOKitServer.h>
31 #include <IOKit/IOKitKeysPrivate.h>
32 #include <IOKit/IOUserClient.h>
33 #include <IOKit/IOService.h>
34 #include <IOKit/IORegistryEntry.h>
35 #include <IOKit/IOCatalogue.h>
36 #include <IOKit/IOMemoryDescriptor.h>
37 #include <IOKit/IOLib.h>
39 #include <IOKit/assert.h>
41 #include "IOServicePrivate.h"
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45 // definitions we should get from osfmk
47 //typedef struct ipc_port * ipc_port_t;
48 typedef natural_t ipc_kobject_type_t
;
50 #define IKOT_IOKIT_SPARE 27
51 #define IKOT_IOKIT_CONNECT 29
52 #define IKOT_IOKIT_OBJECT 30
56 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
57 ipc_kobject_type_t type
);
59 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
61 extern mach_port_name_t
iokit_make_send_right( task_t task
,
62 io_object_t obj
, ipc_kobject_type_t type
);
64 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
66 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
68 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
70 extern ipc_port_t master_device_port
;
72 extern void iokit_retain_port( ipc_port_t port
);
73 extern void iokit_release_port( ipc_port_t port
);
75 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
77 #include <mach/mach_traps.h>
78 #include <vm/vm_map.h>
83 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
87 class IOMachPort
: public OSObject
89 OSDeclareDefaultStructors(IOMachPort
)
96 static IOMachPort
* portForObject( OSObject
* obj
,
97 ipc_kobject_type_t type
);
98 static bool noMoreSendersForObject( OSObject
* obj
,
99 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
100 static void releasePortForObject( OSObject
* obj
,
101 ipc_kobject_type_t type
);
102 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
104 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
106 static mach_port_name_t
makeSendRightForTask( task_t task
,
107 io_object_t obj
, ipc_kobject_type_t type
);
112 #define super OSObject
113 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
115 static IOLock
* gIOObjectPortLock
;
117 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
119 // not in dictForType() for debugging ease
120 static OSDictionary
* gIOObjectPorts
;
121 static OSDictionary
* gIOConnectPorts
;
123 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
125 OSDictionary
** dict
;
127 if( IKOT_IOKIT_OBJECT
== type
)
128 dict
= &gIOObjectPorts
;
129 else if( IKOT_IOKIT_CONNECT
== type
)
130 dict
= &gIOConnectPorts
;
135 *dict
= OSDictionary::withCapacity( 1 );
140 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
141 ipc_kobject_type_t type
)
143 IOMachPort
* inst
= 0;
146 IOTakeLock( gIOObjectPortLock
);
150 dict
= dictForType( type
);
154 if( (inst
= (IOMachPort
*)
155 dict
->getObject( (const OSSymbol
*) obj
))) {
161 inst
= new IOMachPort
;
162 if( inst
&& !inst
->init()) {
167 inst
->port
= iokit_alloc_object_port( obj
, type
);
170 dict
->setObject( (const OSSymbol
*) obj
, inst
);
180 IOUnlock( gIOObjectPortLock
);
185 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
186 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
189 IOMachPort
* machPort
;
190 bool destroyed
= true;
192 IOTakeLock( gIOObjectPortLock
);
194 if( (dict
= dictForType( type
))) {
197 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
199 destroyed
= (machPort
->mscount
== *mscount
);
201 dict
->removeObject( (const OSSymbol
*) obj
);
203 *mscount
= machPort
->mscount
;
208 IOUnlock( gIOObjectPortLock
);
213 void IOMachPort::releasePortForObject( OSObject
* obj
,
214 ipc_kobject_type_t type
)
217 IOMachPort
* machPort
;
219 IOTakeLock( gIOObjectPortLock
);
221 if( (dict
= dictForType( type
))) {
223 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
224 if( machPort
&& !machPort
->holdDestroy
)
225 dict
->removeObject( (const OSSymbol
*) obj
);
229 IOUnlock( gIOObjectPortLock
);
232 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
235 IOMachPort
* machPort
;
237 IOLockLock( gIOObjectPortLock
);
239 if( (dict
= dictForType( type
))) {
240 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
242 machPort
->holdDestroy
= true;
245 IOLockUnlock( gIOObjectPortLock
);
248 void IOUserClient::destroyUserReferences( OSObject
* obj
)
250 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
253 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
257 IOTakeLock( gIOObjectPortLock
);
260 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
263 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
267 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
269 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
270 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
272 uc
->mappings
->release();
275 dict
->removeObject( (const OSSymbol
*) obj
);
279 IOUnlock( gIOObjectPortLock
);
282 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
283 io_object_t obj
, ipc_kobject_type_t type
)
285 return( iokit_make_send_right( task
, obj
, type
));
288 void IOMachPort::free( void )
291 iokit_destroy_object_port( port
);
295 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
297 class IOUserNotification
: public OSIterator
299 OSDeclareDefaultStructors(IOUserNotification
)
301 IONotifier
* holdNotify
;
306 virtual bool init( void );
309 virtual void setNotification( IONotifier
* obj
);
311 virtual void reset();
312 virtual bool isValid();
315 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
319 // functions called from osfmk/device/iokit_rpc.c
322 iokit_add_reference( io_object_t obj
)
329 iokit_remove_reference( io_object_t obj
)
336 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
338 IOMachPort
* machPort
;
341 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
343 port
= machPort
->port
;
345 iokit_retain_port( port
);
356 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
357 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
359 IOUserClient
* client
;
361 IOUserNotification
* notify
;
363 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
364 return( kIOReturnNotReady
);
366 if( IKOT_IOKIT_CONNECT
== type
)
368 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
369 client
->clientDied();
371 else if( IKOT_IOKIT_OBJECT
== type
)
373 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
375 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
376 notify
->setNotification( 0 );
379 return( kIOReturnSuccess
);
384 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
386 class IOServiceUserNotification
: public IOUserNotification
388 OSDeclareDefaultStructors(IOServiceUserNotification
)
391 mach_msg_header_t msgHdr
;
392 OSNotificationHeader notifyHeader
;
395 enum { kMaxOutstanding
= 1024 };
400 OSObject
* lastEntry
;
405 virtual bool init( mach_port_t port
, natural_t type
,
406 OSAsyncReference reference
);
409 static bool _handler( void * target
,
410 void * ref
, IOService
* newService
);
411 virtual bool handler( void * ref
, IOService
* newService
);
413 virtual OSObject
* getNextObject();
416 class IOServiceMessageUserNotification
: public IOUserNotification
418 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
421 mach_msg_header_t msgHdr
;
422 mach_msg_body_t msgBody
;
423 mach_msg_port_descriptor_t ports
[1];
424 OSNotificationHeader notifyHeader
;
432 virtual bool init( mach_port_t port
, natural_t type
,
433 OSAsyncReference reference
, vm_size_t extraSize
);
436 static IOReturn
_handler( void * target
, void * ref
,
437 UInt32 messageType
, IOService
* provider
,
438 void * messageArgument
, vm_size_t argSize
);
439 virtual IOReturn
handler( void * ref
,
440 UInt32 messageType
, IOService
* provider
,
441 void * messageArgument
, vm_size_t argSize
);
443 virtual OSObject
* getNextObject();
446 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
449 #define super OSIterator
450 OSDefineMetaClass( IOUserNotification
, OSIterator
)
451 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
453 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
455 bool IOUserNotification::init( void )
460 lock
= IOLockAlloc();
467 void IOUserNotification::free( void )
470 holdNotify
->remove();
471 // can't be in handler now
480 void IOUserNotification::setNotification( IONotifier
* notify
)
482 IONotifier
* previousNotify
;
484 IOLockLock( gIOObjectPortLock
);
486 previousNotify
= holdNotify
;
489 IOLockUnlock( gIOObjectPortLock
);
492 previousNotify
->remove();
495 void IOUserNotification::reset()
500 bool IOUserNotification::isValid()
505 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
508 #define super IOUserNotification
509 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
511 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
513 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
514 OSAsyncReference reference
)
516 newSet
= OSArray::withCapacity( 1 );
520 msgSize
= sizeof( PingMsg
) + 0;
521 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
525 bzero( pingMsg
, msgSize
);
527 pingMsg
->msgHdr
.msgh_remote_port
= port
;
528 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
529 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
530 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
531 pingMsg
->msgHdr
.msgh_size
= msgSize
;
532 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
534 pingMsg
->notifyHeader
.size
= 0;
535 pingMsg
->notifyHeader
.type
= type
;
536 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
538 return( super::init() );
541 void IOServiceUserNotification::free( void )
546 OSObject
* _lastEntry
;
550 _lastEntry
= lastEntry
;
555 if( _pingMsg
&& _msgSize
)
556 IOFree( _pingMsg
, _msgSize
);
559 _lastEntry
->release();
565 bool IOServiceUserNotification::_handler( void * target
,
566 void * ref
, IOService
* newService
)
568 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
571 bool IOServiceUserNotification::handler( void * ref
,
572 IOService
* newService
)
576 ipc_port_t port
= NULL
;
577 bool sendPing
= false;
581 count
= newSet
->getCount();
582 if( count
< kMaxOutstanding
) {
584 newSet
->setObject( newService
);
585 if( (sendPing
= (armed
&& (0 == count
))))
591 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
592 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
595 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
596 pingMsg
->msgHdr
.msgh_local_port
= port
;
598 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
600 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
601 pingMsg
->msgHdr
.msgh_size
);
603 iokit_release_port( port
);
605 if( KERN_SUCCESS
!= kr
)
606 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
612 OSObject
* IOServiceUserNotification::getNextObject()
620 lastEntry
->release();
622 count
= newSet
->getCount();
624 result
= newSet
->getObject( count
- 1 );
626 newSet
->removeObject( count
- 1);
638 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
640 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
642 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
644 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
645 OSAsyncReference reference
, vm_size_t extraSize
)
648 extraSize
+= sizeof(IOServiceInterestContent
);
649 msgSize
= sizeof( PingMsg
) + extraSize
;
650 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
654 bzero( pingMsg
, msgSize
);
656 pingMsg
->msgHdr
.msgh_remote_port
= port
;
657 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
659 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
660 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
661 pingMsg
->msgHdr
.msgh_size
= msgSize
;
662 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
664 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
666 pingMsg
->ports
[0].name
= 0;
667 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
668 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
670 pingMsg
->notifyHeader
.size
= extraSize
;
671 pingMsg
->notifyHeader
.type
= type
;
672 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
674 return( super::init() );
677 void IOServiceMessageUserNotification::free( void )
687 if( _pingMsg
&& _msgSize
)
688 IOFree( _pingMsg
, _msgSize
);
691 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
692 UInt32 messageType
, IOService
* provider
,
693 void * argument
, vm_size_t argSize
)
695 return( ((IOServiceMessageUserNotification
*) target
)->handler(
696 ref
, messageType
, provider
, argument
, argSize
));
699 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
700 UInt32 messageType
, IOService
* provider
,
701 void * messageArgument
, vm_size_t argSize
)
704 ipc_port_t thisPort
, providerPort
;
705 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
706 pingMsg
->notifyHeader
.content
;
708 data
->messageType
= messageType
;
710 argSize
= sizeof( messageArgument
);
711 data
->messageArgument
[0] = messageArgument
;
713 if( argSize
> kIOUserNotifyMaxMessageSize
)
714 argSize
= kIOUserNotifyMaxMessageSize
;
715 bcopy( messageArgument
, data
->messageArgument
, argSize
);
717 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
718 + sizeof( IOServiceInterestContent
)
719 - sizeof( data
->messageArgument
)
722 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
723 pingMsg
->ports
[0].name
= providerPort
;
724 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
725 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
726 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
727 pingMsg
->msgHdr
.msgh_size
);
729 iokit_release_port( thisPort
);
731 iokit_release_port( providerPort
);
733 if( KERN_SUCCESS
!= kr
)
734 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
736 return( kIOReturnSuccess
);
739 OSObject
* IOServiceMessageUserNotification::getNextObject()
744 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
747 #define super IOService
748 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
750 void IOUserClient::initialize( void )
752 gIOObjectPortLock
= IOLockAlloc();
754 assert( gIOObjectPortLock
);
757 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
758 mach_port_t wakePort
,
759 void *callback
, void *refcon
)
761 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
762 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
763 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
766 inline OSDictionary
* CopyConsoleUser(UInt32 uid
)
769 OSDictionary
* user
= 0;
771 if ((array
= OSDynamicCast(OSArray
,
772 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
774 for (unsigned int idx
= 0;
775 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
779 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
780 && (uid
== num
->unsigned32BitValue())) {
790 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
791 const char * privilegeName
)
794 security_token_t token
;
795 mach_msg_type_number_t count
;
800 if ((secureConsole
= !strcmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
)))
801 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
803 task
= (task_t
)securityToken
;
805 count
= TASK_SECURITY_TOKEN_COUNT
;
806 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
808 if (KERN_SUCCESS
!= kr
)
810 else if (!strcmp(privilegeName
, kIOClientPrivilegeAdministrator
)) {
811 if (0 != token
.val
[0])
812 kr
= kIOReturnNotPrivileged
;
813 } else if (!strcmp(privilegeName
, kIOClientPrivilegeLocalUser
)) {
814 user
= CopyConsoleUser(token
.val
[0]);
818 kr
= kIOReturnNotPrivileged
;
819 } else if (secureConsole
|| !strcmp(privilegeName
, kIOClientPrivilegeConsoleUser
)) {
820 user
= CopyConsoleUser(token
.val
[0]);
822 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
823 kr
= kIOReturnNotPrivileged
;
824 else if ( secureConsole
) {
825 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
826 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
827 kr
= kIOReturnNotPrivileged
;
832 kr
= kIOReturnNotPrivileged
;
834 kr
= kIOReturnUnsupported
;
839 bool IOUserClient::init()
841 if( getPropertyTable())
844 return super::init();
847 bool IOUserClient::init(OSDictionary
* dictionary
)
849 if( getPropertyTable())
852 return super::init(dictionary
);
855 bool IOUserClient::initWithTask(task_t owningTask
,
859 if( getPropertyTable())
862 return super::init();
865 bool IOUserClient::initWithTask(task_t owningTask
,
868 OSDictionary
* properties
)
872 ok
= super::init( properties
);
873 ok
&= initWithTask( owningTask
, securityID
, type
);
878 void IOUserClient::free()
886 IOReturn
IOUserClient::clientDied( void )
888 return( clientClose());
891 IOReturn
IOUserClient::clientClose( void )
893 return( kIOReturnUnsupported
);
896 IOService
* IOUserClient::getService( void )
901 IOReturn
IOUserClient::registerNotificationPort(
902 mach_port_t
/* port */,
906 return( kIOReturnUnsupported
);
909 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
910 semaphore_t
* semaphore
)
912 return( kIOReturnUnsupported
);
915 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
917 return( kIOReturnUnsupported
);
920 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
921 IOOptionBits
* options
,
922 IOMemoryDescriptor
** memory
)
924 return( kIOReturnUnsupported
);
927 IOMemoryMap
* IOUserClient::mapClientMemory(
930 IOOptionBits mapFlags
,
931 IOVirtualAddress atAddress
)
934 IOOptionBits options
= 0;
935 IOMemoryDescriptor
* memory
;
936 IOMemoryMap
* map
= 0;
938 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
940 if( memory
&& (kIOReturnSuccess
== err
)) {
942 options
= (options
& ~kIOMapUserOptionsMask
)
943 | (mapFlags
& kIOMapUserOptionsMask
);
944 map
= memory
->map( task
, atAddress
, options
);
951 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
952 OSObject
*obj
, io_object_t
*clientObj
)
954 mach_port_name_t name
;
956 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
959 *(mach_port_name_t
*)clientObj
= name
;
960 return kIOReturnSuccess
;
963 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
968 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
973 IOExternalMethod
* IOUserClient::
974 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
976 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
979 *targetP
= (IOService
*) method
->object
;
984 IOExternalAsyncMethod
* IOUserClient::
985 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
987 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
990 *targetP
= (IOService
*) method
->object
;
995 IOExternalTrap
* IOUserClient::
996 getExternalTrapForIndex(UInt32 index
)
1001 IOExternalTrap
* IOUserClient::
1002 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1004 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1007 *targetP
= trap
->object
;
1013 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1014 IOReturn result
, void *args
[], UInt32 numArgs
)
1017 mach_msg_header_t msgHdr
;
1018 OSNotificationHeader notifyHdr
;
1019 IOAsyncCompletionContent asyncContent
;
1020 void * args
[kMaxAsyncArgs
];
1023 mach_port_t replyPort
;
1026 // If no reply port, do nothing.
1027 replyPort
= (mach_port_t
) reference
[0];
1028 if(replyPort
== MACH_PORT_NULL
)
1029 return kIOReturnSuccess
;
1031 if(numArgs
> kMaxAsyncArgs
)
1032 return kIOReturnMessageTooLarge
;
1033 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1035 replyMsg
.msgHdr
.msgh_size
=
1036 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
1037 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1038 replyMsg
.msgHdr
.msgh_local_port
= 0;
1039 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1041 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1042 + numArgs
*sizeof(void *);
1043 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1044 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
1046 replyMsg
.asyncContent
.result
= result
;
1048 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
1049 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
1050 replyMsg
.msgHdr
.msgh_size
);
1051 if( KERN_SUCCESS
!= kr
)
1052 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
1056 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1060 #define CHECK(cls,obj,out) \
1062 if( !(out = OSDynamicCast( cls, obj))) \
1063 return( kIOReturnBadArgument )
1065 /* Routine io_object_get_class */
1066 kern_return_t
is_io_object_get_class(
1068 io_name_t className
)
1070 const OSMetaClass
* my_obj
= NULL
;
1073 return( kIOReturnBadArgument
);
1075 my_obj
= object
->getMetaClass();
1077 return (kIOReturnNotFound
);
1080 strcpy( className
, my_obj
->getClassName());
1081 return( kIOReturnSuccess
);
1084 /* Routine io_object_get_superclass */
1085 kern_return_t
is_io_object_get_superclass(
1086 mach_port_t master_port
,
1088 io_name_t class_name
)
1090 const OSMetaClass
* my_obj
= NULL
;
1091 const OSMetaClass
* superclass
= NULL
;
1092 const OSSymbol
*my_name
= NULL
;
1093 const char *my_cstr
= NULL
;
1095 if (!obj_name
|| !class_name
)
1096 return (kIOReturnBadArgument
);
1098 if( master_port
!= master_device_port
)
1099 return( kIOReturnNotPrivileged
);
1101 my_name
= OSSymbol::withCString(obj_name
);
1104 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1108 superclass
= my_obj
->getSuperClass();
1112 return( kIOReturnNotFound
);
1115 my_cstr
= superclass
->getClassName();
1118 strncpy(class_name
, my_cstr
, sizeof(io_name_t
)-1);
1119 return( kIOReturnSuccess
);
1121 return (kIOReturnNotFound
);
1124 /* Routine io_object_get_bundle_identifier */
1125 kern_return_t
is_io_object_get_bundle_identifier(
1126 mach_port_t master_port
,
1128 io_name_t bundle_name
)
1130 const OSMetaClass
* my_obj
= NULL
;
1131 const OSSymbol
*my_name
= NULL
;
1132 const OSSymbol
*identifier
= NULL
;
1133 const char *my_cstr
= NULL
;
1135 if (!obj_name
|| !bundle_name
)
1136 return (kIOReturnBadArgument
);
1138 if( master_port
!= master_device_port
)
1139 return( kIOReturnNotPrivileged
);
1141 my_name
= OSSymbol::withCString(obj_name
);
1144 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1149 identifier
= my_obj
->getKmodName();
1152 return( kIOReturnNotFound
);
1155 my_cstr
= identifier
->getCStringNoCopy();
1157 strncpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
)-1);
1158 return( kIOReturnSuccess
);
1161 return (kIOReturnBadArgument
);
1164 /* Routine io_object_conforms_to */
1165 kern_return_t
is_io_object_conforms_to(
1167 io_name_t className
,
1168 boolean_t
*conforms
)
1171 return( kIOReturnBadArgument
);
1173 *conforms
= (0 != object
->metaCast( className
));
1174 return( kIOReturnSuccess
);
1177 /* Routine io_object_get_retain_count */
1178 kern_return_t
is_io_object_get_retain_count(
1183 return( kIOReturnBadArgument
);
1185 *retainCount
= object
->getRetainCount();
1186 return( kIOReturnSuccess
);
1189 /* Routine io_iterator_next */
1190 kern_return_t
is_io_iterator_next(
1191 io_object_t iterator
,
1192 io_object_t
*object
)
1196 CHECK( OSIterator
, iterator
, iter
);
1198 obj
= iter
->getNextObject();
1202 return( kIOReturnSuccess
);
1204 return( kIOReturnNoDevice
);
1207 /* Routine io_iterator_reset */
1208 kern_return_t
is_io_iterator_reset(
1209 io_object_t iterator
)
1211 CHECK( OSIterator
, iterator
, iter
);
1215 return( kIOReturnSuccess
);
1218 /* Routine io_iterator_is_valid */
1219 kern_return_t
is_io_iterator_is_valid(
1220 io_object_t iterator
,
1221 boolean_t
*is_valid
)
1223 CHECK( OSIterator
, iterator
, iter
);
1225 *is_valid
= iter
->isValid();
1227 return( kIOReturnSuccess
);
1230 /* Routine io_service_match_property_table */
1231 kern_return_t
is_io_service_match_property_table(
1232 io_service_t _service
,
1233 io_string_t matching
,
1234 boolean_t
*matches
)
1236 CHECK( IOService
, _service
, service
);
1240 OSDictionary
* dict
;
1242 obj
= OSUnserializeXML( matching
);
1244 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1245 *matches
= service
->passiveMatch( dict
);
1246 kr
= kIOReturnSuccess
;
1248 kr
= kIOReturnBadArgument
;
1256 /* Routine io_service_match_property_table_ool */
1257 kern_return_t
is_io_service_match_property_table_ool(
1258 io_object_t service
,
1259 io_buf_ptr_t matching
,
1260 mach_msg_type_number_t matchingCnt
,
1262 boolean_t
*matches
)
1266 vm_map_offset_t map_data
;
1268 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1269 data
= CAST_DOWN(vm_offset_t
, map_data
);
1271 if( KERN_SUCCESS
== kr
) {
1272 // must return success after vm_map_copyout() succeeds
1273 *result
= is_io_service_match_property_table( service
,
1274 (char *) data
, matches
);
1275 vm_deallocate( kernel_map
, data
, matchingCnt
);
1281 /* Routine io_service_get_matching_services */
1282 kern_return_t
is_io_service_get_matching_services(
1283 mach_port_t master_port
,
1284 io_string_t matching
,
1285 io_iterator_t
*existing
)
1289 OSDictionary
* dict
;
1291 if( master_port
!= master_device_port
)
1292 return( kIOReturnNotPrivileged
);
1294 obj
= OSUnserializeXML( matching
);
1296 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1297 *existing
= IOService::getMatchingServices( dict
);
1298 kr
= kIOReturnSuccess
;
1300 kr
= kIOReturnBadArgument
;
1308 /* Routine io_service_get_matching_services_ool */
1309 kern_return_t
is_io_service_get_matching_services_ool(
1310 mach_port_t master_port
,
1311 io_buf_ptr_t matching
,
1312 mach_msg_type_number_t matchingCnt
,
1314 io_object_t
*existing
)
1318 vm_map_offset_t map_data
;
1320 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1321 data
= CAST_DOWN(vm_offset_t
, map_data
);
1323 if( KERN_SUCCESS
== kr
) {
1324 // must return success after vm_map_copyout() succeeds
1325 *result
= is_io_service_get_matching_services( master_port
,
1326 (char *) data
, existing
);
1327 vm_deallocate( kernel_map
, data
, matchingCnt
);
1333 /* Routine io_service_add_notification */
1334 kern_return_t
is_io_service_add_notification(
1335 mach_port_t master_port
,
1336 io_name_t notification_type
,
1337 io_string_t matching
,
1339 io_async_ref_t reference
,
1340 mach_msg_type_number_t referenceCnt
,
1341 io_object_t
* notification
)
1343 IOServiceUserNotification
* userNotify
= 0;
1344 IONotifier
* notify
= 0;
1345 const OSSymbol
* sym
;
1346 OSDictionary
* dict
;
1348 unsigned long int userMsgType
;
1351 if( master_port
!= master_device_port
)
1352 return( kIOReturnNotPrivileged
);
1355 err
= kIOReturnNoResources
;
1357 if( !(sym
= OSSymbol::withCString( notification_type
)))
1358 err
= kIOReturnNoResources
;
1360 if( !(dict
= OSDynamicCast( OSDictionary
,
1361 OSUnserializeXML( matching
)))) {
1362 err
= kIOReturnBadArgument
;
1366 if( (sym
== gIOPublishNotification
)
1367 || (sym
== gIOFirstPublishNotification
))
1368 userMsgType
= kIOServicePublishNotificationType
;
1369 else if( (sym
== gIOMatchedNotification
)
1370 || (sym
== gIOFirstMatchNotification
))
1371 userMsgType
= kIOServiceMatchedNotificationType
;
1372 else if( sym
== gIOTerminatedNotification
)
1373 userMsgType
= kIOServiceTerminatedNotificationType
;
1375 userMsgType
= kLastIOKitNotificationType
;
1377 userNotify
= new IOServiceUserNotification
;
1379 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1381 userNotify
->release();
1387 notify
= IOService::addNotification( sym
, dict
,
1388 &userNotify
->_handler
, userNotify
);
1391 *notification
= userNotify
;
1392 userNotify
->setNotification( notify
);
1393 err
= kIOReturnSuccess
;
1395 err
= kIOReturnUnsupported
;
1407 /* Routine io_service_add_notification_ool */
1408 kern_return_t
is_io_service_add_notification_ool(
1409 mach_port_t master_port
,
1410 io_name_t notification_type
,
1411 io_buf_ptr_t matching
,
1412 mach_msg_type_number_t matchingCnt
,
1413 mach_port_t wake_port
,
1414 io_async_ref_t reference
,
1415 mach_msg_type_number_t referenceCnt
,
1417 io_object_t
*notification
)
1421 vm_map_offset_t map_data
;
1423 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1424 data
= CAST_DOWN(vm_offset_t
, map_data
);
1426 if( KERN_SUCCESS
== kr
) {
1427 // must return success after vm_map_copyout() succeeds
1428 *result
= is_io_service_add_notification( master_port
, notification_type
,
1429 (char *) data
, wake_port
, reference
, referenceCnt
, notification
);
1430 vm_deallocate( kernel_map
, data
, matchingCnt
);
1437 /* Routine io_service_add_notification_old */
1438 kern_return_t
is_io_service_add_notification_old(
1439 mach_port_t master_port
,
1440 io_name_t notification_type
,
1441 io_string_t matching
,
1444 io_object_t
* notification
)
1446 return( is_io_service_add_notification( master_port
, notification_type
,
1447 matching
, port
, &ref
, 1, notification
));
1450 /* Routine io_service_add_message_notification */
1451 kern_return_t
is_io_service_add_interest_notification(
1452 io_object_t _service
,
1453 io_name_t type_of_interest
,
1455 io_async_ref_t reference
,
1456 mach_msg_type_number_t referenceCnt
,
1457 io_object_t
* notification
)
1460 IOServiceMessageUserNotification
* userNotify
= 0;
1461 IONotifier
* notify
= 0;
1462 const OSSymbol
* sym
;
1465 CHECK( IOService
, _service
, service
);
1467 err
= kIOReturnNoResources
;
1468 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1470 userNotify
= new IOServiceMessageUserNotification
;
1472 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1473 reference
, kIOUserNotifyMaxMessageSize
)) {
1474 userNotify
->release();
1480 notify
= service
->registerInterest( sym
,
1481 &userNotify
->_handler
, userNotify
);
1483 *notification
= userNotify
;
1484 userNotify
->setNotification( notify
);
1485 err
= kIOReturnSuccess
;
1487 err
= kIOReturnUnsupported
;
1496 /* Routine io_service_acknowledge_notification */
1497 kern_return_t
is_io_service_acknowledge_notification(
1498 io_object_t _service
,
1499 natural_t notify_ref
,
1500 natural_t response
)
1502 CHECK( IOService
, _service
, service
);
1504 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1505 (IOOptionBits
) response
));
1509 /* Routine io_connect_get_semaphore */
1510 kern_return_t
is_io_connect_get_notification_semaphore(
1511 io_connect_t connection
,
1512 natural_t notification_type
,
1513 semaphore_t
*semaphore
)
1515 CHECK( IOUserClient
, connection
, client
);
1517 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1521 /* Routine io_registry_get_root_entry */
1522 kern_return_t
is_io_registry_get_root_entry(
1523 mach_port_t master_port
,
1526 IORegistryEntry
* entry
;
1528 if( master_port
!= master_device_port
)
1529 return( kIOReturnNotPrivileged
);
1531 entry
= IORegistryEntry::getRegistryRoot();
1536 return( kIOReturnSuccess
);
1539 /* Routine io_registry_create_iterator */
1540 kern_return_t
is_io_registry_create_iterator(
1541 mach_port_t master_port
,
1544 io_object_t
*iterator
)
1546 if( master_port
!= master_device_port
)
1547 return( kIOReturnNotPrivileged
);
1549 *iterator
= IORegistryIterator::iterateOver(
1550 IORegistryEntry::getPlane( plane
), options
);
1552 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1555 /* Routine io_registry_entry_create_iterator */
1556 kern_return_t
is_io_registry_entry_create_iterator(
1557 io_object_t registry_entry
,
1560 io_object_t
*iterator
)
1562 CHECK( IORegistryEntry
, registry_entry
, entry
);
1564 *iterator
= IORegistryIterator::iterateOver( entry
,
1565 IORegistryEntry::getPlane( plane
), options
);
1567 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1570 /* Routine io_registry_iterator_enter */
1571 kern_return_t
is_io_registry_iterator_enter_entry(
1572 io_object_t iterator
)
1574 CHECK( IORegistryIterator
, iterator
, iter
);
1578 return( kIOReturnSuccess
);
1581 /* Routine io_registry_iterator_exit */
1582 kern_return_t
is_io_registry_iterator_exit_entry(
1583 io_object_t iterator
)
1587 CHECK( IORegistryIterator
, iterator
, iter
);
1589 didIt
= iter
->exitEntry();
1591 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1594 /* Routine io_registry_entry_from_path */
1595 kern_return_t
is_io_registry_entry_from_path(
1596 mach_port_t master_port
,
1598 io_object_t
*registry_entry
)
1600 IORegistryEntry
* entry
;
1602 if( master_port
!= master_device_port
)
1603 return( kIOReturnNotPrivileged
);
1605 entry
= IORegistryEntry::fromPath( path
);
1607 *registry_entry
= entry
;
1609 return( kIOReturnSuccess
);
1612 /* Routine io_registry_entry_in_plane */
1613 kern_return_t
is_io_registry_entry_in_plane(
1614 io_object_t registry_entry
,
1616 boolean_t
*inPlane
)
1618 CHECK( IORegistryEntry
, registry_entry
, entry
);
1620 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1622 return( kIOReturnSuccess
);
1626 /* Routine io_registry_entry_get_path */
1627 kern_return_t
is_io_registry_entry_get_path(
1628 io_object_t registry_entry
,
1633 CHECK( IORegistryEntry
, registry_entry
, entry
);
1635 length
= sizeof( io_string_t
);
1636 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1637 return( kIOReturnSuccess
);
1639 return( kIOReturnBadArgument
);
1643 /* Routine io_registry_entry_get_name */
1644 kern_return_t
is_io_registry_entry_get_name(
1645 io_object_t registry_entry
,
1648 CHECK( IORegistryEntry
, registry_entry
, entry
);
1650 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1652 return( kIOReturnSuccess
);
1655 /* Routine io_registry_entry_get_name_in_plane */
1656 kern_return_t
is_io_registry_entry_get_name_in_plane(
1657 io_object_t registry_entry
,
1658 io_name_t planeName
,
1661 const IORegistryPlane
* plane
;
1662 CHECK( IORegistryEntry
, registry_entry
, entry
);
1665 plane
= IORegistryEntry::getPlane( planeName
);
1669 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1671 return( kIOReturnSuccess
);
1674 /* Routine io_registry_entry_get_location_in_plane */
1675 kern_return_t
is_io_registry_entry_get_location_in_plane(
1676 io_object_t registry_entry
,
1677 io_name_t planeName
,
1678 io_name_t location
)
1680 const IORegistryPlane
* plane
;
1681 CHECK( IORegistryEntry
, registry_entry
, entry
);
1684 plane
= IORegistryEntry::getPlane( planeName
);
1688 const char * cstr
= entry
->getLocation( plane
);
1691 strncpy( location
, cstr
, sizeof( io_name_t
));
1692 return( kIOReturnSuccess
);
1694 return( kIOReturnNotFound
);
1697 // Create a vm_map_copy_t or kalloc'ed data for memory
1698 // to be copied out. ipc will free after the copyout.
1700 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1701 io_buf_ptr_t
* buf
)
1706 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1707 false /* src_destroy */, ©
);
1709 assert( err
== KERN_SUCCESS
);
1710 if( err
== KERN_SUCCESS
)
1711 *buf
= (char *) copy
;
1716 /* Routine io_registry_entry_get_property */
1717 kern_return_t
is_io_registry_entry_get_property_bytes(
1718 io_object_t registry_entry
,
1719 io_name_t property_name
,
1720 io_scalar_inband_t buf
,
1721 mach_msg_type_number_t
*dataCnt
)
1729 unsigned int len
= 0;
1730 const void * bytes
= 0;
1731 IOReturn ret
= kIOReturnSuccess
;
1733 CHECK( IORegistryEntry
, registry_entry
, entry
);
1735 obj
= entry
->copyProperty(property_name
);
1737 return( kIOReturnNoResources
);
1739 // One day OSData will be a common container base class
1741 if( (data
= OSDynamicCast( OSData
, obj
))) {
1742 len
= data
->getLength();
1743 bytes
= data
->getBytesNoCopy();
1745 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1746 len
= str
->getLength() + 1;
1747 bytes
= str
->getCStringNoCopy();
1749 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1750 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1751 bytes
= boo
->isTrue() ? "Yes" : "No";
1753 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1754 offsetBytes
= off
->unsigned64BitValue();
1755 len
= off
->numberOfBytes();
1756 bytes
= &offsetBytes
;
1757 #ifdef __BIG_ENDIAN__
1758 bytes
= (const void *)
1759 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1763 ret
= kIOReturnBadArgument
;
1767 ret
= kIOReturnIPCError
;
1770 bcopy( bytes
, buf
, len
);
1779 /* Routine io_registry_entry_get_property */
1780 kern_return_t
is_io_registry_entry_get_property(
1781 io_object_t registry_entry
,
1782 io_name_t property_name
,
1783 io_buf_ptr_t
*properties
,
1784 mach_msg_type_number_t
*propertiesCnt
)
1790 CHECK( IORegistryEntry
, registry_entry
, entry
);
1792 obj
= entry
->copyProperty(property_name
);
1794 return( kIOReturnNotFound
);
1796 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1799 return( kIOReturnNoMemory
);
1803 if( obj
->serialize( s
)) {
1804 len
= s
->getLength();
1805 *propertiesCnt
= len
;
1806 err
= copyoutkdata( s
->text(), len
, properties
);
1809 err
= kIOReturnUnsupported
;
1817 /* Routine io_registry_entry_get_property_recursively */
1818 kern_return_t
is_io_registry_entry_get_property_recursively(
1819 io_object_t registry_entry
,
1821 io_name_t property_name
,
1823 io_buf_ptr_t
*properties
,
1824 mach_msg_type_number_t
*propertiesCnt
)
1830 CHECK( IORegistryEntry
, registry_entry
, entry
);
1832 obj
= entry
->copyProperty( property_name
,
1833 IORegistryEntry::getPlane( plane
), options
);
1835 return( kIOReturnNotFound
);
1837 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1840 return( kIOReturnNoMemory
);
1845 if( obj
->serialize( s
)) {
1846 len
= s
->getLength();
1847 *propertiesCnt
= len
;
1848 err
= copyoutkdata( s
->text(), len
, properties
);
1851 err
= kIOReturnUnsupported
;
1859 /* Routine io_registry_entry_get_properties */
1860 kern_return_t
is_io_registry_entry_get_properties(
1861 io_object_t registry_entry
,
1862 io_buf_ptr_t
*properties
,
1863 mach_msg_type_number_t
*propertiesCnt
)
1868 CHECK( IORegistryEntry
, registry_entry
, entry
);
1870 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1872 return( kIOReturnNoMemory
);
1876 if( entry
->serializeProperties( s
)) {
1877 len
= s
->getLength();
1878 *propertiesCnt
= len
;
1879 err
= copyoutkdata( s
->text(), len
, properties
);
1882 err
= kIOReturnUnsupported
;
1889 /* Routine io_registry_entry_set_properties */
1890 kern_return_t is_io_registry_entry_set_properties
1892 io_object_t registry_entry
,
1893 io_buf_ptr_t properties
,
1894 mach_msg_type_number_t propertiesCnt
,
1901 vm_map_offset_t map_data
;
1903 CHECK( IORegistryEntry
, registry_entry
, entry
);
1905 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
1906 data
= CAST_DOWN(vm_offset_t
, map_data
);
1908 if( KERN_SUCCESS
== err
) {
1910 // must return success after vm_map_copyout() succeeds
1911 obj
= OSUnserializeXML( (const char *) data
);
1912 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1915 res
= entry
->setProperties( obj
);
1918 res
= kIOReturnBadArgument
;
1926 /* Routine io_registry_entry_get_child_iterator */
1927 kern_return_t
is_io_registry_entry_get_child_iterator(
1928 io_object_t registry_entry
,
1930 io_object_t
*iterator
)
1932 CHECK( IORegistryEntry
, registry_entry
, entry
);
1934 *iterator
= entry
->getChildIterator(
1935 IORegistryEntry::getPlane( plane
));
1937 return( kIOReturnSuccess
);
1940 /* Routine io_registry_entry_get_parent_iterator */
1941 kern_return_t
is_io_registry_entry_get_parent_iterator(
1942 io_object_t registry_entry
,
1944 io_object_t
*iterator
)
1946 CHECK( IORegistryEntry
, registry_entry
, entry
);
1948 *iterator
= entry
->getParentIterator(
1949 IORegistryEntry::getPlane( plane
));
1951 return( kIOReturnSuccess
);
1954 /* Routine io_service_get_busy_state */
1955 kern_return_t
is_io_service_get_busy_state(
1956 io_object_t _service
,
1959 CHECK( IOService
, _service
, service
);
1961 *busyState
= service
->getBusyState();
1963 return( kIOReturnSuccess
);
1966 /* Routine io_service_get_state */
1967 kern_return_t
is_io_service_get_state(
1968 io_object_t _service
,
1971 CHECK( IOService
, _service
, service
);
1973 *state
= service
->getState();
1975 return( kIOReturnSuccess
);
1978 /* Routine io_service_wait_quiet */
1979 kern_return_t
is_io_service_wait_quiet(
1980 io_object_t _service
,
1981 mach_timespec_t wait_time
)
1983 CHECK( IOService
, _service
, service
);
1985 return( service
->waitQuiet( &wait_time
));
1988 /* Routine io_service_request_probe */
1989 kern_return_t
is_io_service_request_probe(
1990 io_object_t _service
,
1993 CHECK( IOService
, _service
, service
);
1995 return( service
->requestProbe( options
));
1999 /* Routine io_service_open */
2000 kern_return_t
is_io_service_open(
2001 io_object_t _service
,
2004 io_object_t
*connection
)
2006 IOUserClient
* client
;
2009 CHECK( IOService
, _service
, service
);
2011 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
2012 connect_type
, 0, &client
);
2014 if( err
== kIOReturnSuccess
) {
2015 assert( OSDynamicCast(IOUserClient
, client
) );
2016 *connection
= client
;
2022 /* Routine io_service_open_ndr */
2023 kern_return_t
is_io_service_open_extended(
2024 io_object_t _service
,
2028 io_buf_ptr_t properties
,
2029 mach_msg_type_number_t propertiesCnt
,
2031 io_object_t
*connection
)
2033 IOUserClient
* client
= 0;
2034 kern_return_t err
= KERN_SUCCESS
;
2035 IOReturn res
= kIOReturnSuccess
;
2036 OSDictionary
* propertiesDict
= 0;
2038 bool disallowAccess
;
2040 CHECK( IOService
, _service
, service
);
2048 vm_map_offset_t map_data
;
2050 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
2052 data
= CAST_DOWN(vm_offset_t
, map_data
);
2053 if (KERN_SUCCESS
== err
)
2055 // must return success after vm_map_copyout() succeeds
2056 obj
= OSUnserializeXML( (const char *) data
);
2057 vm_deallocate( kernel_map
, data
, propertiesCnt
);
2058 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
2059 if (!propertiesDict
)
2061 res
= kIOReturnBadArgument
;
2066 if (kIOReturnSuccess
!= res
)
2070 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
2073 if (!propertiesDict
)
2074 propertiesDict
= OSDictionary::withCapacity(4);
2075 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
2079 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
2084 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
2085 connect_type
, propertiesDict
, &client
);
2088 propertiesDict
->release();
2090 if (res
== kIOReturnSuccess
)
2092 assert( OSDynamicCast(IOUserClient
, client
) );
2094 disallowAccess
= (crossEndian
2095 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
2096 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
2100 client
->clientClose();
2103 res
= kIOReturnUnsupported
;
2106 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
2111 *connection
= client
;
2117 /* Routine io_service_close */
2118 kern_return_t
is_io_service_close(
2119 io_object_t connection
)
2122 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2123 return( kIOReturnSuccess
);
2125 CHECK( IOUserClient
, connection
, client
);
2127 client
->clientClose();
2129 return( kIOReturnSuccess
);
2132 /* Routine io_connect_get_service */
2133 kern_return_t
is_io_connect_get_service(
2134 io_object_t connection
,
2135 io_object_t
*service
)
2137 IOService
* theService
;
2139 CHECK( IOUserClient
, connection
, client
);
2141 theService
= client
->getService();
2143 theService
->retain();
2145 *service
= theService
;
2147 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2150 /* Routine io_connect_set_notification_port */
2151 kern_return_t
is_io_connect_set_notification_port(
2152 io_object_t connection
,
2153 int notification_type
,
2157 CHECK( IOUserClient
, connection
, client
);
2159 return( client
->registerNotificationPort( port
, notification_type
,
2163 kern_return_t
is_io_connect_map_memory(
2164 io_object_t connect
,
2167 vm_address_t
* mapAddr
,
2168 vm_size_t
* mapSize
,
2174 CHECK( IOUserClient
, connect
, client
);
2176 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
2179 *mapAddr
= map
->getVirtualAddress();
2181 *mapSize
= map
->getLength();
2183 if( client
->sharedInstance
2184 || (task
!= current_task())) {
2185 // push a name out to the task owning the map,
2186 // so we can clean up maps
2188 mach_port_name_t name
=
2190 IOMachPort::makeSendRightForTask(
2191 task
, map
, IKOT_IOKIT_OBJECT
);
2195 // keep it with the user client
2196 IOLockLock( gIOObjectPortLock
);
2197 if( 0 == client
->mappings
)
2198 client
->mappings
= OSSet::withCapacity(2);
2199 if( client
->mappings
)
2200 client
->mappings
->setObject( map
);
2201 IOLockUnlock( gIOObjectPortLock
);
2204 err
= kIOReturnSuccess
;
2207 err
= kIOReturnBadArgument
;
2212 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2215 IOMemoryMap
* map
= 0;
2217 IOLockLock(gIOObjectPortLock
);
2219 iter
= OSCollectionIterator::withCollection(mappings
);
2222 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2224 if(mem
== map
->getMemoryDescriptor())
2227 mappings
->removeObject(map
);
2234 IOLockUnlock(gIOObjectPortLock
);
2239 kern_return_t
is_io_connect_unmap_memory(
2240 io_object_t connect
,
2243 vm_address_t mapAddr
)
2246 IOOptionBits options
= 0;
2247 IOMemoryDescriptor
* memory
;
2250 CHECK( IOUserClient
, connect
, client
);
2252 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
2254 if( memory
&& (kIOReturnSuccess
== err
)) {
2256 options
= (options
& ~kIOMapUserOptionsMask
)
2257 | kIOMapAnywhere
| kIOMapReference
;
2259 map
= memory
->map( task
, mapAddr
, options
);
2263 IOLockLock( gIOObjectPortLock
);
2264 if( client
->mappings
)
2265 client
->mappings
->removeObject( map
);
2266 IOLockUnlock( gIOObjectPortLock
);
2268 mach_port_name_t name
= 0;
2269 if (task
!= current_task())
2270 name
= IOMachPort::makeSendRightForTask( task
, map
, IKOT_IOKIT_OBJECT
);
2274 err
= iokit_mod_send_right( task
, name
, -2 );
2275 err
= kIOReturnSuccess
;
2278 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2279 if (task
== current_task())
2283 err
= kIOReturnBadArgument
;
2290 /* Routine io_connect_add_client */
2291 kern_return_t
is_io_connect_add_client(
2292 io_object_t connection
,
2293 io_object_t connect_to
)
2295 CHECK( IOUserClient
, connection
, client
);
2296 CHECK( IOUserClient
, connect_to
, to
);
2298 return( client
->connectClient( to
) );
2302 /* Routine io_connect_set_properties */
2303 kern_return_t
is_io_connect_set_properties(
2304 io_object_t connection
,
2305 io_buf_ptr_t properties
,
2306 mach_msg_type_number_t propertiesCnt
,
2309 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2313 /* Routine io_connect_method_scalarI_scalarO */
2314 kern_return_t
is_io_connect_method_scalarI_scalarO(
2315 io_object_t connect
,
2318 IOByteCount inputCount
,
2320 IOByteCount
* outputCount
)
2323 IOExternalMethod
* method
;
2327 CHECK( IOUserClient
, connect
, client
);
2328 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
2330 err
= kIOReturnBadArgument
;
2331 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2333 if( inputCount
!= method
->count0
)
2335 if( *outputCount
!= method
->count1
)
2338 func
= method
->func
;
2340 switch( inputCount
) {
2343 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2344 input
[3], input
[4], input
[5] );
2347 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2352 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2354 &output
[0], &output
[1] );
2357 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2358 &output
[0], &output
[1], &output
[2] );
2361 err
= (object
->*func
)( input
[0], input
[1],
2362 &output
[0], &output
[1], &output
[2],
2366 err
= (object
->*func
)( input
[0],
2367 &output
[0], &output
[1], &output
[2],
2368 &output
[3], &output
[4] );
2371 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
2372 &output
[3], &output
[4], &output
[5] );
2376 IOLog("%s: Bad method table\n", client
->getName());
2381 err
= kIOReturnUnsupported
;
2386 /* Routine io_connect_method_scalarI_structureO */
2387 kern_return_t
is_io_connect_method_scalarI_structureO(
2388 io_object_t connect
,
2391 IOByteCount inputCount
,
2393 IOByteCount
* outputCount
)
2396 IOExternalMethod
* method
;
2400 CHECK( IOUserClient
, connect
, client
);
2402 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2404 err
= kIOReturnBadArgument
;
2405 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2407 if( inputCount
!= method
->count0
)
2409 if( (0xffffffff != method
->count1
)
2410 && (*outputCount
!= method
->count1
))
2413 func
= method
->func
;
2415 switch( inputCount
) {
2418 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2423 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2425 output
, (void *)outputCount
);
2428 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2429 output
, (void *)outputCount
, 0 );
2432 err
= (object
->*func
)( input
[0], input
[1],
2433 output
, (void *)outputCount
, 0, 0 );
2436 err
= (object
->*func
)( input
[0],
2437 output
, (void *)outputCount
, 0, 0, 0 );
2440 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
2444 IOLog("%s: Bad method table\n", client
->getName());
2449 err
= kIOReturnUnsupported
;
2454 /* Routine io_connect_method_scalarI_structureI */
2455 kern_return_t
is_io_connect_method_scalarI_structureI(
2456 io_connect_t connect
,
2459 IOByteCount inputCount
,
2460 UInt8
* inputStruct
,
2461 IOByteCount inputStructCount
)
2464 IOExternalMethod
* method
;
2468 CHECK( IOUserClient
, connect
, client
);
2470 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2472 err
= kIOReturnBadArgument
;
2473 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2475 if( (0xffffffff != method
->count0
)
2476 && (inputCount
!= method
->count0
))
2478 if( (0xffffffff != method
->count1
)
2479 && (inputStructCount
!= method
->count1
))
2482 func
= method
->func
;
2484 switch( inputCount
) {
2487 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2492 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2494 inputStruct
, (void *)inputStructCount
);
2497 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2498 inputStruct
, (void *)inputStructCount
,
2502 err
= (object
->*func
)( input
[0], input
[1],
2503 inputStruct
, (void *)inputStructCount
,
2507 err
= (object
->*func
)( input
[0],
2508 inputStruct
, (void *)inputStructCount
,
2512 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
2517 IOLog("%s: Bad method table\n", client
->getName());
2522 err
= kIOReturnUnsupported
;
2527 /* Routine io_connect_method_structureI_structureO */
2528 kern_return_t
is_io_connect_method_structureI_structureO(
2529 io_object_t connect
,
2532 IOByteCount inputCount
,
2534 IOByteCount
* outputCount
)
2537 IOExternalMethod
* method
;
2541 CHECK( IOUserClient
, connect
, client
);
2543 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2545 err
= kIOReturnBadArgument
;
2546 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2548 if( (0xffffffff != method
->count0
)
2549 && (inputCount
!= method
->count0
))
2551 if( (0xffffffff != method
->count1
)
2552 && (*outputCount
!= method
->count1
))
2555 func
= method
->func
;
2557 if( method
->count1
) {
2558 if( method
->count0
) {
2559 err
= (object
->*func
)( input
, output
,
2560 (void *)inputCount
, outputCount
, 0, 0 );
2562 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2565 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2571 err
= kIOReturnUnsupported
;
2576 kern_return_t
is_io_async_method_scalarI_scalarO(
2577 io_object_t connect
,
2578 mach_port_t wakePort
,
2579 io_async_ref_t reference
,
2580 mach_msg_type_number_t referenceCnt
,
2583 IOByteCount inputCount
,
2585 IOByteCount
* outputCount
)
2588 IOExternalAsyncMethod
*method
;
2592 CHECK( IOUserClient
, connect
, client
);
2593 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2595 err
= kIOReturnBadArgument
;
2596 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2598 if( inputCount
!= method
->count0
)
2600 if( *outputCount
!= method
->count1
)
2603 reference
[0] = (natural_t
) wakePort
;
2604 func
= method
->func
;
2606 switch( inputCount
) {
2609 err
= (object
->*func
)( reference
,
2610 input
[0], input
[1], input
[2],
2611 input
[3], input
[4], input
[5] );
2614 err
= (object
->*func
)( reference
,
2615 input
[0], input
[1], input
[2],
2620 err
= (object
->*func
)( reference
,
2621 input
[0], input
[1], input
[2],
2623 &output
[0], &output
[1] );
2626 err
= (object
->*func
)( reference
,
2627 input
[0], input
[1], input
[2],
2628 &output
[0], &output
[1], &output
[2] );
2631 err
= (object
->*func
)( reference
,
2633 &output
[0], &output
[1], &output
[2],
2637 err
= (object
->*func
)( reference
,
2639 &output
[0], &output
[1], &output
[2],
2640 &output
[3], &output
[4] );
2643 err
= (object
->*func
)( reference
,
2644 &output
[0], &output
[1], &output
[2],
2645 &output
[3], &output
[4], &output
[5] );
2649 IOLog("%s: Bad method table\n", client
->getName());
2654 err
= kIOReturnUnsupported
;
2659 kern_return_t
is_io_async_method_scalarI_structureO(
2660 io_object_t connect
,
2661 mach_port_t wakePort
,
2662 io_async_ref_t reference
,
2663 mach_msg_type_number_t referenceCnt
,
2666 IOByteCount inputCount
,
2668 IOByteCount
* outputCount
)
2671 IOExternalAsyncMethod
*method
;
2675 CHECK( IOUserClient
, connect
, client
);
2677 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2679 err
= kIOReturnBadArgument
;
2680 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2682 if( inputCount
!= method
->count0
)
2684 if( (0xffffffff != method
->count1
)
2685 && (*outputCount
!= method
->count1
))
2688 reference
[0] = (natural_t
) wakePort
;
2689 func
= method
->func
;
2691 switch( inputCount
) {
2694 err
= (object
->*func
)( reference
,
2695 input
[0], input
[1], input
[2],
2700 err
= (object
->*func
)( reference
,
2701 input
[0], input
[1], input
[2],
2703 output
, (void *)outputCount
);
2706 err
= (object
->*func
)( reference
,
2707 input
[0], input
[1], input
[2],
2708 output
, (void *)outputCount
, 0 );
2711 err
= (object
->*func
)( reference
,
2713 output
, (void *)outputCount
, 0, 0 );
2716 err
= (object
->*func
)( reference
,
2718 output
, (void *)outputCount
, 0, 0, 0 );
2721 err
= (object
->*func
)( reference
,
2722 output
, (void *)outputCount
, 0, 0, 0, 0 );
2726 IOLog("%s: Bad method table\n", client
->getName());
2731 err
= kIOReturnUnsupported
;
2736 kern_return_t
is_io_async_method_scalarI_structureI(
2737 io_connect_t connect
,
2738 mach_port_t wakePort
,
2739 io_async_ref_t reference
,
2740 mach_msg_type_number_t referenceCnt
,
2743 IOByteCount inputCount
,
2744 UInt8
* inputStruct
,
2745 IOByteCount inputStructCount
)
2748 IOExternalAsyncMethod
*method
;
2752 CHECK( IOUserClient
, connect
, client
);
2754 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2756 err
= kIOReturnBadArgument
;
2757 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2759 if( (0xffffffff != method
->count0
)
2760 && (inputCount
!= method
->count0
))
2762 if( (0xffffffff != method
->count1
)
2763 && (inputStructCount
!= method
->count1
))
2766 reference
[0] = (natural_t
) wakePort
;
2767 func
= method
->func
;
2769 switch( inputCount
) {
2772 err
= (object
->*func
)( reference
,
2773 input
[0], input
[1], input
[2],
2778 err
= (object
->*func
)( reference
,
2779 input
[0], input
[1], input
[2],
2781 inputStruct
, (void *)inputStructCount
);
2784 err
= (object
->*func
)( reference
,
2785 input
[0], input
[1], input
[2],
2786 inputStruct
, (void *)inputStructCount
,
2790 err
= (object
->*func
)( reference
,
2792 inputStruct
, (void *)inputStructCount
,
2796 err
= (object
->*func
)( reference
,
2798 inputStruct
, (void *)inputStructCount
,
2802 err
= (object
->*func
)( reference
,
2803 inputStruct
, (void *)inputStructCount
,
2808 IOLog("%s: Bad method table\n", client
->getName());
2813 err
= kIOReturnUnsupported
;
2818 kern_return_t
is_io_async_method_structureI_structureO(
2819 io_object_t connect
,
2820 mach_port_t wakePort
,
2821 io_async_ref_t reference
,
2822 mach_msg_type_number_t referenceCnt
,
2825 IOByteCount inputCount
,
2827 IOByteCount
* outputCount
)
2830 IOExternalAsyncMethod
*method
;
2834 CHECK( IOUserClient
, connect
, client
);
2836 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2838 err
= kIOReturnBadArgument
;
2839 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2841 if( (0xffffffff != method
->count0
)
2842 && (inputCount
!= method
->count0
))
2844 if( (0xffffffff != method
->count1
)
2845 && (*outputCount
!= method
->count1
))
2848 reference
[0] = (natural_t
) wakePort
;
2849 func
= method
->func
;
2851 if( method
->count1
) {
2852 if( method
->count0
) {
2853 err
= (object
->*func
)( reference
,
2855 (void *)inputCount
, outputCount
, 0, 0 );
2857 err
= (object
->*func
)( reference
,
2858 output
, outputCount
, 0, 0, 0, 0 );
2861 err
= (object
->*func
)( reference
,
2862 input
, (void *)inputCount
, 0, 0, 0, 0 );
2868 err
= kIOReturnUnsupported
;
2872 /* Routine io_make_matching */
2873 kern_return_t
is_io_make_matching(
2874 mach_port_t master_port
,
2876 IOOptionBits options
,
2878 IOByteCount inputCount
,
2879 io_string_t matching
)
2882 IOReturn err
= kIOReturnSuccess
;
2883 OSDictionary
* dict
;
2885 if( master_port
!= master_device_port
)
2886 return( kIOReturnNotPrivileged
);
2890 case kIOServiceMatching
:
2891 dict
= IOService::serviceMatching( gIOServiceKey
);
2894 case kIOBSDNameMatching
:
2895 dict
= IOBSDNameMatching( (const char *) input
);
2898 case kIOOFPathMatching
:
2899 dict
= IOOFPathMatching( (const char *) input
,
2900 matching
, sizeof( io_string_t
));
2908 return( kIOReturnUnsupported
);
2911 s
= OSSerialize::withCapacity(4096);
2913 err
= kIOReturnNoMemory
;
2917 if( !dict
->serialize( s
)) {
2918 err
= kIOReturnUnsupported
;
2922 if( s
->getLength() > sizeof( io_string_t
)) {
2923 err
= kIOReturnNoMemory
;
2926 strcpy( matching
, s
->text());
2938 /* Routine io_catalog_send_data */
2939 kern_return_t
is_io_catalog_send_data(
2940 mach_port_t master_port
,
2942 io_buf_ptr_t inData
,
2943 mach_msg_type_number_t inDataCount
,
2948 kern_return_t kr
= kIOReturnError
;
2950 //printf("io_catalog_send_data called. flag: %d\n", flag);
2952 if( master_port
!= master_device_port
)
2953 return kIOReturnNotPrivileged
;
2955 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2956 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2957 return kIOReturnBadArgument
;
2960 vm_map_offset_t map_data
;
2962 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
2963 data
= CAST_DOWN(vm_offset_t
, map_data
);
2965 if( kr
!= KERN_SUCCESS
)
2968 // must return success after vm_map_copyout() succeeds
2971 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2972 vm_deallocate( kernel_map
, data
, inDataCount
);
2974 *result
= kIOReturnNoMemory
;
2975 return( KERN_SUCCESS
);
2981 case kIOCatalogAddDrivers
:
2982 case kIOCatalogAddDriversNoMatch
: {
2985 array
= OSDynamicCast(OSArray
, obj
);
2987 if ( !gIOCatalogue
->addDrivers( array
,
2988 flag
== kIOCatalogAddDrivers
) ) {
2989 kr
= kIOReturnError
;
2993 kr
= kIOReturnBadArgument
;
2998 case kIOCatalogRemoveDrivers
:
2999 case kIOCatalogRemoveDriversNoMatch
: {
3000 OSDictionary
* dict
;
3002 dict
= OSDynamicCast(OSDictionary
, obj
);
3004 if ( !gIOCatalogue
->removeDrivers( dict
,
3005 flag
== kIOCatalogRemoveDrivers
) ) {
3006 kr
= kIOReturnError
;
3010 kr
= kIOReturnBadArgument
;
3015 case kIOCatalogStartMatching
: {
3016 OSDictionary
* dict
;
3018 dict
= OSDynamicCast(OSDictionary
, obj
);
3020 if ( !gIOCatalogue
->startMatching( dict
) ) {
3021 kr
= kIOReturnError
;
3025 kr
= kIOReturnBadArgument
;
3030 case kIOCatalogRemoveKernelLinker
: {
3031 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
3032 kr
= kIOReturnError
;
3034 kr
= kIOReturnSuccess
;
3040 kr
= kIOReturnBadArgument
;
3044 if (obj
) obj
->release();
3047 return( KERN_SUCCESS
);
3050 /* Routine io_catalog_terminate */
3051 kern_return_t
is_io_catalog_terminate(
3052 mach_port_t master_port
,
3058 if( master_port
!= master_device_port
)
3059 return kIOReturnNotPrivileged
;
3061 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3062 kIOClientPrivilegeAdministrator
);
3063 if( kIOReturnSuccess
!= kr
)
3067 case kIOCatalogServiceTerminate
:
3069 IOService
* service
;
3071 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
3072 kIORegistryIterateRecursively
);
3074 return kIOReturnNoMemory
;
3078 while( (service
= (IOService
*)iter
->getNextObject()) ) {
3079 if( service
->metaCast(name
)) {
3080 if ( !service
->terminate( kIOServiceRequired
3081 | kIOServiceSynchronous
) ) {
3082 kr
= kIOReturnUnsupported
;
3087 } while( !service
&& !iter
->isValid());
3091 case kIOCatalogModuleUnload
:
3092 case kIOCatalogModuleTerminate
:
3093 kr
= gIOCatalogue
->terminateDriversForModule(name
,
3094 flag
== kIOCatalogModuleUnload
);
3098 kr
= kIOReturnBadArgument
;
3105 /* Routine io_catalog_get_data */
3106 kern_return_t
is_io_catalog_get_data(
3107 mach_port_t master_port
,
3109 io_buf_ptr_t
*outData
,
3110 mach_msg_type_number_t
*outDataCount
)
3112 kern_return_t kr
= kIOReturnSuccess
;
3115 if( master_port
!= master_device_port
)
3116 return kIOReturnNotPrivileged
;
3118 //printf("io_catalog_get_data called. flag: %d\n", flag);
3120 s
= OSSerialize::withCapacity(4096);
3122 return kIOReturnNoMemory
;
3126 kr
= gIOCatalogue
->serializeData(flag
, s
);
3128 if ( kr
== kIOReturnSuccess
) {
3133 size
= s
->getLength();
3134 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
3135 if ( kr
== kIOReturnSuccess
) {
3136 bcopy(s
->text(), (void *)data
, size
);
3137 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
3138 (vm_map_size_t
)size
, true, ©
);
3139 *outData
= (char *)copy
;
3140 *outDataCount
= size
;
3149 /* Routine io_catalog_get_gen_count */
3150 kern_return_t
is_io_catalog_get_gen_count(
3151 mach_port_t master_port
,
3154 if( master_port
!= master_device_port
)
3155 return kIOReturnNotPrivileged
;
3157 //printf("io_catalog_get_gen_count called.\n");
3160 return kIOReturnBadArgument
;
3162 *genCount
= gIOCatalogue
->getGenerationCount();
3164 return kIOReturnSuccess
;
3167 /* Routine io_catalog_module_loaded */
3168 kern_return_t
is_io_catalog_module_loaded(
3169 mach_port_t master_port
,
3172 if( master_port
!= master_device_port
)
3173 return kIOReturnNotPrivileged
;
3175 //printf("io_catalog_module_loaded called. name %s\n", name);
3178 return kIOReturnBadArgument
;
3180 gIOCatalogue
->moduleHasLoaded(name
);
3182 return kIOReturnSuccess
;
3185 kern_return_t
is_io_catalog_reset(
3186 mach_port_t master_port
,
3189 if( master_port
!= master_device_port
)
3190 return kIOReturnNotPrivileged
;
3193 case kIOCatalogResetDefault
:
3194 gIOCatalogue
->reset();
3198 return kIOReturnBadArgument
;
3201 return kIOReturnSuccess
;
3204 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
3206 kern_return_t result
= kIOReturnBadArgument
;
3207 IOUserClient
*userClient
;
3209 if ((userClient
= OSDynamicCast(IOUserClient
,
3210 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
3211 IOExternalTrap
*trap
;
3212 IOService
*target
= NULL
;
3214 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
3216 if (trap
&& target
) {
3222 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
3226 userClient
->release();
3234 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
3235 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
3236 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
3237 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
3238 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
3239 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
3240 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
3241 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
3242 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
3243 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
3244 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
3245 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
3246 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
3247 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
3248 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
3249 OSMetaClassDefineReservedUnused(IOUserClient
, 15);