2 * Copyright (c) 1998-2000 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@
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
27 * 14 Aug 98 sdouglas created.
28 * 08 Dec 98 sdouglas cpp.
31 #include <IOKit/IOKitServer.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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 // definitions we should get from osfmk
45 //typedef struct ipc_port * ipc_port_t;
46 typedef natural_t ipc_kobject_type_t
;
48 #define IKOT_IOKIT_SPARE 27
49 #define IKOT_IOKIT_CONNECT 29
50 #define IKOT_IOKIT_OBJECT 30
54 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
55 ipc_kobject_type_t type
);
57 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
59 extern mach_port_name_t
iokit_make_send_right( task_t task
,
60 io_object_t obj
, ipc_kobject_type_t type
);
62 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
64 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
66 extern ipc_port_t master_device_port
;
68 #include <vm/vm_map.h>
73 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
75 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
77 class IOMachPort
: public OSObject
79 OSDeclareDefaultStructors(IOMachPort
)
84 static IOMachPort
* portForObject( OSObject
* obj
,
85 ipc_kobject_type_t type
);
86 static void releasePortForObject( OSObject
* obj
,
87 ipc_kobject_type_t type
);
88 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
90 static mach_port_name_t
makeSendRightForTask( task_t task
,
91 io_object_t obj
, ipc_kobject_type_t type
);
96 #define super OSObject
97 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
99 static IOLock
* gIOObjectPortLock
;
101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103 // not in dictForType() for debugging ease
104 static OSDictionary
* gIOObjectPorts
;
105 static OSDictionary
* gIOConnectPorts
;
107 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
109 OSDictionary
** dict
;
111 if( IKOT_IOKIT_OBJECT
== type
)
112 dict
= &gIOObjectPorts
;
113 else if( IKOT_IOKIT_CONNECT
== type
)
114 dict
= &gIOConnectPorts
;
119 *dict
= OSDictionary::withCapacity( 1 );
124 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
125 ipc_kobject_type_t type
)
127 IOMachPort
* inst
= 0;
130 IOTakeLock( gIOObjectPortLock
);
134 dict
= dictForType( type
);
138 if( (inst
= (IOMachPort
*)
139 dict
->getObject( (const OSSymbol
*) obj
)))
142 inst
= new IOMachPort
;
143 if( inst
&& !inst
->init()) {
148 inst
->port
= iokit_alloc_object_port( obj
, type
);
151 dict
->setObject( (const OSSymbol
*) obj
, inst
);
152 inst
->release(); // one more to free port => release obj
161 IOUnlock( gIOObjectPortLock
);
166 void IOMachPort::releasePortForObject( OSObject
* obj
,
167 ipc_kobject_type_t type
)
171 IOTakeLock( gIOObjectPortLock
);
173 if( (dict
= dictForType( type
))) {
175 dict
->removeObject( (const OSSymbol
*) obj
);
179 IOUnlock( gIOObjectPortLock
);
182 void IOUserClient::destroyUserReferences( OSObject
* obj
)
184 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
185 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_CONNECT
);
188 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
189 io_object_t obj
, ipc_kobject_type_t type
)
191 return( iokit_make_send_right( task
, obj
, type
));
194 void IOMachPort::free( void )
197 iokit_destroy_object_port( port
);
201 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
205 // functions called from osfmk/device/iokit_rpc.c
208 iokit_add_reference( io_object_t obj
)
215 iokit_remove_reference( io_object_t obj
)
222 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
224 IOMachPort
* machPort
;
226 if( (machPort
= IOMachPort::portForObject( obj
, type
)))
227 return( machPort
->port
);
233 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
234 ipc_kobject_type_t type
)
236 IOUserClient
* client
;
239 if( (IKOT_IOKIT_CONNECT
== type
)
240 && (client
= OSDynamicCast( IOUserClient
, obj
)))
241 client
->clientDied();
242 else if( (IKOT_IOKIT_OBJECT
== type
)
243 && (map
= OSDynamicCast( IOMemoryMap
, obj
)))
246 IOMachPort::releasePortForObject( obj
, type
);
248 return( kIOReturnSuccess
);
253 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
255 class IOUserNotification
: public OSIterator
257 OSDeclareDefaultStructors(IOUserNotification
)
260 mach_msg_header_t msgHdr
;
261 OSNotificationHeader notifyHeader
;
266 IONotifier
* holdNotify
;
271 virtual bool init( mach_port_t port
, natural_t type
,
272 OSAsyncReference reference
,
273 vm_size_t messageSize
);
276 virtual void setNotification( IONotifier
* obj
);
278 virtual void reset();
279 virtual bool isValid();
282 class IOServiceUserNotification
: public IOUserNotification
284 OSDeclareDefaultStructors(IOServiceUserNotification
)
286 enum { kMaxOutstanding
= 256 };
289 OSObject
* lastEntry
;
294 virtual bool init( mach_port_t port
, natural_t type
,
295 OSAsyncReference reference
);
298 static bool _handler( void * target
,
299 void * ref
, IOService
* newService
);
300 virtual bool handler( void * ref
, IOService
* newService
);
302 virtual OSObject
* getNextObject();
305 class IOServiceMessageUserNotification
: public IOUserNotification
307 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
311 virtual bool init( mach_port_t port
, natural_t type
,
312 OSAsyncReference reference
, vm_size_t extraSize
);
315 static IOReturn
_handler( void * target
, void * ref
,
316 UInt32 messageType
, IOService
* provider
,
317 void * messageArgument
, vm_size_t argSize
);
318 virtual IOReturn
handler( void * ref
,
319 UInt32 messageType
, IOService
* provider
,
320 void * messageArgument
, vm_size_t argSize
);
322 virtual OSObject
* getNextObject();
325 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
328 #define super OSIterator
329 OSDefineMetaClass( IOUserNotification
, OSIterator
)
330 OSDefineAbstractStructors( IOUserNotification
, OSIterator
)
332 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
334 bool IOUserNotification::init( mach_port_t port
, natural_t type
,
335 OSAsyncReference reference
, vm_size_t extraSize
)
340 lock
= IOLockAlloc();
344 msgSize
= sizeof( PingMsg
) + extraSize
;
345 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
349 bzero( pingMsg
, msgSize
);
351 pingMsg
->msgHdr
.msgh_remote_port
= port
;
352 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
353 MACH_MSG_TYPE_COPY_SEND
,
354 MACH_MSG_TYPE_COPY_SEND
);
355 pingMsg
->msgHdr
.msgh_size
= msgSize
;
356 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
358 pingMsg
->notifyHeader
.size
= extraSize
;
359 pingMsg
->notifyHeader
.type
= type
;
360 bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) );
365 void IOUserNotification::free( void )
368 holdNotify
->remove();
369 // can't be in handler now
372 IOFree( pingMsg
, msgSize
);
381 void IOUserNotification::setNotification( IONotifier
* notify
)
384 holdNotify
->remove();
389 void IOUserNotification::reset()
394 bool IOUserNotification::isValid()
399 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
402 #define super IOUserNotification
403 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
405 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
407 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
408 OSAsyncReference reference
)
410 newSet
= OSArray::withCapacity( 1 );
414 return( super::init( port
, type
, reference
, 0) );
417 void IOServiceUserNotification::free( void )
420 lastEntry
->release();
428 bool IOServiceUserNotification::_handler( void * target
,
429 void * ref
, IOService
* newService
)
431 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
434 bool IOServiceUserNotification::handler( void * /* ref */,
435 IOService
* newService
)
439 IOMachPort
* machPort
;
440 bool sendPing
= false;
444 count
= newSet
->getCount();
445 if( count
< kMaxOutstanding
) {
447 newSet
->setObject( newService
);
448 if( (sendPing
= (armed
&& (0 == count
))))
455 if( (0 == pingMsg
->msgHdr
.msgh_local_port
)
456 && (machPort
= IOMachPort::portForObject( this, IKOT_IOKIT_OBJECT
) ))
457 pingMsg
->msgHdr
.msgh_local_port
= machPort
->port
;
459 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
460 pingMsg
->msgHdr
.msgh_size
);
461 if( KERN_SUCCESS
!= kr
)
462 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
468 OSObject
* IOServiceUserNotification::getNextObject()
476 lastEntry
->release();
478 count
= newSet
->getCount();
480 result
= newSet
->getObject( count
- 1 );
482 newSet
->removeObject( count
- 1);
494 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
496 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
498 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
500 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
501 OSAsyncReference reference
, vm_size_t extraSize
)
503 return( super::init( port
, type
, reference
,
504 sizeof(IOServiceInterestContent
) + extraSize
) );
507 void IOServiceMessageUserNotification::free( void )
512 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
513 UInt32 messageType
, IOService
* provider
,
514 void * argument
, vm_size_t argSize
)
516 return( ((IOServiceMessageUserNotification
*) target
)->handler(
517 ref
, messageType
, provider
, argument
, argSize
));
520 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
521 UInt32 messageType
, IOService
* provider
,
522 void * messageArgument
, vm_size_t argSize
)
525 IOMachPort
* machPort
;
526 IOServiceInterestContent
* data
= (IOServiceInterestContent
*)
527 pingMsg
->notifyHeader
.content
;
529 data
->messageType
= messageType
;
531 argSize
= sizeof( messageArgument
);
532 data
->messageArgument
[0] = messageArgument
;
534 if( argSize
> kIOUserNotifyMaxMessageSize
)
535 argSize
= kIOUserNotifyMaxMessageSize
;
536 bcopy( messageArgument
, data
->messageArgument
, argSize
);
538 pingMsg
->msgHdr
.msgh_size
= sizeof( PingMsg
)
539 + sizeof( IOServiceInterestContent
)
540 - sizeof( data
->messageArgument
)
543 if( (machPort
= IOMachPort::portForObject( provider
, IKOT_IOKIT_OBJECT
) ))
544 pingMsg
->msgHdr
.msgh_local_port
= machPort
->port
;
546 pingMsg
->msgHdr
.msgh_local_port
= MACH_PORT_NULL
;
548 kr
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
,
549 pingMsg
->msgHdr
.msgh_size
);
550 if( KERN_SUCCESS
!= kr
)
551 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
553 return( kIOReturnSuccess
);
556 OSObject
* IOServiceMessageUserNotification::getNextObject()
561 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
564 #define super IOService
565 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
567 void IOUserClient::initialize( void )
569 gIOObjectPortLock
= IOLockAlloc();
571 assert( gIOObjectPortLock
);
574 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
575 mach_port_t wakePort
,
576 void *callback
, void *refcon
)
578 asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
;
579 asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
;
580 asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
;
583 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
584 const char * privilegeName
)
587 security_token_t token
;
588 mach_msg_type_number_t count
;
590 if( 0 != strcmp( privilegeName
, kIOClientPrivilegeAdministrator
))
591 return( kIOReturnUnsupported
);
593 count
= TASK_SECURITY_TOKEN_COUNT
;
594 kr
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
,
595 (task_info_t
) &token
, &count
);
596 if( (kr
== kIOReturnSuccess
)
597 && (0 != token
.val
[0]))
598 kr
= kIOReturnNotPrivileged
;
603 bool IOUserClient::initWithTask(task_t owningTask
,
607 if( getPropertyTable())
610 return super::init();
613 bool IOUserClient::initWithTask(task_t owningTask
,
616 OSDictionary
* properties
)
620 ok
= super::init( properties
);
621 ok
&= initWithTask( owningTask
, securityID
, type
);
626 void IOUserClient::free()
634 IOReturn
IOUserClient::clientDied( void )
636 return( clientClose());
639 IOReturn
IOUserClient::clientClose( void )
641 return( kIOReturnUnsupported
);
644 IOService
* IOUserClient::getService( void )
649 IOReturn
IOUserClient::registerNotificationPort(
650 mach_port_t
/* port */,
654 return( kIOReturnUnsupported
);
657 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
658 semaphore_t
* semaphore
)
660 return( kIOReturnUnsupported
);
663 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
665 return( kIOReturnUnsupported
);
668 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
669 IOOptionBits
* options
,
670 IOMemoryDescriptor
** memory
)
672 return( kIOReturnUnsupported
);
675 IOMemoryMap
* IOUserClient::mapClientMemory(
678 IOOptionBits mapFlags
= kIOMapAnywhere
,
679 IOVirtualAddress atAddress
= 0 )
682 IOOptionBits options
= 0;
683 IOMemoryDescriptor
* memory
;
684 IOMemoryMap
* map
= 0;
686 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
688 if( memory
&& (kIOReturnSuccess
== err
)) {
690 options
= (options
& ~kIOMapUserOptionsMask
)
691 | (mapFlags
& kIOMapUserOptionsMask
);
692 map
= memory
->map( task
, atAddress
, options
);
699 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
700 OSObject
*obj
, io_object_t
*clientObj
)
702 mach_port_name_t name
;
704 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
707 *(mach_port_name_t
*)clientObj
= name
;
708 return kIOReturnSuccess
;
711 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
716 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
721 IOExternalMethod
* IOUserClient::
722 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
724 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
727 *targetP
= (IOService
*) method
->object
;
732 IOExternalAsyncMethod
* IOUserClient::
733 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
735 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
738 *targetP
= (IOService
*) method
->object
;
743 IOExternalTrap
* IOUserClient::
744 getExternalTrapForIndex(UInt32 index
)
749 IOExternalTrap
* IOUserClient::
750 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
752 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
755 *targetP
= trap
->object
;
761 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
762 IOReturn result
, void *args
[], UInt32 numArgs
)
765 mach_msg_header_t msgHdr
;
766 OSNotificationHeader notifyHdr
;
767 IOAsyncCompletionContent asyncContent
;
768 void * args
[kMaxAsyncArgs
];
771 mach_port_t replyPort
;
774 // If no reply port, do nothing.
775 replyPort
= (mach_port_t
) reference
[0];
776 if(replyPort
== MACH_PORT_NULL
)
777 return kIOReturnSuccess
;
779 if(numArgs
> kMaxAsyncArgs
)
780 return kIOReturnMessageTooLarge
;
781 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
,0);
782 replyMsg
.msgHdr
.msgh_size
=
783 sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *);
784 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
785 replyMsg
.msgHdr
.msgh_local_port
= 0;
786 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
788 replyMsg
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
789 + numArgs
*sizeof(void *);
790 replyMsg
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
791 bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
));
793 replyMsg
.asyncContent
.result
= result
;
795 bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
);
796 kr
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
,
797 replyMsg
.msgHdr
.msgh_size
);
798 if( KERN_SUCCESS
!= kr
)
799 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr
);
803 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
805 #include <IOKit/pci/IOPCIDevice.h>
807 static void makeMatchingCompatible( OSDictionary
* dict
)
815 static const char * gratuitousNameChanges
[] = {
816 "IOImports", kIOProviderClassKey
,
817 "IOClass Names", kIOClassKey
,
818 "IOProbe Score", kIOProbeScoreKey
,
819 "IOKit Debug", kIOKitDebugKey
,
820 "IONeededResources", kIOResourceMatchKey
,
821 "IOName Match", kIONameMatchKey
,
822 "IOPCI Match", kIOPCIMatchKey
,
823 "IOPCI Primary Match", kIOPCIPrimaryMatchKey
,
824 "IOPCI Secondary Match",kIOPCISecondaryMatchKey
,
825 "IOPCI Class Match", kIOPCIClassMatchKey
,
829 while( (key
= gratuitousNameChanges
[i
++])) {
830 newKey
= gratuitousNameChanges
[i
++];
831 if( (value
= dict
->getObject( key
))
832 && (0 == dict
->getObject( newKey
))) {
834 dict
->setObject( newKey
, value
);
835 dict
->removeObject( key
);
837 if( (str
= OSDynamicCast(OSString
, dict
->getObject("CFBundleIdentifier"))))
838 IOLog("kext \"%s\" ", str
->getCStringNoCopy());
839 IOLog("must change \"%s\" to \"%s\"\n", key
, newKey
);
844 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
848 #define CHECK(cls,obj,out) \
850 if( !(out = OSDynamicCast( cls, obj))) \
851 return( kIOReturnBadArgument )
853 /* Routine io_object_get_class */
854 kern_return_t
is_io_object_get_class(
856 io_name_t className
)
859 return( kIOReturnBadArgument
);
861 strcpy( className
, object
->getMetaClass()->getClassName());
862 return( kIOReturnSuccess
);
865 /* Routine io_object_conforms_to */
866 kern_return_t
is_io_object_conforms_to(
869 boolean_t
*conforms
)
872 return( kIOReturnBadArgument
);
874 *conforms
= (0 != object
->metaCast( className
));
875 return( kIOReturnSuccess
);
878 /* Routine io_object_get_retain_count */
879 kern_return_t
is_io_object_get_retain_count(
884 return( kIOReturnBadArgument
);
886 *retainCount
= object
->getRetainCount();
887 return( kIOReturnSuccess
);
890 /* Routine io_iterator_next */
891 kern_return_t
is_io_iterator_next(
892 io_object_t iterator
,
893 io_object_t
*object
)
897 CHECK( OSIterator
, iterator
, iter
);
899 obj
= iter
->getNextObject();
903 return( kIOReturnSuccess
);
905 return( kIOReturnNoDevice
);
908 /* Routine io_iterator_reset */
909 kern_return_t
is_io_iterator_reset(
910 io_object_t iterator
)
912 CHECK( OSIterator
, iterator
, iter
);
916 return( kIOReturnSuccess
);
919 /* Routine io_iterator_is_valid */
920 kern_return_t
is_io_iterator_is_valid(
921 io_object_t iterator
,
922 boolean_t
*is_valid
)
924 CHECK( OSIterator
, iterator
, iter
);
926 *is_valid
= iter
->isValid();
928 return( kIOReturnSuccess
);
931 /* Routine io_service_match_property_table */
932 kern_return_t
is_io_service_match_property_table(
933 io_service_t _service
,
934 io_string_t matching
,
937 CHECK( IOService
, _service
, service
);
943 obj
= OSUnserializeXML( matching
);
945 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
946 *matches
= service
->passiveMatch( dict
);
947 kr
= kIOReturnSuccess
;
949 kr
= kIOReturnBadArgument
;
957 /* Routine io_service_get_matching_services */
958 kern_return_t
is_io_service_get_matching_services(
959 mach_port_t master_port
,
960 io_string_t matching
,
961 io_iterator_t
*existing
)
967 if( master_port
!= master_device_port
)
968 return( kIOReturnNotPrivileged
);
970 obj
= OSUnserializeXML( matching
);
972 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
973 makeMatchingCompatible( dict
); // temp for binary compatibility
974 *existing
= IOService::getMatchingServices( dict
);
975 kr
= kIOReturnSuccess
;
977 kr
= kIOReturnBadArgument
;
985 /* Routine io_service_add_notification */
986 kern_return_t
is_io_service_add_notification(
987 mach_port_t master_port
,
988 io_name_t notification_type
,
989 io_string_t matching
,
991 io_async_ref_t reference
,
992 mach_msg_type_number_t referenceCnt
,
993 io_object_t
* notification
)
996 IOServiceUserNotification
* userNotify
= 0;
997 IONotifier
* notify
= 0;
998 const OSSymbol
* sym
;
1001 unsigned long int userMsgType
;
1004 if( master_port
!= master_device_port
)
1005 return( kIOReturnNotPrivileged
);
1008 err
= kIOReturnNoResources
;
1010 if( !(sym
= OSSymbol::withCString( notification_type
)))
1011 err
= kIOReturnNoResources
;
1013 if( !(dict
= OSDynamicCast( OSDictionary
,
1014 OSUnserializeXML( matching
)))) {
1015 err
= kIOReturnBadArgument
;
1018 makeMatchingCompatible( dict
); // temp for binary compatibility
1020 if( (sym
== gIOPublishNotification
)
1021 || (sym
== gIOFirstPublishNotification
))
1022 userMsgType
= kIOServicePublishNotificationType
;
1023 else if( (sym
== gIOMatchedNotification
)
1024 || (sym
== gIOFirstMatchNotification
))
1025 userMsgType
= kIOServiceMatchedNotificationType
;
1026 else if( sym
== gIOTerminatedNotification
)
1027 userMsgType
= kIOServiceTerminatedNotificationType
;
1029 userMsgType
= kLastIOKitNotificationType
;
1031 userNotify
= new IOServiceUserNotification
;
1033 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
1035 userNotify
->release();
1041 notify
= IOService::addNotification( sym
, dict
,
1042 &userNotify
->_handler
, userNotify
);
1045 *notification
= userNotify
;
1046 userNotify
->setNotification( notify
);
1047 err
= kIOReturnSuccess
;
1049 err
= kIOReturnUnsupported
;
1061 /* Routine io_service_add_notification_old */
1062 kern_return_t
is_io_service_add_notification_old(
1063 mach_port_t master_port
,
1064 io_name_t notification_type
,
1065 io_string_t matching
,
1068 io_object_t
* notification
)
1070 return( is_io_service_add_notification( master_port
, notification_type
,
1071 matching
, port
, &ref
, 1, notification
));
1074 /* Routine io_service_add_message_notification */
1075 kern_return_t
is_io_service_add_interest_notification(
1076 io_object_t _service
,
1077 io_name_t type_of_interest
,
1079 io_async_ref_t reference
,
1080 mach_msg_type_number_t referenceCnt
,
1081 io_object_t
* notification
)
1084 IOServiceMessageUserNotification
* userNotify
= 0;
1085 IONotifier
* notify
= 0;
1086 const OSSymbol
* sym
;
1089 CHECK( IOService
, _service
, service
);
1091 err
= kIOReturnNoResources
;
1092 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
1094 userNotify
= new IOServiceMessageUserNotification
;
1096 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
1097 reference
, kIOUserNotifyMaxMessageSize
)) {
1098 userNotify
->release();
1104 notify
= service
->registerInterest( sym
,
1105 &userNotify
->_handler
, userNotify
);
1107 *notification
= userNotify
;
1108 userNotify
->setNotification( notify
);
1109 err
= kIOReturnSuccess
;
1111 err
= kIOReturnUnsupported
;
1118 /* Routine io_service_acknowledge_notification */
1119 kern_return_t
is_io_service_acknowledge_notification(
1120 io_object_t _service
,
1121 natural_t notify_ref
,
1122 natural_t response
)
1124 CHECK( IOService
, _service
, service
);
1126 return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
,
1127 (IOOptionBits
) response
));
1131 /* Routine io_connect_get_semaphore */
1132 kern_return_t
is_io_connect_get_notification_semaphore(
1133 io_connect_t connection
,
1134 natural_t notification_type
,
1135 semaphore_t
*semaphore
)
1137 CHECK( IOUserClient
, connection
, client
);
1139 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
1143 /* Routine io_registry_get_root_entry */
1144 kern_return_t
is_io_registry_get_root_entry(
1145 mach_port_t master_port
,
1148 IORegistryEntry
* entry
;
1150 if( master_port
!= master_device_port
)
1151 return( kIOReturnNotPrivileged
);
1153 entry
= IORegistryEntry::getRegistryRoot();
1158 return( kIOReturnSuccess
);
1161 /* Routine io_registry_create_iterator */
1162 kern_return_t
is_io_registry_create_iterator(
1163 mach_port_t master_port
,
1166 io_object_t
*iterator
)
1168 if( master_port
!= master_device_port
)
1169 return( kIOReturnNotPrivileged
);
1171 *iterator
= IORegistryIterator::iterateOver(
1172 IORegistryEntry::getPlane( plane
), options
);
1174 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1177 /* Routine io_registry_entry_create_iterator */
1178 kern_return_t
is_io_registry_entry_create_iterator(
1179 io_object_t registry_entry
,
1182 io_object_t
*iterator
)
1184 CHECK( IORegistryEntry
, registry_entry
, entry
);
1186 *iterator
= IORegistryIterator::iterateOver( entry
,
1187 IORegistryEntry::getPlane( plane
), options
);
1189 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
1192 /* Routine io_registry_iterator_enter */
1193 kern_return_t
is_io_registry_iterator_enter_entry(
1194 io_object_t iterator
)
1196 CHECK( IORegistryIterator
, iterator
, iter
);
1200 return( kIOReturnSuccess
);
1203 /* Routine io_registry_iterator_exit */
1204 kern_return_t
is_io_registry_iterator_exit_entry(
1205 io_object_t iterator
)
1209 CHECK( IORegistryIterator
, iterator
, iter
);
1211 didIt
= iter
->exitEntry();
1213 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
1216 /* Routine io_registry_entry_from_path */
1217 kern_return_t
is_io_registry_entry_from_path(
1218 mach_port_t master_port
,
1220 io_object_t
*registry_entry
)
1222 IORegistryEntry
* entry
;
1224 if( master_port
!= master_device_port
)
1225 return( kIOReturnNotPrivileged
);
1227 entry
= IORegistryEntry::fromPath( path
);
1229 *registry_entry
= entry
;
1231 return( kIOReturnSuccess
);
1234 /* Routine io_registry_entry_in_plane */
1235 kern_return_t
is_io_registry_entry_in_plane(
1236 io_object_t registry_entry
,
1238 boolean_t
*inPlane
)
1240 CHECK( IORegistryEntry
, registry_entry
, entry
);
1242 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
1244 return( kIOReturnSuccess
);
1248 /* Routine io_registry_entry_get_path */
1249 kern_return_t
is_io_registry_entry_get_path(
1250 io_object_t registry_entry
,
1255 CHECK( IORegistryEntry
, registry_entry
, entry
);
1257 length
= sizeof( io_string_t
);
1258 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
1259 return( kIOReturnSuccess
);
1261 return( kIOReturnBadArgument
);
1265 /* Routine io_registry_entry_get_name */
1266 kern_return_t
is_io_registry_entry_get_name(
1267 io_object_t registry_entry
,
1270 CHECK( IORegistryEntry
, registry_entry
, entry
);
1272 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
1274 return( kIOReturnSuccess
);
1277 /* Routine io_registry_entry_get_name_in_plane */
1278 kern_return_t
is_io_registry_entry_get_name_in_plane(
1279 io_object_t registry_entry
,
1283 CHECK( IORegistryEntry
, registry_entry
, entry
);
1285 strncpy( name
, entry
->getName( IORegistryEntry::getPlane( plane
)),
1286 sizeof( io_name_t
));
1288 return( kIOReturnSuccess
);
1291 // Create a vm_map_copy_t or kalloc'ed data for memory
1292 // to be copied out. ipc will free after the copyout.
1294 static kern_return_t
copyoutkdata( void * data
, vm_size_t len
,
1295 io_buf_ptr_t
* buf
)
1300 err
= vm_map_copyin( kernel_map
, (vm_offset_t
) data
, len
,
1301 false /* src_destroy */, ©
);
1303 assert( err
== KERN_SUCCESS
);
1304 if( err
== KERN_SUCCESS
)
1305 *buf
= (char *) copy
;
1310 /* Routine io_registry_entry_get_properties */
1311 kern_return_t
is_io_registry_entry_get_properties(
1312 io_object_t registry_entry
,
1313 io_buf_ptr_t
*properties
,
1314 mach_msg_type_number_t
*propertiesCnt
)
1319 CHECK( IORegistryEntry
, registry_entry
, entry
);
1321 OSSerialize
* s
= OSSerialize::withCapacity(4096);
1324 return( kIOReturnNoMemory
);
1328 if( entry
->serializeProperties( s
)) {
1329 len
= s
->getLength();
1330 *propertiesCnt
= len
;
1331 err
= copyoutkdata( s
->text(), len
, properties
);
1334 err
= kIOReturnUnsupported
;
1341 /* Routine io_registry_entry_set_properties */
1342 kern_return_t is_io_registry_entry_set_properties
1344 io_object_t registry_entry
,
1345 io_buf_ptr_t properties
,
1346 mach_msg_type_number_t propertiesCnt
,
1354 CHECK( IORegistryEntry
, registry_entry
, entry
);
1356 err
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
) properties
);
1358 if( KERN_SUCCESS
== err
) {
1360 // must return success after vm_map_copyout() succeeds
1361 obj
= OSUnserializeXML( (const char *) data
);
1362 vm_deallocate( kernel_map
, data
, propertiesCnt
);
1365 res
= entry
->setProperties( obj
);
1368 res
= kIOReturnBadArgument
;
1377 /* Routine io_registry_entry_get_property */
1378 kern_return_t
is_io_registry_entry_get_property(
1379 io_object_t registry_entry
,
1380 io_name_t property_name
,
1381 io_scalar_inband_t buf
,
1382 mach_msg_type_number_t
*dataCnt
)
1390 unsigned int len
= 0;
1391 const void * bytes
= 0;
1392 IOReturn ret
= kIOReturnSuccess
;
1394 CHECK( IORegistryEntry
, registry_entry
, entry
);
1396 obj
= entry
->getProperty( property_name
);
1398 return( kIOReturnNoResources
);
1400 // One day OSData will be a common container base class
1402 if( (data
= OSDynamicCast( OSData
, obj
))) {
1403 len
= data
->getLength();
1404 bytes
= data
->getBytesNoCopy();
1406 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
1407 len
= str
->getLength() + 1;
1408 bytes
= str
->getCStringNoCopy();
1410 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
1411 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
1412 bytes
= boo
->isTrue() ? "Yes" : "No";
1414 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
1415 offsetBytes
= off
->unsigned64BitValue();
1416 len
= off
->numberOfBytes();
1417 bytes
= &offsetBytes
;
1419 bytes
= (const void *)
1420 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
1424 ret
= kIOReturnBadArgument
;
1428 ret
= kIOReturnIPCError
;
1431 bcopy( bytes
, buf
, len
);
1439 /* Routine io_registry_entry_get_child_iterator */
1440 kern_return_t
is_io_registry_entry_get_child_iterator(
1441 io_object_t registry_entry
,
1443 io_object_t
*iterator
)
1445 CHECK( IORegistryEntry
, registry_entry
, entry
);
1447 *iterator
= entry
->getChildIterator(
1448 IORegistryEntry::getPlane( plane
));
1450 return( kIOReturnSuccess
);
1453 /* Routine io_registry_entry_get_parent_iterator */
1454 kern_return_t
is_io_registry_entry_get_parent_iterator(
1455 io_object_t registry_entry
,
1457 io_object_t
*iterator
)
1459 CHECK( IORegistryEntry
, registry_entry
, entry
);
1461 *iterator
= entry
->getParentIterator(
1462 IORegistryEntry::getPlane( plane
));
1464 return( kIOReturnSuccess
);
1467 /* Routine io_service_get_busy_state */
1468 kern_return_t
is_io_service_get_busy_state(
1469 io_object_t _service
,
1472 CHECK( IOService
, _service
, service
);
1474 *busyState
= service
->getBusyState();
1476 return( kIOReturnSuccess
);
1479 /* Routine io_service_wait_quiet */
1480 kern_return_t
is_io_service_wait_quiet(
1481 io_object_t _service
,
1482 mach_timespec_t wait_time
)
1484 CHECK( IOService
, _service
, service
);
1486 return( service
->waitQuiet( &wait_time
));
1489 /* Routine io_service_request_probe */
1490 kern_return_t
is_io_service_request_probe(
1491 io_object_t _service
,
1494 CHECK( IOService
, _service
, service
);
1496 return( service
->requestProbe( options
));
1500 /* Routine io_service_open */
1501 kern_return_t
is_io_service_open(
1502 io_object_t _service
,
1505 io_object_t
*connection
)
1507 IOUserClient
* client
;
1510 CHECK( IOService
, _service
, service
);
1512 err
= service
->newUserClient( owningTask
, (void *) owningTask
,
1513 connect_type
, &client
);
1515 if( err
== kIOReturnSuccess
) {
1516 assert( OSDynamicCast(IOUserClient
, client
) );
1517 *connection
= client
;
1523 /* Routine io_service_close */
1524 kern_return_t
is_io_service_close(
1525 io_object_t connection
)
1527 CHECK( IOUserClient
, connection
, client
);
1529 client
->clientClose();
1531 return( kIOReturnSuccess
);
1534 /* Routine io_connect_get_service */
1535 kern_return_t
is_io_connect_get_service(
1536 io_object_t connection
,
1537 io_object_t
*service
)
1539 IOService
* theService
;
1541 CHECK( IOUserClient
, connection
, client
);
1543 theService
= client
->getService();
1545 theService
->retain();
1547 *service
= theService
;
1549 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
1552 /* Routine io_connect_set_notification_port */
1553 kern_return_t
is_io_connect_set_notification_port(
1554 io_object_t connection
,
1555 int notification_type
,
1559 CHECK( IOUserClient
, connection
, client
);
1561 return( client
->registerNotificationPort( port
, notification_type
,
1565 kern_return_t
is_io_connect_map_memory(
1566 io_object_t connect
,
1569 vm_address_t
* mapAddr
,
1570 vm_size_t
* mapSize
,
1576 CHECK( IOUserClient
, connect
, client
);
1578 map
= client
->mapClientMemory( type
, task
, flags
, *mapAddr
);
1581 *mapAddr
= map
->getVirtualAddress();
1583 *mapSize
= map
->getLength();
1585 if( task
!= current_task()) {
1586 // push a name out to the task owning the map,
1587 // so we can clean up maps
1588 mach_port_name_t name
= IOMachPort::makeSendRightForTask(
1589 task
, map
, IKOT_IOKIT_OBJECT
);
1593 // keep it with the user client
1594 IOLockLock( gIOObjectPortLock
);
1595 if( 0 == client
->mappings
)
1596 client
->mappings
= OSSet::withCapacity(2);
1597 if( client
->mappings
)
1598 client
->mappings
->setObject( map
);
1599 IOLockUnlock( gIOObjectPortLock
);
1602 err
= kIOReturnSuccess
;
1605 err
= kIOReturnBadArgument
;
1610 kern_return_t
is_io_connect_unmap_memory(
1611 io_object_t connect
,
1614 vm_address_t mapAddr
)
1617 IOOptionBits options
= 0;
1618 IOMemoryDescriptor
* memory
;
1621 CHECK( IOUserClient
, connect
, client
);
1623 err
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1625 if( memory
&& (kIOReturnSuccess
== err
)) {
1627 options
= (options
& ~kIOMapUserOptionsMask
)
1628 | kIOMapAnywhere
| kIOMapReference
;
1630 map
= memory
->map( task
, mapAddr
, options
);
1633 IOLockLock( gIOObjectPortLock
);
1634 if( client
->mappings
)
1635 client
->mappings
->removeObject( map
);
1636 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
1637 IOLockUnlock( gIOObjectPortLock
);
1640 err
= kIOReturnBadArgument
;
1647 /* Routine io_connect_add_client */
1648 kern_return_t
is_io_connect_add_client(
1649 io_object_t connection
,
1650 io_object_t connect_to
)
1652 CHECK( IOUserClient
, connection
, client
);
1653 CHECK( IOUserClient
, connect_to
, to
);
1655 return( client
->connectClient( to
) );
1659 /* Routine io_connect_set_properties */
1660 kern_return_t
is_io_connect_set_properties(
1661 io_object_t connection
,
1662 io_buf_ptr_t properties
,
1663 mach_msg_type_number_t propertiesCnt
,
1666 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
1670 /* Routine io_connect_method_scalarI_scalarO */
1671 kern_return_t
is_io_connect_method_scalarI_scalarO(
1672 io_object_t connect
,
1675 IOByteCount inputCount
,
1677 IOByteCount
* outputCount
)
1680 IOExternalMethod
* method
;
1684 CHECK( IOUserClient
, connect
, client
);
1685 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
))) {
1687 err
= kIOReturnBadArgument
;
1688 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
1690 if( inputCount
!= method
->count0
)
1692 if( *outputCount
!= method
->count1
)
1695 func
= method
->func
;
1697 switch( inputCount
) {
1700 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1701 input
[3], input
[4], input
[5] );
1704 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1709 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1711 &output
[0], &output
[1] );
1714 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1715 &output
[0], &output
[1], &output
[2] );
1718 err
= (object
->*func
)( input
[0], input
[1],
1719 &output
[0], &output
[1], &output
[2],
1723 err
= (object
->*func
)( input
[0],
1724 &output
[0], &output
[1], &output
[2],
1725 &output
[3], &output
[4] );
1728 err
= (object
->*func
)( &output
[0], &output
[1], &output
[2],
1729 &output
[3], &output
[4], &output
[5] );
1733 IOLog("%s: Bad method table\n", client
->getName());
1738 err
= kIOReturnUnsupported
;
1743 /* Routine io_connect_method_scalarI_structureO */
1744 kern_return_t
is_io_connect_method_scalarI_structureO(
1745 io_object_t connect
,
1748 IOByteCount inputCount
,
1750 IOByteCount
* outputCount
)
1753 IOExternalMethod
* method
;
1757 CHECK( IOUserClient
, connect
, client
);
1759 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1761 err
= kIOReturnBadArgument
;
1762 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
1764 if( inputCount
!= method
->count0
)
1766 if( (0xffffffff != method
->count1
)
1767 && (*outputCount
!= method
->count1
))
1770 func
= method
->func
;
1772 switch( inputCount
) {
1775 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1780 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1782 output
, (void *)outputCount
);
1785 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1786 output
, (void *)outputCount
, 0 );
1789 err
= (object
->*func
)( input
[0], input
[1],
1790 output
, (void *)outputCount
, 0, 0 );
1793 err
= (object
->*func
)( input
[0],
1794 output
, (void *)outputCount
, 0, 0, 0 );
1797 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
1801 IOLog("%s: Bad method table\n", client
->getName());
1806 err
= kIOReturnUnsupported
;
1811 /* Routine io_connect_method_scalarI_structureI */
1812 kern_return_t
is_io_connect_method_scalarI_structureI(
1813 io_connect_t connect
,
1816 IOByteCount inputCount
,
1817 UInt8
* inputStruct
,
1818 IOByteCount inputStructCount
)
1821 IOExternalMethod
* method
;
1825 CHECK( IOUserClient
, connect
, client
);
1827 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1829 err
= kIOReturnBadArgument
;
1830 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
1832 if( (0xffffffff != method
->count0
)
1833 && (inputCount
!= method
->count0
))
1835 if( (0xffffffff != method
->count1
)
1836 && (inputStructCount
!= method
->count1
))
1839 func
= method
->func
;
1841 switch( inputCount
) {
1844 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1849 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1851 inputStruct
, (void *)inputStructCount
);
1854 err
= (object
->*func
)( input
[0], input
[1], input
[2],
1855 inputStruct
, (void *)inputStructCount
,
1859 err
= (object
->*func
)( input
[0], input
[1],
1860 inputStruct
, (void *)inputStructCount
,
1864 err
= (object
->*func
)( input
[0],
1865 inputStruct
, (void *)inputStructCount
,
1869 err
= (object
->*func
)( inputStruct
, (void *)inputStructCount
,
1874 IOLog("%s: Bad method table\n", client
->getName());
1879 err
= kIOReturnUnsupported
;
1884 /* Routine io_connect_method_structureI_structureO */
1885 kern_return_t
is_io_connect_method_structureI_structureO(
1886 io_object_t connect
,
1889 IOByteCount inputCount
,
1891 IOByteCount
* outputCount
)
1894 IOExternalMethod
* method
;
1898 CHECK( IOUserClient
, connect
, client
);
1900 if( (method
= client
->getTargetAndMethodForIndex(&object
, index
)) ) {
1902 err
= kIOReturnBadArgument
;
1903 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
1905 if( (0xffffffff != method
->count0
)
1906 && (inputCount
!= method
->count0
))
1908 if( (0xffffffff != method
->count1
)
1909 && (*outputCount
!= method
->count1
))
1912 func
= method
->func
;
1914 if( method
->count1
) {
1915 if( method
->count0
) {
1916 err
= (object
->*func
)( input
, output
,
1917 (void *)inputCount
, outputCount
, 0, 0 );
1919 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
1922 err
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 );
1928 err
= kIOReturnUnsupported
;
1933 kern_return_t
is_io_async_method_scalarI_scalarO(
1934 io_object_t connect
,
1935 mach_port_t wakePort
,
1936 io_async_ref_t reference
,
1937 mach_msg_type_number_t referenceCnt
,
1940 IOByteCount inputCount
,
1942 IOByteCount
* outputCount
)
1945 IOExternalAsyncMethod
*method
;
1949 CHECK( IOUserClient
, connect
, client
);
1950 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
1952 err
= kIOReturnBadArgument
;
1953 if( kIOUCScalarIScalarO
!= (method
->flags
& kIOUCTypeMask
))
1955 if( inputCount
!= method
->count0
)
1957 if( *outputCount
!= method
->count1
)
1960 reference
[0] = (natural_t
) wakePort
;
1961 func
= method
->func
;
1963 switch( inputCount
) {
1966 err
= (object
->*func
)( reference
,
1967 input
[0], input
[1], input
[2],
1968 input
[3], input
[4], input
[5] );
1971 err
= (object
->*func
)( reference
,
1972 input
[0], input
[1], input
[2],
1977 err
= (object
->*func
)( reference
,
1978 input
[0], input
[1], input
[2],
1980 &output
[0], &output
[1] );
1983 err
= (object
->*func
)( reference
,
1984 input
[0], input
[1], input
[2],
1985 &output
[0], &output
[1], &output
[2] );
1988 err
= (object
->*func
)( reference
,
1990 &output
[0], &output
[1], &output
[2],
1994 err
= (object
->*func
)( reference
,
1996 &output
[0], &output
[1], &output
[2],
1997 &output
[3], &output
[4] );
2000 err
= (object
->*func
)( reference
,
2001 &output
[0], &output
[1], &output
[2],
2002 &output
[3], &output
[4], &output
[5] );
2006 IOLog("%s: Bad method table\n", client
->getName());
2011 err
= kIOReturnUnsupported
;
2016 kern_return_t
is_io_async_method_scalarI_structureO(
2017 io_object_t connect
,
2018 mach_port_t wakePort
,
2019 io_async_ref_t reference
,
2020 mach_msg_type_number_t referenceCnt
,
2023 IOByteCount inputCount
,
2025 IOByteCount
* outputCount
)
2028 IOExternalAsyncMethod
*method
;
2032 CHECK( IOUserClient
, connect
, client
);
2034 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2036 err
= kIOReturnBadArgument
;
2037 if( kIOUCScalarIStructO
!= (method
->flags
& kIOUCTypeMask
))
2039 if( inputCount
!= method
->count0
)
2041 if( (0xffffffff != method
->count1
)
2042 && (*outputCount
!= method
->count1
))
2045 reference
[0] = (natural_t
) wakePort
;
2046 func
= method
->func
;
2048 switch( inputCount
) {
2051 err
= (object
->*func
)( reference
,
2052 input
[0], input
[1], input
[2],
2057 err
= (object
->*func
)( reference
,
2058 input
[0], input
[1], input
[2],
2060 output
, (void *)outputCount
);
2063 err
= (object
->*func
)( reference
,
2064 input
[0], input
[1], input
[2],
2065 output
, (void *)outputCount
, 0 );
2068 err
= (object
->*func
)( reference
,
2070 output
, (void *)outputCount
, 0, 0 );
2073 err
= (object
->*func
)( reference
,
2075 output
, (void *)outputCount
, 0, 0, 0 );
2078 err
= (object
->*func
)( reference
,
2079 output
, (void *)outputCount
, 0, 0, 0, 0 );
2083 IOLog("%s: Bad method table\n", client
->getName());
2088 err
= kIOReturnUnsupported
;
2093 kern_return_t
is_io_async_method_scalarI_structureI(
2094 io_connect_t connect
,
2095 mach_port_t wakePort
,
2096 io_async_ref_t reference
,
2097 mach_msg_type_number_t referenceCnt
,
2100 IOByteCount inputCount
,
2101 UInt8
* inputStruct
,
2102 IOByteCount inputStructCount
)
2105 IOExternalAsyncMethod
*method
;
2109 CHECK( IOUserClient
, connect
, client
);
2111 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2113 err
= kIOReturnBadArgument
;
2114 if( kIOUCScalarIStructI
!= (method
->flags
& kIOUCTypeMask
))
2116 if( (0xffffffff != method
->count0
)
2117 && (inputCount
!= method
->count0
))
2119 if( (0xffffffff != method
->count1
)
2120 && (inputStructCount
!= method
->count1
))
2123 reference
[0] = (natural_t
) wakePort
;
2124 func
= method
->func
;
2126 switch( inputCount
) {
2129 err
= (object
->*func
)( reference
,
2130 input
[0], input
[1], input
[2],
2135 err
= (object
->*func
)( reference
,
2136 input
[0], input
[1], input
[2],
2138 inputStruct
, (void *)inputStructCount
);
2141 err
= (object
->*func
)( reference
,
2142 input
[0], input
[1], input
[2],
2143 inputStruct
, (void *)inputStructCount
,
2147 err
= (object
->*func
)( reference
,
2149 inputStruct
, (void *)inputStructCount
,
2153 err
= (object
->*func
)( reference
,
2155 inputStruct
, (void *)inputStructCount
,
2159 err
= (object
->*func
)( reference
,
2160 inputStruct
, (void *)inputStructCount
,
2165 IOLog("%s: Bad method table\n", client
->getName());
2170 err
= kIOReturnUnsupported
;
2175 kern_return_t
is_io_async_method_structureI_structureO(
2176 io_object_t connect
,
2177 mach_port_t wakePort
,
2178 io_async_ref_t reference
,
2179 mach_msg_type_number_t referenceCnt
,
2182 IOByteCount inputCount
,
2184 IOByteCount
* outputCount
)
2187 IOExternalAsyncMethod
*method
;
2191 CHECK( IOUserClient
, connect
, client
);
2193 if( (method
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) {
2195 err
= kIOReturnBadArgument
;
2196 if( kIOUCStructIStructO
!= (method
->flags
& kIOUCTypeMask
))
2198 if( (0xffffffff != method
->count0
)
2199 && (inputCount
!= method
->count0
))
2201 if( (0xffffffff != method
->count1
)
2202 && (*outputCount
!= method
->count1
))
2205 reference
[0] = (natural_t
) wakePort
;
2206 func
= method
->func
;
2208 if( method
->count1
) {
2209 if( method
->count0
) {
2210 err
= (object
->*func
)( reference
,
2212 (void *)inputCount
, outputCount
, 0, 0 );
2214 err
= (object
->*func
)( reference
,
2215 output
, outputCount
, 0, 0, 0, 0 );
2218 err
= (object
->*func
)( reference
,
2219 input
, (void *)inputCount
, 0, 0, 0, 0 );
2225 err
= kIOReturnUnsupported
;
2229 /* Routine io_make_matching */
2230 kern_return_t
is_io_make_matching(
2231 mach_port_t master_port
,
2233 IOOptionBits options
,
2235 IOByteCount inputCount
,
2236 io_string_t matching
)
2239 IOReturn err
= kIOReturnSuccess
;
2240 OSDictionary
* dict
;
2242 if( master_port
!= master_device_port
)
2243 return( kIOReturnNotPrivileged
);
2247 case kIOServiceMatching
:
2248 dict
= IOService::serviceMatching( gIOServiceKey
);
2251 case kIOBSDNameMatching
:
2252 dict
= IOBSDNameMatching( (const char *) input
);
2255 case kIOOFPathMatching
:
2256 dict
= IOOFPathMatching( (const char *) input
,
2257 matching
, sizeof( io_string_t
));
2265 return( kIOReturnUnsupported
);
2268 s
= OSSerialize::withCapacity(4096);
2270 err
= kIOReturnNoMemory
;
2274 if( !dict
->serialize( s
)) {
2275 err
= kIOReturnUnsupported
;
2279 if( s
->getLength() > sizeof( io_string_t
)) {
2280 err
= kIOReturnNoMemory
;
2283 strcpy( matching
, s
->text());
2295 /* Routine io_catalog_send_data */
2296 kern_return_t
is_io_catalog_send_data(
2297 mach_port_t master_port
,
2299 io_buf_ptr_t inData
,
2300 mach_msg_type_number_t inDataCount
,
2305 kern_return_t kr
= kIOReturnError
;
2307 //printf("io_catalog_send_data called. flag: %d\n", flag);
2309 if( master_port
!= master_device_port
)
2310 return kIOReturnNotPrivileged
;
2312 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2313 if(flag
!= kIOCatalogRemoveKernelLinker
&& ( !inData
|| !inDataCount
) )
2314 return kIOReturnBadArgument
;
2317 kr
= vm_map_copyout( kernel_map
, &data
, (vm_map_copy_t
)inData
);
2318 if( kr
!= KERN_SUCCESS
)
2321 // must return success after vm_map_copyout() succeeds
2324 obj
= (OSObject
*)OSUnserializeXML((const char *)data
);
2325 vm_deallocate( kernel_map
, data
, inDataCount
);
2327 *result
= kIOReturnNoMemory
;
2328 return( KERN_SUCCESS
);
2334 case kIOCatalogAddDrivers
:
2335 case kIOCatalogAddDriversNoMatch
: {
2338 array
= OSDynamicCast(OSArray
, obj
);
2341 OSDictionary
* dict
;
2343 while( (dict
= OSDynamicCast(OSDictionary
, array
->getObject(i
++))))
2344 makeMatchingCompatible( dict
);
2346 if ( !gIOCatalogue
->addDrivers( array
,
2347 flag
== kIOCatalogAddDrivers
) ) {
2348 kr
= kIOReturnError
;
2352 kr
= kIOReturnBadArgument
;
2357 case kIOCatalogRemoveDrivers
:
2358 case kIOCatalogRemoveDriversNoMatch
: {
2359 OSDictionary
* dict
;
2361 dict
= OSDynamicCast(OSDictionary
, obj
);
2363 makeMatchingCompatible( dict
);
2364 if ( !gIOCatalogue
->removeDrivers( dict
,
2365 flag
== kIOCatalogRemoveDrivers
) ) {
2366 kr
= kIOReturnError
;
2370 kr
= kIOReturnBadArgument
;
2375 case kIOCatalogStartMatching
: {
2376 OSDictionary
* dict
;
2378 dict
= OSDynamicCast(OSDictionary
, obj
);
2380 makeMatchingCompatible( dict
);
2381 if ( !gIOCatalogue
->startMatching( dict
) ) {
2382 kr
= kIOReturnError
;
2386 kr
= kIOReturnBadArgument
;
2391 case kIOCatalogRemoveKernelLinker
: {
2392 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) {
2393 kr
= kIOReturnError
;
2399 kr
= kIOReturnBadArgument
;
2403 if (obj
) obj
->release();
2406 return( KERN_SUCCESS
);
2409 /* Routine io_catalog_terminate */
2410 kern_return_t
is_io_catalog_terminate(
2411 mach_port_t master_port
,
2417 if( master_port
!= master_device_port
)
2418 return kIOReturnNotPrivileged
;
2420 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
2421 kIOClientPrivilegeAdministrator
);
2422 if( kIOReturnSuccess
!= kr
)
2426 case kIOCatalogServiceTerminate
:
2428 IOService
* service
;
2430 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
2431 kIORegistryIterateRecursively
);
2433 return kIOReturnNoMemory
;
2437 while( (service
= (IOService
*)iter
->getNextObject()) ) {
2438 if( service
->metaCast(name
)) {
2439 if ( !service
->terminate( kIOServiceRequired
2440 | kIOServiceSynchronous
) ) {
2441 kr
= kIOReturnUnsupported
;
2446 } while( !service
&& !iter
->isValid());
2450 case kIOCatalogModuleUnload
:
2451 case kIOCatalogModuleTerminate
:
2452 kr
= gIOCatalogue
->terminateDriversForModule(name
,
2453 flag
== kIOCatalogModuleUnload
);
2457 kr
= kIOReturnBadArgument
;
2464 /* Routine io_catalog_get_data */
2465 kern_return_t
is_io_catalog_get_data(
2466 mach_port_t master_port
,
2468 io_buf_ptr_t
*outData
,
2469 mach_msg_type_number_t
*outDataCount
)
2471 kern_return_t kr
= kIOReturnSuccess
;
2474 if( master_port
!= master_device_port
)
2475 return kIOReturnNotPrivileged
;
2477 //printf("io_catalog_get_data called. flag: %d\n", flag);
2479 s
= OSSerialize::withCapacity(4096);
2481 return kIOReturnNoMemory
;
2485 case kIOCatalogGetContents
:
2486 if ( !gIOCatalogue
->serialize(s
) ) {
2487 kr
= kIOReturnNoMemory
;
2492 kr
= kIOReturnBadArgument
;
2496 if ( kr
== kIOReturnSuccess
) {
2501 size
= s
->getLength();
2502 kr
= vm_allocate(kernel_map
, &data
, size
, true);
2503 if ( kr
== kIOReturnSuccess
) {
2504 bcopy(s
->text(), (void *)data
, size
);
2505 kr
= vm_map_copyin(kernel_map
, data
, size
, true, ©
);
2506 *outData
= (char *)copy
;
2507 *outDataCount
= size
;
2516 /* Routine io_catalog_get_gen_count */
2517 kern_return_t
is_io_catalog_get_gen_count(
2518 mach_port_t master_port
,
2521 if( master_port
!= master_device_port
)
2522 return kIOReturnNotPrivileged
;
2524 //printf("io_catalog_get_gen_count called.\n");
2527 return kIOReturnBadArgument
;
2529 *genCount
= gIOCatalogue
->getGenerationCount();
2531 return kIOReturnSuccess
;
2534 /* Routine io_catalog_module_loaded */
2535 kern_return_t
is_io_catalog_module_loaded(
2536 mach_port_t master_port
,
2539 if( master_port
!= master_device_port
)
2540 return kIOReturnNotPrivileged
;
2542 //printf("io_catalog_module_loaded called. name %s\n", name);
2545 return kIOReturnBadArgument
;
2547 gIOCatalogue
->moduleHasLoaded(name
);
2549 return kIOReturnSuccess
;
2552 kern_return_t
is_io_catalog_reset(
2553 mach_port_t master_port
,
2556 if( master_port
!= master_device_port
)
2557 return kIOReturnNotPrivileged
;
2560 case kIOCatalogResetDefault
:
2561 gIOCatalogue
->reset();
2565 return kIOReturnBadArgument
;
2568 return kIOReturnSuccess
;
2571 kern_return_t
iokit_user_client_trap(io_object_t userClientRef
, UInt32 index
, void *p1
, void *p2
, void *p3
, void *p4
, void *p5
, void *p6
)
2573 kern_return_t result
= kIOReturnBadArgument
;
2574 IOUserClient
*userClient
;
2576 if ((userClient
= OSDynamicCast(IOUserClient
, iokit_lookup_connect_ref_current_task(userClientRef
)))) {
2577 IOExternalTrap
*trap
;
2578 IOService
*target
= NULL
;
2580 trap
= userClient
->getTargetAndTrapForIndex(&target
, index
);
2582 if (trap
&& target
) {
2588 result
= (target
->*func
)(p1
, p2
, p3
, p4
, p5
, p6
);
2592 userClient
->release();
2600 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
2601 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
2602 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
2603 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
2604 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
2605 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
2606 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
2607 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
2608 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
2609 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
2610 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
2611 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
2612 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
2613 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
2614 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
2615 OSMetaClassDefineReservedUnused(IOUserClient
, 15);