2 * Copyright (c) 1998-2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <libkern/c++/OSKext.h>
31 #include <IOKit/IOKitServer.h>
32 #include <IOKit/IOKitKeysPrivate.h>
33 #include <IOKit/IOUserClient.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IORegistryEntry.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOMemoryDescriptor.h>
38 #include <IOKit/IOBufferMemoryDescriptor.h>
39 #include <IOKit/IOLib.h>
40 #include <IOKit/IOStatisticsPrivate.h>
41 #include <IOKit/IOTimeStamp.h>
42 #include <IOKit/system.h>
43 #include <libkern/OSDebug.h>
45 #include <sys/kauth.h>
46 #include <sys/codesign.h>
51 #include <security/mac_framework.h>
53 #include <sys/kauth.h>
57 #endif /* CONFIG_MACF */
59 #include <IOKit/assert.h>
61 #include "IOServicePrivate.h"
62 #include "IOKitKernelInternal.h"
64 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
65 #define SCALAR32(x) ((uint32_t )x)
66 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
67 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
68 #define REF32(x) ((int)(x))
72 kIOUCAsync0Flags
= 3ULL,
73 kIOUCAsync64Flag
= 1ULL
78 #define IOStatisticsRegisterCounter() \
80 reserved->counter = IOStatistics::registerUserClient(this); \
83 #define IOStatisticsUnregisterCounter() \
86 IOStatistics::unregisterUserClient(reserved->counter); \
89 #define IOStatisticsClientCall() \
91 IOStatistics::countUserClientCall(client); \
96 #define IOStatisticsRegisterCounter()
97 #define IOStatisticsUnregisterCounter()
98 #define IOStatisticsClientCall()
100 #endif /* IOKITSTATS */
102 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 // definitions we should get from osfmk
106 //typedef struct ipc_port * ipc_port_t;
107 typedef natural_t ipc_kobject_type_t
;
109 #define IKOT_IOKIT_SPARE 27
110 #define IKOT_IOKIT_CONNECT 29
111 #define IKOT_IOKIT_OBJECT 30
115 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
116 ipc_kobject_type_t type
);
118 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
120 extern mach_port_name_t
iokit_make_send_right( task_t task
,
121 io_object_t obj
, ipc_kobject_type_t type
);
123 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
125 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
127 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
129 extern ipc_port_t master_device_port
;
131 extern void iokit_retain_port( ipc_port_t port
);
132 extern void iokit_release_port( ipc_port_t port
);
133 extern void iokit_release_port_send( ipc_port_t port
);
135 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
137 #include <mach/mach_traps.h>
138 #include <vm/vm_map.h>
143 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
145 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
147 class IOMachPort
: public OSObject
149 OSDeclareDefaultStructors(IOMachPort
)
156 static IOMachPort
* portForObject( OSObject
* obj
,
157 ipc_kobject_type_t type
);
158 static bool noMoreSendersForObject( OSObject
* obj
,
159 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
160 static void releasePortForObject( OSObject
* obj
,
161 ipc_kobject_type_t type
);
162 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
164 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
166 static mach_port_name_t
makeSendRightForTask( task_t task
,
167 io_object_t obj
, ipc_kobject_type_t type
);
169 virtual void free() APPLE_KEXT_OVERRIDE
;
172 #define super OSObject
173 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
175 static IOLock
* gIOObjectPortLock
;
177 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
179 // not in dictForType() for debugging ease
180 static OSDictionary
* gIOObjectPorts
;
181 static OSDictionary
* gIOConnectPorts
;
183 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
185 OSDictionary
** dict
;
187 if( IKOT_IOKIT_OBJECT
== type
)
188 dict
= &gIOObjectPorts
;
189 else if( IKOT_IOKIT_CONNECT
== type
)
190 dict
= &gIOConnectPorts
;
195 *dict
= OSDictionary::withCapacity( 1 );
200 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
201 ipc_kobject_type_t type
)
203 IOMachPort
* inst
= 0;
206 IOTakeLock( gIOObjectPortLock
);
210 dict
= dictForType( type
);
214 if( (inst
= (IOMachPort
*)
215 dict
->getObject( (const OSSymbol
*) obj
))) {
221 inst
= new IOMachPort
;
222 if( inst
&& !inst
->init()) {
227 inst
->port
= iokit_alloc_object_port( obj
, type
);
230 dict
->setObject( (const OSSymbol
*) obj
, inst
);
240 IOUnlock( gIOObjectPortLock
);
245 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
246 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
249 IOMachPort
* machPort
;
250 bool destroyed
= true;
252 IOTakeLock( gIOObjectPortLock
);
254 if( (dict
= dictForType( type
))) {
257 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
259 destroyed
= (machPort
->mscount
<= *mscount
);
261 dict
->removeObject( (const OSSymbol
*) obj
);
263 *mscount
= machPort
->mscount
;
268 IOUnlock( gIOObjectPortLock
);
273 void IOMachPort::releasePortForObject( OSObject
* obj
,
274 ipc_kobject_type_t type
)
277 IOMachPort
* machPort
;
279 IOTakeLock( gIOObjectPortLock
);
281 if( (dict
= dictForType( type
))) {
283 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
284 if( machPort
&& !machPort
->holdDestroy
)
285 dict
->removeObject( (const OSSymbol
*) obj
);
289 IOUnlock( gIOObjectPortLock
);
292 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
295 IOMachPort
* machPort
;
297 IOLockLock( gIOObjectPortLock
);
299 if( (dict
= dictForType( type
))) {
300 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
302 machPort
->holdDestroy
= true;
305 IOLockUnlock( gIOObjectPortLock
);
308 void IOUserClient::destroyUserReferences( OSObject
* obj
)
310 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
313 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
317 IOTakeLock( gIOObjectPortLock
);
320 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
323 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
327 if ((uc
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
)
329 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
330 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
332 uc
->mappings
->release();
335 dict
->removeObject( (const OSSymbol
*) obj
);
339 IOUnlock( gIOObjectPortLock
);
342 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
343 io_object_t obj
, ipc_kobject_type_t type
)
345 return( iokit_make_send_right( task
, obj
, type
));
348 void IOMachPort::free( void )
351 iokit_destroy_object_port( port
);
355 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
357 class IOUserIterator
: public OSIterator
359 OSDeclareDefaultStructors(IOUserIterator
)
361 OSObject
* userIteratorObject
;
364 static IOUserIterator
* withIterator(OSIterator
* iter
);
365 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
366 virtual void free() APPLE_KEXT_OVERRIDE
;
368 virtual void reset() APPLE_KEXT_OVERRIDE
;
369 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
370 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
373 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
375 class IOUserNotification
: public IOUserIterator
377 OSDeclareDefaultStructors(IOUserNotification
)
379 #define holdNotify userIteratorObject
383 virtual void free() APPLE_KEXT_OVERRIDE
;
385 virtual void setNotification( IONotifier
* obj
);
387 virtual void reset() APPLE_KEXT_OVERRIDE
;
388 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
391 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
393 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
396 IOUserIterator::withIterator(OSIterator
* iter
)
400 if (!iter
) return (0);
402 me
= new IOUserIterator
;
403 if (me
&& !me
->init())
409 me
->userIteratorObject
= iter
;
415 IOUserIterator::init( void )
417 if (!OSObject::init()) return (false);
419 lock
= IOLockAlloc();
427 IOUserIterator::free()
429 if (userIteratorObject
) userIteratorObject
->release();
430 if (lock
) IOLockFree(lock
);
435 IOUserIterator::reset()
438 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
439 ((OSIterator
*)userIteratorObject
)->reset();
444 IOUserIterator::isValid()
449 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
450 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
457 IOUserIterator::getNextObject()
462 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
463 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
469 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
472 // functions called from osfmk/device/iokit_rpc.c
475 iokit_add_reference( io_object_t obj
)
482 iokit_remove_reference( io_object_t obj
)
489 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
491 IOMachPort
* machPort
;
494 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
496 port
= machPort
->port
;
498 iokit_retain_port( port
);
509 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
510 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
512 IOUserClient
* client
;
514 IOUserNotification
* notify
;
516 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
517 return( kIOReturnNotReady
);
519 if( IKOT_IOKIT_CONNECT
== type
)
521 if( (client
= OSDynamicCast( IOUserClient
, obj
))) {
522 IOStatisticsClientCall();
523 client
->clientDied();
526 else if( IKOT_IOKIT_OBJECT
== type
)
528 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
530 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
531 notify
->setNotification( 0 );
534 return( kIOReturnSuccess
);
539 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
541 class IOServiceUserNotification
: public IOUserNotification
543 OSDeclareDefaultStructors(IOServiceUserNotification
)
546 mach_msg_header_t msgHdr
;
547 OSNotificationHeader64 notifyHeader
;
550 enum { kMaxOutstanding
= 1024 };
555 OSObject
* lastEntry
;
560 virtual bool init( mach_port_t port
, natural_t type
,
561 void * reference
, vm_size_t referenceSize
,
563 virtual void free() APPLE_KEXT_OVERRIDE
;
565 static bool _handler( void * target
,
566 void * ref
, IOService
* newService
, IONotifier
* notifier
);
567 virtual bool handler( void * ref
, IOService
* newService
);
569 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
572 class IOServiceMessageUserNotification
: public IOUserNotification
574 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
577 mach_msg_header_t msgHdr
;
578 mach_msg_body_t msgBody
;
579 mach_msg_port_descriptor_t ports
[1];
580 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
590 virtual bool init( mach_port_t port
, natural_t type
,
591 void * reference
, vm_size_t referenceSize
,
595 virtual void free() APPLE_KEXT_OVERRIDE
;
597 static IOReturn
_handler( void * target
, void * ref
,
598 UInt32 messageType
, IOService
* provider
,
599 void * messageArgument
, vm_size_t argSize
);
600 virtual IOReturn
handler( void * ref
,
601 UInt32 messageType
, IOService
* provider
,
602 void * messageArgument
, vm_size_t argSize
);
604 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
607 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
610 #define super IOUserIterator
611 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
612 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
614 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
616 void IOUserNotification::free( void )
620 assert(OSDynamicCast(IONotifier
, holdNotify
));
621 ((IONotifier
*)holdNotify
)->remove();
624 // can't be in handler now
630 void IOUserNotification::setNotification( IONotifier
* notify
)
632 OSObject
* previousNotify
;
634 IOLockLock( gIOObjectPortLock
);
636 previousNotify
= holdNotify
;
639 IOLockUnlock( gIOObjectPortLock
);
643 assert(OSDynamicCast(IONotifier
, previousNotify
));
644 ((IONotifier
*)previousNotify
)->remove();
648 void IOUserNotification::reset()
653 bool IOUserNotification::isValid()
658 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
661 #define super IOUserNotification
662 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
664 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
666 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
667 void * reference
, vm_size_t referenceSize
,
673 newSet
= OSArray::withCapacity( 1 );
677 if (referenceSize
> sizeof(OSAsyncReference64
))
680 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
681 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
685 bzero( pingMsg
, msgSize
);
687 pingMsg
->msgHdr
.msgh_remote_port
= port
;
688 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
689 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
690 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
691 pingMsg
->msgHdr
.msgh_size
= msgSize
;
692 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
694 pingMsg
->notifyHeader
.size
= 0;
695 pingMsg
->notifyHeader
.type
= type
;
696 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
701 void IOServiceUserNotification::free( void )
706 OSObject
* _lastEntry
;
710 _lastEntry
= lastEntry
;
715 if( _pingMsg
&& _msgSize
) {
716 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
717 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
719 IOFree(_pingMsg
, _msgSize
);
723 _lastEntry
->release();
729 bool IOServiceUserNotification::_handler( void * target
,
730 void * ref
, IOService
* newService
, IONotifier
* notifier
)
732 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
735 bool IOServiceUserNotification::handler( void * ref
,
736 IOService
* newService
)
740 ipc_port_t port
= NULL
;
741 bool sendPing
= false;
745 count
= newSet
->getCount();
746 if( count
< kMaxOutstanding
) {
748 newSet
->setObject( newService
);
749 if( (sendPing
= (armed
&& (0 == count
))))
755 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
756 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
759 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
760 pingMsg
->msgHdr
.msgh_local_port
= port
;
762 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
764 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
765 pingMsg
->msgHdr
.msgh_size
,
766 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
769 iokit_release_port( port
);
771 if( KERN_SUCCESS
!= kr
)
772 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
778 OSObject
* IOServiceUserNotification::getNextObject()
786 lastEntry
->release();
788 count
= newSet
->getCount();
790 result
= newSet
->getObject( count
- 1 );
792 newSet
->removeObject( count
- 1);
804 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
806 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
808 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
810 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
811 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
817 if (referenceSize
> sizeof(OSAsyncReference64
))
820 clientIs64
= client64
;
822 owningPID
= proc_selfpid();
824 extraSize
+= sizeof(IOServiceInterestContent64
);
825 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
+ extraSize
;
826 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
830 bzero( pingMsg
, msgSize
);
832 pingMsg
->msgHdr
.msgh_remote_port
= port
;
833 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
835 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
836 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
837 pingMsg
->msgHdr
.msgh_size
= msgSize
;
838 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
840 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
842 pingMsg
->ports
[0].name
= 0;
843 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
844 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
846 pingMsg
->notifyHeader
.size
= extraSize
;
847 pingMsg
->notifyHeader
.type
= type
;
848 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
853 void IOServiceMessageUserNotification::free( void )
863 if( _pingMsg
&& _msgSize
) {
864 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
865 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
867 IOFree( _pingMsg
, _msgSize
);
871 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
872 UInt32 messageType
, IOService
* provider
,
873 void * argument
, vm_size_t argSize
)
875 return( ((IOServiceMessageUserNotification
*) target
)->handler(
876 ref
, messageType
, provider
, argument
, argSize
));
879 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
880 UInt32 messageType
, IOService
* provider
,
881 void * messageArgument
, vm_size_t argSize
)
884 ipc_port_t thisPort
, providerPort
;
885 IOServiceInterestContent64
* data
= (IOServiceInterestContent64
*)
886 ((((uint8_t *) pingMsg
) + msgSize
) - pingMsg
->notifyHeader
.size
);
887 // == pingMsg->notifyHeader.content;
889 if (kIOMessageCopyClientID
== messageType
)
891 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
892 return (kIOReturnSuccess
);
895 data
->messageType
= messageType
;
899 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
901 argSize
= sizeof(data
->messageArgument
[0]);
904 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
905 argSize
= sizeof(uint32_t);
910 if( argSize
> kIOUserNotifyMaxMessageSize
)
911 argSize
= kIOUserNotifyMaxMessageSize
;
912 bcopy( messageArgument
, data
->messageArgument
, argSize
);
915 // adjust message size for ipc restrictions
917 type
= pingMsg
->notifyHeader
.type
;
918 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
919 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
920 pingMsg
->notifyHeader
.type
= type
;
921 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
923 pingMsg
->msgHdr
.msgh_size
= msgSize
- pingMsg
->notifyHeader
.size
924 + sizeof( IOServiceInterestContent64
)
925 - sizeof( data
->messageArgument
)
928 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
929 pingMsg
->ports
[0].name
= providerPort
;
930 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
931 pingMsg
->msgHdr
.msgh_local_port
= thisPort
;
932 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
933 pingMsg
->msgHdr
.msgh_size
,
934 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
937 iokit_release_port( thisPort
);
939 iokit_release_port( providerPort
);
941 if( KERN_SUCCESS
!= kr
)
942 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
944 return( kIOReturnSuccess
);
947 OSObject
* IOServiceMessageUserNotification::getNextObject()
952 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
955 #define super IOService
956 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
958 void IOUserClient::initialize( void )
960 gIOObjectPortLock
= IOLockAlloc();
962 assert( gIOObjectPortLock
);
965 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
966 mach_port_t wakePort
,
967 void *callback
, void *refcon
)
969 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
970 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
971 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
972 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
975 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
976 mach_port_t wakePort
,
977 mach_vm_address_t callback
, io_user_reference_t refcon
)
979 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
980 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
981 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
982 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
985 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
986 mach_port_t wakePort
,
987 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
989 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
990 if (vm_map_is_64bit(get_task_map(task
))) {
991 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
995 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
998 OSDictionary
* user
= 0;
1000 if ((array
= OSDynamicCast(OSArray
,
1001 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1003 for (unsigned int idx
= 0;
1004 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1008 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1009 && (uid
== num
->unsigned32BitValue())) {
1019 static OSDictionary
* CopyUserOnConsole(void)
1022 OSDictionary
* user
= 0;
1024 if ((array
= OSDynamicCast(OSArray
,
1025 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1027 for (unsigned int idx
= 0;
1028 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1031 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
1042 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
1043 IOService
* service
)
1047 p
= (proc_t
) get_bsdtask_info(task
);
1050 uint64_t authorizationID
;
1052 authorizationID
= proc_uniqueid(p
);
1053 if (authorizationID
)
1055 if (service
->getAuthorizationID() == authorizationID
)
1057 return (kIOReturnSuccess
);
1062 return (kIOReturnNotPermitted
);
1065 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
1066 const char * privilegeName
)
1069 security_token_t token
;
1070 mach_msg_type_number_t count
;
1072 OSDictionary
* user
;
1076 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1077 sizeof(kIOClientPrivilegeForeground
)))
1079 if (task_is_gpu_denied(current_task()))
1080 return (kIOReturnNotPrivileged
);
1082 return (kIOReturnSuccess
);
1085 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1086 sizeof(kIOClientPrivilegeConsoleSession
)))
1091 task
= (task_t
) securityToken
;
1093 task
= current_task();
1094 p
= (proc_t
) get_bsdtask_info(task
);
1095 kr
= kIOReturnNotPrivileged
;
1097 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1099 user
= CopyUserOnConsole();
1103 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1104 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1106 kr
= kIOReturnSuccess
;
1110 kauth_cred_unref(&cred
);
1115 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1116 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1117 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1119 task
= (task_t
)securityToken
;
1121 count
= TASK_SECURITY_TOKEN_COUNT
;
1122 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1124 if (KERN_SUCCESS
!= kr
)
1126 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1127 sizeof(kIOClientPrivilegeAdministrator
))) {
1128 if (0 != token
.val
[0])
1129 kr
= kIOReturnNotPrivileged
;
1130 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1131 sizeof(kIOClientPrivilegeLocalUser
))) {
1132 user
= CopyConsoleUser(token
.val
[0]);
1136 kr
= kIOReturnNotPrivileged
;
1137 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1138 sizeof(kIOClientPrivilegeConsoleUser
))) {
1139 user
= CopyConsoleUser(token
.val
[0]);
1141 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1142 kr
= kIOReturnNotPrivileged
;
1143 else if ( secureConsole
) {
1144 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1145 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1146 kr
= kIOReturnNotPrivileged
;
1151 kr
= kIOReturnNotPrivileged
;
1153 kr
= kIOReturnUnsupported
;
1158 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1159 const char * entitlement
)
1161 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1165 char procname
[MAXCOMLEN
+ 1] = "";
1167 void *entitlements_blob
= NULL
;
1168 char *entitlements_data
= NULL
;
1169 OSObject
*entitlements_obj
= NULL
;
1170 OSDictionary
*entitlements
= NULL
;
1171 OSString
*errorString
= NULL
;
1172 OSObject
*value
= NULL
;
1174 p
= (proc_t
)get_bsdtask_info(task
);
1178 proc_name(pid
, procname
, (int)sizeof(procname
));
1180 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1183 if (len
<= offsetof(CS_GenericBlob
, data
))
1187 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1188 * we'll try to parse in the kernel.
1190 len
-= offsetof(CS_GenericBlob
, data
);
1191 if (len
> MAX_ENTITLEMENTS_LEN
) {
1192 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1197 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1198 * what is stored in the entitlements blob. Copy the string and
1201 entitlements_data
= (char *)IOMalloc(len
+ 1);
1202 if (entitlements_data
== NULL
)
1204 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1205 entitlements_data
[len
] = '\0';
1207 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1208 if (errorString
!= NULL
) {
1209 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1212 if (entitlements_obj
== NULL
)
1215 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1216 if (entitlements
== NULL
)
1219 /* Fetch the entitlement value from the dictionary. */
1220 value
= entitlements
->getObject(entitlement
);
1225 if (entitlements_data
!= NULL
)
1226 IOFree(entitlements_data
, len
+ 1);
1227 if (entitlements_obj
!= NULL
)
1228 entitlements_obj
->release();
1229 if (errorString
!= NULL
)
1230 errorString
->release();
1234 bool IOUserClient::init()
1236 if (getPropertyTable() || super::init())
1242 bool IOUserClient::init(OSDictionary
* dictionary
)
1244 if (getPropertyTable() || super::init(dictionary
))
1250 bool IOUserClient::initWithTask(task_t owningTask
,
1254 if (getPropertyTable() || super::init())
1260 bool IOUserClient::initWithTask(task_t owningTask
,
1263 OSDictionary
* properties
)
1267 ok
= super::init( properties
);
1268 ok
&= initWithTask( owningTask
, securityID
, type
);
1273 bool IOUserClient::reserve()
1276 reserved
= IONew(ExpansionData
, 1);
1281 setTerminateDefer(NULL
, true);
1282 IOStatisticsRegisterCounter();
1287 void IOUserClient::free()
1290 mappings
->release();
1292 IOStatisticsUnregisterCounter();
1295 IODelete(reserved
, ExpansionData
, 1);
1300 IOReturn
IOUserClient::clientDied( void )
1302 IOReturn ret
= kIOReturnNotReady
;
1304 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
))
1306 ret
= clientClose();
1312 IOReturn
IOUserClient::clientClose( void )
1314 return( kIOReturnUnsupported
);
1317 IOService
* IOUserClient::getService( void )
1322 IOReturn
IOUserClient::registerNotificationPort(
1323 mach_port_t
/* port */,
1325 UInt32
/* refCon */)
1327 return( kIOReturnUnsupported
);
1330 IOReturn
IOUserClient::registerNotificationPort(
1333 io_user_reference_t refCon
)
1335 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1338 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1339 semaphore_t
* semaphore
)
1341 return( kIOReturnUnsupported
);
1344 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1346 return( kIOReturnUnsupported
);
1349 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1350 IOOptionBits
* options
,
1351 IOMemoryDescriptor
** memory
)
1353 return( kIOReturnUnsupported
);
1357 IOMemoryMap
* IOUserClient::mapClientMemory(
1360 IOOptionBits mapFlags
,
1361 IOVirtualAddress atAddress
)
1367 IOMemoryMap
* IOUserClient::mapClientMemory64(
1370 IOOptionBits mapFlags
,
1371 mach_vm_address_t atAddress
)
1374 IOOptionBits options
= 0;
1375 IOMemoryDescriptor
* memory
;
1376 IOMemoryMap
* map
= 0;
1378 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1380 if( memory
&& (kIOReturnSuccess
== err
)) {
1382 options
= (options
& ~kIOMapUserOptionsMask
)
1383 | (mapFlags
& kIOMapUserOptionsMask
);
1384 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1391 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1392 OSObject
*obj
, io_object_t
*clientObj
)
1394 mach_port_name_t name
;
1396 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1398 *(mach_port_name_t
*)clientObj
= name
;
1399 return kIOReturnSuccess
;
1402 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1407 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1412 IOExternalMethod
* IOUserClient::
1413 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1415 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1418 *targetP
= (IOService
*) method
->object
;
1423 IOExternalAsyncMethod
* IOUserClient::
1424 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1426 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1429 *targetP
= (IOService
*) method
->object
;
1434 IOExternalTrap
* IOUserClient::
1435 getExternalTrapForIndex(UInt32 index
)
1440 IOExternalTrap
* IOUserClient::
1441 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1443 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1446 *targetP
= trap
->object
;
1452 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1455 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1457 if (MACH_PORT_NULL
!= port
)
1458 iokit_release_port_send(port
);
1460 return (kIOReturnSuccess
);
1463 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1465 if (MACH_PORT_NULL
!= port
)
1466 iokit_release_port_send(port
);
1468 return (kIOReturnSuccess
);
1471 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1472 IOReturn result
, void *args
[], UInt32 numArgs
)
1474 OSAsyncReference64 reference64
;
1475 io_user_reference_t args64
[kMaxAsyncArgs
];
1478 if (numArgs
> kMaxAsyncArgs
)
1479 return kIOReturnMessageTooLarge
;
1481 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1482 reference64
[idx
] = REF64(reference
[idx
]);
1484 for (idx
= 0; idx
< numArgs
; idx
++)
1485 args64
[idx
] = REF64(args
[idx
]);
1487 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1490 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1491 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1493 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1496 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1497 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1499 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1502 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1503 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1507 mach_msg_header_t msgHdr
;
1512 OSNotificationHeader notifyHdr
;
1513 IOAsyncCompletionContent asyncContent
;
1514 uint32_t args
[kMaxAsyncArgs
];
1518 OSNotificationHeader64 notifyHdr
;
1519 IOAsyncCompletionContent asyncContent
;
1520 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1525 mach_port_t replyPort
;
1528 // If no reply port, do nothing.
1529 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1530 if (replyPort
== MACH_PORT_NULL
)
1531 return kIOReturnSuccess
;
1533 if (numArgs
> kMaxAsyncArgs
)
1534 return kIOReturnMessageTooLarge
;
1536 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1538 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1539 replyMsg
.msgHdr
.msgh_local_port
= 0;
1540 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1541 if (kIOUCAsync64Flag
& reference
[0])
1543 replyMsg
.msgHdr
.msgh_size
=
1544 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1545 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1546 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1547 + numArgs
* sizeof(io_user_reference_t
);
1548 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1549 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1551 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1553 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1559 replyMsg
.msgHdr
.msgh_size
=
1560 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1561 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1563 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1564 + numArgs
* sizeof(uint32_t);
1565 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1567 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1568 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1570 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1572 for (idx
= 0; idx
< numArgs
; idx
++)
1573 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1576 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1577 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1578 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1580 /* Fail on full queue. */
1581 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1582 replyMsg
.msgHdr
.msgh_size
);
1584 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
))
1585 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__
, kr
);
1590 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1594 #define CHECK(cls,obj,out) \
1596 if( !(out = OSDynamicCast( cls, obj))) \
1597 return( kIOReturnBadArgument )
1599 #define CHECKLOCKED(cls,obj,out) \
1600 IOUserIterator * oIter; \
1602 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1603 return (kIOReturnBadArgument); \
1604 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
1605 return (kIOReturnBadArgument)
1607 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1609 // Create a vm_map_copy_t or kalloc'ed data for memory
1610 // to be copied out. ipc will free after the copyout.
1612 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1613 io_buf_ptr_t
* buf
)
1618 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1619 false /* src_destroy */, ©
);
1621 assert( err
== KERN_SUCCESS
);
1622 if( err
== KERN_SUCCESS
)
1623 *buf
= (char *) copy
;
1628 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1630 /* Routine io_server_version */
1631 kern_return_t
is_io_server_version(
1632 mach_port_t master_port
,
1635 *version
= IOKIT_SERVER_VERSION
;
1636 return (kIOReturnSuccess
);
1639 /* Routine io_object_get_class */
1640 kern_return_t
is_io_object_get_class(
1642 io_name_t className
)
1644 const OSMetaClass
* my_obj
= NULL
;
1645 const char * my_class_name
= NULL
;
1648 return( kIOReturnBadArgument
);
1650 if ( !my_class_name
) {
1651 my_obj
= object
->getMetaClass();
1653 return (kIOReturnNotFound
);
1656 my_class_name
= my_obj
->getClassName();
1659 strlcpy( className
, my_class_name
, sizeof(io_name_t
));
1661 return( kIOReturnSuccess
);
1664 /* Routine io_object_get_superclass */
1665 kern_return_t
is_io_object_get_superclass(
1666 mach_port_t master_port
,
1668 io_name_t class_name
)
1670 const OSMetaClass
* my_obj
= NULL
;
1671 const OSMetaClass
* superclass
= NULL
;
1672 const OSSymbol
*my_name
= NULL
;
1673 const char *my_cstr
= NULL
;
1675 if (!obj_name
|| !class_name
)
1676 return (kIOReturnBadArgument
);
1678 if( master_port
!= master_device_port
)
1679 return( kIOReturnNotPrivileged
);
1681 my_name
= OSSymbol::withCString(obj_name
);
1684 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1688 superclass
= my_obj
->getSuperClass();
1692 return( kIOReturnNotFound
);
1695 my_cstr
= superclass
->getClassName();
1698 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1699 return( kIOReturnSuccess
);
1701 return (kIOReturnNotFound
);
1704 /* Routine io_object_get_bundle_identifier */
1705 kern_return_t
is_io_object_get_bundle_identifier(
1706 mach_port_t master_port
,
1708 io_name_t bundle_name
)
1710 const OSMetaClass
* my_obj
= NULL
;
1711 const OSSymbol
*my_name
= NULL
;
1712 const OSSymbol
*identifier
= NULL
;
1713 const char *my_cstr
= NULL
;
1715 if (!obj_name
|| !bundle_name
)
1716 return (kIOReturnBadArgument
);
1718 if( master_port
!= master_device_port
)
1719 return( kIOReturnNotPrivileged
);
1721 my_name
= OSSymbol::withCString(obj_name
);
1724 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1729 identifier
= my_obj
->getKmodName();
1732 return( kIOReturnNotFound
);
1735 my_cstr
= identifier
->getCStringNoCopy();
1737 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1738 return( kIOReturnSuccess
);
1741 return (kIOReturnBadArgument
);
1744 /* Routine io_object_conforms_to */
1745 kern_return_t
is_io_object_conforms_to(
1747 io_name_t className
,
1748 boolean_t
*conforms
)
1751 return( kIOReturnBadArgument
);
1753 *conforms
= (0 != object
->metaCast( className
));
1755 return( kIOReturnSuccess
);
1758 /* Routine io_object_get_retain_count */
1759 kern_return_t
is_io_object_get_retain_count(
1761 uint32_t *retainCount
)
1764 return( kIOReturnBadArgument
);
1766 *retainCount
= object
->getRetainCount();
1767 return( kIOReturnSuccess
);
1770 /* Routine io_iterator_next */
1771 kern_return_t
is_io_iterator_next(
1772 io_object_t iterator
,
1773 io_object_t
*object
)
1778 CHECK( OSIterator
, iterator
, iter
);
1780 obj
= iter
->getNextObject();
1784 ret
= kIOReturnSuccess
;
1786 ret
= kIOReturnNoDevice
;
1791 /* Routine io_iterator_reset */
1792 kern_return_t
is_io_iterator_reset(
1793 io_object_t iterator
)
1795 CHECK( OSIterator
, iterator
, iter
);
1799 return( kIOReturnSuccess
);
1802 /* Routine io_iterator_is_valid */
1803 kern_return_t
is_io_iterator_is_valid(
1804 io_object_t iterator
,
1805 boolean_t
*is_valid
)
1807 CHECK( OSIterator
, iterator
, iter
);
1809 *is_valid
= iter
->isValid();
1811 return( kIOReturnSuccess
);
1815 static kern_return_t
internal_io_service_match_property_table(
1816 io_service_t _service
,
1817 const char * matching
,
1818 mach_msg_type_number_t matching_size
,
1821 CHECK( IOService
, _service
, service
);
1825 OSDictionary
* dict
;
1827 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1828 : OSUnserializeXML(matching
);
1829 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1831 *matches
= service
->passiveMatch( dict
);
1832 kr
= kIOReturnSuccess
;
1834 kr
= kIOReturnBadArgument
;
1842 /* Routine io_service_match_property_table */
1843 kern_return_t
is_io_service_match_property_table(
1844 io_service_t service
,
1845 io_string_t matching
,
1846 boolean_t
*matches
)
1848 return (internal_io_service_match_property_table(service
, matching
, 0, matches
));
1852 /* Routine io_service_match_property_table_ool */
1853 kern_return_t
is_io_service_match_property_table_ool(
1854 io_object_t service
,
1855 io_buf_ptr_t matching
,
1856 mach_msg_type_number_t matchingCnt
,
1857 kern_return_t
*result
,
1858 boolean_t
*matches
)
1862 vm_map_offset_t map_data
;
1864 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1865 data
= CAST_DOWN(vm_offset_t
, map_data
);
1867 if( KERN_SUCCESS
== kr
) {
1868 // must return success after vm_map_copyout() succeeds
1869 *result
= internal_io_service_match_property_table(service
,
1870 (const char *)data
, matchingCnt
, matches
);
1871 vm_deallocate( kernel_map
, data
, matchingCnt
);
1877 /* Routine io_service_match_property_table_bin */
1878 kern_return_t
is_io_service_match_property_table_bin(
1879 io_object_t service
,
1880 io_struct_inband_t matching
,
1881 mach_msg_type_number_t matchingCnt
,
1884 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
1887 static kern_return_t
internal_io_service_get_matching_services(
1888 mach_port_t master_port
,
1889 const char * matching
,
1890 mach_msg_type_number_t matching_size
,
1891 io_iterator_t
*existing
)
1895 OSDictionary
* dict
;
1897 if( master_port
!= master_device_port
)
1898 return( kIOReturnNotPrivileged
);
1900 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1901 : OSUnserializeXML(matching
);
1902 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1903 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
1904 kr
= kIOReturnSuccess
;
1906 kr
= kIOReturnBadArgument
;
1914 /* Routine io_service_get_matching_services */
1915 kern_return_t
is_io_service_get_matching_services(
1916 mach_port_t master_port
,
1917 io_string_t matching
,
1918 io_iterator_t
*existing
)
1920 return (internal_io_service_get_matching_services(master_port
, matching
, 0, existing
));
1923 /* Routine io_service_get_matching_services_ool */
1924 kern_return_t
is_io_service_get_matching_services_ool(
1925 mach_port_t master_port
,
1926 io_buf_ptr_t matching
,
1927 mach_msg_type_number_t matchingCnt
,
1928 kern_return_t
*result
,
1929 io_object_t
*existing
)
1933 vm_map_offset_t map_data
;
1935 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
1936 data
= CAST_DOWN(vm_offset_t
, map_data
);
1938 if( KERN_SUCCESS
== kr
) {
1939 // must return success after vm_map_copyout() succeeds
1940 // and mig will copy out objects on success
1942 *result
= internal_io_service_get_matching_services(master_port
,
1943 (const char *) data
, matchingCnt
, existing
);
1944 vm_deallocate( kernel_map
, data
, matchingCnt
);
1950 /* Routine io_service_get_matching_services_bin */
1951 kern_return_t
is_io_service_get_matching_services_bin(
1952 mach_port_t master_port
,
1953 io_struct_inband_t matching
,
1954 mach_msg_type_number_t matchingCnt
,
1955 io_object_t
*existing
)
1957 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
1961 static kern_return_t
internal_io_service_get_matching_service(
1962 mach_port_t master_port
,
1963 const char * matching
,
1964 mach_msg_type_number_t matching_size
,
1965 io_service_t
*service
)
1969 OSDictionary
* dict
;
1971 if( master_port
!= master_device_port
)
1972 return( kIOReturnNotPrivileged
);
1974 obj
= matching_size
? OSUnserializeXML(matching
, matching_size
)
1975 : OSUnserializeXML(matching
);
1976 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
1977 *service
= IOService::copyMatchingService( dict
);
1978 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
1980 kr
= kIOReturnBadArgument
;
1988 /* Routine io_service_get_matching_service */
1989 kern_return_t
is_io_service_get_matching_service(
1990 mach_port_t master_port
,
1991 io_string_t matching
,
1992 io_service_t
*service
)
1994 return (internal_io_service_get_matching_service(master_port
, matching
, 0, service
));
1997 /* Routine io_service_get_matching_services_ool */
1998 kern_return_t
is_io_service_get_matching_service_ool(
1999 mach_port_t master_port
,
2000 io_buf_ptr_t matching
,
2001 mach_msg_type_number_t matchingCnt
,
2002 kern_return_t
*result
,
2003 io_object_t
*service
)
2007 vm_map_offset_t map_data
;
2009 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2010 data
= CAST_DOWN(vm_offset_t
, map_data
);
2012 if( KERN_SUCCESS
== kr
) {
2013 // must return success after vm_map_copyout() succeeds
2014 // and mig will copy out objects on success
2016 *result
= internal_io_service_get_matching_service(master_port
,
2017 (const char *) data
, matchingCnt
, service
);
2018 vm_deallocate( kernel_map
, data
, matchingCnt
);
2024 /* Routine io_service_get_matching_service_bin */
2025 kern_return_t
is_io_service_get_matching_service_bin(
2026 mach_port_t master_port
,
2027 io_struct_inband_t matching
,
2028 mach_msg_type_number_t matchingCnt
,
2029 io_object_t
*service
)
2031 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
2034 static kern_return_t
internal_io_service_add_notification(
2035 mach_port_t master_port
,
2036 io_name_t notification_type
,
2037 const char * matching
,
2038 size_t matching_size
,
2041 vm_size_t referenceSize
,
2043 io_object_t
* notification
)
2045 IOServiceUserNotification
* userNotify
= 0;
2046 IONotifier
* notify
= 0;
2047 const OSSymbol
* sym
;
2048 OSDictionary
* dict
;
2050 unsigned long int userMsgType
;
2052 if( master_port
!= master_device_port
)
2053 return( kIOReturnNotPrivileged
);
2056 err
= kIOReturnNoResources
;
2058 if( !(sym
= OSSymbol::withCString( notification_type
)))
2059 err
= kIOReturnNoResources
;
2063 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2067 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
));
2071 err
= kIOReturnBadArgument
;
2075 if( (sym
== gIOPublishNotification
)
2076 || (sym
== gIOFirstPublishNotification
))
2077 userMsgType
= kIOServicePublishNotificationType
;
2078 else if( (sym
== gIOMatchedNotification
)
2079 || (sym
== gIOFirstMatchNotification
))
2080 userMsgType
= kIOServiceMatchedNotificationType
;
2081 else if( sym
== gIOTerminatedNotification
)
2082 userMsgType
= kIOServiceTerminatedNotificationType
;
2084 userMsgType
= kLastIOKitNotificationType
;
2086 userNotify
= new IOServiceUserNotification
;
2088 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
2089 reference
, referenceSize
, client64
)) {
2090 iokit_release_port_send(port
);
2091 userNotify
->release();
2097 notify
= IOService::addMatchingNotification( sym
, dict
,
2098 &userNotify
->_handler
, userNotify
);
2100 *notification
= userNotify
;
2101 userNotify
->setNotification( notify
);
2102 err
= kIOReturnSuccess
;
2104 err
= kIOReturnUnsupported
;
2117 /* Routine io_service_add_notification */
2118 kern_return_t
is_io_service_add_notification(
2119 mach_port_t master_port
,
2120 io_name_t notification_type
,
2121 io_string_t matching
,
2123 io_async_ref_t reference
,
2124 mach_msg_type_number_t referenceCnt
,
2125 io_object_t
* notification
)
2127 return (internal_io_service_add_notification(master_port
, notification_type
,
2128 matching
, 0, port
, &reference
[0], sizeof(io_async_ref_t
),
2129 false, notification
));
2132 /* Routine io_service_add_notification_64 */
2133 kern_return_t
is_io_service_add_notification_64(
2134 mach_port_t master_port
,
2135 io_name_t notification_type
,
2136 io_string_t matching
,
2137 mach_port_t wake_port
,
2138 io_async_ref64_t reference
,
2139 mach_msg_type_number_t referenceCnt
,
2140 io_object_t
*notification
)
2142 return (internal_io_service_add_notification(master_port
, notification_type
,
2143 matching
, 0, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2144 true, notification
));
2147 /* Routine io_service_add_notification_bin */
2148 kern_return_t is_io_service_add_notification_bin
2150 mach_port_t master_port
,
2151 io_name_t notification_type
,
2152 io_struct_inband_t matching
,
2153 mach_msg_type_number_t matchingCnt
,
2154 mach_port_t wake_port
,
2155 io_async_ref_t reference
,
2156 mach_msg_type_number_t referenceCnt
,
2157 io_object_t
*notification
)
2159 return (internal_io_service_add_notification(master_port
, notification_type
,
2160 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2161 false, notification
));
2164 /* Routine io_service_add_notification_bin_64 */
2165 kern_return_t is_io_service_add_notification_bin_64
2167 mach_port_t master_port
,
2168 io_name_t notification_type
,
2169 io_struct_inband_t matching
,
2170 mach_msg_type_number_t matchingCnt
,
2171 mach_port_t wake_port
,
2172 io_async_ref64_t reference
,
2173 mach_msg_type_number_t referenceCnt
,
2174 io_object_t
*notification
)
2176 return (internal_io_service_add_notification(master_port
, notification_type
,
2177 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2178 true, notification
));
2181 static kern_return_t
internal_io_service_add_notification_ool(
2182 mach_port_t master_port
,
2183 io_name_t notification_type
,
2184 io_buf_ptr_t matching
,
2185 mach_msg_type_number_t matchingCnt
,
2186 mach_port_t wake_port
,
2188 vm_size_t referenceSize
,
2190 kern_return_t
*result
,
2191 io_object_t
*notification
)
2195 vm_map_offset_t map_data
;
2197 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2198 data
= CAST_DOWN(vm_offset_t
, map_data
);
2200 if( KERN_SUCCESS
== kr
) {
2201 // must return success after vm_map_copyout() succeeds
2202 // and mig will copy out objects on success
2204 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2205 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2206 vm_deallocate( kernel_map
, data
, matchingCnt
);
2212 /* Routine io_service_add_notification_ool */
2213 kern_return_t
is_io_service_add_notification_ool(
2214 mach_port_t master_port
,
2215 io_name_t notification_type
,
2216 io_buf_ptr_t matching
,
2217 mach_msg_type_number_t matchingCnt
,
2218 mach_port_t wake_port
,
2219 io_async_ref_t reference
,
2220 mach_msg_type_number_t referenceCnt
,
2221 kern_return_t
*result
,
2222 io_object_t
*notification
)
2224 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2225 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2226 false, result
, notification
));
2229 /* Routine io_service_add_notification_ool_64 */
2230 kern_return_t
is_io_service_add_notification_ool_64(
2231 mach_port_t master_port
,
2232 io_name_t notification_type
,
2233 io_buf_ptr_t matching
,
2234 mach_msg_type_number_t matchingCnt
,
2235 mach_port_t wake_port
,
2236 io_async_ref64_t reference
,
2237 mach_msg_type_number_t referenceCnt
,
2238 kern_return_t
*result
,
2239 io_object_t
*notification
)
2241 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2242 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2243 true, result
, notification
));
2246 /* Routine io_service_add_notification_old */
2247 kern_return_t
is_io_service_add_notification_old(
2248 mach_port_t master_port
,
2249 io_name_t notification_type
,
2250 io_string_t matching
,
2252 // for binary compatibility reasons, this must be natural_t for ILP32
2254 io_object_t
* notification
)
2256 return( is_io_service_add_notification( master_port
, notification_type
,
2257 matching
, port
, &ref
, 1, notification
));
2261 static kern_return_t
internal_io_service_add_interest_notification(
2262 io_object_t _service
,
2263 io_name_t type_of_interest
,
2266 vm_size_t referenceSize
,
2268 io_object_t
* notification
)
2271 IOServiceMessageUserNotification
* userNotify
= 0;
2272 IONotifier
* notify
= 0;
2273 const OSSymbol
* sym
;
2276 CHECK( IOService
, _service
, service
);
2278 err
= kIOReturnNoResources
;
2279 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2281 userNotify
= new IOServiceMessageUserNotification
;
2283 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2284 reference
, referenceSize
,
2285 kIOUserNotifyMaxMessageSize
,
2287 iokit_release_port_send(port
);
2288 userNotify
->release();
2294 notify
= service
->registerInterest( sym
,
2295 &userNotify
->_handler
, userNotify
);
2297 *notification
= userNotify
;
2298 userNotify
->setNotification( notify
);
2299 err
= kIOReturnSuccess
;
2301 err
= kIOReturnUnsupported
;
2310 /* Routine io_service_add_message_notification */
2311 kern_return_t
is_io_service_add_interest_notification(
2312 io_object_t service
,
2313 io_name_t type_of_interest
,
2315 io_async_ref_t reference
,
2316 mach_msg_type_number_t referenceCnt
,
2317 io_object_t
* notification
)
2319 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2320 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2323 /* Routine io_service_add_interest_notification_64 */
2324 kern_return_t
is_io_service_add_interest_notification_64(
2325 io_object_t service
,
2326 io_name_t type_of_interest
,
2327 mach_port_t wake_port
,
2328 io_async_ref64_t reference
,
2329 mach_msg_type_number_t referenceCnt
,
2330 io_object_t
*notification
)
2332 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2333 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2337 /* Routine io_service_acknowledge_notification */
2338 kern_return_t
is_io_service_acknowledge_notification(
2339 io_object_t _service
,
2340 natural_t notify_ref
,
2341 natural_t response
)
2343 CHECK( IOService
, _service
, service
);
2345 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2346 (IOOptionBits
) response
));
2350 /* Routine io_connect_get_semaphore */
2351 kern_return_t
is_io_connect_get_notification_semaphore(
2352 io_connect_t connection
,
2353 natural_t notification_type
,
2354 semaphore_t
*semaphore
)
2356 CHECK( IOUserClient
, connection
, client
);
2358 IOStatisticsClientCall();
2359 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2363 /* Routine io_registry_get_root_entry */
2364 kern_return_t
is_io_registry_get_root_entry(
2365 mach_port_t master_port
,
2368 IORegistryEntry
* entry
;
2370 if( master_port
!= master_device_port
)
2371 return( kIOReturnNotPrivileged
);
2373 entry
= IORegistryEntry::getRegistryRoot();
2378 return( kIOReturnSuccess
);
2381 /* Routine io_registry_create_iterator */
2382 kern_return_t
is_io_registry_create_iterator(
2383 mach_port_t master_port
,
2386 io_object_t
*iterator
)
2388 if( master_port
!= master_device_port
)
2389 return( kIOReturnNotPrivileged
);
2391 *iterator
= IOUserIterator::withIterator(
2392 IORegistryIterator::iterateOver(
2393 IORegistryEntry::getPlane( plane
), options
));
2395 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2398 /* Routine io_registry_entry_create_iterator */
2399 kern_return_t
is_io_registry_entry_create_iterator(
2400 io_object_t registry_entry
,
2403 io_object_t
*iterator
)
2405 CHECK( IORegistryEntry
, registry_entry
, entry
);
2407 *iterator
= IOUserIterator::withIterator(
2408 IORegistryIterator::iterateOver( entry
,
2409 IORegistryEntry::getPlane( plane
), options
));
2411 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2414 /* Routine io_registry_iterator_enter */
2415 kern_return_t
is_io_registry_iterator_enter_entry(
2416 io_object_t iterator
)
2418 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2420 IOLockLock(oIter
->lock
);
2422 IOLockUnlock(oIter
->lock
);
2424 return( kIOReturnSuccess
);
2427 /* Routine io_registry_iterator_exit */
2428 kern_return_t
is_io_registry_iterator_exit_entry(
2429 io_object_t iterator
)
2433 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2435 IOLockLock(oIter
->lock
);
2436 didIt
= iter
->exitEntry();
2437 IOLockUnlock(oIter
->lock
);
2439 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2442 /* Routine io_registry_entry_from_path */
2443 kern_return_t
is_io_registry_entry_from_path(
2444 mach_port_t master_port
,
2446 io_object_t
*registry_entry
)
2448 IORegistryEntry
* entry
;
2450 if( master_port
!= master_device_port
)
2451 return( kIOReturnNotPrivileged
);
2453 entry
= IORegistryEntry::fromPath( path
);
2455 *registry_entry
= entry
;
2457 return( kIOReturnSuccess
);
2461 /* Routine io_registry_entry_from_path */
2462 kern_return_t
is_io_registry_entry_from_path_ool(
2463 mach_port_t master_port
,
2464 io_string_inband_t path
,
2465 io_buf_ptr_t path_ool
,
2466 mach_msg_type_number_t path_oolCnt
,
2467 kern_return_t
*result
,
2468 io_object_t
*registry_entry
)
2470 IORegistryEntry
* entry
;
2471 vm_map_offset_t map_data
;
2476 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2480 res
= err
= KERN_SUCCESS
;
2481 if (path
[0]) cpath
= path
;
2484 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2485 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2487 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2488 if (KERN_SUCCESS
== err
)
2490 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2491 cpath
= CAST_DOWN(const char *, map_data
);
2492 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2496 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2498 entry
= IORegistryEntry::fromPath(cpath
);
2499 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2502 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2504 if (KERN_SUCCESS
!= err
) res
= err
;
2505 *registry_entry
= entry
;
2512 /* Routine io_registry_entry_in_plane */
2513 kern_return_t
is_io_registry_entry_in_plane(
2514 io_object_t registry_entry
,
2516 boolean_t
*inPlane
)
2518 CHECK( IORegistryEntry
, registry_entry
, entry
);
2520 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2522 return( kIOReturnSuccess
);
2526 /* Routine io_registry_entry_get_path */
2527 kern_return_t
is_io_registry_entry_get_path(
2528 io_object_t registry_entry
,
2533 CHECK( IORegistryEntry
, registry_entry
, entry
);
2535 length
= sizeof( io_string_t
);
2536 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2537 return( kIOReturnSuccess
);
2539 return( kIOReturnBadArgument
);
2542 /* Routine io_registry_entry_get_path */
2543 kern_return_t
is_io_registry_entry_get_path_ool(
2544 io_object_t registry_entry
,
2546 io_string_inband_t path
,
2547 io_buf_ptr_t
*path_ool
,
2548 mach_msg_type_number_t
*path_oolCnt
)
2550 enum { kMaxPath
= 16384 };
2555 CHECK( IORegistryEntry
, registry_entry
, entry
);
2559 length
= sizeof(io_string_inband_t
);
2560 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2564 buf
= IONew(char, length
);
2565 if (!buf
) err
= kIOReturnNoMemory
;
2566 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2569 *path_oolCnt
= length
;
2570 err
= copyoutkdata(buf
, length
, path_ool
);
2572 if (buf
) IODelete(buf
, char, kMaxPath
);
2579 /* Routine io_registry_entry_get_name */
2580 kern_return_t
is_io_registry_entry_get_name(
2581 io_object_t registry_entry
,
2584 CHECK( IORegistryEntry
, registry_entry
, entry
);
2586 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2588 return( kIOReturnSuccess
);
2591 /* Routine io_registry_entry_get_name_in_plane */
2592 kern_return_t
is_io_registry_entry_get_name_in_plane(
2593 io_object_t registry_entry
,
2594 io_name_t planeName
,
2597 const IORegistryPlane
* plane
;
2598 CHECK( IORegistryEntry
, registry_entry
, entry
);
2601 plane
= IORegistryEntry::getPlane( planeName
);
2605 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2607 return( kIOReturnSuccess
);
2610 /* Routine io_registry_entry_get_location_in_plane */
2611 kern_return_t
is_io_registry_entry_get_location_in_plane(
2612 io_object_t registry_entry
,
2613 io_name_t planeName
,
2614 io_name_t location
)
2616 const IORegistryPlane
* plane
;
2617 CHECK( IORegistryEntry
, registry_entry
, entry
);
2620 plane
= IORegistryEntry::getPlane( planeName
);
2624 const char * cstr
= entry
->getLocation( plane
);
2627 strncpy( location
, cstr
, sizeof( io_name_t
));
2628 return( kIOReturnSuccess
);
2630 return( kIOReturnNotFound
);
2633 /* Routine io_registry_entry_get_registry_entry_id */
2634 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2635 io_object_t registry_entry
,
2636 uint64_t *entry_id
)
2638 CHECK( IORegistryEntry
, registry_entry
, entry
);
2640 *entry_id
= entry
->getRegistryEntryID();
2642 return (kIOReturnSuccess
);
2645 /* Routine io_registry_entry_get_property */
2646 kern_return_t
is_io_registry_entry_get_property_bytes(
2647 io_object_t registry_entry
,
2648 io_name_t property_name
,
2649 io_struct_inband_t buf
,
2650 mach_msg_type_number_t
*dataCnt
)
2658 unsigned int len
= 0;
2659 const void * bytes
= 0;
2660 IOReturn ret
= kIOReturnSuccess
;
2662 CHECK( IORegistryEntry
, registry_entry
, entry
);
2665 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2666 return kIOReturnNotPermitted
;
2669 obj
= entry
->copyProperty(property_name
);
2671 return( kIOReturnNoResources
);
2673 // One day OSData will be a common container base class
2675 if( (data
= OSDynamicCast( OSData
, obj
))) {
2676 len
= data
->getLength();
2677 bytes
= data
->getBytesNoCopy();
2679 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2680 len
= str
->getLength() + 1;
2681 bytes
= str
->getCStringNoCopy();
2683 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2684 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2685 bytes
= boo
->isTrue() ? "Yes" : "No";
2687 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2688 offsetBytes
= off
->unsigned64BitValue();
2689 len
= off
->numberOfBytes();
2690 bytes
= &offsetBytes
;
2691 #ifdef __BIG_ENDIAN__
2692 bytes
= (const void *)
2693 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2697 ret
= kIOReturnBadArgument
;
2701 ret
= kIOReturnIPCError
;
2704 bcopy( bytes
, buf
, len
);
2713 /* Routine io_registry_entry_get_property */
2714 kern_return_t
is_io_registry_entry_get_property(
2715 io_object_t registry_entry
,
2716 io_name_t property_name
,
2717 io_buf_ptr_t
*properties
,
2718 mach_msg_type_number_t
*propertiesCnt
)
2724 CHECK( IORegistryEntry
, registry_entry
, entry
);
2727 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2728 return kIOReturnNotPermitted
;
2731 obj
= entry
->copyProperty(property_name
);
2733 return( kIOReturnNotFound
);
2735 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2738 return( kIOReturnNoMemory
);
2741 if( obj
->serialize( s
)) {
2742 len
= s
->getLength();
2743 *propertiesCnt
= len
;
2744 err
= copyoutkdata( s
->text(), len
, properties
);
2747 err
= kIOReturnUnsupported
;
2755 /* Routine io_registry_entry_get_property_recursively */
2756 kern_return_t
is_io_registry_entry_get_property_recursively(
2757 io_object_t registry_entry
,
2759 io_name_t property_name
,
2761 io_buf_ptr_t
*properties
,
2762 mach_msg_type_number_t
*propertiesCnt
)
2768 CHECK( IORegistryEntry
, registry_entry
, entry
);
2771 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2772 return kIOReturnNotPermitted
;
2775 obj
= entry
->copyProperty( property_name
,
2776 IORegistryEntry::getPlane( plane
), options
);
2778 return( kIOReturnNotFound
);
2780 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2783 return( kIOReturnNoMemory
);
2786 if( obj
->serialize( s
)) {
2787 len
= s
->getLength();
2788 *propertiesCnt
= len
;
2789 err
= copyoutkdata( s
->text(), len
, properties
);
2792 err
= kIOReturnUnsupported
;
2802 static kern_return_t
2803 filteredProperties(IORegistryEntry
*entry
, OSDictionary
*properties
, OSDictionary
**filteredp
)
2805 kern_return_t err
= 0;
2806 OSDictionary
*filtered
= NULL
;
2807 OSCollectionIterator
*iter
= NULL
;
2810 kauth_cred_t cred
= kauth_cred_get();
2812 if (properties
== NULL
)
2813 return kIOReturnUnsupported
;
2815 if ((iter
= OSCollectionIterator::withCollection(properties
)) == NULL
||
2816 (filtered
= OSDictionary::withCapacity(properties
->getCapacity())) == NULL
) {
2817 err
= kIOReturnNoMemory
;
2821 while ((p
= iter
->getNextObject()) != NULL
) {
2822 if ((key
= OSDynamicCast(OSSymbol
, p
)) == NULL
||
2823 mac_iokit_check_get_property(cred
, entry
, key
->getCStringNoCopy()) != 0)
2825 filtered
->setObject(key
, properties
->getObject(key
));
2831 *filteredp
= filtered
;
2837 /* Routine io_registry_entry_get_properties */
2838 kern_return_t
is_io_registry_entry_get_properties(
2839 io_object_t registry_entry
,
2840 io_buf_ptr_t
*properties
,
2841 mach_msg_type_number_t
*propertiesCnt
)
2843 kern_return_t err
= 0;
2846 CHECK( IORegistryEntry
, registry_entry
, entry
);
2848 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2850 return( kIOReturnNoMemory
);
2852 if (!entry
->serializeProperties(s
))
2853 err
= kIOReturnUnsupported
;
2856 if (!err
&& mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
2857 OSObject
*propobj
= OSUnserializeXML(s
->text(), s
->getLength());
2858 OSDictionary
*filteredprops
= NULL
;
2859 err
= filteredProperties(entry
, OSDynamicCast(OSDictionary
, propobj
), &filteredprops
);
2860 if (propobj
) propobj
->release();
2864 if (!filteredprops
->serialize(s
))
2865 err
= kIOReturnUnsupported
;
2867 if (filteredprops
!= NULL
)
2868 filteredprops
->release();
2870 #endif /* CONFIG_MACF */
2873 len
= s
->getLength();
2874 *propertiesCnt
= len
;
2875 err
= copyoutkdata( s
->text(), len
, properties
);
2884 struct GetPropertiesEditorRef
2887 IORegistryEntry
* entry
;
2888 OSCollection
* root
;
2891 static const OSMetaClassBase
*
2892 GetPropertiesEditor(void * reference
,
2894 OSCollection
* container
,
2895 const OSSymbol
* name
,
2896 const OSMetaClassBase
* value
)
2898 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
2900 if (!ref
->root
) ref
->root
= container
;
2901 if (ref
->root
== container
)
2903 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
2908 if (value
) value
->retain();
2912 #endif /* CONFIG_MACF */
2914 /* Routine io_registry_entry_get_properties */
2915 kern_return_t
is_io_registry_entry_get_properties_bin(
2916 io_object_t registry_entry
,
2917 io_buf_ptr_t
*properties
,
2918 mach_msg_type_number_t
*propertiesCnt
)
2920 kern_return_t err
= kIOReturnSuccess
;
2923 OSSerialize::Editor editor
= 0;
2926 CHECK(IORegistryEntry
, registry_entry
, entry
);
2929 GetPropertiesEditorRef ref
;
2930 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
2932 editor
= &GetPropertiesEditor
;
2934 ref
.cred
= kauth_cred_get();
2940 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
2941 if (!s
) return (kIOReturnNoMemory
);
2943 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
2945 if (kIOReturnSuccess
== err
)
2947 len
= s
->getLength();
2948 *propertiesCnt
= len
;
2949 err
= copyoutkdata(s
->text(), len
, properties
);
2956 /* Routine io_registry_entry_get_property_bin */
2957 kern_return_t
is_io_registry_entry_get_property_bin(
2958 io_object_t registry_entry
,
2960 io_name_t property_name
,
2962 io_buf_ptr_t
*properties
,
2963 mach_msg_type_number_t
*propertiesCnt
)
2968 const OSSymbol
* sym
;
2970 CHECK( IORegistryEntry
, registry_entry
, entry
);
2973 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2974 return kIOReturnNotPermitted
;
2977 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
2979 obj
= entry
->copyProperty(property_name
,
2980 IORegistryEntry::getPlane(plane
), options
);
2984 obj
= entry
->copyProperty(property_name
);
2988 return( kIOReturnNotFound
);
2990 sym
= OSSymbol::withCString(property_name
);
2993 if (gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
2997 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3000 return( kIOReturnNoMemory
);
3003 if( obj
->serialize( s
)) {
3004 len
= s
->getLength();
3005 *propertiesCnt
= len
;
3006 err
= copyoutkdata( s
->text(), len
, properties
);
3008 } else err
= kIOReturnUnsupported
;
3017 /* Routine io_registry_entry_set_properties */
3018 kern_return_t is_io_registry_entry_set_properties
3020 io_object_t registry_entry
,
3021 io_buf_ptr_t properties
,
3022 mach_msg_type_number_t propertiesCnt
,
3023 kern_return_t
* result
)
3029 vm_map_offset_t map_data
;
3031 CHECK( IORegistryEntry
, registry_entry
, entry
);
3033 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
3034 return( kIOReturnMessageTooLarge
);
3036 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3037 data
= CAST_DOWN(vm_offset_t
, map_data
);
3039 if( KERN_SUCCESS
== err
) {
3041 // must return success after vm_map_copyout() succeeds
3042 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3043 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3046 res
= kIOReturnBadArgument
;
3048 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3049 registry_entry
, obj
))
3051 res
= kIOReturnNotPermitted
;
3056 res
= entry
->setProperties( obj
);
3068 /* Routine io_registry_entry_get_child_iterator */
3069 kern_return_t
is_io_registry_entry_get_child_iterator(
3070 io_object_t registry_entry
,
3072 io_object_t
*iterator
)
3074 CHECK( IORegistryEntry
, registry_entry
, entry
);
3076 *iterator
= entry
->getChildIterator(
3077 IORegistryEntry::getPlane( plane
));
3079 return( kIOReturnSuccess
);
3082 /* Routine io_registry_entry_get_parent_iterator */
3083 kern_return_t
is_io_registry_entry_get_parent_iterator(
3084 io_object_t registry_entry
,
3086 io_object_t
*iterator
)
3088 CHECK( IORegistryEntry
, registry_entry
, entry
);
3090 *iterator
= entry
->getParentIterator(
3091 IORegistryEntry::getPlane( plane
));
3093 return( kIOReturnSuccess
);
3096 /* Routine io_service_get_busy_state */
3097 kern_return_t
is_io_service_get_busy_state(
3098 io_object_t _service
,
3099 uint32_t *busyState
)
3101 CHECK( IOService
, _service
, service
);
3103 *busyState
= service
->getBusyState();
3105 return( kIOReturnSuccess
);
3108 /* Routine io_service_get_state */
3109 kern_return_t
is_io_service_get_state(
3110 io_object_t _service
,
3112 uint32_t *busy_state
,
3113 uint64_t *accumulated_busy_time
)
3115 CHECK( IOService
, _service
, service
);
3117 *state
= service
->getState();
3118 *busy_state
= service
->getBusyState();
3119 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3121 return( kIOReturnSuccess
);
3124 /* Routine io_service_wait_quiet */
3125 kern_return_t
is_io_service_wait_quiet(
3126 io_object_t _service
,
3127 mach_timespec_t wait_time
)
3131 CHECK( IOService
, _service
, service
);
3133 timeoutNS
= wait_time
.tv_sec
;
3134 timeoutNS
*= kSecondScale
;
3135 timeoutNS
+= wait_time
.tv_nsec
;
3137 return( service
->waitQuiet(timeoutNS
) );
3140 /* Routine io_service_request_probe */
3141 kern_return_t
is_io_service_request_probe(
3142 io_object_t _service
,
3145 CHECK( IOService
, _service
, service
);
3147 return( service
->requestProbe( options
));
3150 /* Routine io_service_get_authorization_id */
3151 kern_return_t
is_io_service_get_authorization_id(
3152 io_object_t _service
,
3153 uint64_t *authorization_id
)
3157 CHECK( IOService
, _service
, service
);
3159 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3160 kIOClientPrivilegeAdministrator
);
3161 if( kIOReturnSuccess
!= kr
)
3164 *authorization_id
= service
->getAuthorizationID();
3169 /* Routine io_service_set_authorization_id */
3170 kern_return_t
is_io_service_set_authorization_id(
3171 io_object_t _service
,
3172 uint64_t authorization_id
)
3174 CHECK( IOService
, _service
, service
);
3176 return( service
->setAuthorizationID( authorization_id
) );
3179 /* Routine io_service_open_ndr */
3180 kern_return_t
is_io_service_open_extended(
3181 io_object_t _service
,
3183 uint32_t connect_type
,
3185 io_buf_ptr_t properties
,
3186 mach_msg_type_number_t propertiesCnt
,
3187 kern_return_t
* result
,
3188 io_object_t
*connection
)
3190 IOUserClient
* client
= 0;
3191 kern_return_t err
= KERN_SUCCESS
;
3192 IOReturn res
= kIOReturnSuccess
;
3193 OSDictionary
* propertiesDict
= 0;
3195 bool disallowAccess
;
3197 CHECK( IOService
, _service
, service
);
3199 if (!owningTask
) return (kIOReturnBadArgument
);
3207 vm_map_offset_t map_data
;
3209 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3210 return( kIOReturnMessageTooLarge
);
3212 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3214 data
= CAST_DOWN(vm_offset_t
, map_data
);
3215 if (KERN_SUCCESS
== err
)
3217 // must return success after vm_map_copyout() succeeds
3218 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3219 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3220 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3221 if (!propertiesDict
)
3223 res
= kIOReturnBadArgument
;
3228 if (kIOReturnSuccess
!= res
)
3232 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3235 if (!propertiesDict
)
3236 propertiesDict
= OSDictionary::withCapacity(4);
3237 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3241 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3246 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3247 connect_type
, propertiesDict
, &client
);
3250 propertiesDict
->release();
3252 if (res
== kIOReturnSuccess
)
3254 assert( OSDynamicCast(IOUserClient
, client
) );
3256 disallowAccess
= (crossEndian
3257 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3258 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3259 if (disallowAccess
) res
= kIOReturnUnsupported
;
3261 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3262 res
= kIOReturnNotPermitted
;
3264 if (kIOReturnSuccess
!= res
)
3266 IOStatisticsClientCall();
3267 client
->clientClose();
3272 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3273 client
->closed
= false;
3274 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3277 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3278 creatorName
->release();
3280 client
->setTerminateDefer(service
, false);
3285 *connection
= client
;
3291 /* Routine io_service_close */
3292 kern_return_t
is_io_service_close(
3293 io_object_t connection
)
3296 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3297 return( kIOReturnSuccess
);
3299 CHECK( IOUserClient
, connection
, client
);
3301 IOStatisticsClientCall();
3303 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
))
3305 client
->clientClose();
3309 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3310 client
->getRegistryEntryID(), client
->getName());
3313 return( kIOReturnSuccess
);
3316 /* Routine io_connect_get_service */
3317 kern_return_t
is_io_connect_get_service(
3318 io_object_t connection
,
3319 io_object_t
*service
)
3321 IOService
* theService
;
3323 CHECK( IOUserClient
, connection
, client
);
3325 theService
= client
->getService();
3327 theService
->retain();
3329 *service
= theService
;
3331 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3334 /* Routine io_connect_set_notification_port */
3335 kern_return_t
is_io_connect_set_notification_port(
3336 io_object_t connection
,
3337 uint32_t notification_type
,
3341 CHECK( IOUserClient
, connection
, client
);
3343 IOStatisticsClientCall();
3344 return( client
->registerNotificationPort( port
, notification_type
,
3345 (io_user_reference_t
) reference
));
3348 /* Routine io_connect_set_notification_port */
3349 kern_return_t
is_io_connect_set_notification_port_64(
3350 io_object_t connection
,
3351 uint32_t notification_type
,
3353 io_user_reference_t reference
)
3355 CHECK( IOUserClient
, connection
, client
);
3357 IOStatisticsClientCall();
3358 return( client
->registerNotificationPort( port
, notification_type
,
3362 /* Routine io_connect_map_memory_into_task */
3363 kern_return_t is_io_connect_map_memory_into_task
3365 io_connect_t connection
,
3366 uint32_t memory_type
,
3368 mach_vm_address_t
*address
,
3369 mach_vm_size_t
*size
,
3376 CHECK( IOUserClient
, connection
, client
);
3378 if (!into_task
) return (kIOReturnBadArgument
);
3380 IOStatisticsClientCall();
3381 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3384 *address
= map
->getAddress();
3386 *size
= map
->getSize();
3388 if( client
->sharedInstance
3389 || (into_task
!= current_task())) {
3390 // push a name out to the task owning the map,
3391 // so we can clean up maps
3392 mach_port_name_t name __unused
=
3393 IOMachPort::makeSendRightForTask(
3394 into_task
, map
, IKOT_IOKIT_OBJECT
);
3397 // keep it with the user client
3398 IOLockLock( gIOObjectPortLock
);
3399 if( 0 == client
->mappings
)
3400 client
->mappings
= OSSet::withCapacity(2);
3401 if( client
->mappings
)
3402 client
->mappings
->setObject( map
);
3403 IOLockUnlock( gIOObjectPortLock
);
3406 err
= kIOReturnSuccess
;
3409 err
= kIOReturnBadArgument
;
3414 /* Routine is_io_connect_map_memory */
3415 kern_return_t
is_io_connect_map_memory(
3416 io_object_t connect
,
3424 mach_vm_address_t address
;
3425 mach_vm_size_t size
;
3427 address
= SCALAR64(*mapAddr
);
3428 size
= SCALAR64(*mapSize
);
3430 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3432 *mapAddr
= SCALAR32(address
);
3433 *mapSize
= SCALAR32(size
);
3440 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3443 IOMemoryMap
* map
= 0;
3445 IOLockLock(gIOObjectPortLock
);
3447 iter
= OSCollectionIterator::withCollection(mappings
);
3450 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3452 if(mem
== map
->getMemoryDescriptor())
3455 mappings
->removeObject(map
);
3462 IOLockUnlock(gIOObjectPortLock
);
3469 /* Routine io_connect_unmap_memory_from_task */
3470 kern_return_t is_io_connect_unmap_memory_from_task
3472 io_connect_t connection
,
3473 uint32_t memory_type
,
3475 mach_vm_address_t address
)
3478 IOOptionBits options
= 0;
3479 IOMemoryDescriptor
* memory
;
3482 CHECK( IOUserClient
, connection
, client
);
3484 if (!from_task
) return (kIOReturnBadArgument
);
3486 IOStatisticsClientCall();
3487 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3489 if( memory
&& (kIOReturnSuccess
== err
)) {
3491 options
= (options
& ~kIOMapUserOptionsMask
)
3492 | kIOMapAnywhere
| kIOMapReference
;
3494 map
= memory
->createMappingInTask( from_task
, address
, options
);
3498 IOLockLock( gIOObjectPortLock
);
3499 if( client
->mappings
)
3500 client
->mappings
->removeObject( map
);
3501 IOLockUnlock( gIOObjectPortLock
);
3503 mach_port_name_t name
= 0;
3504 if (from_task
!= current_task())
3505 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3508 map
->userClientUnmap();
3509 err
= iokit_mod_send_right( from_task
, name
, -2 );
3510 err
= kIOReturnSuccess
;
3513 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3514 if (from_task
== current_task())
3518 err
= kIOReturnBadArgument
;
3524 kern_return_t
is_io_connect_unmap_memory(
3525 io_object_t connect
,
3531 mach_vm_address_t address
;
3533 address
= SCALAR64(mapAddr
);
3535 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3541 /* Routine io_connect_add_client */
3542 kern_return_t
is_io_connect_add_client(
3543 io_object_t connection
,
3544 io_object_t connect_to
)
3546 CHECK( IOUserClient
, connection
, client
);
3547 CHECK( IOUserClient
, connect_to
, to
);
3549 IOStatisticsClientCall();
3550 return( client
->connectClient( to
) );
3554 /* Routine io_connect_set_properties */
3555 kern_return_t
is_io_connect_set_properties(
3556 io_object_t connection
,
3557 io_buf_ptr_t properties
,
3558 mach_msg_type_number_t propertiesCnt
,
3559 kern_return_t
* result
)
3561 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3564 /* Routine io_user_client_method */
3565 kern_return_t is_io_connect_method_var_output
3567 io_connect_t connection
,
3569 io_scalar_inband64_t scalar_input
,
3570 mach_msg_type_number_t scalar_inputCnt
,
3571 io_struct_inband_t inband_input
,
3572 mach_msg_type_number_t inband_inputCnt
,
3573 mach_vm_address_t ool_input
,
3574 mach_vm_size_t ool_input_size
,
3575 io_struct_inband_t inband_output
,
3576 mach_msg_type_number_t
*inband_outputCnt
,
3577 io_scalar_inband64_t scalar_output
,
3578 mach_msg_type_number_t
*scalar_outputCnt
,
3579 io_buf_ptr_t
*var_output
,
3580 mach_msg_type_number_t
*var_outputCnt
3583 CHECK( IOUserClient
, connection
, client
);
3585 IOExternalMethodArguments args
;
3587 IOMemoryDescriptor
* inputMD
= 0;
3588 OSObject
* structureVariableOutputData
= 0;
3590 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3591 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3593 args
.selector
= selector
;
3595 args
.asyncWakePort
= MACH_PORT_NULL
;
3596 args
.asyncReference
= 0;
3597 args
.asyncReferenceCount
= 0;
3598 args
.structureVariableOutputData
= &structureVariableOutputData
;
3600 args
.scalarInput
= scalar_input
;
3601 args
.scalarInputCount
= scalar_inputCnt
;
3602 args
.structureInput
= inband_input
;
3603 args
.structureInputSize
= inband_inputCnt
;
3606 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3607 kIODirectionOut
, current_task());
3609 args
.structureInputDescriptor
= inputMD
;
3611 args
.scalarOutput
= scalar_output
;
3612 args
.scalarOutputCount
= *scalar_outputCnt
;
3613 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3614 args
.structureOutput
= inband_output
;
3615 args
.structureOutputSize
= *inband_outputCnt
;
3616 args
.structureOutputDescriptor
= NULL
;
3617 args
.structureOutputDescriptorSize
= 0;
3619 IOStatisticsClientCall();
3620 ret
= client
->externalMethod( selector
, &args
);
3622 *scalar_outputCnt
= args
.scalarOutputCount
;
3623 *inband_outputCnt
= args
.structureOutputSize
;
3625 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3627 OSSerialize
* serialize
;
3631 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3633 len
= serialize
->getLength();
3634 *var_outputCnt
= len
;
3635 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3637 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3639 len
= data
->getLength();
3640 *var_outputCnt
= len
;
3641 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3645 ret
= kIOReturnUnderrun
;
3651 if (structureVariableOutputData
)
3652 structureVariableOutputData
->release();
3657 /* Routine io_user_client_method */
3658 kern_return_t is_io_connect_method
3660 io_connect_t connection
,
3662 io_scalar_inband64_t scalar_input
,
3663 mach_msg_type_number_t scalar_inputCnt
,
3664 io_struct_inband_t inband_input
,
3665 mach_msg_type_number_t inband_inputCnt
,
3666 mach_vm_address_t ool_input
,
3667 mach_vm_size_t ool_input_size
,
3668 io_struct_inband_t inband_output
,
3669 mach_msg_type_number_t
*inband_outputCnt
,
3670 io_scalar_inband64_t scalar_output
,
3671 mach_msg_type_number_t
*scalar_outputCnt
,
3672 mach_vm_address_t ool_output
,
3673 mach_vm_size_t
*ool_output_size
3676 CHECK( IOUserClient
, connection
, client
);
3678 IOExternalMethodArguments args
;
3680 IOMemoryDescriptor
* inputMD
= 0;
3681 IOMemoryDescriptor
* outputMD
= 0;
3683 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3684 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3686 args
.selector
= selector
;
3688 args
.asyncWakePort
= MACH_PORT_NULL
;
3689 args
.asyncReference
= 0;
3690 args
.asyncReferenceCount
= 0;
3691 args
.structureVariableOutputData
= 0;
3693 args
.scalarInput
= scalar_input
;
3694 args
.scalarInputCount
= scalar_inputCnt
;
3695 args
.structureInput
= inband_input
;
3696 args
.structureInputSize
= inband_inputCnt
;
3699 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3700 kIODirectionOut
, current_task());
3702 args
.structureInputDescriptor
= inputMD
;
3704 args
.scalarOutput
= scalar_output
;
3705 args
.scalarOutputCount
= *scalar_outputCnt
;
3706 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3707 args
.structureOutput
= inband_output
;
3708 args
.structureOutputSize
= *inband_outputCnt
;
3710 if (ool_output
&& ool_output_size
)
3712 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3713 kIODirectionIn
, current_task());
3716 args
.structureOutputDescriptor
= outputMD
;
3717 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3719 IOStatisticsClientCall();
3720 ret
= client
->externalMethod( selector
, &args
);
3722 *scalar_outputCnt
= args
.scalarOutputCount
;
3723 *inband_outputCnt
= args
.structureOutputSize
;
3724 *ool_output_size
= args
.structureOutputDescriptorSize
;
3729 outputMD
->release();
3734 /* Routine io_async_user_client_method */
3735 kern_return_t is_io_connect_async_method
3737 io_connect_t connection
,
3738 mach_port_t wake_port
,
3739 io_async_ref64_t reference
,
3740 mach_msg_type_number_t referenceCnt
,
3742 io_scalar_inband64_t scalar_input
,
3743 mach_msg_type_number_t scalar_inputCnt
,
3744 io_struct_inband_t inband_input
,
3745 mach_msg_type_number_t inband_inputCnt
,
3746 mach_vm_address_t ool_input
,
3747 mach_vm_size_t ool_input_size
,
3748 io_struct_inband_t inband_output
,
3749 mach_msg_type_number_t
*inband_outputCnt
,
3750 io_scalar_inband64_t scalar_output
,
3751 mach_msg_type_number_t
*scalar_outputCnt
,
3752 mach_vm_address_t ool_output
,
3753 mach_vm_size_t
* ool_output_size
3756 CHECK( IOUserClient
, connection
, client
);
3758 IOExternalMethodArguments args
;
3760 IOMemoryDescriptor
* inputMD
= 0;
3761 IOMemoryDescriptor
* outputMD
= 0;
3763 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3764 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3766 reference
[0] = (io_user_reference_t
) wake_port
;
3767 if (vm_map_is_64bit(get_task_map(current_task())))
3768 reference
[0] |= kIOUCAsync64Flag
;
3770 args
.selector
= selector
;
3772 args
.asyncWakePort
= wake_port
;
3773 args
.asyncReference
= reference
;
3774 args
.asyncReferenceCount
= referenceCnt
;
3776 args
.scalarInput
= scalar_input
;
3777 args
.scalarInputCount
= scalar_inputCnt
;
3778 args
.structureInput
= inband_input
;
3779 args
.structureInputSize
= inband_inputCnt
;
3782 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3783 kIODirectionOut
, current_task());
3785 args
.structureInputDescriptor
= inputMD
;
3787 args
.scalarOutput
= scalar_output
;
3788 args
.scalarOutputCount
= *scalar_outputCnt
;
3789 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3790 args
.structureOutput
= inband_output
;
3791 args
.structureOutputSize
= *inband_outputCnt
;
3795 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3796 kIODirectionIn
, current_task());
3799 args
.structureOutputDescriptor
= outputMD
;
3800 args
.structureOutputDescriptorSize
= *ool_output_size
;
3802 IOStatisticsClientCall();
3803 ret
= client
->externalMethod( selector
, &args
);
3805 *inband_outputCnt
= args
.structureOutputSize
;
3806 *ool_output_size
= args
.structureOutputDescriptorSize
;
3811 outputMD
->release();
3816 /* Routine io_connect_method_scalarI_scalarO */
3817 kern_return_t
is_io_connect_method_scalarI_scalarO(
3818 io_object_t connect
,
3820 io_scalar_inband_t input
,
3821 mach_msg_type_number_t inputCount
,
3822 io_scalar_inband_t output
,
3823 mach_msg_type_number_t
* outputCount
)
3827 io_scalar_inband64_t _input
;
3828 io_scalar_inband64_t _output
;
3830 mach_msg_type_number_t struct_outputCnt
= 0;
3831 mach_vm_size_t ool_output_size
= 0;
3833 bzero(&_output
[0], sizeof(_output
));
3834 for (i
= 0; i
< inputCount
; i
++)
3835 _input
[i
] = SCALAR64(input
[i
]);
3837 err
= is_io_connect_method(connect
, index
,
3841 NULL
, &struct_outputCnt
,
3842 _output
, outputCount
,
3843 0, &ool_output_size
);
3845 for (i
= 0; i
< *outputCount
; i
++)
3846 output
[i
] = SCALAR32(_output
[i
]);
3851 kern_return_t
shim_io_connect_method_scalarI_scalarO(
3852 IOExternalMethod
* method
,
3854 const io_user_scalar_t
* input
,
3855 mach_msg_type_number_t inputCount
,
3856 io_user_scalar_t
* output
,
3857 mach_msg_type_number_t
* outputCount
)
3860 io_scalar_inband_t _output
;
3862 err
= kIOReturnBadArgument
;
3864 bzero(&_output
[0], sizeof(_output
));
3867 if( inputCount
!= method
->count0
)
3869 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
3872 if( *outputCount
!= method
->count1
)
3874 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
3878 func
= method
->func
;
3880 switch( inputCount
) {
3883 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3884 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
3887 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3888 ARG32(input
[3]), ARG32(input
[4]),
3892 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3894 &_output
[0], &_output
[1] );
3897 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
3898 &_output
[0], &_output
[1], &_output
[2] );
3901 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
3902 &_output
[0], &_output
[1], &_output
[2],
3906 err
= (object
->*func
)( ARG32(input
[0]),
3907 &_output
[0], &_output
[1], &_output
[2],
3908 &_output
[3], &_output
[4] );
3911 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
3912 &_output
[3], &_output
[4], &_output
[5] );
3916 IOLog("%s: Bad method table\n", object
->getName());
3922 for (i
= 0; i
< *outputCount
; i
++)
3923 output
[i
] = SCALAR32(_output
[i
]);
3928 /* Routine io_async_method_scalarI_scalarO */
3929 kern_return_t
is_io_async_method_scalarI_scalarO(
3930 io_object_t connect
,
3931 mach_port_t wake_port
,
3932 io_async_ref_t reference
,
3933 mach_msg_type_number_t referenceCnt
,
3935 io_scalar_inband_t input
,
3936 mach_msg_type_number_t inputCount
,
3937 io_scalar_inband_t output
,
3938 mach_msg_type_number_t
* outputCount
)
3942 io_scalar_inband64_t _input
;
3943 io_scalar_inband64_t _output
;
3944 io_async_ref64_t _reference
;
3946 bzero(&_output
[0], sizeof(_output
));
3947 for (i
= 0; i
< referenceCnt
; i
++)
3948 _reference
[i
] = REF64(reference
[i
]);
3950 mach_msg_type_number_t struct_outputCnt
= 0;
3951 mach_vm_size_t ool_output_size
= 0;
3953 for (i
= 0; i
< inputCount
; i
++)
3954 _input
[i
] = SCALAR64(input
[i
]);
3956 err
= is_io_connect_async_method(connect
,
3957 wake_port
, _reference
, referenceCnt
,
3962 NULL
, &struct_outputCnt
,
3963 _output
, outputCount
,
3964 0, &ool_output_size
);
3966 for (i
= 0; i
< *outputCount
; i
++)
3967 output
[i
] = SCALAR32(_output
[i
]);
3971 /* Routine io_async_method_scalarI_structureO */
3972 kern_return_t
is_io_async_method_scalarI_structureO(
3973 io_object_t connect
,
3974 mach_port_t wake_port
,
3975 io_async_ref_t reference
,
3976 mach_msg_type_number_t referenceCnt
,
3978 io_scalar_inband_t input
,
3979 mach_msg_type_number_t inputCount
,
3980 io_struct_inband_t output
,
3981 mach_msg_type_number_t
* outputCount
)
3984 io_scalar_inband64_t _input
;
3985 io_async_ref64_t _reference
;
3987 for (i
= 0; i
< referenceCnt
; i
++)
3988 _reference
[i
] = REF64(reference
[i
]);
3990 mach_msg_type_number_t scalar_outputCnt
= 0;
3991 mach_vm_size_t ool_output_size
= 0;
3993 for (i
= 0; i
< inputCount
; i
++)
3994 _input
[i
] = SCALAR64(input
[i
]);
3996 return (is_io_connect_async_method(connect
,
3997 wake_port
, _reference
, referenceCnt
,
4002 output
, outputCount
,
4003 NULL
, &scalar_outputCnt
,
4004 0, &ool_output_size
));
4007 /* Routine io_async_method_scalarI_structureI */
4008 kern_return_t
is_io_async_method_scalarI_structureI(
4009 io_connect_t connect
,
4010 mach_port_t wake_port
,
4011 io_async_ref_t reference
,
4012 mach_msg_type_number_t referenceCnt
,
4014 io_scalar_inband_t input
,
4015 mach_msg_type_number_t inputCount
,
4016 io_struct_inband_t inputStruct
,
4017 mach_msg_type_number_t inputStructCount
)
4020 io_scalar_inband64_t _input
;
4021 io_async_ref64_t _reference
;
4023 for (i
= 0; i
< referenceCnt
; i
++)
4024 _reference
[i
] = REF64(reference
[i
]);
4026 mach_msg_type_number_t scalar_outputCnt
= 0;
4027 mach_msg_type_number_t inband_outputCnt
= 0;
4028 mach_vm_size_t ool_output_size
= 0;
4030 for (i
= 0; i
< inputCount
; i
++)
4031 _input
[i
] = SCALAR64(input
[i
]);
4033 return (is_io_connect_async_method(connect
,
4034 wake_port
, _reference
, referenceCnt
,
4037 inputStruct
, inputStructCount
,
4039 NULL
, &inband_outputCnt
,
4040 NULL
, &scalar_outputCnt
,
4041 0, &ool_output_size
));
4044 /* Routine io_async_method_structureI_structureO */
4045 kern_return_t
is_io_async_method_structureI_structureO(
4046 io_object_t connect
,
4047 mach_port_t wake_port
,
4048 io_async_ref_t reference
,
4049 mach_msg_type_number_t referenceCnt
,
4051 io_struct_inband_t input
,
4052 mach_msg_type_number_t inputCount
,
4053 io_struct_inband_t output
,
4054 mach_msg_type_number_t
* outputCount
)
4057 mach_msg_type_number_t scalar_outputCnt
= 0;
4058 mach_vm_size_t ool_output_size
= 0;
4059 io_async_ref64_t _reference
;
4061 for (i
= 0; i
< referenceCnt
; i
++)
4062 _reference
[i
] = REF64(reference
[i
]);
4064 return (is_io_connect_async_method(connect
,
4065 wake_port
, _reference
, referenceCnt
,
4070 output
, outputCount
,
4071 NULL
, &scalar_outputCnt
,
4072 0, &ool_output_size
));
4076 kern_return_t
shim_io_async_method_scalarI_scalarO(
4077 IOExternalAsyncMethod
* method
,
4079 mach_port_t asyncWakePort
,
4080 io_user_reference_t
* asyncReference
,
4081 uint32_t asyncReferenceCount
,
4082 const io_user_scalar_t
* input
,
4083 mach_msg_type_number_t inputCount
,
4084 io_user_scalar_t
* output
,
4085 mach_msg_type_number_t
* outputCount
)
4089 io_scalar_inband_t _output
;
4091 io_async_ref_t reference
;
4093 bzero(&_output
[0], sizeof(_output
));
4094 for (i
= 0; i
< asyncReferenceCount
; i
++)
4095 reference
[i
] = REF32(asyncReference
[i
]);
4097 err
= kIOReturnBadArgument
;
4101 if( inputCount
!= method
->count0
)
4103 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4106 if( *outputCount
!= method
->count1
)
4108 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4112 func
= method
->func
;
4114 switch( inputCount
) {
4117 err
= (object
->*func
)( reference
,
4118 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4119 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4122 err
= (object
->*func
)( reference
,
4123 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4124 ARG32(input
[3]), ARG32(input
[4]),
4128 err
= (object
->*func
)( reference
,
4129 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4131 &_output
[0], &_output
[1] );
4134 err
= (object
->*func
)( reference
,
4135 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4136 &_output
[0], &_output
[1], &_output
[2] );
4139 err
= (object
->*func
)( reference
,
4140 ARG32(input
[0]), ARG32(input
[1]),
4141 &_output
[0], &_output
[1], &_output
[2],
4145 err
= (object
->*func
)( reference
,
4147 &_output
[0], &_output
[1], &_output
[2],
4148 &_output
[3], &_output
[4] );
4151 err
= (object
->*func
)( reference
,
4152 &_output
[0], &_output
[1], &_output
[2],
4153 &_output
[3], &_output
[4], &_output
[5] );
4157 IOLog("%s: Bad method table\n", object
->getName());
4162 for (i
= 0; i
< *outputCount
; i
++)
4163 output
[i
] = SCALAR32(_output
[i
]);
4169 /* Routine io_connect_method_scalarI_structureO */
4170 kern_return_t
is_io_connect_method_scalarI_structureO(
4171 io_object_t connect
,
4173 io_scalar_inband_t input
,
4174 mach_msg_type_number_t inputCount
,
4175 io_struct_inband_t output
,
4176 mach_msg_type_number_t
* outputCount
)
4179 io_scalar_inband64_t _input
;
4181 mach_msg_type_number_t scalar_outputCnt
= 0;
4182 mach_vm_size_t ool_output_size
= 0;
4184 for (i
= 0; i
< inputCount
; i
++)
4185 _input
[i
] = SCALAR64(input
[i
]);
4187 return (is_io_connect_method(connect
, index
,
4191 output
, outputCount
,
4192 NULL
, &scalar_outputCnt
,
4193 0, &ool_output_size
));
4196 kern_return_t
shim_io_connect_method_scalarI_structureO(
4198 IOExternalMethod
* method
,
4200 const io_user_scalar_t
* input
,
4201 mach_msg_type_number_t inputCount
,
4202 io_struct_inband_t output
,
4203 IOByteCount
* outputCount
)
4208 err
= kIOReturnBadArgument
;
4211 if( inputCount
!= method
->count0
)
4213 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4216 if( (kIOUCVariableStructureSize
!= method
->count1
)
4217 && (*outputCount
!= method
->count1
))
4219 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4223 func
= method
->func
;
4225 switch( inputCount
) {
4228 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4229 ARG32(input
[3]), ARG32(input
[4]),
4233 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4235 output
, (void *)outputCount
);
4238 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4239 output
, (void *)outputCount
, 0 );
4242 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4243 output
, (void *)outputCount
, 0, 0 );
4246 err
= (object
->*func
)( ARG32(input
[0]),
4247 output
, (void *)outputCount
, 0, 0, 0 );
4250 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4254 IOLog("%s: Bad method table\n", object
->getName());
4263 kern_return_t
shim_io_async_method_scalarI_structureO(
4264 IOExternalAsyncMethod
* method
,
4266 mach_port_t asyncWakePort
,
4267 io_user_reference_t
* asyncReference
,
4268 uint32_t asyncReferenceCount
,
4269 const io_user_scalar_t
* input
,
4270 mach_msg_type_number_t inputCount
,
4271 io_struct_inband_t output
,
4272 mach_msg_type_number_t
* outputCount
)
4277 io_async_ref_t reference
;
4279 for (i
= 0; i
< asyncReferenceCount
; i
++)
4280 reference
[i
] = REF32(asyncReference
[i
]);
4282 err
= kIOReturnBadArgument
;
4284 if( inputCount
!= method
->count0
)
4286 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4289 if( (kIOUCVariableStructureSize
!= method
->count1
)
4290 && (*outputCount
!= method
->count1
))
4292 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4296 func
= method
->func
;
4298 switch( inputCount
) {
4301 err
= (object
->*func
)( reference
,
4302 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4303 ARG32(input
[3]), ARG32(input
[4]),
4307 err
= (object
->*func
)( reference
,
4308 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4310 output
, (void *)outputCount
);
4313 err
= (object
->*func
)( reference
,
4314 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4315 output
, (void *)outputCount
, 0 );
4318 err
= (object
->*func
)( reference
,
4319 ARG32(input
[0]), ARG32(input
[1]),
4320 output
, (void *)outputCount
, 0, 0 );
4323 err
= (object
->*func
)( reference
,
4325 output
, (void *)outputCount
, 0, 0, 0 );
4328 err
= (object
->*func
)( reference
,
4329 output
, (void *)outputCount
, 0, 0, 0, 0 );
4333 IOLog("%s: Bad method table\n", object
->getName());
4341 /* Routine io_connect_method_scalarI_structureI */
4342 kern_return_t
is_io_connect_method_scalarI_structureI(
4343 io_connect_t connect
,
4345 io_scalar_inband_t input
,
4346 mach_msg_type_number_t inputCount
,
4347 io_struct_inband_t inputStruct
,
4348 mach_msg_type_number_t inputStructCount
)
4351 io_scalar_inband64_t _input
;
4353 mach_msg_type_number_t scalar_outputCnt
= 0;
4354 mach_msg_type_number_t inband_outputCnt
= 0;
4355 mach_vm_size_t ool_output_size
= 0;
4357 for (i
= 0; i
< inputCount
; i
++)
4358 _input
[i
] = SCALAR64(input
[i
]);
4360 return (is_io_connect_method(connect
, index
,
4362 inputStruct
, inputStructCount
,
4364 NULL
, &inband_outputCnt
,
4365 NULL
, &scalar_outputCnt
,
4366 0, &ool_output_size
));
4369 kern_return_t
shim_io_connect_method_scalarI_structureI(
4370 IOExternalMethod
* method
,
4372 const io_user_scalar_t
* input
,
4373 mach_msg_type_number_t inputCount
,
4374 io_struct_inband_t inputStruct
,
4375 mach_msg_type_number_t inputStructCount
)
4378 IOReturn err
= kIOReturnBadArgument
;
4382 if (inputCount
!= method
->count0
)
4384 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4387 if( (kIOUCVariableStructureSize
!= method
->count1
)
4388 && (inputStructCount
!= method
->count1
))
4390 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4394 func
= method
->func
;
4396 switch( inputCount
) {
4399 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4400 ARG32(input
[3]), ARG32(input
[4]),
4404 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4406 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4409 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4410 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4414 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4415 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4419 err
= (object
->*func
)( ARG32(input
[0]),
4420 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4424 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4429 IOLog("%s: Bad method table\n", object
->getName());
4437 kern_return_t
shim_io_async_method_scalarI_structureI(
4438 IOExternalAsyncMethod
* method
,
4440 mach_port_t asyncWakePort
,
4441 io_user_reference_t
* asyncReference
,
4442 uint32_t asyncReferenceCount
,
4443 const io_user_scalar_t
* input
,
4444 mach_msg_type_number_t inputCount
,
4445 io_struct_inband_t inputStruct
,
4446 mach_msg_type_number_t inputStructCount
)
4450 IOReturn err
= kIOReturnBadArgument
;
4451 io_async_ref_t reference
;
4453 for (i
= 0; i
< asyncReferenceCount
; i
++)
4454 reference
[i
] = REF32(asyncReference
[i
]);
4458 if (inputCount
!= method
->count0
)
4460 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4463 if( (kIOUCVariableStructureSize
!= method
->count1
)
4464 && (inputStructCount
!= method
->count1
))
4466 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4470 func
= method
->func
;
4472 switch( inputCount
) {
4475 err
= (object
->*func
)( reference
,
4476 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4477 ARG32(input
[3]), ARG32(input
[4]),
4481 err
= (object
->*func
)( reference
,
4482 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4484 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4487 err
= (object
->*func
)( reference
,
4488 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4489 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4493 err
= (object
->*func
)( reference
,
4494 ARG32(input
[0]), ARG32(input
[1]),
4495 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4499 err
= (object
->*func
)( reference
,
4501 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4505 err
= (object
->*func
)( reference
,
4506 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4511 IOLog("%s: Bad method table\n", object
->getName());
4519 /* Routine io_connect_method_structureI_structureO */
4520 kern_return_t
is_io_connect_method_structureI_structureO(
4521 io_object_t connect
,
4523 io_struct_inband_t input
,
4524 mach_msg_type_number_t inputCount
,
4525 io_struct_inband_t output
,
4526 mach_msg_type_number_t
* outputCount
)
4528 mach_msg_type_number_t scalar_outputCnt
= 0;
4529 mach_vm_size_t ool_output_size
= 0;
4531 return (is_io_connect_method(connect
, index
,
4535 output
, outputCount
,
4536 NULL
, &scalar_outputCnt
,
4537 0, &ool_output_size
));
4540 kern_return_t
shim_io_connect_method_structureI_structureO(
4541 IOExternalMethod
* method
,
4543 io_struct_inband_t input
,
4544 mach_msg_type_number_t inputCount
,
4545 io_struct_inband_t output
,
4546 IOByteCount
* outputCount
)
4549 IOReturn err
= kIOReturnBadArgument
;
4553 if( (kIOUCVariableStructureSize
!= method
->count0
)
4554 && (inputCount
!= method
->count0
))
4556 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4559 if( (kIOUCVariableStructureSize
!= method
->count1
)
4560 && (*outputCount
!= method
->count1
))
4562 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4566 func
= method
->func
;
4568 if( method
->count1
) {
4569 if( method
->count0
) {
4570 err
= (object
->*func
)( input
, output
,
4571 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4573 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4576 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4585 kern_return_t
shim_io_async_method_structureI_structureO(
4586 IOExternalAsyncMethod
* method
,
4588 mach_port_t asyncWakePort
,
4589 io_user_reference_t
* asyncReference
,
4590 uint32_t asyncReferenceCount
,
4591 io_struct_inband_t input
,
4592 mach_msg_type_number_t inputCount
,
4593 io_struct_inband_t output
,
4594 mach_msg_type_number_t
* outputCount
)
4599 io_async_ref_t reference
;
4601 for (i
= 0; i
< asyncReferenceCount
; i
++)
4602 reference
[i
] = REF32(asyncReference
[i
]);
4604 err
= kIOReturnBadArgument
;
4607 if( (kIOUCVariableStructureSize
!= method
->count0
)
4608 && (inputCount
!= method
->count0
))
4610 IOLog("%s: IOUserClient inputCount count mismatch\n", object
->getName());
4613 if( (kIOUCVariableStructureSize
!= method
->count1
)
4614 && (*outputCount
!= method
->count1
))
4616 IOLog("%s: IOUserClient outputCount count mismatch\n", object
->getName());
4620 func
= method
->func
;
4622 if( method
->count1
) {
4623 if( method
->count0
) {
4624 err
= (object
->*func
)( reference
,
4626 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4628 err
= (object
->*func
)( reference
,
4629 output
, outputCount
, 0, 0, 0, 0 );
4632 err
= (object
->*func
)( reference
,
4633 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4641 /* Routine io_catalog_send_data */
4642 kern_return_t
is_io_catalog_send_data(
4643 mach_port_t master_port
,
4645 io_buf_ptr_t inData
,
4646 mach_msg_type_number_t inDataCount
,
4647 kern_return_t
* result
)
4651 kern_return_t kr
= kIOReturnError
;
4653 //printf("io_catalog_send_data called. flag: %d\n", flag);
4655 if( master_port
!= master_device_port
)
4656 return kIOReturnNotPrivileged
;
4658 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4659 flag
!= kIOCatalogKextdActive
&&
4660 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4661 ( !inData
|| !inDataCount
) )
4663 return kIOReturnBadArgument
;
4667 vm_map_offset_t map_data
;
4669 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4670 return( kIOReturnMessageTooLarge
);
4672 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4673 data
= CAST_DOWN(vm_offset_t
, map_data
);
4675 if( kr
!= KERN_SUCCESS
)
4678 // must return success after vm_map_copyout() succeeds
4681 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4682 vm_deallocate( kernel_map
, data
, inDataCount
);
4684 *result
= kIOReturnNoMemory
;
4685 return( KERN_SUCCESS
);
4691 case kIOCatalogResetDrivers
:
4692 case kIOCatalogResetDriversNoMatch
: {
4695 array
= OSDynamicCast(OSArray
, obj
);
4697 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4698 flag
== kIOCatalogResetDrivers
) ) {
4700 kr
= kIOReturnError
;
4703 kr
= kIOReturnBadArgument
;
4708 case kIOCatalogAddDrivers
:
4709 case kIOCatalogAddDriversNoMatch
: {
4712 array
= OSDynamicCast(OSArray
, obj
);
4714 if ( !gIOCatalogue
->addDrivers( array
,
4715 flag
== kIOCatalogAddDrivers
) ) {
4716 kr
= kIOReturnError
;
4720 kr
= kIOReturnBadArgument
;
4725 case kIOCatalogRemoveDrivers
:
4726 case kIOCatalogRemoveDriversNoMatch
: {
4727 OSDictionary
* dict
;
4729 dict
= OSDynamicCast(OSDictionary
, obj
);
4731 if ( !gIOCatalogue
->removeDrivers( dict
,
4732 flag
== kIOCatalogRemoveDrivers
) ) {
4733 kr
= kIOReturnError
;
4737 kr
= kIOReturnBadArgument
;
4742 case kIOCatalogStartMatching
: {
4743 OSDictionary
* dict
;
4745 dict
= OSDynamicCast(OSDictionary
, obj
);
4747 if ( !gIOCatalogue
->startMatching( dict
) ) {
4748 kr
= kIOReturnError
;
4752 kr
= kIOReturnBadArgument
;
4757 case kIOCatalogRemoveKernelLinker
:
4758 kr
= KERN_NOT_SUPPORTED
;
4761 case kIOCatalogKextdActive
:
4763 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
4764 OSKext::setKextdActive();
4766 /* Dump all nonloaded startup extensions; kextd will now send them
4769 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4771 kr
= kIOReturnSuccess
;
4774 case kIOCatalogKextdFinishedLaunching
: {
4776 static bool clearedBusy
= false;
4779 IOService
* serviceRoot
= IOService::getServiceRoot();
4781 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
4782 serviceRoot
->adjustBusy(-1);
4787 kr
= kIOReturnSuccess
;
4792 kr
= kIOReturnBadArgument
;
4796 if (obj
) obj
->release();
4799 return( KERN_SUCCESS
);
4802 /* Routine io_catalog_terminate */
4803 kern_return_t
is_io_catalog_terminate(
4804 mach_port_t master_port
,
4810 if( master_port
!= master_device_port
)
4811 return kIOReturnNotPrivileged
;
4813 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
4814 kIOClientPrivilegeAdministrator
);
4815 if( kIOReturnSuccess
!= kr
)
4819 #if !defined(SECURE_KERNEL)
4820 case kIOCatalogServiceTerminate
:
4822 IOService
* service
;
4824 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
4825 kIORegistryIterateRecursively
);
4827 return kIOReturnNoMemory
;
4831 while( (service
= (IOService
*)iter
->getNextObject()) ) {
4832 if( service
->metaCast(name
)) {
4833 if ( !service
->terminate( kIOServiceRequired
4834 | kIOServiceSynchronous
) ) {
4835 kr
= kIOReturnUnsupported
;
4840 } while( !service
&& !iter
->isValid());
4844 case kIOCatalogModuleUnload
:
4845 case kIOCatalogModuleTerminate
:
4846 kr
= gIOCatalogue
->terminateDriversForModule(name
,
4847 flag
== kIOCatalogModuleUnload
);
4852 kr
= kIOReturnBadArgument
;
4859 /* Routine io_catalog_get_data */
4860 kern_return_t
is_io_catalog_get_data(
4861 mach_port_t master_port
,
4863 io_buf_ptr_t
*outData
,
4864 mach_msg_type_number_t
*outDataCount
)
4866 kern_return_t kr
= kIOReturnSuccess
;
4869 if( master_port
!= master_device_port
)
4870 return kIOReturnNotPrivileged
;
4872 //printf("io_catalog_get_data called. flag: %d\n", flag);
4874 s
= OSSerialize::withCapacity(4096);
4876 return kIOReturnNoMemory
;
4878 kr
= gIOCatalogue
->serializeData(flag
, s
);
4880 if ( kr
== kIOReturnSuccess
) {
4885 size
= s
->getLength();
4886 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
4887 if ( kr
== kIOReturnSuccess
) {
4888 bcopy(s
->text(), (void *)data
, size
);
4889 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
4890 (vm_map_size_t
)size
, true, ©
);
4891 *outData
= (char *)copy
;
4892 *outDataCount
= size
;
4901 /* Routine io_catalog_get_gen_count */
4902 kern_return_t
is_io_catalog_get_gen_count(
4903 mach_port_t master_port
,
4906 if( master_port
!= master_device_port
)
4907 return kIOReturnNotPrivileged
;
4909 //printf("io_catalog_get_gen_count called.\n");
4912 return kIOReturnBadArgument
;
4914 *genCount
= gIOCatalogue
->getGenerationCount();
4916 return kIOReturnSuccess
;
4919 /* Routine io_catalog_module_loaded.
4920 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
4922 kern_return_t
is_io_catalog_module_loaded(
4923 mach_port_t master_port
,
4926 if( master_port
!= master_device_port
)
4927 return kIOReturnNotPrivileged
;
4929 //printf("io_catalog_module_loaded called. name %s\n", name);
4932 return kIOReturnBadArgument
;
4934 gIOCatalogue
->moduleHasLoaded(name
);
4936 return kIOReturnSuccess
;
4939 kern_return_t
is_io_catalog_reset(
4940 mach_port_t master_port
,
4943 if( master_port
!= master_device_port
)
4944 return kIOReturnNotPrivileged
;
4947 case kIOCatalogResetDefault
:
4948 gIOCatalogue
->reset();
4952 return kIOReturnBadArgument
;
4955 return kIOReturnSuccess
;
4958 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
4960 kern_return_t result
= kIOReturnBadArgument
;
4961 IOUserClient
*userClient
;
4963 if ((userClient
= OSDynamicCast(IOUserClient
,
4964 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
4965 IOExternalTrap
*trap
;
4966 IOService
*target
= NULL
;
4968 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
4970 if (trap
&& target
) {
4976 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
4980 userClient
->release();
4988 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
4989 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
4993 IOByteCount structureOutputSize
;
4998 count
= dispatch
->checkScalarInputCount
;
4999 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
5001 return (kIOReturnBadArgument
);
5004 count
= dispatch
->checkStructureInputSize
;
5005 if ((kIOUCVariableStructureSize
!= count
)
5006 && (count
!= ((args
->structureInputDescriptor
)
5007 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
5009 return (kIOReturnBadArgument
);
5012 count
= dispatch
->checkScalarOutputCount
;
5013 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
5015 return (kIOReturnBadArgument
);
5018 count
= dispatch
->checkStructureOutputSize
;
5019 if ((kIOUCVariableStructureSize
!= count
)
5020 && (count
!= ((args
->structureOutputDescriptor
)
5021 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
5023 return (kIOReturnBadArgument
);
5026 if (dispatch
->function
)
5027 err
= (*dispatch
->function
)(target
, reference
, args
);
5029 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5035 // pre-Leopard API's don't do ool structs
5036 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
5038 err
= kIOReturnIPCError
;
5042 structureOutputSize
= args
->structureOutputSize
;
5044 if (args
->asyncWakePort
)
5046 IOExternalAsyncMethod
* method
;
5048 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
5049 return (kIOReturnUnsupported
);
5051 if (kIOUCForegroundOnly
& method
->flags
)
5053 if (task_is_gpu_denied(current_task()))
5054 return (kIOReturnNotPermitted
);
5057 switch (method
->flags
& kIOUCTypeMask
)
5059 case kIOUCScalarIStructI
:
5060 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5061 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5062 args
->scalarInput
, args
->scalarInputCount
,
5063 (char *)args
->structureInput
, args
->structureInputSize
);
5066 case kIOUCScalarIScalarO
:
5067 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5068 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5069 args
->scalarInput
, args
->scalarInputCount
,
5070 args
->scalarOutput
, &args
->scalarOutputCount
);
5073 case kIOUCScalarIStructO
:
5074 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5075 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5076 args
->scalarInput
, args
->scalarInputCount
,
5077 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5081 case kIOUCStructIStructO
:
5082 err
= shim_io_async_method_structureI_structureO( method
, object
,
5083 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5084 (char *)args
->structureInput
, args
->structureInputSize
,
5085 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5089 err
= kIOReturnBadArgument
;
5095 IOExternalMethod
* method
;
5097 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
5098 return (kIOReturnUnsupported
);
5100 if (kIOUCForegroundOnly
& method
->flags
)
5102 if (task_is_gpu_denied(current_task()))
5103 return (kIOReturnNotPermitted
);
5106 switch (method
->flags
& kIOUCTypeMask
)
5108 case kIOUCScalarIStructI
:
5109 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5110 args
->scalarInput
, args
->scalarInputCount
,
5111 (char *) args
->structureInput
, args
->structureInputSize
);
5114 case kIOUCScalarIScalarO
:
5115 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5116 args
->scalarInput
, args
->scalarInputCount
,
5117 args
->scalarOutput
, &args
->scalarOutputCount
);
5120 case kIOUCScalarIStructO
:
5121 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5122 args
->scalarInput
, args
->scalarInputCount
,
5123 (char *) args
->structureOutput
, &structureOutputSize
);
5127 case kIOUCStructIStructO
:
5128 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5129 (char *) args
->structureInput
, args
->structureInputSize
,
5130 (char *) args
->structureOutput
, &structureOutputSize
);
5134 err
= kIOReturnBadArgument
;
5139 args
->structureOutputSize
= structureOutputSize
;
5146 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5147 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5149 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5150 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5152 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5153 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5154 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5155 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5156 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5157 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5158 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5159 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5160 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5161 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5162 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5163 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5164 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5165 OSMetaClassDefineReservedUnused(IOUserClient
, 15);