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/IOKitKeysPrivate.h>
26 #include <IOKit/IOUserClient.h>
27 #include <IOKit/IOService.h>
28 #include <IOKit/IOService.h>
29 #include <IOKit/IORegistryEntry.h>
30 #include <IOKit/IOCatalogue.h>
31 #include <IOKit/IOMemoryDescriptor.h>
32 #include <IOKit/IOLib.h>
34 #include <IOKit/assert.h>
36 #include "IOServicePrivate.h"
38 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40 // definitions we should get from osfmk
42 //typedef struct ipc_port * ipc_port_t;
43 typedef natural_t ipc_kobject_type_t
;
45 #define IKOT_IOKIT_SPARE 27
46 #define IKOT_IOKIT_CONNECT 29
47 #define IKOT_IOKIT_OBJECT 30
51 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
52 ipc_kobject_type_t type
);
54 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
56 extern mach_port_name_t
iokit_make_send_right( task_t task
,
57 io_object_t obj
, ipc_kobject_type_t type
);
59 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
61 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
63 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
65 extern ipc_port_t master_device_port
;
67 extern void iokit_retain_port( ipc_port_t port
);
68 extern void iokit_release_port( ipc_port_t port
);
70 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
72 #include <mach/mach_traps.h>
73 #include <vm/vm_map.h>
78 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
82 class IOMachPort
: public OSObject
84 OSDeclareDefaultStructors(IOMachPort
)
91 static IOMachPort
* portForObject( OSObject
* obj
,
92 ipc_kobject_type_t type
);
93 static bool noMoreSendersForObject( OSObject
* obj
,
94 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
95 static void releasePortForObject( OSObject
* obj
,
96 ipc_kobject_type_t type
);
97 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
99 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
101 static mach_port_name_t
makeSendRightForTask( task_t task
,
102 io_object_t obj
, ipc_kobject_type_t type
);
107 #define super OSObject
108 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
110 static IOLock
* gIOObjectPortLock
;
112 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
114 // not in dictForType() for debugging ease
115 static OSDictionary
* gIOObjectPorts
;
116 static OSDictionary
* gIOConnectPorts
;
118 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
120 OSDictionary
** dict
;
122 if( IKOT_IOKIT_OBJECT
== type
)
123 dict
= &gIOObjectPorts
;
124 else if( IKOT_IOKIT_CONNECT
== type
)
125 dict
= &gIOConnectPorts
;
130 *dict
= OSDictionary::withCapacity( 1 );
135 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
136 ipc_kobject_type_t type
)
138 IOMachPort
* inst
= 0;
141 IOTakeLock( gIOObjectPortLock
);
145 dict
= dictForType( type
);
149 if( (inst
= (IOMachPort
*)
150 dict
->getObject( (const OSSymbol
*) obj
))) {
156 inst
= new IOMachPort
;
157 if( inst
&& !inst
->init()) {
162 inst
->port
= iokit_alloc_object_port( obj
, type
);
165 dict
->setObject( (const OSSymbol
*) obj
, inst
);
175 IOUnlock( gIOObjectPortLock
);
180 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
181 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
184 IOMachPort
* machPort
;
185 bool destroyed
= true;
187 IOTakeLock( gIOObjectPortLock
);
189 if( (dict
= dictForType( type
))) {
192 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
194 destroyed
= (machPort
->mscount
== *mscount
);
196 dict
->removeObject( (const OSSymbol
*) obj
);
198 *mscount
= machPort
->mscount
;
203 IOUnlock( gIOObjectPortLock
);
208 void IOMachPort::releasePortForObject( OSObject
* obj
,
209 ipc_kobject_type_t type
)
212 IOMachPort
* machPort
;
214 IOTakeLock( gIOObjectPortLock
);
216 if( (dict
= dictForType( type
))) {
218 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
219 if( machPort
&& !machPort
->holdDestroy
)
220 dict
->removeObject( (const OSSymbol
*) obj
);
224 IOUnlock( gIOObjectPortLock
);
227 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
230 IOMachPort
* machPort
;
232 IOLockLock( gIOObjectPortLock
);
234 if( (dict
= dictForType( type
))) {
235 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
237 machPort
->holdDestroy
= true;
240 IOLockUnlock( gIOObjectPortLock
);
243 void IOUserClient::destroyUserReferences( OSObject
* obj
)
245 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
248 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
252 IOTakeLock( gIOObjectPortLock
);
255 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
258 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
262 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
264 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
265 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
267 uc
->mappings
->release();
270 dict
->removeObject( (const OSSymbol
*) obj
);
274 IOUnlock( gIOObjectPortLock
);
277 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
278 io_object_t obj
, ipc_kobject_type_t type
)
280 return( iokit_make_send_right( task
, obj
, type
));
283 void IOMachPort::free( void )
286 iokit_destroy_object_port( port
);
290 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
292 class IOUserNotification
: public OSIterator
294 OSDeclareDefaultStructors(IOUserNotification
)
296 IONotifier
* holdNotify
;
301 virtual bool init( void );
304 virtual void setNotification( IONotifier
* obj
);
306 virtual void reset();
307 virtual bool isValid();
310 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
314 // functions called from osfmk/device/iokit_rpc.c
317 iokit_add_reference( io_object_t obj
)
324 iokit_remove_reference( io_object_t obj
)
331 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
333 IOMachPort
* machPort
;
336 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
338 port
= machPort
->port
;
340 iokit_retain_port( port
);
351 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
352 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
354 IOUserClient
* client
;
356 IOUserNotification
* notify
;
358 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
359 return( kIOReturnNotReady
);
361 if( IKOT_IOKIT_CONNECT
== type
)
363 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
364 client
->clientDied();
366 else if( IKOT_IOKIT_OBJECT
== type
)
368 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
370 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
371 notify
->setNotification( 0 );
374 return( kIOReturnSuccess
);
379 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
381 class IOServiceUserNotification
: public IOUserNotification
383 OSDeclareDefaultStructors(IOServiceUserNotification
)
386 mach_msg_header_t msgHdr
;
387 OSNotificationHeader notifyHeader
;
390 enum { kMaxOutstanding
= 1024 };
395 OSObject
* lastEntry
;
400 virtual bool init( mach_port_t port
, natural_t type
,
401 OSAsyncReference reference
);
404 static bool _handler( void * target
,
405 void * ref
, IOService
* newService
);
406 virtual bool handler( void * ref
, IOService
* newService
);
408 virtual OSObject
* getNextObject();
411 class IOServiceMessageUserNotification
: public IOUserNotification
413 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
416 mach_msg_header_t msgHdr
;
417 mach_msg_body_t msgBody
;
418 mach_msg_port_descriptor_t ports
[1];
419 OSNotificationHeader notifyHeader
;
427 virtual bool init( mach_port_t port
, natural_t type
,
428 OSAsyncReference reference
, vm_size_t extraSize
);
431 static IOReturn
_handler( void * target
, void * ref
,
432 UInt32 messageType
, IOService
* provider
,
433 void * messageArgument
, vm_size_t argSize
);
434 virtual IOReturn
handler( void * ref
,
435 UInt32 messageType
, IOService
* provider
,
436 void * messageArgument
, vm_size_t argSize
);
438 virtual OSObject
* getNextObject();
441 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
444 #define super OSIterator
445 OSDefineMetaClass( IOUserNotification
, OSIterator
)
446 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
448 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
450 bool IOUserNotification::init( void )
455 lock
= IOLockAlloc();
462 void IOUserNotification::free( void )
465 holdNotify
->remove();
466 // can't be in handler now
475 void IOUserNotification::setNotification( IONotifier
* notify
)
477 IONotifier
* previousNotify
;
479 IOLockLock( gIOObjectPortLock
);
481 previousNotify
= holdNotify
;
484 IOLockUnlock( gIOObjectPortLock
);
487 previousNotify
->remove();
490 void IOUserNotification::reset()
495 bool IOUserNotification::isValid()
500 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
503 #define super IOUserNotification
504 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
506 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
508 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
509 OSAsyncReference reference
)
511 newSet
= OSArray::withCapacity( 1 );
515 msgSize
= sizeof( PingMsg
) + 0;
516 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
520 bzero( pingMsg
, msgSize
);
522 pingMsg
->msgHdr
.msgh_remote_port
= port
;
523 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
524 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
525 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
526 pingMsg
->msgHdr
.msgh_size
= msgSize
;
527 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
529 pingMsg
->notifyHeader
.size
= 0;
530 pingMsg
->notifyHeader
.type
= type
;
531 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
533 return( super::init() );
536 void IOServiceUserNotification::free( void )
541 OSObject
* _lastEntry
;
545 _lastEntry
= lastEntry
;
550 if( _pingMsg
&& _msgSize
)
551 IOFree( _pingMsg
, _msgSize
);
554 _lastEntry
->release();
560 bool IOServiceUserNotification::_handler( void * target
,
561 void * ref
, IOService
* newService
)
563 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
566 bool IOServiceUserNotification::handler( void * ref
,
567 IOService
* newService
)
571 ipc_port_t port
= NULL
;
572 bool sendPing
= false;
576 count
= newSet
->getCount();
577 if( count
< kMaxOutstanding
) {
579 newSet
->setObject( newService
);
580 if( (sendPing
= (armed
&& (0 == count
))))
586 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
587 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
590 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
591 pingMsg
->msgHdr
.msgh_local_port
= port
;
593 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
595 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
596 pingMsg
->msgHdr
.msgh_size
);
598 iokit_release_port( port
);
600 if( KERN_SUCCESS
!= kr
)
601 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
607 OSObject
* IOServiceUserNotification::getNextObject()
615 lastEntry
->release();
617 count
= newSet
->getCount();
619 result
= newSet
->getObject( count
- 1 );
621 newSet
->removeObject( count
- 1);
633 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
635 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
637 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
639 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
640 OSAsyncReference reference
, vm_size_t extraSize
)
643 extraSize
+= sizeof(IOServiceInterestContent
);
644 msgSize
= sizeof( PingMsg
) + extraSize
;
645 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
649 bzero( pingMsg
, msgSize
);
651 pingMsg
->msgHdr
.msgh_remote_port
= port
;
652 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
654 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
655 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
656 pingMsg
->msgHdr
.msgh_size
= msgSize
;
657 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
659 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
661 pingMsg
->ports
[0].name
= 0;
662 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
663 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
665 pingMsg
->notifyHeader
.size
= extraSize
;
666 pingMsg
->notifyHeader
.type
= type
;
667 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
669 return( super::init() );
672 void IOServiceMessageUserNotification::free( void )
682 if( _pingMsg
&& _msgSize
)
683 IOFree( _pingMsg
, _msgSize
);
686 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
687 UInt32 messageType
, IOService
* provider
,
688 void * argument
, vm_size_t argSize
)
690 return( ((IOServiceMessageUserNotification
*) target
)->handler(
691 ref
, messageType
, provider
, argument
, argSize
));
694 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
695 UInt32 messageType
, IOService
* provider
,
696 void * messageArgument
, vm_size_t argSize
)
699 ipc_port_t thisPort
, providerPort
;
700 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
701 pingMsg
->notifyHeader
.content
;
703 data
->messageType
= messageType
;
705 argSize
= sizeof( messageArgument
);
706 data
->messageArgument
[0] = messageArgument
;
708 if( argSize
> kIOUserNotifyMaxMessageSize
)
709 argSize
= kIOUserNotifyMaxMessageSize
;
710 bcopy( messageArgument
, data
->messageArgument
, argSize
);
712 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
713 + sizeof( IOServiceInterestContent
)
714 - sizeof( data
->messageArgument
)
717 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
718 pingMsg
->ports
[0].name
= providerPort
;
719 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
720 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
721 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
722 pingMsg
->msgHdr
.msgh_size
);
724 iokit_release_port( thisPort
);
726 iokit_release_port( providerPort
);
728 if( KERN_SUCCESS
!= kr
)
729 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
731 return( kIOReturnSuccess
);
734 OSObject
* IOServiceMessageUserNotification::getNextObject()
739 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
742 #define super IOService
743 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
745 void IOUserClient::initialize( void )
747 gIOObjectPortLock
= IOLockAlloc();
749 assert( gIOObjectPortLock
);
752 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
753 mach_port_t wakePort
,
754 void *callback
, void *refcon
)
756 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
757 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
758 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
761 inline OSDictionary
* CopyConsoleUser(UInt32 uid
)
764 OSDictionary
* user
= 0;
766 if ((array
= OSDynamicCast(OSArray
,
767 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
769 for (unsigned int idx
= 0;
770 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
774 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
775 && (uid
== num
->unsigned32BitValue())) {
785 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
786 const char * privilegeName
)
789 security_token_t token
;
790 mach_msg_type_number_t count
;
795 if ((secureConsole
= !strcmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
)))
796 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
798 task
= (task_t
)securityToken
;
800 count
= TASK_SECURITY_TOKEN_COUNT
;
801 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
803 if (KERN_SUCCESS
!= kr
)
805 else if (!strcmp(privilegeName
, kIOClientPrivilegeAdministrator
)) {
806 if (0 != token
.val
[0])
807 kr
= kIOReturnNotPrivileged
;
808 } else if (!strcmp(privilegeName
, kIOClientPrivilegeLocalUser
)) {
809 user
= CopyConsoleUser(token
.val
[0]);
813 kr
= kIOReturnNotPrivileged
;
814 } else if (secureConsole
|| !strcmp(privilegeName
, kIOClientPrivilegeConsoleUser
)) {
815 user
= CopyConsoleUser(token
.val
[0]);
817 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
818 kr
= kIOReturnNotPrivileged
;
819 else if ( secureConsole
) {
820 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
821 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
822 kr
= kIOReturnNotPrivileged
;
827 kr
= kIOReturnNotPrivileged
;
829 kr
= kIOReturnUnsupported
;
834 bool IOUserClient::initWithTask(task_t owningTask
,
838 if( getPropertyTable())
841 return super::init();
844 bool IOUserClient::initWithTask(task_t owningTask
,
847 OSDictionary
* properties
)
851 ok
= super::init( properties
);
852 ok
&= initWithTask( owningTask
, securityID
, type
);
857 void IOUserClient::free()
865 IOReturn
IOUserClient::clientDied( void )
867 return( clientClose());
870 IOReturn
IOUserClient::clientClose( void )
872 return( kIOReturnUnsupported
);
875 IOService
* IOUserClient::getService( void )
880 IOReturn
IOUserClient::registerNotificationPort(
881 mach_port_t
/* port */,
885 return( kIOReturnUnsupported
);
888 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
889 semaphore_t
* semaphore
)
891 return( kIOReturnUnsupported
);
894 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
896 return( kIOReturnUnsupported
);
899 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
900 IOOptionBits
* options
,
901 IOMemoryDescriptor
** memory
)
903 return( kIOReturnUnsupported
);
906 IOMemoryMap
* IOUserClient::mapClientMemory(
909 IOOptionBits mapFlags
,
910 IOVirtualAddress atAddress
)
913 IOOptionBits options
= 0;
914 IOMemoryDescriptor
* memory
;
915 IOMemoryMap
* map
= 0;
917 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
919 if( memory
&& (kIOReturnSuccess
== err
)) {
921 options
= (options
& ~kIOMapUserOptionsMask
)
922 | (mapFlags
& kIOMapUserOptionsMask
);
923 map
= memory
->map( task
, atAddress
, options
);
930 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
931 OSObject
*obj
, io_object_t
*clientObj
)
933 mach_port_name_t name
;
935 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
938 *(mach_port_name_t
*)clientObj
= name
;
939 return kIOReturnSuccess
;
942 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
947 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
952 IOExternalMethod
* IOUserClient::
953 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
955 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
958 *targetP
= (IOService
*) method
->object
;
963 IOExternalAsyncMethod
* IOUserClient::
964 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
966 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
969 *targetP
= (IOService
*) method
->object
;
974 IOExternalTrap
* IOUserClient::
975 getExternalTrapForIndex(UInt32 index
)
980 IOExternalTrap
* IOUserClient::
981 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
983 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
986 *targetP
= trap
->object
;
992 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
993 IOReturn result
, void *args
[], UInt32 numArgs
)
996 mach_msg_header_t msgHdr
;
997 OSNotificationHeader notifyHdr
;
998 IOAsyncCompletionContent asyncContent
;
999 void * args
[kMaxAsyncArgs
];
1002 mach_port_t replyPort
;
1005 // If no reply port, do nothing.
1006 replyPort
= (mach_port_t
) reference
[0];
1007 if(replyPort
== MACH_PORT_NULL
)
1008 return kIOReturnSuccess
;
1010 if(numArgs
> kMaxAsyncArgs
)
1011 return kIOReturnMessageTooLarge
;
1012 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1014 replyMsg
.msgHdr
.msgh_size
=
1015 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
1016 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1017 replyMsg
.msgHdr
.msgh_local_port
= 0;
1018 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1020 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1021 + numArgs
*sizeof(void *);
1022 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1023 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
1025 replyMsg
.asyncContent
.result
= result
;
1027 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
1028 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
1029 replyMsg
.msgHdr
.msgh_size
);
1030 if( KERN_SUCCESS
!= kr
)
1031 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
1035 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1039 #define CHECK(cls,obj,out) \
1041 if( !(out = OSDynamicCast( cls, obj))) \
1042 return( kIOReturnBadArgument )
1044 /* Routine io_object_get_class */
1045 kern_return_t
is_io_object_get_class(
1047 io_name_t className
)
1049 const OSMetaClass
* my_obj
= NULL
;
1052 return( kIOReturnBadArgument
);
1054 my_obj
= object
->getMetaClass();
1056 return (kIOReturnNotFound
);
1059 strcpy( className
, my_obj
->getClassName());
1060 return( kIOReturnSuccess
);
1063 /* Routine io_object_get_superclass */
1064 kern_return_t
is_io_object_get_superclass(
1065 mach_port_t master_port
,
1067 io_name_t class_name
)
1069 const OSMetaClass
* my_obj
= NULL
;
1070 const OSMetaClass
* superclass
= NULL
;
1071 const OSSymbol
*my_name
= NULL
;
1072 const char *my_cstr
= NULL
;
1074 if (!obj_name
|| !class_name
)
1075 return (kIOReturnBadArgument
);
1077 if( master_port
!= master_device_port
)
1078 return( kIOReturnNotPrivileged
);
1080 my_name
= OSSymbol::withCString(obj_name
);
1083 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1087 superclass
= my_obj
->getSuperClass();
1091 return( kIOReturnNotFound
);
1094 my_cstr
= superclass
->getClassName();
1097 strncpy(class_name
, my_cstr
, sizeof(io_name_t
)-1);
1098 return( kIOReturnSuccess
);
1100 return (kIOReturnNotFound
);
1103 /* Routine io_object_get_bundle_identifier */
1104 kern_return_t
is_io_object_get_bundle_identifier(
1105 mach_port_t master_port
,
1107 io_name_t bundle_name
)
1109 const OSMetaClass
* my_obj
= NULL
;
1110 const OSSymbol
*my_name
= NULL
;
1111 const OSSymbol
*identifier
= NULL
;
1112 const char *my_cstr
= NULL
;
1114 if (!obj_name
|| !bundle_name
)
1115 return (kIOReturnBadArgument
);
1117 if( master_port
!= master_device_port
)
1118 return( kIOReturnNotPrivileged
);
1120 my_name
= OSSymbol::withCString(obj_name
);
1123 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1128 identifier
= my_obj
->getKmodName();
1131 return( kIOReturnNotFound
);
1134 my_cstr
= identifier
->getCStringNoCopy();
1136 strncpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
)-1);
1137 return( kIOReturnSuccess
);
1140 return (kIOReturnBadArgument
);
1143 /* Routine io_object_conforms_to */
1144 kern_return_t
is_io_object_conforms_to(
1146 io_name_t className
,
1147 boolean_t
*conforms
)
1150 return( kIOReturnBadArgument
);
1152 *conforms
= (0 != object
->metaCast( className
));
1153 return( kIOReturnSuccess
);
1156 /* Routine io_object_get_retain_count */
1157 kern_return_t
is_io_object_get_retain_count(
1162 return( kIOReturnBadArgument
);
1164 *retainCount
= object
->getRetainCount();
1165 return( kIOReturnSuccess
);
1168 /* Routine io_iterator_next */
1169 kern_return_t
is_io_iterator_next(
1170 io_object_t iterator
,
1171 io_object_t
*object
)
1175 CHECK( OSIterator
, iterator
, iter
);
1177 obj
= iter
->getNextObject();
1181 return( kIOReturnSuccess
);
1183 return( kIOReturnNoDevice
);
1186 /* Routine io_iterator_reset */
1187 kern_return_t
is_io_iterator_reset(
1188 io_object_t iterator
)
1190 CHECK( OSIterator
, iterator
, iter
);
1194 return( kIOReturnSuccess
);
1197 /* Routine io_iterator_is_valid */
1198 kern_return_t
is_io_iterator_is_valid(
1199 io_object_t iterator
,
1200 boolean_t
*is_valid
)
1202 CHECK( OSIterator
, iterator
, iter
);
1204 *is_valid
= iter
->isValid();
1206 return( kIOReturnSuccess
);
1209 /* Routine io_service_match_property_table */
1210 kern_return_t
is_io_service_match_property_table(
1211 io_service_t _service
,
1212 io_string_t matching
,
1213 boolean_t
*matches
)
1215 CHECK( IOService
, _service
, service
);
1219 OSDictionary
* dict
;
1221 obj
= OSUnserializeXML( matching
);
1223 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1224 *matches
= service
->passiveMatch( dict
);
1225 kr
= kIOReturnSuccess
;
1227 kr
= kIOReturnBadArgument
;
1235 /* Routine io_service_match_property_table_ool */
1236 kern_return_t
is_io_service_match_property_table_ool(
1237 io_object_t service
,
1238 io_buf_ptr_t matching
,
1239 mach_msg_type_number_t matchingCnt
,
1241 boolean_t
*matches
)
1245 vm_map_offset_t map_data
;
1247 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1248 data
= CAST_DOWN(vm_offset_t
, map_data
);
1250 if( KERN_SUCCESS
== kr
) {
1251 // must return success after vm_map_copyout() succeeds
1252 *result
= is_io_service_match_property_table( service
,
1253 (char *) data
, matches
);
1254 vm_deallocate( kernel_map
, data
, matchingCnt
);
1260 /* Routine io_service_get_matching_services */
1261 kern_return_t
is_io_service_get_matching_services(
1262 mach_port_t master_port
,
1263 io_string_t matching
,
1264 io_iterator_t
*existing
)
1268 OSDictionary
* dict
;
1270 if( master_port
!= master_device_port
)
1271 return( kIOReturnNotPrivileged
);
1273 obj
= OSUnserializeXML( matching
);
1275 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1276 *existing
= IOService::getMatchingServices( dict
);
1277 kr
= kIOReturnSuccess
;
1279 kr
= kIOReturnBadArgument
;
1287 /* Routine io_service_get_matching_services_ool */
1288 kern_return_t
is_io_service_get_matching_services_ool(
1289 mach_port_t master_port
,
1290 io_buf_ptr_t matching
,
1291 mach_msg_type_number_t matchingCnt
,
1293 io_object_t
*existing
)
1297 vm_map_offset_t map_data
;
1299 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1300 data
= CAST_DOWN(vm_offset_t
, map_data
);
1302 if( KERN_SUCCESS
== kr
) {
1303 // must return success after vm_map_copyout() succeeds
1304 *result
= is_io_service_get_matching_services( master_port
,
1305 (char *) data
, existing
);
1306 vm_deallocate( kernel_map
, data
, matchingCnt
);
1312 /* Routine io_service_add_notification */
1313 kern_return_t
is_io_service_add_notification(
1314 mach_port_t master_port
,
1315 io_name_t notification_type
,
1316 io_string_t matching
,
1318 io_async_ref_t reference
,
1319 mach_msg_type_number_t referenceCnt
,
1320 io_object_t
* notification
)
1322 IOServiceUserNotification
* userNotify
= 0;
1323 IONotifier
* notify
= 0;
1324 const OSSymbol
* sym
;
1325 OSDictionary
* dict
;
1327 unsigned long int userMsgType
;
1330 if( master_port
!= master_device_port
)
1331 return( kIOReturnNotPrivileged
);
1334 err
= kIOReturnNoResources
;
1336 if( !(sym
= OSSymbol::withCString( notification_type
)))
1337 err
= kIOReturnNoResources
;
1339 if( !(dict
= OSDynamicCast( OSDictionary
,
1340 OSUnserializeXML( matching
)))) {
1341 err
= kIOReturnBadArgument
;
1345 if( (sym
== gIOPublishNotification
)
1346 || (sym
== gIOFirstPublishNotification
))
1347 userMsgType
= kIOServicePublishNotificationType
;
1348 else if( (sym
== gIOMatchedNotification
)
1349 || (sym
== gIOFirstMatchNotification
))
1350 userMsgType
= kIOServiceMatchedNotificationType
;
1351 else if( sym
== gIOTerminatedNotification
)
1352 userMsgType
= kIOServiceTerminatedNotificationType
;
1354 userMsgType
= kLastIOKitNotificationType
;
1356 userNotify
= new IOServiceUserNotification
;
1358 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1360 userNotify
->release();
1366 notify
= IOService::addNotification( sym
, dict
,
1367 &userNotify
->_handler
, userNotify
);
1370 *notification
= userNotify
;
1371 userNotify
->setNotification( notify
);
1372 err
= kIOReturnSuccess
;
1374 err
= kIOReturnUnsupported
;
1386 /* Routine io_service_add_notification_ool */
1387 kern_return_t
is_io_service_add_notification_ool(
1388 mach_port_t master_port
,
1389 io_name_t notification_type
,
1390 io_buf_ptr_t matching
,
1391 mach_msg_type_number_t matchingCnt
,
1392 mach_port_t wake_port
,
1393 io_async_ref_t reference
,
1394 mach_msg_type_number_t referenceCnt
,
1396 io_object_t
*notification
)
1400 vm_map_offset_t map_data
;
1402 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1403 data
= CAST_DOWN(vm_offset_t
, map_data
);
1405 if( KERN_SUCCESS
== kr
) {
1406 // must return success after vm_map_copyout() succeeds
1407 *result
= is_io_service_add_notification( master_port
, notification_type
,
1408 (char *) data
, wake_port
, reference
, referenceCnt
, notification
);
1409 vm_deallocate( kernel_map
, data
, matchingCnt
);
1416 /* Routine io_service_add_notification_old */
1417 kern_return_t
is_io_service_add_notification_old(
1418 mach_port_t master_port
,
1419 io_name_t notification_type
,
1420 io_string_t matching
,
1423 io_object_t
* notification
)
1425 return( is_io_service_add_notification( master_port
, notification_type
,
1426 matching
, port
, &ref
, 1, notification
));
1429 /* Routine io_service_add_message_notification */
1430 kern_return_t
is_io_service_add_interest_notification(
1431 io_object_t _service
,
1432 io_name_t type_of_interest
,
1434 io_async_ref_t reference
,
1435 mach_msg_type_number_t referenceCnt
,
1436 io_object_t
* notification
)
1439 IOServiceMessageUserNotification
* userNotify
= 0;
1440 IONotifier
* notify
= 0;
1441 const OSSymbol
* sym
;
1444 CHECK( IOService
, _service
, service
);
1446 err
= kIOReturnNoResources
;
1447 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1449 userNotify
= new IOServiceMessageUserNotification
;
1451 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1452 reference
, kIOUserNotifyMaxMessageSize
)) {
1453 userNotify
->release();
1459 notify
= service
->registerInterest( sym
,
1460 &userNotify
->_handler
, userNotify
);
1462 *notification
= userNotify
;
1463 userNotify
->setNotification( notify
);
1464 err
= kIOReturnSuccess
;
1466 err
= kIOReturnUnsupported
;
1475 /* Routine io_service_acknowledge_notification */
1476 kern_return_t
is_io_service_acknowledge_notification(
1477 io_object_t _service
,
1478 natural_t notify_ref
,
1479 natural_t response
)
1481 CHECK( IOService
, _service
, service
);
1483 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1484 (IOOptionBits
) response
));
1488 /* Routine io_connect_get_semaphore */
1489 kern_return_t
is_io_connect_get_notification_semaphore(
1490 io_connect_t connection
,
1491 natural_t notification_type
,
1492 semaphore_t
*semaphore
)
1494 CHECK( IOUserClient
, connection
, client
);
1496 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1500 /* Routine io_registry_get_root_entry */
1501 kern_return_t
is_io_registry_get_root_entry(
1502 mach_port_t master_port
,
1505 IORegistryEntry
* entry
;
1507 if( master_port
!= master_device_port
)
1508 return( kIOReturnNotPrivileged
);
1510 entry
= IORegistryEntry::getRegistryRoot();
1515 return( kIOReturnSuccess
);
1518 /* Routine io_registry_create_iterator */
1519 kern_return_t
is_io_registry_create_iterator(
1520 mach_port_t master_port
,
1523 io_object_t
*iterator
)
1525 if( master_port
!= master_device_port
)
1526 return( kIOReturnNotPrivileged
);
1528 *iterator
= IORegistryIterator::iterateOver(
1529 IORegistryEntry::getPlane( plane
), options
);
1531 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1534 /* Routine io_registry_entry_create_iterator */
1535 kern_return_t
is_io_registry_entry_create_iterator(
1536 io_object_t registry_entry
,
1539 io_object_t
*iterator
)
1541 CHECK( IORegistryEntry
, registry_entry
, entry
);
1543 *iterator
= IORegistryIterator::iterateOver( entry
,
1544 IORegistryEntry::getPlane( plane
), options
);
1546 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1549 /* Routine io_registry_iterator_enter */
1550 kern_return_t
is_io_registry_iterator_enter_entry(
1551 io_object_t iterator
)
1553 CHECK( IORegistryIterator
, iterator
, iter
);
1557 return( kIOReturnSuccess
);
1560 /* Routine io_registry_iterator_exit */
1561 kern_return_t
is_io_registry_iterator_exit_entry(
1562 io_object_t iterator
)
1566 CHECK( IORegistryIterator
, iterator
, iter
);
1568 didIt
= iter
->exitEntry();
1570 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1573 /* Routine io_registry_entry_from_path */
1574 kern_return_t
is_io_registry_entry_from_path(
1575 mach_port_t master_port
,
1577 io_object_t
*registry_entry
)
1579 IORegistryEntry
* entry
;
1581 if( master_port
!= master_device_port
)
1582 return( kIOReturnNotPrivileged
);
1584 entry
= IORegistryEntry::fromPath( path
);
1586 *registry_entry
= entry
;
1588 return( kIOReturnSuccess
);
1591 /* Routine io_registry_entry_in_plane */
1592 kern_return_t
is_io_registry_entry_in_plane(
1593 io_object_t registry_entry
,
1595 boolean_t
*inPlane
)
1597 CHECK( IORegistryEntry
, registry_entry
, entry
);
1599 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1601 return( kIOReturnSuccess
);
1605 /* Routine io_registry_entry_get_path */
1606 kern_return_t
is_io_registry_entry_get_path(
1607 io_object_t registry_entry
,
1612 CHECK( IORegistryEntry
, registry_entry
, entry
);
1614 length
= sizeof( io_string_t
);
1615 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1616 return( kIOReturnSuccess
);
1618 return( kIOReturnBadArgument
);
1622 /* Routine io_registry_entry_get_name */
1623 kern_return_t
is_io_registry_entry_get_name(
1624 io_object_t registry_entry
,
1627 CHECK( IORegistryEntry
, registry_entry
, entry
);
1629 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1631 return( kIOReturnSuccess
);
1634 /* Routine io_registry_entry_get_name_in_plane */
1635 kern_return_t
is_io_registry_entry_get_name_in_plane(
1636 io_object_t registry_entry
,
1637 io_name_t planeName
,
1640 const IORegistryPlane
* plane
;
1641 CHECK( IORegistryEntry
, registry_entry
, entry
);
1644 plane
= IORegistryEntry::getPlane( planeName
);
1648 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
1650 return( kIOReturnSuccess
);
1653 /* Routine io_registry_entry_get_location_in_plane */
1654 kern_return_t
is_io_registry_entry_get_location_in_plane(
1655 io_object_t registry_entry
,
1656 io_name_t planeName
,
1657 io_name_t location
)
1659 const IORegistryPlane
* plane
;
1660 CHECK( IORegistryEntry
, registry_entry
, entry
);
1663 plane
= IORegistryEntry::getPlane( planeName
);
1667 const char * cstr
= entry
->getLocation( plane
);
1670 strncpy( location
, cstr
, sizeof( io_name_t
));
1671 return( kIOReturnSuccess
);
1673 return( kIOReturnNotFound
);
1676 // Create a vm_map_copy_t or kalloc'ed data for memory
1677 // to be copied out. ipc will free after the copyout.
1679 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1680 io_buf_ptr_t
* buf
)
1685 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1686 false /* src_destroy */, ©
);
1688 assert( err
== KERN_SUCCESS
);
1689 if( err
== KERN_SUCCESS
)
1690 *buf
= (char *) copy
;
1695 /* Routine io_registry_entry_get_property */
1696 kern_return_t
is_io_registry_entry_get_property_bytes(
1697 io_object_t registry_entry
,
1698 io_name_t property_name
,
1699 io_scalar_inband_t buf
,
1700 mach_msg_type_number_t
*dataCnt
)
1708 unsigned int len
= 0;
1709 const void * bytes
= 0;
1710 IOReturn ret
= kIOReturnSuccess
;
1712 CHECK( IORegistryEntry
, registry_entry
, entry
);
1714 obj
= entry
->copyProperty(property_name
);
1716 return( kIOReturnNoResources
);
1718 // One day OSData will be a common container base class
1720 if( (data
= OSDynamicCast( OSData
, obj
))) {
1721 len
= data
->getLength();
1722 bytes
= data
->getBytesNoCopy();
1724 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1725 len
= str
->getLength() + 1;
1726 bytes
= str
->getCStringNoCopy();
1728 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1729 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1730 bytes
= boo
->isTrue() ? "Yes" : "No";
1732 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1733 offsetBytes
= off
->unsigned64BitValue();
1734 len
= off
->numberOfBytes();
1735 bytes
= &offsetBytes
;
1736 #ifdef __BIG_ENDIAN__
1737 bytes
= (const void *)
1738 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1742 ret
= kIOReturnBadArgument
;
1746 ret
= kIOReturnIPCError
;
1749 bcopy( bytes
, buf
, len
);
1757 /* Routine io_registry_entry_get_property */
1758 kern_return_t
is_io_registry_entry_get_property(
1759 io_object_t registry_entry
,
1760 io_name_t property_name
,
1761 io_buf_ptr_t
*properties
,
1762 mach_msg_type_number_t
*propertiesCnt
)
1768 CHECK( IORegistryEntry
, registry_entry
, entry
);
1770 obj
= entry
->copyProperty(property_name
);
1772 return( kIOReturnNotFound
);
1774 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1777 return( kIOReturnNoMemory
);
1781 if( obj
->serialize( s
)) {
1782 len
= s
->getLength();
1783 *propertiesCnt
= len
;
1784 err
= copyoutkdata( s
->text(), len
, properties
);
1787 err
= kIOReturnUnsupported
;
1795 /* Routine io_registry_entry_get_property_recursively */
1796 kern_return_t
is_io_registry_entry_get_property_recursively(
1797 io_object_t registry_entry
,
1799 io_name_t property_name
,
1801 io_buf_ptr_t
*properties
,
1802 mach_msg_type_number_t
*propertiesCnt
)
1808 CHECK( IORegistryEntry
, registry_entry
, entry
);
1810 obj
= entry
->copyProperty( property_name
,
1811 IORegistryEntry::getPlane( plane
), options
);
1813 return( kIOReturnNotFound
);
1815 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1818 return( kIOReturnNoMemory
);
1823 if( obj
->serialize( s
)) {
1824 len
= s
->getLength();
1825 *propertiesCnt
= len
;
1826 err
= copyoutkdata( s
->text(), len
, properties
);
1829 err
= kIOReturnUnsupported
;
1837 /* Routine io_registry_entry_get_properties */
1838 kern_return_t
is_io_registry_entry_get_properties(
1839 io_object_t registry_entry
,
1840 io_buf_ptr_t
*properties
,
1841 mach_msg_type_number_t
*propertiesCnt
)
1846 CHECK( IORegistryEntry
, registry_entry
, entry
);
1848 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1850 return( kIOReturnNoMemory
);
1854 if( entry
->serializeProperties( s
)) {
1855 len
= s
->getLength();
1856 *propertiesCnt
= len
;
1857 err
= copyoutkdata( s
->text(), len
, properties
);
1860 err
= kIOReturnUnsupported
;
1867 /* Routine io_registry_entry_set_properties */
1868 kern_return_t is_io_registry_entry_set_properties
1870 io_object_t registry_entry
,
1871 io_buf_ptr_t properties
,
1872 mach_msg_type_number_t propertiesCnt
,
1879 vm_map_offset_t map_data
;
1881 CHECK( IORegistryEntry
, registry_entry
, entry
);
1883 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
1884 data
= CAST_DOWN(vm_offset_t
, map_data
);
1886 if( KERN_SUCCESS
== err
) {
1888 // must return success after vm_map_copyout() succeeds
1889 obj
= OSUnserializeXML( (const char *) data
);
1890 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1893 res
= entry
->setProperties( obj
);
1896 res
= kIOReturnBadArgument
;
1904 /* Routine io_registry_entry_get_child_iterator */
1905 kern_return_t
is_io_registry_entry_get_child_iterator(
1906 io_object_t registry_entry
,
1908 io_object_t
*iterator
)
1910 CHECK( IORegistryEntry
, registry_entry
, entry
);
1912 *iterator
= entry
->getChildIterator(
1913 IORegistryEntry::getPlane( plane
));
1915 return( kIOReturnSuccess
);
1918 /* Routine io_registry_entry_get_parent_iterator */
1919 kern_return_t
is_io_registry_entry_get_parent_iterator(
1920 io_object_t registry_entry
,
1922 io_object_t
*iterator
)
1924 CHECK( IORegistryEntry
, registry_entry
, entry
);
1926 *iterator
= entry
->getParentIterator(
1927 IORegistryEntry::getPlane( plane
));
1929 return( kIOReturnSuccess
);
1932 /* Routine io_service_get_busy_state */
1933 kern_return_t
is_io_service_get_busy_state(
1934 io_object_t _service
,
1937 CHECK( IOService
, _service
, service
);
1939 *busyState
= service
->getBusyState();
1941 return( kIOReturnSuccess
);
1944 /* Routine io_service_get_state */
1945 kern_return_t
is_io_service_get_state(
1946 io_object_t _service
,
1949 CHECK( IOService
, _service
, service
);
1951 *state
= service
->getState();
1953 return( kIOReturnSuccess
);
1956 /* Routine io_service_wait_quiet */
1957 kern_return_t
is_io_service_wait_quiet(
1958 io_object_t _service
,
1959 mach_timespec_t wait_time
)
1961 CHECK( IOService
, _service
, service
);
1963 return( service
->waitQuiet( &wait_time
));
1966 /* Routine io_service_request_probe */
1967 kern_return_t
is_io_service_request_probe(
1968 io_object_t _service
,
1971 CHECK( IOService
, _service
, service
);
1973 return( service
->requestProbe( options
));
1977 /* Routine io_service_open */
1978 kern_return_t
is_io_service_open(
1979 io_object_t _service
,
1982 io_object_t
*connection
)
1984 IOUserClient
* client
;
1987 CHECK( IOService
, _service
, service
);
1989 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1990 connect_type
, &client
);
1992 if( err
== kIOReturnSuccess
) {
1993 assert( OSDynamicCast(IOUserClient
, client
) );
1994 *connection
= client
;
2000 /* Routine io_service_close */
2001 kern_return_t
is_io_service_close(
2002 io_object_t connection
)
2005 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
2006 return( kIOReturnSuccess
);
2008 CHECK( IOUserClient
, connection
, client
);
2010 client
->clientClose();
2012 return( kIOReturnSuccess
);
2015 /* Routine io_connect_get_service */
2016 kern_return_t
is_io_connect_get_service(
2017 io_object_t connection
,
2018 io_object_t
*service
)
2020 IOService
* theService
;
2022 CHECK( IOUserClient
, connection
, client
);
2024 theService
= client
->getService();
2026 theService
->retain();
2028 *service
= theService
;
2030 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
2033 /* Routine io_connect_set_notification_port */
2034 kern_return_t
is_io_connect_set_notification_port(
2035 io_object_t connection
,
2036 int notification_type
,
2040 CHECK( IOUserClient
, connection
, client
);
2042 return( client
->registerNotificationPort( port
, notification_type
,
2046 kern_return_t
is_io_connect_map_memory(
2047 io_object_t connect
,
2050 vm_address_t
* mapAddr
,
2051 vm_size_t
* mapSize
,
2057 CHECK( IOUserClient
, connect
, client
);
2059 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
2062 *mapAddr
= map
->getVirtualAddress();
2064 *mapSize
= map
->getLength();
2066 if( task
!= current_task()) {
2067 // push a name out to the task owning the map,
2068 // so we can clean up maps
2070 mach_port_name_t name
=
2072 IOMachPort::makeSendRightForTask(
2073 task
, map
, IKOT_IOKIT_OBJECT
);
2077 // keep it with the user client
2078 IOLockLock( gIOObjectPortLock
);
2079 if( 0 == client
->mappings
)
2080 client
->mappings
= OSSet::withCapacity(2);
2081 if( client
->mappings
)
2082 client
->mappings
->setObject( map
);
2083 IOLockUnlock( gIOObjectPortLock
);
2086 err
= kIOReturnSuccess
;
2089 err
= kIOReturnBadArgument
;
2094 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
2097 IOMemoryMap
* map
= 0;
2099 IOLockLock(gIOObjectPortLock
);
2101 iter
= OSCollectionIterator::withCollection(mappings
);
2104 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
2106 if(mem
== map
->getMemoryDescriptor())
2109 mappings
->removeObject(map
);
2116 IOLockUnlock(gIOObjectPortLock
);
2121 kern_return_t
is_io_connect_unmap_memory(
2122 io_object_t connect
,
2125 vm_address_t mapAddr
)
2128 IOOptionBits options
= 0;
2129 IOMemoryDescriptor
* memory
;
2132 CHECK( IOUserClient
, connect
, client
);
2134 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
2136 if( memory
&& (kIOReturnSuccess
== err
)) {
2138 options
= (options
& ~kIOMapUserOptionsMask
)
2139 | kIOMapAnywhere
| kIOMapReference
;
2141 map
= memory
->map( task
, mapAddr
, options
);
2145 IOLockLock( gIOObjectPortLock
);
2146 if( client
->mappings
)
2147 client
->mappings
->removeObject( map
);
2148 IOLockUnlock( gIOObjectPortLock
);
2150 mach_port_name_t name
= 0;
2151 if (task
!= current_task())
2152 name
= IOMachPort::makeSendRightForTask( task
, map
, IKOT_IOKIT_OBJECT
);
2156 err
= iokit_mod_send_right( task
, name
, -2 );
2157 err
= kIOReturnSuccess
;
2160 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
2161 if (task
== current_task())
2165 err
= kIOReturnBadArgument
;
2172 /* Routine io_connect_add_client */
2173 kern_return_t
is_io_connect_add_client(
2174 io_object_t connection
,
2175 io_object_t connect_to
)
2177 CHECK( IOUserClient
, connection
, client
);
2178 CHECK( IOUserClient
, connect_to
, to
);
2180 return( client
->connectClient( to
) );
2184 /* Routine io_connect_set_properties */
2185 kern_return_t
is_io_connect_set_properties(
2186 io_object_t connection
,
2187 io_buf_ptr_t properties
,
2188 mach_msg_type_number_t propertiesCnt
,
2191 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
2195 /* Routine io_connect_method_scalarI_scalarO */
2196 kern_return_t
is_io_connect_method_scalarI_scalarO(
2197 io_object_t connect
,
2200 IOByteCount inputCount
,
2202 IOByteCount
* outputCount
)
2205 IOExternalMethod
* method
;
2209 CHECK( IOUserClient
, connect
, client
);
2210 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
2212 err
= kIOReturnBadArgument
;
2213 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2215 if( inputCount
!= method
->count0
)
2217 if( *outputCount
!= method
->count1
)
2220 func
= method
->func
;
2222 switch( inputCount
) {
2225 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2226 input
[3], input
[4], input
[5] );
2229 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2234 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2236 &output
[0], &output
[1] );
2239 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2240 &output
[0], &output
[1], &output
[2] );
2243 err
= (object
->*func
)( input
[0], input
[1],
2244 &output
[0], &output
[1], &output
[2],
2248 err
= (object
->*func
)( input
[0],
2249 &output
[0], &output
[1], &output
[2],
2250 &output
[3], &output
[4] );
2253 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
2254 &output
[3], &output
[4], &output
[5] );
2258 IOLog("%s: Bad method table\n", client
->getName());
2263 err
= kIOReturnUnsupported
;
2268 /* Routine io_connect_method_scalarI_structureO */
2269 kern_return_t
is_io_connect_method_scalarI_structureO(
2270 io_object_t connect
,
2273 IOByteCount inputCount
,
2275 IOByteCount
* outputCount
)
2278 IOExternalMethod
* method
;
2282 CHECK( IOUserClient
, connect
, client
);
2284 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2286 err
= kIOReturnBadArgument
;
2287 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2289 if( inputCount
!= method
->count0
)
2291 if( (0xffffffff != method
->count1
)
2292 && (*outputCount
!= method
->count1
))
2295 func
= method
->func
;
2297 switch( inputCount
) {
2300 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2305 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2307 output
, (void *)outputCount
);
2310 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2311 output
, (void *)outputCount
, 0 );
2314 err
= (object
->*func
)( input
[0], input
[1],
2315 output
, (void *)outputCount
, 0, 0 );
2318 err
= (object
->*func
)( input
[0],
2319 output
, (void *)outputCount
, 0, 0, 0 );
2322 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
2326 IOLog("%s: Bad method table\n", client
->getName());
2331 err
= kIOReturnUnsupported
;
2336 /* Routine io_connect_method_scalarI_structureI */
2337 kern_return_t
is_io_connect_method_scalarI_structureI(
2338 io_connect_t connect
,
2341 IOByteCount inputCount
,
2342 UInt8
* inputStruct
,
2343 IOByteCount inputStructCount
)
2346 IOExternalMethod
* method
;
2350 CHECK( IOUserClient
, connect
, client
);
2352 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2354 err
= kIOReturnBadArgument
;
2355 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2357 if( (0xffffffff != method
->count0
)
2358 && (inputCount
!= method
->count0
))
2360 if( (0xffffffff != method
->count1
)
2361 && (inputStructCount
!= method
->count1
))
2364 func
= method
->func
;
2366 switch( inputCount
) {
2369 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2374 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2376 inputStruct
, (void *)inputStructCount
);
2379 err
= (object
->*func
)( input
[0], input
[1], input
[2],
2380 inputStruct
, (void *)inputStructCount
,
2384 err
= (object
->*func
)( input
[0], input
[1],
2385 inputStruct
, (void *)inputStructCount
,
2389 err
= (object
->*func
)( input
[0],
2390 inputStruct
, (void *)inputStructCount
,
2394 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
2399 IOLog("%s: Bad method table\n", client
->getName());
2404 err
= kIOReturnUnsupported
;
2409 /* Routine io_connect_method_structureI_structureO */
2410 kern_return_t
is_io_connect_method_structureI_structureO(
2411 io_object_t connect
,
2414 IOByteCount inputCount
,
2416 IOByteCount
* outputCount
)
2419 IOExternalMethod
* method
;
2423 CHECK( IOUserClient
, connect
, client
);
2425 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
2427 err
= kIOReturnBadArgument
;
2428 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2430 if( (0xffffffff != method
->count0
)
2431 && (inputCount
!= method
->count0
))
2433 if( (0xffffffff != method
->count1
)
2434 && (*outputCount
!= method
->count1
))
2437 func
= method
->func
;
2439 if( method
->count1
) {
2440 if( method
->count0
) {
2441 err
= (object
->*func
)( input
, output
,
2442 (void *)inputCount
, outputCount
, 0, 0 );
2444 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
2447 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
2453 err
= kIOReturnUnsupported
;
2458 kern_return_t
is_io_async_method_scalarI_scalarO(
2459 io_object_t connect
,
2460 mach_port_t wakePort
,
2461 io_async_ref_t reference
,
2462 mach_msg_type_number_t referenceCnt
,
2465 IOByteCount inputCount
,
2467 IOByteCount
* outputCount
)
2470 IOExternalAsyncMethod
*method
;
2474 CHECK( IOUserClient
, connect
, client
);
2475 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2477 err
= kIOReturnBadArgument
;
2478 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
2480 if( inputCount
!= method
->count0
)
2482 if( *outputCount
!= method
->count1
)
2485 reference
[0] = (natural_t
) wakePort
;
2486 func
= method
->func
;
2488 switch( inputCount
) {
2491 err
= (object
->*func
)( reference
,
2492 input
[0], input
[1], input
[2],
2493 input
[3], input
[4], input
[5] );
2496 err
= (object
->*func
)( reference
,
2497 input
[0], input
[1], input
[2],
2502 err
= (object
->*func
)( reference
,
2503 input
[0], input
[1], input
[2],
2505 &output
[0], &output
[1] );
2508 err
= (object
->*func
)( reference
,
2509 input
[0], input
[1], input
[2],
2510 &output
[0], &output
[1], &output
[2] );
2513 err
= (object
->*func
)( reference
,
2515 &output
[0], &output
[1], &output
[2],
2519 err
= (object
->*func
)( reference
,
2521 &output
[0], &output
[1], &output
[2],
2522 &output
[3], &output
[4] );
2525 err
= (object
->*func
)( reference
,
2526 &output
[0], &output
[1], &output
[2],
2527 &output
[3], &output
[4], &output
[5] );
2531 IOLog("%s: Bad method table\n", client
->getName());
2536 err
= kIOReturnUnsupported
;
2541 kern_return_t
is_io_async_method_scalarI_structureO(
2542 io_object_t connect
,
2543 mach_port_t wakePort
,
2544 io_async_ref_t reference
,
2545 mach_msg_type_number_t referenceCnt
,
2548 IOByteCount inputCount
,
2550 IOByteCount
* outputCount
)
2553 IOExternalAsyncMethod
*method
;
2557 CHECK( IOUserClient
, connect
, client
);
2559 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2561 err
= kIOReturnBadArgument
;
2562 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2564 if( inputCount
!= method
->count0
)
2566 if( (0xffffffff != method
->count1
)
2567 && (*outputCount
!= method
->count1
))
2570 reference
[0] = (natural_t
) wakePort
;
2571 func
= method
->func
;
2573 switch( inputCount
) {
2576 err
= (object
->*func
)( reference
,
2577 input
[0], input
[1], input
[2],
2582 err
= (object
->*func
)( reference
,
2583 input
[0], input
[1], input
[2],
2585 output
, (void *)outputCount
);
2588 err
= (object
->*func
)( reference
,
2589 input
[0], input
[1], input
[2],
2590 output
, (void *)outputCount
, 0 );
2593 err
= (object
->*func
)( reference
,
2595 output
, (void *)outputCount
, 0, 0 );
2598 err
= (object
->*func
)( reference
,
2600 output
, (void *)outputCount
, 0, 0, 0 );
2603 err
= (object
->*func
)( reference
,
2604 output
, (void *)outputCount
, 0, 0, 0, 0 );
2608 IOLog("%s: Bad method table\n", client
->getName());
2613 err
= kIOReturnUnsupported
;
2618 kern_return_t
is_io_async_method_scalarI_structureI(
2619 io_connect_t connect
,
2620 mach_port_t wakePort
,
2621 io_async_ref_t reference
,
2622 mach_msg_type_number_t referenceCnt
,
2625 IOByteCount inputCount
,
2626 UInt8
* inputStruct
,
2627 IOByteCount inputStructCount
)
2630 IOExternalAsyncMethod
*method
;
2634 CHECK( IOUserClient
, connect
, client
);
2636 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2638 err
= kIOReturnBadArgument
;
2639 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2641 if( (0xffffffff != method
->count0
)
2642 && (inputCount
!= method
->count0
))
2644 if( (0xffffffff != method
->count1
)
2645 && (inputStructCount
!= method
->count1
))
2648 reference
[0] = (natural_t
) wakePort
;
2649 func
= method
->func
;
2651 switch( inputCount
) {
2654 err
= (object
->*func
)( reference
,
2655 input
[0], input
[1], input
[2],
2660 err
= (object
->*func
)( reference
,
2661 input
[0], input
[1], input
[2],
2663 inputStruct
, (void *)inputStructCount
);
2666 err
= (object
->*func
)( reference
,
2667 input
[0], input
[1], input
[2],
2668 inputStruct
, (void *)inputStructCount
,
2672 err
= (object
->*func
)( reference
,
2674 inputStruct
, (void *)inputStructCount
,
2678 err
= (object
->*func
)( reference
,
2680 inputStruct
, (void *)inputStructCount
,
2684 err
= (object
->*func
)( reference
,
2685 inputStruct
, (void *)inputStructCount
,
2690 IOLog("%s: Bad method table\n", client
->getName());
2695 err
= kIOReturnUnsupported
;
2700 kern_return_t
is_io_async_method_structureI_structureO(
2701 io_object_t connect
,
2702 mach_port_t wakePort
,
2703 io_async_ref_t reference
,
2704 mach_msg_type_number_t referenceCnt
,
2707 IOByteCount inputCount
,
2709 IOByteCount
* outputCount
)
2712 IOExternalAsyncMethod
*method
;
2716 CHECK( IOUserClient
, connect
, client
);
2718 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2720 err
= kIOReturnBadArgument
;
2721 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2723 if( (0xffffffff != method
->count0
)
2724 && (inputCount
!= method
->count0
))
2726 if( (0xffffffff != method
->count1
)
2727 && (*outputCount
!= method
->count1
))
2730 reference
[0] = (natural_t
) wakePort
;
2731 func
= method
->func
;
2733 if( method
->count1
) {
2734 if( method
->count0
) {
2735 err
= (object
->*func
)( reference
,
2737 (void *)inputCount
, outputCount
, 0, 0 );
2739 err
= (object
->*func
)( reference
,
2740 output
, outputCount
, 0, 0, 0, 0 );
2743 err
= (object
->*func
)( reference
,
2744 input
, (void *)inputCount
, 0, 0, 0, 0 );
2750 err
= kIOReturnUnsupported
;
2754 /* Routine io_make_matching */
2755 kern_return_t
is_io_make_matching(
2756 mach_port_t master_port
,
2758 IOOptionBits options
,
2760 IOByteCount inputCount
,
2761 io_string_t matching
)
2764 IOReturn err
= kIOReturnSuccess
;
2765 OSDictionary
* dict
;
2767 if( master_port
!= master_device_port
)
2768 return( kIOReturnNotPrivileged
);
2772 case kIOServiceMatching
:
2773 dict
= IOService::serviceMatching( gIOServiceKey
);
2776 case kIOBSDNameMatching
:
2777 dict
= IOBSDNameMatching( (const char *) input
);
2780 case kIOOFPathMatching
:
2781 dict
= IOOFPathMatching( (const char *) input
,
2782 matching
, sizeof( io_string_t
));
2790 return( kIOReturnUnsupported
);
2793 s
= OSSerialize::withCapacity(4096);
2795 err
= kIOReturnNoMemory
;
2799 if( !dict
->serialize( s
)) {
2800 err
= kIOReturnUnsupported
;
2804 if( s
->getLength() > sizeof( io_string_t
)) {
2805 err
= kIOReturnNoMemory
;
2808 strcpy( matching
, s
->text());
2820 /* Routine io_catalog_send_data */
2821 kern_return_t
is_io_catalog_send_data(
2822 mach_port_t master_port
,
2824 io_buf_ptr_t inData
,
2825 mach_msg_type_number_t inDataCount
,
2830 kern_return_t kr
= kIOReturnError
;
2832 //printf("io_catalog_send_data called. flag: %d\n", flag);
2834 if( master_port
!= master_device_port
)
2835 return kIOReturnNotPrivileged
;
2837 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2838 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2839 return kIOReturnBadArgument
;
2842 vm_map_offset_t map_data
;
2844 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
2845 data
= CAST_DOWN(vm_offset_t
, map_data
);
2847 if( kr
!= KERN_SUCCESS
)
2850 // must return success after vm_map_copyout() succeeds
2853 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2854 vm_deallocate( kernel_map
, data
, inDataCount
);
2856 *result
= kIOReturnNoMemory
;
2857 return( KERN_SUCCESS
);
2863 case kIOCatalogAddDrivers
:
2864 case kIOCatalogAddDriversNoMatch
: {
2867 array
= OSDynamicCast(OSArray
, obj
);
2869 if ( !gIOCatalogue
->addDrivers( array
,
2870 flag
== kIOCatalogAddDrivers
) ) {
2871 kr
= kIOReturnError
;
2875 kr
= kIOReturnBadArgument
;
2880 case kIOCatalogRemoveDrivers
:
2881 case kIOCatalogRemoveDriversNoMatch
: {
2882 OSDictionary
* dict
;
2884 dict
= OSDynamicCast(OSDictionary
, obj
);
2886 if ( !gIOCatalogue
->removeDrivers( dict
,
2887 flag
== kIOCatalogRemoveDrivers
) ) {
2888 kr
= kIOReturnError
;
2892 kr
= kIOReturnBadArgument
;
2897 case kIOCatalogStartMatching
: {
2898 OSDictionary
* dict
;
2900 dict
= OSDynamicCast(OSDictionary
, obj
);
2902 if ( !gIOCatalogue
->startMatching( dict
) ) {
2903 kr
= kIOReturnError
;
2907 kr
= kIOReturnBadArgument
;
2912 case kIOCatalogRemoveKernelLinker
: {
2913 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
2914 kr
= kIOReturnError
;
2916 kr
= kIOReturnSuccess
;
2922 kr
= kIOReturnBadArgument
;
2926 if (obj
) obj
->release();
2929 return( KERN_SUCCESS
);
2932 /* Routine io_catalog_terminate */
2933 kern_return_t
is_io_catalog_terminate(
2934 mach_port_t master_port
,
2940 if( master_port
!= master_device_port
)
2941 return kIOReturnNotPrivileged
;
2943 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
2944 kIOClientPrivilegeAdministrator
);
2945 if( kIOReturnSuccess
!= kr
)
2949 case kIOCatalogServiceTerminate
:
2951 IOService
* service
;
2953 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
2954 kIORegistryIterateRecursively
);
2956 return kIOReturnNoMemory
;
2960 while( (service
= (IOService
*)iter
->getNextObject()) ) {
2961 if( service
->metaCast(name
)) {
2962 if ( !service
->terminate( kIOServiceRequired
2963 | kIOServiceSynchronous
) ) {
2964 kr
= kIOReturnUnsupported
;
2969 } while( !service
&& !iter
->isValid());
2973 case kIOCatalogModuleUnload
:
2974 case kIOCatalogModuleTerminate
:
2975 kr
= gIOCatalogue
->terminateDriversForModule(name
,
2976 flag
== kIOCatalogModuleUnload
);
2980 kr
= kIOReturnBadArgument
;
2987 /* Routine io_catalog_get_data */
2988 kern_return_t
is_io_catalog_get_data(
2989 mach_port_t master_port
,
2991 io_buf_ptr_t
*outData
,
2992 mach_msg_type_number_t
*outDataCount
)
2994 kern_return_t kr
= kIOReturnSuccess
;
2997 if( master_port
!= master_device_port
)
2998 return kIOReturnNotPrivileged
;
3000 //printf("io_catalog_get_data called. flag: %d\n", flag);
3002 s
= OSSerialize::withCapacity(4096);
3004 return kIOReturnNoMemory
;
3008 kr
= gIOCatalogue
->serializeData(flag
, s
);
3010 if ( kr
== kIOReturnSuccess
) {
3015 size
= s
->getLength();
3016 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
3017 if ( kr
== kIOReturnSuccess
) {
3018 bcopy(s
->text(), (void *)data
, size
);
3019 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
3020 (vm_map_size_t
)size
, true, ©
);
3021 *outData
= (char *)copy
;
3022 *outDataCount
= size
;
3031 /* Routine io_catalog_get_gen_count */
3032 kern_return_t
is_io_catalog_get_gen_count(
3033 mach_port_t master_port
,
3036 if( master_port
!= master_device_port
)
3037 return kIOReturnNotPrivileged
;
3039 //printf("io_catalog_get_gen_count called.\n");
3042 return kIOReturnBadArgument
;
3044 *genCount
= gIOCatalogue
->getGenerationCount();
3046 return kIOReturnSuccess
;
3049 /* Routine io_catalog_module_loaded */
3050 kern_return_t
is_io_catalog_module_loaded(
3051 mach_port_t master_port
,
3054 if( master_port
!= master_device_port
)
3055 return kIOReturnNotPrivileged
;
3057 //printf("io_catalog_module_loaded called. name %s\n", name);
3060 return kIOReturnBadArgument
;
3062 gIOCatalogue
->moduleHasLoaded(name
);
3064 return kIOReturnSuccess
;
3067 kern_return_t
is_io_catalog_reset(
3068 mach_port_t master_port
,
3071 if( master_port
!= master_device_port
)
3072 return kIOReturnNotPrivileged
;
3075 case kIOCatalogResetDefault
:
3076 gIOCatalogue
->reset();
3080 return kIOReturnBadArgument
;
3083 return kIOReturnSuccess
;
3086 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
3088 kern_return_t result
= kIOReturnBadArgument
;
3089 IOUserClient
*userClient
;
3091 if ((userClient
= OSDynamicCast(IOUserClient
,
3092 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
3093 IOExternalTrap
*trap
;
3094 IOService
*target
= NULL
;
3096 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
3098 if (trap
&& target
) {
3104 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
3108 userClient
->release();
3116 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
3117 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
3118 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
3119 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
3120 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
3121 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
3122 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
3123 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
3124 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
3125 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
3126 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
3127 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
3128 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
3129 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
3130 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
3131 OSMetaClassDefineReservedUnused(IOUserClient
, 15);