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>
53 #include <security/mac_framework.h>
55 #include <sys/kauth.h>
59 #endif /* CONFIG_MACF */
61 #include <IOKit/assert.h>
63 #include "IOServicePrivate.h"
64 #include "IOKitKernelInternal.h"
66 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
67 #define SCALAR32(x) ((uint32_t )x)
68 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
69 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
70 #define REF32(x) ((int)(x))
74 kIOUCAsync0Flags
= 3ULL,
75 kIOUCAsync64Flag
= 1ULL,
76 kIOUCAsyncErrorLoggedFlag
= 2ULL
81 #define IOStatisticsRegisterCounter() \
83 reserved->counter = IOStatistics::registerUserClient(this); \
86 #define IOStatisticsUnregisterCounter() \
89 IOStatistics::unregisterUserClient(reserved->counter); \
92 #define IOStatisticsClientCall() \
94 IOStatistics::countUserClientCall(client); \
99 #define IOStatisticsRegisterCounter()
100 #define IOStatisticsUnregisterCounter()
101 #define IOStatisticsClientCall()
103 #endif /* IOKITSTATS */
105 #if DEVELOPMENT || DEBUG
107 #define FAKE_STACK_FRAME(a) \
108 const void ** __frameptr; \
109 const void * __retaddr; \
110 __frameptr = (typeof(__frameptr)) __builtin_frame_address(0); \
111 __retaddr = __frameptr[1]; \
114 #define FAKE_STACK_FRAME_END() \
115 __frameptr[1] = __retaddr;
117 #else /* DEVELOPMENT || DEBUG */
119 #define FAKE_STACK_FRAME(a)
120 #define FAKE_STACK_FRAME_END()
122 #endif /* DEVELOPMENT || DEBUG */
124 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
126 // definitions we should get from osfmk
128 //typedef struct ipc_port * ipc_port_t;
129 typedef natural_t ipc_kobject_type_t
;
131 #define IKOT_IOKIT_SPARE 27
132 #define IKOT_IOKIT_CONNECT 29
133 #define IKOT_IOKIT_OBJECT 30
137 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
138 ipc_kobject_type_t type
);
140 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
142 extern mach_port_name_t
iokit_make_send_right( task_t task
,
143 io_object_t obj
, ipc_kobject_type_t type
);
145 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
147 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
149 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
151 extern ipc_port_t master_device_port
;
153 extern void iokit_retain_port( ipc_port_t port
);
154 extern void iokit_release_port( ipc_port_t port
);
155 extern void iokit_release_port_send( ipc_port_t port
);
157 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
159 #include <mach/mach_traps.h>
160 #include <vm/vm_map.h>
165 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
167 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
169 class IOMachPort
: public OSObject
171 OSDeclareDefaultStructors(IOMachPort
)
178 static IOMachPort
* portForObject( OSObject
* obj
,
179 ipc_kobject_type_t type
);
180 static bool noMoreSendersForObject( OSObject
* obj
,
181 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
182 static void releasePortForObject( OSObject
* obj
,
183 ipc_kobject_type_t type
);
184 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
186 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
188 static mach_port_name_t
makeSendRightForTask( task_t task
,
189 io_object_t obj
, ipc_kobject_type_t type
);
191 virtual void free() APPLE_KEXT_OVERRIDE
;
194 #define super OSObject
195 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
197 static IOLock
* gIOObjectPortLock
;
199 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
201 // not in dictForType() for debugging ease
202 static OSDictionary
* gIOObjectPorts
;
203 static OSDictionary
* gIOConnectPorts
;
205 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
207 OSDictionary
** dict
;
209 if( IKOT_IOKIT_OBJECT
== type
)
210 dict
= &gIOObjectPorts
;
211 else if( IKOT_IOKIT_CONNECT
== type
)
212 dict
= &gIOConnectPorts
;
217 *dict
= OSDictionary::withCapacity( 1 );
222 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
223 ipc_kobject_type_t type
)
225 IOMachPort
* inst
= 0;
228 IOTakeLock( gIOObjectPortLock
);
232 dict
= dictForType( type
);
236 if( (inst
= (IOMachPort
*)
237 dict
->getObject( (const OSSymbol
*) obj
))) {
243 inst
= new IOMachPort
;
244 if( inst
&& !inst
->init()) {
249 inst
->port
= iokit_alloc_object_port( obj
, type
);
252 dict
->setObject( (const OSSymbol
*) obj
, inst
);
262 IOUnlock( gIOObjectPortLock
);
267 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
268 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
271 IOMachPort
* machPort
;
273 bool destroyed
= true;
275 IOTakeLock( gIOObjectPortLock
);
277 if( (dict
= dictForType( type
))) {
280 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
282 destroyed
= (machPort
->mscount
<= *mscount
);
283 if (!destroyed
) *mscount
= machPort
->mscount
;
286 if ((IKOT_IOKIT_CONNECT
== type
) && (uc
= OSDynamicCast(IOUserClient
, obj
)))
290 dict
->removeObject( (const OSSymbol
*) obj
);
296 IOUnlock( gIOObjectPortLock
);
301 void IOMachPort::releasePortForObject( OSObject
* obj
,
302 ipc_kobject_type_t type
)
305 IOMachPort
* machPort
;
307 assert(IKOT_IOKIT_CONNECT
!= type
);
309 IOTakeLock( gIOObjectPortLock
);
311 if( (dict
= dictForType( type
))) {
313 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
314 if( machPort
&& !machPort
->holdDestroy
)
315 dict
->removeObject( (const OSSymbol
*) obj
);
319 IOUnlock( gIOObjectPortLock
);
322 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
325 IOMachPort
* machPort
;
327 IOLockLock( gIOObjectPortLock
);
329 if( (dict
= dictForType( type
))) {
330 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
332 machPort
->holdDestroy
= true;
335 IOLockUnlock( gIOObjectPortLock
);
338 void IOUserClient::destroyUserReferences( OSObject
* obj
)
340 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
343 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
347 IOTakeLock( gIOObjectPortLock
);
350 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
353 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
357 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
362 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
363 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
365 uc
->mappings
->release();
369 dict
->removeObject( (const OSSymbol
*) obj
);
373 IOUnlock( gIOObjectPortLock
);
376 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
377 io_object_t obj
, ipc_kobject_type_t type
)
379 return( iokit_make_send_right( task
, obj
, type
));
382 void IOMachPort::free( void )
385 iokit_destroy_object_port( port
);
389 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
391 class IOUserIterator
: public OSIterator
393 OSDeclareDefaultStructors(IOUserIterator
)
395 OSObject
* userIteratorObject
;
398 static IOUserIterator
* withIterator(OSIterator
* iter
);
399 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
400 virtual void free() APPLE_KEXT_OVERRIDE
;
402 virtual void reset() APPLE_KEXT_OVERRIDE
;
403 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
404 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
407 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
409 class IOUserNotification
: public IOUserIterator
411 OSDeclareDefaultStructors(IOUserNotification
)
413 #define holdNotify userIteratorObject
417 virtual void free() APPLE_KEXT_OVERRIDE
;
419 virtual void setNotification( IONotifier
* obj
);
421 virtual void reset() APPLE_KEXT_OVERRIDE
;
422 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
425 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
427 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
430 IOUserIterator::withIterator(OSIterator
* iter
)
434 if (!iter
) return (0);
436 me
= new IOUserIterator
;
437 if (me
&& !me
->init())
443 me
->userIteratorObject
= iter
;
449 IOUserIterator::init( void )
451 if (!OSObject::init()) return (false);
453 lock
= IOLockAlloc();
461 IOUserIterator::free()
463 if (userIteratorObject
) userIteratorObject
->release();
464 if (lock
) IOLockFree(lock
);
469 IOUserIterator::reset()
472 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
473 ((OSIterator
*)userIteratorObject
)->reset();
478 IOUserIterator::isValid()
483 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
484 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
491 IOUserIterator::getNextObject()
496 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
497 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
503 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
506 // functions called from osfmk/device/iokit_rpc.c
509 iokit_add_reference( io_object_t obj
)
516 iokit_remove_reference( io_object_t obj
)
523 iokit_add_connect_reference( io_object_t obj
)
529 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) OSIncrementAtomic(&uc
->__ipc
);
535 iokit_remove_connect_reference( io_object_t obj
)
538 bool finalize
= false;
542 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
544 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive())
546 IOLockLock(gIOObjectPortLock
);
547 if ((finalize
= uc
->__ipcFinal
)) uc
->__ipcFinal
= false;
548 IOLockUnlock(gIOObjectPortLock
);
550 if (finalize
) uc
->scheduleFinalize(true);
557 IOUserClient::finalizeUserReferences(OSObject
* obj
)
562 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
564 IOLockLock(gIOObjectPortLock
);
565 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) ok
= false;
566 IOLockUnlock(gIOObjectPortLock
);
572 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
574 IOMachPort
* machPort
;
577 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
579 port
= machPort
->port
;
581 iokit_retain_port( port
);
592 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
593 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
595 IOUserClient
* client
;
597 IOUserNotification
* notify
;
599 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
600 return( kIOReturnNotReady
);
602 if( IKOT_IOKIT_CONNECT
== type
)
604 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
606 IOStatisticsClientCall();
607 client
->clientDied();
610 else if( IKOT_IOKIT_OBJECT
== type
)
612 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
614 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
615 notify
->setNotification( 0 );
618 return( kIOReturnSuccess
);
623 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
625 class IOServiceUserNotification
: public IOUserNotification
627 OSDeclareDefaultStructors(IOServiceUserNotification
)
630 mach_msg_header_t msgHdr
;
631 OSNotificationHeader64 notifyHeader
;
634 enum { kMaxOutstanding
= 1024 };
639 OSObject
* lastEntry
;
645 virtual bool init( mach_port_t port
, natural_t type
,
646 void * reference
, vm_size_t referenceSize
,
648 virtual void free() APPLE_KEXT_OVERRIDE
;
650 static bool _handler( void * target
,
651 void * ref
, IOService
* newService
, IONotifier
* notifier
);
652 virtual bool handler( void * ref
, IOService
* newService
);
654 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
657 class IOServiceMessageUserNotification
: public IOUserNotification
659 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
662 mach_msg_header_t msgHdr
;
663 mach_msg_body_t msgBody
;
664 mach_msg_port_descriptor_t ports
[1];
665 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
676 virtual bool init( mach_port_t port
, natural_t type
,
677 void * reference
, vm_size_t referenceSize
,
681 virtual void free() APPLE_KEXT_OVERRIDE
;
683 static IOReturn
_handler( void * target
, void * ref
,
684 UInt32 messageType
, IOService
* provider
,
685 void * messageArgument
, vm_size_t argSize
);
686 virtual IOReturn
handler( void * ref
,
687 UInt32 messageType
, IOService
* provider
,
688 void * messageArgument
, vm_size_t argSize
);
690 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
693 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
696 #define super IOUserIterator
697 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
698 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
700 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
702 void IOUserNotification::free( void )
706 assert(OSDynamicCast(IONotifier
, holdNotify
));
707 ((IONotifier
*)holdNotify
)->remove();
710 // can't be in handler now
716 void IOUserNotification::setNotification( IONotifier
* notify
)
718 OSObject
* previousNotify
;
720 IOLockLock( gIOObjectPortLock
);
722 previousNotify
= holdNotify
;
725 IOLockUnlock( gIOObjectPortLock
);
729 assert(OSDynamicCast(IONotifier
, previousNotify
));
730 ((IONotifier
*)previousNotify
)->remove();
734 void IOUserNotification::reset()
739 bool IOUserNotification::isValid()
744 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
747 #define super IOUserNotification
748 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
750 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
752 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
753 void * reference
, vm_size_t referenceSize
,
759 newSet
= OSArray::withCapacity( 1 );
763 if (referenceSize
> sizeof(OSAsyncReference64
))
766 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
767 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
771 bzero( pingMsg
, msgSize
);
773 pingMsg
->msgHdr
.msgh_remote_port
= port
;
774 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
775 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
776 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
777 pingMsg
->msgHdr
.msgh_size
= msgSize
;
778 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
780 pingMsg
->notifyHeader
.size
= 0;
781 pingMsg
->notifyHeader
.type
= type
;
782 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
787 void IOServiceUserNotification::free( void )
792 OSObject
* _lastEntry
;
796 _lastEntry
= lastEntry
;
801 if( _pingMsg
&& _msgSize
) {
802 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
803 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
805 IOFree(_pingMsg
, _msgSize
);
809 _lastEntry
->release();
815 bool IOServiceUserNotification::_handler( void * target
,
816 void * ref
, IOService
* newService
, IONotifier
* notifier
)
818 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
821 bool IOServiceUserNotification::handler( void * ref
,
822 IOService
* newService
)
826 ipc_port_t port
= NULL
;
827 bool sendPing
= false;
831 count
= newSet
->getCount();
832 if( count
< kMaxOutstanding
) {
834 newSet
->setObject( newService
);
835 if( (sendPing
= (armed
&& (0 == count
))))
841 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
842 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
845 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
846 pingMsg
->msgHdr
.msgh_local_port
= port
;
848 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
850 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
851 pingMsg
->msgHdr
.msgh_size
,
852 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
855 iokit_release_port( port
);
857 if( (KERN_SUCCESS
!= kr
) && !ipcLogged
)
860 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
867 OSObject
* IOServiceUserNotification::getNextObject()
871 OSObject
* releaseEntry
;
875 releaseEntry
= lastEntry
;
876 count
= newSet
->getCount();
878 result
= newSet
->getObject( count
- 1 );
880 newSet
->removeObject( count
- 1);
889 if (releaseEntry
) releaseEntry
->release();
894 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
896 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
898 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
900 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
901 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
907 if (referenceSize
> sizeof(OSAsyncReference64
))
910 clientIs64
= client64
;
912 owningPID
= proc_selfpid();
914 extraSize
+= sizeof(IOServiceInterestContent64
);
915 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
916 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
920 bzero( pingMsg
, msgSize
);
922 pingMsg
->msgHdr
.msgh_remote_port
= port
;
923 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
925 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
926 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
927 pingMsg
->msgHdr
.msgh_size
= msgSize
;
928 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
930 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
932 pingMsg
->ports
[0].name
= 0;
933 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
934 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
936 pingMsg
->notifyHeader
.size
= extraSize
;
937 pingMsg
->notifyHeader
.type
= type
;
938 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
943 void IOServiceMessageUserNotification::free( void )
953 if( _pingMsg
&& _msgSize
) {
954 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
955 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
957 IOFree( _pingMsg
, _msgSize
);
961 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
962 UInt32 messageType
, IOService
* provider
,
963 void * argument
, vm_size_t argSize
)
965 return( ((IOServiceMessageUserNotification
*) target
)->handler(
966 ref
, messageType
, provider
, argument
, argSize
));
969 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
970 UInt32 messageType
, IOService
* provider
,
971 void * messageArgument
, vm_size_t callerArgSize
)
973 enum { kLocalMsgSize
= 0x100 };
974 uint64_t stackMsg
[kLocalMsgSize
/ sizeof(uint64_t)];
978 vm_size_t thisMsgSize
;
979 ipc_port_t thisPort
, providerPort
;
980 struct PingMsg
* thisMsg
;
981 IOServiceInterestContent64
* data
;
983 if (kIOMessageCopyClientID
== messageType
)
985 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
986 return (kIOReturnSuccess
);
989 if (callerArgSize
== 0)
991 if (clientIs64
) argSize
= sizeof(data
->messageArgument
[0]);
992 else argSize
= sizeof(uint32_t);
996 argSize
= callerArgSize
;
997 if( argSize
> kIOUserNotifyMaxMessageSize
)
998 argSize
= kIOUserNotifyMaxMessageSize
;
1001 // adjust message size for ipc restrictions
1003 type
= pingMsg
->notifyHeader
.type
;
1004 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
1005 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
1006 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
1008 thisMsgSize
= msgSize
1009 + sizeof( IOServiceInterestContent64
)
1010 - sizeof( data
->messageArgument
)
1013 if (thisMsgSize
> sizeof(stackMsg
))
1015 allocMsg
= IOMalloc(thisMsgSize
);
1016 if (!allocMsg
) return (kIOReturnNoMemory
);
1017 thisMsg
= (typeof(thisMsg
)) allocMsg
;
1022 thisMsg
= (typeof(thisMsg
)) stackMsg
;
1025 bcopy(pingMsg
, thisMsg
, msgSize
);
1026 thisMsg
->notifyHeader
.type
= type
;
1027 data
= (IOServiceInterestContent64
*) (((uint8_t *) thisMsg
) + msgSize
);
1028 // == pingMsg->notifyHeader.content;
1029 data
->messageType
= messageType
;
1031 if (callerArgSize
== 0)
1033 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
1036 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
1041 bcopy( messageArgument
, data
->messageArgument
, callerArgSize
);
1042 bzero((void *)(((uintptr_t) &data
->messageArgument
[0]) + callerArgSize
), argSize
- callerArgSize
);
1045 thisMsg
->notifyHeader
.type
= type
;
1046 thisMsg
->msgHdr
.msgh_size
= thisMsgSize
;
1048 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
1049 thisMsg
->ports
[0].name
= providerPort
;
1050 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
1051 thisMsg
->msgHdr
.msgh_local_port
= thisPort
;
1053 kr
= mach_msg_send_from_kernel_with_options( &thisMsg
->msgHdr
,
1054 thisMsg
->msgHdr
.msgh_size
,
1055 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
1058 iokit_release_port( thisPort
);
1060 iokit_release_port( providerPort
);
1063 IOFree(allocMsg
, thisMsgSize
);
1065 if((KERN_SUCCESS
!= kr
) && !ipcLogged
)
1068 IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1071 return( kIOReturnSuccess
);
1074 OSObject
* IOServiceMessageUserNotification::getNextObject()
1079 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1082 #define super IOService
1083 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1085 IOLock
* gIOUserClientOwnersLock
;
1087 void IOUserClient::initialize( void )
1089 gIOObjectPortLock
= IOLockAlloc();
1090 gIOUserClientOwnersLock
= IOLockAlloc();
1091 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1094 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1095 mach_port_t wakePort
,
1096 void *callback
, void *refcon
)
1098 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1099 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1100 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1101 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1104 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1105 mach_port_t wakePort
,
1106 mach_vm_address_t callback
, io_user_reference_t refcon
)
1108 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1109 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1110 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1111 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1114 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1115 mach_port_t wakePort
,
1116 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1118 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1119 if (vm_map_is_64bit(get_task_map(task
))) {
1120 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1124 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
1127 OSDictionary
* user
= 0;
1129 if ((array
= OSDynamicCast(OSArray
,
1130 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1132 for (unsigned int idx
= 0;
1133 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1137 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1138 && (uid
== num
->unsigned32BitValue())) {
1148 static OSDictionary
* CopyUserOnConsole(void)
1151 OSDictionary
* user
= 0;
1153 if ((array
= OSDynamicCast(OSArray
,
1154 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1156 for (unsigned int idx
= 0;
1157 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1160 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
1171 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
1172 IOService
* service
)
1176 p
= (proc_t
) get_bsdtask_info(task
);
1179 uint64_t authorizationID
;
1181 authorizationID
= proc_uniqueid(p
);
1182 if (authorizationID
)
1184 if (service
->getAuthorizationID() == authorizationID
)
1186 return (kIOReturnSuccess
);
1191 return (kIOReturnNotPermitted
);
1194 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
1195 const char * privilegeName
)
1198 security_token_t token
;
1199 mach_msg_type_number_t count
;
1201 OSDictionary
* user
;
1205 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1206 sizeof(kIOClientPrivilegeForeground
)))
1208 if (task_is_gpu_denied(current_task()))
1209 return (kIOReturnNotPrivileged
);
1211 return (kIOReturnSuccess
);
1214 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1215 sizeof(kIOClientPrivilegeConsoleSession
)))
1220 task
= (task_t
) securityToken
;
1222 task
= current_task();
1223 p
= (proc_t
) get_bsdtask_info(task
);
1224 kr
= kIOReturnNotPrivileged
;
1226 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1228 user
= CopyUserOnConsole();
1232 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1233 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1235 kr
= kIOReturnSuccess
;
1239 kauth_cred_unref(&cred
);
1244 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1245 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1246 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1248 task
= (task_t
)securityToken
;
1250 count
= TASK_SECURITY_TOKEN_COUNT
;
1251 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1253 if (KERN_SUCCESS
!= kr
)
1255 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1256 sizeof(kIOClientPrivilegeAdministrator
))) {
1257 if (0 != token
.val
[0])
1258 kr
= kIOReturnNotPrivileged
;
1259 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1260 sizeof(kIOClientPrivilegeLocalUser
))) {
1261 user
= CopyConsoleUser(token
.val
[0]);
1265 kr
= kIOReturnNotPrivileged
;
1266 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1267 sizeof(kIOClientPrivilegeConsoleUser
))) {
1268 user
= CopyConsoleUser(token
.val
[0]);
1270 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1271 kr
= kIOReturnNotPrivileged
;
1272 else if ( secureConsole
) {
1273 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1274 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1275 kr
= kIOReturnNotPrivileged
;
1280 kr
= kIOReturnNotPrivileged
;
1282 kr
= kIOReturnUnsupported
;
1287 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1288 const char * entitlement
)
1290 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1294 char procname
[MAXCOMLEN
+ 1] = "";
1296 void *entitlements_blob
= NULL
;
1297 char *entitlements_data
= NULL
;
1298 OSObject
*entitlements_obj
= NULL
;
1299 OSDictionary
*entitlements
= NULL
;
1300 OSString
*errorString
= NULL
;
1301 OSObject
*value
= NULL
;
1303 p
= (proc_t
)get_bsdtask_info(task
);
1307 proc_name(pid
, procname
, (int)sizeof(procname
));
1309 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1312 if (len
<= offsetof(CS_GenericBlob
, data
))
1316 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1317 * we'll try to parse in the kernel.
1319 len
-= offsetof(CS_GenericBlob
, data
);
1320 if (len
> MAX_ENTITLEMENTS_LEN
) {
1321 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1326 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1327 * what is stored in the entitlements blob. Copy the string and
1330 entitlements_data
= (char *)IOMalloc(len
+ 1);
1331 if (entitlements_data
== NULL
)
1333 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1334 entitlements_data
[len
] = '\0';
1336 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1337 if (errorString
!= NULL
) {
1338 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1341 if (entitlements_obj
== NULL
)
1344 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1345 if (entitlements
== NULL
)
1348 /* Fetch the entitlement value from the dictionary. */
1349 value
= entitlements
->getObject(entitlement
);
1354 if (entitlements_data
!= NULL
)
1355 IOFree(entitlements_data
, len
+ 1);
1356 if (entitlements_obj
!= NULL
)
1357 entitlements_obj
->release();
1358 if (errorString
!= NULL
)
1359 errorString
->release();
1363 bool IOUserClient::init()
1365 if (getPropertyTable() || super::init())
1371 bool IOUserClient::init(OSDictionary
* dictionary
)
1373 if (getPropertyTable() || super::init(dictionary
))
1379 bool IOUserClient::initWithTask(task_t owningTask
,
1383 if (getPropertyTable() || super::init())
1389 bool IOUserClient::initWithTask(task_t owningTask
,
1392 OSDictionary
* properties
)
1396 ok
= super::init( properties
);
1397 ok
&= initWithTask( owningTask
, securityID
, type
);
1402 bool IOUserClient::reserve()
1405 reserved
= IONew(ExpansionData
, 1);
1410 setTerminateDefer(NULL
, true);
1411 IOStatisticsRegisterCounter();
1416 struct IOUserClientOwner
1419 queue_chain_t taskLink
;
1421 queue_chain_t ucLink
;
1425 IOUserClient::registerOwner(task_t task
)
1427 IOUserClientOwner
* owner
;
1431 IOLockLock(gIOUserClientOwnersLock
);
1434 ret
= kIOReturnSuccess
;
1436 if (!owners
.next
) queue_init(&owners
);
1439 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1441 if (task
!= owner
->task
) continue;
1448 owner
= IONew(IOUserClientOwner
, 1);
1449 if (!newOwner
) ret
= kIOReturnNoMemory
;
1454 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1455 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1459 IOLockUnlock(gIOUserClientOwnersLock
);
1465 IOUserClient::noMoreSenders(void)
1467 IOUserClientOwner
* owner
;
1469 IOLockLock(gIOUserClientOwnersLock
);
1473 while (!queue_empty(&owners
))
1475 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1476 queue_remove(task_io_user_clients(owner
->task
), owner
, IOUserClientOwner
*, taskLink
);
1477 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1478 IODelete(owner
, IOUserClientOwner
, 1);
1480 owners
.next
= owners
.prev
= NULL
;
1483 IOLockUnlock(gIOUserClientOwnersLock
);
1486 extern "C" kern_return_t
1487 iokit_task_terminate(task_t task
)
1489 IOUserClientOwner
* owner
;
1490 IOUserClient
* dead
;
1492 queue_head_t
* taskque
;
1494 IOLockLock(gIOUserClientOwnersLock
);
1496 taskque
= task_io_user_clients(task
);
1498 while (!queue_empty(taskque
))
1500 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1502 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1503 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1504 if (queue_empty(&uc
->owners
))
1507 IOLog("destroying out of band connect for %s\n", uc
->getName());
1508 // now using the uc queue head as a singly linked queue,
1509 // leaving .next as NULL to mark it empty
1510 uc
->owners
.next
= NULL
;
1511 uc
->owners
.prev
= (queue_entry_t
) dead
;
1514 IODelete(owner
, IOUserClientOwner
, 1);
1517 IOLockUnlock(gIOUserClientOwnersLock
);
1522 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1523 uc
->owners
.prev
= NULL
;
1524 if (uc
->sharedInstance
|| !uc
->closed
) uc
->clientDied();
1528 return (KERN_SUCCESS
);
1531 void IOUserClient::free()
1533 if( mappings
) mappings
->release();
1535 IOStatisticsUnregisterCounter();
1537 assert(!owners
.next
);
1538 assert(!owners
.prev
);
1540 if (reserved
) IODelete(reserved
, ExpansionData
, 1);
1545 IOReturn
IOUserClient::clientDied( void )
1547 IOReturn ret
= kIOReturnNotReady
;
1549 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
))
1551 ret
= clientClose();
1557 IOReturn
IOUserClient::clientClose( void )
1559 return( kIOReturnUnsupported
);
1562 IOService
* IOUserClient::getService( void )
1567 IOReturn
IOUserClient::registerNotificationPort(
1568 mach_port_t
/* port */,
1570 UInt32
/* refCon */)
1572 return( kIOReturnUnsupported
);
1575 IOReturn
IOUserClient::registerNotificationPort(
1578 io_user_reference_t refCon
)
1580 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1583 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1584 semaphore_t
* semaphore
)
1586 return( kIOReturnUnsupported
);
1589 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1591 return( kIOReturnUnsupported
);
1594 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1595 IOOptionBits
* options
,
1596 IOMemoryDescriptor
** memory
)
1598 return( kIOReturnUnsupported
);
1602 IOMemoryMap
* IOUserClient::mapClientMemory(
1605 IOOptionBits mapFlags
,
1606 IOVirtualAddress atAddress
)
1612 IOMemoryMap
* IOUserClient::mapClientMemory64(
1615 IOOptionBits mapFlags
,
1616 mach_vm_address_t atAddress
)
1619 IOOptionBits options
= 0;
1620 IOMemoryDescriptor
* memory
;
1621 IOMemoryMap
* map
= 0;
1623 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1625 if( memory
&& (kIOReturnSuccess
== err
)) {
1627 FAKE_STACK_FRAME(getMetaClass());
1629 options
= (options
& ~kIOMapUserOptionsMask
)
1630 | (mapFlags
& kIOMapUserOptionsMask
);
1631 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1634 FAKE_STACK_FRAME_END();
1640 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1641 OSObject
*obj
, io_object_t
*clientObj
)
1643 mach_port_name_t name
;
1645 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1647 *(mach_port_name_t
*)clientObj
= name
;
1648 return kIOReturnSuccess
;
1651 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1656 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1661 IOExternalTrap
* IOUserClient::
1662 getExternalTrapForIndex(UInt32 index
)
1667 #pragma clang diagnostic push
1668 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1670 // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
1671 // functions can break clients of kexts implementing getExternalMethodForIndex()
1672 IOExternalMethod
* IOUserClient::
1673 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1675 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1678 *targetP
= (IOService
*) method
->object
;
1683 IOExternalAsyncMethod
* IOUserClient::
1684 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1686 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1689 *targetP
= (IOService
*) method
->object
;
1694 IOExternalTrap
* IOUserClient::
1695 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1697 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1700 *targetP
= trap
->object
;
1705 #pragma clang diagnostic pop
1707 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1710 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1712 if (MACH_PORT_NULL
!= port
)
1713 iokit_release_port_send(port
);
1715 return (kIOReturnSuccess
);
1718 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1720 if (MACH_PORT_NULL
!= port
)
1721 iokit_release_port_send(port
);
1723 return (kIOReturnSuccess
);
1726 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1727 IOReturn result
, void *args
[], UInt32 numArgs
)
1729 OSAsyncReference64 reference64
;
1730 io_user_reference_t args64
[kMaxAsyncArgs
];
1733 if (numArgs
> kMaxAsyncArgs
)
1734 return kIOReturnMessageTooLarge
;
1736 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1737 reference64
[idx
] = REF64(reference
[idx
]);
1739 for (idx
= 0; idx
< numArgs
; idx
++)
1740 args64
[idx
] = REF64(args
[idx
]);
1742 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1745 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1746 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1748 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1751 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1752 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1754 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1757 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1758 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1762 mach_msg_header_t msgHdr
;
1767 OSNotificationHeader notifyHdr
;
1768 IOAsyncCompletionContent asyncContent
;
1769 uint32_t args
[kMaxAsyncArgs
];
1773 OSNotificationHeader64 notifyHdr
;
1774 IOAsyncCompletionContent asyncContent
;
1775 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1780 mach_port_t replyPort
;
1783 // If no reply port, do nothing.
1784 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1785 if (replyPort
== MACH_PORT_NULL
)
1786 return kIOReturnSuccess
;
1788 if (numArgs
> kMaxAsyncArgs
)
1789 return kIOReturnMessageTooLarge
;
1791 bzero(&replyMsg
, sizeof(replyMsg
));
1792 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1794 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1795 replyMsg
.msgHdr
.msgh_local_port
= 0;
1796 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1797 if (kIOUCAsync64Flag
& reference
[0])
1799 replyMsg
.msgHdr
.msgh_size
=
1800 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1801 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1802 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1803 + numArgs
* sizeof(io_user_reference_t
);
1804 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1805 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1807 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1809 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1815 replyMsg
.msgHdr
.msgh_size
=
1816 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1817 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1819 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1820 + numArgs
* sizeof(uint32_t);
1821 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1823 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1824 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1826 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1828 for (idx
= 0; idx
< numArgs
; idx
++)
1829 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1832 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1833 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1834 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1836 /* Fail on full queue. */
1837 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1838 replyMsg
.msgHdr
.msgh_size
);
1840 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
) && !(kIOUCAsyncErrorLoggedFlag
& reference
[0]))
1842 reference
[0] |= kIOUCAsyncErrorLoggedFlag
;
1843 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1849 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1853 #define CHECK(cls,obj,out) \
1855 if( !(out = OSDynamicCast( cls, obj))) \
1856 return( kIOReturnBadArgument )
1858 #define CHECKLOCKED(cls,obj,out) \
1859 IOUserIterator * oIter; \
1861 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1862 return (kIOReturnBadArgument); \
1863 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
1864 return (kIOReturnBadArgument)
1866 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1868 // Create a vm_map_copy_t or kalloc'ed data for memory
1869 // to be copied out. ipc will free after the copyout.
1871 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1872 io_buf_ptr_t
* buf
)
1877 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1878 false /* src_destroy */, ©
);
1880 assert( err
== KERN_SUCCESS
);
1881 if( err
== KERN_SUCCESS
)
1882 *buf
= (char *) copy
;
1887 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1889 /* Routine io_server_version */
1890 kern_return_t
is_io_server_version(
1891 mach_port_t master_port
,
1894 *version
= IOKIT_SERVER_VERSION
;
1895 return (kIOReturnSuccess
);
1898 /* Routine io_object_get_class */
1899 kern_return_t
is_io_object_get_class(
1901 io_name_t className
)
1903 const OSMetaClass
* my_obj
= NULL
;
1906 return( kIOReturnBadArgument
);
1908 my_obj
= object
->getMetaClass();
1910 return (kIOReturnNotFound
);
1913 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1915 return( kIOReturnSuccess
);
1918 /* Routine io_object_get_superclass */
1919 kern_return_t
is_io_object_get_superclass(
1920 mach_port_t master_port
,
1922 io_name_t class_name
)
1924 const OSMetaClass
* my_obj
= NULL
;
1925 const OSMetaClass
* superclass
= NULL
;
1926 const OSSymbol
*my_name
= NULL
;
1927 const char *my_cstr
= NULL
;
1929 if (!obj_name
|| !class_name
)
1930 return (kIOReturnBadArgument
);
1932 if( master_port
!= master_device_port
)
1933 return( kIOReturnNotPrivileged
);
1935 my_name
= OSSymbol::withCString(obj_name
);
1938 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1942 superclass
= my_obj
->getSuperClass();
1946 return( kIOReturnNotFound
);
1949 my_cstr
= superclass
->getClassName();
1952 strlcpy(class_name
, my_cstr
, sizeof(io_name_t
));
1953 return( kIOReturnSuccess
);
1955 return (kIOReturnNotFound
);
1958 /* Routine io_object_get_bundle_identifier */
1959 kern_return_t
is_io_object_get_bundle_identifier(
1960 mach_port_t master_port
,
1962 io_name_t bundle_name
)
1964 const OSMetaClass
* my_obj
= NULL
;
1965 const OSSymbol
*my_name
= NULL
;
1966 const OSSymbol
*identifier
= NULL
;
1967 const char *my_cstr
= NULL
;
1969 if (!obj_name
|| !bundle_name
)
1970 return (kIOReturnBadArgument
);
1972 if( master_port
!= master_device_port
)
1973 return( kIOReturnNotPrivileged
);
1975 my_name
= OSSymbol::withCString(obj_name
);
1978 my_obj
= OSMetaClass::getMetaClassWithName(my_name
);
1983 identifier
= my_obj
->getKmodName();
1986 return( kIOReturnNotFound
);
1989 my_cstr
= identifier
->getCStringNoCopy();
1991 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1992 return( kIOReturnSuccess
);
1995 return (kIOReturnBadArgument
);
1998 /* Routine io_object_conforms_to */
1999 kern_return_t
is_io_object_conforms_to(
2001 io_name_t className
,
2002 boolean_t
*conforms
)
2005 return( kIOReturnBadArgument
);
2007 *conforms
= (0 != object
->metaCast( className
));
2009 return( kIOReturnSuccess
);
2012 /* Routine io_object_get_retain_count */
2013 kern_return_t
is_io_object_get_retain_count(
2015 uint32_t *retainCount
)
2018 return( kIOReturnBadArgument
);
2020 *retainCount
= object
->getRetainCount();
2021 return( kIOReturnSuccess
);
2024 /* Routine io_iterator_next */
2025 kern_return_t
is_io_iterator_next(
2026 io_object_t iterator
,
2027 io_object_t
*object
)
2032 CHECK( OSIterator
, iterator
, iter
);
2034 obj
= iter
->getNextObject();
2038 ret
= kIOReturnSuccess
;
2040 ret
= kIOReturnNoDevice
;
2045 /* Routine io_iterator_reset */
2046 kern_return_t
is_io_iterator_reset(
2047 io_object_t iterator
)
2049 CHECK( OSIterator
, iterator
, iter
);
2053 return( kIOReturnSuccess
);
2056 /* Routine io_iterator_is_valid */
2057 kern_return_t
is_io_iterator_is_valid(
2058 io_object_t iterator
,
2059 boolean_t
*is_valid
)
2061 CHECK( OSIterator
, iterator
, iter
);
2063 *is_valid
= iter
->isValid();
2065 return( kIOReturnSuccess
);
2069 static kern_return_t
internal_io_service_match_property_table(
2070 io_service_t _service
,
2071 const char * matching
,
2072 mach_msg_type_number_t matching_size
,
2075 CHECK( IOService
, _service
, service
);
2079 OSDictionary
* dict
;
2081 assert(matching_size
);
2082 obj
= OSUnserializeXML(matching
, matching_size
);
2084 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2085 *matches
= service
->passiveMatch( dict
);
2086 kr
= kIOReturnSuccess
;
2088 kr
= kIOReturnBadArgument
;
2096 /* Routine io_service_match_property_table */
2097 kern_return_t
is_io_service_match_property_table(
2098 io_service_t service
,
2099 io_string_t matching
,
2100 boolean_t
*matches
)
2102 return (kIOReturnUnsupported
);
2106 /* Routine io_service_match_property_table_ool */
2107 kern_return_t
is_io_service_match_property_table_ool(
2108 io_object_t service
,
2109 io_buf_ptr_t matching
,
2110 mach_msg_type_number_t matchingCnt
,
2111 kern_return_t
*result
,
2112 boolean_t
*matches
)
2116 vm_map_offset_t map_data
;
2118 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2119 data
= CAST_DOWN(vm_offset_t
, map_data
);
2121 if( KERN_SUCCESS
== kr
) {
2122 // must return success after vm_map_copyout() succeeds
2123 *result
= internal_io_service_match_property_table(service
,
2124 (const char *)data
, matchingCnt
, matches
);
2125 vm_deallocate( kernel_map
, data
, matchingCnt
);
2131 /* Routine io_service_match_property_table_bin */
2132 kern_return_t
is_io_service_match_property_table_bin(
2133 io_object_t service
,
2134 io_struct_inband_t matching
,
2135 mach_msg_type_number_t matchingCnt
,
2138 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
2141 static kern_return_t
internal_io_service_get_matching_services(
2142 mach_port_t master_port
,
2143 const char * matching
,
2144 mach_msg_type_number_t matching_size
,
2145 io_iterator_t
*existing
)
2149 OSDictionary
* dict
;
2151 if( master_port
!= master_device_port
)
2152 return( kIOReturnNotPrivileged
);
2154 assert(matching_size
);
2155 obj
= OSUnserializeXML(matching
, matching_size
);
2157 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2158 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2159 kr
= kIOReturnSuccess
;
2161 kr
= kIOReturnBadArgument
;
2169 /* Routine io_service_get_matching_services */
2170 kern_return_t
is_io_service_get_matching_services(
2171 mach_port_t master_port
,
2172 io_string_t matching
,
2173 io_iterator_t
*existing
)
2175 return (kIOReturnUnsupported
);
2178 /* Routine io_service_get_matching_services_ool */
2179 kern_return_t
is_io_service_get_matching_services_ool(
2180 mach_port_t master_port
,
2181 io_buf_ptr_t matching
,
2182 mach_msg_type_number_t matchingCnt
,
2183 kern_return_t
*result
,
2184 io_object_t
*existing
)
2188 vm_map_offset_t map_data
;
2190 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2191 data
= CAST_DOWN(vm_offset_t
, map_data
);
2193 if( KERN_SUCCESS
== kr
) {
2194 // must return success after vm_map_copyout() succeeds
2195 // and mig will copy out objects on success
2197 *result
= internal_io_service_get_matching_services(master_port
,
2198 (const char *) data
, matchingCnt
, existing
);
2199 vm_deallocate( kernel_map
, data
, matchingCnt
);
2205 /* Routine io_service_get_matching_services_bin */
2206 kern_return_t
is_io_service_get_matching_services_bin(
2207 mach_port_t master_port
,
2208 io_struct_inband_t matching
,
2209 mach_msg_type_number_t matchingCnt
,
2210 io_object_t
*existing
)
2212 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
2216 static kern_return_t
internal_io_service_get_matching_service(
2217 mach_port_t master_port
,
2218 const char * matching
,
2219 mach_msg_type_number_t matching_size
,
2220 io_service_t
*service
)
2224 OSDictionary
* dict
;
2226 if( master_port
!= master_device_port
)
2227 return( kIOReturnNotPrivileged
);
2229 assert(matching_size
);
2230 obj
= OSUnserializeXML(matching
, matching_size
);
2232 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2233 *service
= IOService::copyMatchingService( dict
);
2234 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2236 kr
= kIOReturnBadArgument
;
2244 /* Routine io_service_get_matching_service */
2245 kern_return_t
is_io_service_get_matching_service(
2246 mach_port_t master_port
,
2247 io_string_t matching
,
2248 io_service_t
*service
)
2250 return (kIOReturnUnsupported
);
2253 /* Routine io_service_get_matching_services_ool */
2254 kern_return_t
is_io_service_get_matching_service_ool(
2255 mach_port_t master_port
,
2256 io_buf_ptr_t matching
,
2257 mach_msg_type_number_t matchingCnt
,
2258 kern_return_t
*result
,
2259 io_object_t
*service
)
2263 vm_map_offset_t map_data
;
2265 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2266 data
= CAST_DOWN(vm_offset_t
, map_data
);
2268 if( KERN_SUCCESS
== kr
) {
2269 // must return success after vm_map_copyout() succeeds
2270 // and mig will copy out objects on success
2272 *result
= internal_io_service_get_matching_service(master_port
,
2273 (const char *) data
, matchingCnt
, service
);
2274 vm_deallocate( kernel_map
, data
, matchingCnt
);
2280 /* Routine io_service_get_matching_service_bin */
2281 kern_return_t
is_io_service_get_matching_service_bin(
2282 mach_port_t master_port
,
2283 io_struct_inband_t matching
,
2284 mach_msg_type_number_t matchingCnt
,
2285 io_object_t
*service
)
2287 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
2290 static kern_return_t
internal_io_service_add_notification(
2291 mach_port_t master_port
,
2292 io_name_t notification_type
,
2293 const char * matching
,
2294 size_t matching_size
,
2297 vm_size_t referenceSize
,
2299 io_object_t
* notification
)
2301 IOServiceUserNotification
* userNotify
= 0;
2302 IONotifier
* notify
= 0;
2303 const OSSymbol
* sym
;
2304 OSDictionary
* dict
;
2306 unsigned long int userMsgType
;
2308 if( master_port
!= master_device_port
)
2309 return( kIOReturnNotPrivileged
);
2312 err
= kIOReturnNoResources
;
2314 if( !(sym
= OSSymbol::withCString( notification_type
)))
2315 err
= kIOReturnNoResources
;
2317 assert(matching_size
);
2318 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2320 err
= kIOReturnBadArgument
;
2324 if( (sym
== gIOPublishNotification
)
2325 || (sym
== gIOFirstPublishNotification
))
2326 userMsgType
= kIOServicePublishNotificationType
;
2327 else if( (sym
== gIOMatchedNotification
)
2328 || (sym
== gIOFirstMatchNotification
))
2329 userMsgType
= kIOServiceMatchedNotificationType
;
2330 else if( sym
== gIOTerminatedNotification
)
2331 userMsgType
= kIOServiceTerminatedNotificationType
;
2333 userMsgType
= kLastIOKitNotificationType
;
2335 userNotify
= new IOServiceUserNotification
;
2337 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
2338 reference
, referenceSize
, client64
)) {
2339 iokit_release_port_send(port
);
2340 userNotify
->release();
2346 notify
= IOService::addMatchingNotification( sym
, dict
,
2347 &userNotify
->_handler
, userNotify
);
2349 *notification
= userNotify
;
2350 userNotify
->setNotification( notify
);
2351 err
= kIOReturnSuccess
;
2353 err
= kIOReturnUnsupported
;
2366 /* Routine io_service_add_notification */
2367 kern_return_t
is_io_service_add_notification(
2368 mach_port_t master_port
,
2369 io_name_t notification_type
,
2370 io_string_t matching
,
2372 io_async_ref_t reference
,
2373 mach_msg_type_number_t referenceCnt
,
2374 io_object_t
* notification
)
2376 return (kIOReturnUnsupported
);
2379 /* Routine io_service_add_notification_64 */
2380 kern_return_t
is_io_service_add_notification_64(
2381 mach_port_t master_port
,
2382 io_name_t notification_type
,
2383 io_string_t matching
,
2384 mach_port_t wake_port
,
2385 io_async_ref64_t reference
,
2386 mach_msg_type_number_t referenceCnt
,
2387 io_object_t
*notification
)
2389 return (kIOReturnUnsupported
);
2392 /* Routine io_service_add_notification_bin */
2393 kern_return_t is_io_service_add_notification_bin
2395 mach_port_t master_port
,
2396 io_name_t notification_type
,
2397 io_struct_inband_t matching
,
2398 mach_msg_type_number_t matchingCnt
,
2399 mach_port_t wake_port
,
2400 io_async_ref_t reference
,
2401 mach_msg_type_number_t referenceCnt
,
2402 io_object_t
*notification
)
2404 return (internal_io_service_add_notification(master_port
, notification_type
,
2405 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2406 false, notification
));
2409 /* Routine io_service_add_notification_bin_64 */
2410 kern_return_t is_io_service_add_notification_bin_64
2412 mach_port_t master_port
,
2413 io_name_t notification_type
,
2414 io_struct_inband_t matching
,
2415 mach_msg_type_number_t matchingCnt
,
2416 mach_port_t wake_port
,
2417 io_async_ref64_t reference
,
2418 mach_msg_type_number_t referenceCnt
,
2419 io_object_t
*notification
)
2421 return (internal_io_service_add_notification(master_port
, notification_type
,
2422 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2423 true, notification
));
2426 static kern_return_t
internal_io_service_add_notification_ool(
2427 mach_port_t master_port
,
2428 io_name_t notification_type
,
2429 io_buf_ptr_t matching
,
2430 mach_msg_type_number_t matchingCnt
,
2431 mach_port_t wake_port
,
2433 vm_size_t referenceSize
,
2435 kern_return_t
*result
,
2436 io_object_t
*notification
)
2440 vm_map_offset_t map_data
;
2442 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2443 data
= CAST_DOWN(vm_offset_t
, map_data
);
2445 if( KERN_SUCCESS
== kr
) {
2446 // must return success after vm_map_copyout() succeeds
2447 // and mig will copy out objects on success
2449 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2450 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2451 vm_deallocate( kernel_map
, data
, matchingCnt
);
2457 /* Routine io_service_add_notification_ool */
2458 kern_return_t
is_io_service_add_notification_ool(
2459 mach_port_t master_port
,
2460 io_name_t notification_type
,
2461 io_buf_ptr_t matching
,
2462 mach_msg_type_number_t matchingCnt
,
2463 mach_port_t wake_port
,
2464 io_async_ref_t reference
,
2465 mach_msg_type_number_t referenceCnt
,
2466 kern_return_t
*result
,
2467 io_object_t
*notification
)
2469 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2470 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2471 false, result
, notification
));
2474 /* Routine io_service_add_notification_ool_64 */
2475 kern_return_t
is_io_service_add_notification_ool_64(
2476 mach_port_t master_port
,
2477 io_name_t notification_type
,
2478 io_buf_ptr_t matching
,
2479 mach_msg_type_number_t matchingCnt
,
2480 mach_port_t wake_port
,
2481 io_async_ref64_t reference
,
2482 mach_msg_type_number_t referenceCnt
,
2483 kern_return_t
*result
,
2484 io_object_t
*notification
)
2486 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2487 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2488 true, result
, notification
));
2491 /* Routine io_service_add_notification_old */
2492 kern_return_t
is_io_service_add_notification_old(
2493 mach_port_t master_port
,
2494 io_name_t notification_type
,
2495 io_string_t matching
,
2497 // for binary compatibility reasons, this must be natural_t for ILP32
2499 io_object_t
* notification
)
2501 return( is_io_service_add_notification( master_port
, notification_type
,
2502 matching
, port
, &ref
, 1, notification
));
2506 static kern_return_t
internal_io_service_add_interest_notification(
2507 io_object_t _service
,
2508 io_name_t type_of_interest
,
2511 vm_size_t referenceSize
,
2513 io_object_t
* notification
)
2516 IOServiceMessageUserNotification
* userNotify
= 0;
2517 IONotifier
* notify
= 0;
2518 const OSSymbol
* sym
;
2521 CHECK( IOService
, _service
, service
);
2523 err
= kIOReturnNoResources
;
2524 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2526 userNotify
= new IOServiceMessageUserNotification
;
2528 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2529 reference
, referenceSize
,
2530 kIOUserNotifyMaxMessageSize
,
2532 iokit_release_port_send(port
);
2533 userNotify
->release();
2539 notify
= service
->registerInterest( sym
,
2540 &userNotify
->_handler
, userNotify
);
2542 *notification
= userNotify
;
2543 userNotify
->setNotification( notify
);
2544 err
= kIOReturnSuccess
;
2546 err
= kIOReturnUnsupported
;
2555 /* Routine io_service_add_message_notification */
2556 kern_return_t
is_io_service_add_interest_notification(
2557 io_object_t service
,
2558 io_name_t type_of_interest
,
2560 io_async_ref_t reference
,
2561 mach_msg_type_number_t referenceCnt
,
2562 io_object_t
* notification
)
2564 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2565 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2568 /* Routine io_service_add_interest_notification_64 */
2569 kern_return_t
is_io_service_add_interest_notification_64(
2570 io_object_t service
,
2571 io_name_t type_of_interest
,
2572 mach_port_t wake_port
,
2573 io_async_ref64_t reference
,
2574 mach_msg_type_number_t referenceCnt
,
2575 io_object_t
*notification
)
2577 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2578 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2582 /* Routine io_service_acknowledge_notification */
2583 kern_return_t
is_io_service_acknowledge_notification(
2584 io_object_t _service
,
2585 natural_t notify_ref
,
2586 natural_t response
)
2588 CHECK( IOService
, _service
, service
);
2590 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2591 (IOOptionBits
) response
));
2595 /* Routine io_connect_get_semaphore */
2596 kern_return_t
is_io_connect_get_notification_semaphore(
2597 io_connect_t connection
,
2598 natural_t notification_type
,
2599 semaphore_t
*semaphore
)
2601 CHECK( IOUserClient
, connection
, client
);
2603 IOStatisticsClientCall();
2604 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2608 /* Routine io_registry_get_root_entry */
2609 kern_return_t
is_io_registry_get_root_entry(
2610 mach_port_t master_port
,
2613 IORegistryEntry
* entry
;
2615 if( master_port
!= master_device_port
)
2616 return( kIOReturnNotPrivileged
);
2618 entry
= IORegistryEntry::getRegistryRoot();
2623 return( kIOReturnSuccess
);
2626 /* Routine io_registry_create_iterator */
2627 kern_return_t
is_io_registry_create_iterator(
2628 mach_port_t master_port
,
2631 io_object_t
*iterator
)
2633 if( master_port
!= master_device_port
)
2634 return( kIOReturnNotPrivileged
);
2636 *iterator
= IOUserIterator::withIterator(
2637 IORegistryIterator::iterateOver(
2638 IORegistryEntry::getPlane( plane
), options
));
2640 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2643 /* Routine io_registry_entry_create_iterator */
2644 kern_return_t
is_io_registry_entry_create_iterator(
2645 io_object_t registry_entry
,
2648 io_object_t
*iterator
)
2650 CHECK( IORegistryEntry
, registry_entry
, entry
);
2652 *iterator
= IOUserIterator::withIterator(
2653 IORegistryIterator::iterateOver( entry
,
2654 IORegistryEntry::getPlane( plane
), options
));
2656 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2659 /* Routine io_registry_iterator_enter */
2660 kern_return_t
is_io_registry_iterator_enter_entry(
2661 io_object_t iterator
)
2663 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2665 IOLockLock(oIter
->lock
);
2667 IOLockUnlock(oIter
->lock
);
2669 return( kIOReturnSuccess
);
2672 /* Routine io_registry_iterator_exit */
2673 kern_return_t
is_io_registry_iterator_exit_entry(
2674 io_object_t iterator
)
2678 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2680 IOLockLock(oIter
->lock
);
2681 didIt
= iter
->exitEntry();
2682 IOLockUnlock(oIter
->lock
);
2684 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2687 /* Routine io_registry_entry_from_path */
2688 kern_return_t
is_io_registry_entry_from_path(
2689 mach_port_t master_port
,
2691 io_object_t
*registry_entry
)
2693 IORegistryEntry
* entry
;
2695 if( master_port
!= master_device_port
)
2696 return( kIOReturnNotPrivileged
);
2698 entry
= IORegistryEntry::fromPath( path
);
2700 *registry_entry
= entry
;
2702 return( kIOReturnSuccess
);
2706 /* Routine io_registry_entry_from_path */
2707 kern_return_t
is_io_registry_entry_from_path_ool(
2708 mach_port_t master_port
,
2709 io_string_inband_t path
,
2710 io_buf_ptr_t path_ool
,
2711 mach_msg_type_number_t path_oolCnt
,
2712 kern_return_t
*result
,
2713 io_object_t
*registry_entry
)
2715 IORegistryEntry
* entry
;
2716 vm_map_offset_t map_data
;
2721 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2725 res
= err
= KERN_SUCCESS
;
2726 if (path
[0]) cpath
= path
;
2729 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2730 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2732 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2733 if (KERN_SUCCESS
== err
)
2735 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2736 cpath
= CAST_DOWN(const char *, map_data
);
2737 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2741 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2743 entry
= IORegistryEntry::fromPath(cpath
);
2744 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2747 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2749 if (KERN_SUCCESS
!= err
) res
= err
;
2750 *registry_entry
= entry
;
2757 /* Routine io_registry_entry_in_plane */
2758 kern_return_t
is_io_registry_entry_in_plane(
2759 io_object_t registry_entry
,
2761 boolean_t
*inPlane
)
2763 CHECK( IORegistryEntry
, registry_entry
, entry
);
2765 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2767 return( kIOReturnSuccess
);
2771 /* Routine io_registry_entry_get_path */
2772 kern_return_t
is_io_registry_entry_get_path(
2773 io_object_t registry_entry
,
2778 CHECK( IORegistryEntry
, registry_entry
, entry
);
2780 length
= sizeof( io_string_t
);
2781 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2782 return( kIOReturnSuccess
);
2784 return( kIOReturnBadArgument
);
2787 /* Routine io_registry_entry_get_path */
2788 kern_return_t
is_io_registry_entry_get_path_ool(
2789 io_object_t registry_entry
,
2791 io_string_inband_t path
,
2792 io_buf_ptr_t
*path_ool
,
2793 mach_msg_type_number_t
*path_oolCnt
)
2795 enum { kMaxPath
= 16384 };
2800 CHECK( IORegistryEntry
, registry_entry
, entry
);
2804 length
= sizeof(io_string_inband_t
);
2805 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2809 buf
= IONew(char, length
);
2810 if (!buf
) err
= kIOReturnNoMemory
;
2811 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2814 *path_oolCnt
= length
;
2815 err
= copyoutkdata(buf
, length
, path_ool
);
2817 if (buf
) IODelete(buf
, char, kMaxPath
);
2824 /* Routine io_registry_entry_get_name */
2825 kern_return_t
is_io_registry_entry_get_name(
2826 io_object_t registry_entry
,
2829 CHECK( IORegistryEntry
, registry_entry
, entry
);
2831 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2833 return( kIOReturnSuccess
);
2836 /* Routine io_registry_entry_get_name_in_plane */
2837 kern_return_t
is_io_registry_entry_get_name_in_plane(
2838 io_object_t registry_entry
,
2839 io_name_t planeName
,
2842 const IORegistryPlane
* plane
;
2843 CHECK( IORegistryEntry
, registry_entry
, entry
);
2846 plane
= IORegistryEntry::getPlane( planeName
);
2850 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2852 return( kIOReturnSuccess
);
2855 /* Routine io_registry_entry_get_location_in_plane */
2856 kern_return_t
is_io_registry_entry_get_location_in_plane(
2857 io_object_t registry_entry
,
2858 io_name_t planeName
,
2859 io_name_t location
)
2861 const IORegistryPlane
* plane
;
2862 CHECK( IORegistryEntry
, registry_entry
, entry
);
2865 plane
= IORegistryEntry::getPlane( planeName
);
2869 const char * cstr
= entry
->getLocation( plane
);
2872 strncpy( location
, cstr
, sizeof( io_name_t
));
2873 return( kIOReturnSuccess
);
2875 return( kIOReturnNotFound
);
2878 /* Routine io_registry_entry_get_registry_entry_id */
2879 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2880 io_object_t registry_entry
,
2881 uint64_t *entry_id
)
2883 CHECK( IORegistryEntry
, registry_entry
, entry
);
2885 *entry_id
= entry
->getRegistryEntryID();
2887 return (kIOReturnSuccess
);
2890 /* Routine io_registry_entry_get_property */
2891 kern_return_t
is_io_registry_entry_get_property_bytes(
2892 io_object_t registry_entry
,
2893 io_name_t property_name
,
2894 io_struct_inband_t buf
,
2895 mach_msg_type_number_t
*dataCnt
)
2903 unsigned int len
= 0;
2904 const void * bytes
= 0;
2905 IOReturn ret
= kIOReturnSuccess
;
2907 CHECK( IORegistryEntry
, registry_entry
, entry
);
2910 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2911 return kIOReturnNotPermitted
;
2914 obj
= entry
->copyProperty(property_name
);
2916 return( kIOReturnNoResources
);
2918 // One day OSData will be a common container base class
2920 if( (data
= OSDynamicCast( OSData
, obj
))) {
2921 len
= data
->getLength();
2922 bytes
= data
->getBytesNoCopy();
2923 if (!data
->isSerializable()) len
= 0;
2925 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2926 len
= str
->getLength() + 1;
2927 bytes
= str
->getCStringNoCopy();
2929 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2930 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2931 bytes
= boo
->isTrue() ? "Yes" : "No";
2933 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2934 offsetBytes
= off
->unsigned64BitValue();
2935 len
= off
->numberOfBytes();
2936 if (len
> sizeof(offsetBytes
)) len
= sizeof(offsetBytes
);
2937 bytes
= &offsetBytes
;
2938 #ifdef __BIG_ENDIAN__
2939 bytes
= (const void *)
2940 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2944 ret
= kIOReturnBadArgument
;
2948 ret
= kIOReturnIPCError
;
2951 bcopy( bytes
, buf
, len
);
2960 /* Routine io_registry_entry_get_property */
2961 kern_return_t
is_io_registry_entry_get_property(
2962 io_object_t registry_entry
,
2963 io_name_t property_name
,
2964 io_buf_ptr_t
*properties
,
2965 mach_msg_type_number_t
*propertiesCnt
)
2971 CHECK( IORegistryEntry
, registry_entry
, entry
);
2974 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2975 return kIOReturnNotPermitted
;
2978 obj
= entry
->copyProperty(property_name
);
2980 return( kIOReturnNotFound
);
2982 OSSerialize
* s
= OSSerialize::withCapacity(4096);
2985 return( kIOReturnNoMemory
);
2988 if( obj
->serialize( s
)) {
2989 len
= s
->getLength();
2990 *propertiesCnt
= len
;
2991 err
= copyoutkdata( s
->text(), len
, properties
);
2994 err
= kIOReturnUnsupported
;
3002 /* Routine io_registry_entry_get_property_recursively */
3003 kern_return_t
is_io_registry_entry_get_property_recursively(
3004 io_object_t registry_entry
,
3006 io_name_t property_name
,
3008 io_buf_ptr_t
*properties
,
3009 mach_msg_type_number_t
*propertiesCnt
)
3015 CHECK( IORegistryEntry
, registry_entry
, entry
);
3018 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3019 return kIOReturnNotPermitted
;
3022 obj
= entry
->copyProperty( property_name
,
3023 IORegistryEntry::getPlane( plane
), options
);
3025 return( kIOReturnNotFound
);
3027 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3030 return( kIOReturnNoMemory
);
3033 if( obj
->serialize( s
)) {
3034 len
= s
->getLength();
3035 *propertiesCnt
= len
;
3036 err
= copyoutkdata( s
->text(), len
, properties
);
3039 err
= kIOReturnUnsupported
;
3047 /* Routine io_registry_entry_get_properties */
3048 kern_return_t
is_io_registry_entry_get_properties(
3049 io_object_t registry_entry
,
3050 io_buf_ptr_t
*properties
,
3051 mach_msg_type_number_t
*propertiesCnt
)
3053 return (kIOReturnUnsupported
);
3058 struct GetPropertiesEditorRef
3061 IORegistryEntry
* entry
;
3062 OSCollection
* root
;
3065 static const OSMetaClassBase
*
3066 GetPropertiesEditor(void * reference
,
3068 OSCollection
* container
,
3069 const OSSymbol
* name
,
3070 const OSMetaClassBase
* value
)
3072 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
3074 if (!ref
->root
) ref
->root
= container
;
3075 if (ref
->root
== container
)
3077 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
3082 if (value
) value
->retain();
3086 #endif /* CONFIG_MACF */
3088 /* Routine io_registry_entry_get_properties */
3089 kern_return_t
is_io_registry_entry_get_properties_bin(
3090 io_object_t registry_entry
,
3091 io_buf_ptr_t
*properties
,
3092 mach_msg_type_number_t
*propertiesCnt
)
3094 kern_return_t err
= kIOReturnSuccess
;
3097 OSSerialize::Editor editor
= 0;
3100 CHECK(IORegistryEntry
, registry_entry
, entry
);
3103 GetPropertiesEditorRef ref
;
3104 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
3106 editor
= &GetPropertiesEditor
;
3108 ref
.cred
= kauth_cred_get();
3114 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3115 if (!s
) return (kIOReturnNoMemory
);
3117 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
3119 if (kIOReturnSuccess
== err
)
3121 len
= s
->getLength();
3122 *propertiesCnt
= len
;
3123 err
= copyoutkdata(s
->text(), len
, properties
);
3130 /* Routine io_registry_entry_get_property_bin */
3131 kern_return_t
is_io_registry_entry_get_property_bin(
3132 io_object_t registry_entry
,
3134 io_name_t property_name
,
3136 io_buf_ptr_t
*properties
,
3137 mach_msg_type_number_t
*propertiesCnt
)
3142 const OSSymbol
* sym
;
3144 CHECK( IORegistryEntry
, registry_entry
, entry
);
3147 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3148 return kIOReturnNotPermitted
;
3151 sym
= OSSymbol::withCString(property_name
);
3152 if (!sym
) return (kIOReturnNoMemory
);
3154 if (gIORegistryEntryPropertyKeysKey
== sym
)
3156 obj
= entry
->copyPropertyKeys();
3160 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
3162 obj
= entry
->copyProperty(property_name
,
3163 IORegistryEntry::getPlane(plane
), options
);
3167 obj
= entry
->copyProperty(property_name
);
3169 if (obj
&& gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
3173 if (!obj
) return (kIOReturnNotFound
);
3175 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3178 return( kIOReturnNoMemory
);
3181 if( obj
->serialize( s
)) {
3182 len
= s
->getLength();
3183 *propertiesCnt
= len
;
3184 err
= copyoutkdata( s
->text(), len
, properties
);
3186 } else err
= kIOReturnUnsupported
;
3195 /* Routine io_registry_entry_set_properties */
3196 kern_return_t is_io_registry_entry_set_properties
3198 io_object_t registry_entry
,
3199 io_buf_ptr_t properties
,
3200 mach_msg_type_number_t propertiesCnt
,
3201 kern_return_t
* result
)
3207 vm_map_offset_t map_data
;
3209 CHECK( IORegistryEntry
, registry_entry
, entry
);
3211 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
3212 return( kIOReturnMessageTooLarge
);
3214 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3215 data
= CAST_DOWN(vm_offset_t
, map_data
);
3217 if( KERN_SUCCESS
== err
) {
3219 FAKE_STACK_FRAME(entry
->getMetaClass());
3221 // must return success after vm_map_copyout() succeeds
3222 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3223 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3226 res
= kIOReturnBadArgument
;
3228 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3229 registry_entry
, obj
))
3231 res
= kIOReturnNotPermitted
;
3236 res
= entry
->setProperties( obj
);
3242 FAKE_STACK_FRAME_END();
3251 /* Routine io_registry_entry_get_child_iterator */
3252 kern_return_t
is_io_registry_entry_get_child_iterator(
3253 io_object_t registry_entry
,
3255 io_object_t
*iterator
)
3257 CHECK( IORegistryEntry
, registry_entry
, entry
);
3259 *iterator
= entry
->getChildIterator(
3260 IORegistryEntry::getPlane( plane
));
3262 return( kIOReturnSuccess
);
3265 /* Routine io_registry_entry_get_parent_iterator */
3266 kern_return_t
is_io_registry_entry_get_parent_iterator(
3267 io_object_t registry_entry
,
3269 io_object_t
*iterator
)
3271 CHECK( IORegistryEntry
, registry_entry
, entry
);
3273 *iterator
= entry
->getParentIterator(
3274 IORegistryEntry::getPlane( plane
));
3276 return( kIOReturnSuccess
);
3279 /* Routine io_service_get_busy_state */
3280 kern_return_t
is_io_service_get_busy_state(
3281 io_object_t _service
,
3282 uint32_t *busyState
)
3284 CHECK( IOService
, _service
, service
);
3286 *busyState
= service
->getBusyState();
3288 return( kIOReturnSuccess
);
3291 /* Routine io_service_get_state */
3292 kern_return_t
is_io_service_get_state(
3293 io_object_t _service
,
3295 uint32_t *busy_state
,
3296 uint64_t *accumulated_busy_time
)
3298 CHECK( IOService
, _service
, service
);
3300 *state
= service
->getState();
3301 *busy_state
= service
->getBusyState();
3302 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3304 return( kIOReturnSuccess
);
3307 /* Routine io_service_wait_quiet */
3308 kern_return_t
is_io_service_wait_quiet(
3309 io_object_t _service
,
3310 mach_timespec_t wait_time
)
3314 CHECK( IOService
, _service
, service
);
3316 timeoutNS
= wait_time
.tv_sec
;
3317 timeoutNS
*= kSecondScale
;
3318 timeoutNS
+= wait_time
.tv_nsec
;
3320 return( service
->waitQuiet(timeoutNS
) );
3323 /* Routine io_service_request_probe */
3324 kern_return_t
is_io_service_request_probe(
3325 io_object_t _service
,
3328 CHECK( IOService
, _service
, service
);
3330 return( service
->requestProbe( options
));
3333 /* Routine io_service_get_authorization_id */
3334 kern_return_t
is_io_service_get_authorization_id(
3335 io_object_t _service
,
3336 uint64_t *authorization_id
)
3340 CHECK( IOService
, _service
, service
);
3342 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3343 kIOClientPrivilegeAdministrator
);
3344 if( kIOReturnSuccess
!= kr
)
3347 *authorization_id
= service
->getAuthorizationID();
3352 /* Routine io_service_set_authorization_id */
3353 kern_return_t
is_io_service_set_authorization_id(
3354 io_object_t _service
,
3355 uint64_t authorization_id
)
3357 CHECK( IOService
, _service
, service
);
3359 return( service
->setAuthorizationID( authorization_id
) );
3362 /* Routine io_service_open_ndr */
3363 kern_return_t
is_io_service_open_extended(
3364 io_object_t _service
,
3366 uint32_t connect_type
,
3368 io_buf_ptr_t properties
,
3369 mach_msg_type_number_t propertiesCnt
,
3370 kern_return_t
* result
,
3371 io_object_t
*connection
)
3373 IOUserClient
* client
= 0;
3374 kern_return_t err
= KERN_SUCCESS
;
3375 IOReturn res
= kIOReturnSuccess
;
3376 OSDictionary
* propertiesDict
= 0;
3378 bool disallowAccess
;
3380 CHECK( IOService
, _service
, service
);
3382 if (!owningTask
) return (kIOReturnBadArgument
);
3383 assert(owningTask
== current_task());
3384 if (owningTask
!= current_task()) return (kIOReturnBadArgument
);
3388 if (properties
) return (kIOReturnUnsupported
);
3393 vm_map_offset_t map_data
;
3395 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3396 return( kIOReturnMessageTooLarge
);
3398 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3400 data
= CAST_DOWN(vm_offset_t
, map_data
);
3401 if (KERN_SUCCESS
== err
)
3403 // must return success after vm_map_copyout() succeeds
3404 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3405 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3406 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3407 if (!propertiesDict
)
3409 res
= kIOReturnBadArgument
;
3414 if (kIOReturnSuccess
!= res
)
3418 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3421 if (!propertiesDict
)
3422 propertiesDict
= OSDictionary::withCapacity(4);
3423 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3427 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3432 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3433 connect_type
, propertiesDict
, &client
);
3436 propertiesDict
->release();
3438 if (res
== kIOReturnSuccess
)
3440 assert( OSDynamicCast(IOUserClient
, client
) );
3442 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3443 client
->closed
= false;
3445 disallowAccess
= (crossEndian
3446 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3447 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3448 if (disallowAccess
) res
= kIOReturnUnsupported
;
3450 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3451 res
= kIOReturnNotPermitted
;
3454 if (kIOReturnSuccess
== res
) res
= client
->registerOwner(owningTask
);
3456 if (kIOReturnSuccess
!= res
)
3458 IOStatisticsClientCall();
3459 client
->clientClose();
3464 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3467 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3468 creatorName
->release();
3470 client
->setTerminateDefer(service
, false);
3475 *connection
= client
;
3481 /* Routine io_service_close */
3482 kern_return_t
is_io_service_close(
3483 io_object_t connection
)
3486 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3487 return( kIOReturnSuccess
);
3489 CHECK( IOUserClient
, connection
, client
);
3491 IOStatisticsClientCall();
3493 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
))
3495 client
->clientClose();
3499 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3500 client
->getRegistryEntryID(), client
->getName());
3503 return( kIOReturnSuccess
);
3506 /* Routine io_connect_get_service */
3507 kern_return_t
is_io_connect_get_service(
3508 io_object_t connection
,
3509 io_object_t
*service
)
3511 IOService
* theService
;
3513 CHECK( IOUserClient
, connection
, client
);
3515 theService
= client
->getService();
3517 theService
->retain();
3519 *service
= theService
;
3521 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3524 /* Routine io_connect_set_notification_port */
3525 kern_return_t
is_io_connect_set_notification_port(
3526 io_object_t connection
,
3527 uint32_t notification_type
,
3531 CHECK( IOUserClient
, connection
, client
);
3533 IOStatisticsClientCall();
3534 return( client
->registerNotificationPort( port
, notification_type
,
3535 (io_user_reference_t
) reference
));
3538 /* Routine io_connect_set_notification_port */
3539 kern_return_t
is_io_connect_set_notification_port_64(
3540 io_object_t connection
,
3541 uint32_t notification_type
,
3543 io_user_reference_t reference
)
3545 CHECK( IOUserClient
, connection
, client
);
3547 IOStatisticsClientCall();
3548 return( client
->registerNotificationPort( port
, notification_type
,
3552 /* Routine io_connect_map_memory_into_task */
3553 kern_return_t is_io_connect_map_memory_into_task
3555 io_connect_t connection
,
3556 uint32_t memory_type
,
3558 mach_vm_address_t
*address
,
3559 mach_vm_size_t
*size
,
3566 CHECK( IOUserClient
, connection
, client
);
3568 if (!into_task
) return (kIOReturnBadArgument
);
3570 IOStatisticsClientCall();
3571 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3574 *address
= map
->getAddress();
3576 *size
= map
->getSize();
3578 if( client
->sharedInstance
3579 || (into_task
!= current_task())) {
3580 // push a name out to the task owning the map,
3581 // so we can clean up maps
3582 mach_port_name_t name __unused
=
3583 IOMachPort::makeSendRightForTask(
3584 into_task
, map
, IKOT_IOKIT_OBJECT
);
3587 // keep it with the user client
3588 IOLockLock( gIOObjectPortLock
);
3589 if( 0 == client
->mappings
)
3590 client
->mappings
= OSSet::withCapacity(2);
3591 if( client
->mappings
)
3592 client
->mappings
->setObject( map
);
3593 IOLockUnlock( gIOObjectPortLock
);
3596 err
= kIOReturnSuccess
;
3599 err
= kIOReturnBadArgument
;
3604 /* Routine is_io_connect_map_memory */
3605 kern_return_t
is_io_connect_map_memory(
3606 io_object_t connect
,
3614 mach_vm_address_t address
;
3615 mach_vm_size_t size
;
3617 address
= SCALAR64(*mapAddr
);
3618 size
= SCALAR64(*mapSize
);
3620 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3622 *mapAddr
= SCALAR32(address
);
3623 *mapSize
= SCALAR32(size
);
3630 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3633 IOMemoryMap
* map
= 0;
3635 IOLockLock(gIOObjectPortLock
);
3637 iter
= OSCollectionIterator::withCollection(mappings
);
3640 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3642 if(mem
== map
->getMemoryDescriptor())
3645 mappings
->removeObject(map
);
3652 IOLockUnlock(gIOObjectPortLock
);
3659 /* Routine io_connect_unmap_memory_from_task */
3660 kern_return_t is_io_connect_unmap_memory_from_task
3662 io_connect_t connection
,
3663 uint32_t memory_type
,
3665 mach_vm_address_t address
)
3668 IOOptionBits options
= 0;
3669 IOMemoryDescriptor
* memory
;
3672 CHECK( IOUserClient
, connection
, client
);
3674 if (!from_task
) return (kIOReturnBadArgument
);
3676 IOStatisticsClientCall();
3677 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3679 if( memory
&& (kIOReturnSuccess
== err
)) {
3681 options
= (options
& ~kIOMapUserOptionsMask
)
3682 | kIOMapAnywhere
| kIOMapReference
;
3684 map
= memory
->createMappingInTask( from_task
, address
, options
);
3688 IOLockLock( gIOObjectPortLock
);
3689 if( client
->mappings
)
3690 client
->mappings
->removeObject( map
);
3691 IOLockUnlock( gIOObjectPortLock
);
3693 mach_port_name_t name
= 0;
3694 if (from_task
!= current_task())
3695 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3698 map
->userClientUnmap();
3699 err
= iokit_mod_send_right( from_task
, name
, -2 );
3700 err
= kIOReturnSuccess
;
3703 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3704 if (from_task
== current_task())
3708 err
= kIOReturnBadArgument
;
3714 kern_return_t
is_io_connect_unmap_memory(
3715 io_object_t connect
,
3721 mach_vm_address_t address
;
3723 address
= SCALAR64(mapAddr
);
3725 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3731 /* Routine io_connect_add_client */
3732 kern_return_t
is_io_connect_add_client(
3733 io_object_t connection
,
3734 io_object_t connect_to
)
3736 CHECK( IOUserClient
, connection
, client
);
3737 CHECK( IOUserClient
, connect_to
, to
);
3739 IOStatisticsClientCall();
3740 return( client
->connectClient( to
) );
3744 /* Routine io_connect_set_properties */
3745 kern_return_t
is_io_connect_set_properties(
3746 io_object_t connection
,
3747 io_buf_ptr_t properties
,
3748 mach_msg_type_number_t propertiesCnt
,
3749 kern_return_t
* result
)
3751 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3754 /* Routine io_user_client_method */
3755 kern_return_t is_io_connect_method_var_output
3757 io_connect_t connection
,
3759 io_scalar_inband64_t scalar_input
,
3760 mach_msg_type_number_t scalar_inputCnt
,
3761 io_struct_inband_t inband_input
,
3762 mach_msg_type_number_t inband_inputCnt
,
3763 mach_vm_address_t ool_input
,
3764 mach_vm_size_t ool_input_size
,
3765 io_struct_inband_t inband_output
,
3766 mach_msg_type_number_t
*inband_outputCnt
,
3767 io_scalar_inband64_t scalar_output
,
3768 mach_msg_type_number_t
*scalar_outputCnt
,
3769 io_buf_ptr_t
*var_output
,
3770 mach_msg_type_number_t
*var_outputCnt
3773 CHECK( IOUserClient
, connection
, client
);
3775 IOExternalMethodArguments args
;
3777 IOMemoryDescriptor
* inputMD
= 0;
3778 OSObject
* structureVariableOutputData
= 0;
3780 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3781 args
.__reservedA
= 0;
3782 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3784 args
.selector
= selector
;
3786 args
.asyncWakePort
= MACH_PORT_NULL
;
3787 args
.asyncReference
= 0;
3788 args
.asyncReferenceCount
= 0;
3789 args
.structureVariableOutputData
= &structureVariableOutputData
;
3791 args
.scalarInput
= scalar_input
;
3792 args
.scalarInputCount
= scalar_inputCnt
;
3793 args
.structureInput
= inband_input
;
3794 args
.structureInputSize
= inband_inputCnt
;
3797 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3798 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3801 args
.structureInputDescriptor
= inputMD
;
3803 args
.scalarOutput
= scalar_output
;
3804 args
.scalarOutputCount
= *scalar_outputCnt
;
3805 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3806 args
.structureOutput
= inband_output
;
3807 args
.structureOutputSize
= *inband_outputCnt
;
3808 args
.structureOutputDescriptor
= NULL
;
3809 args
.structureOutputDescriptorSize
= 0;
3811 IOStatisticsClientCall();
3812 ret
= client
->externalMethod( selector
, &args
);
3814 *scalar_outputCnt
= args
.scalarOutputCount
;
3815 *inband_outputCnt
= args
.structureOutputSize
;
3817 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3819 OSSerialize
* serialize
;
3823 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3825 len
= serialize
->getLength();
3826 *var_outputCnt
= len
;
3827 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3829 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3831 len
= data
->getLength();
3832 *var_outputCnt
= len
;
3833 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3837 ret
= kIOReturnUnderrun
;
3843 if (structureVariableOutputData
)
3844 structureVariableOutputData
->release();
3849 /* Routine io_user_client_method */
3850 kern_return_t is_io_connect_method
3852 io_connect_t connection
,
3854 io_scalar_inband64_t scalar_input
,
3855 mach_msg_type_number_t scalar_inputCnt
,
3856 io_struct_inband_t inband_input
,
3857 mach_msg_type_number_t inband_inputCnt
,
3858 mach_vm_address_t ool_input
,
3859 mach_vm_size_t ool_input_size
,
3860 io_struct_inband_t inband_output
,
3861 mach_msg_type_number_t
*inband_outputCnt
,
3862 io_scalar_inband64_t scalar_output
,
3863 mach_msg_type_number_t
*scalar_outputCnt
,
3864 mach_vm_address_t ool_output
,
3865 mach_vm_size_t
*ool_output_size
3868 CHECK( IOUserClient
, connection
, client
);
3870 IOExternalMethodArguments args
;
3872 IOMemoryDescriptor
* inputMD
= 0;
3873 IOMemoryDescriptor
* outputMD
= 0;
3875 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3876 args
.__reservedA
= 0;
3877 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3879 args
.selector
= selector
;
3881 args
.asyncWakePort
= MACH_PORT_NULL
;
3882 args
.asyncReference
= 0;
3883 args
.asyncReferenceCount
= 0;
3884 args
.structureVariableOutputData
= 0;
3886 args
.scalarInput
= scalar_input
;
3887 args
.scalarInputCount
= scalar_inputCnt
;
3888 args
.structureInput
= inband_input
;
3889 args
.structureInputSize
= inband_inputCnt
;
3892 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3893 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3896 args
.structureInputDescriptor
= inputMD
;
3898 args
.scalarOutput
= scalar_output
;
3899 args
.scalarOutputCount
= *scalar_outputCnt
;
3900 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3901 args
.structureOutput
= inband_output
;
3902 args
.structureOutputSize
= *inband_outputCnt
;
3904 if (ool_output
&& ool_output_size
)
3906 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3907 kIODirectionIn
, current_task());
3910 args
.structureOutputDescriptor
= outputMD
;
3911 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3913 IOStatisticsClientCall();
3914 ret
= client
->externalMethod( selector
, &args
);
3916 *scalar_outputCnt
= args
.scalarOutputCount
;
3917 *inband_outputCnt
= args
.structureOutputSize
;
3918 *ool_output_size
= args
.structureOutputDescriptorSize
;
3923 outputMD
->release();
3928 /* Routine io_async_user_client_method */
3929 kern_return_t is_io_connect_async_method
3931 io_connect_t connection
,
3932 mach_port_t wake_port
,
3933 io_async_ref64_t reference
,
3934 mach_msg_type_number_t referenceCnt
,
3936 io_scalar_inband64_t scalar_input
,
3937 mach_msg_type_number_t scalar_inputCnt
,
3938 io_struct_inband_t inband_input
,
3939 mach_msg_type_number_t inband_inputCnt
,
3940 mach_vm_address_t ool_input
,
3941 mach_vm_size_t ool_input_size
,
3942 io_struct_inband_t inband_output
,
3943 mach_msg_type_number_t
*inband_outputCnt
,
3944 io_scalar_inband64_t scalar_output
,
3945 mach_msg_type_number_t
*scalar_outputCnt
,
3946 mach_vm_address_t ool_output
,
3947 mach_vm_size_t
* ool_output_size
3950 CHECK( IOUserClient
, connection
, client
);
3952 IOExternalMethodArguments args
;
3954 IOMemoryDescriptor
* inputMD
= 0;
3955 IOMemoryDescriptor
* outputMD
= 0;
3957 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3958 args
.__reservedA
= 0;
3959 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3961 reference
[0] = (io_user_reference_t
) wake_port
;
3962 if (vm_map_is_64bit(get_task_map(current_task())))
3963 reference
[0] |= kIOUCAsync64Flag
;
3965 args
.selector
= selector
;
3967 args
.asyncWakePort
= wake_port
;
3968 args
.asyncReference
= reference
;
3969 args
.asyncReferenceCount
= referenceCnt
;
3971 args
.scalarInput
= scalar_input
;
3972 args
.scalarInputCount
= scalar_inputCnt
;
3973 args
.structureInput
= inband_input
;
3974 args
.structureInputSize
= inband_inputCnt
;
3977 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3978 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3981 args
.structureInputDescriptor
= inputMD
;
3983 args
.scalarOutput
= scalar_output
;
3984 args
.scalarOutputCount
= *scalar_outputCnt
;
3985 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3986 args
.structureOutput
= inband_output
;
3987 args
.structureOutputSize
= *inband_outputCnt
;
3991 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3992 kIODirectionIn
, current_task());
3995 args
.structureOutputDescriptor
= outputMD
;
3996 args
.structureOutputDescriptorSize
= *ool_output_size
;
3998 IOStatisticsClientCall();
3999 ret
= client
->externalMethod( selector
, &args
);
4001 *inband_outputCnt
= args
.structureOutputSize
;
4002 *ool_output_size
= args
.structureOutputDescriptorSize
;
4007 outputMD
->release();
4012 /* Routine io_connect_method_scalarI_scalarO */
4013 kern_return_t
is_io_connect_method_scalarI_scalarO(
4014 io_object_t connect
,
4016 io_scalar_inband_t input
,
4017 mach_msg_type_number_t inputCount
,
4018 io_scalar_inband_t output
,
4019 mach_msg_type_number_t
* outputCount
)
4023 io_scalar_inband64_t _input
;
4024 io_scalar_inband64_t _output
;
4026 mach_msg_type_number_t struct_outputCnt
= 0;
4027 mach_vm_size_t ool_output_size
= 0;
4029 bzero(&_output
[0], sizeof(_output
));
4030 for (i
= 0; i
< inputCount
; i
++)
4031 _input
[i
] = SCALAR64(input
[i
]);
4033 err
= is_io_connect_method(connect
, index
,
4037 NULL
, &struct_outputCnt
,
4038 _output
, outputCount
,
4039 0, &ool_output_size
);
4041 for (i
= 0; i
< *outputCount
; i
++)
4042 output
[i
] = SCALAR32(_output
[i
]);
4047 kern_return_t
shim_io_connect_method_scalarI_scalarO(
4048 IOExternalMethod
* method
,
4050 const io_user_scalar_t
* input
,
4051 mach_msg_type_number_t inputCount
,
4052 io_user_scalar_t
* output
,
4053 mach_msg_type_number_t
* outputCount
)
4056 io_scalar_inband_t _output
;
4058 err
= kIOReturnBadArgument
;
4060 bzero(&_output
[0], sizeof(_output
));
4063 if( inputCount
!= method
->count0
)
4065 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4066 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4069 if( *outputCount
!= method
->count1
)
4071 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4072 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4076 func
= method
->func
;
4078 switch( inputCount
) {
4081 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4082 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4085 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4086 ARG32(input
[3]), ARG32(input
[4]),
4090 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4092 &_output
[0], &_output
[1] );
4095 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4096 &_output
[0], &_output
[1], &_output
[2] );
4099 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4100 &_output
[0], &_output
[1], &_output
[2],
4104 err
= (object
->*func
)( ARG32(input
[0]),
4105 &_output
[0], &_output
[1], &_output
[2],
4106 &_output
[3], &_output
[4] );
4109 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
4110 &_output
[3], &_output
[4], &_output
[5] );
4114 IOLog("%s: Bad method table\n", object
->getName());
4120 for (i
= 0; i
< *outputCount
; i
++)
4121 output
[i
] = SCALAR32(_output
[i
]);
4126 /* Routine io_async_method_scalarI_scalarO */
4127 kern_return_t
is_io_async_method_scalarI_scalarO(
4128 io_object_t connect
,
4129 mach_port_t wake_port
,
4130 io_async_ref_t reference
,
4131 mach_msg_type_number_t referenceCnt
,
4133 io_scalar_inband_t input
,
4134 mach_msg_type_number_t inputCount
,
4135 io_scalar_inband_t output
,
4136 mach_msg_type_number_t
* outputCount
)
4140 io_scalar_inband64_t _input
;
4141 io_scalar_inband64_t _output
;
4142 io_async_ref64_t _reference
;
4144 bzero(&_output
[0], sizeof(_output
));
4145 for (i
= 0; i
< referenceCnt
; i
++)
4146 _reference
[i
] = REF64(reference
[i
]);
4148 mach_msg_type_number_t struct_outputCnt
= 0;
4149 mach_vm_size_t ool_output_size
= 0;
4151 for (i
= 0; i
< inputCount
; i
++)
4152 _input
[i
] = SCALAR64(input
[i
]);
4154 err
= is_io_connect_async_method(connect
,
4155 wake_port
, _reference
, referenceCnt
,
4160 NULL
, &struct_outputCnt
,
4161 _output
, outputCount
,
4162 0, &ool_output_size
);
4164 for (i
= 0; i
< *outputCount
; i
++)
4165 output
[i
] = SCALAR32(_output
[i
]);
4169 /* Routine io_async_method_scalarI_structureO */
4170 kern_return_t
is_io_async_method_scalarI_structureO(
4171 io_object_t connect
,
4172 mach_port_t wake_port
,
4173 io_async_ref_t reference
,
4174 mach_msg_type_number_t referenceCnt
,
4176 io_scalar_inband_t input
,
4177 mach_msg_type_number_t inputCount
,
4178 io_struct_inband_t output
,
4179 mach_msg_type_number_t
* outputCount
)
4182 io_scalar_inband64_t _input
;
4183 io_async_ref64_t _reference
;
4185 for (i
= 0; i
< referenceCnt
; i
++)
4186 _reference
[i
] = REF64(reference
[i
]);
4188 mach_msg_type_number_t scalar_outputCnt
= 0;
4189 mach_vm_size_t ool_output_size
= 0;
4191 for (i
= 0; i
< inputCount
; i
++)
4192 _input
[i
] = SCALAR64(input
[i
]);
4194 return (is_io_connect_async_method(connect
,
4195 wake_port
, _reference
, referenceCnt
,
4200 output
, outputCount
,
4201 NULL
, &scalar_outputCnt
,
4202 0, &ool_output_size
));
4205 /* Routine io_async_method_scalarI_structureI */
4206 kern_return_t
is_io_async_method_scalarI_structureI(
4207 io_connect_t connect
,
4208 mach_port_t wake_port
,
4209 io_async_ref_t reference
,
4210 mach_msg_type_number_t referenceCnt
,
4212 io_scalar_inband_t input
,
4213 mach_msg_type_number_t inputCount
,
4214 io_struct_inband_t inputStruct
,
4215 mach_msg_type_number_t inputStructCount
)
4218 io_scalar_inband64_t _input
;
4219 io_async_ref64_t _reference
;
4221 for (i
= 0; i
< referenceCnt
; i
++)
4222 _reference
[i
] = REF64(reference
[i
]);
4224 mach_msg_type_number_t scalar_outputCnt
= 0;
4225 mach_msg_type_number_t inband_outputCnt
= 0;
4226 mach_vm_size_t ool_output_size
= 0;
4228 for (i
= 0; i
< inputCount
; i
++)
4229 _input
[i
] = SCALAR64(input
[i
]);
4231 return (is_io_connect_async_method(connect
,
4232 wake_port
, _reference
, referenceCnt
,
4235 inputStruct
, inputStructCount
,
4237 NULL
, &inband_outputCnt
,
4238 NULL
, &scalar_outputCnt
,
4239 0, &ool_output_size
));
4242 /* Routine io_async_method_structureI_structureO */
4243 kern_return_t
is_io_async_method_structureI_structureO(
4244 io_object_t connect
,
4245 mach_port_t wake_port
,
4246 io_async_ref_t reference
,
4247 mach_msg_type_number_t referenceCnt
,
4249 io_struct_inband_t input
,
4250 mach_msg_type_number_t inputCount
,
4251 io_struct_inband_t output
,
4252 mach_msg_type_number_t
* outputCount
)
4255 mach_msg_type_number_t scalar_outputCnt
= 0;
4256 mach_vm_size_t ool_output_size
= 0;
4257 io_async_ref64_t _reference
;
4259 for (i
= 0; i
< referenceCnt
; i
++)
4260 _reference
[i
] = REF64(reference
[i
]);
4262 return (is_io_connect_async_method(connect
,
4263 wake_port
, _reference
, referenceCnt
,
4268 output
, outputCount
,
4269 NULL
, &scalar_outputCnt
,
4270 0, &ool_output_size
));
4274 kern_return_t
shim_io_async_method_scalarI_scalarO(
4275 IOExternalAsyncMethod
* method
,
4277 mach_port_t asyncWakePort
,
4278 io_user_reference_t
* asyncReference
,
4279 uint32_t asyncReferenceCount
,
4280 const io_user_scalar_t
* input
,
4281 mach_msg_type_number_t inputCount
,
4282 io_user_scalar_t
* output
,
4283 mach_msg_type_number_t
* outputCount
)
4287 io_scalar_inband_t _output
;
4289 io_async_ref_t reference
;
4291 bzero(&_output
[0], sizeof(_output
));
4292 for (i
= 0; i
< asyncReferenceCount
; i
++)
4293 reference
[i
] = REF32(asyncReference
[i
]);
4295 err
= kIOReturnBadArgument
;
4299 if( inputCount
!= method
->count0
)
4301 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4302 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4305 if( *outputCount
!= method
->count1
)
4307 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4308 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4312 func
= method
->func
;
4314 switch( inputCount
) {
4317 err
= (object
->*func
)( reference
,
4318 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4319 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4322 err
= (object
->*func
)( reference
,
4323 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4324 ARG32(input
[3]), ARG32(input
[4]),
4328 err
= (object
->*func
)( reference
,
4329 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4331 &_output
[0], &_output
[1] );
4334 err
= (object
->*func
)( reference
,
4335 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4336 &_output
[0], &_output
[1], &_output
[2] );
4339 err
= (object
->*func
)( reference
,
4340 ARG32(input
[0]), ARG32(input
[1]),
4341 &_output
[0], &_output
[1], &_output
[2],
4345 err
= (object
->*func
)( reference
,
4347 &_output
[0], &_output
[1], &_output
[2],
4348 &_output
[3], &_output
[4] );
4351 err
= (object
->*func
)( reference
,
4352 &_output
[0], &_output
[1], &_output
[2],
4353 &_output
[3], &_output
[4], &_output
[5] );
4357 IOLog("%s: Bad method table\n", object
->getName());
4362 for (i
= 0; i
< *outputCount
; i
++)
4363 output
[i
] = SCALAR32(_output
[i
]);
4369 /* Routine io_connect_method_scalarI_structureO */
4370 kern_return_t
is_io_connect_method_scalarI_structureO(
4371 io_object_t connect
,
4373 io_scalar_inband_t input
,
4374 mach_msg_type_number_t inputCount
,
4375 io_struct_inband_t output
,
4376 mach_msg_type_number_t
* outputCount
)
4379 io_scalar_inband64_t _input
;
4381 mach_msg_type_number_t scalar_outputCnt
= 0;
4382 mach_vm_size_t ool_output_size
= 0;
4384 for (i
= 0; i
< inputCount
; i
++)
4385 _input
[i
] = SCALAR64(input
[i
]);
4387 return (is_io_connect_method(connect
, index
,
4391 output
, outputCount
,
4392 NULL
, &scalar_outputCnt
,
4393 0, &ool_output_size
));
4396 kern_return_t
shim_io_connect_method_scalarI_structureO(
4398 IOExternalMethod
* method
,
4400 const io_user_scalar_t
* input
,
4401 mach_msg_type_number_t inputCount
,
4402 io_struct_inband_t output
,
4403 IOByteCount
* outputCount
)
4408 err
= kIOReturnBadArgument
;
4411 if( inputCount
!= method
->count0
)
4413 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4414 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4417 if( (kIOUCVariableStructureSize
!= method
->count1
)
4418 && (*outputCount
!= method
->count1
))
4420 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4421 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4425 func
= method
->func
;
4427 switch( inputCount
) {
4430 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4431 ARG32(input
[3]), ARG32(input
[4]),
4435 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4437 output
, (void *)outputCount
);
4440 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4441 output
, (void *)outputCount
, 0 );
4444 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4445 output
, (void *)outputCount
, 0, 0 );
4448 err
= (object
->*func
)( ARG32(input
[0]),
4449 output
, (void *)outputCount
, 0, 0, 0 );
4452 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4456 IOLog("%s: Bad method table\n", object
->getName());
4465 kern_return_t
shim_io_async_method_scalarI_structureO(
4466 IOExternalAsyncMethod
* method
,
4468 mach_port_t asyncWakePort
,
4469 io_user_reference_t
* asyncReference
,
4470 uint32_t asyncReferenceCount
,
4471 const io_user_scalar_t
* input
,
4472 mach_msg_type_number_t inputCount
,
4473 io_struct_inband_t output
,
4474 mach_msg_type_number_t
* outputCount
)
4479 io_async_ref_t reference
;
4481 for (i
= 0; i
< asyncReferenceCount
; i
++)
4482 reference
[i
] = REF32(asyncReference
[i
]);
4484 err
= kIOReturnBadArgument
;
4486 if( inputCount
!= method
->count0
)
4488 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4489 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4492 if( (kIOUCVariableStructureSize
!= method
->count1
)
4493 && (*outputCount
!= method
->count1
))
4495 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4496 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4500 func
= method
->func
;
4502 switch( inputCount
) {
4505 err
= (object
->*func
)( reference
,
4506 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4507 ARG32(input
[3]), ARG32(input
[4]),
4511 err
= (object
->*func
)( reference
,
4512 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4514 output
, (void *)outputCount
);
4517 err
= (object
->*func
)( reference
,
4518 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4519 output
, (void *)outputCount
, 0 );
4522 err
= (object
->*func
)( reference
,
4523 ARG32(input
[0]), ARG32(input
[1]),
4524 output
, (void *)outputCount
, 0, 0 );
4527 err
= (object
->*func
)( reference
,
4529 output
, (void *)outputCount
, 0, 0, 0 );
4532 err
= (object
->*func
)( reference
,
4533 output
, (void *)outputCount
, 0, 0, 0, 0 );
4537 IOLog("%s: Bad method table\n", object
->getName());
4545 /* Routine io_connect_method_scalarI_structureI */
4546 kern_return_t
is_io_connect_method_scalarI_structureI(
4547 io_connect_t connect
,
4549 io_scalar_inband_t input
,
4550 mach_msg_type_number_t inputCount
,
4551 io_struct_inband_t inputStruct
,
4552 mach_msg_type_number_t inputStructCount
)
4555 io_scalar_inband64_t _input
;
4557 mach_msg_type_number_t scalar_outputCnt
= 0;
4558 mach_msg_type_number_t inband_outputCnt
= 0;
4559 mach_vm_size_t ool_output_size
= 0;
4561 for (i
= 0; i
< inputCount
; i
++)
4562 _input
[i
] = SCALAR64(input
[i
]);
4564 return (is_io_connect_method(connect
, index
,
4566 inputStruct
, inputStructCount
,
4568 NULL
, &inband_outputCnt
,
4569 NULL
, &scalar_outputCnt
,
4570 0, &ool_output_size
));
4573 kern_return_t
shim_io_connect_method_scalarI_structureI(
4574 IOExternalMethod
* method
,
4576 const io_user_scalar_t
* input
,
4577 mach_msg_type_number_t inputCount
,
4578 io_struct_inband_t inputStruct
,
4579 mach_msg_type_number_t inputStructCount
)
4582 IOReturn err
= kIOReturnBadArgument
;
4586 if (inputCount
!= method
->count0
)
4588 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4589 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4592 if( (kIOUCVariableStructureSize
!= method
->count1
)
4593 && (inputStructCount
!= method
->count1
))
4595 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputStructCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4596 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4600 func
= method
->func
;
4602 switch( inputCount
) {
4605 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4606 ARG32(input
[3]), ARG32(input
[4]),
4610 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4612 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4615 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4616 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4620 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4621 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4625 err
= (object
->*func
)( ARG32(input
[0]),
4626 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4630 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4635 IOLog("%s: Bad method table\n", object
->getName());
4643 kern_return_t
shim_io_async_method_scalarI_structureI(
4644 IOExternalAsyncMethod
* method
,
4646 mach_port_t asyncWakePort
,
4647 io_user_reference_t
* asyncReference
,
4648 uint32_t asyncReferenceCount
,
4649 const io_user_scalar_t
* input
,
4650 mach_msg_type_number_t inputCount
,
4651 io_struct_inband_t inputStruct
,
4652 mach_msg_type_number_t inputStructCount
)
4656 IOReturn err
= kIOReturnBadArgument
;
4657 io_async_ref_t reference
;
4659 for (i
= 0; i
< asyncReferenceCount
; i
++)
4660 reference
[i
] = REF32(asyncReference
[i
]);
4664 if (inputCount
!= method
->count0
)
4666 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4667 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4670 if( (kIOUCVariableStructureSize
!= method
->count1
)
4671 && (inputStructCount
!= method
->count1
))
4673 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputStructCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4674 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4678 func
= method
->func
;
4680 switch( inputCount
) {
4683 err
= (object
->*func
)( reference
,
4684 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4685 ARG32(input
[3]), ARG32(input
[4]),
4689 err
= (object
->*func
)( reference
,
4690 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4692 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4695 err
= (object
->*func
)( reference
,
4696 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4697 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4701 err
= (object
->*func
)( reference
,
4702 ARG32(input
[0]), ARG32(input
[1]),
4703 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4707 err
= (object
->*func
)( reference
,
4709 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4713 err
= (object
->*func
)( reference
,
4714 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4719 IOLog("%s: Bad method table\n", object
->getName());
4727 /* Routine io_connect_method_structureI_structureO */
4728 kern_return_t
is_io_connect_method_structureI_structureO(
4729 io_object_t connect
,
4731 io_struct_inband_t input
,
4732 mach_msg_type_number_t inputCount
,
4733 io_struct_inband_t output
,
4734 mach_msg_type_number_t
* outputCount
)
4736 mach_msg_type_number_t scalar_outputCnt
= 0;
4737 mach_vm_size_t ool_output_size
= 0;
4739 return (is_io_connect_method(connect
, index
,
4743 output
, outputCount
,
4744 NULL
, &scalar_outputCnt
,
4745 0, &ool_output_size
));
4748 kern_return_t
shim_io_connect_method_structureI_structureO(
4749 IOExternalMethod
* method
,
4751 io_struct_inband_t input
,
4752 mach_msg_type_number_t inputCount
,
4753 io_struct_inband_t output
,
4754 IOByteCount
* outputCount
)
4757 IOReturn err
= kIOReturnBadArgument
;
4761 if( (kIOUCVariableStructureSize
!= method
->count0
)
4762 && (inputCount
!= method
->count0
))
4764 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
, (uint64_t)kIOUCVariableStructureSize
);
4765 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4768 if( (kIOUCVariableStructureSize
!= method
->count1
)
4769 && (*outputCount
!= method
->count1
))
4771 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4772 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4776 func
= method
->func
;
4778 if( method
->count1
) {
4779 if( method
->count0
) {
4780 err
= (object
->*func
)( input
, output
,
4781 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4783 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4786 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4795 kern_return_t
shim_io_async_method_structureI_structureO(
4796 IOExternalAsyncMethod
* method
,
4798 mach_port_t asyncWakePort
,
4799 io_user_reference_t
* asyncReference
,
4800 uint32_t asyncReferenceCount
,
4801 io_struct_inband_t input
,
4802 mach_msg_type_number_t inputCount
,
4803 io_struct_inband_t output
,
4804 mach_msg_type_number_t
* outputCount
)
4809 io_async_ref_t reference
;
4811 for (i
= 0; i
< asyncReferenceCount
; i
++)
4812 reference
[i
] = REF32(asyncReference
[i
]);
4814 err
= kIOReturnBadArgument
;
4817 if( (kIOUCVariableStructureSize
!= method
->count0
)
4818 && (inputCount
!= method
->count0
))
4820 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
, (uint64_t)kIOUCVariableStructureSize
);
4821 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4824 if( (kIOUCVariableStructureSize
!= method
->count1
)
4825 && (*outputCount
!= method
->count1
))
4827 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4828 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4832 func
= method
->func
;
4834 if( method
->count1
) {
4835 if( method
->count0
) {
4836 err
= (object
->*func
)( reference
,
4838 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4840 err
= (object
->*func
)( reference
,
4841 output
, outputCount
, 0, 0, 0, 0 );
4844 err
= (object
->*func
)( reference
,
4845 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4854 bool gIOKextdClearedBusy
= false;
4857 /* Routine io_catalog_send_data */
4858 kern_return_t
is_io_catalog_send_data(
4859 mach_port_t master_port
,
4861 io_buf_ptr_t inData
,
4862 mach_msg_type_number_t inDataCount
,
4863 kern_return_t
* result
)
4867 kern_return_t kr
= kIOReturnError
;
4869 //printf("io_catalog_send_data called. flag: %d\n", flag);
4871 if( master_port
!= master_device_port
)
4872 return kIOReturnNotPrivileged
;
4874 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4875 flag
!= kIOCatalogKextdActive
&&
4876 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4877 ( !inData
|| !inDataCount
) )
4879 return kIOReturnBadArgument
;
4883 vm_map_offset_t map_data
;
4885 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4886 return( kIOReturnMessageTooLarge
);
4888 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4889 data
= CAST_DOWN(vm_offset_t
, map_data
);
4891 if( kr
!= KERN_SUCCESS
)
4894 // must return success after vm_map_copyout() succeeds
4897 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4898 vm_deallocate( kernel_map
, data
, inDataCount
);
4900 *result
= kIOReturnNoMemory
;
4901 return( KERN_SUCCESS
);
4907 case kIOCatalogResetDrivers
:
4908 case kIOCatalogResetDriversNoMatch
: {
4911 array
= OSDynamicCast(OSArray
, obj
);
4913 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4914 flag
== kIOCatalogResetDrivers
) ) {
4916 kr
= kIOReturnError
;
4919 kr
= kIOReturnBadArgument
;
4924 case kIOCatalogAddDrivers
:
4925 case kIOCatalogAddDriversNoMatch
: {
4928 array
= OSDynamicCast(OSArray
, obj
);
4930 if ( !gIOCatalogue
->addDrivers( array
,
4931 flag
== kIOCatalogAddDrivers
) ) {
4932 kr
= kIOReturnError
;
4936 kr
= kIOReturnBadArgument
;
4941 case kIOCatalogRemoveDrivers
:
4942 case kIOCatalogRemoveDriversNoMatch
: {
4943 OSDictionary
* dict
;
4945 dict
= OSDynamicCast(OSDictionary
, obj
);
4947 if ( !gIOCatalogue
->removeDrivers( dict
,
4948 flag
== kIOCatalogRemoveDrivers
) ) {
4949 kr
= kIOReturnError
;
4953 kr
= kIOReturnBadArgument
;
4958 case kIOCatalogStartMatching
: {
4959 OSDictionary
* dict
;
4961 dict
= OSDynamicCast(OSDictionary
, obj
);
4963 if ( !gIOCatalogue
->startMatching( dict
) ) {
4964 kr
= kIOReturnError
;
4968 kr
= kIOReturnBadArgument
;
4973 case kIOCatalogRemoveKernelLinker
:
4974 kr
= KERN_NOT_SUPPORTED
;
4977 case kIOCatalogKextdActive
:
4979 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
4980 OSKext::setKextdActive();
4982 /* Dump all nonloaded startup extensions; kextd will now send them
4985 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4987 kr
= kIOReturnSuccess
;
4990 case kIOCatalogKextdFinishedLaunching
: {
4992 if (!gIOKextdClearedBusy
) {
4993 IOService
* serviceRoot
= IOService::getServiceRoot();
4995 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
4996 serviceRoot
->adjustBusy(-1);
4997 gIOKextdClearedBusy
= true;
5001 kr
= kIOReturnSuccess
;
5006 kr
= kIOReturnBadArgument
;
5010 if (obj
) obj
->release();
5013 return( KERN_SUCCESS
);
5016 /* Routine io_catalog_terminate */
5017 kern_return_t
is_io_catalog_terminate(
5018 mach_port_t master_port
,
5024 if( master_port
!= master_device_port
)
5025 return kIOReturnNotPrivileged
;
5027 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
5028 kIOClientPrivilegeAdministrator
);
5029 if( kIOReturnSuccess
!= kr
)
5033 #if !defined(SECURE_KERNEL)
5034 case kIOCatalogServiceTerminate
:
5036 IOService
* service
;
5038 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
5039 kIORegistryIterateRecursively
);
5041 return kIOReturnNoMemory
;
5045 while( (service
= (IOService
*)iter
->getNextObject()) ) {
5046 if( service
->metaCast(name
)) {
5047 if ( !service
->terminate( kIOServiceRequired
5048 | kIOServiceSynchronous
) ) {
5049 kr
= kIOReturnUnsupported
;
5054 } while( !service
&& !iter
->isValid());
5058 case kIOCatalogModuleUnload
:
5059 case kIOCatalogModuleTerminate
:
5060 kr
= gIOCatalogue
->terminateDriversForModule(name
,
5061 flag
== kIOCatalogModuleUnload
);
5066 kr
= kIOReturnBadArgument
;
5073 /* Routine io_catalog_get_data */
5074 kern_return_t
is_io_catalog_get_data(
5075 mach_port_t master_port
,
5077 io_buf_ptr_t
*outData
,
5078 mach_msg_type_number_t
*outDataCount
)
5080 kern_return_t kr
= kIOReturnSuccess
;
5083 if( master_port
!= master_device_port
)
5084 return kIOReturnNotPrivileged
;
5086 //printf("io_catalog_get_data called. flag: %d\n", flag);
5088 s
= OSSerialize::withCapacity(4096);
5090 return kIOReturnNoMemory
;
5092 kr
= gIOCatalogue
->serializeData(flag
, s
);
5094 if ( kr
== kIOReturnSuccess
) {
5099 size
= s
->getLength();
5100 kr
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
);
5101 if ( kr
== kIOReturnSuccess
) {
5102 bcopy(s
->text(), (void *)data
, size
);
5103 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
5104 (vm_map_size_t
)size
, true, ©
);
5105 *outData
= (char *)copy
;
5106 *outDataCount
= size
;
5115 /* Routine io_catalog_get_gen_count */
5116 kern_return_t
is_io_catalog_get_gen_count(
5117 mach_port_t master_port
,
5120 if( master_port
!= master_device_port
)
5121 return kIOReturnNotPrivileged
;
5123 //printf("io_catalog_get_gen_count called.\n");
5126 return kIOReturnBadArgument
;
5128 *genCount
= gIOCatalogue
->getGenerationCount();
5130 return kIOReturnSuccess
;
5133 /* Routine io_catalog_module_loaded.
5134 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
5136 kern_return_t
is_io_catalog_module_loaded(
5137 mach_port_t master_port
,
5140 if( master_port
!= master_device_port
)
5141 return kIOReturnNotPrivileged
;
5143 //printf("io_catalog_module_loaded called. name %s\n", name);
5146 return kIOReturnBadArgument
;
5148 gIOCatalogue
->moduleHasLoaded(name
);
5150 return kIOReturnSuccess
;
5153 kern_return_t
is_io_catalog_reset(
5154 mach_port_t master_port
,
5157 if( master_port
!= master_device_port
)
5158 return kIOReturnNotPrivileged
;
5161 case kIOCatalogResetDefault
:
5162 gIOCatalogue
->reset();
5166 return kIOReturnBadArgument
;
5169 return kIOReturnSuccess
;
5172 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5174 kern_return_t result
= kIOReturnBadArgument
;
5175 IOUserClient
*userClient
;
5177 if ((userClient
= OSDynamicCast(IOUserClient
,
5178 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
5179 IOExternalTrap
*trap
;
5180 IOService
*target
= NULL
;
5182 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5184 if (trap
&& target
) {
5190 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5194 iokit_remove_connect_reference(userClient
);
5202 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5203 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5207 IOByteCount structureOutputSize
;
5212 count
= dispatch
->checkScalarInputCount
;
5213 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
5215 return (kIOReturnBadArgument
);
5218 count
= dispatch
->checkStructureInputSize
;
5219 if ((kIOUCVariableStructureSize
!= count
)
5220 && (count
!= ((args
->structureInputDescriptor
)
5221 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
5223 return (kIOReturnBadArgument
);
5226 count
= dispatch
->checkScalarOutputCount
;
5227 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
5229 return (kIOReturnBadArgument
);
5232 count
= dispatch
->checkStructureOutputSize
;
5233 if ((kIOUCVariableStructureSize
!= count
)
5234 && (count
!= ((args
->structureOutputDescriptor
)
5235 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
5237 return (kIOReturnBadArgument
);
5240 if (dispatch
->function
)
5241 err
= (*dispatch
->function
)(target
, reference
, args
);
5243 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5249 // pre-Leopard API's don't do ool structs
5250 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
5252 err
= kIOReturnIPCError
;
5256 structureOutputSize
= args
->structureOutputSize
;
5258 if (args
->asyncWakePort
)
5260 IOExternalAsyncMethod
* method
;
5262 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
5263 return (kIOReturnUnsupported
);
5265 if (kIOUCForegroundOnly
& method
->flags
)
5267 if (task_is_gpu_denied(current_task()))
5268 return (kIOReturnNotPermitted
);
5271 switch (method
->flags
& kIOUCTypeMask
)
5273 case kIOUCScalarIStructI
:
5274 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5275 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5276 args
->scalarInput
, args
->scalarInputCount
,
5277 (char *)args
->structureInput
, args
->structureInputSize
);
5280 case kIOUCScalarIScalarO
:
5281 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5282 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5283 args
->scalarInput
, args
->scalarInputCount
,
5284 args
->scalarOutput
, &args
->scalarOutputCount
);
5287 case kIOUCScalarIStructO
:
5288 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5289 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5290 args
->scalarInput
, args
->scalarInputCount
,
5291 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5295 case kIOUCStructIStructO
:
5296 err
= shim_io_async_method_structureI_structureO( method
, object
,
5297 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5298 (char *)args
->structureInput
, args
->structureInputSize
,
5299 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5303 err
= kIOReturnBadArgument
;
5309 IOExternalMethod
* method
;
5311 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
5312 return (kIOReturnUnsupported
);
5314 if (kIOUCForegroundOnly
& method
->flags
)
5316 if (task_is_gpu_denied(current_task()))
5317 return (kIOReturnNotPermitted
);
5320 switch (method
->flags
& kIOUCTypeMask
)
5322 case kIOUCScalarIStructI
:
5323 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5324 args
->scalarInput
, args
->scalarInputCount
,
5325 (char *) args
->structureInput
, args
->structureInputSize
);
5328 case kIOUCScalarIScalarO
:
5329 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5330 args
->scalarInput
, args
->scalarInputCount
,
5331 args
->scalarOutput
, &args
->scalarOutputCount
);
5334 case kIOUCScalarIStructO
:
5335 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5336 args
->scalarInput
, args
->scalarInputCount
,
5337 (char *) args
->structureOutput
, &structureOutputSize
);
5341 case kIOUCStructIStructO
:
5342 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5343 (char *) args
->structureInput
, args
->structureInputSize
,
5344 (char *) args
->structureOutput
, &structureOutputSize
);
5348 err
= kIOReturnBadArgument
;
5353 args
->structureOutputSize
= structureOutputSize
;
5359 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5360 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5362 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5363 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5365 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5366 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5367 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5368 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5369 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5370 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5371 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5372 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5373 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5374 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5375 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5376 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5377 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5378 OSMetaClassDefineReservedUnused(IOUserClient
, 15);